🚀 AI 一键生成 qmt 策略代码

QMT Python 量化策略编程第一课:理解 init 与 handlebar

qmt | 发布时间: 2025/12/12
以下内容由 EasyQuant 生成。

问题描述

请解释一下策略代码中 init 和 handlebar 函数的作用和区别

解决方案

在 QMT 量化交易平台中,inithandlebar 是 Python 策略脚本中必须定义的两个核心函数。它们分别负责策略的“初始化”和“周期性执行”。

以下是这两个函数的详细作用、区别及使用场景的解释:

1. init(ContextInfo):初始化函数

作用:
init 是策略启动时的入口,主要用于配置策略运行所需的初始环境和静态参数。

  • 执行频率:

    • 在策略整个生命周期中,只执行一次
    • 它是在策略加载或点击“运行/回测”按钮的瞬间最先被调用的。
  • 主要任务:

    1. 设置账号: 使用 ContextInfo.set_account() 绑定交易账号。
    2. 设置股票池: 使用 ContextInfo.set_universe() 设定策略要关注的标的列表。
    3. 初始化全局变量:ContextInfo 对象上绑定自定义变量(如 ContextInfo.count = 0),以便在 handlebar 中跨周期调用和修改。
    4. 设置回测参数(仅回测模式): 如设置起止时间、初始资金、手续费率等(虽然这些通常在界面设置,但代码中设置优先级更高)。
    5. 设置定时器: 使用 ContextInfo.run_time() 设置定时任务。

代码示例:

def init(ContextInfo):
    # 1. 设置交易账号
    ContextInfo.set_account('6000001234')
    
    # 2. 设置股票池(例如:平安银行)
    ContextInfo.set_universe(['000001.SZ'])
    
    # 3. 初始化自定义全局变量
    ContextInfo.hold_days = 0  # 记录持仓天数
    print("策略初始化完成")

2. handlebar(ContextInfo):核心执行函数

作用:
handlebar 是策略的“心脏”,包含了所有的交易逻辑、数据处理和信号判断。

  • 执行频率:

    • 回测模式: 按照 K 线的时间序列,从开始时间到结束时间,每根 K 线(Bar)执行一次
    • 实盘/模拟交易模式:
      1. 首先对历史 K 线逐根执行(用于计算指标初始状态)。
      2. 运行到最新一根 K 线(实时行情)时,每一个 Tick(分笔数据)推送都会触发一次执行
      3. 通常交易信号是在当前 K 线结束(Last Tick)或下一根 K 线开始(New Bar)时确认。
  • 主要任务:

    1. 获取数据: 调用 get_market_dataget_history_data 获取行情。
    2. 计算指标: 根据行情计算 MA、MACD 等技术指标。
    3. 逻辑判断: 判断是否满足买入或卖出条件。
    4. 执行交易: 满足条件时调用 passorderorder_shares 等函数下单。
    5. 绘图输出: 使用 ContextInfo.paint() 在界面画图。

代码示例:

def handlebar(ContextInfo):
    # 1. 获取当前 K 线位置
    index = ContextInfo.barpos
    
    # 2. 获取当前主图品种的收盘价
    # 注意:这里仅为演示,实际获取数据建议使用 get_market_data_ex
    close_price = ContextInfo.get_market_data(['close'])
    
    # 3. 简单的逻辑判断
    if close_price > 100:
        print(f"当前价格 {close_price} 大于 100,触发逻辑")
        # order_shares(...) # 下单逻辑

3. 核心区别对比表

特性 init(ContextInfo) handlebar(ContextInfo)
中文名称 初始化函数 行情事件/处理函数
执行次数 仅 1 次(启动时) 多次(随 K 线和 Tick 更新不断执行)
主要用途 环境配置、参数设置、变量定义 策略逻辑、信号计算、下单交易
数据状态 此时尚未开始遍历行情数据 可以获取当前时间点的具体行情数据
变量传递 负责定义全局变量 负责读取和修改全局变量

4. 变量传递机制(ContextInfo)

QMT 使用 ContextInfo 对象在 inithandlebar 之间传递数据。

  • 如果你在 init 中定义了 ContextInfo.my_money = 10000
  • 那么你在 handlebar 中就可以通过 ContextInfo.my_money 读取或修改这个值。
  • 注意: 不要使用 Python 原生的 global 关键字,建议将所有需要跨函数使用的变量都挂载到 ContextInfo 对象下。

Q&A

Q: 如果我不写 init 函数会怎样?
A: 策略会报错无法运行。QMT 规定 Python 策略必须包含 inithandlebar 两个方法的定义,即使 init 中什么都不做(写 pass),也必须定义它。

Q: 我可以在 init 中下单交易吗?
A: 不建议。init 运行时行情数据流尚未开始驱动,且账号状态可能未完全就绪。交易指令应在 handlebar 中根据行情逻辑触发。

Q: handlebar 在实盘中是每秒运行一次吗?
A: 不是固定的每秒一次。它是行情驱动的。如果有新的 Tick 数据(分笔成交)推送到终端,handlebar 就会被调用一次。如果市场静止无成交,它就不会运行。

Q: 如何判断 handlebar 当前运行的是历史 K 线还是最新的实时 K 线?
A: 可以使用 ContextInfo.is_last_bar() 方法。如果返回 True,表示当前运行到了最后一根 K 线(即实时行情阶段)。