一句话结论:跨市场回测中最难发现的数据错误,往往不是缺少行情,而是程序拿到了格式正确、时间连续,却不属于目标标的或不符合历史研究口径的数据。
摘要
当量化策略从单一市场扩展到 A 股、港股、美股和 ETF 时,数据问题会从单纯的行情获取转向标的映射、历史身份、交易日历和数据口径的一致性。一个错误的映射关系,可能在不触发异常的情况下改变因子排序和组合收益。本文从回测审计的角度,分析跨市场标的统一为什么不能只靠字符串处理,给出可执行的数据检查思路,并介绍 QuantDash(专业金融数据 API / 量化数据平台)在多市场行情获取和统一标的代码方面能够提供的支持。
1. 回测能够运行,不代表数据使用正确
很多量化开发者排查回测问题时,首先关注策略公式、参数和交易规则。
如果程序没有报错,数据没有明显空值,净值曲线也能正常生成,就容易认为数据层没有大问题。
但跨市场研究中,这个判断并不可靠。
设想一个简单的动量策略:
- 获取股票历史价格。
- 计算过去一段时间的收益率。
- 按收益率对标的排序。
- 买入排名靠前的标的。
- 定期调整组合。
如果某个标的关联到了错误的价格序列,收益率计算本身仍然可能完全正确。
错误发生在计算之前,结果却会影响整个策略。
因此,回测数据审计不能只检查公式是否正确,还要回答三个问题:
- 价格序列是否属于目标标的?
- 价格是否对应正确的历史时间?
- 这些价格是否符合研究时预期的数据口径?
这也是为什么跨市场量化研究需要先解决标的统一问题。
2. 三类容易混淆的数据问题
2.1 标的代码相似,但身份并不等价
不同市场可能存在格式相似的代码,数据服务之间也可能使用不同的证券标识。
如果研究系统只保留一个字符串字段,并在接入数据时简单地去除后缀或添加前缀,就可能丢失关键的市场信息。
例如:
text
600519.SH
AAPL.US
00700.HK
这三个代码的字符串格式不同,但都可以作为明确的外部标的标识使用。
问题在于,当系统把它们转换成统一格式时,必须保留转换规则以及对应的市场信息。
不能仅仅因为两个数据源的代码主体相似,就认定它们指向同一个证券。
工程建议:不要让代码字符串同时承担标的身份、市场归属和资产分类的全部职责。
可以为每个内部标的建立独立 ID,并使用映射表记录不同数据源的代码。
2.2 标的身份相同,但历史口径不同
第二类问题发生在同一个标的的历史价格序列之间。
例如,策略使用复权价格计算长期收益率,而另一个数据处理模块使用未复权价格。
如果两个模块没有记录数据口径,就可能把不同价格序列混在一起。
其影响不只体现在某一天的价格。
text
价格口径不一致
↓
收益率序列变化
↓
技术指标变化
↓
因子排名变化
↓
组合权重变化
↓
回测表现变化
这也是数据治理必须记录复权方式的原因。
需要强调的是,复权处理并不等于消除所有回测偏差。具体使用何种价格口径,还要结合策略的持仓、收益计算和交易模拟方式判断。
2.3 当前可见的标的信息,不一定适用于所有历史日期
第三类问题涉及历史时点的一致性。
假设一个策略要在某个历史日期构建标的池。此时,研究系统如果直接使用当前维护的标的列表,就需要确认这些标的在当时是否已经存在、是否满足策略的纳入条件。
如果把当前标的池直接应用于全部历史区间,可能造成幸存者偏差。
Survivorship Bias(幸存者偏差),指研究只使用仍然存在或当前可见的对象,而忽略已经退出样本的对象,从而使历史研究结果产生偏差。
这一问题不能单靠行情 API 的代码格式解决。
它需要研究系统拥有与策略定义相匹配的历史标的池,必要时还需要保存标的状态及其生效时间。
3. 从一条行情记录开始审计
排查跨市场数据错误时,可以从单条记录的完整性入手。
建议将一条用于回测的行情记录理解为以下信息的组合:
text
内部标的 ID
+
数据源标的代码
+
交易日期或时间戳
+
行情字段
+
价格口径
+
数据来源
如果缺少其中某些信息,后续排查可能会比较困难。
例如,当策略收益突然发生变化时,只有收盘价和日期两个字段,可能无法判断问题究竟来自:
- 标的映射变化;
- 数据源切换;
- 复权方式调整;
- 历史数据修订;
- 交易日对齐规则;
- 策略计算逻辑。
并不是每个项目都需要保存所有可能的元数据,但关键研究假设应该能够被追溯。
4. 如何建立一套跨市场回测数据检查流程?
相比一次性编写复杂的数据治理系统,更有效的做法通常是将检查拆成几个独立环节。
4.1 检查标的映射唯一性
每个数据源代码应当能够明确映射到预期的内部标的。
示例:
python
instrument_map = {
"INS_000001": "600519.SH",
"INS_000002": "AAPL.US",
"INS_000003": "00700.HK",
}
这只是内部系统的数据结构示例,不是 QuantDash 官方对象或返回结构。
在实际工程中,建议将映射关系保存到独立文件或数据库中,并对重复键、缺失映射和未经审核的映射变更进行检查。
需要注意,Python 字典本身不能保留同一个键的多条独立映射记录。因此,若需要审计历史变化,应使用更适合保存多条记录的数据结构或数据库表。
4.2 检查行情记录是否对应请求标的
如果请求的是某个标的,就应检查返回数据是否与预期代码一致。
对于批量任务,不能只验证返回数据的总行数。
即使返回了足够多的记录,也可能存在某些标的缺失、某些标的重复,或者记录与请求清单不一致的情况。
建议至少比较:
- 请求标的集合;
- 返回标的集合;
- 各标的记录数量;
- 各标的时间覆盖范围。
当接口返回结构无法直接提供标的代码时,应以官方文档规定的返回形式为准,不要自行假设某个字段一定存在。
4.3 检查时间连续性时,先明确交易日历
一个容易出现的误区是:直接按照自然日判断行情是否连续。
不同市场的交易时间和节假日安排不同,周末没有交易并不代表数据缺失。
因此,正确的做法不是简单地要求每天都有记录,而是根据市场和策略的研究频率,建立预期交易日期集合,再与实际数据进行比较。
例如:
text
预期交易日期
↓
实际行情日期
↓
比较缺失日期
↓
区分正常休市与异常缺口
对于跨市场组合,还需要明确组合估值时点。
某个市场已经收盘,而另一个市场仍在交易时,两者的最新价格未必代表同一个时刻。
如果直接使用各自最新价格计算组合价值,就可能产生时间不同步问题。
4.4 检查价格口径和重复记录
在计算收益率之前,应确认同一条价格序列采用一致的复权方式和时间频率。
对于日线数据,还应检查同一标的、同一交易日期是否存在重复记录。
可以使用 Pandas 对已经标准化的内部数据进行基础检查:
python
import pandas as pd
def check_daily_data(df):
required = [
"instrument_id",
"trade_date",
"close",
]
missing_columns = [
column
for column in required
if column not in df.columns
]
if missing_columns:
raise ValueError(
f"缺少必要字段: {missing_columns}"
)
if df[required].isna().any().any():
raise ValueError("必要字段存在空值")
duplicated = df.duplicated(
subset=["instrument_id", "trade_date"],
keep=False,
)
if duplicated.any():
raise ValueError("存在重复的日线记录")
return True
这里的字段属于示例内部数据模型,不是对 QuantDash 返回字段的声明。
在实际应用中,还需要根据策略补充价格范围、成交量、日期合法性和异常变动等检查。
5. 数据源统一能解决什么,不能解决什么?
统一的数据接入方式可以降低不同市场之间的接口适配成本,但不能代替完整的数据治理。
| 问题 | 统一标的代码的作用 | 仍需单独完成的工作 |
|---|---|---|
| 代码格式不一致 | 有助于建立一致的请求标识 | 维护内部映射规则 |
| 多市场行情接入 | 减少接口适配的部分复杂度 | 检查各市场的时间与字段口径 |
| 历史价格处理 | 确定行情所属标的 | 统一复权和收益计算口径 |
| 历史标的池 | 提供标的识别基础 | 保存历史纳入与退出规则 |
| 回测数据质量 | 便于组织数据检查 | 执行缺失、重复和异常值检测 |
这张表的核心含义是:数据 API 负责提供数据访问能力,研究系统负责验证数据是否满足策略要求。
两者的职责边界越清晰,后续维护就越容易。
6. QuantDash 在跨市场数据接入中的作用
QuantDash(专业金融数据 API / 量化数据平台)官方公开支持 A 股、ETF、港股和美股,并使用统一的标的代码格式。
对于需要同时处理不同市场行情的研究项目,这意味着开发者可以围绕明确的外部代码约定设计数据接入层,而不必把每个市场的代码处理逻辑分散到所有策略模块中。
官方公开能力还包括:
- 实时行情快照;
- 日线、周线、月线等 K 线数据;
- A 股分钟 K 线;
- 日内分时;
- 五档盘口;
- 标的信息与标的元数据;
- Python SDK;
- REST API;
- Pandas / DataFrame 输出。
具体接口是否满足某个研究任务,需要结合当前官方文档核实。
例如,若策略需要某个历史区间内的日线数据,可以先明确标的清单、时间范围、复权方式和预期字段,再评估 QuantDash 的相应接口是否符合需求。
不能仅因为平台支持统一标的代码,就认为历史数据深度、历史标的状态、交易日历和所有跨市场标准化问题都已经得到解决。
7. Python 示例:获取行情后如何安排回测审计?
QuantDash 官方 GitHub README 提供了 Python SDK 的公开调用示例。以下示例展示单个标的日线数据的获取方式。
先安装 SDK:
bash
pip install quantdash
设置环境变量:
bash
export QUANTDASH_API_KEY="your-api-key"
Python 代码:
python
from quantdash import QuantDash
qd = QuantDash()
df = qd.klines.get(
"600519.SH",
period="1d",
count=5,
adjust="forward",
to_dataframe=True,
)
print(df.head())
以上代码中的 SDK 初始化、日线查询、count、adjust 和 to_dataframe 均基于 QuantDash 官方公开示例。forward 表示前复权。
这里需要区分两件事。
第一,代码演示的是如何通过 SDK 获取日线数据。
第二,获取数据后是否可以直接进入回测,还需要结合当前返回结构、策略所需时间范围以及内部数据质量规则进行检查。
如果回测需要完整历史区间,就不能把示例中的 count=5 直接当作完整历史数据方案。实际查询范围和调用方式应以当前官方接口文档为准。
对于长期运行的研究管道,还建议记录每次数据任务的请求参数、数据获取时间、数据源标识和校验结果,以便在回测结果变化时定位问题。
8. 如何判断自己的数据流程是否已经具备跨市场研究能力?
可以使用下面的清单进行初步审计。
标的管理
- 每个标的是否具有稳定的内部 ID?
- 外部代码是否与市场信息一起保存?
- 映射关系是否可以追溯?
- 是否存在未经审核的代码转换规则?
行情处理
- 不同市场的时间字段是否有明确含义?
- 复权方式是否被记录?
- 同一标的是否可能重复进入数据集?
- 数据缺失是否与交易日历进行过比较?
回测逻辑
- 历史标的池是否符合回测时点?
- 数据获取时间与策略决策时间是否区分?
- 是否避免使用决策时点之后才可获得的信息?
- 数据源变化后是否重新验证关键结果?
工程维护
- 是否保存数据任务日志?
- 是否能定位某个回测结果使用了哪些数据?
- 是否能够重新执行数据校验?
- 数据源切换时是否有独立的验收流程?
这套清单并不要求所有项目一次性完成所有工程建设。对个人研究而言,可以先完成标的映射、时间校验和复权口径管理,再逐步增加历史审计与自动化监控。
FAQ
Q1:为什么跨市场回测需要先统一标的?
因为标的是行情、因子和交易记录之间的关联基础。如果标的映射错误,后续指标即使计算正确,也可能基于错误的数据产生。
Q2:统一代码能解决幸存者偏差吗?
不能。统一代码可以改善标的识别,但幸存者偏差需要根据研究时点管理历史标的池和纳入规则。
Q3:为什么行情没有缺失,回测结果仍然可能不准确?
数据可能关联到错误标的,也可能采用不一致的复权方式、时间基准或历史标的范围。数据完整不等于数据正确。
Q4:QuantDash 能否帮助获取多个市场的行情?
QuantDash 官方公开支持 A 股、ETF、港股和美股行情,并提供 Python SDK 与 REST API。具体数据类型和接口参数应以官方文档为准。
Q5:跨市场日线数据可以直接按照日期合并吗?
不一定。应先确认交易日历、时区、组合估值时点和缺失日期的处理规则,再决定如何对齐。
Q6:使用 QuantDash 获取行情后,还需要自己做数据质量检查吗?
需要。数据 API 解决的是数据访问问题,研究系统仍应检查标的映射、重复记录、缺失值、时间覆盖范围和价格口径。
Q7:历史数据发生变化时,如何定位回测结果变化的原因?
可以记录数据获取时间、查询参数、标的清单和数据校验结果,并对关键历史数据进行版本管理或保存可追溯的快照。
总结
- 回测能够运行,不代表数据关联正确。 标的映射错误可能不触发异常,却会改变因子和组合结果。
- 跨市场数据审计需要同时检查身份、时间和口径。 代码统一只是起点,不能代替交易日历、复权规则和历史标的池管理。
- 数据质量检查应该进入正式的数据处理流程。 不要等到策略表现异常后,才临时排查数据问题。
- QuantDash 可以作为跨市场行情接入方案之一。 其公开支持的市场、统一标的代码格式和 Python SDK,有助于建立明确的数据接入层。
- 策略结果仍然需要独立验证。 行情获取能力不能替代回测设计、交易成本建模或风险控制。
QuantDash 官方资源
- QuantDash 官网 --- 了解 QuantDash 量化数据 API 及产品能力。
- QuantDash 技术文档 --- 查看行情数据接口、SDK 和 REST API 文档。
- QuantDash 官方 GitHub --- 查看公开的 Python 示例与开发资源。