Files
MoFin/scripts/branch_scanner.py
T

69 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""每30分钟扫描所有持仓的分支状态,发现可操作的分支就推"""
import sys, json, os
sys.path.insert(0, '/home/hmo/MoFin')
sys.path.insert(0, '/home/hmo/web-dashboard')
from strategy_tree import detect_scenario
DEC_PATH = '/home/hmo/web-dashboard/data/decisions.json'
PF_PATH = '/home/hmo/web-dashboard/data/portfolio.json'
XMPP_BRIDGE = "http://127.0.0.1:5805/"
XMPP_USER = "hmo@yoin.fun"
def push(msg):
try:
from urllib.request import Request, urlopen
payload = json.dumps({"to": XMPP_USER, "body": msg, "type": "chat"}).encode()
req = Request(XMPP_BRIDGE, data=payload, headers={"Content-Type": "application/json"})
urlopen(req, timeout=5)
except Exception:
pass
def main():
scenario = detect_scenario()
if not scenario.get('id'):
return 0 # SILENT
alives = []
dec = json.load(open(DEC_PATH))
pf = json.load(open(PF_PATH))
pf_codes = {h['code'] for h in pf.get('holdings', [])}
for e in dec.get('decisions', []):
code = e.get('code', '')
tree = e.get('strategy_tree', {})
if not tree or not tree.get('branches'):
continue
branches = tree['branches']
price = e.get('price', 0)
shares = e.get('shares', 0)
cost = e.get('cost', 0)
if price <= 0:
continue
# 用 strategy_tree 评估
try:
from strategy_tree import evaluate_branches
results = evaluate_branches(code, scenario['id'], price, shares, cost)
for r in results:
if r.get('applicable') and r.get('action_type') != 'hold':
is_held = code in pf_codes
label = '持仓' if is_held else '自选'
alives.append(f" {label} {r.get('action_type','?')} {code}@{price} | 情景{scenario.get('label','')}{r.get('branch_id','').split('_')[-1]}| {r.get('rationale','')[:30]}")
break
except Exception:
pass
if not alives:
return 0 # SILENT
# 只推单一情景行 + 操作列表
out_lines = [f"【知微】分支扫描 | {scenario.get('label','')}({scenario.get('id','')})"]
out_lines.extend(alives)
msg = '\n'.join(out_lines)
print(msg)
push(msg)
return 1
if __name__ == '__main__':
sys.exit(main())