问题描述
ContextInfo.get_market_data_ex 无法取得周线以上数据,但是知识库里面明明写着 period 的周期包含 1y,1mon,1q 这些。
改用 ContextInfo.get_market_data 就可以,但是知识库里面说不推荐使用这个,推荐使用 ContextInfo.get_market_data_ex?
解决方案
您好!这是一个在 QMT 平台开发中非常常见的问题。关于 ContextInfo.get_market_data_ex 无法获取周线及以上周期数据的情况,以下是详细的解答和替代方案:
1. 为什么 get_market_data_ex 无法获取周线以上数据?
仔细查阅 QMT 官方 API 文档可以发现,虽然旧版的 get_market_data 支持 '1w'、'1mon' 等长周期,但新版的 get_market_data_ex 在 period 参数的可选范围上做了限制。文档中明确指出 get_market_data_ex 的 period 可选范围为:
'tick':分笔数据'1m'、'5m'、'15m'等分钟周期'1d':日线数据'l2quoteaux'/'l2transactioncount':Level2 数据
结论:get_market_data_ex 接口在底层设计上目前确实不支持直接拉取周线(1w)、月线(1mon)、季线(1q)和年线(1y)数据。官方推荐使用 _ex 版本是因为它在获取日线及日内数据时性能更好、返回的 DataFrame 结构更标准,且支持订阅模式。
2. 推荐的替代方案
既然官方不推荐使用旧版的 get_market_data,您可以采用以下三种标准且高效的替代方案来获取周线及以上周期数据:
方案一:使用 ContextInfo.get_history_data(推荐用于策略回测/运行)
如果您是在策略的 handlebar 中需要获取股票池的历史长周期数据,get_history_data 是最正规的做法。它完全支持 '1w', '1mon', '1q', '1y'。
def init(ContextInfo):
ContextInfo.set_universe(['000300.SH'])
def handlebar(ContextInfo):
# 获取最近5根周线数据
his_data = ContextInfo.get_history_data(5, '1w', 'close', dividend_type=1)
print(his_data)
方案二:使用 get_market_data_ex 获取日线,通过 Pandas 重采样(推荐用于复杂数据分析)
如果您非常喜欢 get_market_data_ex 返回的 DataFrame 格式,可以先获取日线(1d)数据,然后利用 Python 强大的 pandas 库将其重采样(Resample)为周线或月线。这种方法非常灵活。
import pandas as pd
def handlebar(ContextInfo):
if not ContextInfo.is_last_bar():
return
# 1. 获取日线数据
data = ContextInfo.get_market_data_ex(
['open', 'high', 'low', 'close', 'volume'],
['000300.SH'],
period='1d',
count=100
)
df = data['000300.SH']
if df.empty:
return
# 2. 将索引转换为 datetime 格式
df.index = pd.to_datetime(df.index)
# 3. 使用 pandas 重采样为周线 (W) 或月线 (M)
# 定义 K 线合成规则
ohlc_dict = {
'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum'
}
weekly_df = df.resample('W-FRI').agg(ohlc_dict).dropna()
print("合成的周线数据:\n", weekly_df)
方案三:使用 ContextInfo.get_local_data(读取本地数据)
如果您已经通过 QMT 终端下载了周线/月线数据到本地,可以直接使用 get_local_data 读取,它同样支持 '1w', '1mon' 等周期。
def handlebar(ContextInfo):
if not ContextInfo.is_last_bar():
return
# 获取本地周线数据
local_data = ContextInfo.get_local_data(
stock_code='000300.SH',
period='1w',
count=10
)
print(local_data)
总结
虽然旧版 get_market_data 还能用,但为了策略的长期稳定性和兼容性,建议不要继续使用。如果需要长周期数据,首选 get_history_data;如果需要 DataFrame 格式进行复杂指标计算,首选 获取日线 + Pandas 重采样 的方式。