//建立交易 private void Connect_TD() { lock (_lockTd) { if (_bWantTdConnect && (null == m_pTdApi || IntPtr.Zero == m_pTdApi)) { m_pTdApi = TraderApi.TD_CreateTdApi(); TraderApi.CTP_RegOnErrRtnOrderAction(m_pMsgQueue, _fnOnErrRtnOrderAction_Holder); TraderApi.CTP_RegOnErrRtnOrderInsert(m_pMsgQueue, _fnOnErrRtnOrderInsert_Holder); TraderApi.CTP_RegOnRspOrderAction(m_pMsgQueue, _fnOnRspOrderAction_Holder); TraderApi.CTP_RegOnRspOrderInsert(m_pMsgQueue, _fnOnRspOrderInsert_Holder); TraderApi.CTP_RegOnRspQryDepthMarketData(m_pMsgQueue, _fnOnRspQryDepthMarketData_Holder); TraderApi.CTP_RegOnRspQryInstrument(m_pMsgQueue, _fnOnRspQryInstrument_Holder); TraderApi.CTP_RegOnRspQryInstrumentCommissionRate(m_pMsgQueue, _fnOnRspQryInstrumentCommissionRate_Holder); TraderApi.CTP_RegOnRspQryInstrumentMarginRate(m_pMsgQueue, _fnOnRspQryInstrumentMarginRate_Holder); TraderApi.CTP_RegOnRspQryInvestorPosition(m_pMsgQueue, _fnOnRspQryInvestorPosition_Holder); TraderApi.CTP_RegOnRspQryTradingAccount(m_pMsgQueue, _fnOnRspQryTradingAccount_Holder); TraderApi.CTP_RegOnRtnInstrumentStatus(m_pMsgQueue, _fnOnRtnInstrumentStatus_Holder); TraderApi.CTP_RegOnRtnOrder(m_pMsgQueue, _fnOnRtnOrder_Holder); TraderApi.CTP_RegOnRtnTrade(m_pMsgQueue, _fnOnRtnTrade_Holder); TraderApi.TD_RegMsgQueue2TdApi(m_pTdApi, m_pMsgQueue); TraderApi.TD_Connect(m_pTdApi, _newTempPath, string.Join(";", server.Trading.ToArray()), server.BrokerID, account.InvestorId, account.Password, ResumeType, server.UserProductInfo, server.AuthCode); //向单例对象中注入操作用句柄 CTPAPI.GetInstance().__RegTdApi(m_pTdApi); } } }
private void OnRtnTrade(IntPtr pTraderApi, ref CThostFtdcTradeField pTrade) { tdlog.Info("时{0},合约{1},方向{2},开平{3},价{4},量{5},引用{6},成交编号{7}", pTrade.TradeTime, pTrade.InstrumentID, pTrade.Direction, pTrade.OffsetFlag, pTrade.Price, pTrade.Volume, pTrade.OrderRef, pTrade.TradeID); //找到自己发送的订单,标记成交 string strSysID = string.Format("{0}:{1}", pTrade.ExchangeID, pTrade.OrderSysID); string strKey; if (!orderMap.TryGetValue(strSysID, out strKey)) { return; } GenericOrderItem item; if (orderMap.TryGetValue(strKey, out item)) { MultiOrderLeg leg = item.GetLeg(CTPAPI.FromCTP(pTrade.Direction), pTrade.InstrumentID); SingleOrder order = leg.Order; #if CTP double Price = pTrade.Price; #elif CTPZQ double Price = Convert.ToDouble(pTrade.Price); #endif int Volume = pTrade.Volume; int LeavesQty = (int)order.LeavesQty - Volume; EmitFilled(order, Price, Volume, CommType.Absolute, 0); // 成交完成,清理数据 OnRtnTradeLastStatus(item, pTrade, strSysID, strKey); } }
private void OnRtnInstrumentStatus(IntPtr pTraderApi, ref CThostFtdcInstrumentStatusField pInstrumentStatus) { tdlog.Info("{0},{1},{2},{3}", pInstrumentStatus.ExchangeID, pInstrumentStatus.InstrumentID, pInstrumentStatus.InstrumentStatus, pInstrumentStatus.EnterReason); //通知单例 CTPAPI.GetInstance().FireOnRtnInstrumentStatus(pInstrumentStatus); }
public override void OnStrategyStop() { CTPAPI.GetInstance().OnRspQryInstrument -= new CTPAPI.RspQryInstrument(OnRspQryInstrument); CTPAPI.GetInstance().OnRspQryInstrumentMarginRate -= new CTPAPI.RspQryInstrumentMarginRate(OnRspQryInstrumentMarginRate); CTPAPI.GetInstance().OnRspQryInstrumentCommissionRate -= new CTPAPI.RspQryInstrumentCommissionRate(OnRspQryInstrumentCommissionRate); CTPAPI.GetInstance().OnRtnInstrumentStatus -= new CTPAPI.RtnInstrumentStatus(OnRtnInstrumentStatus); CTPAPI.GetInstance().OnRspQryDepthMarketData -= new CTPAPI.RspQryDepthMarketData(OnRspQryDepthMarketData); // 此方法已经过期,在插件3.8.2.0中开始废弃 //CTPAPI.GetInstance().OnRtnDepthMarketData -= new CTPAPI.RtnDepthMarketData(OnRtnDepthMarketData); }
public override void OnBar(Bar bar) { //以下四句只是演示,实盘中请保存查询出来的结果,并且一天只查一次 CTPAPI.GetInstance().ReqQryInstrument("IF1312"); // 一定得加上TThostFtdcHedgeFlagType CTPAPI.GetInstance().ReqQryInstrumentMarginRate("IF1312", TThostFtdcHedgeFlagType.Speculation); //目前模拟平台目前查询没有返回,实盘时返回的是产品的手续费,如查"IF1312",返回的是"IF" CTPAPI.GetInstance().ReqQryInstrumentCommissionRate("IF1312"); //通过交易接口查询,主要用来取涨跌停或没有直接订阅的行情 CTPAPI.GetInstance().ReqQryDepthMarketData("IF1309"); }
private void Send(SPOrderItem item) { if (item == null) { return; } SingleOrder order = item.Leg[0].Order; SingleOrder order2 = item.Leg[1].Order; string symbol = item.GetSymbol(); double price = order.Price - order2.Price; int qty = (int)order.OrderQty; // 是否要做价格调整? byte[] bytes = { (byte)CTPAPI.ToCTP(item.Leg[0].OpenClose), (byte)CTPAPI.ToCTP(item.Leg[1].OpenClose) }; string szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length); byte[] bytes2 = { (byte)HedgeFlagType, (byte)HedgeFlagType }; string szCombHedgeFlag = System.Text.Encoding.Default.GetString(bytes2, 0, bytes2.Length); TThostFtdcDirectionType Direction = order.Side == Side.Buy ? TThostFtdcDirectionType.Buy : TThostFtdcDirectionType.Sell; TThostFtdcOrderPriceTypeType OrderPriceType = TThostFtdcOrderPriceTypeType.LimitPrice; TThostFtdcTimeConditionType TimeCondition = TThostFtdcTimeConditionType.GFD; TThostFtdcContingentConditionType ContingentCondition = TThostFtdcContingentConditionType.Immediately; TThostFtdcVolumeConditionType VolumeCondition = TThostFtdcVolumeConditionType.AV; int nRet = 0; #if CTP nRet = TraderApi.TD_SendOrder(m_pTdApi, -1, symbol, Direction, szCombOffsetFlag, szCombHedgeFlag, qty, price, OrderPriceType, TimeCondition, ContingentCondition, 0, VolumeCondition); #endif if (nRet > 0) { orderMap.CreateNewOrder(string.Format("{0}:{1}:{2}", _RspUserLogin.FrontID, _RspUserLogin.SessionID, nRet), item); } }
public override void OnStrategyStart() { CTPAPI.GetInstance().OnRspQryInstrument += new CTPAPI.RspQryInstrument(OnRspQryInstrument); CTPAPI.GetInstance().OnRspQryInstrumentMarginRate += new CTPAPI.RspQryInstrumentMarginRate(OnRspQryInstrumentMarginRate); CTPAPI.GetInstance().OnRspQryInstrumentCommissionRate += new CTPAPI.RspQryInstrumentCommissionRate(OnRspQryInstrumentCommissionRate); // 交易所状态 CTPAPI.GetInstance().OnRtnInstrumentStatus += new CTPAPI.RtnInstrumentStatus(OnRtnInstrumentStatus); CTPAPI.GetInstance().OnRspQryTradingAccount += new CTPAPI.RspQryTradingAccount(OnRspQryTradingAccount); CTPAPI.GetInstance().OnRspReqQryInvestorPosition += new CTPAPI.RspReqQryInvestorPosition(OnRspReqQryInvestorPosition); // 此方法已经过期,在插件3.8.2.0中开始废弃 //CTPAPI.GetInstance().OnRtnDepthMarketData += new CTPAPI.RtnDepthMarketData(OnRtnDepthMarketData); }
private void Disconnect_MD() { lock (_lockMd) { if (null != m_pMdApi && IntPtr.Zero != m_pMdApi) { MdApi.MD_RegMsgQueue2MdApi(m_pMdApi, IntPtr.Zero); MdApi.MD_ReleaseMdApi(m_pMdApi); m_pMdApi = IntPtr.Zero; CTPAPI.GetInstance().__RegMdApi(m_pMdApi); } _bMdConnected = false; } }
private void Disconnect_TD() { lock (_lockTd) { if (null != m_pTdApi && IntPtr.Zero != m_pTdApi) { TraderApi.TD_RegMsgQueue2TdApi(m_pTdApi, IntPtr.Zero); TraderApi.TD_ReleaseTdApi(m_pTdApi); m_pTdApi = IntPtr.Zero; CTPAPI.GetInstance().__RegTdApi(m_pTdApi); } _bTdConnected = false; } }
private void OnRspQryInstrumentMarginRate(IntPtr pTraderApi, ref CThostFtdcInstrumentMarginRateField pInstrumentMarginRate, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast) { if (0 == pRspInfo.ErrorID) { _dictMarginRate[pInstrumentMarginRate.InstrumentID] = pInstrumentMarginRate; tdlog.Info("已经接收保证金率 {0}", pInstrumentMarginRate.InstrumentID); //通知单例 CTPAPI.GetInstance().FireOnRspQryInstrumentMarginRate(pInstrumentMarginRate); } else { tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryInstrumentMarginRate:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg); EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryInstrumentMarginRate:" + pRspInfo.ErrorMsg); } }
private void EmitCancelReject(GenericOrderItem item, int error_id, string message) { TextResponse r = new TextResponse() { Error = CTPAPI.FromCTP(error_id), ErrorID = error_id, ErrorMsg = message, }; foreach (var leg in item.GetLegs()) { r.OpenClose = leg.OpenClose; leg.Order.Text = r.ToString(); EmitCancelReject(leg.Order, leg.Order.OrdStatus, r.ToString()); } }
private void OnRspQryInvestorPosition(IntPtr pTraderApi, ref CThostFtdcInvestorPositionField pInvestorPosition, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast) { if (0 == pRspInfo.ErrorID) { string key = GetPositionKey(pInvestorPosition); _dictPositions[key] = pInvestorPosition; CTPAPI.GetInstance().FireOnRspReqQryInvestorPosition(pInvestorPosition); timerPonstion.Enabled = false; timerPonstion.Enabled = true; } else { tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryInvestorPosition:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg); EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryInvestorPosition:" + pRspInfo.ErrorMsg); } }
private void OnRtnInstrumentStatus(IntPtr pTraderApi, ref CThostFtdcInstrumentStatusField pInstrumentStatus) { tdlog.Info("{0},{1},{2},{3},{4},{5},{6},{7}", pInstrumentStatus.ExchangeID, pInstrumentStatus.InstrumentID, pInstrumentStatus.InstrumentStatus, pInstrumentStatus.EnterReason, pInstrumentStatus.EnterTime, pInstrumentStatus.TradingSegmentSN, pInstrumentStatus.ExchangeInstID, pInstrumentStatus.SettlementGroupID); //通知单例 CTPAPI.GetInstance().FireOnRtnInstrumentStatus(pInstrumentStatus); // 到IF的交割日,是否会收到两个有关IF的记录?如果在此进行清理是否会有问题? // 只会收到一条 // 遍历是否过期 if (pInstrumentStatus.InstrumentStatus == TThostFtdcInstrumentStatusType.Closed) { Dictionary <GenericOrderItem, CThostFtdcOrderField> tmp = new Dictionary <GenericOrderItem, CThostFtdcOrderField>(); foreach (var pair in orderMap.OrderItem_OrderField) { if (pair.Value.ExchangeID == pInstrumentStatus.ExchangeID) { int cnt = pair.Key.GetLegNum(); foreach (var pair2 in orderMap.Order_OrderItem) { // 得找到OpenQuant层的单子 if (pair.Key == pair2.Value) { --cnt; EmitExpired(pair2.Key); if (cnt <= 0) { break; } } } tmp[pair.Key] = pair.Value; } } foreach (var pair in tmp) { OnLastStatus(pair.Key, pair.Value.OrderSysID, pair.Value.OrderRef); } tmp.Clear(); } }
//建立行情 private void Connect_MD() { lock (_lockMd) { if (_bWantMdConnect && (null == m_pMdApi || IntPtr.Zero == m_pMdApi)) { m_pMdApi = MdApi.MD_CreateMdApi(); MdApi.CTP_RegOnRtnDepthMarketData(m_pMsgQueue, _fnOnRtnDepthMarketData_Holder); MdApi.MD_RegMsgQueue2MdApi(m_pMdApi, m_pMsgQueue); MdApi.MD_Connect(m_pMdApi, _newTempPath, string.Join(";", server.MarketData.ToArray()), server.BrokerID, account.InvestorId, account.Password); //向单例对象中注入操作用句柄 CTPAPI.GetInstance().__RegMdApi(m_pMdApi); } } }
private void Send(QuoteOrderItem item) { if (item == null) { return; } SingleOrder AskOrder = item.Sell.Order; SingleOrder BidOrder = item.Buy.Order; string symbol = item.Buy.Order.Symbol; double AskPrice = AskOrder.Price; double BidPrice = BidOrder.Price; int AskVolume = (int)AskOrder.OrderQty; int BidVolume = (int)BidOrder.OrderQty; TThostFtdcOffsetFlagType AskOffsetFlag = CTPAPI.ToCTP(item.Sell.OpenClose); TThostFtdcOffsetFlagType BidOffsetFlag = CTPAPI.ToCTP(item.Buy.OpenClose); TThostFtdcHedgeFlagType AskHedgeFlag = HedgeFlagType; TThostFtdcHedgeFlagType BidHedgeFlag = HedgeFlagType; int nRet = 0; #if CTP nRet = TraderApi.TD_SendQuote(m_pTdApi, -1, symbol, AskPrice, BidPrice, AskVolume, BidVolume, AskOffsetFlag, BidOffsetFlag, AskHedgeFlag, BidHedgeFlag); #endif if (nRet > 0) { orderMap.CreateNewOrder(string.Format("{0}:{1}:{2}", _RspUserLogin.FrontID, _RspUserLogin.SessionID, nRet), item); } }
private void OnRspQryTradingAccount(IntPtr pTraderApi, ref CThostFtdcTradingAccountField pTradingAccount, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLastt) { if (0 == pRspInfo.ErrorID) { m_TradingAccount = pTradingAccount; //有资金信息过来了,重新计时 timerAccount.Enabled = false; timerAccount.Enabled = true; //通知单例,还是使用GetBrokerInfo来取呢? CTPAPI.GetInstance().__RegTradingAccount(m_TradingAccount); CTPAPI.GetInstance().FireOnRspQryTradingAccount(pTradingAccount); } else { tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryTradingAccount:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg); EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryTradingAccount:" + pRspInfo.ErrorMsg); } }
public void OnRspQryDepthMarketData(IntPtr pTraderApi, ref CThostFtdcDepthMarketDataField pDepthMarketData, ref CThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast) { if (0 == pRspInfo.ErrorID) { CThostFtdcDepthMarketDataField DepthMarket; if (!_dictDepthMarketData.TryGetValue(pDepthMarketData.InstrumentID, out DepthMarket)) { //没找到此元素,保存一下 _dictDepthMarketData[pDepthMarketData.InstrumentID] = pDepthMarketData; } tdlog.Info("已经接收查询深度行情 {0}", pDepthMarketData.InstrumentID); //通知单例 CTPAPI.GetInstance().FireOnRspQryDepthMarketData(pDepthMarketData); } else { tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryDepthMarketData:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg); EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryDepthMarketData:" + pRspInfo.ErrorMsg); } }
private void _Disconnect() { timerConnect.Enabled = false; timerDisconnect.Enabled = false; timerAccount.Enabled = false; timerPonstion.Enabled = false; CTPAPI.GetInstance().__RegInstrumentDictionary(null); CTPAPI.GetInstance().__RegInstrumentCommissionRateDictionary(null); CTPAPI.GetInstance().__RegInstrumentMarginRateDictionary(null); CTPAPI.GetInstance().__RegDepthMarketDataDictionary(null); Disconnect_MD(); Disconnect_TD(); Disconnect_MsgQueue(); Clear(); ChangeStatus(ProviderStatus.Disconnected); isConnected = false; EmitDisconnectedEvent(); }
private void Send(CommonOrderItem item) { if (item == null) { return; } SingleOrder order = item.Leg.Order; string apiSymbol; string apiExchange; double apiTickSize; string altSymbol; #if CTP GetInstrumentInfoForCTP(order.Instrument, out apiSymbol, out apiExchange, out apiTickSize); altSymbol = apiSymbol; #elif CTPZQ GetInstrumentInfoForCTPZQ(order.Instrument, out apiSymbol, out apiExchange, out apiTickSize, out altSymbol); #endif double price = order.Price; int qty = (int)order.OrderQty; //市价修正,如果不连接行情,此修正不执行,得策略层处理 CThostFtdcDepthMarketDataField DepthMarket; //如果取出来了,并且为有效的,涨跌停价将不为0 _dictDepthMarketData.TryGetValue(altSymbol, out DepthMarket); //市价单模拟 if (OrdType.Market == order.OrdType) { //按买卖调整价格 if (order.Side == Side.Buy) { price = DepthMarket.LastPrice + LastPricePlusNTicks * apiTickSize; } else { price = DepthMarket.LastPrice - LastPricePlusNTicks * apiTickSize; } } price = FixPrice(price, order.Side, apiTickSize, DepthMarket.LowerLimitPrice, DepthMarket.UpperLimitPrice); // 是否要做价格调整? byte[] bytes = { (byte)CTPAPI.ToCTP(item.Leg.OpenClose) }; string szCombOffsetFlag = System.Text.Encoding.Default.GetString(bytes, 0, bytes.Length); byte[] bytes2 = { (byte)HedgeFlagType }; string szCombHedgeFlag = System.Text.Encoding.Default.GetString(bytes2, 0, bytes2.Length); TThostFtdcDirectionType Direction = order.Side == Side.Buy ? TThostFtdcDirectionType.Buy : TThostFtdcDirectionType.Sell; TThostFtdcOrderPriceTypeType OrderPriceType = TThostFtdcOrderPriceTypeType.LimitPrice; TThostFtdcTimeConditionType TimeCondition = TThostFtdcTimeConditionType.GFD; TThostFtdcContingentConditionType ContingentCondition = TThostFtdcContingentConditionType.Immediately; TThostFtdcVolumeConditionType VolumeCondition = TThostFtdcVolumeConditionType.AV; #if CTP bool bSupportMarketOrder = SupportMarketOrder.Contains(apiExchange); #elif CTPZQ bool bSupportMarketOrder = true; #endif switch (order.TimeInForce) { case TimeInForce.IOC: TimeCondition = TThostFtdcTimeConditionType.IOC; VolumeCondition = TThostFtdcVolumeConditionType.AV; break; case TimeInForce.FOK: TimeCondition = TThostFtdcTimeConditionType.IOC; VolumeCondition = TThostFtdcVolumeConditionType.CV; break; default: break; } int nRet = 0; switch (order.OrdType) { case OrdType.Limit: break; case OrdType.Market: if (SwitchMakertOrderToLimitOrder || !bSupportMarketOrder) { } else { price = 0; OrderPriceType = TThostFtdcOrderPriceTypeType.AnyPrice; TimeCondition = TThostFtdcTimeConditionType.IOC; } break; default: tdlog.Warn("没有实现{0}", order.OrdType); return; } #if CTP nRet = TraderApi.TD_SendOrder(m_pTdApi, apiSymbol, Direction, szCombOffsetFlag, szCombHedgeFlag, qty, price, OrderPriceType, TimeCondition, ContingentCondition, order.StopPx, VolumeCondition); #elif CTPZQ nRet = TraderApi.TD_SendOrder(m_pTdApi, apiSymbol, apiExchange, Direction, szCombOffsetFlag, szCombHedgeFlag, qty, string.Format("{0}", price), OrderPriceType, TimeCondition, ContingentCondition, order.StopPx, VolumeCondition); #endif if (nRet > 0) { orderMap.CreateNewOrder(string.Format("{0}:{1}:{2}", _RspUserLogin.FrontID, _RspUserLogin.SessionID, nRet), item); } }
private void _Connect() { // 限制低版本的OpenQuant不能使用,其它产品不做限制 switch (Framework.Installation.MainProduct) { case "OpenQuant": if (Assembly.GetEntryAssembly().GetName().Version < new Version(3, 9, 3)) { MessageBox.Show("您的OpenQuant版本过低,请装最新版"); return; } break; case "QuantRouter": break; case "QuantBase": break; case "QuantTrader": break; } CTPAPI.GetInstance().__RegInstrumentDictionary(_dictInstruments); CTPAPI.GetInstance().__RegInstrumentCommissionRateDictionary(_dictCommissionRate); CTPAPI.GetInstance().__RegDepthMarketDataDictionary(_dictDepthMarketData); CTPAPI.GetInstance().__RegInvestorPositionDictionary(_dictPositions); #if CTP CTPAPI.GetInstance().__RegInstrumentMarginRateDictionary(_dictMarginRate); #endif server = null; account = null; bool bCheckOk = false; do { if (0 == serversList.Count) { MessageBox.Show("您还没有设置 服务器 信息,目前只选择第一条进行连接"); break; } if (0 == accountsList.Count) { MessageBox.Show("您还没有设置 账号 信息,目前只选择第一条进行连接"); break; } server = serversList[0]; account = accountsList[0]; if (string.IsNullOrEmpty(server.BrokerID)) { MessageBox.Show("BrokerID不能为空"); break; } if (_bWantTdConnect && 0 == server.Trading.Count()) { MessageBox.Show("交易服务器地址不全"); break; } if (_bWantMdConnect && 0 == server.MarketData.Count()) { MessageBox.Show("行情服务器信息不全"); break; } if (string.IsNullOrEmpty(account.InvestorId) || string.IsNullOrEmpty(account.Password)) { MessageBox.Show("账号信息不全"); break; } bCheckOk = true; } while (false); if (false == bCheckOk) { ChangeStatus(ProviderStatus.Disconnected); isConnected = false; return; } //新建目录 _newTempPath = string.Format("{1}{0}{2}{0}{3}{0}{4}", Path.DirectorySeparatorChar, ApiTempPath, this.Name, server.BrokerID, account.InvestorId); Directory.CreateDirectory(_newTempPath); ChangeStatus(ProviderStatus.Connecting); //如果前面一次连接一直连不上,新改地址后也会没响应,所以先删除 Disconnect_MD(); Disconnect_TD(); if (_bWantMdConnect || _bWantTdConnect) { timerDisconnect.Enabled = true; Connect_MsgQueue(); } if (_bWantMdConnect) { Connect_MD(); } if (_bWantTdConnect) { Connect_TD(); } }
private void OnRtnForQuoteRsp(IntPtr pMdUserApi, ref CThostFtdcForQuoteRspField pForQuoteRsp) { Console.WriteLine("OnRtnForQuoteRsp"); // 询价请求 CTPAPI.GetInstance().FireOnRtnForQuoteRsp(pForQuoteRsp); }
private void _Connect() { CTPAPI.GetInstance().__RegInstrumentDictionary(_dictInstruments); CTPAPI.GetInstance().__RegInstrumentCommissionRateDictionary(_dictCommissionRate); CTPAPI.GetInstance().__RegInstrumentMarginRateDictionary(_dictMarginRate); CTPAPI.GetInstance().__RegDepthMarketDataDictionary(_dictDepthMarketData); server = null; account = null; bool bCheckOk = false; do { if (0 == serversList.Count) { MessageBox.Show("您还没有设置 服务器 信息,目前只选择第一条进行连接"); break; } if (0 == accountsList.Count) { MessageBox.Show("您还没有设置 账号 信息,目前只选择第一条进行连接"); break; } server = serversList[0]; account = accountsList[0]; if (string.IsNullOrEmpty(server.BrokerID)) { MessageBox.Show("BrokerID不能为空"); break; } if (_bWantTdConnect && 0 == server.Trading.Count()) { MessageBox.Show("交易服务器地址不全"); break; } if (_bWantMdConnect && 0 == server.MarketData.Count()) { MessageBox.Show("行情服务器信息不全"); break; } if (string.IsNullOrEmpty(account.InvestorId) || string.IsNullOrEmpty(account.Password)) { MessageBox.Show("账号信息不全"); break; } bCheckOk = true; } while (false); if (false == bCheckOk) { ChangeStatus(ProviderStatus.Disconnected); isConnected = false; return; } //新建目录 _newTempPath = ApiTempPath + Path.DirectorySeparatorChar + server.BrokerID + Path.DirectorySeparatorChar + account.InvestorId; Directory.CreateDirectory(_newTempPath); ChangeStatus(ProviderStatus.Connecting); //如果前面一次连接一直连不上,新改地址后也会没响应,所以先删除 Disconnect_MD(); Disconnect_TD(); if (_bWantMdConnect || _bWantTdConnect) { timerDisconnect.Enabled = true; Connect_MsgQueue(); } if (_bWantMdConnect) { Connect_MD(); } if (_bWantTdConnect) { Connect_TD(); } }
private void OnRtnDepthMarketData(IntPtr pApi, ref CThostFtdcDepthMarketDataField pDepthMarketData) { DataRecord record; if (!_dictAltSymbol2Instrument.TryGetValue(pDepthMarketData.InstrumentID, out record)) { mdlog.Warn("合约{0}不在订阅列表中却收到了数据", pDepthMarketData.InstrumentID); return; } Instrument instrument = record.Instrument; CThostFtdcDepthMarketDataField DepthMarket; _dictDepthMarketData.TryGetValue(pDepthMarketData.InstrumentID, out DepthMarket); //将更新字典的功能提前,因为如果一开始就OnTrade中下单,涨跌停没有更新 _dictDepthMarketData[pDepthMarketData.InstrumentID] = pDepthMarketData; if (TimeMode.LocalTime == _TimeMode) { //为了生成正确的Bar,使用本地时间 _dateTime = Clock.Now; } else { //直接按HH:mm:ss来解析,测试过这种方法目前是效率比较高的方法 try { // 只有使用交易所行情时才需要处理跨天的问题 ChangeTradingDay(pDepthMarketData.TradingDay); int HH = int.Parse(pDepthMarketData.UpdateTime.Substring(0, 2)); int mm = int.Parse(pDepthMarketData.UpdateTime.Substring(3, 2)); int ss = int.Parse(pDepthMarketData.UpdateTime.Substring(6, 2)); _dateTime = new DateTime(_yyyy, _MM, _dd, HH, mm, ss, pDepthMarketData.UpdateMillisec); } catch (Exception) { _dateTime = Clock.Now; } } if (record.TradeRequested) { //通过测试,发现IB的Trade与Quote在行情过来时数量是不同的,在这也做到不同 if (DepthMarket.LastPrice == pDepthMarketData.LastPrice && DepthMarket.Volume == pDepthMarketData.Volume) { } else { //行情过来时是今天累计成交量,得转换成每个tick中成交量之差 int volume = pDepthMarketData.Volume - DepthMarket.Volume; if (0 == DepthMarket.Volume) { //没有接收到最开始的一条,所以这计算每个Bar的数据时肯定超大,强行设置为0 volume = 0; } else if (volume < 0) { //如果隔夜运行,会出现今早成交量0-昨收盘成交量,出现负数,所以当发现为负时要修改 volume = pDepthMarketData.Volume; } Trade trade = new Trade(_dateTime, pDepthMarketData.LastPrice == double.MaxValue ? 0 : pDepthMarketData.LastPrice, volume); EmitNewTradeEvent(instrument, trade); } } if (record.QuoteRequested) { //if ( //DepthMarket.BidVolume1 == pDepthMarketData.BidVolume1 //&& DepthMarket.AskVolume1 == pDepthMarketData.AskVolume1 //&& DepthMarket.BidPrice1 == pDepthMarketData.BidPrice1 //&& DepthMarket.AskPrice1 == pDepthMarketData.AskPrice1 //) //{ } //else { Quote quote = new Quote(_dateTime, pDepthMarketData.BidPrice1 == double.MaxValue ? 0 : pDepthMarketData.BidPrice1, pDepthMarketData.BidVolume1, pDepthMarketData.AskPrice1 == double.MaxValue ? 0 : pDepthMarketData.AskPrice1, pDepthMarketData.AskVolume1 ); EmitNewQuoteEvent(instrument, quote); } } if (record.MarketDepthRequested) { EmitNewMarketDepth(instrument, _dateTime, 0, MDSide.Ask, pDepthMarketData.AskPrice1, pDepthMarketData.AskVolume1); EmitNewMarketDepth(instrument, _dateTime, 0, MDSide.Bid, pDepthMarketData.BidPrice1, pDepthMarketData.BidVolume1); //EmitNewMarketDepth(instrument, _dateTime, 1, MDSide.Ask, pDepthMarketData.AskPrice2, pDepthMarketData.AskVolume2); //EmitNewMarketDepth(instrument, _dateTime, 1, MDSide.Bid, pDepthMarketData.BidPrice2, pDepthMarketData.BidVolume2); //EmitNewMarketDepth(instrument, _dateTime, 2, MDSide.Ask, pDepthMarketData.AskPrice3, pDepthMarketData.AskVolume3); //EmitNewMarketDepth(instrument, _dateTime, 2, MDSide.Bid, pDepthMarketData.BidPrice3, pDepthMarketData.BidVolume3); //EmitNewMarketDepth(instrument, _dateTime, 3, MDSide.Ask, pDepthMarketData.AskPrice4, pDepthMarketData.AskVolume4); //EmitNewMarketDepth(instrument, _dateTime, 3, MDSide.Bid, pDepthMarketData.BidPrice4, pDepthMarketData.BidVolume4); //EmitNewMarketDepth(instrument, _dateTime, 4, MDSide.Ask, pDepthMarketData.AskPrice5, pDepthMarketData.AskVolume5); //EmitNewMarketDepth(instrument, _dateTime, 4, MDSide.Bid, pDepthMarketData.BidPrice5, pDepthMarketData.BidVolume5); } // 价差生成功能 do { if (null == CTPAPI.GetInstance().SpreadMarketData) { break; } ISpreadMarketData SpreadMarketData = CTPAPI.GetInstance().SpreadMarketData; var ticks = SpreadMarketData.CalculateSpread(pDepthMarketData); if (null == ticks) { break; } foreach (var tick in ticks) { Instrument inst = InstrumentManager.Instruments[tick.Symbol]; if (null == inst) { continue; } if (!double.IsNaN(tick.Price)) { Trade trade = new Trade(_dateTime, tick.Price, tick.Size); trade.ProviderId = tick.ProviderId; EmitNewTradeEvent(inst, trade); } if (!double.IsNaN(tick.Ask) && !double.IsNaN(tick.Bid)) { Quote quote = new Quote(_dateTime, tick.Bid, tick.BidSize, tick.Ask, tick.AskSize); quote.ProviderId = tick.ProviderId; EmitNewQuoteEvent(inst, quote); } } } while (false); // 直接回报CTP的行情信息 if (EmitOnRtnDepthMarketData) { CTPAPI.GetInstance().FireOnRtnDepthMarketData(pDepthMarketData); } }