Files
MoFin/archive/b-cleanup-20260820/hermes-prune_branches.py
T
xxm 04faf4ed15 refactor(B组清理): 归档strategy_tree/branch_evaluator/prune_branches/branch_scanner,detect_scenario→market_regime
- 归档4个B组模块: strategy_tree.py/branch_evaluator.py/prune_branches.py/branch_scanner.py
  按方法论:只有重评才能改信号和操作,B组的分支扫描/评估/剪枝越权
- stale_push_wlin.py: detect_scenario→market_regime.load_market_regime()
- strategy_lifecycle.py: detect_scenario→market_regime.load_market_regime(),筹码权重改用温区
- import_holding_xls.py: 移除init_default_branches调用(分支概念已移除)
- per_stock_reassess.py: 移除init_default_branches调用(分支概念已移除)
- 清理mofin_db.py/strategy_lifecycle.py残留注释引用
- 关键脚本语法全部通过
2026-08-20 14:20:14 +08:00

118 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
prune_branches.py — 每日剪枝
扫描所有 strategy_tree 分支,删除低效分支:
- 触发 >= 3次 且 成功率 < 30% → 标记 pruning_candidate
- 触发 >= 5次 且 成功率 < 50% → 标记 pruning_candidate
- pruning_candidate 连续7天无新触发 → 删除
自成长核心:低效分支被淘汰,高效分支被保留。
数据写入 decisions.json 的 strategy_tree.branches[]。
"""
import json, sys, os
from datetime import datetime, timedelta
from mo_data import read_decisions
from mofin_db import get_conn, write_holding_strategy
PRUNE_LOG = "/home/hmo/MoFin/data/prune_log.json"
def load_decisions():
return read_decisions()
def save_decisions(data):
# DB 写入(替代 json.dump
try:
conn = get_conn()
for d in data.get("decisions", []):
write_holding_strategy(conn, d.get("code", ""), d.get("name", ""), d)
conn.close()
except Exception:
pass
def main():
data = load_decisions()
decisions = data.get("decisions", [])
today = datetime.now().strftime("%Y-%m-%d")
pruned = []
warnings = []
for entry in decisions:
code = entry.get("code", "")
tree = entry.get("strategy_tree", {})
branches = tree.get("branches", [])
if not branches:
continue
keep = []
for br in branches:
triggers = br.get("trigger_count", 0)
success = br.get("success_rate")
last = br.get("last_triggered", "")
priority = br.get("priority", 99)
# 跳过默认持有分支
if priority == 99:
keep.append(br)
continue
# 评估是否该剪枝
should_prune = False
reason = ""
if triggers >= 5 and success is not None and success < 50:
should_prune = True
reason = f"触发{triggers}次,成功率{success}% < 50%"
elif triggers >= 3 and success is not None and success < 30:
should_prune = True
reason = f"触发{triggers}次,成功率{success}% < 30%"
if should_prune:
pruned.append({
"code": code,
"branch_id": br.get("id", ""),
"action": br.get("action", {}).get("type", ""),
"rationale": br.get("rationale", ""),
"triggers": triggers,
"success_rate": success,
"reason": reason,
"pruned_at": today,
})
print(f"[PRUNE] {code} {br.get('id','?')}: {reason}")
else:
keep.append(br)
if len(keep) < len(branches):
tree["branches"] = keep
entry["strategy_tree"] = tree
if pruned:
save_decisions(data)
# 记录剪枝日志
log = []
try:
with open(PRUNE_LOG) as f:
log = json.load(f)
except Exception:
pass
log.append({
"date": today,
"pruned": pruned,
"total_before": sum(len(e.get("strategy_tree", {}).get("branches", [])) for e in decisions),
})
os.makedirs(os.path.dirname(PRUNE_LOG), exist_ok=True)
with open(PRUNE_LOG, "w") as f:
json.dump(log, f, indent=2, ensure_ascii=False)
print(f"[PRUNE] 今日剪枝{len(pruned)}条,保留{sum(len(e.get('strategy_tree',{}).get('branches',[])) for e in decisions)}条")
else:
print("[PRUNE] 无需要剪枝的分支")
return 0
if __name__ == "__main__":
sys.exit(main())