
做量化交易的人大部分时间都在研究趋势、动量、均线这些东西但我今天想聊一个A股特有的、带点“野路子”色彩的短线高盈亏比策略——烂板策略。如果你在股票社区混过应该听过“打板”这个词就是专门买涨停板。而烂板策略是打板体系里一个非常特殊的分支专门盯那些涨停板被砸开过、又封回去的票。听起来是不是有点反常识涨停被砸开说明抛压大、筹码松动凭啥还要去买这里面的门道恰恰是短线资金博弈最精彩的地方。这篇文章我会从策略逻辑讲到Python量化实现再到数据API选型和回测坑点把我自己实操中踩过的坑和总结出来的经验全部摊开来说。内容比较硬核适合已经有Python基础、对量化交易有初步概念同时愿意研究A股短线交易机制的读者。如果你只是想抄一段代码就去实盘那这篇文章不适合你但如果你想搞明白“烂板为什么能赚”“怎么用数据把它刻画出来”这篇文章应该能让你少走不少弯路。1. 烂板策略的本质为什么被砸开的涨停反而是机会1.1 从打板战法到烂板先搞清楚游戏规则要理解烂板策略得先理解打板。A股有涨跌停制度主板个股单日涨幅上限是10%创业板和科创板是20%。一只股票涨到涨停价后如果买盘足够强就会在涨停价上堆出巨量买单这就是“封板”。封住之后想买的人只能排队等前面的人撤单或者卖单砸出来这就是“排队”。打板客的核心逻辑是涨停板代表当日最强的市场共识今天能封住涨停说明有资金在外面拼命想买却买不到那么明天大概率还有惯性溢价高开甚至继续涨停的概率很大。所以打板客会在涨停价排队买入赌的就是次日溢价。但这里有个很现实的问题真正强势的票往往一字板或者秒板根本排不到。你打开交易软件看到某只股票涨停了去排队前面可能压了几千万手的买单轮到你的概率微乎其微。而你能买到的涨停板多半是那种封板不坚决、被反复砸开的——这就是“烂板”。烂板策略做的正是这个“别人不敢买、但你能买得进”的窗口。它本质上是在赌一个股票虽然盘中被砸开过多次但最终多方依然把涨停封住了说明多空博弈后多方赢了。次日如果市场情绪配合这种票会走出“弱转强”溢价非常可观。这就是烂板策略的底层逻辑——分歧转一致。1.2 烂板是怎么形成的散户看到的是恐慌量化看到的是数据一根烂板K线背后其实是三种力量的博弈。第一种是获利盘出逃。股票从底部涨上来短线浮盈的人看到涨停被砸开第一反应是落袋为安于是蜂拥卖出砸出天量卖单。第二种是套牢盘解套。如果这只股票前期跌了很久涨停价正好触及前期套牢筹码密集区解套盘会集中卖出形成巨大抛压。第三种是主力主动洗盘。主力资金想在启动前把不坚定的浮筹洗出去故意撤掉涨停封单、砸几笔大单制造恐慌让散户交出筹码然后再重新封板。这三种力量叠加就出现了盘口上反复“打开-回封-再打开-再回封”的拉锯状态。很多散户看到烂板会恐慌因为分时图上的每一次砸开都像末日降临。但换个角度想如果最终封住了说明买入力量扛住了这么多抛压这个位置已经完成了换手。浮筹被清洗干净后次日拉升的阻力反而更小。这就是为什么烂板之后经常出现“弱转强”的隔日大涨因为今天恐慌卖出的筹码已经变成了新主力手里相对干净的底仓。从量化角度我们要做的不是揣测主力的意图而是把“烂板”这个模糊的概念拆解成可计算的指标是否触及涨停、涨停后是否开板、开板几次、最终是否回封、封单大小、换手率高低。把这些指标转换成规则就成了一个完整的量化信号体系。1.3 不是所有烂板都值得做先立几条硬规矩烂板策略听起来很美好但如果你把每一个“盘中破板又回封”的票都买入大概率会亏得连裤衩都不剩。烂板也分强弱质量差的烂板往往只是出货的假动作。我把自己实操中总结的几条硬性过滤标准放在前面后面量化部分还会再展开优先做首板烂板回避高位烂板。一个股票如果是第一个涨停就出现烂板次日走弱的容忍度高但如果已经连续涨停在高位出现烂板大概率是资金出货这种票坚决不碰。开板次数控制在3次以内。开板次数越多说明抛压越重封板力度越弱。超过3次还硬做就是在赌命。关注回封的速度。第一次开板后如果在很短时间内就被大单重新封回去说明承接力度强反之如果磨磨蹭蹭半天封不回去说明多方根本没有决心。换手率不能太高也不能太低。换手太高比如超过20%可能是天量出货换手太低比如低于3%说明市场关注度不够次日溢价空间有限。这些标准不是凭空拍脑袋定的都是我从几千条历史烂板数据里统计出来的。量化交易的核心恰恰在这里把盘感变成规则把规则变成代码。2. 把烂板策略翻译成量化逻辑信号定义与过滤条件2.1 核心信号一次涨停、至少一次开板、最终封回把烂板策略转化成计算机能理解的逻辑第一步是定义“什么是触发信号”。我把这个过程拆成三个必要条件第一当日最高价必须触及涨停价。注意是触及不是收盘价必须在涨停价。很多股票盘中冲上涨停又砸下来收盘可能只涨了6%但这种“摸板”动作本身就是资金意愿的表达。不过对于烂板策略我们同时也要求最终收盘必须封在涨停价上因为只有真正封住的票次日才有走强的预期。第二封板之后至少经历一次开板。这是“烂”的定义所在。如果一只股票开盘直接涨停板全天像焊死一样没有打开过那叫“死板”不是烂板排队也买不进。所谓烂板一定是封板状态被中断过然后重新封回。这个中断在数据上体现为某个分钟K线收盘价低于涨停价且之前和之后都有收盘价等于涨停价的分钟K线。第三收盘时必须处于封板状态。这是信号成立的最终确认条件。在T1制度下当天买入的最早也要次日才能卖出如果尾盘都没能封住板说明多方连最后的脸面都保不住了次日大概率低开这种票根本没有参与价值。这三个条件合在一起就是我定义的核心信号。上面这段逻辑如果用人眼看分时图几秒钟就能判断出来但要让计算机每天扫描全市场5000多只股票你需要把判断过程拆得非常明确尤其是“封板状态”的判定。A股的实际涨停价不是简单的前收盘价乘以涨停比例而是四舍五入到分位比如前收盘10.03元的涨停价就是11.03元而不是11.04元。这些细节在代码里必须处理到位否则你扫出来的信号和实际盘面会差一截。2.2 质量过滤开板次数、封单强度、换手率的量化标准核心信号扫出来之后大概每天能有十几只甚至几十只烂板票但这里面大部分都是“垃圾板”。我前面提到的几条硬规矩现在就要翻译成可计算的过滤条件。第一个是开板次数。我用分钟级数据统计股票从触板到收盘封板状态被打破了几次。阈值我一般设成3超过3次直接剔除。逻辑很简单每一次开板都意味着一次抛压释放开板次数越多说明卖方的力量越强最终的封板越不牢靠。回测数据也支持这一点开板次数1次的票次日平均溢价明显高于开板次数5次以上的票。第二个是回封强度。我通常用两个子指标衡量一是回封耗时即每次开板后用了几根分钟K线才重新封回耗时越短越强二是封单金额用日线级或分钟级数据里涨停价上的买一金额估算封单金额越大说明资金护板的决心越强。封单金额不好直接从普通行情API获取我一般用“涨停价附近的大单成交比例”作为代理指标实战效果也还不错。第三个是换手率。换手率我控制在3%到20%之间。太低了说明股票没什么人气次日没有接盘资金太高了说明筹码已经大面积易手很有可能是主力借涨停出货。注意这里说的换手率是全天的换手不是涨停那一刻的瞬时换手因为在数据上瞬时换手很难精确还原。第四个是市值和板块过滤。我一般剔掉总市值低于30亿的票因为小市值票容易被资金恶意操纵信号质量极不稳定。同时如果当日所属板块整体表现低迷我也会降低该板块内烂板票的优先级。板块过滤在量化上实现起来比较麻烦涉及行业分类数据的引入我会在后面的代码部分给出一个简化版本。2.3 环境过滤炸板率与市场情绪决定了策略当天能不能做做短线的人都懂一个词——情绪周期。市场好的时候涨停板封得牢烂板后市场会给你修复溢价市场差的时候涨停板就是最大的空头陷阱今天封住明天照样跌停给你看。所以烂板策略不能焊死在自动驾驶模式下必须引入环境过滤机制。我用的一个核心环境指标是“全市场炸板率”。所谓炸板是指盘中曾经涨停但收盘没能封住涨停的股票。炸板率就是当日炸板数量除以当日曾涨停的总数量包括最终封住的再乘以100%。炸板率越高说明市场承接力越差打板资金亏钱效应越明显此时任何烂板策略的胜率都会大幅下降。我自己回测下来炸板率低于30%的时候烂板策略的次日正收益概率能到55%以上而炸板率超过50%的时候胜率会跌破40%这时候无论信号多完美都应该直接跳过。所以我把炸板率30%作为开仓闸门炸板率在30%到50%之间降低仓位超过50%直接空仓这个规则也写进了回测框架。同时我也会参考当日涨停家数如果全市场涨停家数少于30家说明市场投机情绪极度冰点同样直接过滤掉所有信号。3. 数据与工具选型量化交易数据API到底怎么选3.1 数据API对比Tushare、AkShare、聚宽、Wind谁更适合做分钟级策略烂板策略对数据的要求不算低——它需要全市场的分钟级行情数据逐日扫描数据量大、要求字段多。数据API的选型直接决定了你写代码的效率和回测的可靠性。Tushare Pro目前散户圈子里用得最多的数据源积分制。日线数据免费接口就能拿但分钟数据和盘口数据需要比较高的积分门槛不算低。优点是数据质量稳定字段规范文档清晰适合搭建正式的量化工程。AkShare完全开源的Python财经数据接口免费靠爬虫抓取公开数据。优势是快、全、零门槛劣势是接口稳定性一般数据偶尔会有缺失或延迟。做烂板策略扫描器这种对延迟不敏感的研究场景AkShare完全够用但如果你要实盘高频我强烈不建议。聚宽/米筐/RiceQuant这类的量化平台自带数据、回测、模拟盘一整套生态。分钟数据可以直接用回测引擎也很成熟适合不喜欢折腾数据管道的朋友。缺点是策略代码被绑定在平台上换平台要重写。Wind/Choice机构级别的数据终端数据质量和响应速度都没话说但价格极其昂贵个人用户基本劝退。我个人目前的工作流是研究阶段用AkShare快速拉数据做信号原型验证确认逻辑没问题后切换到Tushare Pro拉正式的历史分钟数据做精细回测。这算是一个性价比很高的组合但如果你的预算允许直接上聚宽或米筐这类平台能省掉很多数据清洗的精力。3.2 分钟级数据和盘口数据的重要性烂板策略的信号判定最少需要1分钟级别的K线数据。用日线数据你只能看到“收盘价接近涨停价”但完全无法判断这中间是否经历过多轮开板回封。而开板次数恰恰是这个策略最核心的信号维度。如果你有条件拿到Level-1快照甚至是逐笔成交数据还能做更精细的封单量分析。不过我的经验是对于绝大多数个人量化玩家1分钟K线的粒度已经足够识别烂板信号了因为A股的涨停封单往往持续数分钟甚至数小时1分钟级别的状态切换足够捕捉到开板回封的节奏。逐笔数据的精度提升对最终收益率的边际影响没有想象中大却会带来极其庞大的数据存储和计算成本。这里必须多说一句复权问题。判断某只股票是否涨停用的是不复权的价格只要处理了复权股价数值就会被向调整导致“价格是否达到涨停价”的判断失真。所以拉数据时如果API提供复权选项一定要选择不复权。等计算收益率的时候再根据你实际持股周期选择前复权或后复权做净值计算。很多新手在这里栽跟头拿前复权数据判断涨停价结果信号漏掉一大半。3.3 数据清洗与停牌退市处理数据源的原始数据不能拿来直接用必须先做一轮清洗。我遇到的常见问题包括新股上市初期涨跌停规则不同主板44%首日涨幅限制、无涨跌幅限制的注册制新股次新前5日ST股涨跌幅限制是5%这些都需要在扫描前单独标记。用统一的中小板10%涨停规则去套所有股票扫描结果必然失真。停牌数据也容易踩坑。停牌股票当天没有行情数据但扫描器可能因为拉不到数据就当它不存在回测时如果买了停牌票资金就被锁住无法交易。我在代码里专门做了过滤当天成交量为0或者成交额为0的股票直接跳过。退市风险股ST板块我干脆整体剔掉不给它污染数据池的机会。4. Python实现从信号扫描到回测框架搭建4.1 环境准备与依赖安装代码部分我用Python 3.9版本演示核心依赖库是pandas、numpy、akshare。如果你后续要换Tushare Pro只要把数据获取层替换掉就行信号判定和回测逻辑都是通用的。安装命令很简单pip install pandas numpy akshare另外提一句AkShare的接口名称偶尔会变动如果某一天import或调用报错先去官方文档看接口是否更新。这种底层数据源的维护成本是免费的代价跑批脚本里最好加一层异常捕获拉数据失败就重试而不是直接崩溃退出。4.2 核心代码烂板信号扫描器的完整实现先写一个获取分钟数据的函数。AkShare里获取A股分钟级行情的接口是stock_zh_a_hist_min_em注意需要指定交易日参数。全市场逐只拉取分钟数据非常慢通常的做法是先用日线数据做一轮粗筛只对当日最高价接近涨停价比如至少上涨8%以上的股票拉分钟数据做细筛这样能节省90%以上的请求时间。import akshare as ak import pandas as pd from datetime import datetime def get_daily_universe(trade_date): 获取全市场日线数据做粗筛 df ak.stock_zh_a_spot_em() df df[df[代码].str.startswith((60, 00, 30))] # 排除北交所 df df[~df[名称].str.contains(ST)] # 剔除ST df[涨幅] (df[最新价] - df[昨收]) / df[昨收] * 100 # 粗筛涨幅8%以上接近涨停 df df[df[涨幅] 8] return df[[代码, 名称, 最新价, 昨收]] def get_minute_data(symbol, trade_date): 获取单只股票1分钟K线 df ak.stock_zh_a_hist_min_em( symbolsymbol, period1, start_datetrade_date, end_datetrade_date, adjust # 不复权 ) if df.empty: return None df[时间] pd.to_datetime(df[时间]) df df.rename(columns{收盘: close, 开盘: open, 最高: high, 最低: low}) return df接下来是烂板信号判定函数。这段是策略的核心我把涨停价判定、开板次数统计、最终封板状态都封装进去。注意涨停价要按昨收价四舍五入到分创业板和科创板按20%计算主板按10%计算。def check_lanban_signal(minute_df, prev_close, limit_ratio0.10): 判断一只股票当日是否为烂板信号 prev_close: 昨收价 limit_ratio: 涨停比例主板0.10创业板/科创板0.20 if minute_df is None or prev_close 0: return None limit_price round(prev_close * (1 limit_ratio), 2) minute_df minute_df.copy() # 判断每根分钟K线是否处于封板状态 # 简化处理分钟收盘价达到涨停价视为封板状态 minute_df[is_limit] (minute_df[close] limit_price) # 判段当日最高价是否触及涨停 if minute_df[high].max() limit_price: return None # 统计开板次数从封板到破板算一次开板 state 0 # 0-未封板 1-封板 open_count 0 limit_touch_count 0 for _, row in minute_df.iterrows(): if row[is_limit]: limit_touch_count 1 if state 0: state 1 else: if state 1: state 0 open_count 1 # 收盘必须封板最后一根K线收盘价达到涨停价 final_limit minute_df[is_limit].iloc[-1] if not final_limit: return None return { symbol: minute_df[symbol].iloc[0] if symbol in minute_df.columns else , limit_price: limit_price, open_count: open_count, limit_touch_count: limit_touch_count, last_close: minute_df[close].iloc[-1], is_lanban: 0 open_count 3 # 开板1-3次 }上面这段代码有个地方需要说明我用“分钟收盘价是否达到涨停价”近似判断封板状态在实盘中可能会和真实的封板状态有偏差。一个更好的方案是用封单量来判断——涨停价上有真实买单挂着才算封板这需要Level-1快照数据。但对于历史回测来说分钟收盘价的近似已经基本可用。完整的扫描器主程序就是对全市场做循环粗筛出来的票逐只拉分钟数据然后调用信号判定函数。这里跑一轮大概需要几分钟到十几分钟取决于当日候选股票数量。为了不让数据请求频繁失败我一般会加一个简单的延时和重试机制。import time def scan_lanban(trade_date): 全市场扫描烂板信号 universe get_daily_universe(trade_date) signals [] for _, row in universe.iterrows(): symbol row[代码] try: minute_df get_minute_data(symbol, trade_date) signal check_lanban_signal(minute_df, row[昨收], limit_ratio0.10) if signal and signal[is_lanban]: signal[symbol] symbol signal[name] row[名称] signal[open_count] signal[open_count] signals.append(signal) time.sleep(0.3) # 控制请求频率 except Exception as e: # 数据请求失败跳过该股票继续 continue return pd.DataFrame(signals)4.3 回测框架把烂板信号跑成收益曲线信号扫描只是第一步真正的考验在回测。我写了一个极简回测框架核心逻辑是每个交易日扫描出烂板信号次日以开盘价买入持有到当日尾盘卖出也就是持有1个交易日并记录收益。T1制度下当天买入不能当天卖所以最早卖出的时机就是买入日的次日。回测中几个关键参数要设置好手续费佣金按万2.5双边收取卖出时额外收取千1的印花税这两项都要算进成本。滑点烂板票的特点是次日波动巨大开盘价附近成交量放大实际成交价不可能刚好等于开盘价我按0.2%的固定滑点估算。仓位单只股票买入金额不超过总资金的20%余下现金闲置或做逆回购。涨停买入限制次日如果股票直接一字涨停开盘实际上根本买不进去回测时必须剔除这种情况否则收益会虚高。class LanbanBacktest: def __init__(self, init_capital1_000_000, fee0.00025, stamp0.001, slippage0.002): self.capital init_capital self.init_capital init_capital self.fee fee self.stamp stamp self.slippage slippage self.positions {} # symbol - {qty:, cost:, buy_date:} self.returns [] def buy(self, symbol, price, date, name): if symbol in self.positions: return # 已持仓不再重复买入 max_amount self.capital * 0.2 qty int(max_amount / (price * (1 self.slippage)) / 100) * 100 if qty 0: return cost qty * price * (1 self.slippage) fee_amount cost * self.fee if cost fee_amount self.capital: qty int((self.capital - fee_amount) / (price * (1 self.slippage)) / 100) * 100 cost qty * price * (1 self.slippage) fee_amount cost * self.fee self.capital - (cost fee_amount) self.positions[symbol] {qty: qty, cost: cost, buy_date: date, name: name} def sell(self, symbol, price, date): if symbol not in self.positions: return pos self.positions.pop(symbol) revenue pos[qty] * price * (1 - self.slippage) fee_amount revenue * (self.fee self.stamp) net_revenue revenue - fee_amount ret (net_revenue - pos[cost]) / pos[cost] self.capital net_revenue return ret然后是一个最简单的回测主循环把历史每一天的信号都喂进去。这里我只展示思路实际运用时你还需要准备一个“股票次日开盘价和收盘价”的价格映射表可以用Tushare批量获取。def run_backtest(signal_dict, price_data, start_date, end_date): bt LanbanBacktest() trade_dates get_trade_dates(start_date, end_date) for date in trade_dates: # 之前买入的股票今天卖出持有一天 for symbol in list(bt.positions.keys()): if symbol in price_data[date]: sell_price price_data[date][symbol][close] ret bt.sell(symbol, sell_price, date) if ret is not None: bt.returns.append({date: date, symbol: symbol, ret: ret}) # 今天的烂板信号明天开盘买入 if date in signal_dict: for signal in signal_dict[date]: next_date get_next_trade_date(date) if next_date not in price_data: continue if signal[symbol] in price_data[next_date]: open_price price_data[next_date][signal[symbol]][open] close_price price_data[next_date][signal[symbol]][close] # 次日一字涨停开盘涨停且收盘涨停跳过 if close_price signal[limit_price] and open_price signal[limit_price]: continue bt.buy(signal[symbol], open_price, next_date, signal.get(name)) # 计算净值曲线 final_capital bt.capital sum( pos[qty] * price_data[bt_pos_date][symbol][close] for symbol, pos in bt.positions.items() for bt_pos_date in [pos[buy_date]] if symbol in price_data.get(bt_pos_date, {}) ) return final_capital / bt.init_capital, bt.returns这段代码不追求极致性能重点是清晰展示回测的骨架。实际跑了你会发现回测结果很大程度上取决于你如何处理“买不进”和“卖不出”的边界情况。经验是回测里宁可多扣一点把滑点调大、把买不进的情况多剔除一些出来的结果虽然难看但更接近实盘心态也会更稳。4.4 ptrade平台对接与实盘注意事项研究验证过逻辑之后下一个问题是怎么接实盘。如果你用的是券商的量化交易终端比如ptrade好消息是ptrade自带分钟级行情接口和实盘交易接口坏消息是它的API和本地Python环境不完全一样代码需要做一层适配。ptrade的核心函数是get_price()获取行情、order()下单单位是股。和本地AkShare/Tushare的代码相比最大的区别是ptrade的数据获取和交易都在券商的服务器上完成延迟很低适合做开盘时段的实时扫描和下单。但我个人的建议是烂板策略本身适合“盘后选股、次日执行”把信号扫描放在收盘后做形成候选列表第二天开盘前确认一下环境指标比如竞价阶段埋单量再手动或半自动完成下单。这样做比全自动的盘中追价要稳健得多因为你有了足够的时间去做质量过滤。实盘还有一个绕不开的问题涨停价附近的成交撮合概率。就算你识别到了信号并决定次日买入开盘如果直接高开5%以上你是否还愿意追这其实是主观交易的一部分。我的做法是在策略里加了一条“开盘涨幅超过5%则放弃买入”的规则把追高风险前置拦截掉。5. 常见问题与排查技巧实录5.1 信号数量太少是不是代码写错了很多朋友第一次跑完扫描器发现一个月总共才出十几个信号第一反应是代码bug。确实烂板策略本身就是一个低频策略信号数量受市场环境影响极大。牛市活跃期可能每天有20只以上的烂板信号熊市冰点期一周都出不了几个。我的排查建议是三步走。第一步先看粗筛环节有没有问题比如说涨幅阈值设得太高把本该进入细筛的股票过滤掉了可以把粗筛的涨幅阈值降到5%验证一下。第二步检查涨停价的计算是否有误特别是昨收价拿错、复权处理不当会直接导致判断偏差。第三步把扫描结果和当日实际盘面做对比随机抽几只票打开分时图人工核对看看开板次数统计是否准确。如果人工核对无误那就是市场环境本身的原因不是代码问题。5.2 回测收益很漂亮实盘却亏钱问题出在哪这是量化交易最经典的“陷阱”。回测很爽、实盘打脸原因我总结过几个第一回测中没有合理对待“买不进”和“卖不出”的情况。烂板次日如果高开秒板你的买单根本成交不了但回测里你假设自己买到了这就凭空多出一大截收益。我在前面的代码里已经处理了次日一字板买不进的情况但更隐蔽的是“开盘后快速拉升、成交概率极低”的票回测里依然会被买入。第二滑点估计严重不足。烂板票次日开盘半小时内的波动剧烈买盘卖盘价差很大你实际成交的价格可能比开盘价高出1%甚至2%。用固定0.2%的滑点显然太乐观我建议回测时至少按0.5%到1%设置滑点观察收益曲线是否还能维持正向。第三情绪环境过滤失效。市场热点切换、监管环境变化都可能让原本有效的策略逻辑暂时失效。烂板策略本质上是赚情绪修复的钱而情绪本身就是周期性的。你可以把炸板率、涨停家数等情绪指标也画在收益曲线旁边看看策略失效的区间是不是正好对应情绪冰点期。5.3 烂板策略的容量限制与资金管理最后聊聊资金容量。烂板策略的标的通常是小市值中低价股日成交量不大资金容量天然受限。我实盘的感觉是单只票的买入金额超过300万以后冲击成本会非常明显基本就是自己在给自己抬轿子。个人投资者资金量在100万以内比较舒服超过500万策略效率和收益曲线都会明显下滑。所以资金管理上我的纪律是单票仓位不超20%单日新开仓不超过总资金的50%当日持仓组合最多5只票。如果当天全市场环境指标不好炸板率偏高我就把单票仓位降到10%宁可少赚也不硬扛。另外止损纪律必须前置我一般设定次日跌破买入价5%坚决止损。烂板策略的盈亏比本来就依赖于少数大肉票如果不在错误方向上及时止血几笔大亏就能把整个月的收益全部回吐。还有个细节是我跑完一轮完整回测之后习惯把收益分布画出来看一眼。烂板策略的收益分布非常偏态大部分信号只能赚个1%到2%少部分能赚到5%以上同时也有相当比例的亏损单。如果你发现自己的收益分布整体偏右那策略逻辑大概率是对的如果整体偏左说明你的过滤条件还不够严格需要回到第二节重新调整信号定义。玩法上可以继续挖掘的还有不少比如把烂板策略和次新股叠加或者把开板次数的阈值做成动态参数跟随市场情绪自适应调整。这些方向我自己还在摸索中。量化交易有趣的地方就在这里策略从来不是写完就结束了而是你每个阶段都会有自己的新认知然后把这些认知持续迭代到模型中。