部分用户在使用真格量化设计策略时因为对交易柜台的机制不熟悉导致对委托、成交、持仓及资金的状态查询与预期不一致,我们将通过介绍CTP的报单机制来说明正确的查询方法。


CTP报单函数简介

ReqOrderInsert

请求报单

OnRspOrderInsert

CTP核心返回的包含错误信息的报单响应

OnRtnOrder

交易系统返回的报单状态,每次报单状态发生变化时被调用。一次报单过程中会被调用数次(例如,如果一笔委托一次性成交则可收到3次委托回报):交易系统将报单向交易所提交时,交易所撤销或接受该报单时,该报单成交时。

例如我们在真格量化系统日志中见到的委托回报:

mark

所以收到一条委托回报并不能说明委托已经成功(即被交易所接受),用户仍需根据委托编号来查询其委托状态。

例如在真格量化中通过status字段来查询委托的状态:

mark

新增处理方式:报单在交易所端校验失败,被交易所拒绝后,CTP 系统同样通过此接口返回报错信息;其中的 OrderStatusMsg 字段包含报错信息。

OnErrRtnOrderInsert

此接口仅在报单被 CTP 端拒绝时被调用用来进行报错。

OnRtnTrade

如果该报单由交易所进行了撮合成交,交易所再次返回该报单的状态(已成交)。并通过此函数返回该笔成交。

报单成交之后,一个报单回报(OnRtnOrder)和一个成交回报(OnRtnTrade)会被发送到客户端,报单回报中报单的状态为“已成交”。建议开发者将成交回报作为报单成交的标志,因为 CTP的交易核心在收到 OnRtnTrade 之后才会更新该报单的状态。如果客户端通过委托回报来判断报单成交与否并立即平仓,有极小的概率会出现在平仓指令到达 CTP交易核心时该报单的状态仍未更新,就会导致对已经持有的仓位无法平仓。


报单序列号

报单序号用于在查询中区分不同的报单。

在CTP和交易所中,每笔委托报单都有 3 组唯一序列号,保证其与其他报单是不重复的。

FrontID + SessionID + OrderRef

用户账户登录之后,交易核心会返回对应此次连接的前置机编号 FrontID 和会话编号 SessionID。这两个编号在此次连接中是不变的。

OrderRef 是报单操作的核心数据结构 CThostFtdcInputOrderField 中的一个字段。开发者可以让 OrderRef 在一次登录期间从MaxOrderRef 起逐一递增,以保证报单的唯一性。开发者也可以选择不对它赋值,则交易核心会自动赋予一个唯一性的值。

这组报单序列号可以由客户端或开发者自行维护,客户端或开发者可以通过该序列号对未成交的委托随时进行撤单操作。

在真格量化中用户可以通过委托对象的id来对委托单进行状态查询、撤单等各种操作:

mark

ExchangeID + TraderID + OrderLocalID

交易核心将报单提交到报盘管理之后由交易核心生成 OrderLocalID并返回给客户端。ExchangeID为合约所在交易所的代码,TraderID由交易核心选定返回。与第一组序列号不同的是:该序列号是由CTP平台的交易核心维护。

ExchangeID + OrderSysID

交易所在接收了报单之后,会为该报单生成报单在交易所的编号OrderSysID。再经由综合交易平台转发给客户端。ExchangeID是固定的。客户端也可以通过这组序列号进行撤单操作。这组序列号由交易所维护。


委托回报

CTP使用的函数是 OnRtnOrder。核心数据结构为 CThostFtdcOrderField。

报单回报主要作用是通知客户端该报单的最新状态,如已提交,已撤销,未触发,已成交等。

开发者应注意,每次委托状态有变化,该函数都会被调用一次。

VolumeTotalOriginal & VolumeTraded & VolumeTotal

上述三个字段分别对应该报单的原始报单数量,已成交数量和剩余数量。

如果报单是分笔成交,则每次成交都会有一次 OnRtnOrder 返回。

条件单触发时,交易核心会对该报单的合法性进行校验,如果校验失败,通过函数 OnRtnErrorConditionalOrder返回校验失败的错误信息。

OrderStatus

 0 全部成交

 1 部分成交,订单还在交易所撮合队列中

 3 未成交,订单还在交易所撮合队列中

 5 已撤销

 a 未知-订单已提交交易所,未从交易所收到确认信息

在真格量化中其对应事件监听函数为OnOrderChange:

mark


成交回报

CTP使用的函数是OnRtnTrade。

函数返回报单成交回报,每笔成交都会调用一次成交回报。成交回报中只包含合约,成交数量,价格等信息。成交回报只包含该笔成交相关的信息,并不包含该笔成交之后投资者的持仓,资金等信息。

函数ReqQryTradingAccount 用于查询投资者最新的资金状况。如保证金,手续费,持仓盈利,可用资金等。

我们建议开发者以成交回报来判断报单是否成交,以及成交数量和价格;若以委托回报(状态为“部分成交或全不成交”)进行判断,由于报单回报与成交回报之间存在理论上的时间差(尽管微乎其微),而 CTP 后台是以成交回报为准更新报单状态的,因此有可能导致对持仓平仓不成功。而想判断成交后账户资金的变化,其查询也应当在确认成交状态后来进行,以确保查询到的资金状况已经反映最新成交所带来的变化。

在真格量化中其对应的事件监听函数为OnTradeDeal:

mark