Files
quanxiel/alpha/质量因子策略.ipynb
T

298 lines
8.6 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 质量因子策略 — 构建与回测\n",
"\n",
"## 策略思路\n",
"质量投资(Quality Investing):买入盈利能力强、财务稳健的公司。\n",
"本策略使用 **ROE、毛利率、资产负债率** 合成质量因子:\n",
"- ROE(净资产收益率)越高 → 质量越好\n",
"- 毛利率越高 → 质量越好\n",
"- 资产负债率越低 → 财务更稳健\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. 加载数据\n",
"\n",
"质量因子需要财务指标(ROE / 毛利率 / 资产负债率),通过 `DataLoader.load_factor` 加载。"
]
},
{
"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",
"roe_data = loader.load_factor('roe', START_DATE, END_DATE) # 净资产收益率\n",
"gross_margin_data = loader.load_factor('gross_margin', START_DATE, END_DATE) # 毛利率\n",
"debt_data = loader.load_factor('debt_to_assets', START_DATE, END_DATE) # 资产负债率\n",
"\n",
"print(f'价格数据: {price_data.shape}')\n",
"print(f'ROE数据: {roe_data.shape}')\n",
"print(f'毛利率数据: {gross_margin_data.shape}')\n",
"print(f'资产负债率数据: {debt_data.shape}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. 质量因子计算与 IC 分析\n",
"\n",
"质量因子 = Z(ROE) + Z(毛利率) + Z(-资产负债率)\n",
"\n",
"财务指标为季度数据,`DataLoader` 已重采样到交易日并做向前填充。"
]
},
{
"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",
"z_roe = zscore_cross_section(roe_data)\n",
"z_gm = zscore_cross_section(gross_margin_data)\n",
"z_debt = -zscore_cross_section(debt_data) # 负债率越低越好\n",
"\n",
"quality_factor = z_roe + z_gm + z_debt\n",
"\n",
"# 未来 20 日收益率(质量因子预测周期较长)\n",
"fwd_20d = price_data.pct_change(20).shift(-20)\n",
"\n",
"factor_stacked = quality_factor.stack()\n",
"fwd_stacked = fwd_20d.stack()\n",
"\n",
"analyzer = FactorAnalyzer(factor_stacked, fwd_stacked)\n",
"ic = analyzer.compute_ic(method='rank')\n",
"\n",
"print('质量因子 IC 汇总:')\n",
"for k, v in analyzer.ic_summary().items():\n",
" print(f' {k}: {v:.4f}')\n",
"\n",
"ic.plot(figsize=(12, 3), title='质量因子 Rank IC 时间序列')\n",
"plt.axhline(y=0, color='r', linestyle='--')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. 分层回测"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"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('质量因子分层收益 (未来20日)')\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='质量因子策略-ROE+毛利率+低负债',\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='每月持有ROE高、毛利率高、负债率低的优质公司'\n",
")\n",
"\n",
"engine = BacktestEngine(config)\n",
"equity_curve = engine.run(\n",
" strategy=strategy,\n",
" price_data=price_data,\n",
" factor_data={'quality': quality_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='brown')\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",
"对比各质量指标单独用于选股的效果:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 各分项因子 IC 对比\n",
"for name, fac in [\n",
" ('ROE', z_roe),\n",
" ('毛利率', z_gm),\n",
" ('低负债率', z_debt),\n",
" ('质量合成', quality_factor),\n",
"]:\n",
" a = FactorAnalyzer(fac.stack(), fwd_stacked)\n",
" s = a.ic_summary()\n",
" print(f'{name}: IC均值={s[\"IC_Mean\"]:.4f}, ICIR={s[\"IR\"]:.4f}, '\n",
" f'IC>0占比={s[\"IC>0_Ratio\"]:.2%}')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.10.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}