From a245c8b4dd86962958897ac9db44893ab448ab8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=A5=E5=BE=AE?= Date: Tue, 21 Jul 2026 13:47:52 +0800 Subject: [PATCH] fix: price_monitor crash when shares is string + type guard in write_holding_strategy Root cause: holding_strategies.shares field got set to literal string 'write_holding_strategy' for 6 records, causing TypeError at price_monitor.py line 611 ('>' not supported between str and int). Fixes: 1. price_monitor.py: Replace set comprehension with safe loop that checks isinstance before comparison. Non-numeric shares treated as holdings for safety. 2. mofin_db.py write_holding_strategy: Add type guard that resets non-numeric shares to 0 with warning. 3. Data fix: Updated 5 corrupted holding_strategies records from holdings table (300035/300308/300750/518880/00700). Set 002594 (watchlist) shares=0. --- deploy/profile-scripts/price_monitor.py | 11 ++++++++++- mofin_db.py | 8 +++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/deploy/profile-scripts/price_monitor.py b/deploy/profile-scripts/price_monitor.py index b5159d11..25f5cd92 100644 --- a/deploy/profile-scripts/price_monitor.py +++ b/deploy/profile-scripts/price_monitor.py @@ -608,7 +608,16 @@ def run_once(round_label=""): # === 第三步:买入区偏离检测 + 自动重评 === reassesed_codes = [] # 先做急跌检测(仅持仓,自选股不推送暴跌告警) - holdings_codes = {d["code"] for d in active if (d.get("shares") or 0) > 0} + holdings_codes = set() + for d in active: + shares = d.get("shares", 0) + if isinstance(shares, (int, float)): + if shares > 0: + holdings_codes.add(d["code"]) + else: + # 非数值shares(如被错误写入的字符串),兜底处理 + holdings_codes.add(d["code"]) + print(f" [WARN] {d.get('code')} shares为非数值({shares!r}),视为持仓处理", flush=True) for d in active: code = d["code"] # 非持仓跳过 diff --git a/mofin_db.py b/mofin_db.py index 98ff7177..6e4ba6ab 100644 --- a/mofin_db.py +++ b/mofin_db.py @@ -1180,6 +1180,12 @@ def write_holding_strategy(conn, code: str, name: str, data: dict, except: pass + # ── 类型守卫:shares 必须是数值,防止字符串写入导致下游崩溃 ── + _shares = data.get('shares', 0) + if not isinstance(_shares, (int, float)): + print(f" [TYPE GUARD] {code} shares类型异常({type(_shares).__name__}={_shares!r}),重置为0", flush=True) + _shares = 0 + # DELETE + INSERT conn.execute("DELETE FROM holding_strategies WHERE code=?", (code,)) conn.execute(""" @@ -1199,7 +1205,7 @@ def write_holding_strategy(conn, code: str, name: str, data: dict, """, ( code, name, data.get('version', 1), data.get('price'), data.get('cost'), - data.get('shares', 0), data.get('stop_loss'), data.get('take_profit'), + _shares, data.get('stop_loss'), data.get('take_profit'), data.get('entry_low'), data.get('entry_high'), currency, data.get('strategy_type', 'holding'), data.get('action'), data.get('timing_signal'), data.get('rr_ratio'),