Files
MoFin/scripts/clean_watchlist.py
T
知微 1abb6bb7fd 自选正反自动同步
clean_watchlist.py 双向:
  买入→持仓→移出自选  (已完成)
  清仓→自动加回自选  (新增)
每日09:05 cron自动执行
2026-06-28 00:18:11 +08:00

101 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""Remove held stocks from watchlist"""
import json, os
WL = "/home/hmo/web-dashboard/data/watchlist.json"
DEC = "/home/hmo/web-dashboard/data/decisions.json"
holding_codes = set()
pf = json.load(open("/home/hmo/web-dashboard/data/portfolio.json"))
for h in pf.get("holdings", []):
c = h.get("code", "")
if c:
holding_codes.add(c)
print(f"持仓 codes: {sorted(holding_codes)}")
# Load watchlist
wl = json.load(open(WL))
stocks = wl.get("stocks", [])
before = len(stocks)
# Remove held stocks
new_stocks = [s for s in stocks if s.get("code") not in holding_codes]
removed = [s for s in stocks if s.get("code") in holding_codes]
after = len(new_stocks)
wl["stocks"] = new_stocks
# Backup
os.rename(WL, WL + ".bak2")
json.dump(wl, open(WL, "w"), indent=2, ensure_ascii=False)
print(f"\n自选: {before}{after}")
print(f"移除 {len(removed)} 只:")
for r in removed:
print(f" {r['code']} {r.get('name','')}")
# Also update decisions.json - set them to "managed_by_holdings" or remove watchlist-only fields
dec = json.load(open(DEC))
dec_changed = 0
for d in dec.get("decisions", []):
code = d.get("code", "")
if code in [r["code"] for r in removed]:
# Remove watchlist-specific tags
if d.get("tag") == "watchlist":
d["tag"] = "managed_by_holdings"
dec_changed += 1
if dec_changed:
os.rename(DEC, DEC + ".bak3")
json.dump(dec, open(DEC, "w"), indent=2, ensure_ascii=False)
print(f"\ndecisions.json: {dec_changed} 只更新标签")
else:
print(f"\ndecisions.json: 无需更新")
# ── 反过程:清仓股自动加回自选 ──
# 找出曾持仓但现已不在 portfolio 的股票
prev_held = {} # code → last_execution info
for d in dec.get("decisions", []):
code = d.get("code", "")
exec_info = d.get("execution", {})
if exec_info and exec_info.get("status") in ("executing", "partial_exit"):
# 当前仍持仓但不在 portfolio?说明 portfolio 数据落后,跳过
pass
elif exec_info and exec_info.get("status") in ("sold", "closed") and code not in holding_codes:
prev_held[code] = {
"name": d.get("name", code),
"entry_low": d.get("entry_low", 0),
"entry_high": d.get("entry_high", 0),
}
if prev_held:
wl_stock_codes = set(s.get("code", "") for s in new_stocks)
added = 0
for code, info in sorted(prev_held.items()):
if code not in wl_stock_codes and code not in holding_codes:
# 确保买入区有值
entry_low = info.get("entry_low", 0) or 0
entry_high = info.get("entry_high", 0) or 0
new_stocks.append({
"code": code,
"name": info["name"],
"entry_low": entry_low,
"entry_high": entry_high,
"stop_loss": 0,
"tag": "recovered_from_sold",
})
added += 1
print(f" ← 已清仓→加回自选: {code} {info['name']}")
if added:
wl["stocks"] = new_stocks
json.dump(wl, open(WL, "w"), indent=2, ensure_ascii=False)
print(f"\n反过程: {added} 只清仓股已加回自选")
else:
print("\n反过程: 无清仓股需加回")
else:
print("\n反过程: 无已清仓记录")
print("\nDONE")