问题描述
我的是 期货账号
周期: 1分钟
快速计算: 10
环境:模型研究【运行模式】
(1)序号10 之前, call_vba 每1分钟计算一次值 都是不同的。 这个是正常的
(2)序号10 之后, call_vba 到当前时间后 就维持 序号10 的值 不再变化了, 这个不正常
不知道这是为什么 call_vba计算值 到当前时间后 不再变化 , 有大佬知道的吗?
解决方案
在 QMT 平台中遇到 call_vba 在历史 K 线上计算正常,但在最新 K 线(当前时间)上数值不再变化的问题,通常与 QMT 的底层运行机制以及 VBA 指标的计算缓存有关。
为什么会出现这种情况?
根据 QMT 的运行机制(详见文档 1.2.3 Python 交易函数运行机制):
- 历史 K 线阶段:模型逐根 K 线运行,每根 K 线调用一次
handlebar,此时call_vba会根据确定的历史 K 线数据计算出准确的值。 - 实时行情阶段(最新 K 线):当运行到最后一根未走完的 K 线时,每来一个 tick 数据,
handlebar就会被触发一次。然而,部分通过call_vba调用的底层指标在设计上可能存在缓存机制,或者仅在 K 线闭合(走完)时才更新其内部状态,导致在盘中 tick 驱动时,返回的始终是该 K 线初始或上一次闭合时的值。
解决方案与建议
为了解决实时行情下指标不更新的问题,建议采用以下几种方法:
方法一:使用 Python 原生库替代 call_vba(强烈推荐)
QMT 平台内置了丰富的 Python 第三方库(如 Pandas、NumPy 和 TA-Lib)。使用 Python 原生代码计算指标,不仅可以避免 call_vba 的黑盒缓存问题,还能确保在每个 tick 到来时都能基于最新价格实时计算。
示例:使用 TA-Lib 计算均线替代 VBA 的 MA
#coding:gbk
import talib
import numpy as np
def init(ContextInfo):
ContextInfo.set_universe(['IF.IF']) # 设置期货主力合约
def handlebar(ContextInfo):
# 获取包含最新 tick 价格的 K 线数据
df = ContextInfo.get_market_data(['close'], stock_code=ContextInfo.get_universe(), period='1m', count=15)
if df.empty or len(df) < 10:
return
# 提取收盘价序列
close_prices = df['close'].values
# 使用 TA-Lib 实时计算 10 周期均线
ma10 = talib.SMA(close_prices, timeperiod=10)
# 打印最新值,盘中每个 tick 都会实时更新
print(f"当前 Bar 索引: {ContextInfo.barpos}, 最新 MA10: {ma10[-1]}")
方法二:检查是否被 is_last_bar() 限制
请检查您的代码中是否使用了 ContextInfo.is_last_bar() 或 ContextInfo.is_new_bar()。如果在 call_vba 外层加了条件判断,可能会导致在盘中 tick 刷新时跳过了计算逻辑。
方法三:强制获取最新分笔数据辅助计算
如果您必须依赖某些特定的逻辑,可以在 handlebar 中使用 ContextInfo.get_full_tick() 获取最新的分笔数据,手动将最新价(lastPrice)拼接到历史序列中进行计算,以确保计算结果包含最新的市场变化。
总结:call_vba 主要用于兼容旧版公式,在实时高频(Tick 级别)驱动下表现可能不如预期。在 Python API 环境下,直接使用 ContextInfo.get_market_data 获取数据并结合 TA-Lib 或 Pandas 进行计算,是解决此类不刷新问题的最佳实践。