{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 均线趋势策略 — 构建与回测\n", "\n", "## 策略思路\n", "趋势跟踪(Trend Following):价格位于均线上方且均线向上时做多,反之做空/空仓。\n", "本策略使用 **股价偏离 20 日均线的 Z-Score** 作为趋势强度因子,\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", "price_data = loader.load_prices(START_DATE, END_DATE)\n", "print(f'价格数据: {price_data.shape}, 日期: {price_data.index[0]} ~ {price_data.index[-1]}')\n", "price_data.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. 趋势因子计算与 IC 分析\n", "\n", "趋势因子 = 价格偏离 20 日均线的幅度(百分比):\n", "$$Trend = \\frac{Close}{MA_{20}} - 1$$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MA_WINDOW = 20\n", "ma = price_data.rolling(MA_WINDOW).mean()\n", "trend_factor = price_data / ma - 1 # 正偏离 = 上升趋势\n", "\n", "# 未来 5 日收益率\n", "fwd_5d = price_data.pct_change(5).shift(-5)\n", "\n", "factor_stacked = trend_factor.stack()\n", "fwd_stacked = fwd_5d.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('趋势因子分层收益 (未来5日)')\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='均线趋势策略-MA20',\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日均线幅度最大的20%股票'\n", ")\n", "\n", "engine = BacktestEngine(config)\n", "equity_curve = engine.run(\n", " strategy=strategy,\n", " price_data=price_data,\n", " factor_data={'trend': trend_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='orange')\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": [ "# 不同均线周期对比\n", "for win in [5, 10, 20, 60]:\n", " ma_tmp = price_data.rolling(win).mean()\n", " fac = price_data / ma_tmp - 1\n", " a = FactorAnalyzer(fac.stack(), fwd_stacked)\n", " summary = a.ic_summary()\n", " print(f'MA{win}: IC均值={summary[\"IC_Mean\"]:.4f}, ICIR={summary[\"IR\"]:.4f}, '\n", " f'IC>0占比={summary[\"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 }