diff --git a/server.py b/server.py index ea095f8f..3dcea7b9 100644 --- a/server.py +++ b/server.py @@ -536,6 +536,24 @@ def get_tracking(): @app.route("/api/research/strategies") def api_research_strategies(): """策略版本列表(含回测结果摘要,支持 period_tag 区间过滤)""" + def _approx_regime_universality(strategy, regime, trades): + """温区级普适近似:温区内信号月份≈trades/温区月均笔数,温区总月份占比(避免逐笔遍历性能问题)""" + try: + import sqlite3 as _sq6 + _c6 = _sq6.connect(str(DATA_DIR / "mofin.db"), timeout=10) + # 温区总月份 + _rm = {r[0]: r[1] for r in _c6.execute( + "SELECT regime, COUNT(DISTINCT substr(date,1,7)) FROM market_regime WHERE market='a' GROUP BY regime").fetchall()} + _c6.close() + regime_total = _rm.get(regime, 0) + if not trades or regime_total == 0: + return {"months": 0, "score": 0, "regime_total_months": regime_total} + # 近似:温区内信号月份 ≈ trades / (温区月均笔数≈3),月份占比 = 信号月份/温区总月份 + est_months = max(1, min(trades // 3, regime_total)) + score = round(min(est_months / regime_total * 100, 100)) + return {"months": est_months, "score": score, "regime_total_months": regime_total} + except Exception: + return {"months": 0, "score": 0, "regime_total_months": 0} try: from strategy_lab import list_strategies, STRATEGY_DESCRIPTIONS pt = request.args.get('period_tag') @@ -563,13 +581,13 @@ def api_research_strategies(): "cagr_pct": _r[7], "max_dd_pct": _r[8], "capital_final": _r[9], "positions_taken": _r[10], "sharpe_ratio": _r[11], "profit_factor": _r[12], - # 2026-08-15 温区级组合级指标(温区行也要显示组合级列) + # 温区级组合级指标(温区行也要显示组合级列) "portfolio": {"cagr_pct": _r[7], "total_return_pct": _r[6], "portfolio_max_dd_pct": _r[8], "capital_final": _r[9], "positions_taken": _r[10], "sharpe_ratio": _r[11], "profit_factor": _r[12]}, - # 温区级 universality(该温区 trades 的月份分散度,对齐整体行普适) - "universality": {"months": _r[2] and min(_r[2] // 4, 12) or 0}, + # 温区级 universality(近似:温区内信号月份≈trades/温区月均,温区总月份;避免逐笔遍历性能问题) + "universality": _approx_regime_universality(_r[0], _r[1], _r[2]), } _c.close() except Exception: @@ -584,7 +602,7 @@ def api_research_strategies(): _c5.close() except Exception: pass - # 2026-08-15 温区级普适:策略在适应温区内发出信号的月份分散度 + 温区总月份占比 + # 温区级普适(近似):温区内信号月份 ≈ trades/温区月均笔数×温区总月份,避免逐笔遍历(性能) # 温区总月份数(A股: choppy35.4%/trend_down30.3%/trend_up34.3%;按市场 regime 时长统计) try: import sqlite3 as _sq3 @@ -597,42 +615,7 @@ def api_research_strategies(): except Exception: _total_months = 0 _regime_months = {} - _regime_universality = {} # (version, regime) -> {'months': N, 'score': 分散度} - try: - import sqlite3 as _sq4, json as _json4, collections as _coll - _c4 = _sq4.connect(str(DATA_DIR / "mofin.db"), timeout=10) - for _r in _c4.execute( - "SELECT version, results_json FROM strategy_research WHERE results_json IS NOT NULL"): - try: - _res = _json4.loads(_r[1]) - _trades = _res.get("trades", []) - if not _trades: - continue - # 按温区过滤该策略 trades(regime_winrates 已有温区归类) - for _rg in ("trend_up", "choppy", "trend_down"): - _rg_months = _coll.Counter() - for _t in _trades: - _ed = _t.get("entry_date", "") - if _ed and _regime_map.get(_ed) == _rg: - _rg_months[_ed[:7]] += 1 - if _rg_months: - _n = len(_rg_months) - _tot = sum(_rg_months.values()) - _score = 0.0 - if _n > 1: - for _c in _rg_months.values(): - _p = _c / _tot - _score -= _p * (0.0 if _p == 0 else __import__('math').log(_p)) - _score = _score / __import__('math').log(_n) * 100 - _regime_universality.setdefault(_r[0], {})[_rg] = { - "months": _n, "score": round(_score, 0), - "regime_total_months": _regime_months.get(_rg, 0), - } - except Exception: - continue - _c4.close() - except Exception: - _regime_universality = {} + # 温区级普适已用近似计算(_approx_regime_universality),不逐笔遍历(性能) _deprecated = {} try: import sqlite3 as _sq2