fix: digest与盯盘推荐区同步(老爸:推荐和XMPP同步)

- flush_rec_digest先回库校验快照: tag撤销/信号降级为弱信号/RR<2.0的条目丢弃
  (队列是打标瞬间快照,之后状态变化不再误推)
- digest预算门槛1.5→2.0(与盯盘exec一致)
- digest每条加💰可执行/排队徽章(与盯盘术语一致)
- buys/queued初始化防NameError
This commit is contained in:
hmo
2026-07-24 12:37:52 +08:00
parent 5667c89943
commit ed842bc85d
+42 -2
View File
@@ -1309,6 +1309,41 @@ def flush_rec_digest(max_items=5):
if not items:
return 0
_os.remove(qf)
# ── 快照回库校验(2026-07-24 老爸:推荐和XMPP同步)──
# 队列是打标瞬间的快照;flush 前回库读实时 信号/RR/tag
# 信号降级为弱信号或RR跌破2.0的条目直接丢弃——XMPP说的必须和盯盘一致。
import sqlite3 as _sq0
_vconn = _sq0.connect("/home/hmo/MoFin/data/mofin.db")
_WEAK = ("信号不充分", "关注", "弱势持有", "观望", "持有", "")
_live = []
for it in items:
r = _vconn.execute(
"SELECT timing_signal, rr_ratio, tag FROM holding_strategies WHERE code=? AND status='active'",
(it['code'],)).fetchone()
if not r:
print(f" [REC] {it['code']} 已不在库,丢弃", flush=True)
continue
cur_sig, cur_rr, cur_tag = r[0] or "", r[1] or 0, r[2] or ""
if cur_tag != 'current_recommend':
print(f" [REC] {it['code']} tag已撤销({cur_tag}),丢弃", flush=True)
continue
if it.get('signal') in ("买入", "可买入", "可加仓"):
if cur_sig in _WEAK:
print(f" [REC] {it['code']} 信号降级为'{cur_sig}',丢弃", flush=True)
continue
if cur_rr < 2.0:
print(f" [REC] {it['code']} 实时RR={cur_rr}<2.0,丢弃", flush=True)
continue
it['signal'] = cur_sig # 用实时信号发
it['rr'] = cur_rr
_live.append(it)
_vconn.close()
items = _live
if not items:
print(" [REC] 快照校验后无有效推荐,不发digest", flush=True)
return 0
_SELL_SIGS = ("卖出", "止盈")
# 卖出/止盈是释放现金的操作,不占买入预算,单独一组排最前
sells = [x for x in items if x.get('signal') in _SELL_SIGS]
@@ -1320,6 +1355,8 @@ def flush_rec_digest(max_items=5):
# ── 现金预算(决定操盘建议 + 换仓策略):只对买入项计算,卖出不占预算 ──
cash_note = ""
rotation_note = ""
buys = []
queued = []
try:
conn = _sq.connect("/home/hmo/MoFin/data/mofin.db")
conn.row_factory = _sq.Row
@@ -1334,7 +1371,7 @@ def flush_rec_digest(max_items=5):
import re as _re
m = _re.search(r'(\d+(?:\.\d+)?)\s*%', it.get('position') or '')
pct = float(m.group(1)) if m else 8.0
if (it.get('rr') or 0) >= 1.5 and cum + pct <= budget_pct + 1e-9:
if (it.get('rr') or 0) >= 2.0 and cum + pct <= budget_pct + 1e-9:
buys.append((it, pct))
cum += pct
else:
@@ -1374,12 +1411,15 @@ def flush_rec_digest(max_items=5):
print(f" [REC] 换仓计算异常: {_re}", flush=True)
lines = [f"📈 新增推荐 {len(items)} 只(按RR排序):"]
# 与盯盘推荐区一致的 可执行/排队 徽章(2026-07-24 老爸:推荐和XMPP同步)
_exec_codes = {b[0]['code'] for b in buys} | {s['code'] for s in sells}
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}")
lines.append(f"{it.get('name') or it['code']}({it['code']}) {it['signal']}"
_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"{it.get('stop_loss') or ''}{it.get('take_profit') or ''}"
f" {_rr_txt} 仓位{it.get('position') or ''}")