问题描述
委托接口(如order_target)要求数量为整数,非整数报单直接失败。
解决方案
ptrade 委托数量校验失败的原因分析
在 ptrade 量化交易平台中,当你调用 order()、order_target() 或 order_value() 等委托接口时,如果遇到**“委托数量校验失败”的报错,通常是因为传入的 amount(委托数量)参数不是整数(int)类型**。
在编写量化策略时,我们经常会根据账户可用资金和当前股票价格来动态计算买入数量(例如:amount = cash / price)。在 Python 中,除法运算的结果默认是浮点数(float)。如果直接将这个浮点数传给 ptrade 的委托接口,底层校验机制会直接拒绝该报单。
此外,A股市场的交易规则也要求:
- 股票买入:必须是 100 股(1手)的整数倍。
- 可转债买入:必须是 10 张的整数倍。
- 卖出:虽然可以卖出零股,但传入的数量参数依然必须是整数类型。
解决方案:如何正确处理委托数量取整
要解决这个问题,核心在于在调用委托接口前,将计算出的数量强制转换为整数,并符合交易所的整手规则。
1. 基础取整:使用 int() 强制转换
如果你使用的是 order_target(目标数量)或 order(按数量买卖),确保传入的变量经过了 int() 转换。
# 错误写法:amount 可能是浮点数,如 150.5
amount = context.portfolio.cash / current_price
order(g.security, amount)
# 正确写法:强制转换为整数
amount = int(context.portfolio.cash / current_price)
order(g.security, amount)
2. 符合交易规则的取整:向下取整到 100 的倍数
为了避免废单或资金不足,买入股票时最好手动向下取整到 100 的倍数。
def handle_data(context, data):
security = '600570.SS'
current_price = data[security]['close']
cash = context.portfolio.cash
# 计算理论可买数量
raw_amount = cash / current_price
# 向下取整到 100 的整数倍
# 例如:raw_amount 为 1250.5,计算后 buy_amount 为 1200
buy_amount = int(raw_amount / 100) * 100
if buy_amount >= 100:
order(security, buy_amount)
log.info(f"成功委托买入 {security},数量:{buy_amount} 股")
else:
log.info("可用资金不足以买入 100 股")
ptrade 委托接口的内置取整机制
根据 ptrade API 文档,部分接口在底层已经做了一定的取整优化,但前提是你传入的数据类型必须合法:
order_value(security, value):你传入的是目标价值(value可以是浮点数),ptrade 底层会自动根据价格计算数量,并自动取整为 100 股(股票)或 10 张(可转债)。如果你不想手动计算数量,推荐使用order_value。order_target(security, amount):期望的最终数量。ptrade 在委托股票时也会取整 100 股,但传入的amount强烈建议使用int类型,避免触发类型校验错误。- 卖出零股:当卖出所有股票时(例如
order_target(security, 0)),不受 100 股的限制,系统会全部卖出。
总结与最佳实践
- 类型敏感:在 Python 量化编程中,时刻注意变量的数据类型。涉及到“数量”、“股数”的变量,一律使用
int()处理。 - 优先使用高级接口:如果只是想按资金比例买入,直接使用
order_value()或order_target_value(),让 ptrade 引擎帮你处理复杂的取整逻辑。 - 日志排查:在
order()之前,使用log.info(type(amount))打印一下数量的类型,可以快速定位是否是因为浮点数导致的校验失败。