news 2026/9/23 10:00:53

【Python量化数据工程实战 #06】前复权后复权分不清?回测数据准备的最佳实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Python量化数据工程实战 #06】前复权后复权分不清?回测数据准备的最佳实践

你跑回测的时候,有没有遇到过这种诡异情况:

  • 某只股票昨天收盘 150 元,今天开盘直接跳到 100 元——没跌停,但跌了 33%
  • 策略信号在除权日疯狂触发,买入卖出全乱套。
  • 同一段代码,Tushare 拉的数据收益 20%,自己拉的数据收益 -5%——数据来源一样,只是没复权

问题出在除权除息。A股每年都有分红、送转股,如果不做复权处理,K线会出现断崖式跳空,你的收益率、均线、波动率全部失真。

这篇文章不讲复杂的金融工程,只给你一个可落地的前复权计算方案:用真实分红数据,手动算出复权因子,让回测结果不再被除权日绑架。

本文你将得到什么

  1. 不复权、前复权、后复权的本质区别(一句话说清)
  2. company_dividends拉分红送股数据,手动计算前复权因子
  3. 一段可直接运行的代码,输出复权后的收盘价
  4. 回测中复权处理的 2 个铁律

一句话说清三种价格

类型含义适用场景
不复权交易所原始成交价格看真实委托、撮合逻辑
前复权最新价格为基准,历史价格往回调整回测、策略研究(推荐)
后复权上市首日为基准,后续价格往前调整长期收益累计、财富增长

回测必须用前复权。原因:前复权保持了最新价格的现实意义,历史价格按比例压缩,收益率计算不会受除权日干扰。

代码实战:手动计算前复权

下面演示完整的复权流程:先拉不复权行情和分红数据,再计算前复权因子。

frommairuiimportClientimportpandasaspd client=Client("LICENCE-66D8-9F96-0C7F0FBCD073")code="600519"# 1) 拉不复权日线raw=client.stock_history(code,lt=120,dividend='n')df=pd.DataFrame(raw)df['t']=pd.to_datetime(df['t'])df=df.sort_values('t').reset_index(drop=True)# 2) 拉分红送股数据divs=client.company_dividends(code)df_div=pd.DataFrame(divs)df_div['sdate']=pd.to_datetime(df_div['sdate'])# 只取在行情区间内且已实施的分红mask=(df_div['sdate']>=df['t'].min())&(df_div['line'].isin(['实施','已实施']))df_div=df_div[mask].sort_values('sdate')# 3) 计算前复权因子(从除权日往历史回溯)df['adj_c']=df['c'].astype(float)for_,rowindf_div.iterrows():sdate=row['sdate']send=float(row['send'])ifrow['send']!='-'else0.0give=float(row['give'])ifrow['give']!='-'else0.0# 送转比例:10送3 = 0.3,即每股变 1.3 股ratio=1.0+(give/10.0)# 对除权日之前的所有价格:先乘股数比,再加现金红利mask_before=df['t']<sdate df.loc[mask_before,'adj_c']=df.loc[mask_before,'adj_c']*ratio+send# 4) 输出对比print(df[['t','c','adj_c']].tail(10).to_string(index=False))

核心逻辑拆解

前复权的核心就一句话:历史价格要反映"如果当初买了,现在值多少"

假设你持有 1 股,股价 100 元:

  • 公司 10 送 3:你的 1 股变成 1.3 股,每股价格变成 100 / 1.3 = 76.92 元
  • 再每股派 2 元:你拿到 2 元现金,每股价格变成 76.92 元(现金不影响股价,但你的总资产增加了)

所以前复权的历史价格需要:

  1. 乘股数比(股变多了,每股价格变低,反过来历史价格要变高)
  2. 加现金红利(你拿到了现金,相当于成本降低)

回测复权的 2 个铁律

铁律 1:回测全程用前复权,但下单必须用不复权

策略信号计算(均线、突破、收益率)全部基于前复权价格,但生成交易指令时,要映射回交易所真实价格(不复权),否则你的买入价和实际撮合价对不上。

# 伪代码:信号计算用 adj_c,下单用 csignal=df['adj_c']>df['adj_ma20']# 前复权算信号order_price=df.loc[signal,'c']# 用不复权价格下单

铁律 2:复权因子一旦确定,回测期间不能变

如果你在 2024 年跑回测,用到了 2025 年才披露的分红数据,那就是未来函数——你在 2024 年不可能知道 2025 年会分红多少。

正确做法:回测到某天,只使用该日期之前已公告的分红方案。company_dividends返回的line字段如果是"预案",说明还没实施,回测中不应纳入。

小结

复权不是可有可无的数据清洗,而是回测的基础设施。记住三点:

  1. 回测用前复权,保持最新价格的真实意义
  2. 手动算复权因子= 股数比累乘 + 现金红利累加
  3. 下单用不复权,模拟真实交易所撮合

掌握这套流程,你的回测结果才具备横向可比性——不会因为某只股票分红多、送转多,就凭空"跑输"其他策略。

下篇预告:数据合并完了,复权也做了,但特征还是太多、相关性太高怎么办?#07 带你用相关性去重 + RFE 递归特征消除,把 100 个特征筛到 10 个最有效的。


免责声明

本文仅供技术学习交流,不构成任何投资建议。市场有风险,决策需谨慎。

代码与文档

更多接口文档和 SDK 使用示例,可查阅官方文档:https://github.com/MaiRuiApi/mairui

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 10:00:38

90%运维都踩坑!终端安全一体化平台落地致命误区拆解

写在前面&#xff1a;看似部署成功&#xff0c;实则全程裸奔终端安全一体化平台集成资产盘点、外设管控、行为审计、文档防护、违规外联管控、离线终端加固等全栈能力&#xff0c;是企业内网安全建设的核心底座。但一线落地中发现&#xff0c;绝大多数安全短板&#xff0c;都不…

作者头像 李华
网站建设 2026/9/23 9:53:58

增材制造如何革新模具材料与冷却设计

1. 模具制造的材料困境与历史局限在传统模具制造领域&#xff0c;工程师们长期陷入一种"材料迷信"——追求一种理论上完美的"万能钢"。这种材料需要同时具备高硬度、高韧性、耐磨性、耐热性&#xff0c;最好还能保持低廉的价格。但从业二十余年的经验告诉我…

作者头像 李华
网站建设 2026/9/23 9:51:21

GIS数据转换实战:Excel与KML互转、无人机POS处理及CZML动画生成

简介&#xff1a;大奇GIS专家是一款服务于地理信息处理与无人机数据应用的专业工具包&#xff0c;重点解决KML与Excel表格之间的批量互换、无人机影像数据处理&#xff0c;以及KML和CZML动画生成三类问题&#xff0c;适合GIS工程师、测绘人员及相关专业学习者使用。压缩包内共包…

作者头像 李华
网站建设 2026/9/23 9:49:32

第177篇_独立站商品采集

【Python爬虫实战】第177篇:独立站商品采集——Shopify独立站商品信息抓取与结构化 所属专栏:【Python爬虫实战】从零到企业级爬虫工程师(CSDN 付费专栏) 本篇篇目:第 177 篇(垂直行业数据采集专题) 难度等级:中级,掌握 requests 与 JSON 解析即可 阅读时长:约 30 分…

作者头像 李华
网站建设 2026/9/23 9:48:17

unity urp的内置后期效果参数

效果参数详解1. Tonemapping 色调映射参数含义展厅 Mode映射算法&#xff1a;None&#xff08;不映射&#xff0c;易死白&#xff09;/ Neutral&#xff08;中性&#xff09;/ ACES&#xff08;电影感&#xff0c;对比更稳&#xff09;ACES2. Bloom 泛光参数含义推荐Threshold多…

作者头像 李华
网站建设 2026/9/23 9:47:15

文件流文本模式与二进制模式:从乱码事故到MultipartFile与Base64互转实战

1. 从一个让我加班到凌晨的乱码事故说起几年前我接手过一个数据导出模块&#xff0c;需求很简单&#xff1a;把数据库里的用户信息导成 CSV 文件&#xff0c;再提供一个上传入口让运营同学把处理好的文件传回来。本地开发环境跑得顺风顺水&#xff0c;测试同学也没报问题&#…

作者头像 李华