gs-quant 量化金融回测实战:一段脚本跑通均值回归策略,看懂 5 个核心指标
【免费下载链接】gs-quantPython toolkit for quantitative finance项目地址: https://gitcode.com/GitHub_Trending/gs/gs-quant
gs-quant 是 Python 量化金融工具包,内置回测引擎、触发器与绩效指标体系。本文用它回测一个"价差均值回归"策略:一段可运行的脚本,从取数、定规则到输出指标,10 分钟走完全程。
先看结果:跑完一次回测你能拿到什么
先给结论。跑完后你会得到一个BackTest对象,它能吐出三样东西:每日净值的 DataFrame、逐笔交易台账、一揽子绩效指标。示意如下(数值仅为说明含义,实际以你的运行结果为准):
| 指标 | 示意值 | 一句话含义 |
|---|---|---|
| Sharpe Ratio(夏普比率) | 0.8 | 每承担一份波动换到的年化收益 |
| Max Drawdown(最大回撤) | -7% | 净值从最高点跌下来的最大幅度 |
| Total Trades(交易次数) | 12 | 一年里进出场了多少次 |
| % Positive Days(盈利天数占比) | 55% | 有多少个交易日是赚钱的 |
倒推一下,要产出这张表需要解决三件事:数据从哪来(价格序列)、何时动手(进出场规则)、怎么算账(引擎逐日定价并计成本)。下面按顺序解决。
原理速览:把价差想象成一根橡皮筋
两只走势相关的股票,价格之比(价差)就像一根被反复拉长的橡皮筋:多数时候在常态长度附近晃动,偶尔被消息拉到很长,然后弹回去。策略的全部逻辑就是:等它拉过头,下注它回弹。
三个关键概念:
- 价差比率(Spread Ratio):A 价格 / B 价格 - 1,衡量两只标的谁相对更贵
- 均值回归(Mean Reversion):偏离常态的价差有弹回常态的倾向
- Z 分数(Z-Score):当前价差偏离近 N 日均值多少个标准差,等于"橡皮筋被拉出去几格"
整个回测就是一条循环:
gs-quant 把这条循环拆成三个可插拔部件:DataSource(喂数据)、Trigger(判断何时动手)、Action(动手做什么),回测引擎逐日推动它们运行。
3 分钟装好环境,认证只需一行
安装一条命令:
pip install gs-quant --upgrade--upgrade保证拿到最新版本与依赖(需 Python 3.8+,pandas 等常用库请自行装好)。
登录一行(首次会提示输入 developer key,注册 gs-quant 账号即可获取):
import gs_quant as gs gs.login() # 认证信息本地保存,之后无需重复一次跑通:完整脚本与分段注解
下面是可整段复制的脚本,按功能分三段。演示用两只同板块大票 AAPL 与 MSFT,实际使用请换成相关性更高的配对。
拉取价格并构造价差信号
这一步取两只标的的收盘价,算出价差比率与 Z 分数,再包装成引擎可读的数据源:
import datetime as dt from gs_quant.markets import Stock from gs_quant.backtests.data_sources import GenericDataSource, MissingDataStrategy start, end = dt.date(2022, 1, 3), dt.date(2025, 1, 3) a = Stock('AAPL').history('price', start_date=start, end_date=end) # 标的A价格 b = Stock('MSFT').history('price', start_date=start, end_date=end) # 标的B价格 spread = a / b - 1 # 价差比率 z = (spread - spread.rolling(60).mean()) / spread.rolling(60).std() # 60日Z分数 signal = GenericDataSource(z.dropna(), MissingDataStrategy.fill_forward) # 引擎可读信号两个关键参数:rolling(60)是平滑窗口(60 个交易日),MissingDataStrategy.fill_forward决定缺值日前向填充而不是中断。数据源实现见 gs_quant/backtests/data_sources.py。
定义进出场规则
这一步声明两个触发器:Z 分数上穿 2 开仓、下穿 1 平仓,每次交易记 200 美元固定成本:
from gs_quant.markets.portfolio import Portfolio from gs_quant.backtests.actions import AddTradeAction, ExitAllPositionsAction, ConstantTransactionModel from gs_quant.backtests.triggers import MktTrigger, MktTriggerRequirements, TriggerDirection pair = Portfolio([(Stock('AAPL'), -1), (Stock('MSFT'), 1)], name='pair') # 做空A,做多B enter = MktTrigger( MktTriggerRequirements(signal, 2.0, TriggerDirection.ABOVE), # Z>2:价差拉过头 AddTradeAction(pair, '60d', name='pair_entry', transaction_cost=ConstantTransactionModel(200))) # 每笔固定成本 exit_pos = MktTrigger( MktTriggerRequirements(signal, 1.0, TriggerDirection.BELOW), # Z回落到1以下:平仓 ExitAllPositionsAction(name='pair_exit')) # 想做对称方向:再加一个 z<-2 进入、z>-1 离开的触发器即可关键参数是2.0 / 1.0两个阈值与'60d'持仓上限;触发器与动作的完整家族(含内置的MeanReversionTrigger)实现在 gs_quant/backtests/triggers.py。
启动回测引擎
这一步把策略交给引擎,逐日推进定价、成交与结算:
from gs_quant.backtests.strategy import Strategy from gs_quant.backtests import GenericEngine strategy = Strategy(None, [enter, exit_pos]) # 第一个参数为初始持仓,None 表示空仓起跑 engine = GenericEngine() backtest = engine.run(start, end, strategy) # 返回 BackTest 对象引擎如何把触发器与动作串成完整回测,见 gs_quant/backtests/generic_engine.py。
读懂结果:回测指标怎么看
拿到backtest对象后,指标、净值曲线、交易台账各一行取出:
stats = backtest.summary_stats() # 一揽子绩效指标 print(stats[['Sharpe Ratio', 'Max Drawdown', 'Total Trades', '% Positive Days']]) backtest.result_summary['Total'].plot() # 组合净值曲线 backtest.trade_ledger().tail() # 逐笔开平仓与盈亏台账这 20 余项指标的计算逻辑集中在 gs_quant/backtests/backtest_objects.py。
挑三个最常看的讲"看什么、怎么判好坏":
- Sharpe Ratio:像汽车油耗,衡量"每单位颠簸换多少里程"。大于 1 算健康,低于 0.5 说明收益大多被波动吃掉
- Max Drawdown:净值水位从高点回落到谷底的深度。均值回归靠"小赢很多次",回撤过深往往意味着配对失效,而不是耐心不够
- Total Trades:一年 10 次上下符合"低频等回弹"的定位;翻到几十次就先怀疑阈值太松
上图为 gs-quant 文档中的一张分周期组合图:柱状是各周期收益、折线是累计值。回测净值曲线与trade_ledger()台账也是同样的"分块 + 累计"读法。
调参与避坑:跑之前的四个检查项
**现象:毛收益不
【免费下载链接】gs-quantPython toolkit for quantitative finance项目地址: https://gitcode.com/GitHub_Trending/gs/gs-quant
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考