feat: 信号权威层级+推荐转场推送统一+🔔分级修正
1. 权威层级: 新鲜(<20h)12维动作级信号, 技术路径(regenerate_all/
price_monitor)无权降级为关注/信号不充分/持有——只有LLM路径或
风险信号(卖出/止盈)可覆盖。根治推荐区'出现-消失'抖动
2. 推荐转场推送统一收拢到 mofin_db.push_recommend_alert:
tag新转为current_recommend时推送(全路径), 含质量门禁;
移除batch_reassess内联推送(防双重告警)
3. price_monitor 🔔分级: 只有持仓股的卖出/止盈才ACTION直推,
买入/加仓机会一律进INFO摘要(老爸: 这种消息不要再发了)
This commit is contained in:
@@ -376,49 +376,11 @@ def save_result(code, full_text, parsed):
|
||||
# ── 推荐操作 tag 同步(与 XMPP 动作级信号同源)──
|
||||
sync_recommend_tag(conn, code, parsed.get("signal", ""))
|
||||
|
||||
# 买入信号→推XMPP通知(在conn close前执行)——推送质量门禁:
|
||||
# 价格必须>0(live_prices实时价)、区间有效(下沿<上沿<下沿x3)、现价不超过上沿5%、
|
||||
# 损<下沿、盈>上沿、损在(0.5x~1.0x)现价内。任何一项不过 → 不推,只记日志。
|
||||
if parsed.get("signal") == "买入":
|
||||
try:
|
||||
_nr = conn.execute("SELECT name FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone()
|
||||
_lp = conn.execute("SELECT price FROM live_prices WHERE code=?", (code,)).fetchone()
|
||||
_name = _nr[0] if _nr else code
|
||||
_p = _lp[0] if _lp and _lp[0] else 0
|
||||
_el = parsed.get("entry_low", 0)
|
||||
_eh = parsed.get("entry_high", 0)
|
||||
_sl = parsed.get("stop_loss", 0)
|
||||
_tp = parsed.get("take_profit", 0)
|
||||
_pos = parsed.get("position", "")
|
||||
_ok, _why = _validate_buy_alert(_p, _el, _eh, _sl, _tp)
|
||||
if _ok:
|
||||
_msg = f"📈 {_name}({code}) 价{_p}→12维分析生成买入信号!区间{_el}~{_eh} 损{_sl} 盈{_tp} 仓位{_pos}"
|
||||
from alert_helper import notify as _notify, ACTION as _ACT
|
||||
_notify("买入信号", _msg, _ACT)
|
||||
print(f" \U0001f4e8 XMPP推送成功: {_msg[:60]}")
|
||||
else:
|
||||
print(f" ⚠️ 买入信号未过推送门禁({_why}),仅记日志不推送", flush=True)
|
||||
except Exception as _e:
|
||||
print(f" \u26a0\ufe0f XMPP推送失败: {_e}")
|
||||
# 买入信号推送已统一收拢到 sync_recommend_tag 的转场推送(防双重告警)。
|
||||
# 本路径只负责写库+tag,推送由 mofin_db.push_recommend_alert 在 tag 转场时触发。
|
||||
|
||||
conn.close()
|
||||
|
||||
|
||||
def _validate_buy_alert(price, el, eh, sl, tp):
|
||||
"""买入信号推送门禁(垃圾信号不发)。
|
||||
返回 (ok, reason)"""
|
||||
if not price or price <= 0:
|
||||
return False, f"无实时价格({price})"
|
||||
if not (el > 0 and eh > el and eh < el * 3):
|
||||
return False, f"区间无效({el}~{eh})"
|
||||
if price > eh * 1.05:
|
||||
return False, f"现价{price}高于区间上沿{eh}超5%(追高信号不推)"
|
||||
if not (sl > 0 and sl < el and price * 0.5 <= sl <= price):
|
||||
return False, f"止损{sl}不合理(需0.5x~1.0x现价且<下沿{el})"
|
||||
if not (tp > eh and tp > sl):
|
||||
return False, f"止盈{tp}需>上沿{eh}且>止损{sl}"
|
||||
return True, ""
|
||||
|
||||
def process_stock(code, force_today=False):
|
||||
"""处理单只股票"""
|
||||
print(f"\n{'='*50}")
|
||||
|
||||
@@ -541,9 +541,13 @@ def run_once(round_label=""):
|
||||
buy_lo = d.get("entry_low", 0)
|
||||
buy_hi = d.get("entry_high", 0)
|
||||
rr = result.get("rr_ratio", 0)
|
||||
if _can_push(code, "stop_loss"):
|
||||
msg = f"🔔 {name}({code}) 价{price}→触发操作区间{max(buy_lo,0):.2f}~{buy_hi:.2f},已触发重评|RR={rr}"
|
||||
_push_action("操作信号", msg)
|
||||
# 分级(老爸规则:只有持仓风控动作才ACTION直推;买入/加仓机会进摘要)
|
||||
if timing_signal in ("卖出","止盈") and (d.get("shares") or 0) > 0:
|
||||
if _can_push(code, "stop_loss"):
|
||||
msg = f"🔔 {name}({code}) 价{price}→触发操作区间{max(buy_lo,0):.2f}~{buy_hi:.2f},已触发重评|RR={rr}"
|
||||
_push_action("操作信号", msg)
|
||||
else:
|
||||
_zone_entries.append(f"{name}({code}) {price}→入区+重评{timing_signal}|RR={rr}")
|
||||
outputs.append(f" 📨 止损重评→已推送Dad: {action}")
|
||||
except Exception as e:
|
||||
outputs.append(f" ⚠️ 止损重评失败: {e}")
|
||||
@@ -581,10 +585,15 @@ def run_once(round_label=""):
|
||||
zone_desc = f"操作区间{lo}~{hi}"
|
||||
if "买入" in timing_signal or "加仓" in timing_signal or timing_signal in ("卖出","止盈"):
|
||||
rr = result.get("rr_ratio", 0)
|
||||
if _can_push(code, key):
|
||||
msg = f"🔔 {name}({code}) 价{price}→触发{zone_desc},已触发重评|RR={rr}"
|
||||
_push_action("操作信号", msg)
|
||||
# 分级(老爸规则:只有持仓风控动作才ACTION直推;买入/加仓机会进摘要)
|
||||
if timing_signal in ("卖出","止盈") and (d.get("shares") or 0) > 0:
|
||||
if _can_push(code, key):
|
||||
msg = f"🔔 {name}({code}) 价{price}→触发{zone_desc},已触发重评|RR={rr}"
|
||||
_push_action("操作信号", msg)
|
||||
outputs.append(f" 📨 区间触发重评→已推送Dad: {action}")
|
||||
else:
|
||||
_zone_entries.append(f"{name}({code}) {price}→{zone_desc}+重评{timing_signal}|RR={rr}")
|
||||
outputs.append(f" 📋 机会记入摘要: {timing_signal} RR={rr}")
|
||||
else:
|
||||
reason = f"重评结果:{timing_signal},不构成操作建议"
|
||||
outputs.append(f" 📋 本地日志(不推): {reason}")
|
||||
|
||||
Reference in New Issue
Block a user