fix: RR架构统一——s2_panic_v2补rr列(断链)/per_stock_reassess删rr覆盖(RR由scanner定)/strategy_lifecycle不重算rr

This commit is contained in:
xxm
2026-08-18 13:27:45 +08:00
parent 13ff507a3e
commit 0ca4e4b69f
3 changed files with 16 additions and 25 deletions
+4 -12
View File
@@ -66,18 +66,10 @@ def _build_full_analysis(code, entry, result):
eh = result.get("entry_high")
sl = result.get("stop_loss") or entry.get("stop_loss", 0)
tp = result.get("take_profit") or entry.get("take_profit", 0)
# 2026-08-18 修复 rr_ratio:统一用 entry/stop/tp 算(与 promote 同口径 rr = (tp-mid)/(mid-sl)
# strategy_lifecycle 的 rr_ratio 可能算错(6.5 vs 实际 8.64),统一用 entry/stop/tp 算最准
_el_rr = result.get("entry_low") if result.get("entry_low") is not None else entry.get("entry_low", 0)
_eh_rr = result.get("entry_high") if result.get("entry_high") is not None else entry.get("entry_high", 0)
_sl_rr = result.get("stop_loss") or entry.get("stop_loss", 0)
_tp_rr = result.get("take_profit") or entry.get("take_profit", 0)
if _el_rr > 0 and _eh_rr > _el_rr and _sl_rr > 0 and _tp_rr > 0:
_mid_rr = (_el_rr + _eh_rr) / 2
rr = round((_tp_rr - _mid_rr) / (_mid_rr - _sl_rr), 2) if _mid_rr > _sl_rr else 0
else:
# 无有效区间/止损/止盈时,用 holding 的旧 rr_ratio 或 0
rr = entry.get("rr_ratio", 0)
# 2026-08-18 修复:删除 rr_ratio 覆盖——RR 由 scanner 定(candidates.rr=holding.rr_ratio),
# per_stock_reassess 不该重算/覆盖(它该用 holding 的 rr_ratio,不重算)。
# 正确架构:RR 是 scanner 定义的单一事实来源,per_stock_reassess 只读不重算。
rr = entry.get("rr_ratio", 0)
act = result.get("action", "")
# ── 从DB拉取大盘、基本面、资金流 ──
@@ -159,14 +159,17 @@ def main():
inserted = 0
for code, name, sig in hits:
reasons = (f"rsi={sig['rsi']} mcap_q={sig['mcap_q']} score={sig['score']}")
# 2026-08-18 补 rr 列(断链 bugpromote 的 _rr is None 全跳过,与 b_td1_v3 同口径)
_mid_v = (sig['price'] * 0.98 + sig['price']) / 2
_rr_v = round((sig["target"] - _mid_v) / (_mid_v - sig["stop_loss"]), 2) if _mid_v > sig["stop_loss"] > 0 else 0
conn.execute(
"INSERT INTO candidates (code, name, sector, reason, entry_range, stop_loss, target, source_strategy, created_at) "
"VALUES (?,?,?,?,?,?,?,?,datetime('now','localtime')) "
"INSERT INTO candidates (code, name, sector, reason, entry_range, stop_loss, target, rr, source_strategy, created_at) "
"VALUES (?,?,?,?,?,?,?,?,?,datetime('now','localtime')) "
"ON CONFLICT(code) DO UPDATE SET "
"name=excluded.name, sector=excluded.sector, reason=excluded.reason, "
"entry_range=excluded.entry_range, stop_loss=excluded.stop_loss, target=excluded.target, source_strategy=excluded.source_strategy",
"entry_range=excluded.entry_range, stop_loss=excluded.stop_loss, target=excluded.target, rr=excluded.rr, source_strategy=excluded.source_strategy",
(code, code, "s2_panic_v2", reasons,
f"{sig['price']*0.98:.2f}~{sig['price']:.2f}", sig["stop_loss"], sig["target"], "s2_panic_v2"))
f"{sig['price']*0.98:.2f}~{sig['price']:.2f}", sig["stop_loss"], sig["target"], _rr_v, "s2_panic_v2"))
inserted += 1
print(f" 🟢 {code} {name}{sig['price']} score={sig['score']} {reasons}", flush=True)
conn.commit()
+5 -9
View File
@@ -1179,15 +1179,11 @@ def reassess_strategy(code, name, price, cost, shares, current_action,
found = True
break
# ----- 风险回报比最终计算 -----
# 2026-08-18 修复:买入价用买入区中值(entry_mid)算 risk,不是现价
# 现价不是买入价——实盘按 entry_mid 买入,risk=entry_mid-stopreward=tp-entry_mid
_el = result.get("entry_low") or 0
_eh = result.get("entry_high") or 0
_entry_mid = (_el + _eh) / 2 if (_el > 0 and _eh > _el) else price
risk = max(_entry_mid - new_stop, _entry_mid * 0.01)
reward = max(new_target - _entry_mid, 0)
rr_ratio = reward / risk if risk > 0 else 0
# ----- 风险回报比(不重算,RR 由 scanner 定)-----
# 2026-08-18 修复:RR 由 scanner 定(candidates.rr=holding.rr_ratio),
# strategy_lifecycle 管持仓状态(信号/止损移动),不重算/重写 RR。
# 正确架构:RR 是 scanner 定义的单一事实来源,lifecycle 只读不重算。
rr_ratio = result.get("rr_ratio") or 0
# ----- 状态判断 -----
if is_deep_loss: