大家好,我是easyquant实战。
⚠️ 重要提示:本文内容面向有一定Python编程基础和交易经验的量化老手。文中涉及的代码需要开通迅投行情VIP或QMT投研版,以及券商miniqmt下单权限,属于高阶量化实现。如果你是量化小白,建议先收藏,打好基础后再来学习。
? 为什么你总在财报发布后“接盘”?
你有没有这种感觉:
某公司发了业绩预增公告,你摩拳擦掌准备买入,结果第二天一字板涨停,根本买不进?
好不容易打开涨停冲进去,后面却高开低走,把你套得死死的?
明明业绩很好,股价就是不涨,反而一路阴跌?
问题出在哪?因为市场太“卷”了——机构提前研究、提前抢跑,等财报出来的时候,肉早就被吃完了,留给你的只有汤,甚至是洗碗水。
那怎么办?答案很简单:把目光从“财报后”转向“财报前”。?
国信金工的一篇研报:【国信金工】超额图谱视角下的成长股投资策略捅破了这层窗户纸——他们发现了一个神奇的窗口,叫“黄金期”:正式财报发布前的10个交易日,超额收益最猛、胜率最高! ?
今天,我就带你深度拆解这个策略,并公开我用 pywencai + xtquant 实现的完整代码。(代码已根据实盘经验做了多处改良,不是简单的照搬,文末可获取)
? 黄金期到底有多猛?数据说话!
研报作者统计了2012年以来两类利好事件(研报标题超预期、业绩预增)的股票,看它们在财报发布前后不同阶段的表现,结果惊人:
| 财报前10天 | 2.09%~2.15% | 91%~93% | 黄金期 |
看到了吗?黄金期超额收益超过2%,胜率超过90%! 而且近年来这个效应还在增强。相反,财报发布后再去买,胜率只剩一半,收益甚至为负。?
为什么会有黄金期?因为信息太多,投资者看不过来——预告发布时大家没反应过来,等到正式财报快发了,资金才想起抢跑,形成一波上涨。而且,这个窗口是可以提前计算的——每个公司都会公布“定期报告预约披露日”,我们完全可以提前知道哪些股票即将进入黄金期!?
? 策略核心:先看时间,再看个股
研报的核心框架只有六个字:先时序,后截面。
? 先时序:按距离财报日分档
根据当前日期距离该股票“定期报告预约披露日”的交易日天数,分成三档:
第一档(黄金期):距离 ≤ 10个交易日(优先买入!) ?
第二档(白银期):10 < 距离 ≤ 20个交易日 ?
第三档(青铜期):距离 > 20天,或没公布日期,或已发财报 ?
? 后截面:同一档内再精选
如果黄金期股票太多(比如超过计划持仓数),就用多因子打分排序,选得分最高的。因子包括:净利润增速、ROE、相对强度等。
如果黄金期股票不够,就从白银期、青铜期里按不同因子补足。
? 还加了“黑科技”降低换手
缓冲机制:排名在边缘的老股票,允许继续持有,不频繁进出。
跃迁机制:老股票如果得分很高,即使本在低一档,也允许“跃迁”到高一档继续持有。
风险规避:在5、6、9、11、12月初,剔除上一期财报前涨幅过高的股票(前5%),防止追高。
⏰ 调仓节奏
财报发布高峰期(1、2、3、4、7、8、10月):每天调仓 ?
财报发布真空期(5、6、9、11、12月):月初调一次,月中不动
? 回测结果(2012-2023)
以中证500为基准,双边千三手续费:
进取组合(50只):年化收益 52.14%,超额 46.15%,最大回撤仅 8.06% ?
稳健组合(100只):年化收益 44.30%,超额 38.32%,最大回撤 6.97% ?️
大部分年份排在主动股基前30%,稳得一批!?
? 实战落地:pywencai + xtquant 复现(带改良)
理论说完了,上代码!我用两个工具:
pywencai:模拟研报的股票池生成,从同花顺i问财拿数据。
xtquant:迅投QMT的Python接口,拿行情、交易日历、下单交易(需要开通迅投行情VIP或QMT投研版 + 券商miniqmt权限)。
⚠️ 再次强调:
你需要Python基础,能看懂pandas和QMT接口。
你需要实盘交易经验,知道什么是滑点、涨停、跌停。
你需要开通相应权限,否则跑不起来。
代码没有100%照搬研报——我根据实盘经验做了多处改良,下面逐条说明为什么改、效果如何。
? 改良1:数据源从“研报标题”简化为“问财选股”
研报做法:爬研报标题,做文本分析,太麻烦。我的做法:用pywencai一句话搞定:
query = """业绩预告类型包含大幅上升,或者业绩预告类型包含预增,业绩预告类型不包含扭亏,沪深A股,非ST,非新股,非次新股,定期报告披露日期,加权净资产收益率,250天最高价"""df = pywencai.get(query=query, cookie=你的cookie)
✅ 好处:门槛低、实时性好,问财本身聚合了业绩预告和研报舆情,效果接近。
? 改良2:选股因子大幅简化
研报做法:多因子模型,调参复杂,容易过拟合。我的做法:
黄金期:按“当前价位”(最新价/250日最高价)降序,防止追高。
白银期:按ROE降序,要质地好。
青铜期:按净利润增幅降序,要够猛。
✅ 好处:简单粗暴,抓住主要矛盾,小资金实盘更稳健。
⚡ 改良3:盘中加技术条件才买入(B1/B2)
研报做法:每天收盘出信号,第二天开盘买。我的做法:盘中轮询,满足技术条件才下单:
B1(首次建仓):股价站上10日均线、预计放量、没大幅高开。
B2(加仓):已有底仓,股价回踩ATR止损线后反弹。
✅ 好处:提高胜率,动态加仓,更贴近实战。
? 改良4:ATR动态止盈(S1/S2)
研报做法:卖出主要看股票是否还在黄金期。我的做法:
S1(部分止盈):冲高回落超过ATR阈值,卖一半,锁定利润。
S2(清仓):股票不在最新股票池,或仓位太小(减仓后),全卖。
✅ 好处:保护利润,降低回撤,避免坐过山车。
?️ 改良5:加强风控
研报做法:缓冲/跃迁机制控制换手,但没限制行业集中度。我的做法:
同一行业最多持有2只(分散风险)。
单日最多买入20只(防冲击)。
总资金不超过设定值(仓位管理)。
✅ 好处:更安全,更适合实盘。
⏱️ 改良6:避开开盘收盘的剧烈波动
研报做法:第二天开盘就交易。我的做法:只在 9:30-11:30 和 13:00-14:30 这两个时段交易。
✅ 好处:避开开盘集合竞价的混乱和收盘前的流动性枯竭,滑点更小。
? 代码核心片段(选股分档)
# 获取问财数据df = pywencai.get(query=query, cookie=你的cookie)# 匹配关键列(问财列名会变,需要动态找)col_date = [c for c in df.columns if '定期报告预计披露日期' in c][0]col_price = [c for c in df.columns if '最新价' in c][0]col_high = [c for c in df.columns if '区间最高价' in c][0]col_roe = [c for c in df.columns if '净资产收益率' in c][0]col_growth = [c for c in df.columns if '预告净利润变动幅度' in c][0]# 计算当前价位df['当前价位'] = df[col_price] / df[col_high]# 获取交易日历trading_calendar = xtdata.get_trading_calendar(market='SH', start_time=today, end_time='')# 分档函数def get_level(date):if date in trading_calendar:idx = trading_calendar.index(date)if idx <= 10: return 1elif idx <= 20: return 2else: return 3else:return 3df['level'] = df[col_date].apply(get_level)# 按优先级选股first = df[df['level'] == 1].sort_values('当前价位', ascending=False)second = df[df['level'] == 2].sort_values(col_roe, ascending=False)third = df[df['level'] == 3].sort_values(col_growth, ascending=False)# 动态选股(根据当前持仓数、单日上限等)
? 如何获取完整代码?
关注公众号 easyquant实战,后台回复“黄金期”即可下载。
下载后请务必:
检查自己是否够格:Python基础、交易经验、QMT权限,缺一不可。
修改配置:在
Config类里填你的同花顺cookie、QMT路径、资金账号(示例路径为E:\xt_data,请根据实际情况调整)。先模拟跑:观察买卖逻辑是否符合预期,再考虑实盘。
调整参数:根据自己的资金量和风险偏好,改
BUY_MONEY、MAX_HOLD_STOCK_NUM、ATR倍数等。
遇到问题欢迎留言交流,大家一起进步!?
? 写在最后
这篇研报给了我很大的启发:真正的α,往往藏在市场行为的细节里。而要把学术研究转化为实盘利器,必须经历“本地化改造”——结合自己的数据源、资金量、风险偏好,做适当的调整。
希望这篇文章能帮你打开一扇新的大门。下一期,我们聊聊股票的小市值策略,敬请期待!?
⚠️ 风险提示:本文内容仅为策略思路分享与量化学习交流,不构成任何投资建议。文中涉及的代码需要特定的行情和交易权限,且需要一定的Python基础和交易经验。请确保你已满足这些条件再尝试实盘。股市有风险,投资需谨慎。


