QMT本地数据缓存详解:get_market_data、get_market_data_ex和get_local_data到底怎么选?
QMT本地数据缓存实战指南:三大核心API的精准选择策略
在量化交易开发中,数据获取是最基础却最关键的环节之一。迅投QMT平台提供了get_market_data、get_market_data_ex和get_local_data三个核心API用于本地数据缓存操作,但很多开发者在实际编码时常常陷入选择困惑。本文将深入剖析这三个函数的差异,通过实际场景演示如何根据需求精准选择最合适的API。
1. 三大API基础特性对比
在深入使用之前,我们需要先了解这三个函数的基本特性和差异。以下是它们的核心对比:
| 特性 | get_market_data | get_market_data_ex | get_local_data |
|---|---|---|---|
| 数据结构 | 双层字典 | 单层字典 | 单层字典 |
| 数据来源 | 本地+实时 | 本地+实时 | 仅本地 |
| 返回格式 | {代码:{字段:DataFrame}} | {代码:DataFrame} | {代码:DataFrame} |
| 实时数据订阅 | 支持 | 支持 | 不支持 |
| 性能表现 | 中等 | 较高 | 最高 |
| 适用场景 | 需要字段级访问 | 需要完整DataFrame | 纯本地操作 |
关键差异解析:
get_market_data返回的是双层嵌套字典结构,适合需要按字段单独处理的场景get_market_data_ex返回的是包含所有字段的完整DataFrame,适合需要整表操作的场景get_local_data仅访问本地缓存,不包含实时数据,适合纯历史数据分析
2. 数据结构差异与选择策略
2.1 get_market_data的双层字典结构
# 获取单个股票的多字段数据 data = xtdata.get_market_data( field_list=['open', 'close', 'high', 'low'], stock_list=['600519.SH'], period='1d', start_time='20230101', end_time='20231231' ) # 访问特定字段 close_prices = data['600519.SH']['close']这种结构的特点:
- 第一层键是股票代码
- 第二层键是字段名称
- 最终值是包含该字段历史数据的DataFrame
适用场景:
- 只需要特定字段而非全部数据时
- 需要对不同字段进行差异化处理时
- 内存有限,希望按需加载字段数据时
2.2 get_market_data_ex的单层DataFrame结构
# 获取多只股票的完整数据 data = xtdata.get_market_data_ex( field_list=['open', 'close', 'volume'], stock_list=['600519.SH', '000858.SZ'], period='1d', start_time='20230101', end_time='20231231' ) # 访问某只股票的完整数据 maotai_data = data['600519.SH']这种结构的特点:
- 单层字典,键是股票代码
- 值是包含所有请求字段的完整DataFrame
- 更适合pandas的链式操作
适用场景:
- 需要同时使用多个字段进行计算时
- 习惯使用pandas进行数据分析时
- 需要保持数据结构简单统一时
2.3 get_local_data的纯本地访问
# 仅获取本地缓存数据 local_data = xtdata.get_local_data( field_list=['open', 'close'], stock_list=['600519.SH'], period='1d', start_time='20230101', end_time='20231231' ) # 数据格式与get_market_data_ex相同 close_prices = local_data['600519.SH']['close']核心特点:
- 完全不依赖网络请求
- 数据仅来自之前下载的本地缓存
- 响应速度最快,稳定性最高
提示:在回测系统中,使用get_local_data通常是最佳选择,因为它避免了不必要的实时数据混入,保证回测的纯粹性。
3. 实时数据集成策略
3.1 混合实时数据的获取
get_market_data和get_market_data_ex都支持实时数据集成,但实现方式有所不同:
# 先订阅实时数据 xtdata.subscribe_quote(stock_list=['600519.SH'], period='1d') # 获取混合数据 mixed_data = xtdata.get_market_data_ex( field_list=['open', 'close'], stock_list=['600519.SH'], period='1d', start_time='20230101', end_time='' # 空字符串表示获取到最新 )实时数据集成要点:
- 必须先调用
subscribe_quote订阅行情 end_time参数留空表示获取到最新数据- 返回数据中,历史部分来自本地缓存,最新部分来自实时行情
3.2 实时数据更新机制
实时数据的更新遵循以下规则:
对于分钟线数据:
- 每收到一个新tick,会更新当前分钟的数据
- 分钟结束时,该分钟数据会被固化
对于日线数据:
- 交易日结束后,当日数据才会被完整记录
- 盘中获取的日线数据是临时值
典型问题解决方案:
# 监控面板数据更新示例 def update_dashboard(): # 使用get_market_data_ex获取最新数据 current_data = xtdata.get_market_data_ex( field_list=['close', 'volume'], stock_list=monitor_stocks, period='1d', start_time=last_update_date, end_time='' ) # 处理数据更新 for code, df in current_data.items(): if len(df) > last_record_count[code]: # 有新数据到达 new_records = df.iloc[last_record_count[code]:] update_visualization(code, new_records) last_record_count[code] = len(df)4. 性能优化实战建议
4.1 批量操作与缓存利用
# 不好的做法:循环获取单只股票数据 for stock in stock_list: data = xtdata.get_market_data_ex( field_list=['close'], stock_list=[stock], period='1d', start_time='20230101', end_time='20231231' ) process(data) # 好的做法:批量获取所有股票数据 all_data = xtdata.get_market_data_ex( field_list=['close'], stock_list=stock_list, # 整个列表一次传入 period='1d', start_time='20230101', end_time='20231231' ) for stock, df in all_data.items(): process(df)性能优化要点:
- 尽量减少API调用次数,使用批量操作
- 合理设置
start_time和end_time,避免获取不必要的数据 - 对于静态分析,优先使用
get_local_data
4.2 内存管理技巧
# 使用生成器处理大数据集 def batch_fetch(stock_list, batch_size=50): for i in range(0, len(stock_list), batch_size): batch = stock_list[i:i+batch_size] data = xtdata.get_local_data( field_list=['open', 'close', 'high', 'low'], stock_list=batch, period='1d', start_time='20000101', end_time='20231231' ) yield data # 分批处理 for batch_data in batch_fetch(large_stock_list): process_batch(batch_data)内存优化策略:
- 对于超大数据集,采用分批获取和处理
- 及时释放不再需要的数据引用
- 考虑使用
del显式删除大对象
5. 典型场景下的API选择
5.1 回测系统实现
# 回测专用数据获取函数 def get_backtest_data(stocks, fields, start_date, end_date): return xtdata.get_local_data( field_list=fields, stock_list=stocks, period='1d', start_time=start_date, end_time=end_date ) # 使用示例 backtest_data = get_backtest_data( stocks=['600519.SH', '000858.SZ'], fields=['open', 'close', 'volume'], start_date='20200101', end_date='20201231' )选择理由:
- 回测需要确定性的历史数据
- 不需要实时行情干扰
- 性能要求高,
get_local_data最快
5.2 实时监控面板
# 初始化订阅 xtdata.subscribe_quote( stock_list=monitor_stocks, period='1m' ) # 定时获取最新数据 def fetch_latest(): return xtdata.get_market_data_ex( field_list=['last_price', 'volume', 'amount'], stock_list=monitor_stocks, period='1m', start_time=last_hour_str, end_time='' )选择理由:
- 需要实时数据更新
get_market_data_ex的单层结构便于整体处理- 混合本地缓存和实时数据满足需求
5.3 大数据分析任务
# 大数据分析专用获取函数 def fetch_for_analysis(stocks, fields, start_date, end_date): # 第一步:确保数据已下载 xtdata.download_history_data2( stock_list=stocks, period='1d', start_time=start_date, end_time=end_date ) # 第二步:获取纯本地数据 return xtdata.get_local_data( field_list=fields, stock_list=stocks, period='1d', start_time=start_date, end_time=end_date )选择理由:
- 数据分析需要纯静态数据
- 提前确保数据完整性
- 大数据量下需要最佳性能
在实际开发中,我经常遇到需要根据不同的阶段选择不同的API。比如在策略研发初期使用get_local_data进行快速回测,而在实盘监控阶段切换到get_market_data_ex获取实时信息。理解每个API的特点和适用场景,可以显著提高开发效率和系统性能。
