/// <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; } }
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); } }
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 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); } }
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); } }
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"); } }
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 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); }
/// <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()); }
/// <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 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); }
/// <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); }
/// <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; }
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> /// 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); } }