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

ptrade 平台如何实时监控 ETF 折溢价并实现套利交易?(附 Python 源码)

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

问题描述

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

Title: ptrade ETF 套利:利用 IOPV 实时计算进行折溢价监控

Question: 在 ptrade 中如何实时计算 ETF 的 IOPV 并进行折溢价套利?

解决方案

ptrade ETF 折溢价套利:利用 IOPV 实时计算进行监控与交易

在 ETF 量化交易中,IOPV(Indicative Optimized Portfolio Value,基金份额参考净值) 是判断 ETF 在二级市场交易价格是否发生折溢价的核心指标。通过在 ptrade 平台实时计算 IOPV,投资者可以在折溢价率突破交易成本门槛时捕获套利机会。


一、ETF 折溢价套利基本原理

  1. 溢价套利(一揽子买入股票 -> 申购 ETF -> 二级市场卖出 ETF)

    • 触发条件:二级市场 ETF 价格 > IOPV + 交易成本。
    • 套利步骤
      1. 在二级市场通过 etf_basket_order 买入一揽子 ETF 成分股。
      2. 在一级市场调用 etf_purchase_redemption 申购 ETF 份额。
      3. 在二级市场卖出申购获得的 ETF 份额,锁定溢价收益。
  2. 折价套利(二级市场买入 ETF -> 赎回成分股 -> 卖出一揽子股票)

    • 触发条件:二级市场 ETF 价格 < IOPV - 交易成本。
    • 套利步骤
      1. 在二级市场买入 ETF 份额。
      2. 在一级市场调用 etf_purchase_redemption 赎回一揽子成分股。
      3. 在二级市场卖出一揽子成分股,锁定折价收益。

二、ptrade 相关 API 接口说明

  • get_etf_info(etf_code):获取 ETF 基础信息(如最小申赎单位 report_unit、预估现金差额 cash_balance 等)。
  • get_etf_stock_list(etf_code):获取目标 ETF 的成分券代码列表。
  • get_etf_stock_info(etf_code, security):获取指定成分券的数量(code_num)、现金替代标志等。
  • get_snapshot(security):获取成分券及 ETF 的实时行情快照。
  • etf_basket_order:ETF 成分券一揽子下单接口。
  • etf_purchase_redemption:ETF 基金申购赎回接口。

三、实时计算 IOPV 与折溢价监控代码实现

以下示例展示如何在 ptrade 盘中(handle_datarun_interval)实时计算 IOPV 并监控折溢价:

def initialize(context):
    # 设置监控的 ETF 代码(以华夏上证50ETF为例)
    g.etf_code = '510050.SS'
    # 设置折溢价套利门槛,例如 0.3%
    g.threshold = 0.003
    set_universe([g.etf_code])

def calculate_iopv(etf_code):
    """
    实时计算 ETF 的 IOPV
    公式:IOPV = (∑(成分股数量 * 成分股最新价) + 预估现金差额) / 最小申赎单位
    """
    # 1. 获取 ETF 基础信息
    etf_info = get_etf_info(etf_code).get(etf_code, {})
    report_unit = etf_info.get('report_unit', 0)
    cash_balance = etf_info.get('cash_balance', 0.0)
    
    if not report_unit:
        return None
        
    # 2. 获取 ETF 成分券列表
    stock_list = get_etf_stock_list(etf_code)
    if not stock_list:
        return None
        
    # 3. 批量获取成分券行情快照
    snapshots = get_snapshot(stock_list)
    
    total_stock_value = 0.0
    for stock in stock_list:
        # 获取单只成分券在篮子中的数量
        st_info = get_etf_stock_info(etf_code, stock).get(stock, {})
        code_num = st_info.get('code_num', 0.0)
        
        # 取成分股最新成交价(也可取买一/卖一价计算盘口 IOPV)
        snap = snapshots.get(stock, {})
        last_px = snap.get('last_px', 0.0)
        
        if last_px > 0:
            total_stock_value += code_num * last_px
            
    # 4. 计算并返回 IOPV
    iopv = (total_stock_value + cash_balance) / report_unit
    return iopv

def handle_data(context, data):
    # 计算实时 IOPV
    iopv = calculate_iopv(g.etf_code)
    if not iopv:
        return
        
    # 获取 ETF 最新二级市场价格
    etf_snap = get_snapshot(g.etf_code).get(g.etf_code, {})
    etf_price = etf_snap.get('last_px', 0.0)
    if etf_price <= 0:
        return
        
    # 计算折溢价率
    premium_rate = (etf_price - iopv) / iopv
    log.info("ETF: %s | 市场现价: %.4f | IOPV: %.4f | 折溢价率: %.2f%%" % 
             (g.etf_code, etf_price, iopv, premium_rate * 100))
             
    # 溢价套利逻辑
    if premium_rate > g.threshold:
        log.info("【信号】触发溢价套利条件,溢价率: %.2f%%" % (premium_rate * 100))
        # 示例:成分股买入篮子下单
        # etf_basket_order(g.etf_code, amount=1, price_style='S1', position=True)
        # 示例:申购 ETF 份额(需达到 report_unit)
        # etf_purchase_redemption(g.etf_code, amount=900000)
        
    # 折价套利逻辑
    elif premium_rate < -g.threshold:
        log.info("【信号】触发折价套利条件,折价率: %.2f%%" % (premium_rate * 100))
        # 示例:二级市场买入 ETF 份额并赎回
        # etf_purchase_redemption(g.etf_code, amount=-900000)

四、注意事项与优化建议

  1. 盘口真实折溢价计算:上述代码采用最新成交价(last_px)计算 IOPV。实际高频交易中,应使用卖一价(卖出成本)计算买入一揽子股票的成本,使用买一价计算 ETF 卖出价格,以准确评估剔除滑点后的真实套利空间。
  2. 现金替代处理:若成分股停牌或存在必须/允许现金替代(cash_replace_flag),需读取 replace_balance 或溢价比例修正篮子资金需求。
  3. 交易资金与报告单位限制:ETF 申赎存在最小申购赎回单位限制(通常为 50 万份到 300 万份),策略运行前需确认账户资金额度满足单笔申赎门槛。