|一个量化小白的真实项目复盘:如何在9:30开盘前,用机器学习找到今天最可能涨停的票?
你有没有过这种经历?
早上9:15打开炒股软件,看着竞价数字跳来跳去,心里直打鼓:这只票竞价涨了3%,是主力试盘还是诱多?那只票突然放量,要不要追?
等你犹豫完,9:30一到,好票已经封板,烂票直接跳水。
我也有同样的困惑。于是,我用了半年时间,做了一个能自动在早盘竞价阶段“算”出涨停概率的模型。
今天不吹牛、不卖课,就把这个项目的真实思路、因子设计逻辑、模型怎么训练的、实战效果如何,全部摊开来讲。
希望你看完,至少能回答一个问题:早盘那10分钟,到底该看什么?
一、为什么死磕“早盘竞价”?
A股的早盘集合竞价(9:15–9:25),是全天资金博弈最激烈的10分钟。
- 9:15–9:20:可以挂单也可以撤单,很多“假单”出没
- 9:20–9:25:只许挂不许撤,真金白银开始亮牌
- 9:25:产生开盘价,全天走势的第一块拼图
能不能涨停,往往在这10分钟里就有蛛丝马迹。
但问题是:竞价数据又短又杂——竞价涨幅、委买委卖、未匹配量、量比……光看一两个指标很容易被骗。传统的技术分析、凭感觉打板,胜率越来越低。
所以我想:能不能让机器学习,从过去几百天的数据里,自己学会识别哪些竞价信号才是真正有效的?
二、模型长什么样?——一个“双引擎”打分系统
我把这个模型做成了一个每天早上9:28自动输出选股列表的小程序。
它的核心很简单:
输入:56个竞价相关的因子(后面会讲大类)
输出:每只股票今天涨停的概率(比如0.88表示88%概率)
具体结构:
- 两个基模型:XGBoost + CatBoost(你可以理解为两个风格不同的“专家”)
- 融合权重:CatBoost占85%的决策权重,XGBoost占15%
- 涨停标准:当日涨幅 ≥ 9.85%(剔除ST和创业板/科创板的特殊规则)
为什么这么配?
回测发现,CatBoost在“没见过的新数据”上更稳,XGBoost则提供一些不同的视角。两者搭配,比单独用任何一个都准。
三、56个因子:我们到底在算什么?
这是模型的核心,也是我们最花心思的地方。出于策略保密,我不能列出全部56个因子,但可以告诉你它们的五大分类,以及每类里的1-2个典型例子——这些思路你平时看盘也能用上。
第一类:今日竞价数据(约15个因子)
直接从当天9:15–9:25的竞价盘口中获取。
举例:竞价涨幅、竞价量比、:4委买委卖。
第二类:昨日及近期行情(约12个因子)
用来判断股票的“股性”和趋势状态。
举例:昨日涨跌幅、昨日实际换手率。
第三类:技术指标(约10个因子)
常见的均线、RSI、MACD等,但做了针对性的参数调整。
举例:MA5与MA20的比值、RSI6与RSI12的对比。
第四类:历史股性与资金痕迹(约8个因子)
捕捉“这只票过去爱不爱涨停”、“主力最近有没有吸筹”。
举例:前15日内涨停次数、前3日大单净量。
第五类:运算衍生与交叉因子(约11个因子)
把上面几类组合起来,形成1+1>2的信号。
说句大实话:这56个因子不是越多越好。真正起作用的可能不到30个,但正是因为做了大量冗余和交叉验证,模型才不容易过拟合。具体哪些因子权重最高——这部分涉及核心机密,就不在这里公开了。
四、数据怎么来的?——数据查询与清洗
数据来自问财、QMT、Akshare等,通过接口自动获取。每天的查询条件包括:主板非ST股、流通市值15-300亿、竞价涨幅小于8%、上市超过100天等。
清洗过程(纯文字描述,无代码):
第一步,根据查询日期自动区分“今日”与“昨日”数据。比如,查询当天的开盘价会被标记为“今日开盘价”,查询前一天的则标记为“昨日开盘价”。
第二步,处理异常值。使用训练集的中位数填充缺失值,并用分位数方法(比如1%和99%分位数)把极端值拉回到合理范围。所有涉及除法的因子都会加上一个极小值防止除零错误。
第三步,特征标准化。将问财返回的各种列名(如“前5日平均成交量”或“前5个交易日的平均成交量”)通过关键词模糊匹配,统一成标准特征名。如果出现重复列,按日期排序并自动添加后缀区分。
五、训练过程:让模型“见过世面”
我用的是 2022年至今约500个交易日的数据,每天200–300只符合条件的股票。
涨停股只占5%–8%,属于极度不平衡的数据——好比100个学生里只有5个考满分,模型很容易“偷懒”全判成不及格。
为了解决这个问题,我用了:
- 时间序列交叉验证:严格按日期顺序切分训练集和验证集,绝不用未来数据作弊
- 类别权重调整:让模型多看几次涨停的样本,但不破坏真实分布
- 分位数裁剪:把极端离谱的数据(比如竞价涨幅突然100%)拉回正常范围
最终在验证集上的成绩:
- AUC = 0.7358(比瞎猜好了46.7%)
- 精确度(阈值0.88时)= 85.7%
意味着:模型说“涨停”的10只票里,大约有8–9只真的涨停了 - 召回率 = 15.8%
意味着:所有真实涨停的票里,模型能提前抓住15.8%(只求精不求多)。
六、实战回测:如果能回到过去……
我用 2025年1月到2026年3月 的数据做了模拟交易(假设每天按模型信号买入,次日卖出):
|
指标 |
数值 |
|
交易次数 |
1210次 |
|
胜率 |
92.81% |
|
平均每笔收益 |
3.57% |
|
最大回撤 |
8.2% |
|
夏普比率 |
2.34 |
⚠️ 注意:这是不考虑手续费、滑点、冲击成本的“理想成绩”。实际实盘会低一些,但方向依然有参考价值。
这个成绩意味着什么?
不是暴利,但很稳。绝大多数交易日只买1–3只票,对了赚3–5%,错了亏1–2%,长期复利可观。
七、每天早晨,它是怎么工作的?
这是我的程序每天的“生物钟”:
- 08:55:启动,准备抓数据
- 09:00:向问财发起56个因子的查询
- 09:15–09:25:一边收数据,一边清洗、计算衍生因子
- 09:28:模型跑完,输出选股列表
- 09:30:开盘,你已经有了一份“今天可能涨停”的候选池
输出示例(以2026-04-13为例):
两级策略:
- 概率 ≥ 0.88 → 放入“精选池”,可考虑买入
- 0.80 ≤ 概率 < 0.88 → 放入“观察池”,用来跟踪模型表现
八、踩过的坑:你以为很顺利,其实全是bug
坑1:数据源的列名天天变
今天叫“前5日平均成交量”,明天变成“前5个交易日的平均成交量”,代码直接炸。
解法:不写死列名,用关键词模糊匹配,比如只要包含“前5日”和“平均成交量”就算。
坑2:重复列名导致特征对不上
同一个因子,因为查询条件不同,返回了两列,模型以为是两个特征,维度出错。
解法:自动检测重复列,按日期新旧排序,给旧数据加后缀。
坑3:训练时用的中位数,预测时忘了存
分位数裁剪必须和训练时完全一致,否则结果失真。
解法:把所有统计量存成一个文件,预测时强制加载。
坑4:9:25–9:30之间只有5分钟
数据一多,处理慢了就赶不上开盘。
解法:并行抓取 + 缓存中间结果 + 关键步骤设置超时熔断。
九、模型到底在看什么?——部分揭秘
出于策略保密,我不能列出全部特征重要性排名,但可以告诉你模型最关注的几类信号:
- 竞价涨幅与量比的配合:单纯高开或单纯放量都不够,两者同时出现才是好信号
- 未匹配量的变化方向:买盘一直在堆积还是逐渐撤单?
- 历史涨停基因:过去15天内有过涨停的票,再次涨停的概率明显更高
- 近期资金趋势:前3日主力净流入为正的票,加分
有意思的是:模型不仅看竞价瞬间的表现,还非常看重“历史股性”和“资金趋势”。也就是说,一只票如果过去经常涨停、近期有资金沉淀、今天竞价又出现异动——那才是真正的高概率机会。
十、未来还能怎么进化?
短期我想做三件事:
- 剔除冗余因子:56个里可能有一半相关性太高,删掉能提速
- 动态阈值:市场情绪好的时候用0.85,差的时候用0.92
- 加入板块热度:同一板块有多只票同时出信号,加分
中长期:
- 用LSTM学习竞价序列的时间变化模式(比如最后1分钟量突然放大)
- 区分震荡市和单边市,用不同模型参数
十一、几句大实话(风险提示)
我必须说清楚:
- 模型会失效。市场在变,过去好用的规律未来可能反过来。
- 数据有延迟或错误。问财不是交易所直连,偶尔会出错。
- 极端行情下不要用。股灾、千股跌停的时候,任何竞价模型都没意义。
- 不要无脑梭哈。再好的模型,单只股票仓位不超过总资金的5%。
我的建议:
把它当成一个 “早盘筛选器” ,帮你从四五千只票里快速选出3–5只值得看的。最终买不买,还要结合当天的消息、板块、自己的风险偏好。
十二、写到最后:量化不是圣杯,但可以是望远镜
做完这个项目,我最深的感受是:
没有哪个模型能100%预测涨停,但它可以让你不再靠感觉和运气去竞价。
那56个因子、双引擎融合、每天5分钟的紧张调度……这一切的价值,并不是找到了“必胜公式”,而是建立了一个可以不断迭代、验证、优化的系统。
你可以在这个框架里,加入自己的因子,调自己的阈值,让它越来越适合你的交易风格。
觉得有用的话,点个赞和在看,让更多在竞价中迷茫的朋友看到。
更多好玩的量化交易方法,等着你来一起玩起来。
