问题描述
解决方案
在PTrade量化交易平台中,期货交易的平仓顺序(优先平昨或只平今仓)是通过平仓函数 buy_close(买入平仓/空平)和 sell_close(卖出平仓/多平)中的 close_today 参数来控制的。
以下是具体的实现方法和代码示例。
核心逻辑说明
PTrade 的平仓函数定义如下:
buy_close(contract, amount, limit_price=None, close_today=False)sell_close(contract, amount, limit_price=None, close_today=False)
通过设置 close_today 参数的值来实现不同的平仓逻辑:
-
优先平昨仓 (
close_today=False):- 这是默认设置。
- 系统会优先平掉昨日(及以前)持有的历史仓位。
- 如果委托数量大于昨仓数量,剩余部分会自动平掉今日新开的仓位。
-
只平今仓 (
close_today=True):- 系统强制只平掉今日新开的仓位。
- 如果委托数量大于今日持仓数量,系统通常会调整为今日持仓的最大数量或报错(取决于具体交易所规则)。
- 注意:根据PTrade文档,
close_today=True主要对 上海期货交易所 (SHFE) 和 上海国际能源交易中心 (INE) 生效。对于其他交易所(如中金所、大商所、郑商所),通常不区分平今和平昨,或者系统会将其强制转换为False。
PTrade 策略代码示例
以下代码展示了如何在策略中实现这两种操作。
def initialize(context):
# 初始化策略
# 这里以上海期货交易所的沪铜(CU)为例,因为上期所严格区分平今和平昨
g.future_code = 'CU2310.XSGE'
set_universe([g.future_code])
# 设置保证金比例和手续费(可选)
set_margin_rate("CU", 0.08)
set_future_commission("CU", 0.00005)
def handle_data(context, data):
# 获取当前持仓信息
position = get_position(g.future_code)
# ---------------------------------------------------
# 场景一:优先平昨仓 (Close Yesterday First)
# ---------------------------------------------------
# 假设我们要平掉 2 手多单
# close_today=False (默认值),表示优先平昨,昨仓不够再平今
if position.long_amount > 0:
# 卖出平仓,多头平仓
sell_close(g.future_code, 2, close_today=False)
log.info("执行优先平昨操作:卖出平仓 2 手")
# ---------------------------------------------------
# 场景二:只平今仓 (Close Today Only)
# ---------------------------------------------------
# 假设我们要平掉 1 手今日开的空单
# close_today=True,表示强制只平今仓
# 注意:必须确保有足够的今仓,否则可能委托失败或被调整
if position.short_amount > 0:
# 买入平仓,空头平仓
buy_close(g.future_code, 1, close_today=True)
log.info("执行只平今仓操作:买入平仓 1 手")
def on_order_response(context, order_list):
# 打印委托反馈,查看订单状态
for order in order_list:
log.info("订单更新: %s, 状态: %s" % (order['entrust_no'], order['status']))
详细参数解析
1. 优先平昨仓 (默认模式)
当 close_today=False 时,PTrade 引擎的处理逻辑如下:
- 检查该合约的昨仓数量(
old_amount)。 - 如果
下单数量 <= 昨仓数量:全部申报为平昨。 - 如果
下单数量 > 昨仓数量:先申报平昨old_amount,剩余的下单数量 - old_amount申报为平今。
2. 只平今仓 (特殊模式)
当 close_today=True 时:
- 引擎会检查该合约的今仓数量(
today_amount)。 - 生成的委托单将带有“平今”标记(Specific for SHFE/INE)。
- 特别提示:如果你的策略运行在非上期所/能源中心品种(如中金所 IF),设置
close_today=True可能会被系统忽略并发出警告,自动转为False处理,因为这些交易所通常不区分平今/平昨指令,或者按交易所默认规则(通常是先开先平)处理。
常见问题 Q&A
Q1: 如果我在中金所(如股指期货 IF)使用 close_today=True 会怎样?
A: PTrade 文档指出,close_today=True 仅对上海期货交易所生效。对于其他交易所,若设置为 True,系统会警告并强行转换为 close_today=False。中金所等交易所通常遵循“先开先平”原则,或者在柜台层面处理手续费优惠,API层面通常不需要显式指定平今。
Q2: 如何判断我当前有多少“今仓”和“昨仓”?
A: 可以通过 get_position 获取持仓对象,利用以下字段计算:
amount: 总持仓。today_amount: 今仓数量(仅回测有效,实盘中需通过amount - 昨仓或柜台返回字段判断)。- 实盘技巧:在实盘中,通常
amount是总持仓。对于上期所品种,柜台通常会区分today_amount。如果 API 的Position对象在实盘未直接提供yesterday_amount,可以用amount - today_amount估算昨仓。
Q3: 为什么要区分平今和平昨?
A: 主要是因为手续费不同。特别是在上海期货交易所(XSGE),某些品种(如螺纹钢、热卷等)在特定时期,平今仓的手续费可能非常昂贵,或者反而免费(免平今)。策略通过控制平仓顺序可以显著降低交易成本。
Q4: 如果我想“优先平今,今仓不够再平昨”怎么办?
A: PTrade API 没有直接的 PrioritizeToday 参数。你需要自己写逻辑:
- 获取当前今仓数量
today_qty。 - 如果
目标平仓量 <= today_qty:调用close_today=True。 - 如果
目标平仓量 > today_qty:- 先调用
close_today=True平掉所有今仓。 - 再调用
close_today=False平掉剩余数量(此时因为今仓已为0,实际上就是平昨)。
- 先调用