fix: MC年化硬编码^0.5虚高——改用实际区间年数(5年策略年化从21.8%修正到真实~8.9%)
This commit is contained in:
+24
-3
@@ -1123,10 +1123,18 @@ def portfolio_sim_full(trades, capital=1000000, runs=50):
|
||||
mean_ret = sum(rets) / len(rets)
|
||||
mean_dd = sum(dds) / len(dds)
|
||||
std = (sum((x - mean_ret) ** 2 for x in rets) / len(rets)) ** 0.5
|
||||
# 年化用实际区间年数(修复硬编码^0.5=2年的虚高问题)
|
||||
_dts = sorted({t['entry_date'] for t in trades if t.get('entry_date')})
|
||||
if _dts:
|
||||
from datetime import datetime as _dt2
|
||||
_span_days = (_dt2.strptime(_dts[-1], '%Y-%m-%d') - _dt2.strptime(_dts[0], '%Y-%m-%d')).days
|
||||
_years = max(_span_days / 365.0, 0.5)
|
||||
else:
|
||||
_years = 2.0
|
||||
return {
|
||||
'capital_final': round(sum(finals) / len(finals), 0),
|
||||
'total_return_pct': round(mean_ret, 1),
|
||||
'cagr_pct': round((((1 + mean_ret / 100) ** 0.5) - 1) * 100, 1),
|
||||
'cagr_pct': round((((1 + mean_ret / 100) ** (1 / _years)) - 1) * 100, 1),
|
||||
'portfolio_max_dd_pct': round(mean_dd, 1),
|
||||
'positions_taken': round(sum(taken) / len(taken)),
|
||||
'positions_skipped': len(trades) - round(sum(taken) / len(taken)),
|
||||
@@ -1154,9 +1162,22 @@ def portfolio_sim(trades, capital=1000000, max_positions=10, cost=True, random_s
|
||||
if not trades:
|
||||
return {}
|
||||
# 交易日历(用大盘指数日期)
|
||||
cal = sorted(_MKT_CTX.keys())
|
||||
if not cal:
|
||||
# 日历从 stock_daily 实际交易日生成(覆盖策略完整区间,不被全局_MKT_CTX的2年限制截断)
|
||||
_dates = sorted({t['entry_date'] for t in trades if t.get('entry_date')})
|
||||
if not _dates:
|
||||
return {}
|
||||
_min_d, _max_d = _dates[0], _dates[-1]
|
||||
# 日历缓存(避免每策略x50次MC重复扫stock_daily)
|
||||
global _CAL_CACHE
|
||||
if '_CAL_CACHE' not in globals() or _CAL_CACHE.get('range') != (_min_d, _max_d):
|
||||
_c = sqlite3.connect(DB_PATH)
|
||||
_CAL_CACHE = {'range': (_min_d, _max_d), 'cal': [r[0] for r in _c.execute(
|
||||
"SELECT DISTINCT date FROM stock_daily WHERE date>=? AND date<=? ORDER BY date",
|
||||
(_min_d, _max_d)).fetchall()]}
|
||||
_c.close()
|
||||
cal = _CAL_CACHE['cal']
|
||||
if not cal:
|
||||
cal = _dates
|
||||
cal_idx = {d: i for i, d in enumerate(cal)}
|
||||
def add_days(d, n):
|
||||
i = cal_idx.get(d)
|
||||
|
||||
Reference in New Issue
Block a user