diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py index 48f4d66..5ffbb77 100644 --- a/crypto_monitor_binance/app.py +++ b/crypto_monitor_binance/app.py @@ -47,6 +47,11 @@ from fib_key_monitor_lib import ( key_signal_type_for_trade_record, stored_key_signal_type, ) +from strategy_trade_labels import ( + STRATEGY_ENTRY_REASON_OPTIONS, + entry_reason_for_monitor_type, + trade_record_monitor_type as resolve_trade_record_monitor_type, +) from journal_chart_lib import ( JOURNAL_CHART_DEFAULT_LIMIT, JOURNAL_CHART_DEFAULT_TF1, @@ -978,7 +983,7 @@ ENTRY_REASON_OPTIONS = ( "关键位收敛突破", "关键位斐波0.618", "关键位斐波0.786", -) +) + STRATEGY_ENTRY_REASON_OPTIONS STATS_SEGMENT_DEFS = ( ("all", "全部交易", {"segment": "all"}), @@ -2479,7 +2484,12 @@ def insert_trade_record( close_ts_ms = _to_ms_with_fallback(closed_at_ms, close_ts) kst = key_signal_type_for_trade_record(key_signal_type, KEY_MONITOR_AUTO_TYPES) snap_sl = initial_stop_loss if initial_stop_loss not in (None, "") else stop_loss - er = (entry_reason or "").strip() or entry_reason_from_key_signal(kst) or "" + er = ( + (entry_reason or "").strip() + or entry_reason_from_key_signal(kst) + or entry_reason_for_monitor_type(monitor_type) + or "" + ) cur = conn.execute( "INSERT INTO trade_records (symbol,monitor_type,key_signal_type,direction,trigger_price,stop_loss,initial_stop_loss,take_profit,margin_capital,leverage,pnl_amount,hold_seconds,trade_style,risk_amount,planned_rr,actual_rr,hold_minutes,opened_at,opened_at_ms,closed_at,closed_at_ms,result,miss_reason,exchange_trade_id,entry_reason,trend_plan_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", ( @@ -2571,6 +2581,12 @@ def order_row_monitor_type(row): return ORDER_MONITOR_TYPE_MANUAL +def trade_record_monitor_type(conn, row): + return resolve_trade_record_monitor_type( + conn, row, default_manual=ORDER_MONITOR_TYPE_MANUAL + ) + + def order_row_key_signal_type(row): if row is None: return None @@ -3982,7 +3998,7 @@ def reconcile_external_closes(conn, days=None): insert_trade_record( conn, symbol=r["symbol"], - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=r["direction"], trigger_price=r["trigger_price"], @@ -5360,7 +5376,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -5419,7 +5435,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -5498,7 +5514,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -5565,7 +5581,7 @@ def force_close_before_reset(): insert_trade_record( conn, symbol=r["symbol"], - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -7276,7 +7292,7 @@ def del_order(id): insert_trade_record( conn, symbol=row["symbol"], - monitor_type=order_row_monitor_type(row), + monitor_type=trade_record_monitor_type(conn, row), key_signal_type=order_row_key_signal_type(row), direction=row["direction"], trigger_price=row["trigger_price"], @@ -7332,7 +7348,7 @@ def del_order(id): insert_trade_record( conn, symbol=row["symbol"], - monitor_type=order_row_monitor_type(row), + monitor_type=trade_record_monitor_type(conn, row), key_signal_type=order_row_key_signal_type(row), direction=row["direction"], trigger_price=row["trigger_price"], diff --git a/crypto_monitor_binance/templates/index.html b/crypto_monitor_binance/templates/index.html index ae3f5b5..7cebe2c 100644 --- a/crypto_monitor_binance/templates/index.html +++ b/crypto_monitor_binance/templates/index.html @@ -1393,11 +1393,18 @@ function fillJournalFromTrade(t){ setJournalField("early_exit_trigger", ""); setJournalField("early_exit_note", ""); const kst = String(t.key_signal_type || "").trim(); - const erFromKey = KEY_ENTRY_REASON_BY_SIGNAL[kst] || ""; - if(erFromKey && JOURNAL_ENTRY_REASON_OPTIONS.includes(erFromKey)){ - setJournalField("entry_reason", erFromKey); + const mt = String(t.monitor_type || "").trim(); + if(mt === "趋势回调" && JOURNAL_ENTRY_REASON_OPTIONS.includes("趋势回调")){ + setJournalField("entry_reason", "趋势回调"); + } else if(mt === "顺势加仓" && JOURNAL_ENTRY_REASON_OPTIONS.includes("顺势加仓")){ + setJournalField("entry_reason", "顺势加仓"); } else { - setJournalField("entry_reason", ""); + const erFromKey = KEY_ENTRY_REASON_BY_SIGNAL[kst] || ""; + if(erFromKey && JOURNAL_ENTRY_REASON_OPTIONS.includes(erFromKey)){ + setJournalField("entry_reason", erFromKey); + } else { + setJournalField("entry_reason", ""); + } } setJournalField("entry_reason_custom", ""); syncJournalEntryReasonOtherUi(); diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py index 216d6db..99855f4 100644 --- a/crypto_monitor_gate/app.py +++ b/crypto_monitor_gate/app.py @@ -48,6 +48,11 @@ from fib_key_monitor_lib import ( key_signal_type_for_trade_record, stored_key_signal_type, ) +from strategy_trade_labels import ( + STRATEGY_ENTRY_REASON_OPTIONS, + entry_reason_for_monitor_type, + trade_record_monitor_type as resolve_trade_record_monitor_type, +) from journal_chart_lib import ( JOURNAL_CHART_DEFAULT_LIMIT, JOURNAL_CHART_DEFAULT_TF1, @@ -978,7 +983,7 @@ ENTRY_REASON_OPTIONS = ( "关键位收敛突破", "关键位斐波0.618", "关键位斐波0.786", -) +) + STRATEGY_ENTRY_REASON_OPTIONS STATS_SEGMENT_DEFS = ( ("all", "全部交易", {"segment": "all"}), @@ -2206,7 +2211,12 @@ def insert_trade_record( close_ts_ms = _to_ms_with_fallback(closed_at_ms, close_ts) kst = key_signal_type_for_trade_record(key_signal_type, KEY_MONITOR_AUTO_TYPES) snap_sl = initial_stop_loss if initial_stop_loss not in (None, "") else stop_loss - er = (entry_reason or "").strip() or entry_reason_from_key_signal(kst) or "" + er = ( + (entry_reason or "").strip() + or entry_reason_from_key_signal(kst) + or entry_reason_for_monitor_type(monitor_type) + or "" + ) conn.execute( "INSERT INTO trade_records (symbol,monitor_type,key_signal_type,direction,trigger_price,stop_loss,initial_stop_loss,take_profit,margin_capital,leverage,pnl_amount,hold_seconds,trade_style,risk_amount,planned_rr,actual_rr,hold_minutes,opened_at,opened_at_ms,closed_at,closed_at_ms,result,miss_reason,exchange_trade_id,entry_reason,trend_plan_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", ( @@ -2297,6 +2307,12 @@ def order_row_monitor_type(row): return ORDER_MONITOR_TYPE_MANUAL +def trade_record_monitor_type(conn, row): + return resolve_trade_record_monitor_type( + conn, row, default_manual=ORDER_MONITOR_TYPE_MANUAL + ) + + def order_row_key_signal_type(row): if row is None: return None @@ -3940,7 +3956,7 @@ def reconcile_external_closes(conn, days=None): insert_trade_record( conn, symbol=r["symbol"], - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=r["direction"], trigger_price=r["trigger_price"], @@ -5320,7 +5336,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -5379,7 +5395,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -5448,7 +5464,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -5515,7 +5531,7 @@ def force_close_before_reset(): insert_trade_record( conn, symbol=r["symbol"], - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -7430,7 +7446,7 @@ def del_order(id): insert_trade_record( conn, symbol=row["symbol"], - monitor_type=order_row_monitor_type(row), + monitor_type=trade_record_monitor_type(conn, row), key_signal_type=order_row_key_signal_type(row), direction=row["direction"], trigger_price=row["trigger_price"], @@ -7487,7 +7503,7 @@ def del_order(id): insert_trade_record( conn, symbol=row["symbol"], - monitor_type=order_row_monitor_type(row), + monitor_type=trade_record_monitor_type(conn, row), key_signal_type=order_row_key_signal_type(row), direction=row["direction"], trigger_price=row["trigger_price"], diff --git a/crypto_monitor_gate/templates/index.html b/crypto_monitor_gate/templates/index.html index ae3f5b5..7cebe2c 100644 --- a/crypto_monitor_gate/templates/index.html +++ b/crypto_monitor_gate/templates/index.html @@ -1393,11 +1393,18 @@ function fillJournalFromTrade(t){ setJournalField("early_exit_trigger", ""); setJournalField("early_exit_note", ""); const kst = String(t.key_signal_type || "").trim(); - const erFromKey = KEY_ENTRY_REASON_BY_SIGNAL[kst] || ""; - if(erFromKey && JOURNAL_ENTRY_REASON_OPTIONS.includes(erFromKey)){ - setJournalField("entry_reason", erFromKey); + const mt = String(t.monitor_type || "").trim(); + if(mt === "趋势回调" && JOURNAL_ENTRY_REASON_OPTIONS.includes("趋势回调")){ + setJournalField("entry_reason", "趋势回调"); + } else if(mt === "顺势加仓" && JOURNAL_ENTRY_REASON_OPTIONS.includes("顺势加仓")){ + setJournalField("entry_reason", "顺势加仓"); } else { - setJournalField("entry_reason", ""); + const erFromKey = KEY_ENTRY_REASON_BY_SIGNAL[kst] || ""; + if(erFromKey && JOURNAL_ENTRY_REASON_OPTIONS.includes(erFromKey)){ + setJournalField("entry_reason", erFromKey); + } else { + setJournalField("entry_reason", ""); + } } setJournalField("entry_reason_custom", ""); syncJournalEntryReasonOtherUi(); diff --git a/crypto_monitor_gate_bot/app.py b/crypto_monitor_gate_bot/app.py index d984148..15ede4e 100644 --- a/crypto_monitor_gate_bot/app.py +++ b/crypto_monitor_gate_bot/app.py @@ -54,6 +54,10 @@ from journal_chart_lib import ( trim_rows_for_trade_review, ) from hub_auth import request_allowed as hub_request_allowed +from strategy_trade_labels import ( + STRATEGY_ENTRY_REASON_OPTIONS, + trade_record_monitor_type as resolve_trade_record_monitor_type, +) from history_window_lib import ( PRESET_CUSTOM, PRESET_UTC_LAST24H, @@ -944,6 +948,7 @@ ENTRY_REASON_OPTIONS = ( "趋势空头:小分歧高吸入场(左侧),确认条件:二次探顶", "波段单:5m顺势突破,确认条件:2根k线+成交量放大+4h同向+日成交量前20", "趋势回调", + "顺势加仓", ) # 复盘表单「其他」选项的 value(非入库值;自定义文本走 entry_reason_custom) ENTRY_REASON_OTHER = "__OTHER__" @@ -2316,6 +2321,10 @@ def ensure_exchange_live_ready(): return True, "" +def trade_record_monitor_type(conn, row): + return resolve_trade_record_monitor_type(conn, row, default_manual="下单监控") + + def exchange_private_api_configured(): """仅表示已配置密钥;与是否允许下单(LIVE_TRADING_ENABLED)无关,用于只读拉仓等。""" return bool(GATE_API_KEY and GATE_API_SECRET) @@ -4005,7 +4014,7 @@ def reconcile_external_closes(conn, days=None): insert_trade_record( conn, symbol=r["symbol"], - monitor_type="下单监控", + monitor_type=trade_record_monitor_type(conn, r), direction=r["direction"], trigger_price=r["trigger_price"], stop_loss=r["stop_loss"], @@ -4940,7 +4949,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type="下单监控", + monitor_type=trade_record_monitor_type(conn, r), direction=direction, trigger_price=trigger_price, stop_loss=stop_loss, @@ -4998,7 +5007,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type="下单监控", + monitor_type=trade_record_monitor_type(conn, r), direction=direction, trigger_price=trigger_price, stop_loss=stop_loss, @@ -5066,7 +5075,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type="下单监控", + monitor_type=trade_record_monitor_type(conn, r), direction=direction, trigger_price=trigger_price, stop_loss=stop_loss, @@ -5131,7 +5140,7 @@ def force_close_before_reset(): insert_trade_record( conn, symbol=r["symbol"], - monitor_type="下单监控", + monitor_type=trade_record_monitor_type(conn, r), direction=direction, trigger_price=trigger_price, stop_loss=r["stop_loss"], @@ -6822,7 +6831,7 @@ def del_order(id): insert_trade_record( conn, symbol=row["symbol"], - monitor_type="下单监控", + monitor_type=trade_record_monitor_type(conn, row), direction=row["direction"], trigger_price=row["trigger_price"], stop_loss=row["stop_loss"], @@ -6876,7 +6885,7 @@ def del_order(id): insert_trade_record( conn, symbol=row["symbol"], - monitor_type="下单监控", + monitor_type=trade_record_monitor_type(conn, row), direction=row["direction"], trigger_price=row["trigger_price"], stop_loss=row["stop_loss"], diff --git a/crypto_monitor_gate_bot/templates/index.html b/crypto_monitor_gate_bot/templates/index.html index 6bf98ee..35d62e0 100644 --- a/crypto_monitor_gate_bot/templates/index.html +++ b/crypto_monitor_gate_bot/templates/index.html @@ -1224,6 +1224,8 @@ function fillJournalFromTrade(t){ syncJournalEntryReasonOtherUi(); if(String(t.monitor_type || "").trim() === "趋势回调" && JOURNAL_ENTRY_REASON_OPTIONS.includes("趋势回调")){ setJournalField("entry_reason", "趋势回调"); + } else if(String(t.monitor_type || "").trim() === "顺势加仓" && JOURNAL_ENTRY_REASON_OPTIONS.includes("顺势加仓")){ + setJournalField("entry_reason", "顺势加仓"); syncJournalEntryReasonOtherUi(); } const er = String(t.result || "").trim(); diff --git a/crypto_monitor_okx/app.py b/crypto_monitor_okx/app.py index c115065..955a0ae 100644 --- a/crypto_monitor_okx/app.py +++ b/crypto_monitor_okx/app.py @@ -47,6 +47,11 @@ from fib_key_monitor_lib import ( key_signal_type_for_trade_record, stored_key_signal_type, ) +from strategy_trade_labels import ( + STRATEGY_ENTRY_REASON_OPTIONS, + entry_reason_for_monitor_type, + trade_record_monitor_type as resolve_trade_record_monitor_type, +) from okx_orders_lib import cancel_okx_all_open_orders, fetch_okx_all_open_orders from journal_chart_lib import ( JOURNAL_CHART_DEFAULT_LIMIT, @@ -946,7 +951,7 @@ ENTRY_REASON_OPTIONS = ( "关键位收敛突破", "关键位斐波0.618", "关键位斐波0.786", -) +) + STRATEGY_ENTRY_REASON_OPTIONS STATS_SEGMENT_DEFS = ( ("all", "全部交易", {"segment": "all"}), @@ -2062,7 +2067,12 @@ def insert_trade_record( close_ts_ms = _to_ms_with_fallback(closed_at_ms, close_ts) kst = key_signal_type_for_trade_record(key_signal_type, KEY_MONITOR_AUTO_TYPES) snap_sl = initial_stop_loss if initial_stop_loss not in (None, "") else stop_loss - er = (entry_reason or "").strip() or entry_reason_from_key_signal(kst) or "" + er = ( + (entry_reason or "").strip() + or entry_reason_from_key_signal(kst) + or entry_reason_for_monitor_type(monitor_type) + or "" + ) conn.execute( "INSERT INTO trade_records (symbol,monitor_type,key_signal_type,direction,trigger_price,stop_loss,initial_stop_loss,take_profit,margin_capital,leverage,pnl_amount,hold_seconds,trade_style,risk_amount,planned_rr,actual_rr,hold_minutes,opened_at,opened_at_ms,closed_at,closed_at_ms,result,miss_reason,exchange_trade_id,entry_reason,trend_plan_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", ( @@ -2152,6 +2162,12 @@ def order_row_monitor_type(row): return ORDER_MONITOR_TYPE_MANUAL +def trade_record_monitor_type(conn, row): + return resolve_trade_record_monitor_type( + conn, row, default_manual=ORDER_MONITOR_TYPE_MANUAL + ) + + def order_row_key_signal_type(row): if row is None: return None @@ -3302,7 +3318,7 @@ def reconcile_external_closes(conn, days=None): insert_trade_record( conn, symbol=r["symbol"], - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=r["direction"], trigger_price=r["trigger_price"], @@ -4843,7 +4859,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -4901,7 +4917,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -4969,7 +4985,7 @@ def check_order_monitors(): insert_trade_record( conn, symbol=sym, - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -5034,7 +5050,7 @@ def force_close_before_reset(): insert_trade_record( conn, symbol=r["symbol"], - monitor_type=order_row_monitor_type(r), + monitor_type=trade_record_monitor_type(conn, r), key_signal_type=order_row_key_signal_type(r), direction=direction, trigger_price=trigger_price, @@ -6680,7 +6696,7 @@ def del_order(id): insert_trade_record( conn, symbol=row["symbol"], - monitor_type=order_row_monitor_type(row), + monitor_type=trade_record_monitor_type(conn, row), key_signal_type=order_row_key_signal_type(row), direction=row["direction"], trigger_price=row["trigger_price"], @@ -6734,7 +6750,7 @@ def del_order(id): insert_trade_record( conn, symbol=row["symbol"], - monitor_type=order_row_monitor_type(row), + monitor_type=trade_record_monitor_type(conn, row), key_signal_type=order_row_key_signal_type(row), direction=row["direction"], trigger_price=row["trigger_price"], diff --git a/crypto_monitor_okx/templates/index.html b/crypto_monitor_okx/templates/index.html index 00f7a2c..78e78a3 100644 --- a/crypto_monitor_okx/templates/index.html +++ b/crypto_monitor_okx/templates/index.html @@ -1402,11 +1402,18 @@ function fillJournalFromTrade(t){ setJournalField("early_exit_trigger", ""); setJournalField("early_exit_note", ""); const kst = String(t.key_signal_type || "").trim(); - const erFromKey = KEY_ENTRY_REASON_BY_SIGNAL[kst] || ""; - if(erFromKey && JOURNAL_ENTRY_REASON_OPTIONS.includes(erFromKey)){ - setJournalField("entry_reason", erFromKey); + const mt = String(t.monitor_type || "").trim(); + if(mt === "趋势回调" && JOURNAL_ENTRY_REASON_OPTIONS.includes("趋势回调")){ + setJournalField("entry_reason", "趋势回调"); + } else if(mt === "顺势加仓" && JOURNAL_ENTRY_REASON_OPTIONS.includes("顺势加仓")){ + setJournalField("entry_reason", "顺势加仓"); } else { - setJournalField("entry_reason", ""); + const erFromKey = KEY_ENTRY_REASON_BY_SIGNAL[kst] || ""; + if(erFromKey && JOURNAL_ENTRY_REASON_OPTIONS.includes(erFromKey)){ + setJournalField("entry_reason", erFromKey); + } else { + setJournalField("entry_reason", ""); + } } setJournalField("entry_reason_custom", ""); syncJournalEntryReasonOtherUi(); diff --git a/strategy_trade_labels.py b/strategy_trade_labels.py new file mode 100644 index 0000000..be68f14 --- /dev/null +++ b/strategy_trade_labels.py @@ -0,0 +1,70 @@ +"""策略交易写入 trade_records 时的类型与复盘开仓类型标注。""" +from __future__ import annotations + +MONITOR_TYPE_TREND_PULLBACK = "趋势回调" +MONITOR_TYPE_ROLL = "顺势加仓" + +ENTRY_REASON_TREND_PULLBACK = "趋势回调" +ENTRY_REASON_ROLL = "顺势加仓" + +STRATEGY_ENTRY_REASON_OPTIONS = ( + ENTRY_REASON_TREND_PULLBACK, + ENTRY_REASON_ROLL, +) + + +def order_had_roll_fills(conn, order_monitor_id) -> bool: + try: + oid = int(order_monitor_id) + except (TypeError, ValueError): + return False + if oid <= 0: + return False + try: + row = conn.execute( + """SELECT 1 FROM roll_legs l + INNER JOIN roll_groups g ON g.id = l.roll_group_id + WHERE g.order_monitor_id=? AND l.status='filled' + LIMIT 1""", + (oid,), + ).fetchone() + return row is not None + except Exception: + return False + + +def _row_monitor_type(row, default_manual: str) -> str: + if row is None: + return default_manual + try: + keys = row.keys() if hasattr(row, "keys") else [] + except Exception: + keys = [] + if "monitor_type" in keys: + mt = (row["monitor_type"] or "").strip() + if mt: + return mt + return default_manual + + +def trade_record_monitor_type(conn, order_row, *, default_manual: str = "下单监控") -> str: + """平仓写入 trade_records 时:曾顺势加仓则标「顺势加仓」,否则沿用监控单类型。""" + oid = None + try: + keys = order_row.keys() if hasattr(order_row, "keys") else [] + if "id" in keys and order_row["id"] is not None: + oid = int(order_row["id"]) + except Exception: + oid = None + if oid and order_had_roll_fills(conn, oid): + return MONITOR_TYPE_ROLL + return _row_monitor_type(order_row, default_manual) + + +def entry_reason_for_monitor_type(monitor_type: str | None) -> str: + mt = (monitor_type or "").strip() + if mt == MONITOR_TYPE_TREND_PULLBACK: + return ENTRY_REASON_TREND_PULLBACK + if mt == MONITOR_TYPE_ROLL: + return ENTRY_REASON_ROLL + return "" diff --git a/strategy_trend_register.py b/strategy_trend_register.py index bb76a2e..84f6ab9 100644 --- a/strategy_trend_register.py +++ b/strategy_trend_register.py @@ -25,8 +25,12 @@ from strategy_trend_lib import ( calc_risk_fraction, validate_trend_bounds, ) +from strategy_trade_labels import ( + ENTRY_REASON_TREND_PULLBACK, + MONITOR_TYPE_TREND_PULLBACK, +) -MONITOR_TYPE_TREND = "趋势回调" +MONITOR_TYPE_TREND = MONITOR_TYPE_TREND_PULLBACK def trend_add_zone_label(direction: str) -> str: @@ -370,6 +374,7 @@ def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) - result=res, opened_at=opened_at, closed_at=closed_at, + entry_reason=ENTRY_REASON_TREND_PULLBACK, ) if "trend_plan_id" in inspect.signature(m.insert_trade_record).parameters: m.insert_trade_record(**kwargs, trend_plan_id=plan_id)