diff --git a/scripts/price_monitor.py b/scripts/price_monitor.py index 9ced72e6..67d011b3 100644 --- a/scripts/price_monitor.py +++ b/scripts/price_monitor.py @@ -30,13 +30,32 @@ except ImportError: # 策略重评依赖(技术面驱动,非机械百分比) sys.path.insert(0, "/home/hmo/web-dashboard") try: - from strategy_lifecycle import reassess_strategy + from strategy_lifecycle import reassess_strategy, reassess_with_context HAS_REASSESS = True except ImportError: HAS_REASSESS = False UA = "Mozilla/5.0" +# ── XMPP推送 ────────────────────────────────────────────────────────── +XMPP_USER = "hmo@yoin.fun" +XMPP_BRIDGE = "http://127.0.0.1:5805/" + +def push_to_xmpp(text): + """通过知微 HTTP bridge 推送到Dad私信""" + if not text.strip(): + return + try: + payload = json.dumps({ + "to": XMPP_USER, + "body": text.strip(), + "type": "chat", + }).encode("utf-8") + req = urllib.request.Request(XMPP_BRIDGE, data=payload, headers={"Content-Type": "application/json"}) + urllib.request.urlopen(req, timeout=5) + except Exception as e: + print(f"[XMPP推送失败] {e}", file=sys.stderr) + # ── 批量拉取价格 ────────────────────────────────────────────────────────── def fetch_all_prices(codes): @@ -350,6 +369,24 @@ def run_once(round_label=""): if key == "stop_loss": outputs.append(f"⚠️ {name}({code}) {price} → 跌破止损{hi}!") record_event(code, name, "stop_loss", price, str(hi)) + # 止损触发 → 立即重评并推送给Dad + try: + cost = d.get("cost", 0) or 0 + shares = d.get("shares", 0) or 0 + current_action = d.get("action", "") + result = reassess_with_context(code, name, price, cost, shares, current_action) + if result: + timing_signal = result.get("timing_signal", "") + action = result.get("action", "") + if "买入" in timing_signal or "加仓" in timing_signal or "止损" in action: + buy_lo = d.get("entry_low", 0) + buy_hi = d.get("entry_high", 0) + rr = result.get("rr_ratio", 0) + msg = f"🛒 {name}({code}) 价{price} 买入区{buy_lo}~{buy_hi} RR={rr} 止损触发!" + push_to_xmpp(msg) + outputs.append(f" 📨 止损重评→已推送Dad: {action}") + except Exception as e: + outputs.append(f" ⚠️ 止损重评失败: {e}") else: extra = "" if "_price" in key: @@ -363,6 +400,22 @@ def run_once(round_label=""): extra = f"({act})" outputs.append(f"⚡ {name}({code}) {price} → 进入{label}{lo}~{hi}{extra}") record_event(code, name, "entry_zone", price, f"{lo}~{hi}", label) + # 进入区间 → 立即重评并推送给Dad + try: + cost = d.get("cost", 0) or 0 + shares = d.get("shares", 0) or 0 + current_action = d.get("action", "") + result = reassess_with_context(code, name, price, cost, shares, current_action) + if result: + timing_signal = result.get("timing_signal", "") + action = result.get("action", "") + if "买入" in timing_signal or "加仓" in timing_signal or "止损" in action: + rr = result.get("rr_ratio", 0) + msg = f"🛒 {name}({code}) 价{price} 买入区{lo}~{hi} RR={rr}" + push_to_xmpp(msg) + outputs.append(f" 📨 区间触发重评→已推送Dad: {action}") + except Exception as e: + outputs.append(f" ⚠️ 区间重评失败: {e}") state[code][key] = True state_updated = True diff --git a/scripts/stale_detector.py b/scripts/stale_detector.py index 391855f1..7c9baaf1 100644 --- a/scripts/stale_detector.py +++ b/scripts/stale_detector.py @@ -183,11 +183,9 @@ def main(): flags.append("[WL_IN]") if strategy_deficient: flags.append("[STRATEGY_STALE]") - prefix = "⚠️仓位挤占 " if position_pct > 80 else "" - issues.append(f"[STRATEGY_STALE] {prefix}价{price:.2f}在买入区{el}~{eh}但策略不完整({'RR='+f'{rr:.2f}<1.5' if rr_invalid else '无止盈位' if not tp else '非买入信号'}),买入区需重评") + issues.append(f"[STRATEGY_STALE] 价{price:.2f}在买入区{el}~{eh}但策略不完整({'RR='+f'{rr:.2f}<1.5' if rr_invalid else '无止盈位' if not tp else '非买入信号'}),买入区需重评") else: - prefix = "⚠️仓位挤占 " if position_pct > 80 else "" - issues.append(f"[PUSH] {prefix}价{price:.2f}入买入区{el}~{eh}") + issues.append(f"[PUSH] 价{price:.2f}入买入区{el}~{eh}") elif price > eh * 1.35: flags.append("[WL_HIGH]") issues.append(f"价{price:.2f}高出买入区+{((price/eh)-1)*100:.0f}%,买入区需重评") @@ -255,8 +253,11 @@ def main(): pass if issues: - print(f"{' '.join(flags)} {tag} {name}({code}) 价{price:.2f}{chg} | 买入{el}~{eh} | {'; '.join(issues)}") - found += 1 + # 仅输出有明确操作信号的行:[PUSH]=推荐买入, [STRATEGY_STALE]=需重评 + # 静默其他纯信息行(如仅"价XX高出/高于买入区"而无操作建议) + if any("[PUSH]" in i or "[STRATEGY_STALE]" in i for i in issues): + print(f"{' '.join(flags)} {tag} {name}({code}) 价{price:.2f}{chg} | 买入{el}~{eh} | {'; '.join(issues)}") + found += 1 if found == 0: print("[SILENT] 所有策略正常")