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

ptrade 期货主力合约换月时如何无缝平滑计算持仓成本?

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

问题描述

请根据以下 SEO 主题生成完整页面内容:

Title: ptrade 期货套利实战:精准计算移仓换月持仓成本

Question: ptrade 期货主力合约换月时如何无缝平滑计算持仓成本?

解决方案

ptrade 期货主力合约换月时无缝平滑计算持仓成本指南

在期货量化交易和跨期套利策略中,随着主力合约即将到期,策略需要将持仓从近期合约平仓并同时在远期主力合约开仓(即移仓换月)。由于不同合约之间存在价差(Contango 或 Backwardation),简单的平仓开仓会导致策略的持仓成本断层,从而影响后续止盈止损与收益率曲线的计算。

本文将介绍如何在 ptrade 量化平台中利用全局变量 g 记录加权持仓成本,实现主力合约移仓换月时的持仓成本平滑过度。


1. 核心计算逻辑

在移仓换月时,为了实现持仓成本的无缝衔接,我们需要计算加权换月成本

$$\text{新合约调整成本} = \text{新合约建仓价} + (\text{旧合约平仓价} - \text{旧合约原始持仓成本})$$

通过将旧合约的浮动盈亏(或价差损益)按比例折算并累加到新合约的持仓成本中,即可保证策略整体的逻辑连贯性。


2. ptrade 实战源码实现

以下源码演示了如何在 ptrade 中监控主力合约到期日,并在换月触发时平旧换新,同时精准计算平滑后的持仓成本:

def initialize(context):
    # 设置旧主力合约与新主力合约代码
    g.old_symbol = 'CU2111.XSGE'
    g.new_symbol = 'CU2112.XSGE'
    set_universe([g.old_symbol, g.new_symbol])
    
    # 记录策略维度的逻辑持仓成本
    g.smooth_cost_basis = 0.0
    g.is_rolled = False

def before_trading_start(context, data):
    # 设置期货保证金比例(以沪铜为例)
    set_margin_rate('CU', 0.08)

def handle_data(context, data):
    # 初始建仓旧合约
    if not g.is_rolled and get_position(g.old_symbol).amount == 0:
        buy_open(g.old_symbol, 1)
        pos = get_position(g.old_symbol)
        g.smooth_cost_basis = pos.long_cost_basis if pos else data[g.old_symbol]['close']
        log.info('初始建仓旧合约 %s,成本: %s' % (g.old_symbol, g.smooth_cost_basis))
        return

    # 获取合约信息,判断旧合约距离到期日天数(此处示例简化为达到特定条件触发换月)
    old_info = get_instruments(g.old_symbol)
    
    # 假设触发换月条件(例如标志位或日期条件)
    if not g.is_rolled and context.blotter.current_dt.day >= 15:
        log.info('开始执行主力合约移仓换月流程...')
        
        # 1. 获取旧合约实时价格与持仓成本
        old_pos = get_position(g.old_symbol)
        old_amount = old_pos.long_amount if old_pos else 1
        old_close_price = data[g.old_symbol]['close']
        old_cost = g.smooth_cost_basis
        
        # 2. 平仓旧合约
        sell_close(g.old_symbol, old_amount)
        
        # 3. 开仓新合约
        new_open_price = data[g.new_symbol]['close']
        buy_open(g.new_symbol, old_amount)
        
        # 4. 平滑计算新合约持仓成本
        # 调整后成本 = 新合约开仓价 + (旧合约平仓价 - 旧合约持仓成本)
        rollover_pnl = old_close_price - old_cost
        g.smooth_cost_basis = new_open_price - rollover_pnl
        
        g.is_rolled = True
        log.info('移仓换月完成!新合约 %s 开仓价: %s, 平滑后算定持仓成本: %s' % (
            g.new_symbol, new_open_price, g.smooth_cost_basis
        ))

3. 注意事项

  1. 数据持久化:模拟盘或实盘环境重启时,强烈建议使用 pickle 将全局持仓成本 g.smooth_cost_basis 保存至研究目录(使用 get_research_path()),防止策略重启导致逻辑成本丢失。
  2. 最小变动价位:使用 get_instruments() 查询对应期货品种的 trade_unit 及价格跳动单位,在设置止盈止损限价(limit_price)时保持精度对齐。
  3. 滑点与手续费:在回测中可通过 set_future_commission() 设定真实的手续费率,确保换月移仓成本计算的精确性。