BOLL+KD双指标量化选股策略:聚宽回测实现与避坑指南

发布时间:2026/10/29 19:14:36
BOLL+KD双指标量化选股策略:聚宽回测实现与避坑指南 简介一份基于布林通道指标与KD随机摆动指标的股票池量化策略分析文档适合具备一定量化基础的投资者作为策略设计与回测参考。文档从动态市盈率、每股收益、净利润环比增长率、净资产收益率、流动资产与流动负债差额、经营活动现金净流量六大指标出发构建股票池并对江山股份、天赐材料、盛新锂能、中矿资源等个股进行基本面分析随后利用布林与KD指标制定买入卖出择时规则通过Python实现代码并完成回测参数设置最终从收益情况、成交情况、夏普比率、索提诺比率、最大回撤等维度解读回测结果。资源包内为一个docx文档大小约391KB内容涵盖研究思路、代码注释、回测设置与结果分析便于直接阅读与二次整理。目前已有326人学习下载适合希望系统梳理选股、择时与回测流程的读者。1. 量化策略拆解拿一份能直接跑出 256% 收益的 BOLLKD 选股方案量化策略文档里最容易被低估的是策略逻辑的自洽性。这篇基于布林指标BOLL和 KD 指标的股票池分析拿到手第一眼感觉是常规双指标组合但拆完才发现它把「选哪些股票、何时买入、何时卖出」三个环节全部用代码和回测固定了下来而不是停留在指标科普。文档完整记录了从动态市盈率、每股收益、净利润环比、ROE、偿债能力、现金流六个财务维度筛出 4 只股票的过程给出了 BOLL 通道与 KD 金叉死叉叠加的精确触发条件并在聚宽平台跑出 2019 至 2022 年 256.66% 的策略收益。适合已经熟悉聚宽或同类回测框架基础操作、想找一套可复现的选股-择时-回测闭环的读者参考。如果完全没有量化基础建议先补平台 API 再上手。2. 股票池构建六个维度财务指标与四只标的的筛选逻辑2.1 为什么是这六个维度而不是只看 PE 和 ROE选股池是整个策略的地基原文选股逻辑并不复杂但维度覆盖比较完整动态市盈率对应价值每股收益对应获利能力净利润环比增长率对应成长性净资产收益率对应质量流动资产与流动负债差额对应偿债能力经营活动现金净流量对应现金流状况。这六类指标实际上是在回答六个不同的问题公司贵不贵、赚不赚钱、还在不在增长、赚钱质量高不高、会不会爆雷、利润有没有真金白银支撑。把这些条件组合起来看筛选标准就变得清晰了动态市盈率 10 到 40 之间排除了亏损股和估值过热的标的每股收益大于 0.3保证有真实的税后利润净利润环比增长大于 30%这是成长性的硬门槛ROE 落在 15% 到 40% 之间既要求盈利能力突出又排除了 ROE 异常高的可疑标的流动资产大于流动负债是基本的偿债安全线经营活动现金流入大于流出则避免「有利润没现金」的纸面富贵。这套条件的筛选结果数量不会太多但每一只都经过多重财务约束组合本身具备一定的基本面安全垫。财务指标 | 类型 | 筛选条件 | 筛选意图 动态市盈率 | 价值类 | 10 PE 40 | 排除亏损与高估值 每股收益 | 获利能力 | EPS 0.3 | 保证税后利润为正且可观 净利润环比增长率 | 成长性 | 增长 30% | 要求业绩处于扩张期 净资产收益率 | 质量类 | 15% ROE 40% | 盈利质量高且不异常 流动资产与流动负债差额 | 偿债能力 | 流动资产 流动负债 | 避免短期偿债风险 经营活动现金净流量 | 现金流状况 | 现金流入 现金流出 | 排除纸面利润2.2 选股代码与数据口径get_fundamentals 的边界原文的选股代码基于聚宽的 get_fundamentals 实现这段代码可以直接抄进 notebook 跑一遍。需要注意一个细节原文 query 里没有显式引入 balance 表但 filter 里用了 balance.total_current_assets实际运行时需要把 balance 也加进 query否则会报字段找不到的错误。修正后的代码如下# 导入聚宽函数库 from jqdata import * # 获取满足财务条件的所有股票列表 stocks_data get_fundamentals( query( valuation.code, # 股票代码 valuation.pe_ratio, # 动态市盈率 valuation.market_cap, # 总市值 indicator.eps, # 每股收益 indicator.roe, # 净资产收益率 indicator.inc_net_profit_annual, # 净利润环比增长率 income.net_profit, # 净利润 cash_flow.subtotal_operate_cash_inflow, # 经营活动现金流入 cash_flow.subtotal_operate_cash_outflow, # 经营活动现金流出 balance.total_current_assets, # 流动资产 balance.total_current_liability # 流动负债 ).filter( valuation.pe_ratio 10, # 动态市盈率下限 valuation.pe_ratio 40, # 动态市盈率上限 indicator.eps 0.3, # 每股收益大于0.3元 indicator.inc_net_profit_annual 0.3, # 净利润环比增长超过30% indicator.roe 15, # ROE下限 indicator.roe 40, # ROE上限 balance.total_current_assets balance.total_current_liability, # 流动资产大于流动负债 cash_flow.subtotal_operate_cash_inflow cash_flow.subtotal_operate_cash_outflow # 经营现金流入大于流出 ), dateNone # 取最新披露数据 )逻辑说明query 部分把 valuation、indicator、income、cash_flow、balance 五张表需要的字段都列了出来filter 部分用七个条件依次收紧。这里的 dateNone 表示取系统当前可用的最新财务数据在实际回测中这个写法需要特别注意后面避坑章节会专门展开。参数说明pe_ratio 的 10 到 40 边界是为了避开亏损股和热门高估值股inc_net_profit_annual 的 0.3 是 30% 的环比增速原文用 0.3 而不是 30是聚宽接口的默认小数格式roe 上限设为 40 主要是过滤掉财务数据异常的公司。如果想把池子放宽可以先把净利润环比降到 0.2 看看候选池数量变化但不建议低于 0.15否则选出来的股票成长属性会明显减弱。2.3 从候选池到四只股票基本面如何落地经过上述财务条件筛选后原文最终确定的四只股票是江山股份、天赐材料、盛新锂能和中矿资源。这个结果不是随机挑选四只都落在当时的高景气赛道江山股份是农药龙头受益于粮食安全带来的农药需求提升天赐材料是锂电池电解液龙头拥有从上游原材料到电解液成品的一体化产业链盛新锂能主营锂产品2021 年归母净利润同比增长 3030.29%中矿资源从事稀有轻金属原料2019 到 2021 年营收增速持续走高。四只股票分属农化制品、电池化学品、能源金属、小金属行业表面看行业分散实际上都围绕新能源和资源安全两条主线。股票代码 | 名称 | 所属行业 | 核心选入逻辑 600389.XSHG | 江山股份 | 农化制品-农药 | 除草剂杀虫剂营收占比 60%盈利增速明显 002709.XSHE | 天赐材料 | 电池-电池化学品 | 电解液龙头一体化产业链布局 002240.XSHE | 盛新锂能 | 能源金属-锂 | 锂产品生产2021 年归母净利同比增长 3030% 002738.XSHE | 中矿资源 | 小金属-其他小金属 | 海外固体矿产勘查领先与盛新锂能合作这里要提醒一句四只股票是 2019 到 2022 年时间窗口下的选股结果行业景气判断有明确的时间背景。现在照着这个思路复现时不能直接照抄标的而是应该跑一遍同样的财务筛选再结合当下的行业景气度人工复核一遍这才是这套逻辑的正确用法。2.4 组合画像55.29% 预期收益背后的高波动选股完成后原文用 Python 计算了四只股票近三年的对数年化收益率和波动率组合的期望收益率是 55.29%年化波动率 57%。单看收益很诱人但波动率也是同类策略里偏高的水平这说明该策略本质上是在用高波动换高收益并非稳赚型。从原文给出的相关性数据看四只股票的相关系数大多在 0.85 到 0.96 之间呈高度正相关。这意味着所谓「组合分散化」的效果有限四只股票基本是同涨同跌一旦行业逻辑被证伪组合回撤会非常剧烈。原文在投资组合设置里用 80% 资金交易、留 20% 现金做风险管理就是对这种高波动的对冲手段。做回测参数设置时这个 80/20 的资金分配是重要前提不能随意改成全仓。3. 择时规则BOLL 通道定趋势方向KD 指标定进出场时机3.1 BOLL 指标的通道逻辑与买卖法则BOLL 指标由三条线组成中轨是 20 周期移动平均线上轨是移动平均线加上 2 倍标准差下轨是移动平均线减去 2 倍标准差。它的核心思想是价格通常运行在通道之内上轨构成压力下轨构成支撑通道宽窄则反映当前波动率的大小。原文的用法是股价向上突破中轨线时买入建仓股价上升穿越上轨线时卖出平仓。前者的逻辑是价格从弱势区域回到均值上方趋势可能由空转多后者的逻辑是价格冲出上轨后回档概率加大属于超买离场信号。在代码里对应的是 Bollinger_Bands 函数参数取 timeperiod20、nbdevup2、nbdevdn2也就是标准的 20 日均线和上下 2 倍标准差。这里有一个容易被忽略的细节该函数返回的 upperband、middleband、lowerband 是字典需要用股票代码作为 key 去取值比如 middleband[security]不能直接把整个字典拿来跟 current_price 做比较。3.2 KD 指标的超买超卖与金叉死叉KD 指标属于超买超卖型指标核心是衡量当前收盘价在过去一段时间价格区间中的相对位置。聚宽接口里调用 KD 函数返回 K 值和 D 值原文参数取 N18、M13、M23也就是说计算周期是 18 日K 值是 RSV 的 3 日移动平均D 值是 K 值的 3 日移动平均。相比常见的 9 日参数18 日周期更慢K 线和 D 线的交叉信号会更少但每次信号的有效性相对更高适合低频的股票池轮动策略。KD 指标的标准用法是K 值在 20 附近向上穿过 D 值时形成金叉买入进场K 值在 80 附近向下穿过 D 值时形成死叉卖出离场。金叉发生在超卖区域说明下跌动能衰竭反弹概率加大死叉发生在超买区域说明上涨动能减弱回调风险增加。原文在此基础上加了两个边界条件买入时要求 K 值大于等于 15卖出时要求 K 值小于等于 80。这个设计比教科书条件更宽松目的是让信号在强势行情中更容易触发买入、在超买区域仍然保留卖出机会。3.3 双指标叠加买入卖出条件的完整触发逻辑单一指标在震荡行情里经常发出假信号BOLL 和 KD 组合的目的是用趋势方向过滤掉一部分无效交叉。完整买入条件是三选一的「与」关系当前股价向上突破中轨线K 值大于等于 15同时 K 线上穿 D 线形成金叉。这三个条件同时满足时用账户可用现金的 80% 买入。这里的关键是 BOLL 中轨负责确认趋势方向KD 金叉负责确认动能转折点两者叠加能过滤掉价格仍在低位但 KD 已经钝化的假信号。卖出条件同样严格当前股价上升穿越上轨线K 值小于等于 80同时 K 线下穿 D 线形成死叉。注意原文卖出用的是 order_target(security, 0)意思是把该股票仓位全部清掉属于一次性的止盈止损操作不是分批减仓。这套双指标逻辑的好处是信号不频繁持仓周期长交易成本低坏处是遇到单边大涨行情时卖出信号迟迟不来回撤会偏大这一点在后文的风险分析中会看到具体数据。4. 聚宽回测实现策略代码逐段拆解与参数设定4.1 initialize 初始化股票池、基准与手续费策略代码可以整体放进聚宽平台的「我的策略」中运行。initialize 函数负责回测开始前的初始化工作包括定义股票池、设置基准指数、开启真实价格复权、设定交易费用。股票池直接用列表写死四只股票代码这是回测可复现的关键一步不建议在 initialize 里每次动态选股否则回测结果会混入选股逻辑本身的误差。# 定义初始化函数 def initialize(context): # 定义股票池天赐材料、盛新锂能、中矿资源、江山股份 g.stocks [002709.XSHE, 002240.XSHE, 002738.XSHE, 600389.XSHG] # 设置基准参数以沪深300指数作为比较基准 set_benchmark(000300.XSHG) # 设置动态复权使用真实价格计算收益 set_option(use_real_price, True) # 设置股票交易手续费印花税0.1%佣金0.03%最低佣金5元 set_order_cost( OrderCost( close_tax0.001, # 卖出时印花税单向征收 open_commission0.0003, # 买入佣金 close_commission0.0003, # 卖出佣金 min_commission5 # 单笔最低佣金5元 ), typestock ) # 每个交易日运行 trade 函数 run_daily(trade, every_bar)逻辑说明set_benchmark 将沪深 300 指数作为基准后续回测报告里所有超额收益、贝塔系数都是相对它计算的use_real_price 设为 True 表示按真实成交价模拟而不是用前复权或后复权价格更贴近实际交易OrderCost 里的 close_tax 只在卖出时收取。手续费参数对回测结果影响很大如果费率设得太低回测收益里会混入不切实际的利润。4.2 trade 主循环每日轮询与买卖条件判定trade 函数是策略的核心每个交易日对股票池中的四只股票依次做判断。先取最近 30 个交易日的收盘价再计算 BOLL 和 KD 指标然后逐条检查买入和卖出条件。需要注意attribute_history 返回的是 DataFrame取最后一根 K 线收盘价用 close_data[close][-1]这个索引方式在聚宽里很常见。# 定义每日交易函数 def trade(context): # 循环遍历股票池中的每只股票 for security in g.stocks: # 获取最近30个交易日的收盘价用于计算当前价格 close_data attribute_history(security, 30, 1d, [close]) # 计算布林通道指标返回上轨、中轨、下轨三个值 upperband, middleband, lowerband Bollinger_Bands( security, check_datecontext.current_dt, # 当前回测日期 timeperiod20, # 中轨周期20日 nbdevup2, # 上轨偏差2倍标准差 nbdevdn2 # 下轨偏差2倍标准差 ) # 取得最新收盘价作为当前价格 current_price close_data[close][-1] # 计算KD指标返回K值和D值 K1, D1 KD( security, check_datecontext.current_dt, N18, # 计算周期18日 M13, # K值平滑天数 M23 # D值平滑天数 ) # 获取账户当前可用现金 cash context.portfolio.available_cash # 买入条件价格突破中轨 K值在低位 金叉 有现金 if current_price middleband[security] and K1[security] 15 and K1[security] D1[security] and (cash 0): # 输出买入日志 log.info(买入 %s % (security)) # 使用 80% 可用资金买入 order_value(security, cash * 0.8) # 卖出条件价格穿越上轨 K值未极端超买 死叉 有可卖持仓 elif current_price upperband[security] and K1[security] 80 and K1[security] D1[security] and context.portfolio.positions[security].closeable_amount 0: # 输出卖出日志 log.info(卖出 %s % (security)) # 清仓该股票 order_target(security, 0) # 每日交易结束日志 log.info(一天交易完成)逻辑说明买入用了 order_value(security, cash * 0.8)第二个参数是买入金额而非股数这样资金利用率更直接卖出用 order_target(security, 0) 把持仓降到 0实现全部平仓。这里有一个关键的仓位逻辑cash 0判断的是可用现金而 order_value 用的是可用现金的 80%也就是说即使账户里只有少量现金也会全部用于买入这符合原文「80% 资金交易、20% 资金做风险管理」的设计。参数说明Bollinger_Bands 的 timeperiod20 是主流默认值nbdevup 和 nbdevdn 都取 2意味着通道宽度是 2 倍标准差。KD 的 N18 比标准 9 日参数更慢交叉信号更少适合这种低频轮动策略。如果想提高交易频率可以把 N 改成 9但要做好信号变多、手续费增加的准备。4.3 回测参数怎么设资金、时间、基准与交易费用回测参数的设置直接决定结果是否可信。原文给出的回测参数是初始资金 20 万元回测时间 2019 年 1 月 1 日到 2022 年 5 月 1 日基准沪深 300 指数交易费用包括印花税 0.1% 单向征收和佣金 0.03% 双向征收最低佣金 5 元。这些参数和上文 initialize 里的设置一一对应可以整理成一张参数表直接照抄。回测参数 | 设置值 | 说明 初始资金 | 200000 元 | 20 万元本金 回测时间 | 2019-01-01 至 2022-05-01 | 约 3 年零 4 个月 回测基准 | 000300.XSHG | 沪深 300 指数 印花税 | 0.1% 单向 | 仅在卖出时收取 佣金 | 0.03% 双向 | 买入卖出均收取单笔最低 5 元这里要特别说明最低佣金 5 元的影响。20 万资金按 80% 买入一笔约 16 万元佣金约 48 元不会触发最低 5 元限制但如果资金量降到 1 万元以下单笔佣金不足 5 元时按 5 元收取实际费率会显著上升。小资金跑这套策略时要注意这一点回测收益和实盘会有偏差。5. 回测避坑五个容易翻车的细节5.1 选股数据时点没卡住用了未来函数现象回测结果异常高年化收益超过 80%但盯着净值曲线发现收益集中在某几个交易日突然跳升。原因get_fundamentals 里 dateNone 表示取「当前」最新财务数据在回测环境中如果当天复权信息更新滞后会把未来披露的财务数据用到历史交易判断里形成未来函数。解决在回测代码中把 date 参数显式设为 context.previous_date或者用 get_fundamentals 的季度披露日期做对齐确保选股只使用当时已经公开的数据。5.2 query 里漏掉了 balance 表代码直接报错现象跑选股代码时提示字段不存在或者 FieldNotFound 类型错误。原因原文的 query 里只写了 valuation、indicator、income、cash_flow 的字段但 filter 条件里用了 balance.total_current_assets 和 balance.total_current_liabilitybalance 表没有被引入 query。解决把所有涉及的表都显式加进 query包括 balance 表确保每个字段都有对应的表来源这一点在聚宽接口中特别重要。5.3 Bollinger_Bands 返回的是字典不是数值现象直接拿 upperband 和 current_price 做比较时报类型错误或者结果始终为 False。原因Bollinger_Bands 在传入单只股票时返回的仍是以股票代码为 key 的字典不能直接把字典和 float 比较。解决统一用 upperband[security]、middleband[security]、lowerband[security] 取值再参与条件判断。KD 指标同理K1[security] 和 D1[security] 才是实际数值。5.4 卖出判断用 closeable_amount避免把当日买入误判为可卖现象盘中买入当天就被卖出产生大量虚假交易和手续费。原因如果判断条件写的是 positions[security].total_amount会把当天买入但 T1 不可卖的持仓也算进去。解决使用 closeable_amount 判断可卖数量这是聚宽里专门表示当日可卖持仓的字段。原文的卖出条件正是用了 closeable_amount 0这个细节值得保留。5.5 该策略是低频策略别拿高频标准去衡量现象回测报告里交易记录极少三年半只有几笔成交容易让人误以为策略失效。原因BOLL 和 KD 双指标叠加后信号触发条件非常苛刻大量时间处于持仓不动或空仓观察状态。解决用低频策略的预期去评估重点关注长期收益、最大回撤和持仓周期而不是日均交易次数。成交频率低本身是优势代表交易成本控制得好但前提是每一笔持仓的逻辑足够扎实。6. 学会读回测报告从 256.66% 收益里看出策略的真实性格6.1 收益端钱是哪段时间赚的回测报告显示策略总收益 256.66%年化 48.28%但收益并不是均匀分布的。原文明确指出主要收益来自 2021 年 5 月至 2022 年 5 月这段区间也就是新能源板块整体走强的阶段。这说明策略的 alpha 很大程度来自股票池本身的高景气度BOLL 和 KD 择时起到的作用是让组合在大涨阶段始终在场、在下跌初期及时离场而不是凭空创造收益。6.2 风险端五个指标一起看夏普比率 1.097意味着每承担一单位总风险能换回约 1.1 单位超额回报索提诺比率 1.693说明下行风险控制比总风险控制更好贝塔 0.934组合波动略大于基准但基本同步波动率 40.4%低于选股时预期的 57%说明择时确实平滑了部分波动最大回撤 38.56%发生在 2021 年 9 月到 2022 年 1 月正好对应大盘高位回调阶段。五个指标合在一起这套策略的画像就是高收益、高波动、但下行风险控制优于普通满仓持有。6.3 一个验证过拟合的小技巧把手里的回测报告看明白之后我一般会再多做一步验证把回测起点从 2019 年 1 月挪到 2020 年 1 月再把股票池里的四只股票换成同板块其他标的比如把天赐材料换成多氟多、把盛新锂能换成赣锋锂业重新跑一遍回测。如果收益和回撤数据发生剧烈变化说明策略的收益高度依赖特定标的和特定时间段属于过拟合如果收益结构基本相似只是数值略有浮动说明策略逻辑本身有稳定性。从那以后我每次拿到回测报告都强制走一遍这套检查顺序——先看收益来自哪个时间段再看最大回撤发生在什么时候最后手动换掉股票池做敏感性测试希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询