ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用Python实现烂板策略:从涨停板博弈到量化回测实战

用Python实现烂板策略:从涨停板博弈到量化回测实战 你有没有在盘中盯过这样的股票明明封死了涨停封单却薄得像层窗户纸几千手一砸就开价格刚滑下来又有资金冲进去抢筹把它重新拉到板上。如此反复三五次分时图就像一条被反复折叠的折线。懂行的人管这种情况叫烂板。在量化交易圈子里围绕烂板衍生出来的策略是一类非常特殊的短线高频交易玩法——它不研究基本面不看均线金叉死叉只盯着涨停板被砸开和回封的瞬间捕捉资金从分歧走向共识的那一段利润。这篇文章围绕烂板策略把从底层逻辑、数据准备、因子构造、Python代码实现到回测陷阱和实盘风控的完整链路讲一遍。我默认看这篇内容的你已经懂Python基础接触过pandas和向量化回测但对涨停板制度下的短线博弈生态还不一定熟悉。内容会比较细尤其是那些回测曲线不会告诉你的坑我会重点讲。1. 烂板策略不是玄学涨停反复打开的博弈本质1.1 烂板到底在交易什么分歧与换手的底层逻辑先说清楚烂板的定义。一只股票盘中触达涨停价但没能在涨停价上一直封住中间被大单砸开、价格回落到涨停价以下之后再被买盘重新拉回涨停——这个过程如果发生两次以上这只股票当天就是烂板。涨停板制度把单日最大涨幅锁死所以涨停本身意味着这只股票当天已经走到最强的位置。但最强并不等于最一致。恰恰相反涨停价的每一次打开都是多空双方在极限定价位置上的直接碰撞。砸板的人觉得这个价格已经透支了明天的空间回封的人认为这只是一个中途站。一次打开就是一次分歧的释放。反直觉的地方来了**烂板往往比一字板更健康。**一字板虽然看着最强但全程没有换手前一天低位买入的人全部浮盈第二天一旦打开这些获利盘的抛压会挤在一起释放反而容易做出大面。而烂板在当天就把该走的获利盘洗出去了一部分筹码在涨停价附近完成交换持仓成本被抬高。次日继续上攻时抛压相对更小筹码结构更扎实。这个策略交易的其实就是分歧之后能否转一致的预期差。量化交易做烂板策略本质上是把这个行为抽象成可计算的特征用规则去寻找那些分歧充分、但共识正在重新形成的标的。1.2 烂板不等于弱势几个经典细分玩法的差异同样是烂板性质完全不同。按资金意图和市场位置可以分出至少三类玩法细分玩法典型形态核心买点适用环境弱转强昨日烂板或炸板今日竞价高开且早盘放量走强竞价高开确认后或早盘分时突破时情绪修复期、冰点反抽期烂板回封当日反复开板尾盘放量重新封板尾盘封板时或次日的溢价情绪上升期赚钱效应较好时炸板低吸当日炸板未回封次日缩量止跌次日分时企稳、不破前日低点时分批进个股有独立逻辑或处于主升中段这三类玩法风险收益特征差异很大。弱转强是胜率相对高但买点难抓的要求你必须在竞价或开盘后的极短时间内做出决策烂板回封是确定性最高但介入时间偏晚的你看到封板那一刻其实已经失去了相对最优的成本位置炸板低吸则是赔率最大但最容易买在半山腰的赌的是反包。量化落地时我建议先选一个细分方向做深。不要指望一套因子同时覆盖三种玩法它们的持仓周期、止损逻辑和入场时机完全不同。混合在一起参数优化会让你痛不欲生。1.3 为什么人工打板高手最终会转向量化实现烂板策略最早是游资和打板族的盘口绝活靠的是盯盘经验。但人工盯盘有几个天然瓶颈其一全市场每天触板、炸板的股票经常有几十上百只一个人能同时盯住5只就不错了其二情绪判断高度依赖盯盘者当时的状态连续亏损后容易动作变形其三人工交易的延迟是秒级的而烂板策略的入场窗口往往是以分钟甚至秒来计算的。量化实现解决的就是这三件事覆盖范围从5只扩大到全市场执行纪律从人治变成代码治决策延迟从几秒压缩到毫秒级。但这也带来新的问题——数据是否支持分钟级判断、回测是否会自欺欺人、实盘能否应对极端波动。这些我后面逐个展开。2. 数据是烂板策略的地基API选型与分钟级数据的坑2.1 日线数据做不了这个策略1分钟是最低配置有人问过我用tushare的日线接口能不能做烂板策略。答案是能做一个非常粗糙的版本——你只能知道这只股票当日涨停过、也炸板过但不知道首封时间是几点不知道炸板炸了几次更不知道回封发生在尾盘还是午后。而这些恰恰是烂板策略最核心的信息。没有日内数据策略等于盲人摸象。对烂板策略来说1分钟K线是最低配置。首封时间、炸板次数、回封时间、封单变化这些因子都能从1分钟级别的数据里提取出来。如果资金和存储条件允许5秒快照或逐笔委托数据会更好能精确算出封单金额的堆积速度、撤单率、不同价位的挂单分布但这些属于进阶选项先不做硬性要求。2.2 数据API怎么选研究环境、回测环境、实盘环境是三个问题很多新手经常问量化交易用的数据API最好的是什么。我的回答一贯是不存在一个API通吃所有场景你至少要面对三个不同问题——研究环境、回测环境、实盘环境。研究环境需要的数据宽、覆盖广、方便做因子分析。我常用akshare和tushare pro配合。akshare免费但接口稳定性一般适合抓取小批量数据做验证tushare pro有积分体系分钟数据和更细的历史数据需要积分门槛但数据质量相对靠谱。回测环境需要历史数据与撮合模型一致。聚宽、米筐这类平台自带完整的历史行情和回测引擎支持分钟级回测对新手最友好不需要自己维护数据库。缺点是策略写完后要迁出到其他环境时代码耦合度较高。实盘环境券商端的使用逻辑和研究端完全不同。ptrade是不少券商提供的量化交易终端支持Python语言可以对接实盘交易接口支持盘中定时运行策略适合把策略放到真实账户里跑。我的常规组合是研究阶段用akshare和tushare做因子验证回测在聚宽或自建向量化框架里完成实盘走券商提供的ptrade环境或自己用官方交易接口对接。三者之间做好数据口径的一致性校验避免出现研究用前复权、回测用不复权这种低级事故。2.3 涨停价与炸板识别的细节数据预处理里的隐形地雷很多人以为判断涨停很简单用收盘价等于涨停价就行。其实远没这么简单这里我踩过很多次坑。涨停价的计算规则主板10%、创业板和科创板20%、ST股5%。计算公式是round(前收盘价 * (1 涨跌幅限制), 2)保留两位小数遵循四舍五入。但注意不同行情软件对四舍五入的边界处理偶尔会有细微差异所以在判断涨停时我建议用一个容差而不是绝对相等high limit_price - 0.001。炸板的判断逻辑也不复杂在1分钟K线上如果某根K线的最高价触及涨停价但随后某一根K线的收盘价或最低价跌落涨停价下方就算发生了一次炸板。但从触及涨停到重新封板之间反复穿越的边界条件要写清楚否则炸板次数会统计错。这里有一个关键的预处理问题判断涨跌停必须使用不复权数据。复权数据会改变历史价格和涨停价的计算基准导致信号错乱。数据接口默认往往给的是前复权数据拿到后要先做转换。此外除权除息日的涨停价会基于新的前收盘计算如果数据里没有除权除息标记很容易把正常波动误判为炸板。3. 把盘口语言翻译成量化因子烂板策略的信号构造3.1 首封时间、炸板次数、回封时间三个核心时间因子数据准备好之后第一步是把盘口语言翻译成因子。我按重要性排序先讲三个时间类因子。首封时间即当日第一次触及涨停的时刻。这个因子反映的是资金做多意愿的强烈程度。一般来说开盘后30分钟内就触及涨停的股票说明有资金在早盘竞价和开盘抢筹阶段就果断动手做多意愿较强。但如果一只股票在连续大涨后出现秒板反而可能是加速赶顶的信号次日断板风险极大。所以首封时间要与股票所处的涨幅位置结合来看。炸板次数是最能体现分歧程度的因子。炸板次数越多说明多空双方的拉锯越剧烈筹码交换越充分。但炸板次数也不是越多越好——反复炸板超过5次还没有彻底封住说明卖方力量仍然很强这种板即使尾盘勉强封住次日也容易继续分歧。通常来说2到4次炸板的标的后续走强的概率相对较高。回封时间即最后一次封住涨停的时刻。这个因子的意义在于判断资金在尾盘阶段的表态。如果回封发生在早盘说明多方快速重新掌控局面如果回封拖到14:30以后说明全天大部分时间都在拉锯尾盘才勉强压制住空方。不同回封时间对应的次日预期差异很大这在实盘中有明显的统计规律。3.2 封单强度与换手率让因子具备量的维度时间因子回答的是什么时候发生量类因子回答的是以多大力度发生。封单金额占流通市值比例是我觉得最有效的一个量类因子。收盘时买一涨停价位上挂着的封单金额除以该股流通市值得到的比例能直观说明资金的封板决心。比例越高次日被砸开的概率越低。这个因子尤其适合区分真封板和假封板——有些股票盘中封单只有几百万这种板就是纸糊的一碰就碎。涨停前的换手率也很关键。它衡量的是资金在涨停之前已经完成了多少筹码交换。换手充分说明浮筹清洗得干净次日抛压小换手不足则说明还有很多获利盘没走次日一旦高开就会有卖压。我一般用开盘到首封时刻之间的成交量除以流通股本作为封板前换手率。当日成交额相对近20日的分位数这个因子用来过滤放量程度。烂板策略本质上需要量能配合缩量的烂板要么是流动性枯竭要么是主力自导自演的对倒都不适合参与。成交额分位在80%以上的标的参与价值更高。3.3 市场情绪过滤器烂板策略的天气系统同一只烂板股放在不同的市场环境下次日的表现可能天差地别。这就是市场情绪过滤器存在的意义。它不直接预测个股涨跌而是做一道该不该在今天开仓的总开关。我常用的情绪指标有三个昨日涨停股今日的平均涨幅衡量打板资金的赚钱效应、市场连板高度的中位数衡量市场对高位股的容忍度、当日盘中曾涨停但最终炸板的个股比例衡量市场承接力。这三个指标合成一个情绪温度温度高于阈值时才允许开仓低于阈值则强制空仓或大幅降低仓位。这个过滤器的价值在烂板策略上体现得尤其明显。烂板策略本身是逆着表面弱势去低吸或打回封如果市场环境不好资金接力意愿弱烂板次日大概率直接低开低走策略会连续吃面。我实测下来加上情绪过滤之后最大回撤能减少30%以上虽然会错过一部分机会但对实盘的体验提升是决定性的。4. Python实战一个可落地的烂板策略骨架与回测4.1 数据获取与涨停价计算代码下面给出一套可以直接改着用的代码骨架。数据获取我以akshare为例接口可能因版本更新而变化使用时以官方最新文档为准。import akshare as ak import pandas as pd import numpy as np def get_1min_data(symbol, date): 获取单只股票某一天的1分钟K线 df ak.stock_zh_a_hist_min_em( symbolsymbol, period1, start_datef{date} 09:30:00, end_datef{date} 15:00:00 ) if df is None or df.empty: return None df.rename(columns{ 时间: time, 开盘: open, 收盘: close, 最高: high, 最低: low, 成交量: volume }, inplaceTrue) df[time] pd.to_datetime(df[time]) return df[[time, open, close, high, low, volume]] def calc_limit_price(prev_close, board_type): 计算涨停价 board_type: main 主板 10%, gem 创业板/科创板 20%, st 5% if board_type main: ratio 0.10 elif board_type in (gem, star): ratio 0.20 elif board_type st: ratio 0.05 else: raise ValueError(unknown board type) return round(prev_close * (1 ratio) 1e-8, 2)需要注意akshare返回的时间列默认含日期我在这里只取了当天的分钟数据。实际做全市场扫描时你要先去获取一份每日的涨停股票池再对池中标的逐只拉分钟线而不是对全市场几千只股票全量拉取否则接口压力和数据量都吃不消。4.2 烂板识别与因子计算代码拿到分钟K线后核心任务是判断炸板并计算因子。这里给出一个核心函数def identify_rotten_board(df, limit_price): 从分钟K线中判断烂板并提取核心因子。 返回dict包含首封时间、炸板次数、末封时间、尾盘回封标志等。 if df is None or len(df) 10: return None # 触及涨停最高价在涨停价±0.001容差内 touch_limit df[high] limit_price - 0.001 # 封住涨停收盘价在涨停价±0.001容差内 sealed_limit df[close] limit_price - 0.001 # 找到所有触及涨停的连续片段 touch_idx np.where(touch_limit)[0] if len(touch_idx) 0: return None # 按连续区间分组 groups [] start touch_idx[0] prev touch_idx[0] for i in touch_idx[1:]: if i prev 1: prev i else: groups.append((start, prev)) start i prev i groups.append((start, prev)) # 首封时间 第一个触及涨停片段的起始时间 first_seal_idx groups[0][0] first_seal_time df.iloc[first_seal_idx][time] # 每个片段结束时是否封住以及片段之间是否出现收盘价脱离涨停 break_times 0 for k in range(len(groups) - 1): seg_end groups[k][1] next_start groups[k 1][0] # 如果前一段最后不是封住状态且两段之间有回落视为一次炸板 if not sealed_limit.iloc[seg_end] and (next_start - seg_end 1): break_times 1 # 末封时间 最后一个触及涨停片段的结束时间 last_seal_time df.iloc[groups[-1][1]][time] return { first_seal_time: first_seal_time, break_times: break_times, last_seal_time: last_seal_time, last_sealed: bool(sealed_limit.iloc[-1]) }这个实现是简化版但主体逻辑是可靠的。有一点我要特别提醒封住在分钟线上只能近似判断。真正的封板状态应该看涨停价上的委托量封单那是tick级数据才有的信息。分钟线用收盘价是否在涨停价上来近似已经足够提取大部分有效特征。4.3 交易信号与次日执行的规则设计因子算完后就该定义交易信号了。以烂板回封和弱转强两个方向为例简单说明信号的合成方式。当日盘后全市场扫描得到所有烂板标的按以下条件过滤首封时间在10:00之前炸板次数在2到5次之间末次回封时间在14:00之后且尾盘处于封板状态封单金额/流通市值 0.5%当日成交额分位 80%排除ST、新股、上市不足60日、停牌股次日策略按两种情况执行如果次日竞价高开0%到5%之间说明市场认可昨天的烂板回封开盘价附近建仓如果次日竞价低开超过3%则放弃避免承接弱势卖出条件我采用时间止损与价格止损结合买入后持有不超过3个交易日若期间最大浮盈达到8%以上则在分时走弱时止盈若跌幅超过5%则无条件止损。这个规则不复杂但执行纪律必须严格。4.4 回测中必须模拟的买不进与卖不出回测框架里最容易被忽略的是涨跌停制度对成交的约束。烂板策略买入的对象全是涨停过的股票而涨停股次日经常直接高开甚至一字板——你挂单买不进是常态。如果回测假设第二天开盘价一定能买到结果会显著偏乐观。我推荐的保守做法是如果次日开盘价直接封涨停即开盘价等于涨停价默认本次信号无法成交直接跳过。如果开盘价高开但未涨停则假设以开盘价成交同时考虑一个固定的滑点比例。这样做会牺牲一部分收益但换来的回测结果与实盘的一致性远远好于理想化模型。卖出端同理。如果持仓期间股价触及跌停不能假设你一定能卖出去保守处理是等到跌停打开后的价格再卖或者直接以次日收盘价为准。这些约束加上之后你会发现原本漂亮的多因子策略年化收益可能打个七折。这才是真实市场。5. 回测曲线会骗人烂板策略的过拟合与成本陷阱5.1 样本少、参数多烂板策略天生容易过拟合烂板策略和趋势策略有一个本质区别样本量。趋势策略一天能在几千只股票上产生信号烂板策略一年下来真正有效的信号可能只有几百个。样本少参数一多就很容易把回测曲线调得无比漂亮但每一条漂亮都是对历史噪声的精确拟合而不是对市场规律的捕捉。我自己的经验是这类策略的参数越少越好。宁可牺牲一点回测的完美度也要保证每个参数背后都有一条清晰的经济逻辑支撑。如果一个参数你不能用一句话解释清楚它捕捉了什么市场行为那它就不该出现在模型里。做参数敏感性测试也很有必要把关键参数上下浮动20%观察回测结果是否大幅恶化。如果稍微一动参数收益就大幅滑坡说明策略已经过拟合了。稳健的参数应该在一个合理区间内都能表现出稳定的收益特征。5.2 幸存者偏差、未来函数和除权日的连环坑统计上的坑一个比一个隐蔽。幸存者偏差是最常见的回测时如果使用当前时点的股票列表去拉历史数据那些已经退市的股票就不会出现在样本里但历史上它们确实存在而且其中有大量是烂板策略的失败案例。正确的做法是使用历史时点的成分股数据快照这个在tushare和聚宽上都有专门的接口。未来函数是另一个重灾区。我在早期版本里干过一件蠢事用当日全天的分钟数据来识别烂板回封然后假设当日尾盘封板那一刻就买入这本身没问题问题在于我同时把当天的封单金额数据也作为次日的买入依据——但封单金额是收盘后才知道的数据。虽然只差一个交易日但在高频场景下这种未来数据会让回测结果失真严重。还有除权日的问题。前复权数据在除权日会调整历史价格导致涨停价的计算依据漂移。我建议做因子计算时统一用不复权数据每次计算涨停价都从当天实际的前收盘价出发不使用复权后的连续价格序列。5.3 手续费与冲击成本高频换手下被低估的杀手烂板策略的持仓周期通常只有1到3天年化换手率轻松超过2000%。在这种换手率下交易成本对收益的侵蚀是致命的。算一笔账A股佣金双边按万2.5计算卖出印花税按万5计算2023年8月起减半后的水平再加上滑点单次完整交易的总成本至少在万12到万25之间。如果按每月换手500%计算一年下来交易成本就能吃掉总资金的6%到12%。对年化收益目标在20%到40%的策略来说这已经是非常大的损耗了。所以回测中手续费和滑点一定要从紧设置。我通常用单边千1.5的手续费加滑点模型做底线压力测试只有在这个成本假设下仍然盈利的策略才有上实盘的价值。另外冲击成本也值得关注烂板标的通常是中市值股票买一和卖一的挂单量有限大资金进场时冲击成本不可忽视。个人资金的容量上限通常在三百万到一千万之间超过这个区间信号会自我衰减。6. 实盘执行才是分水岭仓位、止损与策略失效监测6.1 开盘三十秒决定收益执行速度与滑点控制烂板策略最关键的执行窗口在次日开盘的30秒内。竞价一结束全天最优的介入价格基本就确定了。人工下单往往要经过看一眼行情、填价格、点确认这个流程少说三四秒遇到网络波动可能十几秒就过去了。量化下单可以把这个过程压缩到毫秒级但这需要你预先写好交易脚本并提前把仓位的预算和标的清单准备好。我建议用限价单而不是市价单。市价单虽然成交快但在开盘瞬间流动性不足时很容易吃到极端价。限价单可以设定一个可接受的最高买入价比如开盘价上方0.5%以内挂上去之后让它排队成交。如果价格迅速脱离你的限价区间说明这波行情比预期强放弃就是了没有必要追。6.2 单票仓位与组合约束烂板策略不是满仓梭哈烂板策略的胜率普遍只有30%到45%比大多数人想象的低得多。它赚钱靠的不是高胜率而是大赚小亏的盈亏比——对了能赚10%以上错了只亏4%到5%。在这种胜率分布下单票梭哈基本等于自杀因为你根本扛不住连续5次亏损。我实盘的仓位规则是单票最大仓位10%同时持仓不超过5只单日新开仓总仓位不超过30%如果情绪过滤器显示市场温度下降单日新开仓总仓位降档到10%以内。这套规则不是为了博收益而是为了保证在连续亏损的情况下账户依然有充分的子弹可以打。另外买入前一定要检查标的的流动性。日均成交额低于5000万的股票即使信号再完美也要放弃。这个约束会过滤掉一部分机会但能避免你在极端行情中被套在里面出不来。6.3 策略失效的识别与退出机制所有短线策略都有生命周期烂板策略也不例外。市场参与者结构变化、交易制度调整、同质化资金涌入都会让一个曾经盈利的策略逐渐失效。关键是你要有一套量化的失效监测机制而不是靠感觉。我的做法是每月做一次滚动评估把策略近30天的实盘收益和同期回测收益对比如果连续两个月的实盘收益比回测收益低20%以上就要开始排查——是参数失效了还是市场风格切换了还是执行环节出了问题。如果连续三个月跑不赢基准模型不管回测曲线上过去多漂亮我都会直接停止该策略而不是抱着侥幸心理继续开仓。比起在失效的策略上死扛更务实的做法是同时维护多个低相关性的子策略比如烂板回封和炸板低吸各跑一套信号彼此之间严格独立。当一个策略进入观察期时另一个还能继续贡献收益账户整体不至于出现断崖式回撤。我做烂板策略最大的体会是这个策略真正的门槛不在回测里而在实盘中。回测曲线上的每一个参数背后都是真金白银的盘中决策。如果你没有一套严格的仓位管理、止损纪律和失效退出机制哪怕模型再先进也会被连续亏损时的情绪冲动摧毁。建议新手先用模拟盘跑三个月老老实实记录每一笔信号的执行情况先把纪律练出来再考虑上真金白银。
返回列表