diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py index 04d9b98..616ca82 100644 --- a/crypto_monitor_binance/app.py +++ b/crypto_monitor_binance/app.py @@ -183,6 +183,7 @@ from lib.trade.entry_model_lib import ( order_entry_template_context, open_position_button_label, parse_manual_order_style_fields, + resolve_effective_trade_entry_reason, resolve_trade_record_entry_reason, trend_manual_entry_reason_count, ) @@ -2105,8 +2106,20 @@ def to_effective_trade_dict(row): item["effective_pnl_amount"] = get_effective_trade_field(row, "reviewed_pnl_amount", "pnl_amount", item.get("pnl_amount")) item["effective_hold_minutes"] = get_effective_trade_field(row, "reviewed_hold_minutes", "hold_minutes", item.get("hold_minutes")) item["effective_hold_seconds"] = get_effective_trade_field(row, "reviewed_hold_seconds", "hold_seconds", item.get("hold_seconds")) - er_eff = get_effective_trade_field(row, "reviewed_entry_reason", "entry_reason", item.get("entry_reason")) - item["effective_entry_reason"] = (str(er_eff).strip() if er_eff is not None else "") or "" + try: + _er_keys = row.keys() if hasattr(row, "keys") else [] + except Exception: + _er_keys = [] + reviewed_er = row["reviewed_entry_reason"] if "reviewed_entry_reason" in _er_keys else None + item["effective_entry_reason"] = resolve_effective_trade_entry_reason( + reviewed_entry_reason=reviewed_er, + entry_reason=item.get("entry_reason"), + key_signal_type=(item.get("key_signal_type") or "").strip() or None, + monitor_type=item.get("monitor_type"), + trade_style=item.get("trade_style"), + entry_reason_from_key_signal=entry_reason_from_key_signal, + entry_reason_for_monitor_type=entry_reason_for_monitor_type, + ) try: _keys = row.keys() if hasattr(row, "keys") else [] except Exception: @@ -2642,6 +2655,7 @@ def insert_trade_record( entry_model=entry_model, key_signal_type=kst, monitor_type=monitor_type, + trade_style=trade_style, entry_reason_from_key_signal=entry_reason_from_key_signal, entry_reason_for_monitor_type=entry_reason_for_monitor_type, ) diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py index 032691a..06d732e 100644 --- a/crypto_monitor_gate/app.py +++ b/crypto_monitor_gate/app.py @@ -182,6 +182,7 @@ from lib.trade.entry_model_lib import ( order_entry_template_context, open_position_button_label, parse_manual_order_style_fields, + resolve_effective_trade_entry_reason, resolve_trade_record_entry_reason, trend_manual_entry_reason_count, ) @@ -2064,8 +2065,20 @@ def to_effective_trade_dict(row): item["effective_pnl_amount"] = get_effective_trade_field(row, "reviewed_pnl_amount", "pnl_amount", item.get("pnl_amount")) item["effective_hold_minutes"] = get_effective_trade_field(row, "reviewed_hold_minutes", "hold_minutes", item.get("hold_minutes")) item["effective_hold_seconds"] = get_effective_trade_field(row, "reviewed_hold_seconds", "hold_seconds", item.get("hold_seconds")) - er_eff = get_effective_trade_field(row, "reviewed_entry_reason", "entry_reason", item.get("entry_reason")) - item["effective_entry_reason"] = (str(er_eff).strip() if er_eff is not None else "") or "" + try: + _er_keys = row.keys() if hasattr(row, "keys") else [] + except Exception: + _er_keys = [] + reviewed_er = row["reviewed_entry_reason"] if "reviewed_entry_reason" in _er_keys else None + item["effective_entry_reason"] = resolve_effective_trade_entry_reason( + reviewed_entry_reason=reviewed_er, + entry_reason=item.get("entry_reason"), + key_signal_type=(item.get("key_signal_type") or "").strip() or None, + monitor_type=item.get("monitor_type"), + trade_style=item.get("trade_style"), + entry_reason_from_key_signal=entry_reason_from_key_signal, + entry_reason_for_monitor_type=entry_reason_for_monitor_type, + ) try: _keys = row.keys() if hasattr(row, "keys") else [] except Exception: @@ -2358,6 +2371,7 @@ def insert_trade_record( entry_model=entry_model, key_signal_type=kst, monitor_type=monitor_type, + trade_style=trade_style, entry_reason_from_key_signal=entry_reason_from_key_signal, entry_reason_for_monitor_type=entry_reason_for_monitor_type, ) diff --git a/crypto_monitor_okx/app.py b/crypto_monitor_okx/app.py index 0796e8b..c512037 100644 --- a/crypto_monitor_okx/app.py +++ b/crypto_monitor_okx/app.py @@ -181,6 +181,7 @@ from lib.trade.entry_model_lib import ( order_entry_template_context, open_position_button_label, parse_manual_order_style_fields, + resolve_effective_trade_entry_reason, resolve_trade_record_entry_reason, trend_manual_entry_reason_count, ) @@ -2012,8 +2013,20 @@ def to_effective_trade_dict(row): item["effective_pnl_amount"] = get_effective_trade_field(row, "reviewed_pnl_amount", "pnl_amount", item.get("pnl_amount")) item["effective_hold_minutes"] = get_effective_trade_field(row, "reviewed_hold_minutes", "hold_minutes", item.get("hold_minutes")) item["effective_hold_seconds"] = get_effective_trade_field(row, "reviewed_hold_seconds", "hold_seconds", item.get("hold_seconds")) - er_eff = get_effective_trade_field(row, "reviewed_entry_reason", "entry_reason", item.get("entry_reason")) - item["effective_entry_reason"] = (str(er_eff).strip() if er_eff is not None else "") or "" + try: + _er_keys = row.keys() if hasattr(row, "keys") else [] + except Exception: + _er_keys = [] + reviewed_er = row["reviewed_entry_reason"] if "reviewed_entry_reason" in _er_keys else None + item["effective_entry_reason"] = resolve_effective_trade_entry_reason( + reviewed_entry_reason=reviewed_er, + entry_reason=item.get("entry_reason"), + key_signal_type=(item.get("key_signal_type") or "").strip() or None, + monitor_type=item.get("monitor_type"), + trade_style=item.get("trade_style"), + entry_reason_from_key_signal=entry_reason_from_key_signal, + entry_reason_for_monitor_type=entry_reason_for_monitor_type, + ) try: _keys = row.keys() if hasattr(row, "keys") else [] except Exception: @@ -2253,6 +2266,7 @@ def insert_trade_record( entry_model=entry_model, key_signal_type=kst, monitor_type=monitor_type, + trade_style=trade_style, entry_reason_from_key_signal=entry_reason_from_key_signal, entry_reason_for_monitor_type=entry_reason_for_monitor_type, ) @@ -7984,10 +7998,10 @@ def add_order(): tc_en = 0 tc_en, tc_h, tc_at = time_close_insert_values(tc_en, tc_h, opened_at_ms) conn.execute( - "INSERT INTO order_monitors (symbol, exchange_symbol, direction, trigger_price, stop_loss, initial_stop_loss, take_profit, margin_capital, leverage, trade_style, risk_percent, risk_amount, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, breakeven_armed, breakeven_price, breakeven_enabled, notional_value, position_ratio, base_amount, order_amount, exchange_order_id, opened_at, opened_at_ms, session_date, monitor_type, time_close_enabled, time_close_hours, time_close_at_ms) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + "INSERT INTO order_monitors (symbol, exchange_symbol, direction, trigger_price, stop_loss, initial_stop_loss, take_profit, margin_capital, leverage, trade_style, entry_model, risk_percent, risk_amount, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, breakeven_armed, breakeven_price, breakeven_enabled, notional_value, position_ratio, base_amount, order_amount, exchange_order_id, opened_at, opened_at_ms, session_date, monitor_type, time_close_enabled, time_close_hours, time_close_at_ms) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", ( symbol, exchange_symbol, direction, trigger_price, stop_loss, stop_loss, take_profit, - margin_capital, leverage, trade_style, risk_percent_db, risk_amount_final, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, 0, breakeven_price, + margin_capital, leverage, trade_style, entry_model, risk_percent_db, risk_amount_final, breakeven_rr_trigger, breakeven_offset_pct, breakeven_step_r, 0, breakeven_price, breakeven_enabled, notional_value, position_ratio, base_amount, amount, open_order_id, opened_at_bj, opened_at_ms, trading_day, "下单监控", tc_en, tc_h, tc_at, diff --git a/lib/trade/entry_model_lib.py b/lib/trade/entry_model_lib.py index bcf17fc..7e05449 100644 --- a/lib/trade/entry_model_lib.py +++ b/lib/trade/entry_model_lib.py @@ -290,6 +290,7 @@ def resolve_trade_record_entry_reason( entry_model: Optional[str] = None, key_signal_type: Optional[str] = None, monitor_type: Optional[str] = None, + trade_style: Optional[str] = None, entry_reason_from_key_signal=None, entry_reason_for_monitor_type=None, ) -> str: @@ -308,9 +309,38 @@ def resolve_trade_record_entry_reason( from_mt = (entry_reason_for_monitor_type(monitor_type) or "").strip() if from_mt: return from_mt + ts = (trade_style or "").strip().lower() + if ts in ("trend", "swing"): + return trade_style_label_zh(ts) return "" +def resolve_effective_trade_entry_reason( + *, + reviewed_entry_reason: Optional[str] = None, + entry_reason: Optional[str] = None, + entry_model: Optional[str] = None, + key_signal_type: Optional[str] = None, + monitor_type: Optional[str] = None, + trade_style: Optional[str] = None, + entry_reason_from_key_signal=None, + entry_reason_for_monitor_type=None, +) -> str: + """交易记录展示/导出用:复盘优先,再回落 entry_model / 关键位 / 策略 / trade_style。""" + for raw in (reviewed_entry_reason, entry_reason): + er = (raw or "").strip() + if er: + return er + return resolve_trade_record_entry_reason( + entry_model=entry_model, + key_signal_type=key_signal_type, + monitor_type=monitor_type, + trade_style=trade_style, + entry_reason_from_key_signal=entry_reason_from_key_signal, + entry_reason_for_monitor_type=entry_reason_for_monitor_type, + ) + + def enrich_entry_model_display(item: dict) -> dict: code = normalize_entry_model_code(item.get("entry_model")) if code: diff --git a/tests/test_entry_model_lib.py b/tests/test_entry_model_lib.py index aeb2593..f72079d 100644 --- a/tests/test_entry_model_lib.py +++ b/tests/test_entry_model_lib.py @@ -127,6 +127,12 @@ class TestEntryModelLib(unittest.TestCase): er2 = resolve_trade_record_entry_reason(entry_model=ENTRY_MODEL_LAUNCH_A) self.assertEqual(er2, "启动A") + def test_resolve_entry_reason_trade_style_fallback(self): + er = resolve_trade_record_entry_reason(trade_style="swing") + self.assertEqual(er, "波段单") + er2 = resolve_trade_record_entry_reason(trade_style="trend") + self.assertEqual(er2, "趋势单") + def test_build_trend_div_journal_options(self): opts = build_trend_div_entry_reason_options(("趋势回调",)) self.assertEqual(opts[:5], ("启动A", "启动B", "大分歧A", "大分歧B", "小分歧"))