问题描述
解决方案
在 QMT 平台中,查询 ETF 基金的实时申赎清单(PCF)和 IOPV(基金份额参考净值)主要依赖于以下两个 API 函数:
get_etf_info(stockcode):用于获取 ETF 的申赎清单数据,返回结果包含现金差额、最小申赎单位、以及具体的成分股列表(包含代码和数量)。get_etf_iopv(stockcode):用于获取 ETF 当前的 IOPV 数值。
以下是完整的策略代码示例,展示了如何在 handlebar 中调用这两个接口并解析输出结果。
策略代码
# -*- coding: gbk -*-
def init(ContextInfo):
# 在初始化中设置要查询的 ETF 代码
# 例如:510050.SH (华夏上证50ETF)
ContextInfo.etf_code = '510050.SH'
print(f"策略初始化完成,准备查询 {ContextInfo.etf_code} 的 ETF 信息")
def handlebar(ContextInfo):
# 为了避免在历史K线上重复打印,仅在最新的一根K线(实时行情)上执行查询
if not ContextInfo.is_last_bar():
return
etf_code = ContextInfo.etf_code
# ============================================================
# 1. 获取 ETF 申赎清单 (包含成分股和数量)
# ============================================================
# get_etf_info 返回一个字典,Key 为时间戳,Value 为包含详细信息的字典
etf_info_map = get_etf_info(etf_code)
if etf_info_map:
# 通常我们取最新的一个时间戳的数据
# 注意:返回的数据可能包含多个时间点,这里演示遍历打印
for timetag, info in etf_info_map.items():
print("=" * 50)
print(f"【ETF 申赎清单信息】 代码: {info.get('etfCode')} 时间戳: {timetag}")
print(f"基金名称: {info.get('etfName')}")
print(f"最小申赎单位: {info.get('reportUnit')} 份")
print(f"现金差额: {info.get('cashBalance')} 元")
print(f"预估现金差额: {info.get('ecc')} 元")
print(f"是否允许申购: {'是' if info.get('enableCreation') == 1 else '否'}")
print(f"是否允许赎回: {'是' if info.get('enableRedemption') == 1 else '否'}")
# 获取成分股列表
components = info.get('stocks', [])
print(f"--- 成分股列表 (共 {len(components)} 只) ---")
# 打印前 5 只成分股作为示例,避免日志过长
for i, comp in enumerate(components):
if i < 5:
print(f"成分股代码: {comp['componentCode']}, "
f"名称: {comp['componentName']}, "
f"数量: {comp['componentVolume']}, "
f"替代标志: {comp['ReplaceFlag']}")
else:
print(f"... 剩余 {len(components) - 5} 只成分股未显示 ...")
break
else:
print(f"未查询到 {etf_code} 的申赎清单数据,请检查代码或数据权限。")
# ============================================================
# 2. 获取 ETF 实时 IOPV (基金份额参考净值)
# ============================================================
iopv = get_etf_iopv(etf_code)
print("-" * 50)
print(f"【ETF IOPV】 {etf_code} 当前参考净值: {iopv}")
print("=" * 50)
代码解析
-
get_etf_info(stockcode)返回结构:- 该函数返回的是一个字典
{timetag: valuedict}。 valuedict中包含了 ETF 的基础信息(如cashBalance现金差额,reportUnit最小申赎单位等)。- 关键字段
stocks是一个列表,列表中的每个元素是一个字典,代表一只成分股。 - 成分股字典包含:
componentCode(代码),componentName(名称),componentVolume(数量/股数),ReplaceFlag(替代标记) 等。
- 该函数返回的是一个字典
-
get_etf_iopv(stockcode)返回结构:- 直接返回一个浮点数(float),即当前的 IOPV 值。
-
运行环境:
- 请在 QMT 的“策略编辑器”中新建一个 Python 策略,将上述代码粘贴进去。
- 点击“运行”即可在下方的日志窗口看到输出结果。
- 注意:
get_etf_info获取的是 ETF 的 PCF(申购赎回清单)文件数据,通常在交易日盘前更新;get_etf_iopv是行情数据,盘中会实时变动。
常见问题 (Q&A)
Q: 为什么 get_etf_info 返回为空?
A: 可能原因有二:一是该 ETF 代码输入错误或该品种不支持申赎(非 ETF);二是本地缺少 ETF 申赎清单数据。请尝试在 QMT 客户端的【数据管理】中补充下载相关数据,或者确保连接的行情服务器正常。
Q: 成分股数量 componentVolume 是指什么?
A: 它指的是一个最小申赎单位(Basket)中,该成分股所需要的股票数量(股)。例如,如果最小申赎单位是 900,000 份,componentVolume 为 100,则表示申购 90 万份 ETF 需要 100 股该股票。
Q: get_etf_iopv 的更新频率是多少?
A: IOPV 通常由交易所每 15 秒计算并发布一次。QMT 获取的是交易所推送的最新快照值。
Q: 如何获取全部成分股而不是只打印前5个?
A: 代码示例中为了防止日志刷屏使用了 if i < 5 进行限制。如果您需要获取全部数据进行计算,直接遍历 components 列表即可,例如:all_stocks = [comp['componentCode'] for comp in components]。