Пример #1
0
        public event DecodeStatusEventHandler DecodeStarted = delegate { }; // Initializing to the empty anonymous method will ensure that the event is never null, even if no methods are subscribed to it.

        /// <summary>
        /// Provides methods and properties for decoding FIX messages.
        /// </summary>
        public Decoder()
        {
            trailer = new Trailer();
            header  = new Header(tag, value, trailer, this);
            xupdate = new MarketDataIncrementalRefresh(tag, value, trailer, this);
            logout  = new Logout(tag, value, trailer);
            logon   = new Logon(tag, value, trailer);
            vupdate = new MarketDataRequest(tag, value, trailer);
            fupdate = new SecurityStatus(tag, value, trailer);
            dupdate = new SecurityDefinition(tag, value, trailer);
            rupdate = new QuoteRequest(tag, value, trailer);
            wupdate = new MarketDataSnapshotFullRefresh(tag, value, trailer);
            message = new Message();
        }
Пример #2
0
        /// <summary>
        /// Applies the current update to the limit order book.
        /// </summary>
        /// <param name="header"></param>
        /// <param name="update"></param>
        public void Build(Header header, MarketDataIncrementalRefresh.RepeatingGroup update)
        {
            if (update.MDUpdateAction == MDUpdateAction.New)
            {
                New(header, update);
            }
            else if (update.MDUpdateAction == MDUpdateAction.Change)
            {
                Change(header, update);
            }
            else if (update.MDUpdateAction == MDUpdateAction.Delete)
            {
                Delete(header, update);
            }

            UpdateTime = header.SendingTime;
        }
Пример #3
0
        // NOTE: In the context of the CME's data platform, a DELETE OrderAction means the deletion of an entire price level
        // from the book, not simply the deletion of a single order.  Deletions of single
        // orders (while the price level remains intact) will be communicated via the
        // CHANGE OrderAction.
        /// <summary>
        /// Removes a price level from the limit order book.
        /// </summary>
        /// <param name="header"></param>
        /// <param name="update"></param>
        private void Delete(Header header, MarketDataIncrementalRefresh.RepeatingGroup update)
        {
            int level = update.MDPriceLevel;

            if (update.MDEntryType == MDEntryType.Bid)
            {
                // TO DO: Find a better way to implement below.
                //if (Bid[level].Price != update.MDEntryPx)
                //{
                //    throw new InvalidOperationException("Rebuild operation is attempting to delete a price level (" + update.MDEntryPx + ") that does not exist in the order book!");
                //}

                ShiftDepthLevelsUp(Bid, header.SendingTime, from: level, to: Depth);

                if (level != Depth) return;

                Bid[level].Delete(header.SendingTime);
            }
            else if (update.MDEntryType == MDEntryType.Offer)
            {
                // TO DO: Find a better way to implement below.
                //if (Ask[level].Price != update.MDEntryPx)
                //{
                //    throw new InvalidOperationException("Rebuild operation is attempting to delete a price level (" + update.MDEntryPx + ") that does not exist in the order book!");
                //}

                ShiftDepthLevelsUp(Ask, header.SendingTime, from: level, to: Depth);

                if (level != Depth) return;

                Ask[level].Delete(header.SendingTime);
            }
        }
Пример #4
0
        // NOTE: In the context of the CME's data platform, a CHANGE OrderAction means a change to the aggregate size
        // of a pre-existing level.  It DOES NOT mean a change to the price of a resting order.
        // A change to the price of a resting order would be communicated via a DELETE OrderAction
        // at the old price, followed immediately by a NEW OrderAction at the new price.
        /// <summary>
        /// Modifies a price level which is already displayed in the limit order book.
        /// </summary>
        /// <param name="header"></param>
        /// <param name="update"></param>
        private void Change(Header header, MarketDataIncrementalRefresh.RepeatingGroup update)
        {
            int level = update.MDPriceLevel;

            if (update.MDEntryType == MDEntryType.Bid)
            {
                if (Bid[level].Price == null)
                {
                    New(header, update);
                    return;
                }

                Bid[level].Size = update.MDEntrySize;
                Bid[level].UpdateTime = header.SendingTime;
                Bid[level].NumberOfOrders = update.NumberOfOrders;
            }
            else if (update.MDEntryType == MDEntryType.Offer)
            {
                if (Ask[level].Price == null)
                {
                    New(header, update);
                    return;
                }

                Ask[level].Size = update.MDEntrySize;
                Ask[level].UpdateTime = header.SendingTime;
                Ask[level].NumberOfOrders = update.NumberOfOrders;
            }
        }
Пример #5
0
        // NOTE: In the context of the CME's data platform, a NEW OrderAction means the addition of an entire price level
        // to the book, not simply the addition of a single order.  Additions of single
        // orders (to a pre-existing price level) will be communicated via the
        // CHANGE OrderAction.
        /// <summary>
        /// Inserts a new price level into the limit order book.
        /// </summary>
        /// <param name="header"></param>
        /// <param name="update"></param>
        private void New(Header header, MarketDataIncrementalRefresh.RepeatingGroup update)
        {
            int level = update.MDPriceLevel;

            if (update.MDEntryType == MDEntryType.Bid)
            {
                ShiftDepthLevelsDown(Bid, from: Depth, to: level);

                Bid[level].Price = update.MDEntryPx;
                Bid[level].Size = update.MDEntrySize;
                Bid[level].UpdateTime = header.SendingTime;
                Bid[level].NumberOfOrders = update.NumberOfOrders;
            }
            else if (update.MDEntryType == MDEntryType.Offer)
            {
                ShiftDepthLevelsDown(Ask, from: Depth, to: level);

                Ask[level].Price = update.MDEntryPx;
                Ask[level].Size = update.MDEntrySize;
                Ask[level].UpdateTime = header.SendingTime;
                Ask[level].NumberOfOrders = update.NumberOfOrders;
            }
        }
Пример #6
0
        public event UpdateEventHandler QuoteParsed = delegate { }; // Initializing to the empty anonymous method will ensure that the event is never null, even if no methods are subscribed to it.

        /// <summary>
        /// Wrapper around the 'TradeParsed' event, called when a trade update has been parsed.
        /// </summary>
        /// <param name="update"></param>
        internal void OnTradeParsed(MarketDataIncrementalRefresh.RepeatingGroup update)
        {
            UpdateEventHandler invoker = TradeParsed;

            invoker(update);
        }
Пример #7
0
        public event DecodeStatusEventHandler DecodeStarted = delegate { }; // Initializing to the empty anonymous method will ensure that the event is never null, even if no methods are subscribed to it.

        /// <summary>
        /// Provides methods and properties for decoding FIX messages.
        /// </summary>
        public Decoder()
        {
            trailer = new Trailer();
            header = new Header(tag, value, trailer, this);
            xupdate = new MarketDataIncrementalRefresh(tag, value, trailer, this);
            logout = new Logout(tag, value, trailer);
            logon = new Logon(tag, value, trailer);
            vupdate = new MarketDataRequest(tag, value, trailer);
            fupdate = new SecurityStatus(tag, value, trailer);
            dupdate = new SecurityDefinition(tag, value, trailer);
            rupdate = new QuoteRequest(tag, value, trailer);
            wupdate = new MarketDataSnapshotFullRefresh(tag, value, trailer);
            message = new Message();
        }
Пример #8
0
 private int GetContractIndex(MarketDataIncrementalRefresh.RepeatingGroup update)
 {
     int contractHash = update.SecurityDesc.GetId();
     
     return instrumentCollection[0].PertinentContracts(currentTime).IndexOf(contractHash);
 }
Пример #9
0
 private void BuildOrderBook(MarketDataIncrementalRefresh.RepeatingGroup update)
 {
     if (update.QuoteCondition != QuoteCondition.Implied)
     {
         OrderBooks[orderBookNumber].Build(header, update);
     }
     else if (update.QuoteCondition == QuoteCondition.Implied)
     {
         ImpliedOrderBooks[orderBookNumber].Build(header, update);
     }
 }
Пример #10
0
 /// <summary>
 /// Uses various elements of a given message to determine whether or not a quote is valid.
 /// </summary>
 /// <param name="update"></param>
 /// <returns></returns>
 protected virtual bool IsValidQuote(MarketDataIncrementalRefresh.RepeatingGroup update)
 {
     return update.QuoteCondition != QuoteCondition.ExchangeBest;
 }
Пример #11
0
 /// <summary>
 /// Uses various elements of a given message to determine whether or not a trade is valid.
 /// </summary>
 /// <param name="update"></param>
 /// <returns></returns>
 protected virtual bool IsValidTrade(MarketDataIncrementalRefresh.RepeatingGroup update)
 {
     return update.QuoteCondition != QuoteCondition.ExchangeBest 
         && update.TradeCondition != TradeCondition.PriceCalculatedByGlobex;
 }
Пример #12
0
        /// <summary>
        /// Called when a quote has been decoded from a market data incremental refresh FIX message.
        /// </summary>
        /// <param name="update"></param>
        protected virtual void OnQuoteParsed(MarketDataIncrementalRefresh.RepeatingGroup update)
        {
            if (!IsValidQuote(update))
            {
                return;
            }

            int contractIndex = GetContractIndex(update);
            if (contractIndex == NOT_FOUND)
            {
                return;
            }

            orderBookNumber = contractIndex;

            messageContainsValidQuote = true;

            BuildOrderBook(update);
        }
Пример #13
0
        /// <summary>
        /// Called when a trade has been decoded from a market data incremental refresh FIX message.
        /// </summary>
        /// <param name="update"></param>
        protected virtual void OnTradeParsed(MarketDataIncrementalRefresh.RepeatingGroup update)
        {
            if (!IsValidTrade(update))
            {
                return;
            }

            int contractIndex = GetContractIndex(update);
            if (contractIndex == NOT_FOUND)
            {
                return;
            }

            messageContainsValidTrade = true;

            OrderBooks[contractIndex].CommitTrade(update.MDEntryPx, currentTime, update.TradeVolume);
        }