/// <summary>
 /// Take the details from <code>level</code>code> and apply them to this level
 /// This does not update entries within the level, only information
 /// pertaining to the level itself.
 /// It is intended that this method should not be used externally to the
 /// API.
 /// </summary>
 /// <param name="level">The price level object from which the details are being
 /// obtained.</param>
 public void setDetails(MamdaOrderBookPriceLevel level)
 {
     this.mSizeChange = level.mSize - this.mSize;
     this.mSize       = level.mSize;
     this.mNumEntries = level.mNumEntries;
     this.mTime       = level.mTime;
 }
 void getEntryInfo(
     MamdaOrderBookEntry entry,
     MamaMsg entMsg,
     MamdaOrderBookPriceLevel level)
 {
     entry.setAction((MamdaOrderBookEntry.Actions)entMsg.getChar(
                         MamdaOrderBookFields.ENTRY_ACTION, 'D'));
     entry.setId(entMsg.getString(MamdaOrderBookFields.ENTRY_ID));
     entry.setSize((long)entMsg.getF64(MamdaOrderBookFields.ENTRY_SIZE, 0));
     entry.setTime(entMsg.getDateTime(MamdaOrderBookFields.ENTRY_TIME, level.getTime()));
 }
 /// <summary>
 /// Add a price level to the order book.
 /// </summary>
 /// <param name="level">The price level to add to the book.</param>
 public void addLevel(MamdaOrderBookPriceLevel level)
 {
     switch (level.getSide())
     {
         case MamdaOrderBookPriceLevel.Sides.Bid:
             addLevelSide(level, mBidLevels);
             break;
         case MamdaOrderBookPriceLevel.Sides.Ask:
             addLevelSide(level, mAskLevels);
             break;
     }
 }
Example #4
0
        /// <summary>
        /// Add a price level to the order book.
        /// </summary>
        /// <param name="level">The price level to add to the book.</param>
        public void addLevel(MamdaOrderBookPriceLevel level)
        {
            switch (level.getSide())
            {
            case MamdaOrderBookPriceLevel.Sides.Bid:
                addLevelSide(level, mBidLevels);
                break;

            case MamdaOrderBookPriceLevel.Sides.Ask:
                addLevelSide(level, mAskLevels);
                break;
            }
        }
Example #5
0
        private void deleteLevelSide(
            MamdaOrderBookPriceLevel level,
            TreeMap bookSide)
        {
            MamaPrice price = level.getPrice();

            if (bookSide.ContainsKey(price))
            {
                /* We actually need to process this properly because the
                 * update may not contain all entries, just updated
                 * ones. */
                bookSide.Remove(price);
            }
        }
Example #6
0
        private void addLevelSide(
            MamdaOrderBookPriceLevel level,
            TreeMap bookSide)
        {
            MamaPrice price = level.getPrice();

            if (!bookSide.ContainsKey(price))
            {
                bookSide.Add(price, level);
            }
            else
            {
                bookSide[price] = level;                 // Overwrite it anyway
            }
        }
Example #7
0
        private void updateLevelSide(
            MamdaOrderBookPriceLevel level,
            TreeMap bookSide)
        {
            MamaPrice price = level.getPrice();

            if (bookSide.ContainsKey(price))
            {
                MamdaOrderBookPriceLevel fullBookLevel =
                    bookSide[price] as MamdaOrderBookPriceLevel;

                /*Iterate over the entries in the update and apply them to the
                 * full book level according to action*/
                foreach (MamdaOrderBookEntry deltaEntry in level)
                {
                    switch (deltaEntry.getAction())
                    {
                    case MamdaOrderBookEntry.Actions.Add:
                        fullBookLevel.addEntry(deltaEntry);
                        break;

                    case MamdaOrderBookEntry.Actions.Update:
                        fullBookLevel.updateEntry(deltaEntry);
                        break;

                    case MamdaOrderBookEntry.Actions.Delete:
                        fullBookLevel.removeEntry(deltaEntry);
                        break;

                    case MamdaOrderBookEntry.Actions.Unknown:
                        /*Do nothing*/
                        break;

                    default:
                        /*Do nothing*/
                        break;
                    }
                }
                /*Update the details for the level itself*/
                fullBookLevel.setDetails(level);
            }
            else
            {
                bookSide.Add(price, level);                 // Add it anyway
            }
        }
        /// <summary>
        /// Copy a price level object which is an exact and deep copy of
        /// the original.
        /// </summary>
        /// <param name="copy">The MamdaOrderBookPriceLevel to copy.</param>
        public void copy(MamdaOrderBookPriceLevel copy)
        {
            setPrice(copy.mPrice);
            setSize(copy.mSize);
            setSizeChange(copy.mSizeChange);
            setNumEntries(copy.mNumEntries);
            setSide(copy.mSide);
            setAction(copy.mAction);
            setTime(copy.mTime);             // always deep copied

            for (int i = 0; i < copy.mEntries.Count; i++)
            {
                MamdaOrderBookEntry entry = new MamdaOrderBookEntry();
                entry.copy((MamdaOrderBookEntry)copy.mEntries[i]);
                mEntries.Add(entry);
            }
        }
        /// <summary>
        /// Construct a price level object which is a shallow copy of
        /// the original.
        /// </summary>
        /// <param name="copy">The MamdaOrderBookPriceLevel to copy.</param>
        public MamdaOrderBookPriceLevel(MamdaOrderBookPriceLevel copy)
        {
            mPrice      = copy.mPrice;
            mSize       = copy.mSize;
            mSizeChange = copy.mSizeChange;
            mNumEntries = copy.mNumEntries;
            mSide       = copy.mSide;
            mAction     = copy.mAction;
            mTime       = copy.mTime;

            for (int i = 0; i < copy.mEntries.Count; i++)
            {
                MamdaOrderBookEntry entry = new MamdaOrderBookEntry(
                    (MamdaOrderBookEntry)copy.mEntries[i]);
                mEntries.Add(entry);
            }
        }
Example #10
0
        /// <summary>
        /// Construct a price level object which is a shallow copy of
        /// the original.
        /// </summary>
        /// <param name="copy">The MamdaOrderBookPriceLevel to copy.</param>
        public MamdaOrderBookPriceLevel(MamdaOrderBookPriceLevel copy)
        {
            mPrice      = copy.mPrice;
            mSize       = copy.mSize;
            mSizeChange = copy.mSizeChange;
            mNumEntries = copy.mNumEntries;
            mSide       = copy.mSide;
            mAction     = copy.mAction;
            mTime       = copy.mTime;

            for (int i = 0; i < copy.mEntries.Count; i++)
            {
                MamdaOrderBookEntry entry = new MamdaOrderBookEntry(
                    (MamdaOrderBookEntry)copy.mEntries[i]);
                mEntries.Add(entry);
            }
        }
        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()));
        }
        /// <summary>
        /// Order book price level equality verification.  A
        ///  is thrown if the price levels are
        /// not equal, along with the reason for the inequality.
        /// </summary>
        /// <param name="rhs"></param>
        /// <exception cref="MamdaOrderBookException">MamdaOrderBookException is thrown if the price levels are</exception>
        public void assertEqual(MamdaOrderBookPriceLevel rhs)
        {
            if ((mPrice != null) != (rhs.mPrice != null))
            {
                throwError("price not equal");
            }
            if (!mPrice.equals(rhs.mPrice))
            {
                throwError("price not equal");
            }
            if (mSize != rhs.mSize)
            {
                throwError("size not equal");
            }
            if (mNumEntries != rhs.mNumEntries)
            {
                throwError("number of entries not equal");
            }
            if (mSide != rhs.mSide)
            {
                throwError("side not equal");
            }
            if (mAction != rhs.mAction)
            {
                throwError("action not equal");
            }
            if (mTime != rhs.mTime)
            {
                throwError("time not equal");
            }

            if (mEntries.Count != rhs.mEntries.Count)
            {
                throwError("entries size mismatch (" + mEntries.Count +
                           "!=" + rhs.mEntries.Count);
            }
            for (int i = 0; i < mEntries.Count; i++)
            {
                MamdaOrderBookEntry lhsEntry = (MamdaOrderBookEntry)mEntries[i];
                MamdaOrderBookEntry rhsEntry = (MamdaOrderBookEntry)rhs.mEntries[i];
                lhsEntry.assertEqual(rhsEntry);
            }
        }
        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);
            }
        }
Example #14
0
        private void deepCopy(IEnumerable bookLevels)
        {
            foreach (MamdaOrderBookPriceLevel bookLevel in bookLevels)
            {
                MamdaOrderBookPriceLevel level = new MamdaOrderBookPriceLevel();
                level.copy(bookLevel);
                switch (level.getAction())
                {
                case MamdaOrderBookPriceLevel.Actions.Add:
                    addLevel(level);
                    break;

                case MamdaOrderBookPriceLevel.Actions.Update:
                    updateLevel(level);
                    break;

                case MamdaOrderBookPriceLevel.Actions.Delete:
                    deleteLevel(level);
                    break;
                }
            }
        }
Example #15
0
        private void dump(TextWriter writer, MamdaOrderBookPriceLevel level, int index)
        {
            string title = level.getSide() == MamdaOrderBookPriceLevel.Sides.Ask ? "Ask" : "Bid";

            writer.WriteLine("{0} {1} | price={2} size={3} action={4} entries={5} time={6}",
                             title,
                             index,
                             level.getPrice(),
                             level.getSize(),
                             level.getAction(),
                             level.getNumEntries(),
                             level.hasTime() ? level.getTime().ToString() : "null");

            foreach (MamdaOrderBookEntry entry in level)
            {
                writer.WriteLine("      |    id={0} size={1} action={2} time={3}",
                                 entry.getId(),
                                 entry.getSize(),
                                 entry.getAction(),
                                 entry.hasTime() ? entry.getTime().ToString() : "null");
            }
        }
Example #16
0
        private void assertEqual(
            TreeMap lhsLevels,
            TreeMap rhsLevels)
        {
            if (lhsLevels.Count != rhsLevels.Count)
            {
                throw new MamdaOrderBookException(
                          "number of price levels do not add up (" + lhsLevels.Count +
                          "/" + rhsLevels.Count);
            }

            IEnumerator lhsEnum = lhsLevels.Values.GetEnumerator();
            IEnumerator rhsEnum = rhsLevels.Values.GetEnumerator();

            while (lhsEnum.MoveNext() && rhsEnum.MoveNext())
            {
                MamdaOrderBookPriceLevel lhsLevel =
                    (MamdaOrderBookPriceLevel)lhsEnum.Current;
                MamdaOrderBookPriceLevel rhsLevel =
                    (MamdaOrderBookPriceLevel)rhsEnum.Current;
                lhsLevel.assertEqual(rhsLevel);
            }
        }
        private void addLevelSide(
			MamdaOrderBookPriceLevel level,
			TreeMap bookSide)
        {
            MamaPrice price = level.getPrice();
            if (!bookSide.ContainsKey(price))
            {
                bookSide.Add(price, level);
            }
            else
            {
                bookSide[price] = level; // Overwrite it anyway
            }
        }
 private void deepCopy(IEnumerable bookLevels)
 {
     foreach (MamdaOrderBookPriceLevel bookLevel in bookLevels)
     {
         MamdaOrderBookPriceLevel level = new MamdaOrderBookPriceLevel();
         level.copy(bookLevel);
         switch (level.getAction())
         {
             case MamdaOrderBookPriceLevel.Actions.Add:
                 addLevel(level);
                 break;
             case MamdaOrderBookPriceLevel.Actions.Update:
                 updateLevel(level);
                 break;
             case MamdaOrderBookPriceLevel.Actions.Delete:
                 deleteLevel(level);
                 break;
         }
     }
 }
        private void dump(TextWriter writer, MamdaOrderBookPriceLevel level, int index)
        {
            string title = level.getSide() == MamdaOrderBookPriceLevel.Sides.Ask ? "Ask" : "Bid";
            writer.WriteLine("{0} {1} | price={2} size={3} action={4} entries={5} time={6}",
                title,
                index,
                level.getPrice(),
                level.getSize(),
                level.getAction(),
                level.getNumEntries(),
                level.hasTime() ? level.getTime().ToString() : "null");

            foreach (MamdaOrderBookEntry entry in level)
            {
                writer.WriteLine("      |    id={0} size={1} action={2} time={3}",
                    entry.getId(),
                    entry.getSize(),
                    entry.getAction(),
                    entry.hasTime() ? entry.getTime().ToString() : "null");
            }
        }
Example #20
0
 /// <summary>
 /// Take the details from <code>level</code>code> and apply them to this level
 /// This does not update entries within the level, only information
 /// pertaining to the level itself.
 /// It is intended that this method should not be used externally to the
 /// API.
 /// </summary>
 /// <param name="level">The price level object from which the details are being
 /// obtained.</param>
 public void setDetails(MamdaOrderBookPriceLevel level)
 {
     this.mSizeChange = level.mSize - this.mSize;
     this.mSize       = level.mSize;
     this.mNumEntries = level.mNumEntries;
     this.mTime       = level.mTime;
 }
        private void getEntries(
            MamdaOrderBookPriceLevel level,
            MamaMsg plMsg)
        {
            /* Entries may or may not exist in the message.  If they do exist,
             * they exist as a vector of submessages, separate submessages, or
             * (if there is only one entry in the message) in the price level
             * message itself. */

            /* Optional order book fields: */
            MamaMsg[] msgEntries = null;

            /*We won't have PL_ENTRIES if FieldAttrsOrderBookWombatMsg
             * is not specified in the data dictionary*/
            if (MamdaOrderBookFields.PL_ENTRIES != null)
            {
                /* null is passed as default value otherwise
                 *  getVectorMsg throws an exception if not found*/
                msgEntries = plMsg.getVectorMsg(MamdaOrderBookFields.PL_ENTRIES, null);
            }
            if (msgEntries != null)
            {
                MamdaOrderBookEntry[] entries = new MamdaOrderBookEntry[msgEntries.Length];
                for (int j = 0; j < msgEntries.Length; j++)
                {
                    MamaMsg entMsg = msgEntries[j];
                    if (entMsg != null)
                    {
                        MamdaOrderBookEntry entry = new MamdaOrderBookEntry();
                        getEntryInfo(entry, entMsg, level);
                        level.addEntry(entry);
                    }
                }
                return;
            }

            /* Second, try the list of entries. */
            int maxEntryFields = MamdaOrderBookFields.PL_ENTRY.Length;

            // Get the number of attached sub messages
            int numEntryAttached = plMsg.getI32(MamdaOrderBookFields.PL_NUM_ATTACH, 0);

            // If there are no sub messages attempt to get the entry Id from this price level message
            if (0 == numEntryAttached)
            {
                string entID = null;
                // Check for the entry Id
                if (plMsg.tryString(MamdaOrderBookFields.ENTRY_ID, ref entID))
                {
                    // Add a new entry to the level
                    MamdaOrderBookEntry entry = new MamdaOrderBookEntry();
                    getEntryInfo(entry, plMsg, level);
                    level.addEntry(entry);
                }
            }

            else
            {
                // Ensure we dont' enumerate beyond the maximum number of entries
                if (numEntryAttached < maxEntryFields)
                {
                    maxEntryFields = numEntryAttached;
                }

                // Enumerate all the entries
                for (int j = 1; j <= maxEntryFields; j++)
                {
                    // Get the sub message
                    MamaMsg entMsg = plMsg.getMsg(MamdaOrderBookFields.PL_ENTRY[j], null);
                    if (entMsg != null)
                    {
                        // Add an entry for this level
                        MamdaOrderBookEntry entry = new MamdaOrderBookEntry();
                        getEntryInfo(entry, entMsg, level);
                        level.addEntry(entry);
                    }
                }
            }
        }
        /// <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);
        }
Example #23
0
        /// <summary>
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        public void setAsDifference(
			MamdaOrderBookPriceLevel lhs,
			MamdaOrderBookPriceLevel rhs)
        {
            int lhsBookSize = lhs.mEntries.Count;
            int rhsBookSize = rhs.mEntries.Count;
            int lhsIndex = 0;
            int rhsIndex = 0;

            while ((lhsIndex < lhsBookSize) && (rhsIndex < rhsBookSize))
            {
                string  lhsId                = null;
                string  rhsId                = null;
                long    lhsSize              = 0;
                long    rhsSize              = 0;
                MamdaOrderBookEntry lhsEntry = null;
                MamdaOrderBookEntry rhsEntry = null;

                if (lhsIndex < lhsBookSize)
                {
                    lhsEntry = (MamdaOrderBookEntry)lhs.mEntries[lhsIndex];
                    lhsId    = lhsEntry.getId();
                    lhsSize  = lhsEntry.getSize();
                }
                if (rhsIndex < rhsBookSize)
                {
                    rhsEntry = (MamdaOrderBookEntry)rhs.mEntries[rhsIndex];
                    rhsId    = rhsEntry.getId();
                    rhsSize  = rhsEntry.getSize();
                }

                if ((lhsId != null) && (rhsId != null))
                {
                    if (lhsId == rhsId)
                    {
                        // Same ID, maybe different size.
                        if (lhsSize != rhsSize)
                        {
                            MamdaOrderBookEntry updateEntry = new MamdaOrderBookEntry(rhsEntry);
                            updateEntry.setAction(MamdaOrderBookEntry.Actions.Update);
                            addEntry(updateEntry);
                        }
                        lhsIndex++;
                        rhsIndex++;
                        continue;
                    }
                    else
                    {
                        // Different ID (either something exists on the LHS
                        // and not on RHS or vice versa).
                        int rhsFound = findEntryAfter(rhs.mEntries, rhsIndex, lhsId);
                        if (rhsFound != rhsSize)
                        {
                            // The ID from the LHS was found on the RHS, so
                            // there must have been additional entries on the
                            // RHS, which we now need to add.
                            do
                            {
                                addEntry((MamdaOrderBookEntry)rhs.mEntries[rhsIndex]);
                                rhsIndex++;
                            }
                            while (rhsIndex < rhsFound);
                        }
                        else
                        {
                            // The ID from the LHS was not present on the RHS,
                            // so add the LHS entry.  Note: it would probably
                            // be faster to iterate over the LHS side rather
                            // than begin the loop again.
                            addEntry((MamdaOrderBookEntry)lhs.mEntries[lhsIndex]);
                            lhsIndex++;
                        }
                    }
                }
            }
            if (mPrice != null && rhs.getPrice() != null)
            {
                mPrice.destroy();
            }
            mPrice = rhs.getPrice();
            setSizeChange(rhs.getSize() - lhs.getSize());
            setSize(rhs.getSize());
            setNumEntries(rhs.getNumEntries());
            setAction(Actions.Update);
            mTime = rhs.getTime();
            setSide(rhs.getSide());
        }
Example #24
0
        void getEntryInfo(
			MamdaOrderBookEntry entry,
			MamaMsg entMsg,
            MamdaOrderBookPriceLevel level)
        {
            entry.setAction((MamdaOrderBookEntry.Actions)entMsg.getChar(
                             MamdaOrderBookFields.ENTRY_ACTION, 'D'));
            entry.setId(entMsg.getString(MamdaOrderBookFields.ENTRY_ID));
            entry.setSize((long)entMsg.getF64(MamdaOrderBookFields.ENTRY_SIZE, 0));
            entry.setTime(entMsg.getDateTime(MamdaOrderBookFields.ENTRY_TIME, level.getTime()));
        }
Example #25
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);
            }
        }
        private void updateLevelSide(
			MamdaOrderBookPriceLevel level,
			TreeMap bookSide)
        {
            MamaPrice price = level.getPrice();
            if (bookSide.ContainsKey(price))
            {
                MamdaOrderBookPriceLevel fullBookLevel =
                    bookSide[price] as MamdaOrderBookPriceLevel;

                /*Iterate over the entries in the update and apply them to the
                 * full book level according to action*/
                foreach (MamdaOrderBookEntry deltaEntry in level)
                {
                    switch (deltaEntry.getAction())
                    {
                        case MamdaOrderBookEntry.Actions.Add:
                            fullBookLevel.addEntry(deltaEntry);
                            break;
                        case MamdaOrderBookEntry.Actions.Update:
                            fullBookLevel.updateEntry(deltaEntry);
                            break;
                        case MamdaOrderBookEntry.Actions.Delete:
                            fullBookLevel.removeEntry(deltaEntry);
                            break;
                        case MamdaOrderBookEntry.Actions.Unknown:
                            /*Do nothing*/
                            break;
                        default:
                            /*Do nothing*/
                            break;
                    }
                }
                /*Update the details for the level itself*/
                fullBookLevel.setDetails(level);
            }
            else
            {
                bookSide.Add(price, level); // Add it anyway
            }
        }
        /// <summary>
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        public void setAsDifference(
            MamdaOrderBookPriceLevel lhs,
            MamdaOrderBookPriceLevel rhs)
        {
            int lhsBookSize = lhs.mEntries.Count;
            int rhsBookSize = rhs.mEntries.Count;
            int lhsIndex    = 0;
            int rhsIndex    = 0;

            while ((lhsIndex < lhsBookSize) && (rhsIndex < rhsBookSize))
            {
                string lhsId   = null;
                string rhsId   = null;
                long   lhsSize = 0;
                long   rhsSize = 0;
                MamdaOrderBookEntry lhsEntry = null;
                MamdaOrderBookEntry rhsEntry = null;

                if (lhsIndex < lhsBookSize)
                {
                    lhsEntry = (MamdaOrderBookEntry)lhs.mEntries[lhsIndex];
                    lhsId    = lhsEntry.getId();
                    lhsSize  = lhsEntry.getSize();
                }
                if (rhsIndex < rhsBookSize)
                {
                    rhsEntry = (MamdaOrderBookEntry)rhs.mEntries[rhsIndex];
                    rhsId    = rhsEntry.getId();
                    rhsSize  = rhsEntry.getSize();
                }

                if ((lhsId != null) && (rhsId != null))
                {
                    if (lhsId == rhsId)
                    {
                        // Same ID, maybe different size.
                        if (lhsSize != rhsSize)
                        {
                            MamdaOrderBookEntry updateEntry = new MamdaOrderBookEntry(rhsEntry);
                            updateEntry.setAction(MamdaOrderBookEntry.Actions.Update);
                            addEntry(updateEntry);
                        }
                        lhsIndex++;
                        rhsIndex++;
                        continue;
                    }
                    else
                    {
                        // Different ID (either something exists on the LHS
                        // and not on RHS or vice versa).
                        int rhsFound = findEntryAfter(rhs.mEntries, rhsIndex, lhsId);
                        if (rhsFound != rhsSize)
                        {
                            // The ID from the LHS was found on the RHS, so
                            // there must have been additional entries on the
                            // RHS, which we now need to add.
                            do
                            {
                                addEntry((MamdaOrderBookEntry)rhs.mEntries[rhsIndex]);
                                rhsIndex++;
                            }while (rhsIndex < rhsFound);
                        }
                        else
                        {
                            // The ID from the LHS was not present on the RHS,
                            // so add the LHS entry.  Note: it would probably
                            // be faster to iterate over the LHS side rather
                            // than begin the loop again.
                            addEntry((MamdaOrderBookEntry)lhs.mEntries[lhsIndex]);
                            lhsIndex++;
                        }
                    }
                }
            }
            if (mPrice != null && rhs.getPrice() != null)
            {
                mPrice.destroy();
            }
            mPrice = rhs.getPrice();
            setSizeChange(rhs.getSize() - lhs.getSize());
            setSize(rhs.getSize());
            setNumEntries(rhs.getNumEntries());
            setAction(Actions.Update);
            mTime = rhs.getTime();
            setSide(rhs.getSide());
        }
        private void deleteLevelSide(
			MamdaOrderBookPriceLevel level,
			TreeMap bookSide)
        {
            MamaPrice price = level.getPrice();
            if (bookSide.ContainsKey(price))
            {
                /* We actually need to process this properly because the
                 * update may not contain all entries, just updated
                 * ones. */
                bookSide.Remove(price);
            }
        }
Example #29
0
        private TreeMap determineDiffs(
            TreeMap resultSide,
            TreeMap lhs,
            TreeMap rhs,
            bool ascending)
        {
            IEnumerator lhsEnum    = lhs.Values.GetEnumerator();
            IEnumerator rhsEnum    = rhs.Values.GetEnumerator();
            bool        lhsHasNext = lhsEnum.MoveNext();
            bool        rhsHasNext = rhsEnum.MoveNext();

            while (lhsHasNext || rhsHasNext)
            {
                MamdaOrderBookPriceLevel lhsLevel = null;
                MamdaOrderBookPriceLevel rhsLevel = null;
                double lhsPrice = double.MinValue;
                double rhsPrice = double.MinValue;
                long   lhsSize  = 0;
                long   rhsSize  = 0;

                if (lhsHasNext)
                {
                    lhsLevel = (MamdaOrderBookPriceLevel)lhsEnum.Current;
                    lhsPrice = lhsLevel.getPrice().getValue();
                    lhsSize  = lhsLevel.getSize();
                }
                if (rhsHasNext)
                {
                    rhsLevel = (MamdaOrderBookPriceLevel)rhsEnum.Current;
                    rhsPrice = rhsLevel.getPrice().getValue();
                    rhsSize  = rhsLevel.getSize();
                }

                // Compare two doubles using an epsilon
                if ((doubleEquals(lhsPrice, rhsPrice)) && (lhsSize == rhsSize))
                {
                    // Usual scenario: both levels are the same
                    lhsHasNext = lhsEnum.MoveNext();
                    rhsHasNext = rhsEnum.MoveNext();
                    continue;
                }

                if (doubleEquals(lhsPrice, rhsPrice))
                {
                    // Same price, different size.  Need to determine the
                    // different entries.
                    MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel();
                    diffLevel.setAsDifference(lhsLevel, rhsLevel);
                    resultSide.Add(lhsLevel.getPrice(), diffLevel);
                    lhsHasNext = lhsEnum.MoveNext();
                    rhsHasNext = rhsEnum.MoveNext();
                    continue;
                }

                if (ascending)
                {
                    if (((lhsPrice > rhsPrice) && (rhsPrice != double.MinValue)) || (lhsPrice == double.MinValue))
                    {
                        // RHS has an additional price level
                        MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel(rhsLevel);
                        resultSide.Add(rhsLevel.getPrice(), diffLevel);
                        rhsHasNext = rhsEnum.MoveNext();
                        continue;
                    }
                    else
                    {
                        // RHS does not have a price level that is on the LHS.
                        // Copy the LHS level and mark all as deleted.
                        MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel(lhsLevel);
                        resultSide.Add(lhsLevel.getPrice(), diffLevel);
                        lhsHasNext = lhsEnum.MoveNext();
                        continue;
                    }
                }
                else
                {
                    if (((lhsPrice > rhsPrice) && (lhsPrice != double.MinValue)) || (rhsPrice == double.MinValue))
                    {
                        // LHS has an additional price level
                        MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel(lhsLevel);
                        resultSide.Add(lhsLevel.getPrice(), diffLevel);                         // CHECK: use indexer?
                        lhsHasNext = lhsEnum.MoveNext();
                        continue;
                    }
                    else
                    {
                        // LHS does not have a price level that is on the RHS.
                        // Copy the RHS level and mark all as deleted.
                        MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel(rhsLevel);
                        resultSide.Add(rhsLevel.getPrice(), diffLevel);                         // CHECK: use indexer?
                        rhsHasNext = rhsEnum.MoveNext();
                        continue;
                    }
                }
            }
            return(resultSide);
        }
Example #30
0
 /// <summary>
 /// Enforce strict checking of order book modifications (at the
 /// expense of some performance).  This setting is passed on to the
 /// MamdaOrderBookPriceLevel and MamdaOrderBookEntry classes.
 /// </summary>
 /// <param name="strict"></param>
 public static void setStrictChecking(bool strict)
 {
     MamdaOrderBookPriceLevel.setStrictChecking(strict);
     MamdaOrderBookEntry.setStrictChecking(strict);
 }
Example #31
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;
        }
        private TreeMap determineDiffs(
			TreeMap resultSide,
			TreeMap lhs,
			TreeMap rhs,
			bool ascending)
        {
            IEnumerator lhsEnum = lhs.Values.GetEnumerator();
            IEnumerator rhsEnum = rhs.Values.GetEnumerator();
            bool lhsHasNext = lhsEnum.MoveNext();
            bool rhsHasNext = rhsEnum.MoveNext();

            while (lhsHasNext || rhsHasNext)
            {
                MamdaOrderBookPriceLevel lhsLevel = null;
                MamdaOrderBookPriceLevel rhsLevel = null;
                double    lhsPrice = double.MinValue;
                double    rhsPrice = double.MinValue;
                long      lhsSize  = 0;
                long      rhsSize  = 0;

                if (lhsHasNext)
                {
                    lhsLevel = (MamdaOrderBookPriceLevel)lhsEnum.Current;
                    lhsPrice = lhsLevel.getPrice().getValue();
                    lhsSize  = lhsLevel.getSize();
                }
                if (rhsHasNext)
                {
                    rhsLevel = (MamdaOrderBookPriceLevel)rhsEnum.Current;
                    rhsPrice = rhsLevel.getPrice().getValue();
                    rhsSize  = rhsLevel.getSize();
                }

                // CHECK: it's usually wrong to compare two doubles w/o using an epsilon
                //		so the condition should be rewritten as
                //			lhsLevel.getPrice().equals(rhsLevel.getPrice())
                if ((lhsPrice == rhsPrice) && (lhsSize == rhsSize))
                {
                    // Usual scenario: both levels are the same
                    lhsHasNext = lhsEnum.MoveNext();
                    rhsHasNext = rhsEnum.MoveNext();
                    continue;
                }

                if (lhsPrice == rhsPrice)
                {
                    // Same price, different size.  Need to determine the
                    // different entries.
                    MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel();
                    diffLevel.setAsDifference(lhsLevel, rhsLevel);
                    resultSide.Add(lhsLevel.getPrice(), diffLevel);
                    lhsHasNext = lhsEnum.MoveNext();
                    rhsHasNext = rhsEnum.MoveNext();
                    continue;
                }

                if (ascending)
                {
                    if (((lhsPrice > rhsPrice) && (rhsPrice != double.MinValue)) || (lhsPrice == double.MinValue))
                    {
                        // RHS has an additional price level
                        MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel(rhsLevel);
                        resultSide.Add(rhsLevel.getPrice(), diffLevel);
                        rhsHasNext = rhsEnum.MoveNext();
                        continue;
                    }
                    else
                    {
                        // RHS does not have a price level that is on the LHS.
                        // Copy the LHS level and mark all as deleted.
                        MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel(lhsLevel);
                        resultSide.Add(lhsLevel.getPrice(), diffLevel);
                        lhsHasNext = lhsEnum.MoveNext();
                        continue;
                    }
                }
                else
                {
                    if (((lhsPrice > rhsPrice) && (lhsPrice != double.MinValue)) || (rhsPrice == double.MinValue))
                    {
                        // LHS has an additional price level
                        MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel(lhsLevel);
                        resultSide.Add(lhsLevel.getPrice(), diffLevel); // CHECK: use indexer?
                        lhsHasNext = lhsEnum.MoveNext();
                        continue;
                    }
                    else
                    {
                        // LHS does not have a price level that is on the RHS.
                        // Copy the RHS level and mark all as deleted.
                        MamdaOrderBookPriceLevel diffLevel = new MamdaOrderBookPriceLevel(rhsLevel);
                        resultSide.Add(rhsLevel.getPrice(), diffLevel); // CHECK: use indexer?
                        rhsHasNext = rhsEnum.MoveNext();
                        continue;
                    }
                }
            }
            return resultSide;
        }
Example #33
0
        private void getEntries(
            MamdaOrderBookPriceLevel level,
            MamaMsg plMsg)
        {
            /* Entries may or may not exist in the message.  If they do exist,
             * they exist as a vector of submessages, separate submessages, or
             * (if there is only one entry in the message) in the price level
             * message itself. */

            /* Optional order book fields: */
            MamaMsg[] msgEntries = null;
            /*We won't have PL_ENTRIES if FieldAttrsOrderBookWombatMsg
             is not specified in the data dictionary*/
            if (MamdaOrderBookFields.PL_ENTRIES != null)
            {
                /* null is passed as default value otherwise
                    getVectorMsg throws an exception if not found*/
                msgEntries = plMsg.getVectorMsg(MamdaOrderBookFields.PL_ENTRIES, null);
            }
            if (msgEntries != null)
            {
                MamdaOrderBookEntry[] entries = new MamdaOrderBookEntry[msgEntries.Length];
                for (int j = 0; j < msgEntries.Length; j++)
                {
                    MamaMsg entMsg = msgEntries[j];
                    if (entMsg != null)
                    {
                        MamdaOrderBookEntry entry = new MamdaOrderBookEntry();
                        getEntryInfo(entry, entMsg, level);
                        level.addEntry(entry);
                    }
                }
                return;
            }

            /* Second, try the list of entries. */
            int maxEntryFields = MamdaOrderBookFields.PL_ENTRY.Length;

            // Get the number of attached sub messages
            int numEntryAttached = plMsg.getI32(MamdaOrderBookFields.PL_NUM_ATTACH, 0);

            // If there are no sub messages attempt to get the entry Id from this price level message
            if (0 == numEntryAttached)
            {
                string entID = null;
                // Check for the entry Id
                if (plMsg.tryString(MamdaOrderBookFields.ENTRY_ID, ref entID))
                {
                    // Add a new entry to the level
                    MamdaOrderBookEntry entry = new MamdaOrderBookEntry();
                    getEntryInfo(entry, plMsg, level);
                    level.addEntry(entry);
                }
            }

            else
            {
                // Ensure we dont' enumerate beyond the maximum number of entries
                if (numEntryAttached < maxEntryFields)
                {
                    maxEntryFields = numEntryAttached;
                }

                // Enumerate all the entries
                for (int j = 1; j <= maxEntryFields; j++)
                {
                    // Get the sub message
                    MamaMsg entMsg = plMsg.getMsg(MamdaOrderBookFields.PL_ENTRY[j], null);
                    if (entMsg != null)
                    {
                        // Add an entry for this level
                        MamdaOrderBookEntry entry = new MamdaOrderBookEntry();
                        getEntryInfo(entry, entMsg, level);
                        level.addEntry(entry);
                    }
                }
            }
        }
Example #34
0
        /// <summary>
        /// Order book price level equality verification.  A
        ///  is thrown if the price levels are
        /// not equal, along with the reason for the inequality.
        /// </summary>
        /// <param name="rhs"></param>
        /// <exception cref="MamdaOrderBookException">MamdaOrderBookException is thrown if the price levels are</exception>
        public void assertEqual(MamdaOrderBookPriceLevel  rhs)
        {
            if ((mPrice != null) != (rhs.mPrice != null))
                throwError("price not equal");
            if (!mPrice.equals(rhs.mPrice))
                throwError("price not equal");
            if (mSize != rhs.mSize)
                throwError("size not equal");
            if (mNumEntries != rhs.mNumEntries)
                throwError("number of entries not equal");
            if (mSide != rhs.mSide)
                throwError("side not equal");
            if (mAction != rhs.mAction)
                throwError("action not equal");
            if (mTime != rhs.mTime)
                throwError ("time not equal");

            if (mEntries.Count != rhs.mEntries.Count)
            {
                throwError ("entries size mismatch (" + mEntries.Count +
                    "!=" + rhs.mEntries.Count);
            }
            for (int i = 0; i < mEntries.Count; i++)
            {
                MamdaOrderBookEntry  lhsEntry = (MamdaOrderBookEntry)mEntries[i];
                MamdaOrderBookEntry  rhsEntry = (MamdaOrderBookEntry)rhs.mEntries[i];
                lhsEntry.assertEqual (rhsEntry);
            }
        }
Example #35
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()));
        }
Example #36
0
        /// <summary>
        /// Copy a price level object which is an exact and deep copy of
        /// the original.
        /// </summary>
        /// <param name="copy">The MamdaOrderBookPriceLevel to copy.</param>
        public void copy(MamdaOrderBookPriceLevel copy)
        {
            setPrice(copy.mPrice);
            setSize(copy.mSize);
            setSizeChange(copy.mSizeChange);
            setNumEntries(copy.mNumEntries);
            setSide(copy.mSide);
            setAction(copy.mAction);
            setTime(copy.mTime); // always deep copied

            for (int i = 0; i < copy.mEntries.Count; i++)
            {
                MamdaOrderBookEntry entry = new MamdaOrderBookEntry();
                entry.copy((MamdaOrderBookEntry)copy.mEntries[i]);
                mEntries.Add(entry);
            }
        }