CTP2报单录入

step1. 客户端报单请求

客户端进行报单是通过ReqOrderInsert接口进行的,需要对入口参数:结构体类型CThostFtdcInputOrderField的30个字段进行填充。

数据被写入到FtdcPacketBuffer里,然后写入到PacketFlow<Packet> *ThostFtdcConnection::m_api_flow里

<BrokerID value="8000" />
<InvestorID value="000226" />
<InstrumentID value="cu1403" />
<OrderRef value="654321" />
<UserID value="8000_amdin" />
<OrderPriceType value="2" />
<Direction value="1" />
<CombOffsetFlag value="0" />
<CombHedgeFlag value="1" />
<LimitPrice value="69830" />
<VolumeTotalOriginal value="1" />
<TimeCondition value="3" />
<GTDDate value=" " />
<VolumeCondition value="1" />
<MinVolume value="1" />
<ContingentCondition value="1" />
<StopPrice value=" " />
<ForceCloseReason value="0" />
<IsAutoSuspend value="0" />
<BusinessUnit value="0249c2c" />
<RequestID value="2147483647" />
<UserForceClose value=" " />
<IsSwapOrder value=" " />
<ExchangeID value="SHFE" />
<AccountID value="" />
<CurrencyID value=" " />
<ClientID value=" " />
<InvestUnitID value="554444" />
<IPAddress value="1212" />
<MacAddress value="dqd" />

 

step2. 交易前置接收报单请求,处理并排队

交易前置的FtdcTraderHandler收到FtdcPacket后,设置order_insert::Parameters的这3个字段:

FrontID(来自g_front_id)
SessionID(来自connection_id)
MeasureNo

其余30个字段来自FTDInputOrderField(FTDInputOrderField又来自从客户端接收的FtdcPacket),共计33个字段,然后进行排队。

 

step3. 交易引擎进行基础业务处理

交易引擎从排队流水中读取SdtpPacket,根据order_insert::PROCEDURE_ID执行相应的基础业务处理函数order_insert,在order_insert内根据ExchangeID执行相应交易所版本的insert_order函数。下面以大商所的insert_order为例继续进行介绍。

1)数据同步状态检查,并设置TradingDay、SettlementID

2)会话检查

     非超级会话需要校验是否在本中心具有交易权限

3)判断是否抢单

     如果报单引用非空,则需根据FrontID+SessionID+OrderRef查找原来的报单,若找到原来的报单就是抢单,若没有找到,则继续报单。下面假设非抢单,继续进行介绍。

4)检查报单字段

5)设置报单状态OrderStatus、报单提交状态OrderSubmitStatus

6)交易权限检查

   如果是期货或者期货组合则查找“大商所投资者合约交易权限”表,如果是期货期权则查找“大商所投资者期权交易权限”表,查找得到的交易权限不是“不能交易”就可以继续进行报单了。

7)设置报单的报单类型OrderType

8)取交易编码ClientID

9)条件单处理

10)handle_order

11)设置经纪公司报单编号BrokerOrderSeq

12)查找交易所报盘,并设置OrderInsertDate、OrderInsertTime、VolumeTotal、OrderLocalID

13)下单频率限制

14)插入“大商所报单表”

15)发送插入交易所报单命令

16)插入“大商所交易所报单表”

 

 其中第10步handle_order是最为重要的一步:资金/持仓的冻结,以handle_single_order为例进行介绍

(1)find_position,查找持仓

确定持仓方向(净持仓、多头、空头)和持仓日期后,查找大商所投资者持仓表,找到了原来的持仓那就拿出来返回(新持仓同旧持仓),找不到原来的持仓就初始化新持仓(旧持仓为默认持仓)。

 

(2)change_frozen_position,调整持仓冻结

根据新报单的报单状态和报单提交状态计算未成交数量,并以该未成交数量为变化量,按照新报单的买卖方向分别增加新持仓的多头冻结LongFrozen空头冻结ShortFrozen,最后结合新持仓的持仓(多空)方向判断是否为平仓。

注意:这里是插入报单期insert_order间进行的handle_single_order而且假定非抢单,所以没有旧报单,但是在别的场景下,比如交易所报单回报handle_exchange_order期间也会进行handle_single_order,彼时原始报单或者说旧报单是存在的,因此新持仓的多头冻结LongFrozen或空头冻结ShortFrozen增加量将不再是新报单的未成交数量,而是新报单与原始报单的未成交数量的差值。由此可见:

差值为正即新报单未成交数量>原始报单未成交数量的情况下,多头冻结或者空头冻结是增加的;//这应该就是传说中的冻结,或者说增加冻结吧,显然报单插入时是肯定增加冻结的!

差值为0即新报单未成交数量=原始报单未成交数量的情况下,多头冻结或者空头冻结是不变的;

差值为负即新报单未成交数量<原始报单未成交数量的情况下,多头冻结或者空头冻结是减少的;//这应该就是传说中的解冻,或者说减少冻结吧,显然撤单插入时是肯定减少冻结的!

 

( 3)frozen_algorithm,调整资金冻结

a. get_order_price,获取冻结价格:

b. cal_fronzen_amount,计算新持仓的冻结资金LongFrozenAmount(或ShortFrozenAmount:冻结价格3000×(新多头冻结数量5-旧多头冻结数量0)×合约数量乘数10=150000

c.  cal_frozen_margin,按合约的产品类型(期货或者期权)计算持仓的冻结保证金:根据指定经纪公司帐号查找“经纪公司保证金算法”表,然后根据找到的保证金算法的保证金价格类型(假设是昨结算价)获得保证金价格(根据钱提供的流水到这一步保证金价格由3000变成了0,因为昨结算价是0) ,接着查找【投资者保证金率】和【交易所保证金率】以计算冻结的保证金、保证金率、保证金率(按手数),最后判断新持仓的持仓多空方向,按照方向分别以不同的值来更新新持仓的冻结的保证金FrozenMargin、保证金率MarginRateByMoney、保证金率(按手数)MarginRateByVolume

d.  cal_cash,期货不需要计算新持仓的CashIn

e. cal_frozen_commission,计算新持仓的冻结手续费金额FrozenCommisision

 

( 4)update_position,更新“大商所投资者持仓”表

---End---

posted @ 2018-01-05 19:39  SAPCE  阅读(1025)  评论(0编辑  收藏  举报