//建立交易 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); //向单例对象中注入操作用句柄 CTPZQAPI.GetInstance().__RegTdApi(m_pTdApi); } } }
private void OnRtnInstrumentStatus(IntPtr pTraderApi, ref CZQThostFtdcInstrumentStatusField pInstrumentStatus) { tdlog.Info("{0},{1},{2},{3}", pInstrumentStatus.ExchangeID, pInstrumentStatus.InstrumentID, pInstrumentStatus.InstrumentStatus, pInstrumentStatus.EnterReason); //通知单例 CTPZQAPI.GetInstance().FireOnRtnInstrumentStatus(pInstrumentStatus); }
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; CTPZQAPI.GetInstance().__RegTdApi(m_pTdApi); } _bTdConnected = false; } }
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; CTPZQAPI.GetInstance().__RegTdApi(m_pMdApi); } _bMdConnected = false; } }
private void OnRspQryInstrumentCommissionRate(IntPtr pTraderApi, ref CZQThostFtdcInstrumentCommissionRateField pInstrumentCommissionRate, ref CZQThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast) { if (0 == pRspInfo.ErrorID) { _dictCommissionRate[pInstrumentCommissionRate.InstrumentID] = pInstrumentCommissionRate; tdlog.Info("已经接收手续费率 {0}", pInstrumentCommissionRate.InstrumentID); //通知单例 CTPZQAPI.GetInstance().FireOnRspQryInstrumentCommissionRate(pInstrumentCommissionRate); } else { tdlog.Error("nRequestID:{0},ErrorID:{1},OnRspQryInstrumentCommissionRate:{2}", nRequestID, pRspInfo.ErrorID, pRspInfo.ErrorMsg); EmitError(nRequestID, pRspInfo.ErrorID, "OnRspQryInstrumentCommissionRate:" + pRspInfo.ErrorMsg); } }
//建立行情 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); //向单例对象中注入操作用句柄 CTPZQAPI.GetInstance().__RegMdApi(m_pMdApi); } } }
private void _Disconnect() { timerConnect.Enabled = false; timerDisconnect.Enabled = false; timerAccount.Enabled = false; timerPonstion.Enabled = false; CTPZQAPI.GetInstance().__RegInstrumentDictionary(null); CTPZQAPI.GetInstance().__RegInstrumentCommissionRateDictionary(null); //CTPZQAPI.GetInstance().__RegInstrumentMarginRateDictionary(null); CTPZQAPI.GetInstance().__RegDepthMarketDataDictionary(null); Disconnect_MD(); Disconnect_TD(); Disconnect_MsgQueue(); Clear(); ChangeStatus(ProviderStatus.Disconnected); isConnected = false; EmitDisconnectedEvent(); }
public void OnRspQryDepthMarketData(IntPtr pTraderApi, ref CZQThostFtdcDepthMarketDataField pDepthMarketData, ref CZQThostFtdcRspInfoField pRspInfo, int nRequestID, bool bIsLast) { if (0 == pRspInfo.ErrorID) { CZQThostFtdcDepthMarketDataField DepthMarket; string symbol = GetYahooSymbol(pDepthMarketData.InstrumentID, pDepthMarketData.ExchangeID); if (!_dictDepthMarketData.TryGetValue(symbol, out DepthMarket)) { //没找到此元素,保存一下 _dictDepthMarketData[symbol] = pDepthMarketData; } tdlog.Info("已经接收查询深度行情 {0}", symbol); //通知单例 CTPZQAPI.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 OnRtnDepthMarketData(IntPtr pApi, ref CZQThostFtdcDepthMarketDataField pDepthMarketData) { string symbol = GetYahooSymbol(pDepthMarketData.InstrumentID, pDepthMarketData.ExchangeID); DataRecord record; if (!_dictAltSymbol2Instrument.TryGetValue(symbol, out record)) { mdlog.Warn("合约{0}不在订阅列表中却收到了数据", symbol); return; } Instrument instrument = record.Instrument; CZQThostFtdcDepthMarketDataField DepthMarket; _dictDepthMarketData.TryGetValue(symbol, out DepthMarket); //将更新字典的功能提前,因为如果一开始就OnTrade中下单,涨跌停没有更新 _dictDepthMarketData[symbol] = pDepthMarketData; if (TimeMode.LocalTime == _TimeMode) { //为了生成正确的Bar,使用本地时间 _dateTime = Clock.Now; } else { //直接按HH:mm:ss来解析,测试过这种方法目前是效率比较高的方法 try { // 只有使用交易所行情时才需要处理跨天的问题 ChangeActionDay(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; } // 使用新的类,保存更多信息 CTPZQTrade trade = new CTPZQTrade(_dateTime, pDepthMarketData.LastPrice == double.MaxValue ? 0 : pDepthMarketData.LastPrice, volume); // 记录深度数据 trade.DepthMarketData = pDepthMarketData; EmitNewTradeEvent(instrument, trade); } } if (record.QuoteRequested) { //if ( //DepthMarket.BidVolume1 == pDepthMarketData.BidVolume1 //&& DepthMarket.AskVolume1 == pDepthMarketData.AskVolume1 //&& DepthMarket.BidPrice1 == pDepthMarketData.BidPrice1 //&& DepthMarket.AskPrice1 == pDepthMarketData.AskPrice1 //) //{ } //else { CTPZQQuote quote = new CTPZQQuote(_dateTime, pDepthMarketData.BidPrice1 == double.MaxValue ? 0 : pDepthMarketData.BidPrice1, pDepthMarketData.BidVolume1, pDepthMarketData.AskPrice1 == double.MaxValue ? 0 : pDepthMarketData.AskPrice1, pDepthMarketData.AskVolume1 ); quote.DepthMarketData = pDepthMarketData; 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); } // 直接回报CTP的行情信息 if (EmitOnRtnDepthMarketData) { CTPZQAPI.GetInstance().FireOnRtnDepthMarketData(pDepthMarketData); } }
private void _Connect() { CTPZQAPI.GetInstance().__RegInstrumentDictionary(_dictInstruments); CTPZQAPI.GetInstance().__RegInstrumentCommissionRateDictionary(_dictCommissionRate); //CTPZQAPI.GetInstance().__RegInstrumentMarginRateDictionary(_dictMarginRate); CTPZQAPI.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(); } }