//建立交易
        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);
                }
            }
        }
Exemplo n.º 2
0
        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;
            }
        }
Exemplo n.º 5
0
        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();
            }
        }