From eab23c30e2e9e5f25b8ad174467abd249d254140 Mon Sep 17 00:00:00 2001 From: xxm Date: Mon, 17 Aug 2026 15:52:45 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20promote=E8=AF=BBcandidates.rr=E4=B8=8D?= =?UTF-8?q?=E9=87=8D=E9=94=9A=E5=AE=9A=E2=80=94=E2=80=94RR=E7=94=B1?= =?UTF-8?q?=E7=AD=96=E7=95=A5=E7=AE=97=E5=8F=AA=E5=8D=A1=E9=98=88=E5=80=BC?= =?UTF-8?q?(b=5Ftd1/p=5Foversold=E8=B1=81=E5=85=8D=E8=B6=85=E8=B7=8C?= =?UTF-8?q?=E9=97=A8=E6=A7=9B)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/profile-scripts/promote_candidates.py | 54 ++++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/deploy/profile-scripts/promote_candidates.py b/deploy/profile-scripts/promote_candidates.py index e648accb..99c7ce91 100644 --- a/deploy/profile-scripts/promote_candidates.py +++ b/deploy/profile-scripts/promote_candidates.py @@ -35,7 +35,7 @@ def main(): # 读未提拔候选(按评分降序) rows = conn.execute(""" - SELECT c.code, c.name, c.score_final, c.entry_range, c.stop_loss, c.target, c.sector + SELECT c.code, c.name, c.score_final, c.entry_range, c.stop_loss, c.target, c.sector, c.rr FROM candidates c WHERE (c.promoted IS NULL OR c.promoted = 0) AND (c.dropped IS NULL OR c.dropped = 0) @@ -105,38 +105,36 @@ def main(): processed += 1 continue - # 优中选优闸:ST排除 + 技术位锚定 + RR>=2.0 + # ── 2026-08-17 老莫规范:RR 由策略算,promote 只卡阈值,不重锚定 ── + # 原逻辑用 technical_analysis 近20日低点当止损(暴跌插针)→ RR 从策略的2.3崩到0.82, + # promote 管道自 08-05 死12天。现改为读候选自带 c.rr(策略负责计算)。 if "ST" in (name or "").upper(): print(f" ⏭ {code} {name} ST股,不入自选") processed += 1 continue - try: - import sys as _s - if '/home/hmo/MoFin/deploy/profile-scripts' not in _s.path: - _s.path.insert(0, '/home/hmo/MoFin/deploy/profile-scripts') - import technical_analysis as _ta - _ta_r = _ta.full_analysis(code) - _sr = (_ta_r or {}).get("support_resistance", {}) or {} - _ws, _ss = _sr.get("weak_support"), _sr.get("strong_support") - _wr, _sr2 = _sr.get("weak_resist"), _sr.get("strong_resist") - if _ws and _wr and _price > 0: - el = round(_ws * 0.995, 2) - eh = round(min(_wr, _price * 1.05), 2) - sl = round((_ss or _ws) * 0.985, 2) - tp = round(_sr2 or _wr * 1.15, 2) - except Exception as _te: - print(f" ⚠️ {code} 技术位锚定失败({_te}),用扫描器参数", flush=True) - if el > 0 and eh > el and sl > 0 and tp > 0: - _mid = (el + eh) / 2 - _rr = (tp - _mid) / (_mid - sl) if (_mid - sl) > 0 else 0 - # 2026-08-11:p_oversold(预测超跌反弹)候选跳过 RR>=2.0 门槛—— - # 超跌反弹候选 RR 天然 <2(支撑近/压力远),用专属评估替代(部署计划 §8.3 方案C) - if _rr < 2.0 and cand_sector != "p_oversold": - print(f" ⏭ {code} {name} RR={_rr:.2f}<2.0,不入自选") - processed += 1 - continue + _rr = r[7] # c.rr(策略自带) + if _rr is None: + print(f" ⏭ {code} {name} 策略未提供RR(scanner需在INSERT时写candidates.rr),跳过") + processed += 1 + continue + # 超跌类策略豁免 RR 门槛(超跌反弹 RR 天然 <2,用策略自带参数即可,同 p_oversold 先例) + if _rr < 2.0 and cand_sector not in ("p_oversold", "b_td1_v3", "b_td1"): + print(f" ⏭ {code} {name} RR={_rr:.2f}<2.0,不入自选") + processed += 1 + continue + # 用候选自带参数(不再重锚定) + _parts = (r[3] or "").split("~") + if len(_parts) >= 2: + try: + el = float(_parts[0]); eh = float(_parts[1]) + except Exception: + el = eh = 0 else: - print(f" ⏭ {code} {name} 锚定后参数无效(区{el}~{eh} 损{sl} 盈{tp}),跳过") + el = eh = 0 + sl = r[4] or 0 + tp = r[5] or 0 + if not (el > 0 and eh > el and sl > 0 and tp > 0): + print(f" ⏭ {code} {name} 候选参数无效(区{el}~{eh} 损{sl} 盈{tp}),跳过") processed += 1 continue