1. 先搞清楚“一进二量化模型”到底在解决什么问题
如果你在找“一进二”的量化模型,最该关心的不是它某一天抓了几个涨停,而是它能不能在你的环境下稳定运行,以及它背后的选股逻辑是否清晰、可复现。
所谓“一进二”,是A股市场里一种常见的短线交易策略,指的是寻找那些在第一个交易日涨停(“一板”)的股票,试图在第二个交易日(“二板”)继续买入并获取溢价。这个策略听起来简单,但难点在于如何从每天众多的首板股票中,筛选出第二天最有可能继续涨停的标的。一个所谓的“最强模型”,核心价值就在于它用一套量化的规则(比如结合了量价、资金、板块、市场情绪等因子)来替代人工的主观判断,试图提高这个筛选的胜率和效率。
所以,面对“7.31日实盘买入4只,2只涨停!”这样的描述,首先要冷静。单日的战绩,尤其是小样本的战绩,几乎没有任何统计意义。它可能是运气,也可能是模型在特定市场环境下的偶然表现。真正值得你花时间研究的,是这套模型的:
- 因子逻辑:它到底用了哪些数据?是单纯的涨停板强度、封单金额,还是结合了龙虎榜、行业热度、大盘情绪?
- 回测框架:有没有历史数据的回测?回测周期多长?夏普比率、最大回撤、年化收益这些关键指标如何?
- 实盘接口:它如何与券商交易系统对接?是半自动预警人工下单,还是全自动交易?这涉及到风控和合规。
- 环境依赖:运行它需要什么数据源(如Tushare、聚宽、米筐)、什么编程环境(Python 3.8+?)、什么硬件条件(需要实时Tick数据吗?)。
我一般会建议,先把模型当成一个“黑盒策略”进行验证。别急着看代码,先问自己:如果给我这个策略的信号列表,我能不能手动复现它的选股结果?这是判断一个量化模型是否“靠谱”的第一步,也是防止被华丽宣传迷惑的关键。
2. 拆解一个典型“一进二”量化模型的运行环境与流程
一个完整的、可运行的“一进二”量化模型,绝不仅仅是一个.py文件。它是一套包含数据、计算、决策、风控的流水线。下面我以一个典型的本地化研究环境为例,拆解你需要准备什么,以及流程是怎样的。
2.1 核心数据准备:你的“弹药库”
没有高质量、结构化的数据,任何量化模型都是空中楼阁。对于“一进二”策略,你至少需要以下几类数据:
- 历史行情数据:股票日线数据(开盘价、最高价、最低价、收盘价、成交量、成交额)。这是基础中的基础。
- 涨停板数据:需要能准确识别历史上每一天的涨停股票列表,以及涨停时间、封单量等。很多通用行情接口不直接提供这个,需要自己根据涨跌幅规则(主板±10%,创业板/科创板±20%)和是否ST进行计算和筛选。
- 板块与概念数据:股票所属的行业板块、热门概念。用于分析涨停股的“题材”属性,这是“一进二”成功率的重要影响因素。
- 市场情绪数据:如昨日涨停股今日表现(即“昨日涨停指数”)、市场连板高度、涨跌家数比等。这些是判断短线投机氛围冷暖的关键指标。
- 龙虎榜数据(可选但重要):观察首板当日是哪些营业部资金买入。游资的参与度有时是后续持续性的风向标。
数据源选择:
- Tushare Pro/米筐/聚宽:这些平台提供了相对完善的API,可以获取上述大部分数据,但通常有积分、费用或频率限制。适合个人研究和小资金实盘。
- 本地数据库:如果你追求极致的速度和稳定性,可以考虑购买商业数据源(如Wind、Choice)并本地化存储。这需要一定的运维和开发能力。
我的经验是:在初期,不要追求大而全的数据。先用一个免费或低成本的数据源(如Tushare Pro的基础数据),把核心的日线、涨停判断逻辑跑通。数据质量的问题,往往在回测阶段就会暴露出来。
2.2 策略开发环境搭建:你的“工作台”
你需要一个稳定的Python环境来编写和回测策略。我个人的常用组合是:
# 1. 创建独立的Python环境(强烈推荐) conda create -n stock_quant python=3.8 conda activate stock_quant # 2. 安装核心依赖 pip install pandas numpy matplotlib seaborn # 数据分析与可视化 pip install tushare # 或 rqdatac, jqdatasdk pip install backtrader 或 zipline 或 empyrical # 回测框架(选一个) pip install schedule # 用于定时任务(如果做实时监控)关于回测框架:backtrader功能强大但稍复杂;zipline是聚宽开源版,生态好;如果你只想做信号分析,用pandas计算收益,再用empyrical计算风险指标(夏普、回撤等)可能更轻量。
关键目录结构建议:
quant_project/ ├── data/ # 存放原始和清洗后的数据 ├── utils/ # 自定义工具函数,如数据获取、涨停判断 ├── strategy/ # 策略核心逻辑 │ └── one_to_two.py ├── backtest/ # 回测脚本 ├── config.py # 配置文件(API token、数据库连接等) └── main.py # 主运行入口2.3 “一进二”策略核心逻辑代码拆解
下面是一个极度简化的策略逻辑框架,用于说明思路,不可直接用于实盘。
# strategy/one_to_two.py import pandas as pd import numpy as np from datetime import datetime, timedelta class OneToTwoStrategy: def __init__(self, data_provider): self.data_provider = data_provider # 数据获取对象 def is_limit_up(self, row): """判断当日是否涨停(简化版,未考虑ST、新股)""" return abs(row['close'] / row['pre_close'] - 1) >= 0.099 # 接近10% def get_first_limit_stocks(self, date): """获取指定日期所有首板股票""" all_data = self.data_provider.get_daily_data(date) # 计算涨停 all_data['is_limit_up'] = all_data.apply(self.is_limit_up, axis=1) first_limit = all_data[all_data['is_limit_up']] # 这里需要更复杂的逻辑:排除非首板(需要历史数据判断昨日是否涨停) # 假设我们已经有了首板股票列表 first_limit_stocks return first_limit_stocks def calculate_features(self, stock_list, date): """为核心股票列表计算特征因子""" features_df = pd.DataFrame() for stock in stock_list: # 因子1:涨停时间(假设有tick数据,这里用日线模拟) # 因子2:封单金额/流通市值 比例 # 因子3:所属板块当日强度 # 因子4:龙虎榜净买入额(如果有) # 因子5:成交量与前几日均量比 # ... 计算多个因子 feature_vector = self._compute_single_stock_features(stock, date) features_df = features_df.append(feature_vector, ignore_index=True) return features_df def filter_stocks(self, features_df): """根据特征因子进行筛选打分""" # 方法1:规则过滤,例如:封单比 > 3%,非ST,市值小于100亿 filtered = features_df[ (features_df['seal_ratio'] > 0.03) & (~features_df['is_st']) & (features_df['market_cap'] < 100) ] # 方法2:模型预测(如果有训练好的分类模型) # filtered['score'] = model.predict_proba(filtered[factor_cols])[:, 1] # filtered = filtered[filtered['score'] > 0.7].sort_values('score', ascending=False) return filtered def run(self, trade_date): """主运行函数:输入交易日期,输出候选股票列表""" print(f"处理交易日: {trade_date}") # 1. 获取首板股票池 first_limit_pool = self.get_first_limit_stocks(trade_date) if first_limit_pool.empty: return [] # 2. 计算特征 features_df = self.calculate_features(first_limit_pool['code'].tolist(), trade_date) # 3. 筛选 candidate_df = self.filter_stocks(features_df) # 4. 输出结果(例如,最多4只) final_candidates = candidate_df.head(4)[['code', 'name']].to_dict('records') return final_candidates # 假设的数据提供类 class MockDataProvider: def get_daily_data(self, date): # 返回该日所有股票的日线数据DataFrame pass # 使用示例 if __name__ == '__main__': provider = MockDataProvider() strategy = OneToTwoStrategy(provider) # 模拟运行2023年7月31日 candidates = strategy.run('20230731') print(f"选股结果: {candidates}")这个框架展示了从“获取首板”到“特征计算”再到“规则/模型筛选”的核心流程。所谓的“最强模型”,差异就体现在calculate_features和filter_stocks这两个函数的复杂度和有效性上。
3. 从回测到模拟:如何验证模型的有效性
拿到一个模型代码,或者自己写完策略逻辑后,千万不要直接上实盘。必须经过严格的回测和模拟盘验证。
3.1 回测:在历史数据中“时光旅行”
回测的目的是检验策略在历史数据上的表现。关键步骤和注意事项:
- 确定回测周期:至少覆盖一轮牛熊,例如3-5年。只在牛市有效的策略没有意义。
- 处理幸存者偏差:回测时,必须使用“当时已知”的信息。不能用到股票未来退市的数据,也不能用到当时还未发生的财务数据。
- 考虑交易成本:必须在收益中扣除佣金(通常万2.5到万3)和印花税(千1,卖出时收取)。这是很多策略从盈利变亏损的关键。
- 设置滑点:在模拟成交时,加入滑点(例如0.1%),以模拟实际交易中无法以精确价格成交的情况。
- 定义买卖规则:对于“一进二”,买入规则通常是:T日收盘后选出股票,T+1日以开盘价或开盘后一段时间均价买入。卖出规则更关键:是涨停持有,不涨停次日卖出?还是设置固定的止盈止损点(如+5%止盈,-3%止损)?
回测结果要看哪些指标?
- 总收益率 & 年化收益率:基础收益。
- 夏普比率:衡量风险调整后的收益。大于1算不错,大于2很好。
- 最大回撤:历史上最大的亏损幅度。你能承受的最大回撤是多少?-20%?-30%?这个指标直接决定你能否坚持执行策略。
- 胜率:盈利交易次数占总交易次数的比例。“一进二”策略胜率通常不会太高,可能在40%-60%之间,但盈亏比(平均盈利/平均亏损)要高。
- 交易次数:样本是否足够多?一年只交易几次的策略,统计意义不大。
一个常见的坑:过度拟合。如果你不断调整参数让策略在历史数据上表现完美,那它在未来大概率会失效。回测结果“看起来太好”(如年化收益50%+,最大回撤<5%),反而要高度警惕。
3.2 模拟盘:在真实市场环境中“彩排”
回测通过后,必须进行模拟盘(Paper Trading)。模拟盘使用实时或准实时的数据运行策略,发出买卖信号,但不下达真实订单。
模拟盘的价值:
- 检验实时数据流:你的数据接口在开盘时能否稳定、快速地获取数据?会不会有延迟或缺失?
- 验证下单逻辑:你的代码能否在9:25集合竞价结束后准确计算出候选股,并在9:30开盘后模拟下单?
- 观察策略心态:虽然不是真钱,但看着模拟盘盈亏波动,也能部分检验你的心理承受能力。
如何搭建简单模拟盘? 你可以用一个定时任务,在每天收盘后(例如下午4点)运行选股策略,生成第二天的候选股列表。然后在第二天开盘前,手动或半自动地“记录”这些股票的开盘价,并在收盘后“记录”收盘价,计算当日盈亏。虽然粗糙,但足以验证策略的实时选股能力。
注意:模拟盘和实盘最大的差距在于流动性冲击和心理因素。模拟盘可以轻易“买入”一只封单很小的涨停股,但实盘你可能根本买不到。模拟盘的亏损你不会心疼,但实盘的亏损会让你怀疑并修改策略。
4. 实盘部署与风控:从代码到交易的最后一公里
如果回测和模拟盘的结果都令人满意,并且你充分理解了策略的亏损期(Drawdown),那么可以考虑小资金实盘。这一步是风险最高的一步。
4.1 实盘接入方式
半自动(推荐起步):
- 策略程序在收盘后或开盘前运行,生成一个候选股列表(如Excel或TXT文件)。
- 开盘后,你手动在券商交易软件里,按照列表和预设仓位下单。
- 优点:安全,你有最终决策权,可以规避程序Bug导致的灾难。
- 缺点:依赖人工执行,可能犹豫或出错,尤其在多只股票同时需要操作时。
全自动(门槛高):
- 策略程序直接通过券商提供的API(如华宝证券、国金证券等部分券商支持)或第三方量化平台(如聚宽、米筐的实盘功能)自动下单。
- 优点:执行纪律性强,速度快。
- 缺点:需要极高的代码稳定性和风控能力。一个死循环或逻辑错误可能导致瞬间巨大亏损。同时,需要解决网络中断、服务器宕机等问题。
4.2 你必须建立的风控清单
实盘前,必须将以下风控措施代码化或制度化:
- 单笔最大亏损:任何一笔交易,亏损达到总资金的X%(例如2%)必须无条件止损。
- 每日最大亏损:当天累计亏损达到Y%(例如5%)停止所有交易。
- 总体最大回撤:账户从高点回撤达到Z%(例如15%)停止策略,全面复盘。
- 持仓限制:单只股票最大仓位(例如20%),单一行业最大仓位(例如30%)。
- 订单监控:程序化交易必须有心跳机制,如果程序卡死或异常退出,要有备用方案(如短信报警、自动平仓)。
- 资金隔离:用于量化交易的资金应该是你输得起的“闲钱”,与生活资金、其他投资资金严格分开。
4.3 实盘中的关键运维细节
- 日志系统:每一次数据获取、信号计算、订单触发,都必须有详细日志。出问题时,日志是唯一的排查依据。
- 数据备份:每日收盘后,备份当日成交记录、持仓、策略日志。
- 定期复盘:每周或每月,对交易记录进行复盘。不仅看盈亏,更要分析亏损交易是否符合策略逻辑?有没有情绪化干预?策略是否出现了环境失效的迹象(例如市场风格从短线连板转向趋势大盘股)?
5. 当模型失效时:如何排查与迭代
没有任何一个量化策略可以永远有效。“一进二”模型尤其依赖于活跃的短线投机氛围。当策略连续亏损时,你需要系统性地排查。
5.1 问题排查顺序
数据问题(最优先):
- 检查数据源是否中断?涨停数据计算是否正确?
- 最近是否有新的交易规则(如涨跌幅调整)导致你的判断逻辑失效?
- 使用
print或日志输出中间结果,核对get_first_limit_stocks函数选出的股票,与同花顺/东方财富等软件显示的首板股票是否一致。
代码逻辑问题:
- 是否在代码更新时引入了Bug?使用Git进行版本管理,每次修改都有记录。
- 环境依赖是否有更新导致不兼容?使用
requirements.txt固定依赖版本。 - 运行一遍历史某天的数据,对比现在的输出和之前的输出是否相同。
市场环境问题:
- 整个市场“一进二”的成功率是否在系统性下降?可以计算一个简单的市场基准:统计历史上所有首板股票次日涨停的比例,看看最近一段时间这个比例是否显著低于历史均值。
- 监管政策是否发生变化?(如对异常交易的监控加强)。
- 市场风格是否切换?(如从炒小、炒差转向业绩驱动)。
策略本身问题(过度拟合失效):
- 这是最棘手的情况。可能策略依赖的某些因子(如特定游资席位行为)已经失效。
- 需要扩大回测样本,查看策略在不同市场阶段(牛市、熊市、震荡市)的表现。如果只在某种特定环境下有效,那么它就是有条件的。
5.2 策略迭代与放弃
- 小步迭代:如果怀疑某个因子失效,可以尝试微调参数或加入新的辅助因子(例如加入北向资金流向、大盘成交量等)。但每次只改一个地方,并重新进行严格的样本外回测。
- 设置观察期:当策略连续亏损触及最大回撤线时,停止实盘,进入观察期。在观察期内只用模拟盘运行,同时深入分析原因。
- 勇于放弃:如果经过多次迭代和长期观察,策略的预期收益风险比已经不再具备吸引力,或者其依赖的市场条件已不复存在,那么果断放弃它,寻找新的Alpha来源。在量化交易中,保存本金和纪律比坚持一个失效的策略重要得多。
最后,回到标题“最强一进二量化模型”,它可能是一个不错的起点或学习样本,但绝非终点。真正的“强”,不在于某一天捕捉了多少涨停,而在于一套严谨的数据处理流程、清晰透明的策略逻辑、完备的风控体系以及长期执行这套系统的纪律。从这个角度看,构建和维护这个系统的过程,其价值远大于某个具体的选股名单。我建议任何想尝试的朋友,从复现一个简单的规则策略开始,把数据、回测、模拟的每一个环节都跑通、吃透,再逐步增加复杂度。这条路没有捷径,但每一步都算数。