feat(推荐): 换仓策略——现金不足时自动给出减弱势持仓换入排队推荐的方案

This commit is contained in:
hmo
2026-07-22 11:01:02 +08:00
parent f35144f3f1
commit 294133d605
+39 -6
View File
@@ -1237,29 +1237,60 @@ def flush_rec_digest(max_items=5):
items.sort(key=lambda x: x.get('rr') or 0, reverse=True)
top = items[:max_items]
# ── 现金预算(决定操盘建议)──
# ── 现金预算(决定操盘建议 + 换仓策略)──
cash_note = ""
rotation_note = ""
try:
conn = _sq.connect("/home/hmo/MoFin/data/mofin.db")
conn.row_factory = _sq.Row
r = conn.execute("SELECT cash, total_assets FROM portfolio_summary WHERE id=1").fetchone()
conn.close()
if r and r[1]:
cash, total = r[0] or 0, r[1]
budget_pct = cash / total * 100
cum = 0.0
buys = []
queued = []
for it in top:
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 cum + pct <= budget_pct + 1e-9:
buys.append(f"{it.get('name') or it['code']}{pct:.0f}%")
buys.append((it, pct))
cum += pct
else:
queued.append((it, pct))
cash_note = (f"现金{cash/10000:.1f}万({budget_pct:.1f}%)|按预算本次可执行: "
+ ("".join(buys) if buys else "(预算不足,先排队观察)")
+ ("".join(f"{b[0].get('name') or b[0]['code']}{b[1]:.0f}%" for b in buys) if buys else "")
+ (f"(合计≈{cum:.0f}%" if buys else ""))
except Exception:
pass
# ── 换仓策略:有排队推荐时,找可减的弱持仓来腾挪 ──
if queued:
weak = conn.execute("""
SELECT hs.code, hs.name, hs.timing_signal, h.position_pct, h.cost, lp.price, lp.change_pct
FROM holding_strategies hs
JOIN holdings h ON hs.code = h.code AND h.is_active = 1
LEFT JOIN live_prices lp ON hs.code = lp.code
WHERE hs.status='active' AND h.shares > 0
AND hs.timing_signal IN ('弱势持有','观望','持有')
ORDER BY CASE hs.timing_signal WHEN '弱势持有' THEN 0 WHEN '观望' THEN 1 ELSE 2 END,
h.position_pct DESC
""").fetchall()
if weak:
need_pct = queued[0][1]
plan = []
freed = 0.0
for w in weak:
if freed >= need_pct:
break
plan.append(w)
freed += w["position_pct"] or 0
q0 = queued[0][0]
rotation_note = (f"🔄 换仓建议:现金不足买 {q0.get('name') or q0['code']}RR={q0.get('rr') or 0})→ "
f"可减 {'+'.join(f\"{w['name']}\" for w in plan)}"
f"{','.join(sorted({w['timing_signal'] for w in plan}))}"
f"腾出≈{freed:.0f}%仓位)换入")
conn.close()
except Exception as _re:
print(f" [REC] 换仓计算异常: {_re}", flush=True)
lines = [f"📈 新增推荐 {len(items)} 只(按RR排序):"]
for i, it in enumerate(top):
@@ -1277,6 +1308,8 @@ def flush_rec_digest(max_items=5):
lines.append(f"…另有 {len(items) - max_items} 只详见盯盘推荐操作区")
if cash_note:
lines.append("💰 " + cash_note)
if rotation_note:
lines.append(rotation_note)
try:
import sys as _s, os as _o2
_s.path.insert(0, '/home/hmo/MoFin/deploy/profile-scripts')