From 5d043627ff7363474e2843fd1c85b92d4f0bca83 Mon Sep 17 00:00:00 2001 From: hmo Date: Mon, 27 Jul 2026 12:22:32 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B9=B0=E5=85=A5=E5=8C=BA=E9=97=B4?= =?UTF-8?q?=E5=8A=A0=E4=B8=AD=E5=80=BC=E6=98=BE=E7=A4=BA(XMPP+=E7=9B=AF?= =?UTF-8?q?=E7=9B=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mofin_db.py | 8 ++++++-- static/index.html | 18 ++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/mofin_db.py b/mofin_db.py index 7ad43b2c..88f55098 100644 --- a/mofin_db.py +++ b/mofin_db.py @@ -1552,9 +1552,12 @@ def flush_rec_digest(max_items=5): _rr_txt = f"RR={_rr_mid}({_lo_val}~{_hi_val})" else: _rr_txt = f"RR={_rr_mid}" + _el = it.get('entry_low') or 0 + _eh = it.get('entry_high') or 0 + _mid = f"{(_el+_eh)/2:.2f}" if _el > 0 and _eh > _el else "—" _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 '—'}" + f" 区{_el or '—'}~{_eh or '—'}(中{_mid})" f" 损{it.get('stop_loss') or '—'} 盈{it.get('take_profit') or '—'}" f" {_rr_txt} 仓位{it.get('position') or '—'}") if it.get('_stale_warn'): @@ -1610,8 +1613,9 @@ def push_recommend_alert(conn, code: str): import sys as _s, os as _o _s.path.insert(0, _o.path.dirname(_o.path.abspath(__file__))) from alert_helper import notify, ACTION + _mid_xmpp = f"{(el+eh)/2:.2f}" if el > 0 and eh > el else "—" msg = (f"📈 {name or code}({code}) 价{price}→12维{sig}!" - f"区间{el}~{eh} 损{sl} 盈{tp} RR={rr or 0} 仓位{pos or '-'}") + f"区间{el}~{eh}(中{_mid_xmpp}) 损{sl} 盈{tp} RR={rr or 0} 仓位{pos or '-'}") return notify("买入信号", msg, ACTION) except Exception as e: print(f" [ALERT] {code} 推送异常: {e}", flush=True) diff --git a/static/index.html b/static/index.html index 4f0c647d..371ac9c1 100644 --- a/static/index.html +++ b/static/index.html @@ -461,7 +461,9 @@ function renderWatchlist() { RR信号仓位 ${stocks.map(s => { - const buyZone = (s.entry_low||0) + '~' + (s.entry_high||0); + const el = s.entry_low||0, eh = s.entry_high||0; + const mid = (el > 0 && eh > el) ? ('(中' + ((el+eh)/2).toFixed(2) + ')') : ''; + const buyZone = el + '~' + eh + mid; const rr = s.rr_ratio || 0; const sl = s.stop_loss || 0; const tp = s.take_profit || 0; @@ -743,7 +745,7 @@ async function openStock(code) {
${sd.timing_signal?`信号 ${sd.timing_signal}`:''} - ${sd.entry_low?`区间 ${sd.entry_low}~${sd.entry_high}`:''} + ${sd.entry_low?`区间 ${sd.entry_low}~${sd.entry_high} 中值${((sd.entry_low+sd.entry_high)/2).toFixed(2)}`:''} ${sd.stop_loss?`损 ${sd.stop_loss}`:''} ${sd.take_profit?`盈 ${sd.take_profit}`:''} RR ${rrTxt} @@ -1452,7 +1454,11 @@ function fmtFullStrategy(s) { const lines = []; if (s.action) lines.push('操作: ' + s.action); if (s.position_advice) lines.push('仓位建议: ' + s.position_advice); - if (s.entry_low || s.entry_high) lines.push('买入区间: ' + (s.entry_low||'—') + '~' + (s.entry_high||'—')); + if (s.entry_low || s.entry_high) { + const el2 = s.entry_low||0, eh2 = s.entry_high||0; + const mid2 = (el2 > 0 && eh2 > el2) ? ' 中值' + ((el2+eh2)/2).toFixed(2) : ''; + lines.push('买入区间: ' + (s.entry_low||'—') + '~' + (s.entry_high||'—') + mid2); + } if (s.stop_loss || s.take_profit) lines.push('止损: ' + (s.stop_loss||'—') + ' / 止盈: ' + (s.take_profit||'—')); if (s.rr_ratio) lines.push('RR: ' + s.rr_ratio.toFixed(2)); if (s.timing_signal) lines.push('信号: ' + s.timing_signal); @@ -1690,7 +1696,11 @@ async function openStrategyHistory(code) { // 策略参数 const params = []; - if (h.entry_low || h.entry_high) params.push('买入区间: ' + (h.entry_low||'—') + '~' + (h.entry_high||'—')); + if (h.entry_low || h.entry_high) { + const el3 = h.entry_low||0, eh3 = h.entry_high||0; + const mid3 = (el3 > 0 && eh3 > el3) ? ' 中值' + ((el3+eh3)/2).toFixed(2) : ''; + params.push('买入区间: ' + (h.entry_low||'—') + '~' + (h.entry_high||'—') + mid3); + } if (h.stop_loss) params.push('止损: ¥' + h.stop_loss); if (h.take_profit) params.push('止盈: ¥' + h.take_profit); if (h.rr_ratio) params.push('RR: ' + h.rr_ratio.toFixed(2));