/// <summary>
 /// Create an order book listener using user-provided data
 /// structures for the full and delta order books.  It is an error
 /// for the deltaBook to be NULL.  If the fullBook is NULL, then
 /// there will be no cached order book (and therefore nothing to
 /// apply the delta order books to); this may be useful in some
 /// circumstances.
 /// </summary>
 /// <param name="fullBook"></param>
 /// <param name="deltaBook"></param>
 public MamdaOrderBookListener(
     MamdaOrderBook fullBook,
     MamdaOrderBook deltaBook)
 {
     mFullBook  = fullBook;
     mDeltaBook = deltaBook;
 }
예제 #2
0
 /// <summary>
 /// Set this order book to be a delta that would, when applied, be
 /// the difference between to other books.
 /// </summary>
 /// <param name="lhs">An order book.</param>
 /// <param name="rhs">An order book.</param>
 public void setAsDeltaDifference(
     MamdaOrderBook lhs,
     MamdaOrderBook rhs)
 {
     clear();
     determineDiffs(mBidLevels, lhs.mBidLevels, rhs.mBidLevels, false);
     determineDiffs(mAskLevels, lhs.mAskLevels, rhs.mAskLevels, true);
 }
예제 #3
0
 /// <summary>
 /// Order book equality verification.  A MamdaOrderBookException is
 /// thrown if the books are not equal, along with the reason for
 /// the inequality.
 /// </summary>
 /// <param name="rhs">The order book to compare to the current book.</param>
 /// <exception cref="MamdaOrderBookException">Throws MamdaOrderBookException
 /// if the two books are not equal.</exception>
 public void assertEqual(MamdaOrderBook rhs)
 {
     if (mSymbol != rhs.mSymbol)
     {
         throw new MamdaOrderBookException(
                   "different symbols: " + mSymbol + "/" + rhs.mSymbol);
     }
     assertEqual(mBidLevels, rhs.mBidLevels);
     assertEqual(mAskLevels, rhs.mAskLevels);
 }
예제 #4
0
        internal void OnBookRecapCallback(
            MamdaSubscription subscription,
            MamdaOrderBookListener listener,
            MamaMsg msg,
            MamdaOrderBookDelta delta,
            MamdaOrderBookRecap recap)
        {
            long snappedSeqNum  = listener.getSeqNum();
            long realTimeSeqNum = mRealTimeListener.getSeqNum();

            MamdaOrderBook fullBook = recap.getFullOrderBook();

            if (snappedSeqNum != realTimeSeqNum)
            {
                mInconclusiveCount++;
                if (mHandler != null)
                {
                    string reason = "sequence numbers differ (" + snappedSeqNum + "!=" + realTimeSeqNum;
                    mHandler.onInconclusive(MamdaOrderBookCheckType.SNAPSHOT, reason);
                }
            }
            else
            {
                try
                {
                    fullBook.assertEqual(mRealTimeListener.getFullOrderBook());
                    mSuccessCount++;
                    if (mHandler != null)
                    {
                        mHandler.onSuccess(MamdaOrderBookCheckType.APPLY_DELTA);
                    }
                }
                catch (MamdaOrderBookException e)
                {
                    mFailureCount++;
                    if (mHandler != null)
                    {
                        mHandler.onFailure(MamdaOrderBookCheckType.SNAPSHOT,
                                           e.ToString(),
                                           msg,
                                           mRealTimeListener.getFullOrderBook(),
                                           fullBook);
                    }
                }
            }
            //Deactivate the subscription
            mSnapShotListener.clear();
            mSnapShotSubsc.deactivate();
        }
        /// <summary>
        /// Returns a shallow copy of the underlying order book.
        /// As such this method should not be called from a separate thread.
        /// The recommended use of this method is to use a timer on the same queue
        /// as data for this book is being dispatched and grab the snapshot at
        /// regular intervals.
        /// </summary>
        /// <returns>A snapshot of the current Order Book</returns>
        public MamdaOrderBook getBookSnapshot()
        {
            MamdaOrderBook mSnapshot = null;

            if (mFullBook != null)
            {
                mSnapshot = new MamdaOrderBook();
                // aquire lock
                lock (mFullBook)
                {
                    mSnapshot.copy(mFullBook);
                    mSnapshot.setSymbol(mFullBook.getSymbol());
                    mSnapshot.setIsConsistent(mFullBook.getIsConsistent());
                }
            }
            return(mSnapshot);
        }
        /// <summary>
        /// Returns a deep copy of the underlying order book.
        /// </summary>
        /// <returns>A deep snapshot of the current Order Book</returns>
        public MamdaOrderBook getDeepBookSnapshot()
        {
            MamdaOrderBook mSnapshot = null;

            if (null != mFullBook)
            {
                mSnapshot = new MamdaOrderBook();
                // aquire lock
                lock (mFullBook)
                {
                    mSnapshot.deepCopy(mFullBook);
                    mSnapshot.setSymbol(mFullBook.getSymbol());                     // strings are immutable, hence safe for assignment
                    mSnapshot.setIsConsistent(mFullBook.getIsConsistent());
                }
            }
            return(mSnapshot);
        }
        private void getLevelInfo(
            MamdaOrderBookPriceLevel level,
            MamaMsg plMsg,
            MamdaOrderBook deltaBook)
        {
            level.setPrice(plMsg.getPrice(MamdaOrderBookFields.PL_PRICE));

            level.setSize((long)plMsg.getF64(MamdaOrderBookFields.PL_SIZE, 0));
            level.setNumEntries((int)plMsg.getF64(MamdaOrderBookFields.PL_NUM_ENTRIES, 1));
            level.setAction((MamdaOrderBookPriceLevel.Actions)plMsg.getChar(
                                MamdaOrderBookFields.PL_ACTION, 'A'));
            level.setSide((MamdaOrderBookPriceLevel.Sides)plMsg.getChar(
                              MamdaOrderBookFields.PL_SIDE, 'B'));

            /* Optional order book fields: */
            level.setSizeChange((long)plMsg.getF64(MamdaOrderBookFields.PL_SIZE_CHANGE, 0));             //default 0
            level.setTime(plMsg.getDateTime(MamdaOrderBookFields.PL_TIME, deltaBook.getBookTime()));
        }
        private void createDeltaFromMamaMsgWithVectorFields(
            MamdaOrderBook delta,
            MamaMsg[] msgLevels)
        {
            /*
             * Books with vector fields always come in a single MamaMsg.
             */
            delta.clear();

            for (int i = 0; i < msgLevels.Length; i++)
            {
                MamaMsg plMsg = msgLevels[i];
                MamdaOrderBookPriceLevel level = new MamdaOrderBookPriceLevel();

                getLevelInfo(level, plMsg, delta);
                getEntries(level, plMsg);
                delta.addLevel(level);
            }
        }
 /// <summary>
 /// createDeltaFromMamaMsg processes a MamaMsg containing a partial
 /// or full order book and returns whether processing is complete
 /// </summary>
 /// <param name="delta"></param>
 /// <param name="msg"></param>
 /// <returns></returns>
 private bool createDeltaFromMamaMsg(
     MamdaOrderBook delta,
     MamaMsg msg)
 {
     // Note: the following test checks whether vector fields are part
     // of the data dictionary.  However, the vector fields may indeed
     // be part of the data dictionary, but the message may still
     // contain the non-vector style order book data.
     if (MamdaOrderBookFields.getHasVectorFields())
     {
         /* null is passed as default value otherwise
          *      getVectorMsg throws an exception if not found*/
         MamaMsg[] msgLevels =
             msg.getVectorMsg(MamdaOrderBookFields.PRICE_LEVELS, null);
         if (msgLevels != null)
         {
             createDeltaFromMamaMsgWithVectorFields(delta, msgLevels);
             return(true);
         }
     }
     return(createDeltaFromMamaMsgWithoutVectorFields(delta, msg));
 }
예제 #10
0
 /// <summary>
 /// Make a shallow copy of a book.
 /// </summary>
 /// <param name="book">The order book to copy.</param>
 public void copy(MamdaOrderBook book)
 {
     clear();
     apply(book);
 }
예제 #11
0
 /// <summary>
 /// Set this order book to be a delta that would, when applied,
 /// delete all of the fields in the bookToDelete.
 /// </summary>
 /// <param name="bookToDelete">The book to be deleted.</param>
 public void setAsDeltaDeleted(MamdaOrderBook bookToDelete)
 {
     copy(bookToDelete);
     markAllDeleted(mBidLevels);
     markAllDeleted(mAskLevels);
 }
예제 #12
0
 /// <summary>
 /// Make a deep copy of a book.
 /// </summary>
 /// <param name="book">The order book to copy.</param>
 public void deepCopy(MamdaOrderBook book)
 {
     clear();
     deepCopy(book.getBidLevels());
     deepCopy(book.getAskLevels());
 }
예제 #13
0
 /// <summary>
 /// Make a shallow copy of a book.
 /// </summary>
 /// <param name="book">The order book to copy.</param>
 public void copy(MamdaOrderBook book)
 {
     clear();
     apply(book);
 }
예제 #14
0
 /// <summary>
 /// Apply a delta to this (presumably) full book.
 /// </summary>
 /// <param name="deltaBook">The delta to apply to the order book.</param>
 public void apply(MamdaOrderBook deltaBook)
 {
     apply(deltaBook.getBidLevels());
     apply(deltaBook.getAskLevels());
 }
예제 #15
0
        private void getLevelInfo(
			MamdaOrderBookPriceLevel level,
			MamaMsg plMsg,
            MamdaOrderBook deltaBook)
        {
            level.setPrice(plMsg.getPrice(MamdaOrderBookFields.PL_PRICE));

            level.setSize((long)plMsg.getF64(MamdaOrderBookFields.PL_SIZE, 0));
            level.setNumEntries((int)plMsg.getF64(MamdaOrderBookFields.PL_NUM_ENTRIES, 1));
            level.setAction((MamdaOrderBookPriceLevel.Actions)plMsg.getChar(
                             MamdaOrderBookFields.PL_ACTION, 'A'));
            level.setSide((MamdaOrderBookPriceLevel.Sides)plMsg.getChar(
                           MamdaOrderBookFields.PL_SIDE, 'B'));

            /* Optional order book fields: */
            level.setSizeChange((long)plMsg.getF64(MamdaOrderBookFields.PL_SIZE_CHANGE, 0)); //default 0
            level.setTime(plMsg.getDateTime(MamdaOrderBookFields.PL_TIME, deltaBook.getBookTime()));
        }
예제 #16
0
        /// <summary>
        /// Returns whether a complete book delta was received.
        /// 
        /// Books without vector fields (i.e. fixed field layout) might
        /// come in multiple MamaMsgs.  The MdMsgNum and MdTotalNum
        /// fields can be used to determine which message is which.
        /// 
        /// When a single price level is present, it may or may not be
        /// encapsulated in a nested message field.  Similarly, with single
        /// entries in a price level.
        /// </summary>
        /// <param name="delta"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        private bool createDeltaFromMamaMsgWithoutVectorFields(
			MamdaOrderBook delta,
			MamaMsg msg)
        {
            int msgNum   = 1;
            int msgTotal = 1;

            if (msg.tryI32(MamaReservedFields.MsgNum, ref mMsgNum))
            {
                msgNum = mMsgNum.Value;
            }
            if (msg.tryI32(MamaReservedFields.MsgTotal, ref mMsgTotal))
            {
                msgTotal = mMsgTotal.Value;
            }

            if (msgNum == 1)
            {
                // Only clear the book if this is the first message in the
                // set of updates.
                delta.clear();
            }

            if (!mHaveSanityCheckedBookDict)
            {
                mHaveSanityCheckedBookDict = true;
                if (MamdaOrderBookFields.PRICE_LEVEL.Length == 0)
                {
                    throw new MamdaOrderBookException (
                        "data dictionary error: cannot find price level fields");
                }
            }

            //for optimised feed date, wNumLevels should be assumed = 1 if not sent
            int numLevelFieldInMsg = 1;
            if (msg.tryI32(MamdaOrderBookFields.NUM_LEVELS, ref mNumLevelFields))
            {
                numLevelFieldInMsg = mNumLevelFields.Value;
            }

            int maxLevelFields = MamdaOrderBookFields.PRICE_LEVEL.Length;
            if (numLevelFieldInMsg < maxLevelFields)
            {
                maxLevelFields = numLevelFieldInMsg;
            }

            for (int i = 1; i <= maxLevelFields; i++)
            {
                MamaMsg plMsg = msg.getMsg(MamdaOrderBookFields.PRICE_LEVEL[i], null);

                if (plMsg == null)
                {
                    if (numLevelFieldInMsg == 1)
                    {
                        /* Price level fields are probably be in the main
                         * message. */
                        plMsg = msg;
                    }
                    else
                    {
                        throw new MamdaDataException (
                            "cannot find price level fields in MamaMsg");
                    }
                }

                MamdaOrderBookPriceLevel level = new MamdaOrderBookPriceLevel();
                getLevelInfo(level, plMsg, delta);
                getEntries(level, plMsg);
                delta.addLevel (level);
            }
            return msgNum == msgTotal;
        }
예제 #17
0
 /// <summary>
 /// Returns a deep copy of the underlying order book.
 /// </summary>
 /// <returns>A deep snapshot of the current Order Book</returns>
 public MamdaOrderBook getDeepBookSnapshot()
 {
     MamdaOrderBook mSnapshot = null;
     if (null != mFullBook)
     {
         mSnapshot = new MamdaOrderBook();
         // aquire lock
         lock (mFullBook)
         {
             mSnapshot.deepCopy(mFullBook);
             mSnapshot.setSymbol(mFullBook.getSymbol()); // strings are immutable, hence safe for assignment
             mSnapshot.setIsConsistent(mFullBook.getIsConsistent());
         }
     }
     return mSnapshot;
 }
예제 #18
0
        /// <summary>
        /// Create an order book listener using user-provided data
        /// structures for the full and delta order books.  It is an error
        /// for the deltaBook to be NULL.  If the fullBook is NULL, then
        /// there will be no cached order book (and therefore nothing to
        /// apply the delta order books to); this may be useful in some
        /// circumstances.
        /// </summary>
        /// <param name="fullBook"></param>
        /// <param name="deltaBook"></param>
        public MamdaOrderBookListener(
			MamdaOrderBook fullBook,
			MamdaOrderBook deltaBook)
        {
            mFullBook  = fullBook;
            mDeltaBook = deltaBook;
        }
예제 #19
0
 /// <summary>
 /// Order book equality verification.  A MamdaOrderBookException is
 /// thrown if the books are not equal, along with the reason for
 /// the inequality.
 /// </summary>
 /// <param name="rhs">The order book to compare to the current book.</param>
 /// <exception cref="MamdaOrderBookException">Throws MamdaOrderBookException
 /// if the two books are not equal.</exception>
 public void assertEqual(MamdaOrderBook  rhs)
 {
     if (mSymbol != rhs.mSymbol)
     {
         throw new MamdaOrderBookException(
             "different symbols: " + mSymbol + "/" + rhs.mSymbol);
     }
     assertEqual(mBidLevels, rhs.mBidLevels);
     assertEqual(mAskLevels, rhs.mAskLevels);
 }
 /// <summary>
 /// Create an order book listener using internally created data
 /// structures for the full and delta order books.
 /// </summary>
 public MamdaOrderBookListener()
 {
     mFullBook  = new MamdaOrderBook();
     mDeltaBook = new MamdaOrderBook();
 }
        /// <summary>
        /// Returns whether a complete book delta was received.
        ///
        /// Books without vector fields (i.e. fixed field layout) might
        /// come in multiple MamaMsgs.  The MdMsgNum and MdTotalNum
        /// fields can be used to determine which message is which.
        ///
        /// When a single price level is present, it may or may not be
        /// encapsulated in a nested message field.  Similarly, with single
        /// entries in a price level.
        /// </summary>
        /// <param name="delta"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        private bool createDeltaFromMamaMsgWithoutVectorFields(
            MamdaOrderBook delta,
            MamaMsg msg)
        {
            int msgNum   = 1;
            int msgTotal = 1;

            if (msg.tryI32(MamaReservedFields.MsgNum, ref mMsgNum))
            {
                msgNum = mMsgNum.Value;
            }
            if (msg.tryI32(MamaReservedFields.MsgTotal, ref mMsgTotal))
            {
                msgTotal = mMsgTotal.Value;
            }

            if (msgNum == 1)
            {
                // Only clear the book if this is the first message in the
                // set of updates.
                delta.clear();
            }

            if (!mHaveSanityCheckedBookDict)
            {
                mHaveSanityCheckedBookDict = true;
                if (MamdaOrderBookFields.PRICE_LEVEL.Length == 0)
                {
                    throw new MamdaOrderBookException(
                              "data dictionary error: cannot find price level fields");
                }
            }

            //for optimised feed date, wNumLevels should be assumed = 1 if not sent
            int numLevelFieldInMsg = 1;

            if (msg.tryI32(MamdaOrderBookFields.NUM_LEVELS, ref mNumLevelFields))
            {
                numLevelFieldInMsg = mNumLevelFields.Value;
            }

            int maxLevelFields = MamdaOrderBookFields.PRICE_LEVEL.Length;

            if (numLevelFieldInMsg < maxLevelFields)
            {
                maxLevelFields = numLevelFieldInMsg;
            }

            for (int i = 1; i <= maxLevelFields; i++)
            {
                MamaMsg plMsg = msg.getMsg(MamdaOrderBookFields.PRICE_LEVEL[i], null);

                if (plMsg == null)
                {
                    if (numLevelFieldInMsg == 1)
                    {
                        /* Price level fields are probably be in the main
                         * message. */
                        plMsg = msg;
                    }
                    else
                    {
                        throw new MamdaDataException(
                                  "cannot find price level fields in MamaMsg");
                    }
                }

                MamdaOrderBookPriceLevel level = new MamdaOrderBookPriceLevel();
                getLevelInfo(level, plMsg, delta);
                getEntries(level, plMsg);
                delta.addLevel(level);
            }
            return(msgNum == msgTotal);
        }
예제 #22
0
 /// <summary>
 /// Returns a shallow copy of the underlying order book.
 /// As such this method should not be called from a separate thread.
 /// The recommended use of this method is to use a timer on the same queue
 /// as data for this book is being dispatched and grab the snapshot at
 /// regular intervals.
 /// </summary>
 /// <returns>A snapshot of the current Order Book</returns>
 public MamdaOrderBook getBookSnapshot()
 {
     MamdaOrderBook mSnapshot = null;
     if (mFullBook != null)
     {
         mSnapshot = new MamdaOrderBook();
         // aquire lock
         lock (mFullBook)
         {
             mSnapshot.copy(mFullBook);
             mSnapshot.setSymbol(mFullBook.getSymbol());
             mSnapshot.setIsConsistent(mFullBook.getIsConsistent());
         }
     }
     return mSnapshot;
 }
예제 #23
0
 /// <summary>
 /// Make a deep copy of a book.
 /// </summary>
 /// <param name="book">The order book to copy.</param>
 public void deepCopy(MamdaOrderBook book)
 {
     clear();
     deepCopy(book.getBidLevels());
     deepCopy(book.getAskLevels());
 }
예제 #24
0
        /// <summary>
        /// createDeltaFromMamaMsg processes a MamaMsg containing a partial
        /// or full order book and returns whether processing is complete
        /// </summary>
        /// <param name="delta"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        private bool createDeltaFromMamaMsg(
			MamdaOrderBook delta,
			MamaMsg msg)
        {
            // Note: the following test checks whether vector fields are part
            // of the data dictionary.  However, the vector fields may indeed
            // be part of the data dictionary, but the message may still
            // contain the non-vector style order book data.
            if (MamdaOrderBookFields.getHasVectorFields())
            {
                /* null is passed as default value otherwise
                    getVectorMsg throws an exception if not found*/
                MamaMsg[] msgLevels =
                    msg.getVectorMsg(MamdaOrderBookFields.PRICE_LEVELS, null);
                if (msgLevels != null)
                {
                    createDeltaFromMamaMsgWithVectorFields(delta, msgLevels);
                    return true;
                }
            }
            return createDeltaFromMamaMsgWithoutVectorFields(delta, msg);
        }
예제 #25
0
 /// <summary>
 /// Set this order book to be a delta that would, when applied,
 /// delete all of the fields in the bookToDelete.
 /// </summary>
 /// <param name="bookToDelete">The book to be deleted.</param>
 public void setAsDeltaDeleted(MamdaOrderBook bookToDelete)
 {
     copy(bookToDelete);
     markAllDeleted(mBidLevels);
     markAllDeleted(mAskLevels);
 }
예제 #26
0
        private void createDeltaFromMamaMsgWithVectorFields(
			MamdaOrderBook delta,
			MamaMsg[] msgLevels)
        {
            /*
             * Books with vector fields always come in a single MamaMsg.
             */
            delta.clear();

            for (int i = 0; i < msgLevels.Length; i++)
            {
                MamaMsg plMsg = msgLevels[i];
                MamdaOrderBookPriceLevel level = new MamdaOrderBookPriceLevel();

                getLevelInfo(level, plMsg, delta);
                getEntries(level, plMsg);
                delta.addLevel(level);
            }
        }
예제 #27
0
        /// <summary>
        /// Set this order book to be a delta that would, when applied, be
        /// the difference between to other books.
        /// </summary>
        /// <param name="lhs">An order book.</param>
        /// <param name="rhs">An order book.</param>
        public void setAsDeltaDifference(
			MamdaOrderBook lhs,
			MamdaOrderBook rhs)
        {
            clear();
            determineDiffs(mBidLevels, lhs.mBidLevels, rhs.mBidLevels, false);
            determineDiffs(mAskLevels, lhs.mAskLevels, rhs.mAskLevels, true);
        }
예제 #28
0
 /// <summary>
 /// Create an order book listener using internally created data
 /// structures for the full and delta order books.
 /// </summary>
 public MamdaOrderBookListener()
 {
     mFullBook  = new MamdaOrderBook();
     mDeltaBook = new MamdaOrderBook();
 }
예제 #29
0
 /// <summary>
 /// Apply a delta to this (presumably) full book.
 /// </summary>
 /// <param name="deltaBook">The delta to apply to the order book.</param>
 public void apply(MamdaOrderBook deltaBook)
 {
     apply(deltaBook.getBidLevels());
     apply(deltaBook.getAskLevels());
 }