摘要
用 Python 调统一行情 API 做跨市场任务时,code=0 只说明工具调用成功,不说明请求的品种已经完整返回。2026 年 6 月 13 日的 TickDB MCP get_ticker 实测中,同一批 symbol 在不同参数下返回集合截然不同:不传 type 时五类全回,传入 type=stock 时只剩三只股票,混入无效代码时静默缺失。本文给出一套 Python 批次完整性校验器,检查意外缺失、意外新增、重复项和类型错配,让数据不完整时关闭批次而非静默继续。
1. 批次成功,不等于横截面完整
量化任务处理跨市场数据时,通常隐含一个假设:一次请求拉回来的数据,是一个完整的横截面。
例如,一次查询同时包含 A 股、港股、美股、数字货币和外汇五类资产。如果返回结果中少了一类,而程序只检查 code=0,这份不完整数据就可能直接进入下游计算。
问题在于,任务状态和数据状态不是一回事。
在本轮 TickDB MCP get_ticker 测试中,code=0 只能说明本次工具调用成功。它不能替你回答以下问题:
- 返回的 symbol 集合是否符合预期?
- 有没有请求了却没有返回的 symbol?
- 有没有未请求却出现在结果中的 symbol?
- 请求或返回中有没有重复 symbol?
- 返回品种的资产类型是否正确?
一句话记住这个区别:批次成功是任务状态,横截面完整是数据状态。两者必须分别判断。
2. 资产缺失会怎样污染下游
假设某个任务定时获取五类资产的快照,用于跨市场比价、波动率矩阵或监控面板。某次请求中,数字货币品种没有返回,但任务仍然显示成功。此时可能出现三类问题:
比率计算失真。 如果计算依赖 A 股和数字货币的价格比,数字货币缺失后,这个比率要么无法计算,要么被错误地填入上一期缓存值。前者应当中断,后者则制造一条看起来正常、实际上已经失真的结果。
权重发生偏移。 如果面板按照资产类别分配权重,少了一类资产后,其余类别的相对权重可能被动提高。此时波动率、风险暴露等指标的统计口径已经改变,但系统未必报错。
出现监控盲区。 如果告警规则是"任意资产波动超过阈值",缺失的资产自然不会触发告警。这不代表市场没有变化,只代表数据没有进入系统。
这些问题的共同特点是:静默。 程序没有崩溃,任务没有报错,结果表也可能正常生成,但计算输入已经不完整。
3. 实测:code=0 对应三种不同的数据状态
以下测试于 2026 年 6 月 13 日 通过 TickDB MCP get_ticker 完成。测试只核对返回状态 code、请求 symbol、返回 symbol 和返回资产类型 type。价格、成交量和 timestamp 属于动态行情,不作为本文结论依据。
测试一:不传 type
请求五个代表品种:600519.SH、700.HK、AAPL.US、BTCUSDT、EURUSD。
脱敏后的关键结果为:
json
{
"code": 0,
"returned": [
{"symbol": "700.HK", "type": "stock"},
{"symbol": "BTCUSDT", "type": "crypto"},
{"symbol": "EURUSD", "type": "forex"},
{"symbol": "AAPL.US", "type": "stock"},
{"symbol": "600519.SH", "type": "stock"}
]
}
五个请求品种均有返回。注意,返回顺序不应被当作请求顺序------集合完整性检查应比较 symbol 集合,而不是依赖数组位置。
测试二:传入 type=stock
使用相同的五个 symbol,并传入 type=stock。脱敏后的关键结果为:
json
{
"code": 0,
"returned": [
{"symbol": "700.HK", "type": "stock"},
{"symbol": "AAPL.US", "type": "stock"},
{"symbol": "600519.SH", "type": "stock"}
]
}
只返回了三只股票。BTCUSDT 和 EURUSD 没有返回。如果任务在请求前已将这两个 symbol 声明为"针对当前工具验证过的预期排除项",本批次可以降级放行。如果程序并不知道它们会被排除,只看到 code=0 就继续运行,相同结果就应被视为集合不完整。关键不在于"缺失了什么",而在于:缺失是否提前声明、是否经过验证、是否被写入批次状态。
测试三:混入无效代码
请求 AAPL.US 和 NOTREAL。脱敏后的关键结果为:
json
{
"code": 0,
"returned": [
{"symbol": "AAPL.US", "type": "stock"}
]
}
NOTREAL 没有出现在返回结果中,但本次调用仍然返回 code=0。如果 NOTREAL 不是事先声明的预期排除项,这就是一次意外缺失。生产任务不应将其视为完整批次。
三组结果归纳如下:
| 本轮调用状态 | 返回集合状态 | 数据判断 |
|---|---|---|
code=0 |
五个请求 symbol 全部返回 | 完整 |
code=0 |
与当前工具已验证的预期排除一致 | 降级 |
code=0 |
无效或异常 symbol 静默缺失 | 不完整 |
结论:code=0 之后仍然需要一次独立的数据完整性判断。
4. 什么时候允许下游继续
在 MCP 调用与下游计算之间增加一道完整性闸门:
| 任务状态 | 数据状态 | 是否放行 | 处理动作 |
|---|---|---|---|
| 成功 | 返回集合完整,无重复,类型一致 | 是 | 正常进入下游 |
| 成功 | 仅缺少事先声明且已验证的预期排除项 | 降级放行 | 记录排除条件和缺失项 |
| 成功 | 存在意外缺失、意外新增、重复或类型错误 | 否 | 关闭批次并告警 |
| 失败 | 未获得有效结果 | 否 | 按错误状态处理 |
完整批次至少应满足:返回集合 = 请求集合 - 预期排除集合 ,并且没有意外缺失、没有意外新增、请求和返回中没有重复 symbol、返回 type 与预期资产类型一致、预期排除项没有意外出现在返回中。
边界提醒:单一市场简单查询不必强求这套跨市场完整性校验。如果你只是偶尔查一两只股票的价格,MCP 或 REST 单次查询就够。跨市场任务才需要关注批次完整性。
5. Python 批次完整性校验器
校验分三步:请求前定义预期 → 返回后提取实际集合 → 执行多维比对。
以下代码是教学示例,不是生产级代码。生产环境还需要补充日志、异常捕获、批次 ID、重试策略和指标上报。
python
def validate_cross_market_batch(
requested: list,
returned: list,
expected_excluded: set = None,
):
"""教学示例,非生产级代码。
Args:
requested: 请求记录列表,每项为 (symbol, expected_type)。
returned: 返回记录列表,每项为 (symbol, actual_type)。
expected_excluded: 事先声明且已针对当前工具验证的预期排除 symbol。
Returns:
(是否允许继续, 诊断信息)
"""
if expected_excluded is None:
expected_excluded = set()
# 所有记录必须是包含 symbol 和 type 的二元组
for index, item in enumerate(requested):
if not isinstance(item, tuple) or len(item) != 2:
return False, f"请求记录结构无效: 索引 {index}"
if not item[0] or not item[1]:
return False, f"请求记录字段为空: 索引 {index}"
for index, item in enumerate(returned):
if not isinstance(item, tuple) or len(item) != 2:
return False, f"返回记录结构无效: 索引 {index}"
if not item[0] or not item[1]:
return False, f"返回记录字段为空: 索引 {index}"
requested_symbols = [item[0] for item in requested]
returned_symbols = [item[0] for item in returned]
requested_set = set(requested_symbols)
returned_set = set(returned_symbols)
# 预期排除项必须来自本次请求
invalid_exclusions = expected_excluded - requested_set
if invalid_exclusions:
return (
False,
f"配置错误,预期排除项不在请求集合中: {invalid_exclusions}",
)
issues = []
requested_duplicates = [
symbol
for symbol in requested_set
if requested_symbols.count(symbol) > 1
]
if requested_duplicates:
issues.append(f"请求重复: {requested_duplicates}")
returned_duplicates = [
symbol
for symbol in returned_set
if returned_symbols.count(symbol) > 1
]
if returned_duplicates:
issues.append(f"返回重复: {returned_duplicates}")
# 预期排除的 symbol 不应出现在返回集合中
unexpectedly_included = returned_set & expected_excluded
if unexpectedly_included:
issues.append(
f"预期排除项意外返回: {unexpectedly_included}"
)
missing = requested_set - returned_set
unexpected_missing = missing - expected_excluded
expected_missing = missing & expected_excluded
unexpected_extra = returned_set - requested_set
if unexpected_missing:
issues.append(f"意外缺失: {unexpected_missing}")
if unexpected_extra:
issues.append(f"意外新增: {unexpected_extra}")
requested_types = dict(requested)
returned_types = dict(returned)
type_mismatches = []
for symbol in requested_set & returned_set:
expected_type = requested_types[symbol]
actual_type = returned_types[symbol]
if expected_type != actual_type:
type_mismatches.append(
f"{symbol}: 预期 {expected_type}, 实际 {actual_type}"
)
if type_mismatches:
issues.append(f"类型不一致: {type_mismatches}")
if issues:
return False, "批次关闭: " + "; ".join(issues)
if returned_set == requested_set and not expected_excluded:
return True, "完整通过"
if returned_set == requested_set - expected_excluded:
return True, f"降级继续,预期排除: {expected_missing}"
return False, "批次关闭: 返回集合状态异常"
使用示例 :五类资产构造预期集合,传入 type=stock 时声明 BTCUSDT 和 EURUSD 为预期排除项:
python
requested = [
("600519.SH", "stock"),
("700.HK", "stock"),
("AAPL.US", "stock"),
("BTCUSDT", "crypto"),
("EURUSD", "forex"),
]
returned = [
("600519.SH", "stock"),
("700.HK", "stock"),
("AAPL.US", "stock"),
]
allowed, message = validate_cross_market_batch(
requested,
returned,
expected_excluded={"BTCUSDT", "EURUSD"},
)
print(allowed, message)
# True 降级继续,预期排除: {'BTCUSDT', 'EURUSD'}
本文以 TickDB 为可复核实测对象 :以上三组测试结果来自 TickDB MCP
get_ticker的 2026 年 6 月 13 日实测。TickDB 在本文中的角色是提供结构化返回,让校验器有明确的 request vs return 集合可比对------跨市场任务的数据完整性判断,前提正是接口返回的 symbol 和 type 字段可解析、可核对。具体字段以 TickDB 官方文档为准:https://docs.tickdb.ai。
6. 校验器也需要反例测试
仅测正常数据不够。完整性校验器必须证明自己会在异常情况下关闭批次。以下反例证明的是客户端校验逻辑,不是 MCP 本身会产生这些异常。
反例一:预期排除项意外返回。 BTCUSDT 已被声明为预期排除项,却出现在返回结果中。校验器应返回 False 批次关闭: 预期排除项意外返回。
反例二:返回记录缺少类型。 某条记录的 type 为空字符串。校验器应返回 False 返回记录字段为空。
反例三:返回记录结构不一致。 数组中混入了非二元组元素。校验器应返回 False 返回记录结构无效。
反例四:资产类型错配。 某品种预期 stock,实际返回 index。校验器应返回 False 批次关闭: 类型不一致。
这些反例证明的是:MCP 调用负责提供结构化返回;是否允许这批数据进入下游,仍然要由你的程序决定。
7. 量化工程师检查清单
每次跨市场任务进入下游前,逐项确认:
- 已定义请求 symbol 和预期资产类型
- 已保存本次请求的原始 symbol 集合
- 预期排除项已经针对当前工具验证
- 已从返回结果中提取 symbol 和 type
- 已检查请求与返回中的重复 symbol
- 已检查意外缺失
- 已检查意外新增
- 已检查资产类型错配
- 已检查预期排除项是否意外返回
- 意外异常会关闭批次,而不是只打印警告
- 降级批次会记录排除条件和缺失项
- 下游只消费通过完整性检查的批次
- 新工具、新端点或新资产类别接入时,会重新验证实际行为
8. 不能从本文推出什么
- 三组结果仅来自 2026 年 6 月 13 日的 TickDB MCP
get_ticker调用 - 本轮
code=0行为不代表其他 MCP 工具具有相同行为 - MCP 实测不能直接证明 REST、WebSocket、K 线或逐笔接口的行为
- 五个代表品种成功返回,不表示所有品种在所有时间均可用
- 重复项、意外新增和类型错配的关闭行为,由客户端校验器反例证明,不是 MCP 异常实测
- 下游比率失真、权重偏移和监控盲区属于工程风险推演,不是 MCP 返回结论
- 本文不涉及策略收益、回测绩效或买卖决策,不构成投资建议
📡 本文实测数据来自 TickDB MCP get_ticker(2026-06-13),文档见 https://docs.tickdb.ai
⚠️ 本文为技术教程,不构成任何投资建议
CSDN 标签
Python、多市场行情API、symbol校验、code=0、TickDB