diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py index 9a78dcc..9b4917f 100644 --- a/crypto_monitor_gate/app.py +++ b/crypto_monitor_gate/app.py @@ -2600,23 +2600,17 @@ def get_exchange_capitals(force=False): def execute_transfer_usdt(amount, from_account, to_account): - if amount <= 0: - return False, "划转金额必须大于0", None - ok_live, reason = ensure_exchange_live_ready() - if not ok_live: - return False, reason, None - try: - resp = exchange.transfer(TRANSFER_CCY, float(amount), from_account, to_account) - return True, "划转成功", resp - except Exception as e: - msg = str(e) - if "INVALID_KEY" in msg or "Invalid key" in msg: - msg += ( - "。常见原因:① GATE_API_SECRET 错误或 .env 里多了空格/换行;② IP 白名单未包含当前服务器出口 IP;" - "③ Gate「交易账户」类 API Key 若不支持钱包接口则无法走账户内划转 POST /wallet/transfers(需在官网确认该 Key 类型是否开放划转);" - "④ Key 已重置或权限变更。你已勾选现货/统一账户仍报错时,优先核对 Secret 与白名单。" - ) - return False, msg, None + from gate_transfer_lib import execute_transfer_usdt as _gate_execute_transfer_usdt + + return _gate_execute_transfer_usdt( + exchange, + amount, + from_account, + to_account, + transfer_ccy=TRANSFER_CCY, + ensure_live_ready=ensure_exchange_live_ready, + ensure_markets_loaded=ensure_markets_loaded, + ) def get_account_usdt_total(account_type): @@ -2638,6 +2632,12 @@ def get_account_usdt_total(account_type): return None +def _auto_transfer_active_count(conn): + from gate_transfer_lib import count_auto_transfer_blockers + + return count_auto_transfer_blockers(conn, count_order_monitors=get_active_position_count) + + def auto_transfer_once_per_day(): run_auto_transfer_once_per_day( enabled=AUTO_TRANSFER_ENABLED, @@ -2647,7 +2647,7 @@ def auto_transfer_once_per_day(): to_account=AUTO_TRANSFER_TO, funds_decimals=2, get_db=get_db, - get_active_position_count=get_active_position_count, + get_active_position_count=_auto_transfer_active_count, get_account_usdt_total=get_account_usdt_total, execute_transfer_usdt=execute_transfer_usdt, send_wechat_msg=send_wechat_msg, @@ -5995,6 +5995,7 @@ def render_main_page(page="trade"): auto_transfer_from=AUTO_TRANSFER_FROM, auto_transfer_to=AUTO_TRANSFER_TO, auto_transfer_bj_hour=AUTO_TRANSFER_BJ_HOUR, + transfer_amount_fmt=format_usdt(AUTO_TRANSFER_AMOUNT), full_margin_buffer_ratio=FULL_MARGIN_BUFFER_RATIO, price_refresh_seconds=PRICE_REFRESH_SECONDS, active_count=active_count, @@ -8104,7 +8105,7 @@ def manual_transfer(): flash(f"手动划转成功:{amount}U {from_account}->{to_account}") else: flash(f"手动划转失败:{msg}") - return redirect("/") + return redirect(request.referrer or "/trade") def _journal_ai_chart_builder(row): diff --git a/crypto_monitor_gate/templates/index.html b/crypto_monitor_gate/templates/index.html index 063cd3a..92a2bc5 100644 --- a/crypto_monitor_gate/templates/index.html +++ b/crypto_monitor_gate/templates/index.html @@ -318,6 +318,7 @@
当日资金(交易账户)
{{ funds_fmt(current_capital) }}U
实时价格更新时间:--(北京时间 UTC+8)
+ {% include 'gate_transfer_block.html' %}
{% if page == 'key_monitor' %} @@ -451,23 +452,6 @@ {% endif %} |移动保本:下单可勾选关闭;开启时 {{ breakeven_rr_trigger }}R 触发(每 1R 阶梯上移),偏移 {{ breakeven_offset_pct }}%
-
- 划转:自动划转 {{ '开启' if auto_transfer_enabled else '关闭' }}(每天北京时间 {{ auto_transfer_bj_hour }}:00起该整点小时内尝试;账簿按 UTC 自然日去重;将 {{ auto_transfer_to }} 调整至 {{ auto_transfer_amount }}U:不足从 {{ auto_transfer_from }} 划入、超出划回 {{ auto_transfer_from }};持仓中不划转并微信通知) -
-
- - - - -
- - - -
+ + + +
diff --git a/tests/test_gate_transfer_lib.py b/tests/test_gate_transfer_lib.py new file mode 100644 index 0000000..bb8ed09 --- /dev/null +++ b/tests/test_gate_transfer_lib.py @@ -0,0 +1,44 @@ +"""gate_transfer_lib 单元测试。""" +from __future__ import annotations + +import sqlite3 +import unittest + +from gate_transfer_lib import count_auto_transfer_blockers + + +class GateTransferLibTest(unittest.TestCase): + def test_counts_order_monitors_first(self): + conn = sqlite3.connect(":memory:") + conn.execute("CREATE TABLE order_monitors (status TEXT)") + conn.execute("CREATE TABLE trend_pullback_plans (status TEXT, first_order_done INTEGER)") + conn.execute("INSERT INTO order_monitors VALUES ('active')") + conn.execute("INSERT INTO trend_pullback_plans VALUES ('active', 1)") + conn.commit() + n = count_auto_transfer_blockers(conn, count_order_monitors=lambda c: 1) + self.assertEqual(n, 1) + conn.close() + + def test_counts_trend_plan_when_no_order_monitors(self): + conn = sqlite3.connect(":memory:") + conn.execute("CREATE TABLE order_monitors (status TEXT)") + conn.execute("CREATE TABLE trend_pullback_plans (status TEXT, first_order_done INTEGER)") + conn.execute("INSERT INTO trend_pullback_plans VALUES ('active', 1)") + conn.commit() + n = count_auto_transfer_blockers(conn, count_order_monitors=lambda c: 0) + self.assertEqual(n, 1) + conn.close() + + def test_ignores_trend_plan_without_first_order(self): + conn = sqlite3.connect(":memory:") + conn.execute("CREATE TABLE order_monitors (status TEXT)") + conn.execute("CREATE TABLE trend_pullback_plans (status TEXT, first_order_done INTEGER)") + conn.execute("INSERT INTO trend_pullback_plans VALUES ('active', 0)") + conn.commit() + n = count_auto_transfer_blockers(conn, count_order_monitors=lambda c: 0) + self.assertEqual(n, 0) + conn.close() + + +if __name__ == "__main__": + unittest.main()