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:
+42
-2
@@ -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 '—'}")
|
||||
|
||||
Reference in New Issue
Block a user