🚀 AI 一键生成 qmt 策略代码

如何利用期货基差(Basis)进行套利交易?

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

问题描述

我该如何获取股指期货和对应指数的实时价格,并计算它们之间的基差?

解决方案

在 QMT 中获取股指期货和对应指数的实时价格并计算基差,主要涉及以下几个步骤:

  1. 确定标的:确定你要关注的期货品种(如 IF, IC, IH, IM)及其对应的现货指数代码。
  2. 获取主力合约:使用 get_main_contract 动态获取当前的主力合约代码(因为期货合约会按月交割变化)。
  3. 获取实时行情:使用 get_full_tick 获取最新的 Tick 快照数据(包含最新价 lastPrice)。
  4. 计算基差:通常基差定义为 现货价格 - 期货价格

以下是完整的策略代码示例。

策略代码实现

# -*- coding: gbk -*-

def init(ContextInfo):
    """
    初始化函数
    """
    # 定义期货品种与其对应的现货指数代码映射关系
    # IF: 沪深300期货 -> 000300.SH
    # IC: 中证500期货 -> 000905.SH
    # IH: 上证50期货   -> 000016.SH
    # IM: 中证1000期货 -> 000852.SH
    ContextInfo.pairs = {
        'IF.IF': '000300.SH',
        'IC.IF': '000905.SH',
        'IH.IF': '000016.SH',
        'IM.IF': '000852.SH'
    }
    
    # 设置定时器,例如每3秒运行一次计算函数(可选,也可以直接写在handlebar里)
    # 这里为了演示清晰,我们直接在 handlebar 中由行情驱动执行

def handlebar(ContextInfo):
    """
    K线/行情驱动函数
    """
    # 仅在实时行情的最后一根K线(或最新Tick)时计算,避免回测历史数据时打印过多日志
    if not ContextInfo.is_last_bar():
        return

    # 遍历定义的品种对
    for future_generic_code, index_code in ContextInfo.pairs.items():
        
        # 1. 获取当前主力合约代码
        # get_main_contract 会返回如 'IF2406.IF' 这样的具体合约代码
        main_contract = ContextInfo.get_main_contract(future_generic_code)
        
        if not main_contract:
            print(f"未找到 {future_generic_code} 的主力合约")
            continue

        # 2. 获取实时 Tick 数据
        # get_full_tick 返回一个字典,key是合约代码,value是包含行情的字典
        code_list = [main_contract, index_code]
        tick_data = ContextInfo.get_full_tick(code_list)
        
        # 检查数据是否获取成功
        if main_contract in tick_data and index_code in tick_data:
            # 提取最新价
            fut_price = tick_data[main_contract].get('lastPrice')
            idx_price = tick_data[index_code].get('lastPrice')
            
            # 确保价格有效(非0且非None)
            if fut_price and idx_price:
                # 3. 计算基差 (Basis = Spot - Future)
                basis = idx_price - fut_price
                
                # 计算基差率 (Basis Rate = Basis / Spot Price)
                basis_rate = (basis / idx_price) * 100
                
                # 4. 输出结果
                print("=" * 30)
                print(f"品种: {future_generic_code} | 主力合约: {main_contract}")
                print(f"指数代码: {index_code}")
                print(f"期货价格: {fut_price:.2f}")
                print(f"指数价格: {idx_price:.2f}")
                print(f"当前基差: {basis:.2f}")
                print(f"基差率: {basis_rate:.2f}%")
                print("=" * 30)
            else:
                print(f"价格数据无效: {main_contract} or {index_code}")
        else:
            print(f"获取行情失败,请检查是否已下载或订阅: {code_list}")

代码核心逻辑解析

  1. ContextInfo.get_main_contract(codemarket):

    • 这是获取主力合约的关键。传入通用的品种代码(如 'IF.IF'),它会自动返回当前市场上持仓量最大的具体合约代码(如 'IF2312.IF')。这保证了策略始终跟踪流动性最好的合约。
  2. ContextInfo.get_full_tick(stock_code_list):

    • 这是获取实时快照最高效的接口。
    • 它返回一个字典,包含买卖五档、最新价、成交量等信息。
    • 我们主要使用其中的 'lastPrice' 字段。
  3. 基差计算公式:

    • 代码中采用的是国内常用的定义:基差 = 现货指数价格 - 期货合约价格
    • 如果基差为(升水),说明现货价格高于期货价格;
    • 如果基差为(贴水),说明期货价格高于现货价格。

运行说明

  1. 将上述代码复制到 QMT 的【策略编辑器】中。
  2. 在【模型设置】中,选择一个默认的运行周期(如 1分钟 或 1天 均可,因为 get_full_tick 获取的是切片数据,不受 K 线周期影响,但 handlebar 的触发频率受行情推送影响)。
  3. 点击【运行】。
  4. 观察下方的【日志输出】窗口,即可看到实时的基差数据。

Q&A

Q: 为什么有时候 get_full_tick 获取不到数据?
A: get_full_tick 依赖于本地行情缓存或实时推送。如果这是你第一次查看某个冷门合约,可能需要先在行情界面打开一下该图表,或者在代码中使用 ContextInfo.subscribe_quote(code) 显式订阅一下该合约的行情。

Q: 如何计算次主力合约(下月合约)的基差?
A: QMT 的 get_main_contract 只能获取主力。如果要获取次主力,通常需要获取该品种的所有合约列表(可以使用 get_option_list 变通获取或通过板块成分股逻辑),然后根据持仓量排序,取持仓量第二大的合约。

Q: 这个策略可以用来进行期现套利吗?
A: 可以作为核心逻辑的一部分。你需要设定一个基差阈值(例如基差率 > 2%),当满足条件时,买入期货并融券卖出ETF(反向套利),或者卖出期货并买入ETF/一篮子股票(正向套利)。但实际交易还需要考虑冲击成本、资金占用和滑点。