// constructor used on very first event to initialize market state (market summary event)
        public MarketState(Security security, TickData bid, TickData ask, TickData trade)
        {
            if (security == null)
                throw new ArgumentException("security object must not be null", "security");

            if (bid == null)
                throw new ArgumentException("TickData object for bid object must not be null", "bid");
            if (ask == null)
                throw new ArgumentException("TickData object for ask object must not be null", "ask");
            if (trade == null)
                throw new ArgumentException("TickData object for trade object must not be null", "bid");

            VolumeTdy = 0;
            OrderFlowTdy = 0;
            VolAtBidTdy = 0;
            VolAtAskTdy = 0;
            _securityObj = security;
            StateType = MktStateType.Summary;

            TimeStamp = bid.TimeStamp;
            FirstOfInterval = true;
            OnBidQuote(bid);
            SetBidOpen(bid);

            OnAskQuote(ask);
            SetAskOpen(ask);

            OnTrade(trade);
            SetTradeOpn(trade);

            SetMid();
            SetMidOpen();
        }
        private bool DuplicateOfPrevDataPoint(TickData newData, MarketState current)
        {
            double currPrice   = 0;
            bool   hasSizeData = false;

            switch (newData.Type)
            {
            case Type.Ask:
                currPrice   = current.Ask;
                hasSizeData = ((_securityObj.HasQuoteSize) && (newData.Size != current.AskVol));
                break;

            case Type.Bid:
                currPrice   = current.Bid;
                hasSizeData = ((_securityObj.HasQuoteSize) && (newData.Size != current.BidVol));
                break;

            case Type.Trade:
                currPrice   = current.LastTrdPrice;
                hasSizeData = (_securityObj.HasTradeSize);
                break;
            }

            // if it doesn't have size data and the price hasn't changed flag it as as duplicate
            return((!hasSizeData) && (Math.Abs(newData.Price - currPrice) < Double.Epsilon));
        }
        private void ParseDataTable(DataFactory factory, DataTable dt)
        {
            Console.WriteLine("Parsing {0} DataTable({1} rows)", factory.SecurityName, dt.Rows.Count.ToString());

            if (!_mktSummaryEvents.ContainsKey(factory))
            {
                _mktSummaryEvents.Add(factory, new MktSummaryEvent {
                    Complete = false
                });
            }
            MktSummaryEvent mktSummary = _mktSummaryEvents[factory];

            foreach (DataRow row in dt.Rows)
            {
                TickData tick = DataRowToTickData(factory, row);
                if (tick != null)
                {
                    if (!mktSummary.Complete)
                    {
                        mktSummary = PrepareMktSummaryEvent(factory, mktSummary, tick);
                        _mktSummaryEvents[factory] = mktSummary;
                    }
                    else
                    {
                        AddHistDataToCache(factory, tick);
                    }
                }
            }
        }
        private void OnBidQuote(TickData bidEvent)
        {
            PrevBid = Bid;
            Bid     = bidEvent.Price;

            PrevBidVol = BidVol;
            BidVol     = _securityObj.HasQuoteSize ? bidEvent.Size : 0;
        }
        private void OnAskQuote(TickData askEvent)
        {
            PrevAsk = Ask;
            Ask     = askEvent.Price;

            PrevAskVol = AskVol;
            AskVol     = _securityObj.HasQuoteSize? askEvent.Size : 0;
        }
Exemple #6
0
        public void NewTick(TickData newData)
        {
            DateTime currTimeBinTimeStamp = getCurrentInterval(newData.TimeStamp);

            if (currTimeBinTimeStamp > DateTime.MinValue) // check to make sure the initialzation has happend
            {
                // get the current market state
                SortedDictionary <uint, MarketState> currTimeBin = _marketData[currTimeBinTimeStamp];
                MarketState currentState = currTimeBin.ElementAt(currTimeBin.Count - 1).Value; // last data point in time bin

                // disregard duplicates
                if (!DuplicateOfPrevDataPoint(newData, currentState))
                {
                    bool addedNewTimeStamp = false;
                    if (!_marketData.ContainsKey(newData.TimeStamp))
                    {
                        _marketData.Add(newData.TimeStamp, new SortedDictionary <uint, MarketState>());
                        _latestTimeBin    = newData.TimeStamp > _latestTimeBin ? newData.TimeStamp : _latestTimeBin;
                        addedNewTimeStamp = true;
                    }

                    var marketDataForTimeStamp = _marketData[newData.TimeStamp];
                    lock (marketDataForTimeStamp)
                    {
                        // create a new updated market state
                        var newState = new MarketState(_securityObj, currentState, newData);

                        newState.BinCnt = (uint)marketDataForTimeStamp.Count;
                        marketDataForTimeStamp.Add(newState.BinCnt, newState);

                        if (LogEachTick)
                        {
                            string output = newState.ToStringAllData();
                            if (newState.StateType == MktStateType.Trade)
                            {
                                output += " " + newState.ToStringAllTradesNoIndentity();
                            }
                            Console.WriteLine(output);
                        }
                    }

                    // let the market aggregator know there is a new timestamp to aggregate
                    if (addedNewTimeStamp)
                    {
                        _markets.AddTickData(this, _marketData[newData.TimeStamp], newData.TimeStamp);
                    }
                }
            }
        }
        private static TickData DataRowToTickData(DataFactory factory, DataRow row)
        {
            Type     type;
            DateTime timeStamp;
            Double   price;
            uint     size;
            Dictionary <string, string> codes = null;
            TickData tick = null;

            // try parse dataRow for tick data values
            if (Enum.TryParse(row[0].ToString(), out type))
            {
                if (DateTime.TryParse(row[1].ToString(), out timeStamp))
                {
                    if (Double.TryParse(row[2].ToString(), out price))
                    {
                        if (uint.TryParse(row[3].ToString(), out size))
                        {
                            if ((price > 0) || (price < 0))
                            {
                                // if there are any codes, add to the tickData event
                                if ((row[4].ToString() != String.Empty) || (row[5].ToString() != String.Empty))
                                {
                                    codes = GetCodes(row[4].ToString(), row[5].ToString(), type);
                                }

                                // create a new tick data event
                                tick = new TickData
                                {
                                    Type        = type,
                                    TimeStamp   = timeStamp,
                                    Price       = price,
                                    Size        = size,
                                    Codes       = codes,
                                    Security    = factory.SecurityObj.Name,
                                    SecurityObj = factory.SecurityObj,
                                    SecurityID  = factory.SecurityObj.Id
                                };

                                //Console.WriteLine(tick.ToString());
                            }
                        }
                    }
                }
            }

            return(tick);
        }
        private void OnTrade(TickData trade)
        {
            LastTrdPrice = trade.Price;
            if (LastTrdPrice == Bid)
            {
                TrdCntBid++;
            }
            if (LastTrdPrice == Ask)
            {
                TrdCntAsk++;
            }

            if ((_securityObj.HasTradeSize) && (trade.Size > 0))
            {
                LastTrdSize = trade.Size;
                if (LastTrdPrice == Bid)
                {
                    VolAtBid += LastTrdSize;
                }
                if (LastTrdPrice == Ask)
                {
                    VolAtAsk += LastTrdSize;
                }
            }
            else
            {
                LastTrdSize = 0;
                VolAtBid    = 0;
                VolAtAsk    = 0;
            }

            if (TrdsAtPrice.ContainsKey(trade.Price))
            {
                TrdsAtPrice[trade.Price].NewTradeAtPrice(LastTrdSize, this);
            }
            else
            {
                if ((_securityObj.HasTradeSize) && (trade.Size > 0))
                {
                    TrdsAtPrice.Add(LastTrdPrice, new TradesAtPrice(LastTrdPrice, LastTrdSize, this));
                }
                else
                {
                    TrdsAtPrice.Add(LastTrdPrice, new TradesAtPrice(LastTrdPrice, this));
                }
            }
        }
        private void AddHistDataToCache(DataFactory factory, TickData tick)
        {
            if (!CachedTickData.ContainsKey(tick.TimeStamp))
            {
                CachedTickData.Add(tick.TimeStamp, new Dictionary <DataFactory, List <TickData> >());
            }

            Dictionary <DataFactory, List <TickData> > timeInterval = CachedTickData[tick.TimeStamp];

            if (!timeInterval.ContainsKey(factory))
            {
                timeInterval.Add(factory, new List <TickData>());
            }
            List <TickData> tickData = timeInterval[factory];

            tickData.Add(tick);
        }
        // constructor used on very first event to initialize market state (market summary event)
        public MarketState(Security security, TickData bid, TickData ask, TickData trade)
        {
            if (security == null)
            {
                throw new ArgumentException("security object must not be null", "security");
            }

            if (bid == null)
            {
                throw new ArgumentException("TickData object for bid object must not be null", "bid");
            }
            if (ask == null)
            {
                throw new ArgumentException("TickData object for ask object must not be null", "ask");
            }
            if (trade == null)
            {
                throw new ArgumentException("TickData object for trade object must not be null", "bid");
            }

            VolumeTdy    = 0;
            OrderFlowTdy = 0;
            VolAtBidTdy  = 0;
            VolAtAskTdy  = 0;
            _securityObj = security;
            StateType    = MktStateType.Summary;

            TimeStamp       = bid.TimeStamp;
            FirstOfInterval = true;
            OnBidQuote(bid);
            SetBidOpen(bid);

            OnAskQuote(ask);
            SetAskOpen(ask);

            OnTrade(trade);
            SetTradeOpn(trade);

            SetMid();
            SetMidOpen();
        }
        public void FirstTick(TickData bid, TickData ask, TickData trade)
        {
            Console.WriteLine("Summary for " + _securityObj.Name);
            DateTime timeBin = bid.TimeStamp; // no timestamp

            if (!_mktInitialized)
            {
                _mktInitialized = true;
                _marketData.Add(timeBin, new SortedDictionary <uint, MarketState>());

                lock (_marketData[timeBin])
                {
                    // initialize the market
                    var newState = new MarketState(_securityObj, bid, ask, trade);

                    // Add the new state to its time bin
                    _marketData[newState.TimeStamp].Add(newState.BinCnt, newState);

                    _markets.AddTickData(this, _marketData[newState.TimeStamp], newState.TimeStamp);
                }
            }
        }
        private void AddHistDataToCache(DataFactory factory, TickData tick)
        {
            if (!CachedTickData.ContainsKey(tick.TimeStamp))
                CachedTickData.Add(tick.TimeStamp, new Dictionary<DataFactory, List<TickData>>());

            Dictionary<DataFactory, List<TickData>> timeInterval = CachedTickData[tick.TimeStamp];

            if (!timeInterval.ContainsKey(factory))
                timeInterval.Add(factory, new List<TickData>());
            List<TickData> tickData = timeInterval[factory];

            tickData.Add(tick);
        }
 private void SetBidOpen(TickData bidEvent)
 {
     BidOpen = bidEvent.Price;
     BidVolOpen = _securityObj.HasQuoteSize ? bidEvent.Size : 0;
 }
 private void SetTradeOpn(TickData trade)
 {
     LastPriceOpn = trade.Price;
 }
 private void SetAskOpen(TickData askEvent)
 {
     AskOpen = askEvent.Price;
     AskVolOpen = _securityObj.HasQuoteSize ? askEvent.Size : 0;
 }
        // constructor used for each successive data event after the initial market summary event
        public MarketState(Security security, MarketState previousMktState, TickData tickData)
        {
            VolumeTdy = 0;
            OrderFlowTdy = 0;
            VolAtBidTdy = 0;
            VolAtAskTdy = 0;
            _securityObj = security;

            if (previousMktState == null)
                throw new ArgumentException("Previous MarketState object must not be null", "previousMktState");

            if (tickData.TimeStamp == null)
                throw new ArgumentException("tickData.TimeStamp must not be null", "tickData.TimeStamp");

            TimeStamp = tickData.TimeStamp;

            FirstOfInterval = (tickData.TimeStamp.Subtract(previousMktState.TimeStamp).TotalSeconds > 0);

            CopyPrevState(previousMktState, FirstOfInterval);

            switch (tickData.Type)
            {
                case Type.Ask:
                    StateType = MktStateType.Ask;
                    OnAskQuote(tickData);
                    SetAskVolChg(previousMktState);
                    SetMid();
                    if (FirstOfInterval)
                    {
                        SetAskOpen(tickData);
                        SetMidOpen();
                    }
                    break;
                case Type.Bid:
                    StateType = MktStateType.Bid;
                    OnBidQuote(tickData);
                    SetBidVolChg(previousMktState);
                    SetMid();
                    if (FirstOfInterval)
                    {
                        SetBidOpen(tickData);
                        SetMidOpen();
                    }
                    break;
                case Type.Trade:
                    StateType = MktStateType.Trade;
                    OnTrade(tickData);
                    if (FirstOfInterval)
                    {
                        SetTradeOpn(tickData);
                    }
                    break;
                default:
                    throw new ArgumentException("TickData's 'Type' parameter must be of enum of type TickData.Type", "tickData");
            }

            if ((FirstOfInterval) || (Codes == null))
            {

                Codes = tickData.Codes;
            }
            else
            {
                if (tickData.Codes != null)
                {
                    if (tickData.Codes.Count > 0)
                    {
                        foreach (var code in tickData.Codes)
                        {
                            if (!Codes.ContainsKey(code.Key))
                                Codes.Add(code.Key, code.Value);
                        }
                    }
                }
            }
        }
        // constructor used for each successive data event after the initial market summary event
        public MarketState(Security security, MarketState previousMktState, TickData tickData)
        {
            VolumeTdy    = 0;
            OrderFlowTdy = 0;
            VolAtBidTdy  = 0;
            VolAtAskTdy  = 0;
            _securityObj = security;

            if (previousMktState == null)
            {
                throw new ArgumentException("Previous MarketState object must not be null", "previousMktState");
            }

            if (tickData.TimeStamp == null)
            {
                throw new ArgumentException("tickData.TimeStamp must not be null", "tickData.TimeStamp");
            }

            TimeStamp = tickData.TimeStamp;

            FirstOfInterval = (tickData.TimeStamp.Subtract(previousMktState.TimeStamp).TotalSeconds > 0);

            CopyPrevState(previousMktState, FirstOfInterval);

            switch (tickData.Type)
            {
            case Type.Ask:
                StateType = MktStateType.Ask;
                OnAskQuote(tickData);
                SetAskVolChg(previousMktState);
                SetMid();
                if (FirstOfInterval)
                {
                    SetAskOpen(tickData);
                    SetMidOpen();
                }
                break;

            case Type.Bid:
                StateType = MktStateType.Bid;
                OnBidQuote(tickData);
                SetBidVolChg(previousMktState);
                SetMid();
                if (FirstOfInterval)
                {
                    SetBidOpen(tickData);
                    SetMidOpen();
                }
                break;

            case Type.Trade:
                StateType = MktStateType.Trade;
                OnTrade(tickData);
                if (FirstOfInterval)
                {
                    SetTradeOpn(tickData);
                }
                break;

            default:
                throw new ArgumentException("TickData's 'Type' parameter must be of enum of type TickData.Type", "tickData");
            }

            if ((FirstOfInterval) || (Codes == null))
            {
                Codes = tickData.Codes;
            }
            else
            {
                if (tickData.Codes != null)
                {
                    if (tickData.Codes.Count > 0)
                    {
                        foreach (var code in tickData.Codes)
                        {
                            if (!Codes.ContainsKey(code.Key))
                            {
                                Codes.Add(code.Key, code.Value);
                            }
                        }
                    }
                }
            }
        }
        private void OnTrade(TickData trade)
        {
            LastTrdPrice = trade.Price;
            if (LastTrdPrice == Bid) TrdCntBid++;
            if (LastTrdPrice == Ask) TrdCntAsk++;

            if ((_securityObj.HasTradeSize) && (trade.Size > 0))
            {
                LastTrdSize = trade.Size;
                if (LastTrdPrice == Bid) VolAtBid += LastTrdSize;
                if (LastTrdPrice == Ask) VolAtAsk += LastTrdSize;
            }
            else
            {
                LastTrdSize = 0;
                VolAtBid = 0;
                VolAtAsk = 0;
            }

            if (TrdsAtPrice.ContainsKey(trade.Price))
            {
                TrdsAtPrice[trade.Price].NewTradeAtPrice(LastTrdSize, this);
            }
            else
            {
                if ((_securityObj.HasTradeSize) && (trade.Size > 0))
                    TrdsAtPrice.Add(LastTrdPrice, new TradesAtPrice(LastTrdPrice, LastTrdSize, this));
                else
                    TrdsAtPrice.Add(LastTrdPrice, new TradesAtPrice(LastTrdPrice, this));
            }
        }
        private static MktSummaryEvent PrepareMktSummaryEvent(DataFactory factory, MktSummaryEvent mktSummary, TickData tick)
        {
            switch (tick.Type)
            {
                case Type.Ask:
                    if (mktSummary.Ask == null)
                    {
                        mktSummary.Ask = tick;
                        if (tick.TimeStamp > mktSummary.EventTime) mktSummary.EventTime = tick.TimeStamp;
                        mktSummary = CheckForSyntheticTradeCondition(factory, mktSummary);
                    }
                    break;
                case Type.Bid:
                    if (mktSummary.Bid == null)
                    {
                        mktSummary.Bid = tick;
                        if (tick.TimeStamp > mktSummary.EventTime) mktSummary.EventTime = tick.TimeStamp;
                        mktSummary = CheckForSyntheticTradeCondition(factory, mktSummary);
                    }
                    break;
                case Type.Trade:
                    if (mktSummary.Trade == null)
                    {
                        mktSummary.Trade = tick;
                        if (tick.TimeStamp > mktSummary.EventTime) mktSummary.EventTime = tick.TimeStamp;
                        mktSummary = CheckForSyntheticTradeCondition(factory, mktSummary);
                    }
                    break;
            }

            if ((mktSummary.Ask != null) && (mktSummary.Bid != null) && mktSummary.Trade != null)
            {
                mktSummary.Complete = true;
                Console.WriteLine("Mkt summary {0} {1} ask {2} bid {3} trade {4}", tick.Security,
                        mktSummary.EventTime.ToLongTimeString(),
                        mktSummary.Ask.Price, mktSummary.Bid.Price, mktSummary.Trade.Price);
            }

            return mktSummary;
        }
        public void NewTick(TickData newData)
        {
            DateTime currTimeBinTimeStamp = getCurrentInterval(newData.TimeStamp);

            if (currTimeBinTimeStamp > DateTime.MinValue) // check to make sure the initialzation has happend
            {
                // get the current market state
                SortedDictionary<uint, MarketState> currTimeBin = _marketData[currTimeBinTimeStamp];
                MarketState currentState = currTimeBin.ElementAt(currTimeBin.Count - 1).Value; // last data point in time bin

                // disregard duplicates
                if (!DuplicateOfPrevDataPoint(newData, currentState))
                {
                    bool addedNewTimeStamp = false;
                    if (!_marketData.ContainsKey(newData.TimeStamp))
                    {
                        _marketData.Add(newData.TimeStamp, new SortedDictionary<uint, MarketState>());
                        addedNewTimeStamp = true;
                    }

                    var marketDataForTimeStamp = _marketData[newData.TimeStamp];
                    lock (marketDataForTimeStamp)
                    {
                        // create a new updated market state
                        var newState = new MarketState(_securityObj, currentState, newData);

                        newState.BinCnt = (uint) marketDataForTimeStamp.Count;
                        marketDataForTimeStamp.Add(newState.BinCnt, newState);

                        if (LogEachTick)
                        {
                            string output = newState.ToStringAllData();
                            if (newState.StateType == MktStateType.Trade) output += " " + newState.ToStringAllTradesNoIndentity();
                            Console.WriteLine(output);
                        }

                    }

                    // let the market aggregator know there is a new timestamp to aggregate
                    if (addedNewTimeStamp)
                        _markets.AddTickData(this, _marketData[newData.TimeStamp], newData.TimeStamp);

                }
            }
        }
 private void SetTradeOpn(TickData trade)
 {
     LastPriceOpn = trade.Price;
 }
        private static TickData DataRowToTickData(DataFactory factory, DataRow row)
        {
            Type type;
            DateTime timeStamp;
            Double price;
            uint size;
            Dictionary<string, string> codes = null;
            TickData tick = null;

            // try parse dataRow for tick data values
            if (Enum.TryParse(row[0].ToString(), out type))
                if (DateTime.TryParse(row[1].ToString(), out timeStamp))
                    if (Double.TryParse(row[2].ToString(), out price))
                        if (uint.TryParse(row[3].ToString(), out size))
                        {
                            if ((price > 0) || (price < 0))
                            {
                                // if there are any codes, add to the tickData event
                                if ((row[4].ToString() != String.Empty) || (row[5].ToString() != String.Empty))
                                {
                                    codes = GetCodes(row[4].ToString(), row[5].ToString(), type);
                                }

                                // create a new tick data event
                                tick = new TickData
                                {
                                    Type = type,
                                    TimeStamp = timeStamp,
                                    Price = price,
                                    Size = size,
                                    Codes = codes,
                                    Security = factory.SecurityObj.Name,
                                    SecurityObj = factory.SecurityObj,
                                    SecurityID = factory.SecurityObj.Id
                                };

                                //Console.WriteLine(tick.ToString());
                            }
                        }

            return tick;
        }
 private void SetAskOpen(TickData askEvent)
 {
     AskOpen    = askEvent.Price;
     AskVolOpen = _securityObj.HasQuoteSize ? askEvent.Size : 0;
 }
        private static MktSummaryEvent PrepareMktSummaryEvent(DataFactory factory, MktSummaryEvent mktSummary, TickData tick)
        {
            switch (tick.Type)
            {
            case Type.Ask:
                if (mktSummary.Ask == null)
                {
                    mktSummary.Ask = tick;
                    if (tick.TimeStamp > mktSummary.EventTime)
                    {
                        mktSummary.EventTime = tick.TimeStamp;
                    }
                    mktSummary = CheckForSyntheticTradeCondition(factory, mktSummary);
                }
                break;

            case Type.Bid:
                if (mktSummary.Bid == null)
                {
                    mktSummary.Bid = tick;
                    if (tick.TimeStamp > mktSummary.EventTime)
                    {
                        mktSummary.EventTime = tick.TimeStamp;
                    }
                    mktSummary = CheckForSyntheticTradeCondition(factory, mktSummary);
                }
                break;

            case Type.Trade:
                if (mktSummary.Trade == null)
                {
                    mktSummary.Trade = tick;
                    if (tick.TimeStamp > mktSummary.EventTime)
                    {
                        mktSummary.EventTime = tick.TimeStamp;
                    }
                    mktSummary = CheckForSyntheticTradeCondition(factory, mktSummary);
                }
                break;
            }

            if ((mktSummary.Ask != null) && (mktSummary.Bid != null) && mktSummary.Trade != null)
            {
                mktSummary.Complete = true;
                Console.WriteLine("Mkt summary {0} {1} ask {2} bid {3} trade {4}", tick.Security,
                                  mktSummary.EventTime.ToLongTimeString(),
                                  mktSummary.Ask.Price, mktSummary.Bid.Price, mktSummary.Trade.Price);
            }

            return(mktSummary);
        }
 private void SetBidOpen(TickData bidEvent)
 {
     BidOpen    = bidEvent.Price;
     BidVolOpen = _securityObj.HasQuoteSize ? bidEvent.Size : 0;
 }
        public void FirstTick(TickData bid, TickData ask, TickData trade)
        {
            Console.WriteLine("Summary for " + _securityObj.Name);
            DateTime timeBin = bid.TimeStamp; // no timestamp
            if (!_mktInitialized)
            {
                _mktInitialized = true;
                _marketData.Add(timeBin, new SortedDictionary<uint, MarketState>());

                lock (_marketData[timeBin])
                {
                    // initialize the market
                    var newState = new MarketState(_securityObj, bid, ask, trade);

                    // Add the new state to its time bin
                    _marketData[newState.TimeStamp].Add(newState.BinCnt, newState);

                    _markets.AddTickData(this, _marketData[newState.TimeStamp], newState.TimeStamp);
                }
            }
        }
        private void OnAskQuote(TickData askEvent)
        {
            PrevAsk = Ask;
            Ask = askEvent.Price;

            PrevAskVol = AskVol;
            AskVol = _securityObj.HasQuoteSize ? askEvent.Size : 0;
        }
        private bool DuplicateOfPrevDataPoint(TickData newData, MarketState current)
        {
            double currPrice = 0;
            bool hasSizeData = false;

            switch (newData.Type)
            {
                case Type.Ask:
                    currPrice = current.Ask;
                    hasSizeData = ((_securityObj.HasQuoteSize) && (newData.Size != current.AskVol));
                    break;
                case Type.Bid:
                    currPrice = current.Bid;
                    hasSizeData = ((_securityObj.HasQuoteSize) && (newData.Size != current.BidVol));
                    break;
                case Type.Trade:
                    currPrice = current.LastTrdPrice;
                    hasSizeData = (_securityObj.HasTradeSize);
                    break;
            }

            // if it doesn't have size data and the price hasn't changed flag it as as duplicate
            return ((!hasSizeData) && (Math.Abs(newData.Price - currPrice) < Double.Epsilon));
        }
        private void OnBidQuote(TickData bidEvent)
        {
            PrevBid = Bid;
            Bid = bidEvent.Price;

            PrevBidVol = BidVol;
            BidVol = _securityObj.HasQuoteSize ? bidEvent.Size : 0;
        }