#!/usr/bin/env python3 """promote_candidates.py — 自动提拔候选股入自选 从 candidates 表读未提拔的候选,评估后自动加入 holding_strategies。 """ import sys, json, sqlite3 from pathlib import Path from datetime import datetime DB_PATH = Path("/home/hmo/MoFin/data/mofin.db") def main(): conn = sqlite3.connect(str(DB_PATH)) conn.row_factory = sqlite3.Row # 读未提拔候选(按评分降序) rows = conn.execute(""" SELECT * FROM candidates WHERE (promoted IS NULL OR promoted = 0) AND (dropped IS NULL OR dropped = 0) AND score >= 6 ORDER BY score DESC """).fetchall() if not rows: print("[PROMOTE] 无待提拔候选") conn.close() return promoted = 0 for r in rows: code = str(r["code"]) name = r["name"] or code price = r["price"] or 0 el = r["entry_low"] or 0 eh = r["entry_high"] or 0 sl = r["stop_loss"] or 0 tp = r["take_profit"] or 0 score = r["score"] or 0 sector = r["sector"] or "" reason = r["reason"] or "" # 查是否已在 holding_strategies exists = conn.execute( "SELECT id FROM holding_strategies WHERE code=? AND status='active'", (code,) ).fetchone() if exists: # 标记已提拔但不重复加 conn.execute("UPDATE candidates SET promoted=1 WHERE code=?", (code,)) print(f" ⏭ {code} {name} 已在自选中,标记promoted") continue # 构建策略 now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") timing_signal = "买入" if score >= 7 else "关注" action = f"市场扫描发现({reason})" if reason else "市场扫描发现" conn.execute(""" INSERT INTO holding_strategies (code, name, price, entry_low, entry_high, stop_loss, take_profit, timing_signal, action, decision_type, strategy_type, status, rr_ratio, stock_category, created_at, updated_at, sector_context, quality_check) VALUES (?,?,?,?,?,?,?,?,?,'自选策略','scan', 'active',0,'关注',?,?,'', 'pending') """, (code, name, price, el, eh, sl, tp, timing_signal, action, now, now)) conn.execute("UPDATE candidates SET promoted=1 WHERE code=?", (code,)) promoted += 1 print(f" ✅ {code} {name} 评分{score} → 已加入自选({timing_signal})", flush=True) conn.commit() print(f"\n[PROMOTE] 本次提拔{promoted}只", flush=True) # 推XMPP if promoted > 0: try: import urllib.request msg = f"📈 自动提拔{promoted}只候选入自选" payload = json.dumps({"to": "hmo@yoin.fun", "body": msg, "type": "chat"}).encode() req = urllib.request.Request("http://127.0.0.1:5805/", data=payload, headers={"Content-Type": "application/json"}) urllib.request.urlopen(req, timeout=5) except Exception: pass conn.close() if __name__ == "__main__": main()