问题描述
/
解决方案
在 ptrade 量化交易平台的实盘环境中,使用 order_value(以及 order、order_target 等下单函数)时,如果遇到“行情快照获取失败导致委托失败”的问题,通常是因为未指定委托价格,系统底层默认调用快照接口失败所致。以下是详细的原因分析及解决方案。
原因分析
根据 ptrade 官方 API 文档说明:
交易场景如果
limit_price字段不入参,系统会默认用行情快照数据最新价报单,假如行情快照获取失败会导致委托失败,系统会在日志中增加提醒。
在实盘交易中,由于网络波动、接口限流或瞬间并发过高,底层自动调用的 get_snapshot 可能会偶发性失败。如果此时你没有传入 limit_price,系统无法确定下单价格,就会直接放弃该笔委托。
解决方案
为了提高实盘策略的健壮性,建议采用以下几种方法来解决和预防此问题:
方案一:显式传入 limit_price 参数(推荐)
最直接有效的方法是不要依赖系统的默认行为,而是在策略代码中自行获取价格,并显式传递给 limit_price 参数。你可以结合 get_snapshot 或 get_history 来获取价格,并加上异常处理。
def handle_data(context, data):
security = '600570.SS'
value = 10000
# 尝试自行获取快照
snapshot = get_snapshot(security)
if snapshot and security in snapshot and snapshot[security].get('last_px', 0) > 0:
# 如果快照获取成功,使用最新价
current_price = snapshot[security]['last_px']
order_value(security, value, limit_price=current_price)
log.info(f"使用快照最新价 {current_price} 下单")
else:
# 如果快照获取失败,使用 data 字典中的收盘价作为备用价格
# 注意:分钟级别策略中 data 包含当前分钟数据
fallback_price = data[security]['close']
order_value(security, value, limit_price=fallback_price)
log.warning(f"快照获取失败,使用备用价格 {fallback_price} 下单")
方案二:使用市价单接口 order_market
如果你希望以市价快速成交,且不关心具体的限价,可以改用 order_market 接口(注意:order_market 是按数量下单,需要先计算出数量)。市价单直接报入交易所,不需要依赖本地的最新价快照。
def handle_data(context, data):
security = '600570.SS'
target_value = 10000
# 使用 data 获取参考价格计算委托数量
ref_price = data[security]['close']
if ref_price > 0:
# 计算需要买入的股数,并向下取整到100的整数倍
amount = int(target_value / ref_price / 100) * 100
if amount >= 100:
# market_type=4 表示最优五档即时成交剩余撤销(适用于上证非科创板及深证)
order_market(security, amount, market_type=4)
log.info(f"市价委托买入 {security} 数量 {amount}")
方案三:增加重试机制
如果是偶发的网络抖动,可以在自定义函数中增加简单的重试机制来获取价格。
import time
def get_safe_price(security, max_retries=3):
for i in range(max_retries):
snapshot = get_snapshot(security)
if snapshot and security in snapshot and snapshot[security].get('last_px', 0) > 0:
return snapshot[security]['last_px']
time.sleep(0.5) # 等待0.5秒后重试
return None
def handle_data(context, data):
security = '600570.SS'
price = get_safe_price(security)
if price:
order_value(security, 10000, limit_price=price)
else:
log.error(f"{security} 多次获取快照失败,放弃本次交易")
总结
在 ptrade 实盘编写中,永远不要假设外部数据接口(如行情快照)会 100% 成功。对于 order_value、order 等下单函数,强烈建议显式计算并传入 limit_price,并在获取价格时做好 None 值判断和备用方案(Fallback),这样才能确保实盘交易的稳定运行。