From 5d08353d4494f95f2befbd598df6e26d33cb54e5 Mon Sep 17 00:00:00 2001 From: hmo Date: Mon, 27 Jul 2026 09:51:16 +0800 Subject: [PATCH] =?UTF-8?q?fix(rr):=20=E4=B8=89=E5=80=BCRR=E5=85=B1?= =?UTF-8?q?=E7=94=A8=E7=BB=9F=E4=B8=80=E4=B8=8A=E6=96=B9=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=20=E6=A0=B9=E6=B2=BB=E4=B8=AD=E5=80=BC>=E8=8C=83=E5=9B=B4?= =?UTF-8?q?=E4=B8=8A=E4=B8=8B=E7=95=8C=E7=9A=84=E8=87=AA=E7=9B=B8=E7=9F=9B?= =?UTF-8?q?=E7=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 上方目标基于区间中值统一定(非每个x单独算),确保rr_low>rr_mid>rr_high恒成立 - digest三值范围排序(小~大)显示,数学自洽 - 弹窗已用下沿/上沿语义标签,数值颠倒不影响理解 --- mofin_db.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/mofin_db.py b/mofin_db.py index 6bbb8ed2..74935ba4 100644 --- a/mofin_db.py +++ b/mofin_db.py @@ -1172,9 +1172,10 @@ def recompute_rr(conn, code: str) -> float: """用买入区+已存止损/止盈重算三值 RR 并写回(rr_low/rr_ratio中值/rr_high)。 根治"LLM 不输出 RR → rr_ratio 永远 0"的断链(红线:RR 由系统算,不信 LLM)。 公式: RR(x) = (上方目标 - x) / (x - 止损);x 分别取买入区下沿/中值/上沿。 - 上方目标 = min(止盈, 20日新高若高于x)(2026-07-24 老爸: - 前高挡在中间时止盈是放空炮,真实RR必须对最近上方阻力先结算; - 突破形态(现价已在20日新高)不惩罚,用止盈全值)。 + 上方目标基于中值参考价统一定(不因 x 不同而漂移),保证三值自洽: + rr_low > rr_ratio > rr_high 恒成立,展示"在同一阻力下不同入场价的敏感度"。 + 目标 = min(止盈, 20日新高若高于中值)(2026-07-24 老爸: + 前高挡在中间时止盈是放空炮,真实RR必须对最近上方阻力先结算)。 rr_ratio=中值 RR 用于排序与2.0门槛;rr_low/rr_high 展示入场价敏感度。 区间缺失 → 中值兜底现价(low/high=0);损/盈缺失或 x<=止损 → 该值=0。""" try: @@ -1196,12 +1197,14 @@ def recompute_rr(conn, code: str) -> float: except Exception: pass + # 基准参考价 = 区间中值(决定上方目标,三值共用) + ref = (el + eh) / 2.0 if el > 0 and eh > el else 0 + target = tp + if ref > 0 and high_20d > ref and high_20d < tp: + target = high_20d + def _rr(x): - if sl > 0 and tp > 0 and x > sl: - # 上方目标:止盈与前高取近者(前高高于x才算阻力,否则视为突破用止盈) - target = tp - if high_20d > x and high_20d < target: - target = high_20d + if sl > 0 and target > 0 and x > sl and target > x: v = round((target - x) / (x - sl), 2) return v if v > 0 else 0.0 return 0.0 @@ -1451,8 +1454,12 @@ def flush_rec_digest(max_items=5): for i, it in enumerate(top): _rr_mid = it.get('rr') or 0 _rr_lo, _rr_hi = it.get('rr_low') or 0, it.get('rr_high') or 0 - _rr_txt = (f"RR={_rr_mid}({_rr_lo}~{_rr_hi})" if _rr_lo and _rr_hi and _rr_lo != _rr_hi - else f"RR={_rr_mid}") + if _rr_lo and _rr_hi and _rr_lo != _rr_hi: + _lo_val = min(_rr_lo, _rr_hi) + _hi_val = max(_rr_lo, _rr_hi) + _rr_txt = f"RR={_rr_mid}({_lo_val}~{_hi_val})" + else: + _rr_txt = f"RR={_rr_mid}" _badge = "💰可执行" if it['code'] in _exec_codes else "⏳排队" lines.append(f"• {_badge} {it.get('name') or it['code']}({it['code']}) {it['signal']}" f" 区{it.get('entry_low') or '—'}~{it.get('entry_high') or '—'}"