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);
            }
        }
示例#2
0
        private void OnRtnDepthMarketData(IntPtr pApi, ref CThostFtdcDepthMarketDataField pDepthMarketData)
        {
            CThostFtdcDepthMarketDataField DepthMarket;
            if (_dictDepthMarketData.TryGetValue(pDepthMarketData.InstrumentID, out DepthMarket))
            {
                if (TimeMode.LocalTime == _TimeMode)
                {
                    //为了生成正确的Bar,使用本地时间
                    _dateTime = Clock.Now;
                }
                else
                {
                    //直接按HH:mm:ss来解析,测试过这种方法目前是效率比较高的方法
                    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);
                }

                Instrument instrument = _dictAltSymbol2Instrument[pDepthMarketData.InstrumentID];

                //通过测试,发现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;
                    }

                    Trade trade = new Trade(_dateTime,
                        pDepthMarketData.LastPrice == double.MaxValue ? 0 : pDepthMarketData.LastPrice,
                        volume);

                    if (null != marketDataFilter)
                    {
            /*                        Trade t = marketDataFilter.FilterTrade(trade, instrument.Symbol);
                        if (null != t)
                        {
                            EmitNewTradeEvent(instrument, t);
                        }
            */                    }
                    else
                    {
                        EmitNewTradeEvent(instrument, trade);
                    }
                }

                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
                    );

                    if (null != marketDataFilter)
                    {
            /*                        Quote q = marketDataFilter.FilterQuote(quote, instrument.Symbol);
                        if (null != q)
                        {
                            EmitNewQuoteEvent(instrument, q);
                        }
            */                    }
                    else
                    {
                        EmitNewQuoteEvent(instrument, quote);
                    }
                }

                _dictDepthMarketData[pDepthMarketData.InstrumentID] = pDepthMarketData;
            }
        }
 private void Dispatcher_HistoricalData(object sender, HistoricalDataEventArgs args)
 {
   HistoricalData data = args.Data;
   ImportTaskViewItem importTaskViewItem;
   if (!this.taskItems.TryGetValue(data.RequestId, out importTaskViewItem))
     return;
   foreach (SmartQuant.DataObject dataObject in data.Objects)
   {
     if (dataObject is Quote)
     {
       Quote quote1 = (Quote) dataObject;
       Quote quote2;
       lock (this.lastQuotes)
       {
         if (!this.lastQuotes.TryGetValue(data.RequestId, out quote2))
         {
           quote2 = new Quote(new Bid(), new Ask());
           this.lastQuotes.Add(data.RequestId, quote2);
         }
       }
       if (quote1.Bid.Price != quote2.Bid.Price || quote1.Bid.Size != quote2.Bid.Size)
         this.framework.DataManager.Save(importTaskViewItem.Task.Instrument, (SmartQuant.DataObject) new Bid(quote1.Bid), SaveMode.Add);
       if (quote1.Ask.Price != quote2.Ask.Price || quote1.Ask.Size != quote2.Ask.Size)
         this.framework.DataManager.Save(importTaskViewItem.Task.Instrument, (SmartQuant.DataObject) new Ask(quote1.Ask), SaveMode.Add);
       quote2.Bid.Price = quote1.Bid.Price;
       quote2.Bid.Size = quote1.Bid.Size;
       quote2.Ask.Price = quote1.Ask.Price;
       quote2.Ask.Size = quote1.Ask.Size;
     }
     else
       this.framework.DataManager.Save(importTaskViewItem.Task.Instrument, dataObject, SaveMode.Add);
   }
   importTaskViewItem.Task.TotalNum = data.TotalNum;
   importTaskViewItem.Task.Count += data.Objects.Length;
 }
示例#4
0
        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来解析,测试过这种方法目前是效率比较高的方法
                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);
            }

            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);

                    if (null != MarketDataFilter)
                    {
                        Trade t = MarketDataFilter.FilterTrade(trade, instrument.Symbol);
                        if (null != t)
                        {
                            EmitNewTradeEvent(instrument, t);
                        }
                    }
                    else
                    {
                        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
                    );

                    if (null != MarketDataFilter)
                    {
                        Quote q = MarketDataFilter.FilterQuote(quote, instrument.Symbol);
                        if (null != q)
                        {
                            EmitNewQuoteEvent(instrument, q);
                        }
                    }
                    else
                    {
                        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);
            }
        }
示例#5
0
        private void OnRtnDepthMarketData(IntPtr pApi, ref CZQThostFtdcDepthMarketDataField pDepthMarketData)
        {
            CZQThostFtdcDepthMarketDataField DepthMarket;
            if (_dictDepthMarketData.TryGetValue(pDepthMarketData.InstrumentID, out DepthMarket))
            {
                //将更新字典的功能提前,因为如果一开始就OnTrade中下单,涨跌停没有更新
                _dictDepthMarketData[pDepthMarketData.InstrumentID] = pDepthMarketData;

                if (TimeMode.LocalTime == _TimeMode)
                {
                    //为了生成正确的Bar,使用本地时间
                    _dateTime = Clock.Now;
                }
                else
                {
                    //直接按HH:mm:ss来解析,测试过这种方法目前是效率比较高的方法
                    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);
                }

                Instrument instrument = _dictAltSymbol2Instrument[pDepthMarketData.InstrumentID];

                //通过测试,发现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);

                    if (null != marketDataFilter)
                    {
                        //comment by fouvy, for openquant 2.9
                        //Trade t = marketDataFilter.FilterTrade(trade, instrument.Symbol);
                        //if (null != t)
                        //{
                        //    EmitNewTradeEvent(instrument, t);
                        //}
                    }
                    else
                    {
                        EmitNewTradeEvent(instrument, trade);
                    }
                }

                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
                    );

                    if (null != marketDataFilter)
                    {
                        //comment by fouvy change for openquant 2.9
                        //Quote q = marketDataFilter.FilterQuote(quote, instrument.Symbol);
                        //if (null != q)
                        //{
                        //    EmitNewQuoteEvent(instrument, q);
                        //}
                    }
                    else
                    {
                        EmitNewQuoteEvent(instrument, quote);
                    }
                }
            }
        }
        public override void onMessage(QuickFix42.MarketDataIncrementalRefresh refresh, QuickFix.SessionID sessionID)
        {
            if (refresh.isSetNoMDEntries())
            {
                string reqID = refresh.getMDReqID().getValue();

                Instrument instrument = (provider as GSFIX).GetInstrument(reqID);

                if (instrument == null)
                    return;

                QuickFix42.MarketDataIncrementalRefresh.NoMDEntries group = new QuickFix42.MarketDataIncrementalRefresh.NoMDEntries();

                int position;
                double price;
                int size;

                SmartQuant.Data.MarketDepth depth;
                SmartQuant.Data.Quote quote;

                for (uint i = 1; i <= refresh.getNoMDEntries().getValue(); i++)
                {
                    refresh.getGroup(i, group);

                    switch (group.getMDUpdateAction().getValue())
                    {
                        // new

                        case QuickFix.MDUpdateAction.NEW:
                            {
                                switch (group.getMDEntryType().getValue())
                                {
                                    case QuickFix.MDEntryType.BID:

                                        //Console.WriteLine("NEW BID");

                                        price = group.getMDEntryPx().getValue();
                                        size = (int)group.getMDEntrySize().getValue();

                                        // market depth

                                        depth = new SmartQuant.Data.MarketDepth(Clock.Now, "", -1, MDOperation.Insert, MDSide.Bid, price, size);

                                        provider.EmitMarketDepth(depth, instrument);

                                        // quote, best bid

                                        if (price > instrument.Quote.Bid)
                                        {
                                            quote = new Quote(instrument.Quote);

                                            quote.DateTime = Clock.Now;
                                            quote.Bid = price;
                                            quote.BidSize = size;

                                            provider.EmitQuote(quote, instrument);
                                        }

                                        break;

                                    case QuickFix.MDEntryType.OFFER:

                                        //Console.WriteLine("NEW ASK");

                                        price = group.getMDEntryPx().getValue();
                                        size = (int)group.getMDEntrySize().getValue();

                                        // market depth

                                        depth = new SmartQuant.Data.MarketDepth(Clock.Now, "", -1, MDOperation.Insert, MDSide.Ask, price, size);

                                        provider.EmitMarketDepth(depth, instrument);

                                        // quote, best ask

                                        if (price < instrument.Quote.Ask)
                                        {
                                            quote = new Quote(instrument.Quote);

                                            quote.DateTime = Clock.Now;
                                            quote.Ask = price;
                                            quote.AskSize = size;

                                            provider.EmitQuote(quote, instrument);
                                        }

                                        break;

                                    case QuickFix.MDEntryType.TRADE:

                                        provider.EmitTrade(new Trade(Clock.Now, group.getMDEntryPx().getValue(), (int)group.getMDEntrySize().getValue()), instrument);

                                        break;
                                }
                            }
                            break;

                        // change

                        case QuickFix.MDUpdateAction.CHANGE:
                            {
                                switch (group.getMDEntryType().getValue())
                                {
                                    case QuickFix.MDEntryType.BID:

                                        //Console.WriteLine("CHANGE BID!");

                                        position = group.getMDEntryPositionNo().getValue() - 1;
                                        size = (int)group.getMDEntrySize().getValue();

                                        // market depth

                                        depth = new SmartQuant.Data.MarketDepth(Clock.Now, "", position, MDOperation.Update, MDSide.Bid, 0, size);

                                        provider.EmitMarketDepth(depth, instrument);

                                        // quote, best bid

                                        if (position == 0)
                                        {
                                            quote = new Quote(instrument.Quote);

                                            quote.DateTime = Clock.Now;
                                            quote.BidSize = (int)group.getMDEntrySize().getValue();

                                            provider.EmitQuote(quote, instrument);
                                        }

                                        break;

                                    case QuickFix.MDEntryType.OFFER:

                                        //Console.WriteLine("CHANGE ASK!");

                                        position = group.getMDEntryPositionNo().getValue() - 1;
                                        size = (int)group.getMDEntrySize().getValue();

                                        // market depth

                                        depth = new SmartQuant.Data.MarketDepth(Clock.Now, "", position, MDOperation.Update, MDSide.Ask, 0, size);

                                        provider.EmitMarketDepth(depth, instrument);

                                        // quote, best bid

                                        if (position == 0)
                                        {
                                            quote = new Quote(instrument.Quote);

                                            quote.DateTime = Clock.Now;
                                            quote.AskSize = (int)group.getMDEntrySize().getValue();

                                            provider.EmitQuote(quote, instrument);
                                        }

                                        break;
                                }
                            }
                            break;

                        // delete

                        case QuickFix.MDUpdateAction.DELETE:
                            {
                                switch (group.getMDEntryType().getValue())
                                {
                                    case QuickFix.MDEntryType.BID:

                                        //Console.WriteLine("DELETE BID");

                                        position = group.getMDEntryPositionNo().getValue() - 1;

                                        // market depth

                                        depth = new SmartQuant.Data.MarketDepth(Clock.Now, "", position, MDOperation.Delete, MDSide.Bid, 0, 0);

                                        provider.EmitMarketDepth(depth, instrument);

                                        // quote

                                        if (position == 0)
                                        {
                                            Quote newQuote = instrument.OrderBook.GetQuote(0);

                                            newQuote.DateTime = Clock.Now;

                                            provider.EmitQuote(newQuote, instrument);
                                        }
                                        break;

                                    case QuickFix.MDEntryType.OFFER:

                                        //Console.WriteLine("DELETE ASK");

                                        position = group.getMDEntryPositionNo().getValue() - 1;

                                        // market depth

                                        depth = new SmartQuant.Data.MarketDepth(Clock.Now, "", position, MDOperation.Delete, MDSide.Ask, 0, 0);

                                        provider.EmitMarketDepth(depth, instrument);

                                        // quote

                                        if (position == 0)
                                        {
                                            Quote newQuote = instrument.OrderBook.GetQuote(0);

                                            newQuote.DateTime = Clock.Now;

                                            provider.EmitQuote(newQuote, instrument);
                                        }

                                        break;
                                }
                            }
                            break;
                    }
                }

                group.Dispose();
            }
        }
        public override void onMessage(QuickFix42.MarketDataSnapshotFullRefresh snapshot, QuickFix.SessionID sessionID)
        {
            if (snapshot.isSetNoMDEntries())
            {
                string reqID = snapshot.getMDReqID().getValue();

                Instrument instrument = (provider as GSFIX).GetInstrument(reqID);

                instrument.OrderBook.Clear();

                QuickFix42.MarketDataSnapshotFullRefresh.NoMDEntries group = new QuickFix42.MarketDataSnapshotFullRefresh.NoMDEntries();

                Quote quote = new Quote();

                quote.DateTime = Clock.Now;

                for (uint i = 1; i <= snapshot.getNoMDEntries().getValue(); i++)
                {
                    snapshot.getGroup(i, group);

                    SmartQuant.Data.MarketDepth depth;

                    int position = 0;

                    if (group.isSetMDEntryPositionNo())
                        position = group.getMDEntryPositionNo().getValue() - 1;

                    double price = group.getMDEntryPx().getValue();
                    int size = (int)group.getMDEntrySize().getValue();

                    // Console.WriteLine("Snapshot Level : " + position + " " + price + " " + size);

                    switch (group.getMDEntryType().getValue())
                    {
                        case QuickFix.MDEntryType.TRADE:

                            provider.EmitTrade(new Trade(Clock.Now, price, size), instrument);

                            break;

                        case QuickFix.MDEntryType.BID:

                            // market depth

                            depth = new SmartQuant.Data.MarketDepth(Clock.Now, "", position, MDOperation.Insert, MDSide.Bid, price, size);

                            provider.EmitMarketDepth(depth, instrument);

                            // quote

                            if (position == 0)
                            {
                                quote.Bid = price;
                                quote.BidSize = size;
                            }

                            break;

                        case QuickFix.MDEntryType.OFFER:

                            // market depth

                            depth = new SmartQuant.Data.MarketDepth(Clock.Now, "", position, MDOperation.Insert, MDSide.Ask, price, size);

                            provider.EmitMarketDepth(depth, instrument);

                            // quote

                            if (position == 0)
                            {
                                quote.Ask = price;
                                quote.AskSize = size;
                            }

                            break;
                    }
                }

                group.Dispose();

                provider.EmitQuote(quote, instrument);
            }
        }