上海期货交易CTP开发——下单

CTP下单涉及到预埋单、委托单的下单和撤单下单。

 

一、预埋单

 

1、预埋单(开盘前,或者非交易时段下单):

CThostFtdcParkedOrderField req = {0};  
strcpy(req.BrokerID,m_BrokerID);  
strcpy(req.InvestorID, m_InvestorInfos[reqInfo.lAccIdx].InvestorID);  
req.InstrumentID; //必填  
ASSERT(m_nOrderRef);  
sprintf(req.OrderRef, "%d", m_nOrderRef++); //必填    
strcpy(req.UserID,m_UserID);  
//价格类型:THOST_FTDC_OPT_AnyPrice  
req.OrderPriceType = THOST_FTDC_OPT_LimitPrice; //必填  
//买卖方向:THOST_FTDC_D_Buy,THOST_FTDC_D_Sell  
req.Direction = THOST_FTDC_D_Sell;  
//开平方向:THOST_FTDC_OF_Open,THOST_FTDC_OF_Close,THOST_FTDC_OF_CloseToday  
req.CombOffsetFlag[0] = THOST_FTDC_OF_Open;  
//套保标志:THOST_FTDC_HF_Speculation,THOST_FTDC_HF_Arbitrage,THOST_FTDC_HF_Hedge  
req.CombHedgeFlag[0] = THOST_FTDC_HF_Hedge;  
//价格  
req.LimitPrice = ; //必填  
//数量  
req.VolumeTotalOriginal = ; //必填  
req.TimeCondition = THOST_FTDC_TC_GFD;  //有效期类型:当日有效  
//req.GTDDate;  
req.VolumeCondition = THOST_FTDC_VC_AV; //成交量类型:任何数量  
req.MinVolume = 1;  //最小成交量:1  
req.ContingentCondition = THOST_FTDC_CC_Immediately;  //触发条件:立即  
//req.StopPrice = ;  //止损价  
req.ForceCloseReason = THOST_FTDC_FCC_NotForceClose;    //强平原因:非强平  
req.IsAutoSuspend = 0;  //自动挂起标志:否  
//req.BusinessUnit;  
req.RequestID = nRequestID;  
req.UserForceClose = 0;   //用户强评标志:否  
///预埋报单编号  
req.ParkedOrderID;  
///用户类型  
req.UserType;  
///预埋单状态  
req.Status;  
///错误代码  
req.ErrorID;  
///错误信息  
req.ErrorMsg;  
//req.IsSwapOrder;  
ReqParkedOrderInsert(&req, nRequestID);

 

2、预埋撤单:

CThostFtdcParkedOrderActionField req = {0};  
strcpy(req.BrokerID,m_BrokerID);  
strcpy(req.InvestorID, m_InvestorInfos[reqInfo.lAccIdx].InvestorID);  
req.OrderActionRef = m_nOrderActionRef++;  
req.OrderRef; //指向预埋单的OrderRef  
req.RequestID = reqInfo.nRequestID;  
req.FrontID = ; //指向预埋单的FrontID  
req.SessionID = ; //指向预埋单的SessionID  
req.ExchangeID; //指向预埋单的市场ID  
req.OrderSysID; //指向预埋单的OrderSysID  
req.ActionFlag = THOST_FTDC_AF_Delete;  
//req.LimitPrice = ;      
//req.VolumeChange = ;  
strcpy(req.UserID, m_UserID);  
req.InstrumentID; //指向预埋单的合约  
//req.ParkedOrderActionID;  
//req.UserType;  
//req.Status;  
//req.ErrorID;  
//req.ErrorMsg;  

ReqParkedOrderAction(&req,nRequestID);

 

3、预埋单撤单:

CThostFtdcRemoveParkedOrderField req = {0};  
strcpy(req.BrokerID,m_BrokerID);  
strcpy(req.InvestorID, m_InvestorInfos[reqInfo.lAccIdx].InvestorID);  
req.ParkedOrderID; //预埋单下单成功会得到该ID,撤单时填上该ID  

ReqRemoveParkedOrder(&req,nRequestID);

 

4、预埋撤单撤单:

CThostFtdcRemoveParkedOrderActionField req = {0};  
strcpy(req.BrokerID,m_BrokerID);  
strcpy(req.InvestorID, m_InvestorInfos[reqInfo.lAccIdx].InvestorID);  
req.ParkedOrderActionID; //预埋撤单下单成功会得到该ID,撤单是填上该ID  

ReqRemoveParkedOrderAction(&req,nRequestID);

 

二、委托单

1、委托单(交易时段内下单,即预埋单时段以外时段)

CThostFtdcInputOrderField req = {0};  
strcpy(req.BrokerID,m_BrokerID);  
strcpy(req.InvestorID, m_InvestorInfos[reqInfo.lAccIdx].InvestorID);  
req.InstrumentID; //必填  
sprintf(req.OrderRef, "%d", m_nOrderRef++);    
strcpy(req.UserID,m_UserID);  
//价格类型  
req.OrderPriceType = THOST_FTDC_OPT_LimitPrice;//必填  
//买卖方向  
req.Direction = ; //必填  
//开平方向  
req.CombOffsetFlag[0] = ; //必填  
//套保标志  
req.CombHedgeFlag[0] = ; //必填  
//价格  
req.LimitPrice = ; //必填  
//数量  
req.VolumeTotalOriginal = ; //必填  
req.TimeCondition = THOST_FTDC_TC_GFD;  //有效期类型:当日有效  
//req.GTDDate;  
req.VolumeCondition = THOST_FTDC_VC_AV; //成交量类型:任何数量  
req.MinVolume = 1;  //最小成交量:1  
req.ContingentCondition = THOST_FTDC_CC_Immediately;  //触发条件:立即  
//req.StopPrice = ;  //止损价  
req.ForceCloseReason = THOST_FTDC_FCC_NotForceClose;    //强平原因:非强平  
req.IsAutoSuspend = 0;  //自动挂起标志:否  
//req.BusinessUnit;  
req.RequestID = nRequestID;  
req.UserForceClose = 0;   //用户强评标志:否  
//req.IsSwapOrder;  
ReqOrderInsert(&req, nRequestID);

 

2、委托撤单:

CThostFtdcInputOrderActionField req = {0};  
strcpy(req.BrokerID,m_BrokerID);  
strcpy(req.InvestorID, m_InvestorInfos[reqInfo.lAccIdx].InvestorID);  
req.OrderActionRef = m_nOrderActionRef++;  
req.OrderRef; //指向委托单的OrderRef  
req.RequestID = nRequestID;  
req.FrontID // 指向委托单的FrontID;  
req.SessionID // 指向委托单的SessionID;  
req.ExchangeID; //指向委托单的ExchangeID  
req.OrderSysID; //指向委托单的OrderSysID  
req.ActionFlag = THOST_FTDC_AF_Delete;  
//req.LimitPrice = packTmp.GetFieldDouble(QLT_ID_CTP_Price);      
//req.VolumeChange = packTmp.GetFieldInt(QLT_ID_CTP_Volume);  
strcpy(req.UserID, m_UserID);  
req.InstrumentID; //指向委托单的合约  

ReqOrderAction(&req,reqInfo.nRequestID);

 

 

三、委托回应:

一笔委托下单,CTP平台如果校验出错,会返回一笔回应,不同委托下单,回应接口不一样。

1、ReqParkedOrderInsert:

OnRspParkedOrderInsert

2、ReqParkedOrderAction:

OnRspParkedOrderAction

3、ReqRemoveParkedOrder:

OnRspRemoveParkedOrder

4、ReqRemoveParkedOrderAction:

OnRspRemoveParkedOrderAction

5、ReqOrderInsert:

OnRspOrderInsert

6、ReqOrderAction:

OnRspOrderAction

 

 

四、委托出错:

 

OnErrRtnOrderInsert/OnErrRtnOrderAction
报盘将通过交易核心检查的报单发送到交易所前置,交易所会再次校验该报单。如果交易所认为该报单不合
法,交易所会将该报单撤销,将错误信息返回给报盘,并返回更新后的该报单的状态。当客户端接收到该错
误信息后,就会调用OnErrRtnOrderInsert /OnErrRtnOrderAction函数, 而更新后的报单状态会通过调用函数OnRtnOrder 发送到客
户端。如果交易所认为该报单合法,则只返回该报单状态(此时的状态应为:“尚未触发”)。

 

五、委托推送(RtnOrder)

一笔委托,可能会收到多笔委托推送,即RtnOrder会收到多次,我们需要通过

switch(pOrder->OrderSubmitStatus)
{
case THOST_FTDC_OSS_InsertSubmitted: ///已提交
case THOST_FTDC_OSS_CancelSubmitted: ///撤单已提交
case THOST_FTDC_OSS_ModifySubmitted: ///修改已提交
//bIsLast = false;
break;
case THOST_FTDC_OSS_Accepted: ///已接受
break;
case THOST_FTDC_OSS_InsertRejected: ///报单已被拒绝
case THOST_FTDC_OSS_CancelRejected: ///撤单已被拒绝
case THOST_FTDC_OSS_ModifyRejected: ///改单已被拒绝
rspInfo.ErrorID = pOrder->OrderSubmitStatus;
break;
default:
rspInfo.ErrorID = pOrder->OrderSubmitStatus;
break;
}

和

switch(pOrder->OrderStatus)
{
case THOST_FTDC_OST_AllTraded: ///全部成交
break;
case THOST_FTDC_OST_PartTradedQueueing: ///部分成交还在队列中
bIsLast = false;
break;
case THOST_FTDC_OST_PartTradedNotQueueing: ///部分成交不在队列中
break;
case THOST_FTDC_OST_NoTradeQueueing: ///未成交还在队列中
//bIsLast = false;
break;
case THOST_FTDC_OST_NoTradeNotQueueing: ///未成交不在队列中
break;
case THOST_FTDC_OST_Canceled: ///撤单
if (!bIsRequest)
{
pOrder->RequestID = FindFuncRequestID(GZ_DisEntrust,&reqInfo);
bIsRequest = pOrder->RequestID!=0;
}
break;
case THOST_FTDC_OST_Unknown: ///未知
case THOST_FTDC_OST_NotTouched: ///尚未触发
case THOST_FTDC_OST_Touched: ///已触发
bIsLast = false;
break;
default:
rspInfo.ErrorID = pOrder->OrderStatus;
break;
}

来判断委托状态。

这里要注意:委托撤单收到的RtnOrder里的RequestID和发送委托撤单的RequestID是不一样的,所以这里没法做到撤单的RequestID一一对应。

这里贴一下委托报单流程:

1. 交易终端通过交易接口向交易前置提交报单申请。
2. 主排队机从前置机订阅交易申请报文。
3. 主排队机将发布的交易序列报文发送给从排队机要求确认。
4. 从排队机收到待确认报文后将相关报文写入流水文件,并立即返回报文确认信息。
5. 交易核心从主排队机订阅交易序列报文。
6. 交易核心对收到的交易序列报文做合法性检查,检查出错误的交易申请报文后就会返回给交易前置一个
包含错误信息的报单响应报文,交易前置立即将该报文信息转发给交易终端。如果检出为合法的交易申
请报文,交易核心也会返回一个报单响应报文到交易前置,但是该报文不会被交易前置返回给交易终端。
7. 两种情况:1,交易前置从交易核心订阅到错误的报单响应报文,以对话模式将该报文转发给交易终端。
2,交易核心返回给交易前置的响应报文是正确的,交易前置立即以私有模式返回对应报单的报单回报到
交易终端(图中前置机到交易终端8)。
8. 两个过程:1,交易前置在订阅到交易核心的报单回报后,以私有模式将该报单回报发送到交易终端。2,
交易核心向交易前置发送了第一个报单回报后,立即产生向交易所申请该报单插入的申请报文,该报文
被报盘管理订阅。
9. 报盘管理订阅到交易所报盘插入申请报文后,将该报文转发到对应报盘接口。
10. 报盘收到报盘管理的报单申请报文后,通过交易所提供的交易接口将该笔报单发送到交易所。
11. 报盘通过交易接口从交易所前置接收报单回报以及成交回报或出错的报单响应报文。
12. 报盘将从交易所接收到的报单回报及成交回报或报单响应汇总到报盘管理。
13. 主排队机从报盘管理订阅从交易所返回的报单信息。
14. 主排队机将报文信息序列化后发送给从排队机进行确认。
15. 从排队机收到待确认报文后将该报文写入流水,并立即返回报文确认信息。
16. 交易核心从主排队机订阅所有的报单以及成交回报信息。
17. 交易前置从交易核心订阅所有交易核心发布的交易结果数据。
18. 交易前置将订阅到的交易结果数据分发到各交易终端。

总结:

对于下单流程的处理:

1、下单出错的话,可以在OnRspXXX函数和OnErrRtnXXX里处理,在这里认为一次下单过程完成,因为不知道RtnOrder里会不会有回应,所以不能在RtnOrder里处理

2、下单成功的话,在RtnOrder里要区分是下单成功、还是撤单、还是委托成功。然后通过RequestID映射到请求,完成一次下单过程

3、进一步处理RtnTrade,收到这个消息,可以刷新成交列表,重新请求持仓列表等

4、这样整个下单流程就完整了

 

 

 

 

 

 

 

分享到: