问题描述
解决方案
在 QMT(Quantitative Master Trading)量化交易平台中,get_history_data 和 get_market_data_ex 都是用于获取历史行情数据的接口,但它们的设计初衷、数据结构和使用场景有显著区别。
以下是两者的详细对比及推荐建议:
1. 核心区别对比
| 特性 | get_history_data |
get_market_data_ex |
|---|---|---|
| 依赖关系 | 强依赖 ContextInfo.set_universe()。必须先设置股票池,该函数只获取股票池内的数据。 |
独立。可以直接传入股票代码列表 (stock_code),不需要依赖 set_universe。 |
| 返回数据结构 | Dict { code : List }。 返回一个字典,Value 是 Python 原生 List。 |
Dict { code : DataFrame }。 返回一个字典,Value 是 Pandas DataFrame。 |
| 时间控制 | 仅支持 len 参数(获取最近 N 根 K 线)。无法指定具体的开始和结束时间。 |
支持 start_time、end_time 和 count。可以精确指定时间段,也可以指定数量。 |
| 数据字段 | 字段较固定(open, high, low, close 等)。 | 字段更丰富,支持 Level2 数据(如 l2quoteaux 等,需权限)。 |
| 复权处理 | 支持(参数 dividend_type)。 |
支持(参数 dividend_type),且默认为 follow(跟随主图)。 |
| 主要用途 | 用于编写简单的、基于循环的逻辑,或者不需要 Pandas 复杂计算的场景。 | 用于现代量化分析,结合 Pandas 进行向量化计算、数据清洗和复杂策略开发。 |
2. 详细解析
A. get_history_data
这是 QMT 较早期的接口,设计逻辑更偏向于传统的逐 K 线运行模式。
- 优点:
- 结构简单,对于不懂 Pandas 的初学者,处理 List 比较直观。
- 在
handlebar机制下,配合set_universe使用,代码量较少。
- 缺点:
- 数据处理麻烦:返回的是 List,如果要做均线、MACD 等计算,通常需要自己写循环或者先转换成 Numpy/Pandas 格式,效率较低且代码冗余。
- 灵活性差:无法获取指定历史时间段的数据(只能取最近 N 个)。
代码示例:
# 必须先设置股票池
ContextInfo.set_universe(['600000.SH'])
# 获取最近 5 天的收盘价
# 返回结构: {'600000.SH': [10.1, 10.2, 10.3, 10.4, 10.5]}
history_data = ContextInfo.get_history_data(5, '1d', 'close')
B. get_market_data_ex
这是 QMT 推荐使用的增强版接口(ex 代表 extension/enhanced),专门为 Python 量化生态(主要是 Pandas)优化。
- 优点:
- 原生 Pandas 支持:直接返回 DataFrame,可以直接调用
df.mean(),df.rolling(),df.apply()等强大的数据分析方法。 - 灵活性极高:可以随意指定任意股票列表、任意时间段。
- 信息全面:索引包含时间戳,列包含数据字段,数据对齐更方便。
- 原生 Pandas 支持:直接返回 DataFrame,可以直接调用
- 缺点:
- 需要用户具备一定的 Pandas 库基础知识。
代码示例:
# 直接获取,无需 set_universe
# 返回结构: {'600000.SH': DataFrame(index=time, columns=['open', 'close'...])}
data_map = ContextInfo.get_market_data_ex(
['open', 'close'],
['600000.SH'],
period='1d',
count=5
)
df = data_map['600000.SH']
# 直接计算均线
ma5 = df['close'].mean()
3. 哪个更好用?
结论:强烈推荐使用 get_market_data_ex。
理由如下:
- 数据分析能力:量化策略通常涉及大量的统计计算(如均线、标准差、协方差),Pandas DataFrame 是 Python 数据分析的标准载体。
get_market_data_ex直接对接 Pandas,避免了繁琐的数据类型转换。 - 灵活性:在回测或实盘中,你经常需要获取"上个月"或"特定日期区间"的数据,
get_history_data无法满足此需求,而get_market_data_ex可以。 - 未来兼容性:
get_market_data(无 ex 版本)已被官方标记为不建议使用,get_market_data_ex是官方主推的接口,维护和支持会更好。
4. 总结建议
- 如果你是 Python 初学者,且策略逻辑非常简单(例如:今天收盘价大于昨天收盘价就买入),不涉及复杂指标计算,可以使用
get_history_data。 - 如果你是 专业量化开发者,或者需要计算技术指标(MA, KDJ, 布林带等)、进行因子分析、处理多只股票的数据对齐,请务必使用
get_market_data_ex。
Q&A: QMT 数据接口常见问题
Q: get_market_data (不带 ex) 和 get_market_data_ex 有什么区别?
A: get_market_data 是旧版接口,返回的数据结构非常复杂(根据参数不同,可能返回值、Series、DataFrame 或 Panel),极易导致代码出错。官方文档明确建议不再使用该接口,改用 get_market_data_ex,后者返回结构统一且清晰。
Q: get_market_data_ex 获取的数据包含停牌填充吗?
A: 可以通过参数 fill_data 控制。默认为 True(暂不可用,具体视版本而定),通常建议在获取 DataFrame 后使用 Pandas 的 fillna 方法(如 ffill 前向填充)来处理停牌数据,这样更可控。
Q: 为什么 get_market_data_ex 返回的是字典而不是直接返回 DataFrame?
A: 因为该接口支持同时查询多只股票。字典的 Key 是股票代码,Value 是该股票对应的 DataFrame。即使只查询一只股票,返回的也是包含一个键值对的字典。
Q: 如何将 get_market_data_ex 返回的字典转换为一个大的 DataFrame?
A: 可以使用 pandas.concat。例如:df_all = pd.concat(data_map.values(), keys=data_map.keys()),这样可以创建一个多级索引的 DataFrame,方便进行截面分析。