|
|
@@ -461,6 +461,81 @@ def update_tx_data_periodically():
|
|
|
logger.error(f"pending更新线程发生未知错误: {e}")
|
|
|
traceback.print_exc()
|
|
|
|
|
|
+# --- 餘額平衡綫程 ---
|
|
|
+def balance_available_funds_periodically():
|
|
|
+ """
|
|
|
+ 每10秒嘗試平衡一次餘額
|
|
|
+ """
|
|
|
+ PROPORTION_LIMIT = 0.3 # 鏈上資金比例低於這個值就會觸發平衡
|
|
|
+ PROPORTION_TARGET = 1 # 鏈上資金占比目標,1表示100%是鏈上資金
|
|
|
+ BASE_COIN = 'USDT'
|
|
|
+ BASE_COIN_ADDR = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
|
|
|
+
|
|
|
+ while True:
|
|
|
+ time.sleep(10)
|
|
|
+
|
|
|
+ try:
|
|
|
+ mexc_available = Decimal(0)
|
|
|
+
|
|
|
+ # 交易所餘額讀取
|
|
|
+ with mexc_lock:
|
|
|
+ balances = mexc_data['account_info']['balances']
|
|
|
+
|
|
|
+ for balance in balances:
|
|
|
+ if balance['asset'].upper() == BASE_COIN:
|
|
|
+ mexc_available = Decimal(balance['free'])
|
|
|
+ mexc_available = mexc_available.quantize(Decimal('1e-2'), rounding=ROUND_DOWN)
|
|
|
+
|
|
|
+ # 鏈上餘額讀取
|
|
|
+ chain_available = web3.get_erc20_balance(BASE_COIN_ADDR)
|
|
|
+ chain_available = chain_available.quantize(Decimal('1e-2'), rounding=ROUND_DOWN)
|
|
|
+
|
|
|
+ # 縂可用餘額(不包括lock的)
|
|
|
+ total_available = mexc_available + chain_available
|
|
|
+
|
|
|
+ # 小於20都懶得做平衡,手續費都不夠
|
|
|
+ if total_available < Decimal(20):
|
|
|
+ continue
|
|
|
+
|
|
|
+ # 計算鏈上資金佔總體的比例
|
|
|
+ proportion = chain_available / total_available
|
|
|
+ proportion = proportion.quantize(Decimal('1e-4'), rounding=ROUND_DOWN)
|
|
|
+
|
|
|
+ # 判斷比例是否滿足limit,不滿足則先不提現
|
|
|
+ if proportion > PROPORTION_LIMIT:
|
|
|
+ continue
|
|
|
+
|
|
|
+ # 鏈上應該具備的資金量
|
|
|
+ chain_available_target = total_available * PROPORTION_TARGET
|
|
|
+ mexc_should_be_withdrawal_founds = chain_available_target - chain_available
|
|
|
+ mexc_should_be_withdrawal_founds = mexc_should_be_withdrawal_founds.quantize(Decimal(1), rounding=ROUND_DOWN)
|
|
|
+
|
|
|
+ if mexc_should_be_withdrawal_founds > 0:
|
|
|
+ withdrawal_params = {
|
|
|
+ 'coin': 'USDT',
|
|
|
+ 'netWork': 'ETH',
|
|
|
+ 'address': USER_WALLET,
|
|
|
+ 'amount': mexc_should_be_withdrawal_founds,
|
|
|
+ }
|
|
|
+ withdrawal_params_formated = pformat(withdrawal_params, indent=2)
|
|
|
+ withdrawal_rst = mexc.wallet.post_withdraw(withdrawal_params)
|
|
|
+ withdrawal_rst_formated = pformat(withdrawal_rst, indent=2)
|
|
|
+
|
|
|
+ logger.info(f"[withdrawal]mexc_available={mexc_available}, chain_available={chain_available},proportion={proportion}, mexc_withdrawal={mexc_should_be_withdrawal_founds}")
|
|
|
+
|
|
|
+ if "id" not in withdrawal_rst:
|
|
|
+ msg = f"[withdrawal]交易所提现失败\n參數: {withdrawal_params_formated}\n響應: {withdrawal_rst_formated}"
|
|
|
+ logger.error(msg)
|
|
|
+ else:
|
|
|
+ msg = f"[withdrawal]交易所提现已发送\n參數: {withdrawal_params_formated}\n響應: {withdrawal_rst_formated}"
|
|
|
+ logger.info(msg)
|
|
|
+ else:
|
|
|
+ # TODO 這是另一個方向,需要從鏈上往交易所劃轉
|
|
|
+ pass
|
|
|
+ except Exception as e:
|
|
|
+ logger.error(f"可用資金平衡綫程发生未知错误: {e}")
|
|
|
+ traceback.print_exc()
|
|
|
+
|
|
|
@app.route('/submit_process', methods=['POST'])
|
|
|
def handle_submit_process():
|
|
|
data = request.get_json()
|
|
|
@@ -568,6 +643,10 @@ if __name__ == "__main__":
|
|
|
pending_thread = threading.Thread(target=update_tx_data_periodically, daemon=True)
|
|
|
pending_thread.start()
|
|
|
|
|
|
+ logger.info("启动餘額平衡线程...")
|
|
|
+ pending_thread = threading.Thread(target=balance_available_funds_periodically, daemon=True)
|
|
|
+ pending_thread.start()
|
|
|
+
|
|
|
logger.info("主线程继续执行,可以执行其他任务或保持运行以观察数据更新。")
|
|
|
|
|
|
logger.info("启动 Flask 套利执行服务器...")
|