feat:添加了基本策略。
This commit is contained in:
@@ -0,0 +1,320 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 多因子选股策略 — 构建与回测\n",
|
||||
"\n",
|
||||
"## 策略思路\n",
|
||||
"多因子模型(Multi-Factor Model)综合多个维度的因子,分散单一因子的风险,提升选股稳健性。\n",
|
||||
"本策略合成 **四大类因子**:\n",
|
||||
"\n",
|
||||
"| 因子类别 | 具体因子 | 代表逻辑 |\n",
|
||||
"|---------|---------|---------|\n",
|
||||
"| 动量 | 20日收益率 | 强者恒强 |\n",
|
||||
"| 低波 | 20日波动率倒数 | 低波动溢价 |\n",
|
||||
"| 价值 | EP (PE倒数) | 低估值 |\n",
|
||||
"| 质量 | ROE | 高盈利能力 |\n",
|
||||
"\n",
|
||||
"每月调仓,综合得分最高的股票入选。\n",
|
||||
"\n",
|
||||
"## 研究流程\n",
|
||||
"1. 加载数据\n",
|
||||
"2. 各因子计算与 IC 分析\n",
|
||||
"3. 等权合成多因子 + 分层回测\n",
|
||||
"4. 构建策略并回测\n",
|
||||
"5. 绩效评估"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"sys.path.insert(0, '..')\n",
|
||||
"\n",
|
||||
"import numpy as np\n",
|
||||
"import pandas as pd\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"from alpha.config import AlphaConfig\n",
|
||||
"from alpha.factors import FactorAnalyzer\n",
|
||||
"from alpha.strategy import Strategy, QuantileSignal, EqualWeightAllocator\n",
|
||||
"from alpha.backtest import BacktestEngine\n",
|
||||
"from alpha.evaluation import PerformanceEvaluator\n",
|
||||
"from alpha.data_loader import DataLoader\n",
|
||||
"\n",
|
||||
"%matplotlib inline\n",
|
||||
"plt.rcParams['font.sans-serif'] = ['SimHei']\n",
|
||||
"plt.rcParams['axes.unicode_minus'] = False\n",
|
||||
"\n",
|
||||
"print('模块导入成功')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 1. 加载数据"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"START_DATE = '2020-01-01'\n",
|
||||
"END_DATE = '2024-12-31'\n",
|
||||
"\n",
|
||||
"loader = DataLoader()\n",
|
||||
"\n",
|
||||
"# 价格 + 估值 + 财务\n",
|
||||
"price_data = loader.load_prices(START_DATE, END_DATE)\n",
|
||||
"pe_data = loader.load_factor('pe_ttm', START_DATE, END_DATE)\n",
|
||||
"roe_data = loader.load_factor('roe', START_DATE, END_DATE)\n",
|
||||
"\n",
|
||||
"print(f'价格数据: {price_data.shape}')\n",
|
||||
"print(f'PE(TTM)数据: {pe_data.shape}')\n",
|
||||
"print(f'ROE数据: {roe_data.shape}')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 2. 各因子计算与 IC 分析"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ---- 截面标准化函数 ----\n",
|
||||
"def zscore_cross_section(df):\n",
|
||||
" return (df - df.mean(axis=1)) / (df.std(axis=1) + 1e-12)\n",
|
||||
"\n",
|
||||
"# ---- 1. 动量因子 (20日收益率) ----\n",
|
||||
"momentum = price_data.pct_change(20)\n",
|
||||
"z_mom = zscore_cross_section(momentum)\n",
|
||||
"\n",
|
||||
"# ---- 2. 低波因子 (20日波动率倒数) ----\n",
|
||||
"daily_ret = price_data.pct_change()\n",
|
||||
"volatility = daily_ret.rolling(20).std()\n",
|
||||
"z_lowvol = -zscore_cross_section(volatility) # 波动越小越好\n",
|
||||
"\n",
|
||||
"# ---- 3. 价值因子 (EP = 1/PE) ----\n",
|
||||
"ep = 1.0 / pe_data.where(pe_data > 0)\n",
|
||||
"z_value = zscore_cross_section(ep)\n",
|
||||
"\n",
|
||||
"# ---- 4. 质量因子 (ROE) ----\n",
|
||||
"z_quality = zscore_cross_section(roe_data)\n",
|
||||
"\n",
|
||||
"# ---- 汇总各因子 ----\n",
|
||||
"factors = {\n",
|
||||
" '动量': momentum,\n",
|
||||
" '低波': -volatility,\n",
|
||||
" '价值': ep,\n",
|
||||
" '质量': roe_data,\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"# 未来 10 日收益率\n",
|
||||
"fwd_10d = price_data.pct_change(10).shift(-10)\n",
|
||||
"\n",
|
||||
"# 各因子 IC 对比\n",
|
||||
"print('各因子 IC 汇总 (未来10日):')\n",
|
||||
"ic_results = {}\n",
|
||||
"for name, fac in factors.items():\n",
|
||||
" a = FactorAnalyzer(fac.stack(), fwd_10d.stack())\n",
|
||||
" s = a.ic_summary()\n",
|
||||
" ic_results[name] = s\n",
|
||||
" print(f' {name}: IC均值={s[\"IC_Mean\"]:.4f}, ICIR={s[\"IR\"]:.4f}, '\n",
|
||||
" f'IC>0占比={s[\"IC>0_Ratio\"]:.2%}')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 3. 合成多因子与分层回测\n",
|
||||
"\n",
|
||||
"等权合成综合得分:\n",
|
||||
"$$Score = \\frac{1}{4}(Z_{Momentum} + Z_{LowVol} + Z_{Value} + Z_{Quality})$$"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 等权合成综合得分\n",
|
||||
"multi_factor = (z_mom + z_lowvol + z_value + z_quality) / 4\n",
|
||||
"\n",
|
||||
"# 分层回测\n",
|
||||
"analyzer = FactorAnalyzer(multi_factor.stack(), fwd_10d.stack())\n",
|
||||
"quantile_ret = analyzer.quantile_returns(n_quantiles=5)\n",
|
||||
"print('多因子分层收益 (Q1=综合得分最低, Q5=最高):')\n",
|
||||
"print(quantile_ret)\n",
|
||||
"\n",
|
||||
"quantile_ret['avg_return'].plot(kind='bar', figsize=(8, 4), color='steelblue')\n",
|
||||
"plt.title('多因子合成分层收益 (未来10日)')\n",
|
||||
"plt.ylabel('平均收益率')\n",
|
||||
"plt.grid(True, alpha=0.3)\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 4. 构建策略并回测"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 回测配置\n",
|
||||
"config = AlphaConfig(\n",
|
||||
" initial_cash=1_000_000,\n",
|
||||
" commission_rate=0.0003,\n",
|
||||
" slippage=0.001,\n",
|
||||
" stamp_tax=0.001,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# 多因子策略:持有综合得分最高的 20% 股票\n",
|
||||
"strategy = Strategy(\n",
|
||||
" name='多因子选股策略-动量+低波+价值+质量',\n",
|
||||
" factors=[],\n",
|
||||
" signal_generator=QuantileSignal(\n",
|
||||
" n_quantiles=5, long_quantile=5, short_quantile=0,\n",
|
||||
" ),\n",
|
||||
" weight_allocator=EqualWeightAllocator(max_positions=10),\n",
|
||||
" description='每月持有动量/低波/价值/质量四因子综合得分最高的20%股票'\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"engine = BacktestEngine(config)\n",
|
||||
"equity_curve = engine.run(\n",
|
||||
" strategy=strategy,\n",
|
||||
" price_data=price_data,\n",
|
||||
" factor_data={'multi': multi_factor},\n",
|
||||
" rebalance_freq='M',\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(f'回测完成, 共 {len(equity_curve)} 个交易日')\n",
|
||||
"print(f'累计收益率: {(equity_curve[\"nav\"].iloc[-1] - 1) * 100:.2f}%')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 5. 净值曲线与回撤"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig, axes = plt.subplots(2, 1, figsize=(14, 8))\n",
|
||||
"\n",
|
||||
"# 净值曲线\n",
|
||||
"axes[0].plot(equity_curve.index, equity_curve['nav'], label='策略净值', color='darkred')\n",
|
||||
"axes[0].axhline(y=1.0, color='gray', linestyle='--')\n",
|
||||
"axes[0].set_title('多因子选股策略净值曲线')\n",
|
||||
"axes[0].legend()\n",
|
||||
"axes[0].grid(True, alpha=0.3)\n",
|
||||
"\n",
|
||||
"# 回撤曲线\n",
|
||||
"nav = equity_curve['nav']\n",
|
||||
"running_max = nav.cummax()\n",
|
||||
"drawdown = (nav - running_max) / running_max\n",
|
||||
"axes[1].fill_between(equity_curve.index, 0, drawdown.values, color='red', alpha=0.3)\n",
|
||||
"axes[1].set_title('回撤曲线')\n",
|
||||
"axes[1].grid(True, alpha=0.3)\n",
|
||||
"\n",
|
||||
"plt.tight_layout()\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 6. 绩效评估"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 基准:股票池等权组合\n",
|
||||
"bench_ret = price_data.pct_change().mean(axis=1)\n",
|
||||
"\n",
|
||||
"evaluator = PerformanceEvaluator(equity_curve, benchmark_returns=bench_ret, risk_free_rate=0.03)\n",
|
||||
"print(evaluator.summary())\n",
|
||||
"\n",
|
||||
"report_df = evaluator.full_report()\n",
|
||||
"pd.DataFrame(list(report_df.items()), columns=['指标', '数值']).set_index('指标')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"## 因子权重敏感性分析\n",
|
||||
"\n",
|
||||
"对比等权合成与单因子策略的 IC 表现:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 单因子 vs 多因子 IC 对比\n",
|
||||
"all_factors = {\n",
|
||||
" '动量': z_mom,\n",
|
||||
" '低波': z_lowvol,\n",
|
||||
" '价值': z_value,\n",
|
||||
" '质量': z_quality,\n",
|
||||
" '多因子(等权)': multi_factor,\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"print(f\"{'因子':<12} {'IC均值':>8} {'ICIR':>8} {'IC>0占比':>10}\")\n",
|
||||
"print('-' * 42)\n",
|
||||
"for name, fac in all_factors.items():\n",
|
||||
" a = FactorAnalyzer(fac.stack(), fwd_10d.stack())\n",
|
||||
" s = a.ic_summary()\n",
|
||||
" print(f\"{name:<12} {s['IC_Mean']:>8.4f} {s['IR']:>8.4f} {s['IC>0_Ratio']:>10.2%}\")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"name": "python",
|
||||
"version": "3.10.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
Reference in New Issue
Block a user