diff --git a/deploy/profile-scripts/batch_reassess.py b/deploy/profile-scripts/batch_reassess.py index 36b47937..8b2e53e2 100644 --- a/deploy/profile-scripts/batch_reassess.py +++ b/deploy/profile-scripts/batch_reassess.py @@ -459,12 +459,12 @@ PE={data.get('pe','?')}(最新财报) 市值={data.get('mcap','?')}亿 请严格按以下格式输出(注意节标题不可省略): -【策略判断】四选一:维持原策略 / 修改参数 / 策略失效重定 / 更换策略归类 -- 默认倾向「维持原策略」;只有情势体检命中红线、或重评侧重检查发现原入场逻辑不成立时,才选后三者 -- 「策略失效重定」= 原策略已不适用,按当前市场环境重新制定(新止损/止盈/持有期) -- 「更换策略归类」= 该股当前更适合另一个策略,从【策略定义】候选中选择,禁止自创 +【策略判断】三选一:维持原策略 / 修改参数 / 策略失效需更换 +- 默认倾向「维持原策略」;只有情势体检命中红线、或重评侧重检查发现原入场逻辑不成立时,才选「策略失效需更换」 +- 「修改参数」= 策略框架仍适用,仅微调参数(止损/止盈/区间) +- 「策略失效需更换」= 原策略在当前情势下已不适合(温区切换/黑天鹅/入场逻辑不成立),必须换一个策略来评估 【策略失效理由】(策略判断≠维持原策略时必填,逐条对照重评侧重说明哪条不成立;维持时写"无需修改") -【更换策略归类】(仅当策略判断=更换策略归类时填,写策略名) +【更换策略归类】策略失效需更换时【必须】从候选中选一个(禁止自创);若确实无合适策略,写"无合适策略" 【维持或修改】明确二选一判断:维持原策略 / 需要修改策略 【修改点及理由】 如果维持原策略 → 写"无需修改" @@ -591,10 +591,11 @@ def parse_response(text): break # 2026-08-18 策略判断(只认【策略判断】节行) + # 老莫 2026-08-18:失效=需更换(同一决策),失效时必须给新归属;给不出才停在失效未归属 result["strategy_judge"] = "" _sj = _section_line("策略判断") if _sj: - _m = re.search(r'策略判断】\s*(维持原策略|修改参数|策略失效重定|更换策略归类)', _sj) + _m = re.search(r'策略判断】\s*(维持原策略|修改参数|策略失效需更换|策略失效重定)', _sj) if _m: result["strategy_judge"] = _m.group(1) # 策略失效理由 @@ -602,18 +603,19 @@ def parse_response(text): _sr = _section_line("策略失效理由") if _sr: result["strategy_reason"] = re.sub(r'^\s*【策略失效理由】\s*', '', _sr).strip()[:200] - # 更换策略归类(封闭集校验:必须在候选列表内) + # 更换策略归类(封闭集校验:必须在候选列表内;失效和更换都解析) result["strategy_switch_to"] = "" _CANDIDATES = ("accumulation", "b_td1_v3", "v_mr", "hk_pe_mom", "hk_pe_oversold", "p_oversold", "s2_panic", "leader", "v_next", "v8.1") _st = _section_line("更换策略归类") if _st: _body = re.sub(r'^\s*【更换策略归类】\s*', '', _st).strip().lower() - for c in _CANDIDATES: - if c in _body: - result["strategy_switch_to"] = c - break - if not result["strategy_switch_to"] and result["strategy_judge"] == "更换策略归类": - result["strategy_judge"] = "策略失效重定" # 归因无效→降级 + if "无合适策略" in _body or "无合适" in _body: + result["strategy_switch_to"] = "" # 明确无合适 → 失效未归属 + else: + for c in _CANDIDATES: + if c in _body: + result["strategy_switch_to"] = c + break return result @@ -741,14 +743,20 @@ def save_result(code, full_text, parsed, ta_levels=None): conn.execute(sql, params) conn.commit() - # 2026-08-18 策略状态落库(strategy_judge/switch_to,老莫:策略切换决策) + # 2026-08-18 策略状态落库(strategy_judge/switch_to,老莫:失效=需更换,同一决策) _j = parsed.get("strategy_judge", "") - if _j == "策略失效重定": - conn.execute("UPDATE holding_strategies SET strategy_state='invalidated' WHERE code=? AND status='active'", (code,)) - conn.commit() - elif _j == "更换策略归类" and parsed.get("strategy_switch_to"): - conn.execute("UPDATE holding_strategies SET strategy_attributed=?, strategy_state='switched', strategy_provenance='llm_attributed' WHERE code=? AND status='active'", (parsed["strategy_switch_to"], code)) - conn.commit() + _st = parsed.get("strategy_switch_to", "") + if _j in ("策略失效需更换", "策略失效重定"): + if _st: + # 失效+给归属 → 切换到新策略 + conn.execute("UPDATE holding_strategies SET strategy_attributed=?, strategy_state='switched', strategy_provenance='llm_attributed' WHERE code=? AND status='active'", (_st, code)) + conn.commit() + print(f" ✅ 策略切换: {_j} → 归属 {_st}(strategy_state=switched)") + else: + # 失效+无合适归属 → 标记失效 + conn.execute("UPDATE holding_strategies SET strategy_state='invalidated' WHERE code=? AND status='active'", (code,)) + conn.commit() + print(f" ✅ 策略失效: {_j} 无合适归属(strategy_state=invalidated)") # ── 信号以分析为唯一事实源(防信号/分析脱节)── from mofin_db import reconcile_signal_from_analysis diff --git a/deploy/profile-scripts/per_stock_reassess.py b/deploy/profile-scripts/per_stock_reassess.py index 0cc74115..7cb4e57d 100644 --- a/deploy/profile-scripts/per_stock_reassess.py +++ b/deploy/profile-scripts/per_stock_reassess.py @@ -476,16 +476,17 @@ def main(): _p2 = _pr2(_full_analysis_text or "") _j2 = _p2.get("strategy_judge", "") _st2 = _p2.get("strategy_switch_to", "") - if _j2 == "策略失效重定": - _rc_conn = __import__('sqlite3').connect('/home/hmo/MoFin/data/mofin.db') - _rc_conn.execute("UPDATE holding_strategies SET strategy_state='invalidated' WHERE code=? AND status='active'", (code,)) - _rc_conn.commit(); _rc_conn.close() - print(f" ✅ 策略判断=策略失效重定,strategy_state→invalidated") - elif _j2 == "更换策略归类" and _st2: - _rc_conn = __import__('sqlite3').connect('/home/hmo/MoFin/data/mofin.db') - _rc_conn.execute("UPDATE holding_strategies SET strategy_attributed=?, strategy_state='switched', strategy_provenance='llm_attributed' WHERE code=? AND status='active'", (_st2, code)) - _rc_conn.commit(); _rc_conn.close() - print(f" ✅ 策略判断=更换策略归类,strategy_attributed={_st2}") + if _j2 in ("策略失效需更换", "策略失效重定"): + if _st2: + _rc_conn = __import__('sqlite3').connect('/home/hmo/MoFin/data/mofin.db') + _rc_conn.execute("UPDATE holding_strategies SET strategy_attributed=?, strategy_state='switched', strategy_provenance='llm_attributed' WHERE code=? AND status='active'", (_st2, code)) + _rc_conn.commit(); _rc_conn.close() + print(f" ✅ 策略切换: {_j2} → 归属 {_st2}(switched)") + else: + _rc_conn = __import__('sqlite3').connect('/home/hmo/MoFin/data/mofin.db') + _rc_conn.execute("UPDATE holding_strategies SET strategy_state='invalidated' WHERE code=? AND status='active'", (code,)) + _rc_conn.commit(); _rc_conn.close() + print(f" ✅ 策略失效: {_j2} 无合适归属(invalidated)") elif _j2: print(f" ℹ️ 策略判断={_j2}(维持/修改参数,不落库)") except Exception as _pe: