期货 / 期货:开平仓与订单

期货

期货:开平仓与订单

期货回测的下单写法:buy_open、sell_open、sell_close、buy_close 四种开平操作与平今参数,target_future_group_order 组合目标仓位,市价、限价 IOC 与 GFD,撮合参考价与滑点;查询与撤单、订单字段与状态、账户资金,以及多空、今昨与可平持仓。

一、四种开平操作

操作 方法 side effect
开多 buy_open 0 0 开仓
开空 sell_open 1 0 开仓
平多 sell_close 1 1 平仓
平空 buy_close 0 1 平仓

四个方法的前三个位置参数都是 account_id, id_or_ins, amount,其余参数建议按名称传。

参数 类型、默认值 说明
account_id 字符串,必填 期货账户
id_or_ins 字符串,必填 带交易所后缀的真实合约
amount Python int,必填 正整数手数;平仓不超过对应可平量
style 默认 None 默认市价;也可传 LimitOrderStyle(...)
remark 字符串,默认 None 订单备注
close_today 布尔值,默认 False,仅平仓 False 先平昨仓、不足再平今仓;True 指定平今,数量不能超过今仓可平量
close_local 布尔值,默认 True,仅平仓 保留接口默认的仓位口径;普通回测按当前账户可平持仓执行,无须修改
retry_num 整数,默认 None 使用追单功能时的追单次数标记;普通委托省略

平仓接口中,close_todayclose_local 位于 style 之后、retry_num 之前。指定平今时写 close_today=True,不要靠位置参数猜顺序。close_local 不是绕过可平仓位校验的开关。

这些方法通常返回 list[Order];格式、数量等检查失败时可能返回空列表或空值,拒单也可能返回一个 status=-1 的订单对象。

注意

列表非空不等于成交成功,要继续看每张订单的状态、成交数量和 message

下面的函数把某合约的今仓全部平掉:

python
from panda_backtest.api.api import buy_close, sell_close


def close_today_positions(context, symbol):
    position = context.future_account_dict[context.account].positions[symbol]
    long_amount = int(position.closable_today_buy_quantity)
    short_amount = int(position.closable_today_sell_quantity)
    if long_amount > 0:
        sell_close(context.account, symbol, long_amount, close_today=True)
    if short_amount > 0:
        buy_close(context.account, symbol, short_amount, close_today=True)

从 DataFrame、NumPy 或持仓字段得到的手数,先检查是有效的整数数量,再转成 int;不要直接传 numpy.int64,也不要用 int 静默截断一个本来不是整数的下单意图。

二、组合目标仓位

target_future_group_order(account, long_symbol_dict, short_symbol_dict) 接受两个 {真实合约: 非负整数目标手数} 字典,返回 None。多头和空头分别计算;目标手数是调仓后的持仓数量,不是本次买卖数量。

python
from panda_backtest.api.api import target_future_group_order


def set_portfolio_target(context):
    target_future_group_order(
        context.account,
        {"A2501.DCE": 2},
        {"M2501.DCE": 1},
    )

上例表示整个期货账户的目标是豆一多头 2 手、豆粕空头 1 手;不在目标字典中的现有持仓方向也会尝试平掉。两个字典都为空表示目标空仓,所以数据查询失败时,不要把空字典当作有效目标提交。

组单适合单一策略专属的账户。它会提交多笔委托,任何一笔都可能拒绝、部分成交或撤单,不是保证同时成功的交易;再次调整前先检查未完成委托,提交后核对实际持仓。主力切换时,把目标字典里的旧合约换成新合约,会产生「平旧、开新」的并行调仓;要求旧仓确认全部平掉后才开新仓的,用分步换月

三、市价、限价与撮合价格

写法 含义
省略 stylestyle=MarketOrderStyle() 市价单,IOC
LimitOrderStyle(price) 限价 IOC,未成交部分立即撤销
LimitOrderStyle(price, time_condition=TimeConditionType.GFD) 限价当日有效,未成交部分保留到后续行情撮合,或撤单、日终为止

price 用品种报价单位,并对齐该合约的最小变动价位。不同品种的最小变动价位不同,不要把示例里的价差原样用到别的合约上。

回测 matching_type 对应的撮合参考价:

取值 参考价
0 当前 Bar 收盘价(日线示例用这个)
1 当前 Bar 开盘价
2 买一卖一中间价
3 买单取卖一、卖单取买一

23 需要有效的盘口数据。期货滑点按最小变动价位的整数倍加在买价上、从卖价中减去。

限价单按所选参考价判断能否成交,同时受成交量等条件约束;不能理解为「当根最高 / 最低价触及限价就一定成交」。计算信号时还要注意时间顺序:用本根的收盘信息、却假设在本根开盘成交,会引入未来信息。

四、查询与撤单

方法 参数 返回与用法
get_open_future_orders account_id, symbol=None 未完成订单列表;无订单返回 [],不传合约时查该账户全部
cancel_future_order account_id, order_id 发起撤单;没有可用于确认成功的返回值,看回调和后续查询
auto_retry_cancel_future_order order, max_retry=15 在撤单回调里对未成交量按原方向重新提交市价单;返回新订单列表或空值

挂单查询包含待报、已报以及仍在队列中的部分成交 / 未成交订单。IOC 也有报单和处理过程,「IOC 不留长期挂单」不等于「永远不需要检查在途状态」。

查询范围是账户和合约,不是策略私有的登记表。记录本策略返回的订单号后再撤单,避免误撤其他委托。只有继续追单仍符合当前信号和风险条件时才用自动追单,它会产生新的市价委托。

五、订单字段

字段 类型、单位 含义
order_id 字符串 订单号,用于撤单和关联回报
account 字符串 账户
order_book_id 字符串 合约代码
side / effect 整数 买卖方向和开平方向,见上文
price 数值,报价单位 委托限价;市价单不以此表示最终成交价
price_type 整数 1 市价,2 限价
quantity 数值,手 订单数量字段;部分成交过程中不能用来反推原始委托量,需要时自己保存
filled_quantity 数值,手 累计成交数量
unfilled_quantity 数值,手 未成交数量
cur_filled_quantity 数值,手 本次成交数量
avg_price 数值,报价单位 订单成交价格字段;多次成交的成本结合成交回报自行记录
transaction_cost 数值,元 订单费用
status 整数 订单状态,见下表
message 字符串 拒单、撤单或其他说明
remark 自定义备注 下单时传入的备注
trade_date 日期值 订单所属交易日

六、订单状态

状态 含义 后续处理
0 待报 继续等待
1 已报未成交 继续等待或撤单
2 全部成交 按实际持仓推进策略
3 已撤单 核对已成交部分,未成交部分结束
4 部分成交,仍在队列 保留未完成登记
5 部分成交,不在队列 核对已成交部分和剩余目标
6 未成交,仍在队列 继续等待或撤单
7 未成交,不在队列 核对终结原因
8 / 9 未触发 / 已触发 结合所用委托类型处理,不当作全部成交
-1 拒单 阅读 message,检查参数、资金、持仓和行情

七、账户资金

account = context.future_account_dict[context.account],以下金额单位均为元:

字段 含义
total_value 账户总权益
cash 可用资金
frozen_cash 冻结资金
margin 已占用保证金
buy_margin / sell_margin 多头 / 空头保证金
daily_pnl 当日盈亏,包含权益变动和当日出入金调整
holding_pnl / realized_pnl 持仓盈亏 / 平仓盈亏
add_profit 累计盈亏,已调整累计出入金
transaction_cost 累计手续费
deposit / withdraw 累计入金 / 出金
today_deposit / today_withdraw 当日入金 / 出金
positions 期货持仓容器

add_profitdaily_pnl 都是金额,不是收益率。可用资金也不是总权益,开仓时还要预留保证金和手续费。

八、多空、今昨与可平持仓

position = account.positions[symbol] 获取指定合约,未持有时也能得到数量为 0 的对象。遍历当前持仓优先用 positions.keys()(只返回实际有持仓的合约);positions.get(symbol) 未持仓时返回 Noneitems()values() 可能带出零仓位条目。

多头字段 空头字段 类型、单位及含义
buy_quantity sell_quantity 手;该方向总持仓
buy_today_quantity sell_today_quantity 手;该方向今仓
closable_buy_quantity closable_sell_quantity 手;扣除冻结后的总可平量
closable_today_buy_quantity closable_today_sell_quantity 手;扣除冻结后的今仓可平量
buy_avg_open_price sell_avg_open_price 报价单位;开仓均价
buy_avg_holding_price sell_avg_holding_price 报价单位;持仓成本价,可能受结算影响
buy_margin sell_margin 元;该方向占用保证金
buy_daily_pnl sell_daily_pnl 元;该方向当日盈亏
  • 昨仓数量 = 总持仓 − 今仓;昨仓可平量 = 总可平量 − 今仓可平量。
  • 平仓取可平量,不能把全部持仓量直接当可平量。总持仓大于 0 而可平量为 0,可能是存在冻结,不要重复发平仓单。
  • 同一合约可以同时有多头和空头,不能用单个数量或净持仓代替两侧仓位。平多用 sell_close,平空用 buy_close