7.5 KiB
7.5 KiB
In [ ]:
import sys
sys.path.insert(0, '..')
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from alpha.config import AlphaConfig
from alpha.factors import FactorAnalyzer
from alpha.strategy import Strategy, QuantileSignal, EqualWeightAllocator
from alpha.backtest import BacktestEngine
from alpha.evaluation import PerformanceEvaluator
from alpha.data_loader import DataLoader
%matplotlib inline
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
print('模块导入成功')In [ ]:
START_DATE = '2020-01-01'
END_DATE = '2024-12-31'
loader = DataLoader()
price_data = loader.load_prices(START_DATE, END_DATE)
print(f'价格数据: {price_data.shape}, 日期: {price_data.index[0]} ~ {price_data.index[-1]}')
price_data.head()In [ ]:
MA_WINDOW = 20
ma = price_data.rolling(MA_WINDOW).mean()
trend_factor = price_data / ma - 1 # 正偏离 = 上升趋势
# 未来 5 日收益率
fwd_5d = price_data.pct_change(5).shift(-5)
factor_stacked = trend_factor.stack()
fwd_stacked = fwd_5d.stack()
analyzer = FactorAnalyzer(factor_stacked, fwd_stacked)
ic = analyzer.compute_ic(method='rank')
print('趋势因子 IC 汇总:')
for k, v in analyzer.ic_summary().items():
print(f' {k}: {v:.4f}')
ic.plot(figsize=(12, 3), title='趋势因子 Rank IC 时间序列')
plt.axhline(y=0, color='r', linestyle='--')
plt.show()In [ ]:
quantile_ret = analyzer.quantile_returns(n_quantiles=5)
print('各分位组平均收益 (Q1=最强下跌趋势, Q5=最强上升趋势):')
print(quantile_ret)
quantile_ret['avg_return'].plot(kind='bar', figsize=(8, 4), color='steelblue')
plt.title('趋势因子分层收益 (未来5日)')
plt.ylabel('平均收益率')
plt.grid(True, alpha=0.3)
plt.show()In [ ]:
# 回测配置
config = AlphaConfig(
initial_cash=1_000_000,
commission_rate=0.0003,
slippage=0.001,
stamp_tax=0.001,
)
# 趋势策略:持有趋势最强(均线偏离最大)的 20% 股票
strategy = Strategy(
name='均线趋势策略-MA20',
factors=[],
signal_generator=QuantileSignal(
n_quantiles=5, long_quantile=5, short_quantile=0,
),
weight_allocator=EqualWeightAllocator(max_positions=10),
description='每月持有价格高于20日均线幅度最大的20%股票'
)
engine = BacktestEngine(config)
equity_curve = engine.run(
strategy=strategy,
price_data=price_data,
factor_data={'trend': trend_factor},
rebalance_freq='M',
)
print(f'回测完成, 共 {len(equity_curve)} 个交易日')
print(f'累计收益率: {(equity_curve["nav"].iloc[-1] - 1) * 100:.2f}%')In [ ]:
fig, axes = plt.subplots(2, 1, figsize=(14, 8))
# 净值曲线
axes[0].plot(equity_curve.index, equity_curve['nav'], label='策略净值', color='orange')
axes[0].axhline(y=1.0, color='gray', linestyle='--')
axes[0].set_title('均线趋势策略净值曲线')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# 回撤曲线
nav = equity_curve['nav']
running_max = nav.cummax()
drawdown = (nav - running_max) / running_max
axes[1].fill_between(equity_curve.index, 0, drawdown.values, color='red', alpha=0.3)
axes[1].set_title('回撤曲线')
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()In [ ]:
# 基准:股票池等权组合
bench_ret = price_data.pct_change().mean(axis=1)
evaluator = PerformanceEvaluator(equity_curve, benchmark_returns=bench_ret, risk_free_rate=0.03)
print(evaluator.summary())
report_df = evaluator.full_report()
pd.DataFrame(list(report_df.items()), columns=['指标', '数值']).set_index('指标')In [ ]:
# 不同均线周期对比
for win in [5, 10, 20, 60]:
ma_tmp = price_data.rolling(win).mean()
fac = price_data / ma_tmp - 1
a = FactorAnalyzer(fac.stack(), fwd_stacked)
summary = a.ic_summary()
print(f'MA{win}: IC均值={summary["IC_Mean"]:.4f}, ICIR={summary["IR"]:.4f}, '
f'IC>0占比={summary["IC>0_Ratio"]:.2%}')