""" evolution/auto_iterator.py — 策略自动迭代 健康度低时生成参数变体,跑回测,记录结果 """ import sys, os, json, sqlite3, copy from datetime import datetime sys.path.insert(0, '/home/hmo/MoFin') import strategy_lab as lab DB = '/home/hmo/MoFin/data/mofin.db' # 可迭代的参数空间 PARAM_SPACE = { 'max_hold_days': [40, 60, 80, 100, 120], 'reentry_days': [5, 10, 15, 20], 'sl_atr': [1.0, 1.5, 2.0, 2.5], } def get_current_health(version='v_next4', days=7): """获取当前策略健康度""" conn = sqlite3.connect(DB) conn.row_factory = sqlite3.Row rows = conn.execute(""" SELECT health_score, date FROM strategy_health WHERE strategy_version=? ORDER BY date DESC LIMIT ? """, (version, days)).fetchall() conn.close() if not rows: return 50 # 无数据,中性 return round(sum(r['health_score'] for r in rows) / len(rows), 1) def propose_variants(parent_version, health): """根据健康度生成变体参数建议""" if health >= 70: print(f"健康度{health}≥70,无需迭代", flush=True) return [] variants = [] severity = 'minor' if health >= 50 else 'major' if severity == 'minor': # 小幅调参 variants.append({ 'parent': parent_version, 'params': {'max_hold_days': 80, 'reentry_days': 15, 'sl_atr': 1.5}, 'description': '微调:确保当前最优参数', }) else: # 大幅调参(扫参数网格) base_hold = 60 base_reentry = 10 for hold in PARAM_SPACE['max_hold_days']: for reentry in PARAM_SPACE['reentry_days']: variants.append({ 'parent': parent_version, 'params': {'max_hold_days': hold, 'reentry_days': reentry, 'sl_atr': 1.5}, 'description': f'网格扫描: h{hold}/r{reentry}', }) return variants def test_variant(variant): """测试单个变体""" name = f"auto_h{variant['params']['max_hold_days']}_r{variant['params']['reentry_days']}" # 克隆基座配置 base = lab.STRATEGIES.get(variant['parent']) if not base: return None cfg = copy.deepcopy(base) cfg['version'] = name cfg['name'] = f"自进化-{variant['description']}" for k, v in variant['params'].items(): cfg['config']['exit'][k] = v lab.STRATEGIES[name] = cfg results = {} for tag, start, end in [('5y', '2021-07-01', '2026-07-24')]: r = lab.run_backtest(name, start, end, 913000, save=False, universe='a', period_tag=tag) pf = r['summary'].get('portfolio_full', {}) results[tag] = { 'full': pf.get('total_return_pct'), 'cagr': pf.get('cagr_pct'), 'dd': pf.get('portfolio_max_dd_pct'), } return {'name': name, 'description': variant['description'], 'results': results} def run_iteration(version='v_next4'): """执行一次迭代检查""" health = get_current_health(version) print(f"{version} 健康度: {health}", flush=True) variants = propose_variants(version, health) if not variants: return [] conn = sqlite3.connect(DB) results = [] for v in variants[:3]: # 最多测3个 print(f"测试: {v['description']}", flush=True) r = test_variant(v) if r: results.append(r) # 记录到 evolution 表 conn.execute(""" INSERT INTO strategy_evolution (parent_version, child_version, change_description, backtest_result, promoted) VALUES (?, ?, ?, ?, 0) """, (version, r['name'], r['description'], json.dumps(r['results'], ensure_ascii=False))) conn.commit() # 打印对比 for r in results: rs = r['results'].get('5y', {}) print(f" {r['name']}: full={rs.get('full')}% cagr={rs.get('cagr')}% dd={rs.get('dd')}%", flush=True) conn.close() return results if __name__ == '__main__': run_iteration()