🚀 AI 一键生成 ptrade 策略代码
立即体验

如何在 ptrade 中获取期货合约的交割日期并实现临近交割日自动平仓?

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

问题描述

ptrade 期货风控:利用 get_instruments 监控交割日防范强平风险
如何在 ptrade 中获取期货合约的交割日期(delivery_date),并在距离交割日仅剩 5 天时自动平仓?

解决方案

在期货交易中,临近交割日(Delivery Date)时,个人投资者或非套保客户通常会被交易所强制平仓,甚至面临流动性枯竭和额外的强平费用。因此,在量化策略中加入交割日监控与自动平仓风控逻辑至关重要。

在 ptrade 平台中,我们可以通过 get_instruments 接口获取期货合约的详细上市信息,其中包括交割日期 delivery_date。结合 context.blotter.current_dt(当前回测/交易时间),即可计算出距离交割日的剩余天数,并在满足条件时执行平仓。

1. 核心接口介绍

get_instruments(contract)

  • 使用场景:回测、交易模块均可用。
  • 参数contract(str,期货合约代码,如 'CU2112.XSGE')。
  • 返回对象属性
    • contract_code:合约代码
    • delivery_date:交割日期(格式通常为 'YYYYMMDD''YYYY-MM-DD' 的字符串)
    • trade_code:交易代码
    • margin_rate:保证金比例
    • ...

2. 核心风控逻辑实现步骤

  1. 获取持仓:通过 context.portfolio.positions 遍历当前账户中的所有期货持仓。
  2. 查询交割日:对每个持仓合约调用 get_instruments(contract),获取其 delivery_date
  3. 计算剩余天数:将交割日字符串与当前交易日进行对比,计算相差天数。
  4. 自动平仓:若相差天数小于等于 5 天,根据持仓方向(多头或空头)调用 sell_closebuy_close 进行平仓。

3. 完整策略源码示例

以下是一个完整的 ptrade 策略示例,展示了如何在每日盘中(handle_data)或定时任务中监控持仓合约的交割日并执行风控平仓:

import datetime

def initialize(context):
    # 设置操作的期货合约池(示例:沪铜与股指期货)
    g.security = ['CU2412.XSGE', 'IF2412.CCFX']
    set_universe(g.security)
    
    # 每天 14:50 运行一次交割日风控检查
    run_daily(context, delivery_risk_control, time='14:50')

def handle_data(context, data):
    # 盘中常规交易逻辑(此处略,仅做风控演示)
    pass

def delivery_risk_control(context):
    """
    交割日风控函数:检查所有持仓,距离交割日 <= 5 天时强制平仓
    """
    log.info("开始执行交割日风控检查...")
    current_date = context.blotter.current_dt.date() # 获取当前交易日期
    
    # 获取当前所有持仓
    positions = context.portfolio.positions
    if not positions:
        log.info("当前无持仓,无需风控。")
        return
        
    for contract, pos in list(positions.items()):
        # 过滤非期货品种(如股票等业务类型)
        if pos.business_type != 'future':
            continue
            
        # 获取合约信息
        instrument_info = get_instruments(contract)
        if not instrument_info or not instrument_info.delivery_date:
            log.warning("未能获取到合约 %s 的交割日信息" % contract)
            continue
            
        delivery_date_str = instrument_info.delivery_date
        
        # 解析交割日字符串为 datetime.date 对象
        try:
            # 兼容处理不同的日期格式
            if '-' in delivery_date_str:
                delivery_date = datetime.datetime.strptime(delivery_date_str, '%Y-%m-%d').date()
            else:
                delivery_date = datetime.datetime.strptime(delivery_date_str, '%Y%m%d').date()
        except Exception as e:
            log.error("解析合约 %s 交割日 %s 失败: %s" % (contract, delivery_date_str, str(e)))
            continue
            
        # 计算距离交割日的剩余天数
        days_to_delivery = (delivery_date - current_date).days
        log.info("合约: %s, 当前日期: %s, 交割日期: %s, 距离交割日: %d 天" % 
                 (contract, current_date, delivery_date, days_to_delivery))
        
        # 触发风控阈值(<= 5天)
        if days_to_delivery <= 5:
            log.warning("【风控警报】合约 %s 距离交割日仅剩 %d 天,触发强制平仓!" % (contract, days_to_delivery))
            
            # 1. 平多仓 (long_amount > 0)
            if pos.long_amount > 0:
                order_id = sell_close(contract, pos.long_amount)
                if order_id:
                    log.info("已发送多头平仓单,合约: %s, 数量: %d" % (contract, pos.long_amount))
            
            # 2. 平空仓 (short_amount > 0)
            if pos.short_amount > 0:
                order_id = buy_close(contract, pos.short_amount)
                if order_id:
                    log.info("已发送空头平仓单,合约: %s, 数量: %d" % (contract, pos.short_amount))

4. 注意事项

  1. 日期格式兼容:不同柜台或历史回测数据返回的 delivery_date 格式可能存在 '20241225''2024-12-25' 的差异,代码中已使用 try-except 和条件判断进行了兼容处理。
  2. 非交易日影响(delivery_date - current_date).days 计算的是自然日差值。如果交割日前有长假(如国庆、春节),建议将风控阈值适当调大(例如设为 7-10 天),以防假期休市无法平仓。
  3. 平今/平昨限制:对于上海期货交易所(XSGE)的合约,平仓时需注意平今仓(close_today=True)与平昨仓的区分,ptrade 的 sell_closebuy_close 默认优先平昨仓。