/// <summary> /// 创建事件参数 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="event"></param> /// <param name="requestID"></param> /// <param name="rspInfo"></param> protected CTPEventArgs <T> CreateEventArgs <T>(int requestID, CTPResponseInfo rspInfo) where T : struct { //if (requestID == 0) //{ // throw new CBFNativeException("Invalid Operation in PreProcessResponse"); //} //转换响应数据 List <Object> rspDataList = this.responseDataMap[requestID]; T value = default(T); if (rspDataList.Count > 0) { value = (T)(rspDataList[0]); } //创建事件参数 CTPEventArgs <T> args = new CTPEventArgs <T>(value, rspInfo); args.RequestData = this.GetRequestData(requestID); return(args); }
/* * /// <summary> * /// 初始化接受数据类型 * /// </summary> * protected override void InitResponseDataTypeMapping() * { * ///客户端认证响应 * responseDataTypeMapping.Add(CTPStockResponseType.AuthenticateResponse, typeof(CZQThostFtdcRspAuthenticateField)); * ///登录请求响应 * responseDataTypeMapping.Add(CTPStockResponseType.UserLoginResponse, typeof(CZQThostFtdcRspUserLoginField)); * ///登出请求响应 * responseDataTypeMapping.Add(CTPStockResponseType.UserLogoutResponse, typeof(CZQThostFtdcUserLogoutField)); * ///用户口令更新请求响应 * responseDataTypeMapping.Add(CTPStockResponseType.UserPasswordUpdateResponse, typeof(CZQThostFtdcUserPasswordUpdateField)); * ///报单录入请求响应 * responseDataTypeMapping.Add(CTPStockResponseType.OrderInsertResponse, typeof(CZQThostFtdcInputOrderField)); * ///报单操作请求响应 * responseDataTypeMapping.Add(CTPStockResponseType.OrderActionResponse, typeof(CZQThostFtdcInputOrderActionField)); * ///查询最大报单数量响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryMaxOrderVolumeResponse, typeof(CZQThostFtdcQueryMaxOrderVolumeField)); * ///请求查询报单响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryOrderResponse, typeof(CZQThostFtdcOrderField)); * ///请求查询成交响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryTradeResponse, typeof(CZQThostFtdcTradeField)); * ///请求查询资金账户响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryTradingAccountResponse, typeof(CZQThostFtdcTradingAccountField)); * ///请求查询投资者响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryInvestorResponse, typeof(CZQThostFtdcInvestorField)); * ///请求查询交易编码响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryTradingCodeResponse, typeof(CZQThostFtdcTradingCodeField)); * ///请求查询合约手续费率响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryInstrumentCommissionRateResponse, typeof(CZQThostFtdcInstrumentCommissionRateField)); * ///请求查询交易所响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryExchangeResponse, typeof(CZQThostFtdcExchangeField)); * ///请求查询合约响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryInstrumentResponse, typeof(CZQThostFtdcInstrumentField)); * ///请求查询行情响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryDepthMarketDataResponse, typeof(CZQThostFtdcDepthMarketDataField)); * ///请求查询投资者持仓明细响应 * responseDataTypeMapping.Add(CTPStockResponseType.QueryInvestorPositionDetailResponse, typeof(CZQThostFtdcInvestorPositionDetailField)); * ///错误应答 * responseDataTypeMapping.Add(CTPStockResponseType.ErrorResponse, typeof(CZQThostFtdcRspInfoField)); * ///报单通知 * responseDataTypeMapping.Add(CTPStockResponseType.ReturnOrderResponse, typeof(CZQThostFtdcOrderField)); * ///成交通知 * responseDataTypeMapping.Add(CTPStockResponseType.ReturnTradeResponse, typeof(CZQThostFtdcTradeField)); * ///报单录入错误回报 * responseDataTypeMapping.Add(CTPStockResponseType.ErrorReturnOrderInsertResponse, typeof(CZQThostFtdcInputOrderField)); * ///报单操作错误回报 * responseDataTypeMapping.Add(CTPStockResponseType.ErrorReturnOrderActionResponse, typeof(CZQThostFtdcOrderActionField)); * ///合约交易状态通知 * responseDataTypeMapping.Add(CTPStockResponseType.ReturnInstrumentStatusResponse, typeof(CZQThostFtdcInstrumentStatusField)); * * } */ #region CTP API Invoke protected override CTPResponseInfo GetResponseInfo(IntPtr pRspInfo) { CTPResponseInfo rsp = new CTPResponseInfo(); CZQThostFtdcRspInfoField rspInfo = PInvokeUtility.GetObjectFromIntPtr <CZQThostFtdcRspInfoField>(pRspInfo); rsp.ErrorID = rspInfo.ErrorID; //rsp.Message = PInvokeUtility.GetUnicodeString(rspInfo.ErrorMsg); rsp.Message = rspInfo.ErrorMsg; return(rsp); }
/// <summary> /// 回调函数 /// </summary> /// <param name="type"></param> /// <param name="pData"></param> /// <param name="pRspInfo"></param> /// <param name="requestID"></param> /// <param name="isLast"></param> protected void CTPResponseHandler(int type, IntPtr pData, IntPtr pRspInfo, int requestID, bool isLast) { TResponseType responseType = ConvertToResponseType(type); ReceiveResponseData(responseType, pData, requestID); if (isLast == true) { CTPResponseInfo rspInfo = GetResponseInfo(pRspInfo); this.ProcessBusinessResponse(responseType, pData, rspInfo, requestID); } }
/// <summary> /// 创建事件参数 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="rspData"></param> /// <param name="rspInfo"></param> /// <returns></returns> protected CTPEventArgs <T> CreateEventArgs <T>(IntPtr rspData, CTPResponseInfo rspInfo) { //转换响应数据 T value = default(T); if (rspData != IntPtr.Zero) { value = PInvokeUtility.GetObjectFromIntPtr <T>(rspData); } //创建事件参数 CTPEventArgs <T> args = new CTPEventArgs <T>(value, rspInfo); return(args); }
/// <summary> /// 创建事件参数 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="requestID"></param> /// <param name="rspInfo"></param> /// <returns></returns> protected CTPEventArgs <List <T> > CreateListEventArgs <T>(int requestID, CTPResponseInfo rspInfo) where T : struct { if (requestID == 0) { throw new Exception("Invalid Operation in PreProcessResponse"); } List <T> list = new List <T>(); //转换响应数据 foreach (Object p in this.responseDataMap[requestID]) { list.Add((T)p); } //创建事件参数 CTPEventArgs <List <T> > args = new CTPEventArgs <List <T> >(list, rspInfo); args.RequestData = this.GetRequestData(requestID); return(args); }
/// <summary> /// 处理业务响应 /// </summary> /// <param name="responseType"></param> /// <param name="pData"></param> /// <param name="rspInfo"></param> /// <param name="requestID"></param> protected abstract void ProcessBusinessResponse(TResponseType responseType, IntPtr pData, CTPResponseInfo rspInfo, int requestID);
protected override void ProcessBusinessResponse(CTPStockResponseType responseType, IntPtr pData, CTPResponseInfo rspInfo, int requestID) { switch (responseType) { #region 当客户端与交易后台建立起通信连接时(还未登录前),该方法被调用。 case CTPStockResponseType.FrontConnectedResponse: { this.isConnect = true; this.UserLogin(); //调用事件 OnEventHandler(CTPStockResponseType.FrontConnectedResponse, new CTPEventArgs()); break; } #endregion #region 用户登录 case CTPStockResponseType.UserLoginResponse: { CTPEventArgs <CZQThostFtdcRspUserLoginField> args = CreateEventArgs <CZQThostFtdcRspUserLoginField>(requestID, rspInfo); this.isLogin = true; this.OnEventHandler(CTPStockResponseType.UserLoginResponse, args); } break; #endregion case CTPStockResponseType.DepthMarketDataResponse: { if (this == null || this.isDispose == true) { return; } CTPEventArgs <CZQThostFtdcDepthMarketDataField> args = CreateEventArgs <CZQThostFtdcDepthMarketDataField>(pData, rspInfo); OnEventHandler(CTPStockResponseType.DepthMarketDataResponse, args); break; } case CTPStockResponseType.ErrorResponse: { CTPEventArgs args = new CTPEventArgs(rspInfo); OnEventHandler(CTPStockResponseType.ErrorResponse, args); break; } } }
public CTPEventArgs(CTPResponseInfo rspInfo) : this(rspInfo, 0) { }
public CTPEventArgs(CTPResponseInfo rspInfo, int requestID) { this.ResponseInfo = rspInfo; this.RequestID = requestID; }
protected override void ProcessBusinessResponse(CTPStockResponseType responseType, IntPtr pData, CTPResponseInfo rspInfo, int requestID) { Trace.WriteLine(string.Format("{0} [{1}]:{2},{3},{4}", this.wallTimeStopwatch.ElapsedMilliseconds, this.UserKey, "ProcessBusinessResponse", responseType, requestID)); switch (responseType) { #region 当客户端与交易后台建立起通信连接时(还未登录前),该方法被调用。 case CTPStockResponseType.FrontConnectedResponse: { this.isConnect = true; this.UserLogin(); //调用事件 OnEventHandler(CTPStockResponseType.FrontConnectedResponse, new CTPEventArgs()); break; } #endregion #region 通信中断 case CTPStockResponseType.FrontDisconnectedResponse: /// 当客户端与交易后台通信连接断开时,该方法被调用。当发生这个情况后,API会自动重新连接,客户端可不做处理。 ///@param nReason 错误原因 /// 0x1001 网络读失败 /// 0x1002 网络写失败 /// 0x2001 接收心跳超时 /// 0x2002 发送心跳失败 /// 0x2003 收到错误报文 { this.isConnect = false; //调用事件 OnEventHandler(CTPStockResponseType.FrontDisconnectedResponse, new CTPEventArgs()); } break; #endregion #region 心跳超时警告 case CTPStockResponseType.HeartBeatWarningResponse: { /// <summary> ///心跳超时警告。当长时间未收到报文时,该方法被调用。 ///@param nTimeLapse 距离上次接收报文的时间 /// </summary> /// <param name="nTimeLapse"></param> Trace.WriteLine("CTPTrader:OnHeartBeatWarning!! " + pData.ToString()); break; } #endregion #region 客户端认证响应 case CTPStockResponseType.AuthenticateResponse: { CTPEventArgs <CZQThostFtdcRspAuthenticateField> args = CreateEventArgs <CZQThostFtdcRspAuthenticateField>(requestID, rspInfo); this.OnEventHandler(CTPStockResponseType.AuthenticateResponse, args); break; } #endregion #region 用户登录 case CTPStockResponseType.UserLoginResponse: { CTPEventArgs <CZQThostFtdcRspUserLoginField> args = CreateEventArgs <CZQThostFtdcRspUserLoginField>(requestID, rspInfo); CZQThostFtdcRspUserLoginField userLogin = args.Value; if (rspInfo.ErrorID == 0) { this.BrokerID = userLogin.BrokerID; this.FrontID = userLogin.FrontID; this.SessionID = userLogin.SessionID; this.isLogin = true; this.loginTime = userLogin.LoginTime; //最大报单引用 int orderRef = 0; if (int.TryParse(userLogin.MaxOrderRef, out orderRef) == false) { orderRef = 0; } this.currentOrderRef = orderRef; //this.currentOrderRef++; DateTime.TryParseExact(userLogin.TradingDay, "yyyyMMdd", null, System.Globalization.DateTimeStyles.AllowWhiteSpaces, out this.tradingDate); TimeSpan.TryParse(userLogin.DCETime, out this.loginTimeDCE); TimeSpan.TryParse(userLogin.CZCETime, out this.loginTimeCZCE); TimeSpan.TryParse(userLogin.SHFETime, out this.loginTimeSHFE); //TimeSpan.TryParse(userLogin.DCETime, out this.currentTimeDCE); this.wallTimeStopwatch.Start(); this.timer.Change(0, 1000); } this.OnEventHandler(CTPStockResponseType.UserLoginResponse, args); } break; #endregion #region 登出请求响应 case CTPStockResponseType.UserLogoutResponse: { this.isLogin = false; //调用事件 OnEventHandler(CTPStockResponseType.UserLogoutResponse, new CTPEventArgs()); break; } #endregion #region 用户口令更新请求响应 case CTPStockResponseType.UserPasswordUpdateResponse: /// <summary> /// 用户口令更新请求响应 /// </summary> { CTPEventArgs <CZQThostFtdcUserPasswordUpdateField> args = CreateEventArgs <CZQThostFtdcUserPasswordUpdateField>(requestID, rspInfo); this.OnEventHandler(CTPStockResponseType.UserPasswordUpdateResponse, args); break; } #endregion #region 报单录入请求响应 case CTPStockResponseType.OrderInsertResponse: { CTPEventArgs <CZQThostFtdcInputOrderField> args = CreateEventArgs <CZQThostFtdcInputOrderField>(requestID, rspInfo); //调用事件 OnEventHandler(CTPStockResponseType.OrderInsertResponse, args); break; } #endregion #region 改单响应 case CTPStockResponseType.OrderActionResponse: { CTPEventArgs <CZQThostFtdcInputOrderActionField> args = CreateEventArgs <CZQThostFtdcInputOrderActionField>(requestID, rspInfo); //调用事件 OnEventHandler(CTPStockResponseType.OrderActionResponse, args); break; } #endregion #region 查询最大报单数量响应 case CTPStockResponseType.QueryMaxOrderVolumeResponse: { CTPEventArgs <CZQThostFtdcQueryMaxOrderVolumeField> args = CreateEventArgs <CZQThostFtdcQueryMaxOrderVolumeField>(requestID, rspInfo); this.OnEventHandler(CTPStockResponseType.QueryMaxOrderVolumeResponse, args); break; } #endregion #region 查询报单响应 case CTPStockResponseType.QueryOrderResponse: { CTPEventArgs <List <CZQThostFtdcOrderField> > args = CreateListEventArgs <CZQThostFtdcOrderField>(requestID, rspInfo); lock (this.OrderList) { this.OrderList.Clear(); this.OrderList.AddRange(args.Value); } //调用事件 OnEventHandler(CTPStockResponseType.QueryOrderResponse, args); break; } #endregion #region 查询成交单响应 case CTPStockResponseType.QueryTradeResponse: { CTPEventArgs <List <CZQThostFtdcTradeField> > args = CreateListEventArgs <CZQThostFtdcTradeField>(requestID, rspInfo); this.TradeList = args.Value; //调用事件 OnEventHandler(CTPStockResponseType.QueryTradeResponse, args); break; } #endregion #region 查询投资者持仓响应 case CTPStockResponseType.QueryInvestorPositionResponse: { CTPEventArgs <List <CZQThostFtdcInvestorPositionField> > args = CreateListEventArgs <CZQThostFtdcInvestorPositionField>(requestID, rspInfo); this.PositionList = args.Value; //调用事件 OnEventHandler(CTPStockResponseType.QueryInvestorPositionResponse, args); break; } #endregion #region 查询资金账户响应 case CTPStockResponseType.QueryTradingAccountResponse: { /// 查询资金账户响应 CTPEventArgs <CZQThostFtdcTradingAccountField> args = CreateEventArgs <CZQThostFtdcTradingAccountField>(requestID, rspInfo); this.tradingAccount = args.Value; this.OnEventHandler(CTPStockResponseType.QueryTradingAccountResponse, args); break; } #endregion #region 查询投资者响应 case CTPStockResponseType.QueryInvestorResponse: { CTPEventArgs <CZQThostFtdcInvestorField> args = CreateEventArgs <CZQThostFtdcInvestorField>(requestID, rspInfo); this.investor = args.Value; this.OnEventHandler(CTPStockResponseType.QueryInvestorResponse, args); break; } #endregion #region 请求查询交易编码响应 case CTPStockResponseType.QueryTradingCodeResponse: { CTPEventArgs <CZQThostFtdcTradingCodeField> args = CreateEventArgs <CZQThostFtdcTradingCodeField>(requestID, rspInfo); this.OnEventHandler(CTPStockResponseType.QueryTradingCodeResponse, args); break; } #endregion #region 查询手续费响应 case CTPStockResponseType.QueryInstrumentCommissionRateResponse: { CTPEventArgs <CZQThostFtdcInstrumentCommissionRateField> args = CreateEventArgs <CZQThostFtdcInstrumentCommissionRateField>(requestID, rspInfo); this.SetInstrumentRate(args.Value); //调用事件 OnEventHandler(CTPStockResponseType.QueryInstrumentCommissionRateResponse, args); break; } #endregion #region 查询交易所响应 case CTPStockResponseType.QueryExchangeResponse: { CTPEventArgs <CZQThostFtdcExchangeField> args = CreateEventArgs <CZQThostFtdcExchangeField>(requestID, rspInfo); //保存市场信息 //CTPExchange ctpExchange = new CTPExchange(); //ctpExchange.SetNativeValue(args.Value); //this.Exchanges.Add(args.Value.ExchangeID, ctpExchange); //调用事件 OnEventHandler(CTPStockResponseType.QueryExchangeResponse, args); break; } #endregion #region 查询合约响应 case CTPStockResponseType.QueryInstrumentResponse: { CTPEventArgs <List <CZQThostFtdcInstrumentField> > values = CreateListEventArgs <CZQThostFtdcInstrumentField>(requestID, rspInfo); foreach (var instrument in values.Value) { if (instrument.ProductClass == CTPStockProductClassType.EFP || instrument.ProductClass == CTPStockProductClassType.Futures || instrument.ProductClass == CTPStockProductClassType.Options) { continue; } CTPStockInstrument ctpInstrument = new CTPStockInstrument(); ctpInstrument.SetNativeValue(instrument); //加入到市场列表 //if (this.Exchanges.ContainsKey(ctpInstrument.ExchangeID)) //{ // this.Exchanges[instrument.ExchangeID].Instruments.Add(ctpInstrument); //} //if (this.SymbolProducts.ContainsKey(ctpInstrument.ProductID.ToUpper()) == false) //{ // this.SymbolProducts.Add(ctpInstrument.ProductID.ToUpper(), new CTPSymbolProduct(instrument)); //} //加入到合约表 if (this.InstrumentDictionary.ContainsKey(ctpInstrument.ID) == false) { this.InstrumentDictionary.Add(ctpInstrument.ID, ctpInstrument); } } //创建新的事件参数 List <CTPStockInstrument> list = new List <CTPStockInstrument>(this.InstrumentDictionary.Values); CTPEventArgs <List <CTPStockInstrument> > args = new CTPEventArgs <List <CTPStockInstrument> >(list); //调用事件 //OnEventHandler(CTPStockResponseType.QueryInstrumentResponse, args); OnEventHandler(CTPStockResponseType.QueryInstrumentResponse, values); break; } #endregion #region 查询行情响应 case CTPStockResponseType.QueryDepthMarketDataResponse: { CTPEventArgs <CZQThostFtdcDepthMarketDataField> args = CreateEventArgs <CZQThostFtdcDepthMarketDataField>(requestID, rspInfo); //调用事件 OnEventHandler(CTPStockResponseType.QueryDepthMarketDataResponse, args); break; } #endregion #region 查询投资者持仓明细响应 case CTPStockResponseType.QueryInvestorPositionDetailResponse: { CTPEventArgs <List <CZQThostFtdcInvestorPositionDetailField> > args = CreateListEventArgs <CZQThostFtdcInvestorPositionDetailField>(requestID, rspInfo); this.PositionDetailList = args.Value; //调用事件 OnEventHandler(CTPStockResponseType.QueryInvestorPositionDetailResponse, args); break; } #endregion #region 错误回报 case CTPStockResponseType.ErrorResponse: { this.OnEventHandler(CTPStockResponseType.ErrorResponse, new CTPEventArgs(rspInfo)); break; } #endregion #region 报单回报 case CTPStockResponseType.ReturnOrderResponse: { CTPEventArgs <CZQThostFtdcOrderField> args = CreateEventArgs <CZQThostFtdcOrderField>(pData, rspInfo); lock (this.orderList) { CTPStockOrderConvert.AppendOrReplaceOrder(this.orderList, args.Value); } if (this.filterRestart == true && this.isInitialized == false) { } else { //调用事件 OnEventHandler(CTPStockResponseType.ReturnOrderResponse, args); } break; } #endregion #region 成交回报 case CTPStockResponseType.ReturnTradeResponse: { CTPEventArgs <CZQThostFtdcTradeField> args = CreateEventArgs <CZQThostFtdcTradeField>(pData, rspInfo); //插入到列表中 CTPStockOrderConvert.AppendOrReplaceOrder(this.tradeList, args.Value); if (this.filterRestart == true && this.isInitialized == false) { } else { //调用事件 OnEventHandler(CTPStockResponseType.ReturnTradeResponse, args); } break; } #endregion #region 错单回报 case CTPStockResponseType.ErrorReturnOrderInsertResponse: { if (this.filterRestart == true && this.isInitialized == false) { } else { CTPEventArgs <CZQThostFtdcInputOrderField> args = CreateEventArgs <CZQThostFtdcInputOrderField>(pData, rspInfo); //调用事件 OnEventHandler(CTPStockResponseType.ErrorReturnOrderInsertResponse, args); } break; } #endregion #region 报单操作错误回报 case CTPStockResponseType.ErrorReturnOrderActionResponse: { if (this.filterRestart == true && this.isInitialized == false) { } else { CTPEventArgs <CZQThostFtdcOrderActionField> args = CreateEventArgs <CZQThostFtdcOrderActionField>(pData, rspInfo); //调用事件 OnEventHandler(CTPStockResponseType.ErrorReturnOrderActionResponse, args); } break; } #endregion #region 合约交易状态通知 case CTPStockResponseType.ReturnInstrumentStatusResponse: { CTPEventArgs <CZQThostFtdcInstrumentStatusField> args = CreateEventArgs <CZQThostFtdcInstrumentStatusField>(pData, rspInfo); CZQThostFtdcInstrumentStatusField instrumentStatus = args.Value; Trace.WriteLine(string.Format("{0}:{1}", instrumentStatus.ExchangeID, instrumentStatus.InstrumentStatus)); //交易所状态 if (this.exchangeStatus.ContainsKey(instrumentStatus.ExchangeID) == false) { this.exchangeStatus.Add(instrumentStatus.ExchangeID, instrumentStatus.InstrumentStatus); } //更新交易所状态 this.exchangeStatus[instrumentStatus.ExchangeID] = instrumentStatus.InstrumentStatus; this.tradingStatus = instrumentStatus.InstrumentStatus; //调用事件 OnEventHandler(CTPStockResponseType.ReturnInstrumentStatusResponse, args); break; } #endregion default: break; } }