3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 ptrade 量化交易平台中,进行 ETF 瞬时折溢价套利(Arbitrage)的核心在于成分券一篮子股票交易与ETF 基金份额申赎之间的协同。通过捕捉二级市场价格与一级市场净值(IOPV)之间的瞬时偏差,交易者可以执行以下两种套利路径:
etf_basket_order) -> 一级市场申购成 ETF 份额(etf_purchase_redemption) -> 二级市场卖出 ETF 份额。etf_purchase_redemption) -> 二级市场卖出一篮子成分股(etf_basket_order)。etf_basket_orderetf_basket_order(etf_code, amount, price_style=None, position=True, info=None)
amount:正数表示买入成分券篮子,负数表示卖出成分券篮子。price_style:委托价位,如 'new'(最新价)、'S1'(卖一)、'B1'(买一)等。position:买入时是否使用已有持仓替代,默认为 True。etf_purchase_redemptionetf_purchase_redemption(etf_code, amount, limit_price=None)
amount:正数表示申购(用股票换 ETF 份额),负数表示赎回(用 ETF 份额换股票)。以下是一个在 ptrade 交易环境中运行的 ETF 溢价套利策略示例:
# -*- coding: utf-8 -*-
def initialize(context):
# 设定套利目标 ETF(例如华安上证50ETF)
g.etf_code = '510050.SS'
set_universe(g.etf_code)
# 设定套利触发阈值(例如溢价 0.5%)
g.arbitrage_threshold = 0.005
# 最小申赎单位(通常为 100万份 或 90万份,需根据 get_etf_info 获取)
g.min_report_unit = 900000
# 运行控制标识
g.is_traded = False
def handle_data(context, data):
if g.is_traded:
return
# 1. 获取 ETF 实时行情快照与 IOPV 估值
snapshot = get_snapshot(g.etf_code)
etf_info = get_etf_info(g.etf_code)
if not snapshot or not etf_info:
log.warning("无法获取行情或ETF基础信息")
return
# 获取二级市场最新成交价
last_px = snapshot[g.etf_code].get('last_px', 0)
# 获取 T-1 日基金单位净值作为参考,或通过其他渠道计算实时 IOPV
nav_pre = etf_info[g.etf_code].get('nav_pre', 0)
g.min_report_unit = etf_info[g.etf_code].get('report_unit', g.min_report_unit)
if last_px <= 0 or nav_pre <= 0:
return
# 计算折溢价率
premium_rate = (last_px - nav_pre) / nav_pre
log.info(f"当前二级市场价格: {last_px}, 参考净值: {nav_pre}, 折溢价率: {premium_rate:.4%}")
# 2. 触发溢价套利逻辑
if premium_rate > g.arbitrage_threshold:
log.info("触发溢价套利,开始执行协同交易...")
# 步骤 A:在二级市场以卖三价快速买入一篮子成分股
# 数量为 1 个最小申购单位
basket_res = etf_basket_order(g.etf_code, g.min_report_unit, price_style='S3', position=False)
if basket_res:
log.info(f"成分股篮子买入委托已发送,涉及股票数: {len(basket_res)}")
# 步骤 B:一键向柜台申报 ETF 申购(用买入的股票换取 ETF 份额)
# 实际实盘中需确认成分股全部成交,此处为瞬时协同演示
order_id = etf_purchase_redemption(g.etf_code, g.min_report_unit)
if order_id:
log.info(f"ETF 申购委托成功,订单ID: {order_id}")
# 步骤 C:在二级市场卖出申购所得的 ETF 份额(实盘中通常为 T+0 循环或次日卖出,取决于具体市场规则)
# order(g.etf_code, -g.min_report_unit)
g.is_traded = True
else:
log.error("ETF 申购委托失败!")
else:
log.error("成分股篮子买入失败!")
2.999),在手动指定 limit_price 时务必做好精度处理,否则会导致废单。etf_basket_order 属于多股批量报单,柜台反馈持仓通常有 6 秒左右的同步时滞。在套利逻辑中,应避免在持仓未完全同步时盲目触发下一步,建议结合 on_order_response 或 on_trade_response 异步主推事件进行状态确认。get_etf_stock_info 查询其 cash_replace_flag(现金替代标志)。若为“必须替代”或“允许替代”,需在 etf_basket_order 的 info 参数中正确配置溢价比例,防止因个股停牌导致整篮子套利失败。