问题描述
解决方案
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. 解决方案
在策略代码中,在调用 order、order_target、order_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. 注意事项
- 市价委托保护限价:在使用
order_market进行科创板等需要保护限价(limit_price)的市价委托时,同样需要遵守上述精度规则。 - 期货特殊性:如果是期货交易,最小变动单位(Tick Size)可能不是简单的四舍五入(例如最小变动0.2),建议使用
round(price / tick_size) * tick_size的逻辑进行处理。 - API返回值:PTrade的行情接口(如
get_snapshot或data)返回的价格通常已经是交易所的标准精度,但在策略内部进行乘除运算(如计算均线、止盈止损价)后,务必在下单前再次进行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元)。