
Qbot 布林线均值回归策略实战从 BOLL 原理到回测与稳健性分析【免费下载链接】Qbot[updating ...] AI 自动量化交易机器人(完全本地部署) AI-powered Quantitative Investment Research Platform. online docs: https://ufund-me.github.io/Qbot ✨ :news: qbot-mini: https://github.com/Charmve/iQuant项目地址: https://gitcode.com/GitHub_Trending/qbot/Qbot布林线均值回归是一种经典的统计套利型股票策略利用均值与标准差构建的布林带判断价格超买/超卖状态是 Qbot 量化投资平台中收录的经典策略之一。本文将基于 Qbot 仓库中的 布林线均值回归.md 文档完整讲解 BOLL 指标的计算原理、均值回归策略的构建思路、掘金量化平台gm.api上的完整策略代码以及不同回测期下的稳健性分析结论同时结合仓库内pytrader、qbot等目录下的源码实现从指标计算、信号生成、回测框架三个层面做纵深印证帮助读者掌握一套可复现、可改参、可迁移到多框架的布林带策略落地方法。一、策略原理布林带与均值回归提起布林线均值回归策略就不得不提布林带Bollinger Bands这个概念。布林带由约翰·布林格John Bollinger提出是利用统计学中的均值和标准差联合计算得出的价格通道由上轨线、中轨线均线和下轨线三条线构成。布林线均值回归策略的核心假设是标的价格绝大多数时间在上轨线与下轨线围成的带状区间内浮动即使短期内突破上下轨长期内仍然会回归到布林带之中。因此一旦价格突破上下轨即形成了潜在的买卖信号当股价向上突破上界上轨时认为价格短期偏高、面临回归压力为卖出信号当股价向下突破下界下轨时认为价格短期偏低、存在反弹空间为买入信号。BOLL 线的计算公式BOLL 线的三条轨道均基于 N 日窗口内的收盘价序列计算公式如下中轨线(MID) N日移动平均线 上轨线(UP) 中轨线 k × 标准差 下轨线(LOW) 中轨线 - k × 标准差其中N为计算周期窗口长度决定轨道对价格变化的敏感度k为标准差倍数决定轨道的宽度即对波动幅度的容忍程度。在 Qbot 仓库中BOLL 指标被列为每日股票指标体系的一员。在 股票指标.md 的 17 项日频指标清单中第 9 项即BOLL指标布林线指标 Bollinger Bands说明该指标在 Qbot 的指标计算管线中具有标准地位可直接作为选股因子与回测信号源使用。二、策略思路与回测设定布林线均值回归策略的实现路径非常清晰共分三步第一步根据历史数据计算 BOLL 线的上下界——利用收盘价序列的移动均值与移动标准差构造中轨、上轨、下轨第二步获得持仓信号——比较最新收盘价与上下轨的穿越关系产生买入/卖出/持有指令第三步回测分析——在指定标的上运行策略统计收益、回撤、胜率等指标检验策略有效性。原文档给出的回测设定如下回测标的SHSE.600004白云机场回测期2009-09-17 13:00:00 至 2020-03-21 15:00:00回测初始资金1000 元需要说明的是该回测运行在掘金量化GoldMiner的gm.api接口之上Qbot 仓库中的经典策略文档如 Alpha对冲.md、多因子选股.md 等均采用了相同的回测代码 稳健性分析文档体例便于读者横向对比不同策略在同一平台上的表现。三、策略代码基于 gm.api 的完整实现以下为原文档提供的完整策略代码运行于掘金量化平台策略采用日线频率在价格向上穿越上轨时卖出、向下穿越下轨时买入# codingutf-8 from __future__ import print_function, absolute_import from gm.api import * 本策略采用布林线进行均值回归交易。当价格触及布林线上轨的时候进行卖出当触及下轨的时候进行买入。 使用600004在 2009-09-17 13:00:00 到 2020-03-21 15:00:00 进行了回测。 注意 1实盘中如果在收盘的那一根bar或tick触发交易信号需要自行处理实盘可能不会成交。 # 策略中必须有init方法 def init(context): # 设置布林线的三个参数 context.maPeriod 26 # 计算BOLL布林线中轨的参数 context.stdPeriod 26 # 计算BOLL 标准差的参数 context.stdRange 1 # 计算BOLL 上下轨和中轨距离的参数 # 设置要进行回测的合约 context.symbol SHSE.600004 # 订阅交易标的, 此处订阅的是600004 context.period max(context.maPeriod, context.stdPeriod, context.stdRange) 1 # 订阅数据滑窗长度 # 订阅行情 subscribe(symbols context.symbol, frequency1d, countcontext.period) def on_bar(context, bars): # 获取数据滑窗只要在init里面有订阅在这里就可以取的到返回值是pandas.DataFrame data context.data(symbolcontext.symbol, frequency1d, countcontext.period, fieldsclose) # 计算boll的上下界 bollUpper data[close].rolling(context.maPeriod).mean() \ context.stdRange * data[close].rolling(context.stdPeriod).std() bollBottom data[close].rolling(context.maPeriod).mean() \ - context.stdRange * data[close].rolling(context.stdPeriod).std() # 获取现有持仓 pos context.account().position(symbolcontext.symbol, sidePositionSide_Long) # 交易逻辑与下单 # 当有持仓且股价穿过BOLL上界的时候卖出股票。 if data.close.values[-1] bollUpper.values[-1] and data.close.values[-2] bollUpper.values[-2]: if pos: # 有持仓就市价卖出股票。 order_volume(symbolcontext.symbol, volume100, sideOrderSide_Sell, order_typeOrderType_Market, position_effectPositionEffect_Close) print(以市价单卖出一手) # 当没有持仓且股价穿过BOLL下界的时候买出股票。 elif data.close.values[-1] bollBottom.values[-1] and data.close.values[-2] bollBottom.values[-2]: if not pos: # 没有持仓就买入一百股。 order_volume(symbolcontext.symbol, volume100, sideOrderSide_Buy, order_typeOrderType_Market, position_effectPositionEffect_Open) print(以市价单买入一手) if __name__ __main__: strategy_id策略ID,由系统生成 filename文件名,请与本文件名保持一致 mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST token绑定计算机的ID,可在系统设置-密钥管理中生成 backtest_start_time回测开始时间 backtest_end_time回测结束时间 backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST backtest_initial_cash回测初始资金 backtest_commission_ratio回测佣金比例 backtest_slippage_ratio回测滑点比例 run(strategy_idstrategy_id, filenamemain.py, modeMODE_BACKTEST, tokentoken_id, backtest_start_time2009-09-17 13:00:00, backtest_end_time2020-03-21 15:00:00, backtest_adjustADJUST_PREV, backtest_initial_cash1000, backtest_commission_ratio0.0001, backtest_slippage_ratio0.0001)3.1 代码逐段拆解参数配置initmaPeriod 26与stdPeriod 26分别指定中轨均线与标准差的滚动窗口长度stdRange 1即公式中的标准差倍数k。context.period max(...) 1取三者最大值加 1 作为订阅数据滑窗长度保证滚动计算有足够的历史数据。行情订阅subscribe(symbols..., frequency1d, countcontext.period)以日线频率订阅标的count指定一次性拉取的 K 线根数。BOLL 上下界计算利用 pandas 的rolling().mean()与rolling().std()直接实现公式——中轨为 N 日收盘价均值上轨为中轨加stdRange倍标准差下轨为中轨减stdRange倍标准差。信号与下单只有当收盘价穿越上轨[-1]突破且[-2]未突破且当前有持仓时才市价卖出 100 股只有收盘价穿越下轨且当前无持仓时才市价买入 100 股。采用穿越而非触碰判断可避免在轨道附近反复触发信号。回测入口runmodeMODE_BACKTEST表示回测模式backtest_adjustADJUST_PREV使用前复权数据backtest_initial_cash1000设定初始资金backtest_commission_ratio0.00010.01%为佣金比例backtest_slippage_ratio0.00010.01%为滑点比例。strategy_id与token需替换为掘金平台上实际生成的策略 ID 与本机绑定密钥。四、回测结果与稳健性分析原文档设定初始资金 1000 元、手续费率 0.01%、滑点比率 0.01% 进行回测回测结果要点如下回测期累计收益率为99.77%年化收益率为9.49%同期沪深 300 收益率为10.03%策略整体跑输大盘最大回撤为32.04%胜率为73.47%。为验证策略的稳定性原文档调整了回测周期观察收益变化| 标的 | 回测期 | 年化收益率 | 最大回撤 | | -- | ------- | --- | --- | | SHSE.600004 | 2009.09.17-2020.03.21 | 9.49% | 32.04% | | SHSE.600004 | 2009.01.01-2014.12.30 | 2.64% | 17.07% | | SHSE.600004 | 2014.01.01-2020.03.21 | 20.75% | 17.21% | | SHSE.600004 | 2009.01.01-2019.03.21 | 8.18% | 31.95% |调整不同的回测期后策略的收益情况发生变化。整体收益均为正但均跑输大盘。由此可以得出两点稳健性结论策略长期保持正收益四个回测窗口年化收益均为正说明均值回归逻辑在白云机场这只标的上具备持续的有效性基础没有出现系统性失效收益对回测期高度敏感2009-2014 窗口年化仅 2.64%而 2014-2020 窗口年化达 20.75%区间选择对结论影响显著。结合胜率 73.47% 但整体跑输沪深 300 的表现可以推断布林线均值回归属于高胜率、低单笔盈亏比的策略类型在震荡市中表现更佳在单边上涨行情中容易过早卖出踏空主升浪因此更适合作为组合中的卫星策略而非全仓押注的进攻策略。注此策略只用于学习、交流、演示不构成任何投资建议。五、仓库源码印证BOLL 指标的三种实现视角Qbot 仓库在pytrader与qbot两个子项目中提供了多套 BOLL 相关的策略实现可以与掘金版策略代码互为印证帮助理解同一指标在不同框架下的落地差异。5.1 TA-Lib 版pytrader/backtest_strategies/BOLL.pypytrader/backtest_strategies/BOLL.py 是基于 TA-Lib 库的 BOLL 策略类继承自 pytrader/backtest_strategies/backtest_strategy_template.py 定义的BacktestStrategyTemplatefrom backtest_strategies.backtest_strategy_template import BacktestStrategyTemplate from pandas import DataFrame from talib._ta_lib import BBANDS class BOLLStrategy(BacktestStrategyTemplate): BOLL指标策略 def get_singal(self, df: DataFrame): upper, middle, lower self.get_boll(df) # 获取最新价格 current_price df.close[-1] # 穿越上轨买入信号 if current_price upper[-1]: return 1 # 穿越下轨卖出信号 if current_price lower[-1]: return 0 return -1 def get_boll(self, df: DataFrame): return BBANDS(df.close, timeperiod14, nbdevup2, nbdevdn2, matype0)这一实现与掘金版在信号方向上恰好相反TA-Lib 版为突破上轨买入、跌破下轨卖出即趋势跟踪用法但在计算层面与文档完全同构BBANDS返回(upper, middle, lower)三元组timeperiod14对应公式中的 Nnbdevup2、nbdevdn2对应标准差倍数 k此处上轨与下轨各用 2 倍matype0表示使用简单移动平均。对比可见同一套 BOLL 公式既可服务于均值回归价格触及轨道反向交易也可服务于趋势突破价格突破轨道顺势交易信号方向完全由策略意图决定这正是技术指标中性工具、策略赋予语义的典型体现。模板基类BacktestStrategyTemplate提供了完整的回测脚手架process()逐日调用get_singal生成持仓信号序列output_earning_rate()以(1 close.pct_change(1).fillna(0) * signals).cumprod()计算策略净值曲线并与基准close / close[0]对比show_plt()绘制收益与指标双面板图。在 pytrader/newbacktest.py 中BOLLStrategy与RSIStrategy、CCIStrategy、MACDStrategy等并列可供切换相关代码行以注释形式存在说明该策略类被设计为可插拔的公共回测组件。5.2 Backtrader 版qbot/strategies/boll_strategy_bt.pyqbot/strategies/boll_strategy_bt.py 提供的是基于 Backtrader 框架的独立可运行回测脚本信号逻辑与掘金版文档完全一致——收盘价跌破下轨买入、突破上轨卖出class BollStrategy(bt.Strategy): # BOLL策略程序 params ( (nk, 13), # 求均值的天数 (printlog, False), ) # 打印log def __init__(self): # 初始化 self.data_close self.datas[0].close # 指定价格序列 # 初始化交易指令、买卖价格和手续费 self.order None self.buy_price None self.buy_comm None # Boll指标计算 self.top bt.indicators.BollingerBands( self.datas[0], periodself.params.nk ).top self.bot bt.indicators.BollingerBands( self.datas[0], periodself.params.nk ).bot # 添加移动均线指标 self.sma bt.indicators.SimpleMovingAverage( self.datas[0], periodself.params.nk ) def next(self): # 买卖策略 if self.order: # 检查是否有指令等待执行 return if not self.position: # 没有持仓 if self.data_close[0] self.bot[0]: # 收盘价格跌破下轨 self.log(BUY CREATE, %.2f % self.data_close[0]) self.order self.buy() # 执行买入 else: if self.data_close[0] self.top[0]: # 收盘价格上涨突破上轨 self.log(SELL CREATE, %.2f % self.data_close[0]) self.order self.sell() # 执行卖出该脚本通过 Backtrader 内置的bt.indicators.BollingerBands计算上下轨并展示了完整的回测装配流程通过 AKShare 的ak.stock_zh_a_hist(symbolcode, adjustqfq, ...)获取前复权日线数据并规范字段命名喂给bt.feeds.PandasData随后cerebro.addstrategy(BollStrategy, nk13, printlogTrue)加载策略、cerebro.broker.setcash(1000000)设定初始资金、setcommission(commission0.0005)设定万五手续费、bt.sizers.FixedSize(stake100)设定每笔 100 股1 手。notify_order与notify_trade两个回调分别记录成交明细与平仓收益stop在回测结束时打印期末总资金。默认示例标的为 600036招商银行回测区间 2021-01-01 至 2022-12-06。这段代码可作为读者在本地复现均值回归版布林策略的最短路径只需将code换成 SHSE.600004 对应的 A 股代码600004即可对照原文档结论。5.3 指标管线版qbot/qbot.py中的多因子信号qbot/qbot.py 展示了 BOLL 指标在因子合成场景中的用法。该脚本用 TA-Lib 一次性计算 MA5/MA10/MA20、BIAS、BOLL、KDJ、RSI 等指标其中布林带部分为data[upper], data[middle], data[lower] talib.BBANDS(data[close], timeperiod20, nbdevup2, nbdevdn2, matype0)随后将多个子策略信号加权合成# 第二个策略股价低于BOLL线底 condition2 (data[close] data[lower]) signals 0.3 * condition2.astype(int)这里的condition2正是布林线均值回归的经典触发条件——收盘价跌破下轨视为超卖赋予 0.3 的权重参与总信号合成。这说明在 Qbot 的多因子体系中布林线突破信号不是单独决定买卖而是作为打分因子之一与其他指标均线多头、KDJ 金叉、RSI 超买超卖加权叠加最终由orders[signals 0] 1生成买入指令。相比单一 BOLL 策略这种用法更贴近实战中的因子组合思路。5.4 三种实现的横向对照| 实现 | 仓库位置 | 指标来源 | 信号方向 | 适用场景 | | -- | -- | -- | -- | -- | | 掘金 gm.api 版 | docs/02-经典策略/01-股票/布林线均值回归.md | pandas rolling 手算 | 破下轨买、破上轨卖均值回归 | 掘金平台回测/实盘 | | TA-Lib 模板版 | pytrader/backtest_strategies/BOLL.py |talib.BBANDS| 破上轨买、破下轨卖趋势 | 可插拔回测组件 | | Backtrader 版 | qbot/strategies/boll_strategy_bt.py |bt.indicators.BollingerBands| 破下轨买、破上轨卖均值回归 | 本地独立回测 | | 因子合成版 | qbot/qbot.py |talib.BBANDS| 跌破下轨作为买入信号之一 | 多因子打分组合 |六、参数解读与调参方向结合原文档参数与仓库源码将 BOLL 均值回归策略涉及的核心参数汇总如下| 参数 | 文档默认值 | 含义 | 调参影响 | | -- | -- | -- | -- | |maPeriodN | 26 | 中轨移动平均窗口 | 越大轨道越平滑、信号越少越小反应越灵敏、假信号越多 | |stdPeriodN | 26 | 标准差计算窗口 | 通常与maPeriod保持一致 | |stdRangek | 1 | 轨道宽度标准差倍数 | k 越大带宽越宽、触发次数越少k 越小信号越频繁。经典取值为 2文档取 1 相对激进 | |volume下单量 | 100 股 | 每次交易手数 | A 股一手为 100 股可按资金量等比例放大 | |backtest_initial_cash| 1000 | 初始资金 | 资金过小时受最小下单量约束明显 | |backtest_commission_ratio| 0.0001 | 佣金比例0.01% | 高频触发类策略对费率敏感 | |backtest_slippage_ratio| 0.0001 | 滑点比例0.01% | 市价单对滑点敏感 |值得注意的调参细节标准差倍数 k经典布林带默认 k2如 pytrader/backtest_strategies/BOLL.py 的nbdevup2, nbdevdn2而本文策略取 k1轨道更窄、触发更频繁与文档回测中 73.47% 的高胜率、但整体跑输大盘的结果是自洽的——窄轨道带来更多交易机会但单次回归空间变小。触发方式文档采用穿越上穿/下穿而非触碰触发data.close.values[-1]与data.close.values[-2]的联合判断可有效过滤轨道附近的反复震荡。复权方式回测使用ADJUST_PREV前复权避免分红除权造成的价格跳空干扰指标计算若涉及历史区间较长的回测应统一数据复权口径。实盘注意代码注释明确指出若在收盘那一根 bar 或 tick 触发交易信号实盘可能无法成交需要自行处理盘中确认逻辑。七、总结布林线均值回归是 Qbot 经典策略集中最简单、最容易上手复现的策略之一。其核心逻辑可以一句话概括价格突破布林带边界即视为超买/超卖反向交易等待价格回归中轨。本文从公式原理出发完整复现了基于掘金量化平台的策略代码并通过调整回测期验证了策略的稳健性边界——整体收益为正但多数时期跑输沪深 300说明该策略适合作为震荡市中的卫星策略或组合因子而非独立的大盘战胜者。同时Qbot 仓库在pytrader与qbot两个子项目中分别提供了 TA-Lib 模板、Backtrader 脚本与多因子合成三种 BOLL 落地形态读者可根据自身回测框架掘金 / 自研模板 / Backtrader任选其一进行复现并依据文中参数表调整窗口长度、标准差倍数、费率与滑点进一步验证不同参数组合下的收益-回撤权衡。再次提醒以上策略与回测数据仅用于学习、交流、演示不构成任何投资建议。实盘前请务必完成充分的样本外验证与风险控制设计。【免费下载链接】Qbot[updating ...] AI 自动量化交易机器人(完全本地部署) AI-powered Quantitative Investment Research Platform. online docs: https://ufund-me.github.io/Qbot ✨ :news: qbot-mini: https://github.com/Charmve/iQuant项目地址: https://gitcode.com/GitHub_Trending/qbot/Qbot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考