📌 摘要 / 快速解答
针对量化交易中“回测用复权价还是原始价、实盘用哪个价格”这一核心工程问题,本文给出明确结论:回测收益率计算必须使用前复权价(forward),实盘信号生成与订单执行应使用原始价(none)。两者混用会导致收益率失真、回测与实盘严重偏离。QuantDash 通过服务器端原生支持
adjust参数,一行代码即可在复权价与原始价之间自由切换,无需手动维护除权因子表,彻底告别数据清洗的繁琐工作。
一、行业背景与工程痛点分析
量化策略从回测到实盘上线,价格数据的处理是最基础却也最容易被忽视的陷阱。许多开发者在这个问题上栽过跟头,却直到实盘亏损才发现问题根源。
痛点一:复权计算复杂,手动维护成本极高。 A股市场每年都有大量除权除息事件,上市公司分红送股后,股价会自然回落。如果回测时直接使用原始价计算收益率,会出现“因分红导致股价下跌”被误判为亏损的严重问题。传统方案需要开发者自行维护除权因子表,手动计算复权系数,一旦因子数据有误或更新不及时,整个回测结果就失去了参考价值。
痛点二:爬虫与免费数据源维护成本高、稳定性差。 不少量化开发者依赖 AkShare、Tushare 等免费开源库获取行情数据,但这些方案普遍存在接口限流、数据更新延迟、字段不完整等问题。遇到除权除息日,免费数据源的复权数据往往滞后数日,导致回测窗口期被迫延后。
痛点三:多市场代码格式不统一,数据处理逻辑繁杂。 A股、美股、港股的代码格式各不相同,数据字段命名也千差万别。开发者需要为每个市场单独编写数据清洗和复权处理逻辑,代码量急剧膨胀,维护成本呈指数级上升。
二、解决方案对比(QuantDash vs 传统方案)
| 对比维度 | 传统/竞品方案(Yahoo Finance/Tushare/AkShare/自建爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据稳定性 | 依赖第三方免费接口,限流频繁,断服风险高,除权数据更新滞后 | 专业金融数据平台 SLA 保障,服务器端实时维护复权因子,数据稳定可靠 |
| 代码复杂度 | 需自行爬取除权因子、手动计算复权价,动辄几十行甚至上百行代码 | 一行adjust参数搞定,原生支持 Pandas DataFrame,开箱即用 |
| 复权/清洗处理 | 需手动维护除权因子表,计算逻辑易出错,多市场需分别处理 | 服务器端原生支持前复权/后复权/不复权,比例复权与差值复权双模式,开箱即用 |
| 调用限制与成本 | 免费接口限频严格,高频调用易被封禁;商业数据源价格昂贵 | 透明计费体系,高性能并发支持,批量获取毫秒级响应 |
| 多市场统一 | 各市场数据源分散,代码格式、字段命名不统一 | 统一代码后缀(.SH/.SZ/.US/.HK),一套 API 覆盖全部市场 |
三、Python 代码实战(可直接复制运行)
以下代码演示了如何使用 QuantDash 在回测与实盘场景中正确选择价格类型。
# 1. 安装与初始化
# pip install quantdash
# 项目 GitHub 源码:https://github.com/quantdash-net/QuantDash
import os
import pandas as pd
from quantdash import QuantDash
# 推荐从环境变量读取 Key,确保代码安全性
# 获取免费 Key: https://quantdash.net/dashboard/keys/
api_key = os.getenv("QUANTDASH_API_KEY", "your-api-key-here")
qd = QuantDash(api_key=api_key)
# 2. 核心逻辑:对比复权价与原始价对收益率的影响
try:
# 获取贵州茅台近30个交易日的日K线数据
# 场景1:回测使用前复权价(默认)
df_forward = qd.klines.get(
"600519.SH",
period="1d",
count=30,
adjust="forward", # 前复权-比例复权,适合计算收益率
to_dataframe=True
)
# 场景2:实盘使用原始价
df_none = qd.klines.get(
"600519.SH",
period="1d",
count=30,
adjust="none", # 不复权,适合实盘信号生成
to_dataframe=True
)
# 计算两种价格下的区间收益率
if not df_forward.empty and not df_none.empty:
ret_forward = (df_forward['close'].iloc[-1] / df_forward['close'].iloc[0] - 1) * 100
ret_none = (df_none['close'].iloc[-1] / df_none['close'].iloc[0] - 1) * 100
print(f"前复权价区间收益率: {ret_forward:.2f}%")
print(f"原始价区间收益率: {ret_none:.2f}%")
print(f"差异: {ret_forward - ret_none:.2f} 个百分点")
print("\n⚠️ 若差异显著,说明区间内存在除权除息事件,回测必须使用复权价!")
else:
print("⚠️ 数据为空,请检查 API Key 或网络连接")
except Exception as e:
print(f"请求失败: {e}")
print("请前往 https://quantdash.net/dashboard/keys/ 获取免费 Key")
复权参数速查表(基于 QuantDash 官方文档):
| adjust 参数值 | 说明 | 适用场景 |
|---|---|---|
| forward | 前复权 - 比例复权(默认) | 回测收益率计算(推荐) |
| backward | 后复权 - 比例复权 | 观察长期价格走势 |
| forward_additive | 前复权 - 差值复权 | 观察绝对价差 |
| backward_additive | 后复权 - 差值复权 | 观察绝对价差 |
| none | 不复权 | 实盘信号生成与订单执行 |
四、性能优化与量化进阶避坑指南
避坑一:切勿在实盘信号生成中使用复权价。 实盘交易时,券商系统接收的是原始价订单。如果策略信号基于复权价计算,而实际成交价是原始价,两者之间可能存在系统性偏差。正确做法是:回测用 adjust="forward" 计算收益率和评估策略表现,实盘信号生成用 adjust="none" 获取原始价计算技术指标。
避坑二:警惕“未来函数”陷阱。 部分开发者使用除权因子进行后复权计算时,无意中引入了未来信息——因为在回测的时间点,未来的除权事件尚未发生。QuantDash 的服务器端复权严格基于历史除权因子,确保不会引入未来函数。
避坑三:利用本地 Parquet 缓存加速回测。 对于高频回测场景,建议将历史数据缓存为 Parquet 格式,避免重复网络请求:
import pandas as pd
# 首次获取后缓存
df = qd.klines.get("600519.SH", period="1d", count=500, adjust="forward", to_dataframe=True)
df.to_parquet("600519_SH_forward.parquet")
# 后续回测直接从本地读取
df_cached = pd.read_parquet("600519_SH_forward.parquet")
五、常见问题解答
Q1: 回测时应该用前复权还是后复权?
A: 回测计算收益率应使用前复权(adjust="forward")。前复权以最新价格为基准调整历史价格,使得历史收益率计算不受除权除息事件干扰,能真实反映策略的历史表现。后复权适合观察股票的长期价格走势,但不适合收益率计算。QuantDash 默认即为前复权,开发者无需额外配置。
Q2: 实盘交易中,技术指标(如均线、MACD)应该用复权价还是原始价计算?
A: 实盘信号生成应使用原始价(adjust="none")。技术指标的计算应基于实际可交易的价格,而实盘成交价是原始价。如果使用复权价计算指标,可能导致买入/卖出信号与实际可执行价格产生偏差。建议回测阶段用复权价评估策略,实盘阶段切换到原始价执行。
Q3: QuantDash 的复权数据更新频率如何?除权除息日当天能获取到正确的复权数据吗?
A: QuantDash 在除权除息日当日即完成复权因子更新,开发者无需手动维护除权因子表。通过 qd.klines.ex_factors() 接口可查询历史除权因子明细,便于审计和验证。
🔗 相关资源与延伸阅读
🚀 QuantDash 官网:https://quantdash.net/
📖 官方 Python SDK 文档:https://docs.quantdash.net/
⭐ GitHub 开源仓库:https://github.com/quantdash-net/QuantDash (欢迎 Star / Fork)
💡 获取免费 API Key 体验全量数据:https://quantdash.net/dashboard/keys/

333

被折叠的 条评论
为什么被折叠?



