void MamdaQuoteToBookListenerImpl::setQuality ( MamdaSubscription* sub, mamaQuality quality) { if (mFullBook->getQuality() == quality) return; // no change mFullBook->setQuality (quality); switch (quality) { case MAMA_QUALITY_OK: break; case MAMA_QUALITY_STALE: case MAMA_QUALITY_MAYBE_STALE: case MAMA_QUALITY_PARTIAL_STALE: case MAMA_QUALITY_FORCED_STALE: case MAMA_QUALITY_UNKNOWN: if (mClearStaleBook) { acquireLock(); clear(); invokeClearHandlers (sub, NULL); releaseLock(); } } }
int main (int argc, const char** argv) { MamdaOrderBook book; setbuf (stdout, NULL); book.setSymbol (symbol); // Populate an order book with N price levels ranging from 50.00 // to 150.00, with M entries in each level. char uniqueId[32]; for (int level = 0; level < N; level++) { MamdaOrderBookTypes::Side side = (level < N/2) ? MamdaOrderBookTypes::MAMDA_BOOK_SIDE_BID : MamdaOrderBookTypes::MAMDA_BOOK_SIDE_ASK; double price = 50.0 + (100.0 * level/(double)N); for (int entry = 0; entry < M; entry++) { mama_u64_t size = 10 * entry; MamaDateTime now; now.setToNow(); snprintf(uniqueId, 32, "%s%.4g%c", symbol, price, (char)side); // book.addUniqueEntry (uniqueId, price, size, side, now); } } return 0; }
/** * Method invoked when we stop processing the last level in a message. We * invoke this method after the last entry for the level gets processed. * The subscription may be destroyed from this callback. */ void onBookAtomicEndBook ( MamdaSubscription* subscription, MamdaBookAtomicListener& listener) { /** * When level recap/delta is received, it is stored in a MamdaOrderBookPriceLevel. * If no entry deltas/recaps are received, then the price level should be applied * to the book. * The entry delta/recap callback will mark the price level with an UNKNOWN side to * show that it does not need to be applied to the book */ if(mReusablePriceLevel.getSide() != MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_UNKNOWN) { if (gExampleLogLevel == EXAMPLE_LOG_LEVEL_NORMAL && mOrderBook.getQuality() == MAMA_QUALITY_OK) { prettyPrint(subscription, mReusablePriceLevel); } applyLevel(mReusablePriceLevel); mReusablePriceLevel.setSide(MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_UNKNOWN); } if(mOrderBook.getQuality() == MAMA_QUALITY_OK && gExampleLogLevel == EXAMPLE_LOG_LEVEL_NORMAL) { prettyPrint(mOrderBook); } cout<< "BOOK END\n"; }
void BookViewer::displayLevels (const MamdaOrderBook& book) { const char* symbol = book.getSymbol (); int symbolCol = sMidColumn - (strlen (symbol)/2); attron (A_BOLD); mvprintw (0, symbolCol, "%s", symbol); mvprintw (1, 0, "%s | %s", " Time Num Size Price", "Price Size Num Time "); attroff (A_BOLD); MamdaOrderBook::constBidIterator bidIter = book.bidBegin (); MamdaOrderBook::constBidIterator bidEnd = book.bidEnd (); MamdaOrderBook::constAskIterator askIter = book.askBegin (); MamdaOrderBook::constAskIterator askEnd = book.askEnd (); for (int i = 2; i < LINES-1; i++) { move (i, 0); if (i < 7) attron (COLOR_PAIR (i-1)); if (bidIter != bidEnd) { const MamdaOrderBookPriceLevel* bidLevel = *bidIter; printw (" %12s %4d %7d %7.4f ", bidLevel->getTime ().getTimeAsString (), bidLevel->getNumEntries (), (long)bidLevel->getSize (), bidLevel->getPrice ()); ++bidIter; } else { printw (" "); } printw ("|"); if (askIter!= askEnd) { const MamdaOrderBookPriceLevel* askLevel = *askIter; printw (" %-7.4f %-7d %-6d %-12s ", askLevel->getPrice (), (long)askLevel->getSize (), askLevel->getNumEntries (), askLevel->getTime ().getTimeAsString ()); ++askIter; } else { printw (" "); } if (i < 7) attroff (COLOR_PAIR (i-1)); } refresh (); // refresh the screen }
void BookViewer::displayEntries (const MamdaOrderBook& book) { const char* symbol = book.getSymbol (); int symbolCol = sMidColumn - (strlen (symbol)/2); attron (A_BOLD); mvprintw (0, symbolCol, "%s", symbol); attroff (A_BOLD); /* Bid entries */ attron (A_BOLD); mvprintw (1, 0, "%s", sBidHeading); attroff (A_BOLD); MamdaOrderBook::constBidIterator bidIter = book.bidBegin (); MamdaOrderBook::constBidIterator bidEnd = book.bidEnd (); int colorId = 1; for (int i = 2; i < LINES-1;) { if (bidIter != bidEnd) { const MamdaOrderBookPriceLevel* bidLevel = *bidIter; displayBidEntriesInLevel (bidLevel, i, colorId); ++bidIter; ++colorId; } else { mvprintw (i, 0, " |"); i++; } } /* Ask entries */ attron (A_BOLD); mvprintw (1, sMidColumn+1, "%s", sAskHeading); attroff (A_BOLD); MamdaOrderBook::constAskIterator askIter = book.askBegin (); MamdaOrderBook::constAskIterator askEnd = book.askEnd (); colorId = 1; for (int i = 2; i < LINES-1;) { if (askIter!= askEnd) { const MamdaOrderBookPriceLevel* askLevel = *askIter; displayAskEntriesInLevel (askLevel, i, colorId); ++askIter; ++colorId; } else { mvprintw (i, sMidColumn+1, " "); i++; } } refresh (); // refresh the screen }
AtomicBookBuilder ( const char* symbol) : mShowEntries (false) , mShowMarketOrders (false) , mEntryPtr (NULL) , mLevelPtr (NULL) , mSymbol (strdup(symbol)) { mOrderBook.setSymbol (mSymbol); mOrderBook.setQuality (MAMA_QUALITY_OK); }
void BookPublisher::createBook (const char* symbol, const char* partId) { mBook = new MamdaOrderBook(); // This turns on the generation of deltas at the order book mBook->generateDeltaMsgs (true); if (symbol) mBook->setSymbol (symbol); if (partId) mBook->setPartId (partId); mBookTime.setToNow(); mBook->setBookTime (mBookTime); mSymbolList.push_back (symbol); }
void MamdaQuoteToBookListenerImpl::handleRecap (MamdaSubscription* subscription, const MamaMsg& msg) { // Clear the book mFullBook->clear(); // Clear ask/bid mQuoteCache.mBidPrice = 0.0; mQuoteCache.mBidSize = 0.0; mQuoteCache.mAskPrice = 0.0; mQuoteCache.mAskSize = 0.0; // get all the fields out of the message updateQuoteFields (msg); checkQuoteCount (subscription, msg); if (mFullBook->getIsConsistent()==false) { mama_log (MAMA_LOG_LEVEL_NORMAL, "Received Recap: Book now consistent for %s\n", (subscription ? subscription->getSymbol() : "no symbol")); } MamdaOrderBookPriceLevel* level = NULL; if (mQuoteCache.mGotBidSize || mQuoteCache.mGotBidPrice) { addLevel (level, mQuoteCache.mBidPrice.getValue(), mQuoteCache.mBidSize, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_BID, mQuoteCache.mQuoteTime); } if (mQuoteCache.mGotAskSize || mQuoteCache.mGotAskPrice) { addLevel (level, mQuoteCache.mAskPrice.getValue(), mQuoteCache.mAskSize, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_ASK, mQuoteCache.mQuoteTime); } mFullBook->setIsConsistent (true); setQuality (subscription, MAMA_QUALITY_OK); invokeRecapHandlers (subscription, &msg); MamdaOrderBookComplexDelta::clear(); }
/** * Method invoked when an order book is cleared. */ void onBookAtomicClear ( MamdaSubscription* subscription, MamdaBookAtomicListener& listener, const MamaMsg& msg) { mOrderBook.clear(); }
void BookPublisher::subscribeToSymbols () { for (vector<const char*>::const_iterator i = mSymbolList.begin (); i != mSymbolList.end (); ++i) { const char* symbol = *i; mBook = new MamdaOrderBook(); // Turn on delta generation mBook->generateDeltaMsgs(true); MamdaSubscription* aSubscription = new MamdaSubscription; MamdaOrderBookListener* aBookListener = new MamdaOrderBookListener(mBook); aSubscription->addMsgListener (aBookListener); aBookListener->setProcessEntries (mProcessEntries); BookTicker* aTicker = new BookTicker; aBookListener->addHandler (aTicker); aSubscription->setType (MAMA_SUBSC_TYPE_BOOK); aSubscription->setMdDataType (MAMA_MD_DATA_TYPE_ORDER_BOOK); mSubscriptionList.push_back (aSubscription); aSubscription->create (Mama::getDefaultEventQueue (mBridge), mSubSource, symbol, NULL); } }
const char* MamdaQuoteToBookListenerImpl::getSymbol() const { if (mFullBook) return mFullBook->getSymbol(); else return "unknown-symbol"; }
void MamdaQuoteToBookListenerImpl::invokeDeltaHandlers ( MamdaSubscription* subscription, const MamaMsg* msg) { if (mCurrentDeltaCount == 0) { // no deltas - no change to the top of book on this update. return; } deque<MamdaOrderBookHandler*>::iterator end = mHandlers.end(); deque<MamdaOrderBookHandler*>::iterator i = mHandlers.begin(); for (; i != end; ++i) { MamdaOrderBookHandler* handler = *i; if (mCurrentDeltaCount == 1) { handler->onBookDelta (subscription, mListener, msg, *this, *mFullBook); } else { MamdaOrderBookComplexDelta::setOrderBook(mFullBook); handler->onBookComplexDelta (subscription, mListener, msg, *this, *mFullBook); MamdaOrderBookComplexDelta::clear(); } } mFullBook->cleanupDetached(); mCurrentDeltaCount =0; }
/** * Method invoked when an order book delta is reported. */ void onBookAtomicLevelDelta ( MamdaSubscription* subscription, MamdaBookAtomicListener& listener, const MamaMsg& msg, const MamdaBookAtomicLevel& level) { /** * The level should only be processed when entires are not received * i.e. for level only based feeds * If an entry was received on the previous level, then the level will * have been marked with an UNKNOWN side and should not be applied to * the book */ if(mReusablePriceLevel.getSide() != MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_UNKNOWN) { if (gExampleLogLevel == EXAMPLE_LOG_LEVEL_NORMAL && mOrderBook.getQuality() == MAMA_QUALITY_OK) { prettyPrint(subscription, mReusablePriceLevel); } applyLevel(mReusablePriceLevel); } /** * Store the current level */ storeLevel(level); }
void MamdaQuoteToBookListenerImpl::checkQuoteCount ( MamdaSubscription* subscription, const MamaMsg& msg) { // Check number of quotes for gaps mama_u32_t quoteCount = mQuoteCache.mTmpQuoteCount; mama_u16_t conflateCount = 0; if (!msg.tryU16 ("wConflateQuoteCount", 23, conflateCount)) { conflateCount = 1; } if (quoteCount > 0) { if ((mQuoteCache.mQuoteCount > 0) && (quoteCount > (mQuoteCache.mQuoteCount+conflateCount))) { mGapBegin = mQuoteCache.mQuoteCount+conflateCount; mGapEnd = quoteCount-1; mQuoteCache.mQuoteCount = quoteCount; mFullBook->setIsConsistent (false); invokeGapHandlers (subscription, &msg); } } mQuoteCache.mQuoteCount = quoteCount; }
void onFailure (MamdaOrderBookCheckType type, const char* reason, const MamaMsg* msg, const MamdaOrderBook& realTimeBook, const MamdaOrderBook& checkBook) { cout << "Failed check (" << mamdaOrderBookCheckTypeToString(type) << "): " << reason << "\n"; if (gExampleLogLevel >= EXAMPLE_LOG_LEVEL_QUIET) { if (msg) cout << "Failed message: " << msg->toString() << "\n"; cout << "Failed current book: "; realTimeBook.dump(cout); cout << "Failed checking book: "; checkBook.dump(cout); cout << "\n"; } }
void onQuality (MamdaSubscription* subscription, mamaQuality quality) { if (gExampleLogLevel == EXAMPLE_LOG_LEVEL_NORMAL) { cout << "atomicbookbuilder: QUALITY: " << quality << "\n"; } mOrderBook.setQuality (quality); }
void onBookGap ( MamdaSubscription* subscription, MamdaOrderBookListener& listener, const MamaMsg* msg, const MamdaOrderBookGap& event, const MamdaOrderBook& book) { printf("\n Book Gap \n"); book.dump(std::cout); }
void MamdaQuoteToBookListenerImpl::deleteLevel ( MamdaOrderBookPriceLevel* level, MamdaOrderBookPriceLevel::Side plSide, const MamaDateTime& plTime) { mFullBook->detach (level); // remove level from book, but still use level for indicating change level->setTime (plTime); level->setSize (0); addDelta (level, (0-level->getSize()), MamdaOrderBookPriceLevel::MAMDA_BOOK_ACTION_DELETE); }
void onBookDelta ( MamdaSubscription* subscription, MamdaOrderBookListener& listener, const MamaMsg* msg, const MamdaOrderBookSimpleDelta& delta, const MamdaOrderBook& book) { printf("\n Book Delta \n"); book.dump(std::cout); }
void MamdaQuoteToBookListenerImpl::clear() { acquireLock(); mQuoteCache.initialize(); mEventSeqNum = 0; mGapBegin = 0; mGapEnd = 0; mFullBook->clear(); releaseLock(); }
void onBookClear ( MamdaSubscription* subscription, MamdaOrderBookListener& listener, const MamaMsg* msg, const MamdaOrderBookClear& clear, const MamdaOrderBook& book) { printf("\n Book Clear \n"); book.dump(std::cout); }
void onBookRecap ( MamdaSubscription* subscription, MamdaOrderBookListener& listener, const MamaMsg* msg, const MamdaOrderBookComplexDelta* delta, const MamdaOrderBookRecap& recap, const MamdaOrderBook& book) { printf("\n Book Recap \n"); book.dump(std::cout); }
void MamdaQuoteToBookListenerImpl::addLevel ( MamdaOrderBookPriceLevel*& level, double plPrice, mama_f64_t plSize, MamdaOrderBookPriceLevel::Side plSide, const MamaDateTime& plTime) { level = mFullBook->findOrCreateLevel (plPrice, plSide); level->setTime (plTime); level->setSize (plSize); addDelta (level, plSize, MamdaOrderBookPriceLevel::MAMDA_BOOK_ACTION_ADD); }
/** * Method invoked before we start processing the first level in a message. * The book should be cleared when isRecap == true. */ void onBookAtomicBeginBook ( MamdaSubscription* subscription, MamdaBookAtomicListener& listener, bool isRecap) { cout<< "BOOK BEGIN\n"; if(isRecap) mOrderBook.clear(); if(mOrderBook.getQuality() == MAMA_QUALITY_OK) { if(isRecap) { cout << "RECAP!!!\n"; } else { cout << "DELTA!!!\n"; } } }
void BookPublisher::onTimer (MamaTimer* timer) { if (!mPublishing) return; // On every timer update we take the next order from the orderArray and processEntries // clear book when at end of orderArray // To avoid editing the book while publishing using multiple threads, we need to have a // lock during the book editing functionality and also when sending initial/recap data. // We use the MamdaLock class for this functionality and have two functions called // acquireLock() and releaseLock() that implement this functionality. acquireLock(); bool publish = false; if (10 == mOrderCount) { mBook->clear(true); mOrderCount = 0; mPublishMsg.updateU8 (NULL, MamaFieldMsgType.mFid, MAMA_MSG_TYPE_BOOK_CLEAR); publish = true; } else { // process multiple orders, alike a complex update processOrder(); processOrder(); // get changes to the book and publish if (mPublishRecaps) { mBook->populateRecap(mPublishMsg); publish=true; } else { publish = mBook->populateDelta(mPublishMsg); } } if (publish) publishMessage(NULL); releaseLock(); }
/** * Method invoked when an order book delta is reported. */ void onBookAtomicLevelEntryDelta ( MamdaSubscription* subscription, MamdaBookAtomicListener& listener, const MamaMsg& msg, const MamdaBookAtomicLevelEntry& levelEntry) { if (gExampleLogLevel == EXAMPLE_LOG_LEVEL_NORMAL && mOrderBook.getQuality() == MAMA_QUALITY_OK) { prettyPrint (subscription, levelEntry); } applyEntry (levelEntry); /** * An entry has been processed on the level so mark the level with * an unknown side so that it will not be applied to book */ mReusablePriceLevel.setSide (MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_UNKNOWN); }
void BookPublisher::onTimer (MamaTimer* timer) { // need to clear publishMsg after every update const char* symbol; for (vector<const char*>::const_iterator i = mSymbolList.begin (); i != mSymbolList.end (); ++i) { symbol = (const char*)*i; acquireLock (symbol); mPublishMsg.clear(); if (mBook->populateDelta (mPublishMsg)) { publishMessage (NULL, symbol); printf ("\n Publishing Message:- %s \n", mPublishMsg.toString()); } else printf ("\n Not publishing from Empty State \n"); releaseLock (symbol); } }
void MamdaQuoteToBookListenerImpl::handleQuote (MamdaSubscription* subscription, const MamaMsg& msg) { checkQuoteCount (subscription, msg); MamdaOrderBookPriceLevel* level = NULL; if (mQuoteCache.mGotBidSize || mQuoteCache.mGotBidPrice) { // get current level MamdaOrderBook::bidIterator bidIter = mFullBook->bidBegin(); if (bidIter == mFullBook->bidEnd()) level = NULL; else level = *bidIter; if (level == NULL) { if (mQuoteCache.mBidSize == (mama_quantity_t)0 || mQuoteCache.mBidPrice.isZero()) { if (mQuoteCache.mBidSize == (mama_quantity_t)0 && mQuoteCache.mBidPrice.isZero()) { mama_log (MAMA_LOG_LEVEL_WARN, "MamdaQuoteToBookListener: Got bid update, but price and size are 0\n"); } } else { addLevel (level, mQuoteCache.mBidPrice.getValue(), mQuoteCache.mBidSize, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_BID, mQuoteCache.mQuoteTime); } } else { if ((mQuoteCache.mBidSize == 0) || (mQuoteCache.mBidPrice.isZero())) { deleteLevel (level, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_BID, mQuoteCache.mQuoteTime); } else if (mQuoteCache.mBidPrice == level->getPrice()) { updateLevel (level, mQuoteCache.mBidSize, mQuoteCache.mBidSize - level->getSize(), MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_BID, mQuoteCache.mQuoteTime); } else { deleteLevel (level, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_BID, mQuoteCache.mQuoteTime); addLevel (level, mQuoteCache.mBidPrice.getValue(), mQuoteCache.mBidSize, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_BID, mQuoteCache.mQuoteTime); } } } if (mQuoteCache.mGotAskSize || mQuoteCache.mGotAskPrice) { // get current level MamdaOrderBook::askIterator askIter = mFullBook->askBegin(); if (askIter == mFullBook->askEnd()) level = NULL; else level = *askIter; if (level == NULL) { if (mQuoteCache.mAskSize == (mama_quantity_t)0 || mQuoteCache.mAskPrice.isZero()) { if (mQuoteCache.mAskSize == (mama_quantity_t)0 && mQuoteCache.mAskPrice.isZero()) { mama_log (MAMA_LOG_LEVEL_WARN, "MamdaQuoteToBookListener: Got ask update, but price and size are 0\n"); } } else { addLevel (level, mQuoteCache.mAskPrice.getValue(), mQuoteCache.mAskSize, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_ASK, mQuoteCache.mQuoteTime); } } else { if ((mQuoteCache.mAskSize == 0) || (mQuoteCache.mAskPrice.isZero())) { deleteLevel (level, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_ASK, mQuoteCache.mQuoteTime); } else if (mQuoteCache.mAskPrice == level->getPrice()) { updateLevel (level, mQuoteCache.mAskSize, mQuoteCache.mAskSize - level->getSize(), MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_ASK, mQuoteCache.mQuoteTime); } else { deleteLevel (level, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_ASK, mQuoteCache.mQuoteTime); addLevel (level, mQuoteCache.mAskPrice.getValue(), mQuoteCache.mAskSize, MamdaOrderBookPriceLevel::MAMDA_BOOK_SIDE_ASK, mQuoteCache.mQuoteTime); } } } if (mUpdateInconsistentBook || mFullBook->getIsConsistent()) { invokeDeltaHandlers (subscription, &msg); } }
void prettyPrintEntries (const MamdaOrderBook& book) { printf ("%s\n", " ID/Num Time Size Price"); MamdaOrderBook::constBidIterator bidIter = book.bidBegin (); MamdaOrderBook::constBidIterator bidEnd = book.bidEnd (); MamdaOrderBook::constAskIterator askIter = book.askBegin (); MamdaOrderBook::constAskIterator askEnd = book.askEnd (); char timeStr[32]; if (mShowMarketOrders) { const MamdaOrderBookPriceLevel* marketBidLevel = book.getBidMarketOrders (); if (marketBidLevel) { marketBidLevel->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" Bid %4d %12s %7g MARKET\n", marketBidLevel->getNumEntries (), timeStr, marketBidLevel->getSize ()); MamdaOrderBookPriceLevel::const_iterator end = marketBidLevel->end (); MamdaOrderBookPriceLevel::const_iterator i = marketBidLevel->begin (); while (i != end) { const MamdaOrderBookEntry* entry = *i; const char* id = entry->getId (); mama_quantity_t size = entry->getSize (); entry->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" %14s %12s %7g MARKET\n", id, timeStr, size); ++i; } } } if (mShowMarketOrders) { const MamdaOrderBookPriceLevel* marketAskLevel = book.getAskMarketOrders (); if (marketAskLevel) { marketAskLevel->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" Ask %4d %12s %7g MARKET\n", marketAskLevel->getNumEntries (), timeStr, marketAskLevel->getSize ()); MamdaOrderBookPriceLevel::const_iterator end = marketAskLevel->end (); MamdaOrderBookPriceLevel::const_iterator i = marketAskLevel->begin (); while (i != end) { const MamdaOrderBookEntry* entry = *i; const char* id = entry->getId (); mama_quantity_t size = entry->getSize (); entry->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" %14s %12s %7g MARKET\n", id, timeStr, size); ++i; } } } while (bidIter != bidEnd) { const MamdaOrderBookPriceLevel* bidLevel = *bidIter; bidLevel->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" Bid %4d %12s %7g %7.*f\n", bidLevel->getNumEntries (), timeStr, bidLevel->getSize (), mPrecision, bidLevel->getPrice ()); MamdaOrderBookPriceLevel::const_iterator end = bidLevel->end (); MamdaOrderBookPriceLevel::const_iterator i = bidLevel->begin (); while (i != end) { const MamdaOrderBookEntry* entry = *i; const char* id = entry->getId (); mama_quantity_t size = entry->getSize (); double price = bidLevel->getPrice (); entry->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" %14s %12s %7g %7.*f\n", id, timeStr, size, mPrecision, price); ++i; } ++bidIter; } while (askIter != askEnd) { const MamdaOrderBookPriceLevel* askLevel = *askIter; askLevel->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" Ask %4d %12s %7g %7.*f\n", askLevel->getNumEntries (), timeStr, askLevel->getSize (), mPrecision, askLevel->getPrice ()); MamdaOrderBookPriceLevel::const_iterator end = askLevel->end (); MamdaOrderBookPriceLevel::const_iterator i = askLevel->begin (); while (i != end) { const MamdaOrderBookEntry* entry = *i; const char* id = entry->getId (); mama_quantity_t size = entry->getSize (); double price = askLevel->getPrice (); entry->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" %14s %12s %7g %7.*f\n", id, timeStr, size, mPrecision, price); ++i; } ++askIter; } }
void prettyPrintLevels (const MamdaOrderBook& book) { printf ("%s | %s\n", " Time Num Size Price Act", "Act Price Size Num Time "); MamdaOrderBook::constBidIterator bidIter = book.bidBegin (); MamdaOrderBook::constBidIterator bidEnd = book.bidEnd (); MamdaOrderBook::constAskIterator askIter = book.askBegin (); MamdaOrderBook::constAskIterator askEnd = book.askEnd (); char timeStr[32]; if (mShowMarketOrders) { printf (" MARKET ORDERS ---------------------------------------------------------------\n"); const MamdaOrderBookPriceLevel* marketOrders = NULL; if (marketOrders = book.getBidMarketOrders()) { marketOrders->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" %12s %4d %7g MARKET %c ", timeStr, marketOrders->getNumEntries (), marketOrders->getSize (), marketOrders->getAction ()); } else { printf (" "); } printf ("|"); if (marketOrders = book.getAskMarketOrders()) { marketOrders->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" %c MARKET %-7g %-6d %-12s ", marketOrders->getAction (), marketOrders->getSize (), marketOrders->getNumEntries (), timeStr); } else { printf (" "); } printf ("\n"); printf (" LIMIT ORDERS ---------------------------------------------------------------\n"); } while ((bidIter != bidEnd) || (askIter != askEnd)) { if (bidIter != bidEnd) { const MamdaOrderBookPriceLevel* bidLevel = *bidIter; bidLevel->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" %12s %4d %7g %7.*f %c ", timeStr, bidLevel->getNumEntries (), bidLevel->getSize (), mPrecision, bidLevel->getPrice (), bidLevel->getAction ()); ++bidIter; } else { printf (" "); } printf ("|"); if (askIter != askEnd) { const MamdaOrderBookPriceLevel* askLevel = *askIter; askLevel->getTime().getAsFormattedString (timeStr, 32, "%T%;"); printf (" %c %-7.*f %-7g %-6d %-12s ", askLevel->getAction (), mPrecision, askLevel->getPrice (), askLevel->getSize (), askLevel->getNumEntries (), timeStr); ++askIter; } printf ("\n"); } printf ("\n"); }