#!/usr/bin/env python3 # -*- coding: utf-8 -*- """strategy_router.py v5 — MoFin 策略动态路由(动态策略库,2026-08-13) 核心(老莫原则): - 策略全温区发信号(不留温区门控在策略内) - 策略-温区表现常态化记录(regime_perf.py / strategy_regime_perf),适用温区动态化 - 组合按当前温区自动激活/休眠策略:当前温区实测胜率高的策略优先 - 不漏历史策略(v_mr_sel trend_down 93%、v7.3 trend_up 94% 等被埋没的强者) 数据流: market_regime(三态) + regime_tracker(平滑K=5) → 当前温区 temp_band(rsi) → 温度/仓位乘数 regime_perf(实测) → 各策略温区表现 → strategy_weights.json(各策略权重/激活状态) """ import json import sys from pathlib import Path from datetime import datetime _SCRIPT_DIR = Path(__file__).resolve().parent sys.path.insert(0, str(_SCRIPT_DIR)) sys.path.insert(0, "/home/hmo/MoFin") OUT = Path("/home/hmo/MoFin/data/strategy_weights.json") DEFAULT_FAMILY = "mr" FAMILY_MAP = { "v_weak": "mr", "v_oversold": "mr", "v_mr": "mr", "v_mr2": "mr", "v_mr3": "mr", "v_mr4": "mr", "v_mr_sel": "mr", "v_lurk_v1": "mr", "v_lurk_v2": "mr", "v_lurk_v3": "mr", "s2_panic": "mr", "v_osc": "mr", "v_next": "trend", "v_next3": "trend", "v_next4": "trend", "v_next5": "trend", "v8.0": "trend", "v8.1": "trend", "v8.2": "trend", "v8.3": "trend", "v7.0": "trend", "v7.1": "trend", "v7.1b": "trend", "v7.2": "trend", "v7.3": "trend", "v6.0": "trend", "v6.1": "trend", "v6.2": "trend", "v9.0": "trend", "v9.1": "trend", "v9.2": "trend", "v_combo": "trend", "v1.0": "trend", "v2.0": "trend", "v3.0": "trend", "v4.0": "trend", "v4.0a": "trend", "v4.0b": "trend", "v4.0c": "trend", "v4.0d": "trend", "v4.0e": "trend", "v4.0f": "trend", "v4.0g": "trend", "v4.0h": "trend", "v4.1": "trend", "v5.0": "trend", "v11.0": "trend", "v11.1": "trend", } def load_regime(): try: p = Path("/home/hmo/MoFin/data/market_regime_smoothed.json") if p.exists(): d = json.loads(p.read_text(encoding="utf-8")) return {"regime": d.get("current_regime", "unknown"), "date": d.get("current_date", "")} except Exception: pass try: from market_regime import load_market_regime return load_market_regime() except Exception: return {"regime": "unknown"} def load_temp(): try: from temp_band import get_market_temp return get_market_temp() except Exception: return {"band": "unknown", "rsi": None} def load_regime_perf(): conn = None try: import sqlite3 conn = sqlite3.connect("/home/hmo/MoFin/data/mofin.db", timeout=30) conn.execute("PRAGMA busy_timeout=30000") rows = conn.execute( "SELECT strategy, regime, trades, win_rate, avg_pnl FROM strategy_regime_perf" ).fetchall() result = {} for strat, reg, n, wr, pnl in rows: result.setdefault(strat, {})[reg] = {"trades": n, "win_rate": wr, "avg_pnl": pnl} return result except Exception: return {} finally: if conn: conn.close() def route(regime, temp, perf): current_regime = regime.get("regime", "unknown") band = temp.get("band", "unknown") weights = {} for name, regs in perf.items(): if not regs: continue cur = regs.get(current_regime) best = max(regs.items(), key=lambda x: x[1].get("win_rate", 0)) best_wr = best[1].get("win_rate", 0) cur_wr = cur.get("win_rate") if cur else None matched = (best_wr >= 50) and (cur_wr is not None and cur_wr >= 50) family = FAMILY_MAP.get(name, DEFAULT_FAMILY) base = 1.0 if matched else 0.3 try: from temp_band import temp_multiplier mult = temp_multiplier(band, family) except Exception: mult = 0.8 weights[name] = { "weight": round(base * mult, 2), "regime": current_regime, "temp_band": band, "family": family, "matched": matched, "best_regime": best[0], "best_win_rate": best[1].get("win_rate", 0), "cur_win_rate": cur.get("win_rate") if cur else None, "cur_avg_pnl": cur.get("avg_pnl") if cur else None, "trades": cur.get("trades") if cur else 0, } return dict(sorted(weights.items(), key=lambda x: -x[1]["weight"])) def main(): regime = load_regime() temp = load_temp() perf = load_regime_perf() weights = route(regime, temp, perf) out = { "state": regime.get("regime", "unknown"), "state_date": regime.get("date", ""), "temp_band": temp.get("band", "unknown"), "temp_rsi": temp.get("rsi"), "weights": weights, "active": [k for k, v in weights.items() if v["matched"]], "updated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "note": "温区(平滑K=5)选策略类型 + 温度(rsi)乘数;策略全温区发信号,适用温区由实测动态决定", } OUT.write_text(json.dumps(out, ensure_ascii=False, indent=1), encoding="utf-8") print(f"strategy_weights.json: 状态={out['state']} 温度={out['temp_band']}(rsi={out['temp_rsi']})") print(f"激活策略: {out['active']}") print("权重排名(前15):") for name, w in list(weights.items())[:15]: mark = "✓" if w["matched"] else "观察" print(f" {name:<12} w={w['weight']:<5} {w['best_regime']:<11} 最佳{w['best_win_rate']:>3.0f}% {mark}") if __name__ == "__main__": main()