From 44c3703f071d427833800991c4fe1645d328856b Mon Sep 17 00:00:00 2001 From: dekun Date: Thu, 11 Jun 2026 22:18:12 +0800 Subject: [PATCH] feat: include time-close result in hub sync and instance trade records Co-authored-by: Cursor --- crypto_monitor_binance/app.py | 3 +- crypto_monitor_binance/templates/index.html | 3 +- crypto_monitor_gate/app.py | 3 +- crypto_monitor_gate/templates/index.html | 3 +- crypto_monitor_gate_bot/app.py | 3 +- crypto_monitor_gate_bot/templates/index.html | 3 +- crypto_monitor_okx/app.py | 3 +- crypto_monitor_okx/templates/index.html | 3 +- hub_trades_lib.py | 2 + tests/test_hub_trades_lib.py | 41 ++++++++++++++++++++ 10 files changed, 59 insertions(+), 8 deletions(-) diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py index 31a54bc..e2b65dd 100644 --- a/crypto_monitor_binance/app.py +++ b/crypto_monitor_binance/app.py @@ -1544,9 +1544,10 @@ TRADE_COMPLETED_RESULTS = ( "手动平仓", "强制清仓", "外部平仓", + TIME_CLOSE_RESULT, ) -REVIEW_RESULT_OPTIONS = ("止盈", "止损", "保本止盈", "移动止盈", "手动平仓") +REVIEW_RESULT_OPTIONS = ("止盈", "止损", "保本止盈", "移动止盈", "手动平仓", TIME_CLOSE_RESULT) def parse_dt_for_trading_day(s): diff --git a/crypto_monitor_binance/templates/index.html b/crypto_monitor_binance/templates/index.html index 0038bc0..bc2d238 100644 --- a/crypto_monitor_binance/templates/index.html +++ b/crypto_monitor_binance/templates/index.html @@ -554,6 +554,7 @@ {% set effective_result = r.effective_result %} {% if effective_result in ["止盈","保本止盈","移动止盈"] %}{{ effective_result }} {% elif effective_result in ["止损","强制清仓","手动平仓"] %}{{ effective_result }} + {% elif effective_result == "时间平仓" %}{{ effective_result }} {% else %}{{ effective_result }}{% endif %} @@ -987,7 +988,7 @@ function editTradeRecordReview(t){ if(takeProfit === null) return; const pnl = prompt("最终盈亏(可手工核对后填写)", String(t.pnl_amount ?? "")); if(pnl === null) return; - const result = prompt("结果(止盈/止损/保本止盈/移动止盈/手动平仓)", String(t.result || "")); + const result = prompt("结果(止盈/止损/保本止盈/移动止盈/手动平仓/时间平仓)", String(t.result || "")); if(result === null) return; const note = prompt("备注(可空)", String(t.miss_reason || "")) ?? ""; const entryHint = "开仓类型:五种固定整句、或自定义说明(2000字内;与复盘表单一致;留空=本次不改该项)"; diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py index fb05cdb..6c03c2a 100644 --- a/crypto_monitor_gate/app.py +++ b/crypto_monitor_gate/app.py @@ -1538,9 +1538,10 @@ TRADE_COMPLETED_RESULTS = ( "手动平仓", "强制清仓", "外部平仓", + TIME_CLOSE_RESULT, ) -REVIEW_RESULT_OPTIONS = ("止盈", "止损", "保本止盈", "移动止盈", "手动平仓") +REVIEW_RESULT_OPTIONS = ("止盈", "止损", "保本止盈", "移动止盈", "手动平仓", TIME_CLOSE_RESULT) def parse_dt_for_trading_day(s): diff --git a/crypto_monitor_gate/templates/index.html b/crypto_monitor_gate/templates/index.html index 8527b61..2428cad 100644 --- a/crypto_monitor_gate/templates/index.html +++ b/crypto_monitor_gate/templates/index.html @@ -534,6 +534,7 @@ {% set effective_result = r.effective_result %} {% if effective_result in ["止盈","保本止盈","移动止盈"] %}{{ effective_result }} {% elif effective_result in ["止损","强制清仓","手动平仓"] %}{{ effective_result }} + {% elif effective_result == "时间平仓" %}{{ effective_result }} {% else %}{{ effective_result }}{% endif %} @@ -967,7 +968,7 @@ function editTradeRecordReview(t){ if(takeProfit === null) return; const pnl = prompt("最终盈亏(可手工核对后填写)", String(t.pnl_amount ?? "")); if(pnl === null) return; - const result = prompt("结果(止盈/止损/保本止盈/移动止盈/手动平仓)", String(t.result || "")); + const result = prompt("结果(止盈/止损/保本止盈/移动止盈/手动平仓/时间平仓)", String(t.result || "")); if(result === null) return; const note = prompt("备注(可空)", String(t.miss_reason || "")) ?? ""; const entryHint = "开仓类型:五种固定整句、或自定义说明(2000字内;与复盘表单一致;留空=本次不改该项)"; diff --git a/crypto_monitor_gate_bot/app.py b/crypto_monitor_gate_bot/app.py index 5fdccdf..36b3efb 100644 --- a/crypto_monitor_gate_bot/app.py +++ b/crypto_monitor_gate_bot/app.py @@ -1538,9 +1538,10 @@ TRADE_COMPLETED_RESULTS = ( "手动平仓", "强制清仓", "外部平仓", + TIME_CLOSE_RESULT, ) -REVIEW_RESULT_OPTIONS = ("止盈", "止损", "保本止盈", "移动止盈", "手动平仓") +REVIEW_RESULT_OPTIONS = ("止盈", "止损", "保本止盈", "移动止盈", "手动平仓", TIME_CLOSE_RESULT) def parse_dt_for_trading_day(s): diff --git a/crypto_monitor_gate_bot/templates/index.html b/crypto_monitor_gate_bot/templates/index.html index 8527b61..2428cad 100644 --- a/crypto_monitor_gate_bot/templates/index.html +++ b/crypto_monitor_gate_bot/templates/index.html @@ -534,6 +534,7 @@ {% set effective_result = r.effective_result %} {% if effective_result in ["止盈","保本止盈","移动止盈"] %}{{ effective_result }} {% elif effective_result in ["止损","强制清仓","手动平仓"] %}{{ effective_result }} + {% elif effective_result == "时间平仓" %}{{ effective_result }} {% else %}{{ effective_result }}{% endif %} @@ -967,7 +968,7 @@ function editTradeRecordReview(t){ if(takeProfit === null) return; const pnl = prompt("最终盈亏(可手工核对后填写)", String(t.pnl_amount ?? "")); if(pnl === null) return; - const result = prompt("结果(止盈/止损/保本止盈/移动止盈/手动平仓)", String(t.result || "")); + const result = prompt("结果(止盈/止损/保本止盈/移动止盈/手动平仓/时间平仓)", String(t.result || "")); if(result === null) return; const note = prompt("备注(可空)", String(t.miss_reason || "")) ?? ""; const entryHint = "开仓类型:五种固定整句、或自定义说明(2000字内;与复盘表单一致;留空=本次不改该项)"; diff --git a/crypto_monitor_okx/app.py b/crypto_monitor_okx/app.py index d735979..8ee27b0 100644 --- a/crypto_monitor_okx/app.py +++ b/crypto_monitor_okx/app.py @@ -1524,9 +1524,10 @@ TRADE_COMPLETED_RESULTS = ( "手动平仓", "强制清仓", "外部平仓", + TIME_CLOSE_RESULT, ) -REVIEW_RESULT_OPTIONS = ("止盈", "止损", "保本止盈", "移动止盈", "手动平仓") +REVIEW_RESULT_OPTIONS = ("止盈", "止损", "保本止盈", "移动止盈", "手动平仓", TIME_CLOSE_RESULT) def parse_dt_for_trading_day(s): diff --git a/crypto_monitor_okx/templates/index.html b/crypto_monitor_okx/templates/index.html index 8f58eea..ff6e79e 100644 --- a/crypto_monitor_okx/templates/index.html +++ b/crypto_monitor_okx/templates/index.html @@ -563,6 +563,7 @@ {% set effective_result = r.effective_result %} {% if effective_result in ["止盈","保本止盈","移动止盈"] %}{{ effective_result }} {% elif effective_result in ["止损","强制清仓","手动平仓"] %}{{ effective_result }} + {% elif effective_result == "时间平仓" %}{{ effective_result }} {% else %}{{ effective_result }}{% endif %} @@ -996,7 +997,7 @@ function editTradeRecordReview(t){ if(takeProfit === null) return; const pnl = prompt("最终盈亏(可手工核对后填写)", String(t.pnl_amount ?? "")); if(pnl === null) return; - const result = prompt("结果(止盈/止损/保本止盈/移动止盈/手动平仓)", String(t.result || "")); + const result = prompt("结果(止盈/止损/保本止盈/移动止盈/手动平仓/时间平仓)", String(t.result || "")); if(result === null) return; const note = prompt("备注(可空)", String(t.miss_reason || "")) ?? ""; const entryHint = "开仓类型:五种固定整句、或自定义说明(2000字内;与复盘表单一致;留空=本次不改该项)"; diff --git a/hub_trades_lib.py b/hub_trades_lib.py index 94a3a7e..9b19765 100644 --- a/hub_trades_lib.py +++ b/hub_trades_lib.py @@ -9,6 +9,7 @@ from strategy_trade_labels import ( MONITOR_TYPE_TREND_PULLBACK, entry_reason_for_monitor_type, ) +from time_close_lib import TIME_CLOSE_RESULT TRADE_COMPLETED_RESULTS = ( "止盈", @@ -18,6 +19,7 @@ TRADE_COMPLETED_RESULTS = ( "手动平仓", "强制清仓", "外部平仓", + TIME_CLOSE_RESULT, ) diff --git a/tests/test_hub_trades_lib.py b/tests/test_hub_trades_lib.py index 5d13a2f..bd8fa78 100644 --- a/tests/test_hub_trades_lib.py +++ b/tests/test_hub_trades_lib.py @@ -152,6 +152,47 @@ class HubTradesLibTest(unittest.TestCase): self.assertTrue(rows[0]["reviewed"]) conn.close() + def test_time_close_result_included(self): + conn = sqlite3.connect(":memory:") + conn.row_factory = sqlite3.Row + conn.execute( + """CREATE TABLE trade_records ( + symbol TEXT, direction TEXT, result TEXT, reviewed_result TEXT, + pnl_amount REAL, reviewed_pnl_amount REAL, exchange_realized_pnl REAL, + closed_at TEXT, reviewed_closed_at TEXT, opened_at TEXT, reviewed_opened_at TEXT, + created_at TEXT, monitor_type TEXT, actual_rr REAL, planned_rr REAL, + trade_style TEXT, entry_reason TEXT, reviewed_at TEXT + )""" + ) + conn.execute( + "INSERT INTO trade_records VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + ( + "BTC/USDT", + "long", + "时间平仓", + None, + 1.2, + None, + None, + "2026-06-06 12:00:00", + None, + "2026-06-06 08:00:00", + None, + "2026-06-06 12:00:00", + "趋势回调", + None, + None, + "trend", + "", + None, + ), + ) + conn.commit() + rows = fetch_trades_for_trading_day(conn, "2026-06-06") + self.assertEqual(len(rows), 1) + self.assertEqual(rows[0]["result"], "时间平仓") + conn.close() + if __name__ == "__main__": unittest.main()