fix(trend): write trade_records when hub closes plan on gate_bot

Gate_bot insert_trade_record lacked entry_reason, causing _finalize_plan to save strategy snapshots but fail trade insert. Filter kwargs by signature, insert before plan commit, and add backfill script.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-07 20:32:44 +08:00
parent 08082eb88f
commit 80226eebcf
4 changed files with 328 additions and 33 deletions
+43 -31
View File
@@ -645,6 +645,18 @@ def _plan_stop_status(result_label: str) -> str:
return "stopped_manual"
def _call_insert_trade_record(m, plan_id: int, kwargs: dict) -> None:
"""按各所 insert_trade_record 签名过滤参数,避免未知字段导致记账失败。"""
fn = getattr(m, "insert_trade_record", None)
if not callable(fn):
raise RuntimeError("app_module 缺少 insert_trade_record")
allowed = set(inspect.signature(fn).parameters.keys())
call = {k: v for k, v in kwargs.items() if k in allowed}
if "trend_plan_id" in allowed:
call["trend_plan_id"] = int(plan_id)
fn(**call)
def _trend_plan_trade_exists(conn, plan_id: int) -> bool:
try:
return conn.execute(
@@ -705,6 +717,37 @@ def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) -
cancel_symbol_orders(cfg, ex_sym)
except Exception:
pass
if not _trend_plan_trade_exists(conn, plan_id):
session_date = row["session_date"] or m.get_trading_day()
session_capital = m.update_session_capital(conn, session_date, pnl_amount)
_call_insert_trade_record(
m,
plan_id,
dict(
conn=conn,
symbol=sym,
monitor_type=MONITOR_TYPE_TREND,
direction=direction,
trigger_price=avg_e,
stop_loss=float(row["stop_loss"]),
initial_stop_loss=float(row.get("initial_stop_loss") or row["stop_loss"]),
take_profit=float(row["take_profit"]),
margin_capital=margin_cap,
leverage=lev,
pnl_amount=pnl_amount,
hold_seconds=hold_seconds,
trade_style="trend_pullback",
risk_amount=risk_amt,
planned_rr=planned_rr,
actual_rr=m.calc_actual_rr(pnl_amount, risk_amt),
result=res,
opened_at=opened_at,
closed_at=closed_at,
entry_reason=ENTRY_REASON_TREND_PULLBACK,
),
)
else:
session_capital = None
st = _plan_stop_status(result_label)
cur = conn.execute(
"UPDATE trend_pullback_plans SET status=?, message=? WHERE id=? AND status='active'",
@@ -728,36 +771,6 @@ def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) -
)
except Exception:
pass
if _trend_plan_trade_exists(conn, plan_id):
return
session_date = row["session_date"] or m.get_trading_day()
session_capital = m.update_session_capital(conn, session_date, pnl_amount)
kwargs = dict(
conn=conn,
symbol=sym,
monitor_type=MONITOR_TYPE_TREND,
direction=direction,
trigger_price=avg_e,
stop_loss=float(row["stop_loss"]),
initial_stop_loss=float(row.get("initial_stop_loss") or row["stop_loss"]),
take_profit=float(row["take_profit"]),
margin_capital=margin_cap,
leverage=lev,
pnl_amount=pnl_amount,
hold_seconds=hold_seconds,
trade_style="trend_pullback",
risk_amount=risk_amt,
planned_rr=planned_rr,
actual_rr=m.calc_actual_rr(pnl_amount, risk_amt),
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)
else:
m.insert_trade_record(**kwargs)
extra = getattr(m, "build_wechat_close_message", None)
send = getattr(m, "send_wechat_msg", None)
if callable(extra) and callable(send):
@@ -777,7 +790,6 @@ def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) -
session_capital_fallback=session_capital,
)
)
conn.commit()
def _trend_plan_open_age_sec(row, m) -> float: