🚀 AI 一键生成 ptrade 策略代码

PTrade 下单失败?详解股票与 ETF 的价格精度处理

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

问题描述

下单时提示价格精度错误怎么办?ETF和股票的精度有什么区别?

解决方案

PTrade下单价格精度处理指南

在PTrade中,如果下单时提示“价格精度错误”或“委托价格不符合最小价差”,通常是因为传入 order 系列函数的 limit_price(限价)参数的小数位数不符合交易所规定的最小变动单位。

以下是关于股票与ETF精度区别的详细说明及代码解决方案。

1. 股票与ETF的精度区别

根据PTrade官方文档及交易所规则,不同品种的价格最小价差(精度)如下:

交易品种 最小价差 保留小数位数 示例价格
普通股票 0.01 元 2位 10.58
ETF基金 0.001 元 3位 1.583
LOF基金 0.001 元 3位 1.205
可转债 0.001 元 3位 110.235
股指期货 0.2 点 1位 3500.2

核心区别: 股票必须保留 2位 小数,而ETF、LOF和可转债通常需要保留 3位 小数。

2. 解决方案

在策略代码中,在调用 orderorder_targetorder_value 等下单函数前,使用 Python 内置的 round() 函数对价格进行处理。

简单示例

# 股票下单示例(保留2位)
stock_price = 10.123456
order('600570.SS', 100, limit_price=round(stock_price, 2))

# ETF下单示例(保留3位)
etf_price = 2.345678
order('510050.SS', 100, limit_price=round(etf_price, 3))

3. 通用策略代码实现

为了在策略中自动处理不同标的的精度,建议编写一个辅助函数来动态判断并处理价格精度。

以下是一个完整的策略示例,展示了如何自动识别股票和ETF并使用正确的精度下单:

def initialize(context):
    # 设置股票池:包含一只股票(恒生电子)和一只ETF(上证50ETF)
    g.stock = '600570.SS'
    g.etf = '510050.SS'
    set_universe([g.stock, g.etf])

def get_price_precision(code):
    """
    根据代码判断价格保留的小数位数
    """
    # 创业板、科创板、主板股票通常为2位
    # ETF、LOF、可转债通常为3位
    # 这里通过简单的逻辑判断,也可以根据get_stock_info获取更详细类型
    
    # 常见的ETF和LOF代码段:51, 15, 16, 58等
    # 可转债代码段:11, 12
    if code.startswith(('51', '15', '16', '58', '11', '12')):
        return 3
    else:
        # 默认为股票,2位
        return 2

def safe_order(security, amount, raw_price):
    """
    封装下单函数,自动处理价格精度
    """
    # 1. 获取该标的应保留的小数位数
    precision = get_price_precision(security)
    
    # 2. 对价格进行四舍五入处理
    final_price = round(raw_price, precision)
    
    # 3. 执行下单
    order(security, amount, limit_price=final_price)
    
    log.info("标的: %s, 原始价格: %f, 下单价格: %f (保留%d位)" % (
        security, raw_price, final_price, precision
    ))

def handle_data(context, data):
    # 示例:获取当前收盘价,并尝试以涨幅1%的价格挂单
    
    # --- 股票交易 ---
    current_price_stock = data[g.stock]['close']
    target_price_stock = current_price_stock * 1.012345 # 模拟计算出的多位小数价格
    # 调用封装函数下单
    safe_order(g.stock, 100, target_price_stock)
    
    # --- ETF交易 ---
    current_price_etf = data[g.etf]['close']
    target_price_etf = current_price_etf * 1.012345
    # 调用封装函数下单
    safe_order(g.etf, 100, target_price_etf)

4. 注意事项

  1. 市价委托保护限价:在使用 order_market 进行科创板等需要保护限价(limit_price)的市价委托时,同样需要遵守上述精度规则。
  2. 期货特殊性:如果是期货交易,最小变动单位(Tick Size)可能不是简单的四舍五入(例如最小变动0.2),建议使用 round(price / tick_size) * tick_size 的逻辑进行处理。
  3. API返回值:PTrade的行情接口(如 get_snapshotdata)返回的价格通常已经是交易所的标准精度,但在策略内部进行乘除运算(如计算均线、止盈止损价)后,务必在下单前再次进行 round 处理。

Q&A

Q: 如果我不传 limit_price 参数会怎样?
A: 如果调用 order(security, amount) 而不传 limit_price,PTrade通常会使用当前的市价(或最新快照价格)进行报单。这种情况下系统会自动处理精度,一般不会报错。但在回测或实盘中,为了控制滑点,建议显式指定 limit_price 并自行处理精度。

Q: 为什么我的ETF下单还是失败,提示价格不在笼子里?
A: 除了精度问题,交易所对委托价格还有“价格笼子”限制(例如买入申报价格不得高于基准价格的102%)。请检查您的策略逻辑,确保计算出的价格没有偏离当前市价太远。

Q: 可转债的精度是多少?
A: 可转债(如代码以11或12开头)在PTrade中通常保留 3位 小数(0.001元)。