fix: AI daily review sqlite3.Row crash and error feedback across four exchanges

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-05 13:39:50 +08:00
parent 995ee8d2e1
commit 86a6081090
7 changed files with 97 additions and 37 deletions
+41 -21
View File
@@ -21,46 +21,66 @@ def _journal_nz(v: Any, default: str = "无") -> str:
return s if s else default
def _row_get(row: Any, key: str, default: Any = None) -> Any:
"""兼容 dict 与 sqlite3.RowRow 无 .get 方法)。"""
if row is None:
return default
getter = getattr(row, "get", None)
if callable(getter):
return getter(key, default)
try:
keys = row.keys() if hasattr(row, "keys") else ()
if key in keys:
return row[key]
except Exception:
pass
try:
return row[key]
except (KeyError, TypeError, IndexError):
return default
def journal_row_lines_for_ai(
idx: int,
row: Mapping[str, Any],
row: Any,
*,
include_hold_duration: bool = True,
) -> str:
"""把 journal 字段拼成给 AI 的文本;四所日复盘/周复盘共用。"""
lines = [
(
f"{idx}. {_journal_nz(row.get('coin'))} {_journal_nz(row.get('tf'))} "
f"| 盈亏:{_journal_nz(row.get('pnl'))}U "
f"| 实际RR:{_journal_nz(row.get('real_rr'))} "
f"| 预期RR:{_journal_nz(row.get('expect_rr'))}"
f"{idx}. {_journal_nz(_row_get(row, 'coin'))} {_journal_nz(_row_get(row, 'tf'))} "
f"| 盈亏:{_journal_nz(_row_get(row, 'pnl'))}U "
f"| 实际RR:{_journal_nz(_row_get(row, 'real_rr'))} "
f"| 预期RR:{_journal_nz(_row_get(row, 'expect_rr'))}"
),
f" 开仓逻辑:{_journal_nz(row.get('entry_reason'))}",
f" 平仓/离场(交易员自述):{_journal_nz(row.get('exit_reason'))}",
f" 开仓逻辑:{_journal_nz(_row_get(row, 'entry_reason'))}",
f" 平仓/离场(交易员自述):{_journal_nz(_row_get(row, 'exit_reason'))}",
]
if include_hold_duration:
lines.append(f" 持仓时长:{_journal_nz(row.get('hold_duration'))}")
lines.append(f" 持仓时长:{_journal_nz(_row_get(row, 'hold_duration'))}")
ee_bits = [
_journal_nz(row.get("early_exit")),
_journal_nz(row.get("early_exit_reason")),
_journal_nz(row.get("early_exit_trigger")),
_journal_nz(row.get("early_exit_note")),
_journal_nz(_row_get(row, "early_exit")),
_journal_nz(_row_get(row, "early_exit_reason")),
_journal_nz(_row_get(row, "early_exit_trigger")),
_journal_nz(_row_get(row, "early_exit_note")),
]
if any(x != "" for x in ee_bits):
lines.append(
" 提前离场记录:"
f"{ee_bits[0]} | 原因:{ee_bits[1]} | 触发:{ee_bits[2]} | 备注:{ee_bits[3]}"
)
mood_bits = f"心态标签:{_journal_nz(row.get('mood_issues'))}"
if row.get("mood_score") is not None:
mood_bits += f" | 自评心态分:{row.get('mood_score')}"
mood_bits = f"心态标签:{_journal_nz(_row_get(row, 'mood_issues'))}"
mood_score = _row_get(row, "mood_score")
if mood_score is not None:
mood_bits += f" | 自评心态分:{mood_score}"
lines.append(f" {mood_bits}")
if _journal_nz(row.get("post_breakeven_stare")) != "":
lines.append(f" 保本后盯盘:{_journal_nz(row.get('post_breakeven_stare'))}")
if _journal_nz(row.get("new_trade_while_occupied")) != "":
lines.append(f" 占用时新开仓:{_journal_nz(row.get('new_trade_while_occupied'))}")
if _journal_nz(row.get("note")) != "":
lines.append(f" 备注:{_journal_nz(row.get('note'))}")
if _journal_nz(_row_get(row, "post_breakeven_stare")) != "":
lines.append(f" 保本后盯盘:{_journal_nz(_row_get(row, 'post_breakeven_stare'))}")
if _journal_nz(_row_get(row, "new_trade_while_occupied")) != "":
lines.append(f" 占用时新开仓:{_journal_nz(_row_get(row, 'new_trade_while_occupied'))}")
if _journal_nz(_row_get(row, "note")) != "":
lines.append(f" 备注:{_journal_nz(_row_get(row, 'note'))}")
return "\n".join(lines) + "\n"