From 778b2137f6b8f27156680b0cd0b0096edc49d478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=A5=E5=BE=AE?= Date: Thu, 9 Jul 2026 20:52:53 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AE=8C=E6=95=B4=E4=B9=9D=E7=BB=B4?= =?UTF-8?q?=E5=88=86=E6=9E=90=E5=AD=98=E5=82=A8+=E6=98=BE=E7=A4=BA(?= =?UTF-8?q?=E5=8F=AF=E7=82=B9=E5=87=BB=E6=9F=A5=E7=9C=8B)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/mofin_db.py | 10 +++--- scripts/per_stock_reassess.py | 59 +++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/scripts/mofin_db.py b/scripts/mofin_db.py index 9965877f..38987a3e 100644 --- a/scripts/mofin_db.py +++ b/scripts/mofin_db.py @@ -1084,6 +1084,7 @@ def write_holding_strategy(conn, code: str, name: str, data: dict) -> tuple[bool signal_factors_j = _json.dumps(data.get('signal_factors', []), ensure_ascii=False) if isinstance(data.get('signal_factors'), list) else data.get('signal_factors_json', '') # DELETE + INSERT + conn.execute("PRAGMA foreign_keys=OFF") # 临时禁用FK(自选股可能不在stocks表) conn.execute("DELETE FROM holding_strategies WHERE code=?", (code,)) conn.execute(""" INSERT INTO holding_strategies @@ -1094,10 +1095,10 @@ def write_holding_strategy(conn, code: str, name: str, data: dict) -> tuple[bool source, reason, updated_at, avg_price, decision_timestamp, note, quality_check, quality_checked_at, quality_issues_json, position_advice, - signal_factors_json, time_horizon, decision_type) + signal_factors_json, time_horizon, decision_type, full_analysis) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?, datetime('now','localtime'), - ?,?,?,?,?,?,?,?,?,?) + ?,?,?,?,?,?,?,?,?,?,?) """, ( code, name, data.get('version', 1), data.get('price'), data.get('cost'), @@ -1113,13 +1114,14 @@ def write_holding_strategy(conn, code: str, name: str, data: dict) -> tuple[bool data.get('avg_price', 0), data.get('timestamp') or data.get('created_at', ''), data.get('note', ''), - data.get('quality_check', ''), + data.get('quality_check', 'pending'), data.get('quality_checked_at', ''), quality_issues_j, data.get('position_advice', ''), signal_factors_j, data.get('time_horizon', ''), - data.get('type', data.get('strategy_type', 'holding')), + data.get('decision_type', data.get('strategy_type', 'holding')), + data.get('full_analysis', ''), )) conn.commit() return True, f"策略 {code} 已写入" diff --git a/scripts/per_stock_reassess.py b/scripts/per_stock_reassess.py index cdcde897..10feb8ee 100644 --- a/scripts/per_stock_reassess.py +++ b/scripts/per_stock_reassess.py @@ -13,6 +13,47 @@ from strategy_lifecycle import reassess_with_context as reassess_strategy from mo_data import read_decisions, read_portfolio +def _build_full_analysis(code, entry, result): + """从重评结果构建完整九维分析文本""" + if not result: + return "" + lines = [] + name = entry.get("name", code) + price = result.get("price", entry.get("price", 0)) + + # 技术面 + tech = result.get("tech_snapshot") or entry.get("tech_snapshot", "") + # 行业 + sector = result.get("sector_context") or entry.get("sector_context", "") + # 信号 + signal = result.get("timing_signal") or entry.get("timing_signal", "") + # 类别 + category = result.get("stock_category") or entry.get("stock_category", "") + + el = result.get("entry_low") or entry.get("entry_low", 0) + eh = result.get("entry_high") or entry.get("entry_high", 0) + sl = result.get("stop_loss") or entry.get("stop_loss", 0) + tp = result.get("take_profit") or entry.get("take_profit", 0) + rr = result.get("rr_ratio") or entry.get("rr_ratio", 0) + + lines.append(f"{name}({code}) — 九维分析") + lines.append("") + if sector: lines.append(f"🏭 行业背景: {sector}") + if tech: lines.append(f"📊 技术分析: {tech}") + if category: lines.append(f"📌 分类: {category}") + lines.append(f"📈 信号: {signal}") + if price: lines.append(f"💵 当前价: {price}") + if el or eh: lines.append(f"🎯 买入区: {el}~{eh}") + if sl: lines.append(f"🛑 止损: {sl}") + if tp: lines.append(f"✅ 止盈: {tp}") + if rr: lines.append(f"📊 RR: {rr:.2f}") + + act = result.get("action", "") + if act: lines.append(f"📋 策略: {act}") + + return "\n".join(lines) + + def main(): codes = [a for a in sys.argv[1:] if not a.startswith("-")] if not codes: @@ -153,10 +194,28 @@ def main(): "source": entry.get("source", "auto"), "reason": result.get("action_note", ""), "version": entry.get("version", 1), + "full_analysis": _build_full_analysis(code, entry, result) if result else "", } write_holding_strategy(_conn, code, entry.get("name", ""), _db_entry) _conn.commit() _conn.close() + # 验证写入 + _fa_check = _db_entry.get("full_analysis", "") + print(f" DEBUG: full_analysis长度={len(_fa_check)} 内容=[{_fa_check[:100]}]") + # 直接用SQL写入full_analysis + try: + _fa_conn = __import__('sqlite3').connect("/home/hmo/MoFin/data/mofin.db") + _fa_conn.execute("UPDATE holding_strategies SET full_analysis=? WHERE code=? AND status='active'", (_fa_check, code)) + _fa_conn.commit() + _fa_conn.close() + print(f" ✅ full_analysis直接SQL写入成功") + except Exception as _fa_e: + print(f" ⚠️ 直接SQL写入失败: {_fa_e}") + _v = __import__('sqlite3').connect(str(__import__('pathlib').Path("/home/hmo/MoFin/data/mofin.db"))) + _fa = _v.execute("SELECT full_analysis FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() + if _fa and _fa[0]: print(f" ✅ full_analysis已写入({len(_fa[0])}字)") + else: print(f" ⚠️ full_analysis为空") + _v.close() print(f" [DB] holding_strategies 已更新: {code}") except Exception as _dbe: print(f" [DB FAIL] holding_strategies 写入失败: {_dbe}", file=sys.stderr)