🚀 AI 一键生成 ptrade 策略代码

PTrade ETF 进阶:监控折溢价率 (NAV vs Price)

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

问题描述

如何计算ETF的折价或溢价率?

解决方案

ETF折价与溢价率计算方法

在PTrade量化交易平台中,计算ETF(交易所交易基金)的折价或溢价率,主要涉及两个核心数据:ETF的市场价格ETF的净值(NAV)或实时参考净值(IOPV)

1. 计算公式

  • 溢价(Premium):市场价格 > 净值
  • 折价(Discount):市场价格 < 净值

计算公式如下:

$$ \text{折溢价率} = \frac{\text{市场价格} - \text{参考净值}}{\text{参考净值}} \times 100% $$

2. 所需API接口

根据PTrade API文档,我们需要使用以下接口获取数据:

  1. get_snapshot(security): 获取ETF的实时行情快照,从中提取最新成交价 (last_px)。
  2. get_etf_info(etf_code): 获取ETF的基础信息,从中提取T-1日的单位净值 (nav_pre)。

注意get_etf_info 返回的是前一交易日的单位净值(nav_pre)。在盘中实时计算时,通常使用交易所发布的**IOPV(基金份额参考净值)**更为准确。但在API文档提供的基础字段中,get_etf_info主要提供静态数据。如果您的券商环境在 get_snapshot 中推送了 IOPV 数据,可优先使用;若无,则通常使用 nav_pre 进行估算或作为盘前参考。

3. 策略代码实现

以下是一个完整的策略示例,展示如何在盘中获取ETF价格和净值信息,并计算折溢价率。

def initialize(context):
    """
    初始化函数
    """
    # 设置我们要监测的ETF代码,例如:510050.SS (上证50ETF)
    g.security = '510050.SS'
    # 设置股票池
    set_universe(g.security)
    
    # 设置每分钟运行一次,用于实时监控折溢价
    # 注意:回测模式下handle_data会自动按频率运行
    
def handle_data(context, data):
    """
    盘中运行函数
    """
    # 1. 获取ETF基础信息 (包含T-1日净值)
    # 注意:get_etf_info 返回的是一个字典,key是ETF代码
    etf_basic_info = get_etf_info(g.security)
    
    # 2. 获取ETF实时行情快照 (包含最新市价)
    snapshot = get_snapshot(g.security)
    
    # 数据有效性检查
    if not etf_basic_info or not snapshot:
        log.info("未获取到ETF信息或行情快照")
        return
        
    # 3. 提取数据
    # 获取 T-1 日单位净值 (nav_pre)
    # 注意:这里使用的是昨收净值。如果是实盘且券商支持IOPV,数据可能在snapshot中
    nav = etf_basic_info[g.security].get('nav_pre')
    
    # 获取最新成交价
    current_price = snapshot[g.security].get('last_px')
    
    # 4. 计算折溢价率
    # 确保分母不为0且数据有效
    if nav and current_price and nav > 0:
        # 计算公式:(现价 - 净值) / 净值 * 100%
        premium_rate = (current_price - nav) / nav * 100
        
        # 5. 打印结果
        log.info("ETF代码: %s" % g.security)
        log.info("最新市价: %.3f" % current_price)
        log.info("参考净值(T-1): %.3f" % nav)
        
        if premium_rate > 0:
            log.info("状态: 溢价 | 溢价率: %.3f%%" % premium_rate)
        elif premium_rate < 0:
            log.info("状态: 折价 | 折价率: %.3f%%" % premium_rate)
        else:
            log.info("状态: 平价 | 折溢价率: 0.00%")
            
        # 6. 简单的交易逻辑示例 (仅供参考)
        # 如果折价超过 2% (即价格远低于净值),可能存在买入机会
        if premium_rate < -2.0:
            log.info("触发折价套利信号,尝试买入...")
            # order(g.security, 1000) 
            
    else:
        log.info("数据缺失,无法计算折溢价率")

4. 代码解析

  1. 获取净值:通过 get_etf_info(g.security) 获取返回的字典,并使用 .get('nav_pre') 提取前一交易日的单位净值。
  2. 获取市价:通过 get_snapshot(g.security) 获取实时快照,使用 .get('last_px') 提取最新成交价。
  3. 计算逻辑:简单的百分比变化率计算。
  4. Python兼容性:代码使用了 %s%.3f 等格式化字符串方法,完全兼容 Python 3.5 及以上版本。

Q&A

Q: 为什么使用 nav_pre (T-1日净值) 而不是实时 IOPV?
A: 在 PTrade 的标准 API 文档 get_etf_info 中,明确提供的字段是 nav_pre (T-1日基金单位净值)。虽然实盘中交易所会推送实时的 IOPV (IOPV 是盘中估算的净值),但该字段在标准文档的 get_snapshot 返回值中未明确列出。如果您的券商环境在 Level-2 行情或快照中包含了 IOPV 字段,您可以将代码中的 nav 替换为快照中的 IOPV 数据以获得更高精度。

Q: 如何利用折溢价率进行交易?
A:

  • 折价套利:当折价率较高(例如 < -1%)时,意味着二级市场价格低于净值,投资者可以在二级市场买入ETF,然后在一级市场申请赎回(需要满足最小赎回单位,通常为几十万份),从而获取差价。
  • 溢价套利:当溢价率较高(例如 > 1%)时,意味着二级市场价格高于净值,投资者可以在一级市场申购ETF份额(通常T+0或T+1可用),然后在二级市场卖出。

Q: 回测和实盘有什么区别?
A: 在回测模式下,get_snapshot 无法使用(文档说明回测不支持),回测中应使用 data[security]['close'] 获取收盘价或当前分钟价格,并配合 get_historyget_fundamentals 获取历史净值数据进行模拟。上述代码主要针对**交易(实盘/模拟盘)**环境设计。