🚀 AI 一键生成 ptrade 策略代码

如何在 PTrade 平台实现期货日历价差交易策略?(附源码)

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

问题描述

请为我编写一个期货跨期套利策略,例如买入近月合约,卖出远月合约。

解决方案

这是一个基于PTrade平台的期货跨期套利策略(Calendar Spread Arbitrage)示例。

策略原理

跨期套利是指在同一交易所进行同一品种、不同交割月份的期货合约交易。

  • 操作方向:买入近月合约(做多),同时卖出远月合约(做空)。这通常被称为“多头套利”或“买入套利”。
  • 获利逻辑:预期价差(近月价格 - 远月价格)会扩大。或者当前价差过低(被低估),预期会回归均值。
  • 交易逻辑
    1. 计算价差:Spread = Price_Near - Price_Far
    2. 开仓:当 Spread < 开仓阈值 时,买入近月,卖出远月。
    3. 平仓:当 Spread > 平仓阈值 时,卖出近月,买入远月(平掉双边仓位)。

PTrade 策略代码

def initialize(context):
    """
    策略初始化函数
    """
    # 1. 设置套利合约对 (请根据实际时间修改合约代码)
    # 近月合约 (做多的一端)
    g.near_contract = 'IF2306.CCFX' 
    # 远月合约 (做空的一端)
    g.far_contract = 'IF2309.CCFX'
    
    # 2. 设置股票池/期货池
    set_universe([g.near_contract, g.far_contract])
    
    # 3. 策略参数设置
    # 开仓阈值:当价差小于此值时开仓 (例如价差为负且很深,预期回归)
    g.entry_threshold = -20.0 
    # 平仓阈值:当价差大于此值时止盈/平仓
    g.exit_threshold = 10.0   
    # 单次交易手数
    g.trade_unit = 1
    
    # 4. 设置手续费 (可选,根据实际品种设置,此处以万分之0.23为例)
    # set_future_commission(g.near_contract, 0.000023)
    # set_future_commission(g.far_contract, 0.000023)
    
    # 5. 设置保证金比例 (可选,此处设为15%)
    # set_margin_rate(g.near_contract, 0.15)
    # set_margin_rate(g.far_contract, 0.15)

    log.info("策略初始化完成,近月: %s, 远月: %s" % (g.near_contract, g.far_contract))

def handle_data(context, data):
    """
    盘中运行函数,每个tick或分钟执行一次
    """
    # 检查数据是否包含我们的合约
    if g.near_contract not in data or g.far_contract not in data:
        return

    # 1. 获取最新价格
    price_near = data[g.near_contract]['close']
    price_far = data[g.far_contract]['close']
    
    # 2. 计算当前价差 (近月 - 远月)
    current_spread = price_near - price_far
    
    # 3. 获取当前持仓信息
    # 获取近月合约的多头持仓
    pos_near = get_position(g.near_contract)
    long_pos_near = pos_near.long_amount if pos_near else 0
    
    # 获取远月合约的空头持仓
    pos_far = get_position(g.far_contract)
    short_pos_far = pos_far.short_amount if pos_far else 0
    
    # 记录日志方便调试
    # log.info("当前价差: %.2f, 持仓状态(近多/远空): %d/%d" % (current_spread, long_pos_near, short_pos_far))
    
    # 4. 交易逻辑
    
    # --- 开仓逻辑 ---
    # 如果当前没有持仓,且价差低于开仓阈值 -> 买近卖远
    if long_pos_near == 0 and short_pos_far == 0:
        if current_spread < g.entry_threshold:
            log.info("触发开仓信号: 价差 %.2f < 阈值 %.2f" % (current_spread, g.entry_threshold))
            
            # 买入开仓近月
            buy_open(g.near_contract, g.trade_unit)
            # 卖出开仓远月
            sell_open(g.far_contract, g.trade_unit)
            
    # --- 平仓逻辑 ---
    # 如果持有套利仓位,且价差回归到平仓阈值之上 -> 平仓获利
    elif long_pos_near > 0 and short_pos_far > 0:
        if current_spread > g.exit_threshold:
            log.info("触发平仓信号: 价差 %.2f > 阈值 %.2f" % (current_spread, g.exit_threshold))
            
            # 卖出平仓近月 (多平)
            # 注意:上期所品种(如CU, RB)需区分平今平昨,中金所(IF, IC)通常不需要
            # 这里使用 close_today=False 优先平昨,通用性较好
            sell_close(g.near_contract, g.trade_unit, close_today=False)
            
            # 买入平仓远月 (空平)
            buy_close(g.far_contract, g.trade_unit, close_today=False)

def before_trading_start(context, data):
    """
    盘前处理
    """
    pass

def after_trading_end(context, data):
    """
    盘后处理
    """
    pass

代码关键点解析

  1. 合约代码 (g.near_contract, g.far_contract)

    • 期货合约代码包含后缀,例如中金所是 .CCFX (如 IF2306.CCFX),上期所是 .XSGE (如 RB2310.XSGE)。
    • 注意:期货合约会到期,实盘中需要定期手动修改代码,或者编写更复杂的逻辑来自动识别主力合约。
  2. 价差计算 (current_spread)

    • 逻辑核心是 近月价格 - 远月价格
    • 如果 current_spread 是负数(例如 -30),说明远月比近月贵(升水结构)。
    • 如果预期价差会缩小(即变得不那么负,或者变正),则买入近月、卖出远月。
  3. 持仓判断 (get_position)

    • PTrade中,期货的 Position 对象区分多头和空头。
    • long_amount: 多头持仓量。
    • short_amount: 空头持仓量。
    • 策略中我们检查 long_pos_near (近月是否有多单) 和 short_pos_far (远月是否有空单) 来确认是否持有套利组合。
  4. 下单函数

    • buy_open: 买入开仓(做多)。
    • sell_open: 卖出开仓(做空)。
    • sell_close: 卖出平仓(平多单)。
    • buy_close: 买入平仓(平空单)。
  5. 平今仓与平昨仓 (close_today)

    • 代码中 close_today=False 表示优先平昨仓(历史持仓)。
    • 如果是上海期货交易所(如螺纹钢 RB、铜 CU),平今仓手续费可能极高,通常建议优先平昨。如果是中金所(IF, IC, IM),该参数影响较小,但设为 False 是比较安全的默认做法。

如何在 PTrade 中运行

  1. 新建一个策略,将上述代码复制进去。
  2. 修改合约代码:将 IF2306.CCFXIF2309.CCFX 替换为当前市场上真实存在的、有流动性的合约代码。
  3. 设置回测参数:选择期货账户,设置初始资金(如 1,000,000),频率建议选择“分钟线”以获得更精确的价差捕捉。
  4. 运行回测查看效果。

Q&A

Q: 如何让策略自动选择主力合约,而不是手动硬编码?
A: 可以使用 get_instrumentsget_future_contracts (如果券商支持) 获取某品种的所有合约,然后根据持仓量 (amount) 或 成交量 (volume) 进行排序,选出最大的两个作为近月和远月主力。这需要编写额外的逻辑函数放在 before_trading_start 中。

Q: 为什么我的单子没有成交?
A: 1. 检查资金是否足够支付保证金。2. 检查合约代码是否已过期或错误。3. 在回测中,如果使用限价单 (limit_price) 可能会因为价格未触及而不成交,本示例默认使用市价(回测中通常以收盘价/最新价成交)。

Q: 什么是“移仓换月”?
A: 当近月合约临近交割时,必须平掉近月合约,并重新在新的合约上开仓,以保持套利组合的存在。本简单示例未包含自动移仓逻辑,实盘中需注意合约到期日。