void TradingEngine::enterBid(Bid bid) { auto &m_bidQueue = m_bidQueues[bid.instrument()]; auto &m_askQueue = m_askQueues[bid.instrument()]; if (m_bidQueue.contains(bid)) { qDebug() << "skipping duplicate bid with id : " << bid.id(); return; } // find a seller for less than we're offering for (auto it = m_askQueue.begin(); it != m_askQueue.end(); ) { Ask ask = *it; if (ask.price() <= bid.price()) { // if we have to make a partial trade if (ask.volume() != bid.volume()) { // seller has more than we want // leaves sell in queue with smaller volume if (ask.volume() > bid.volume()) { Ask a = ask.createPartial(bid.volume()); createTrade(a, bid); ++it; // we want more from another seller // removes sell, as it's completed } else { Bid b = bid.createPartial(ask.volume()); it = m_askQueue.erase(it); createTrade(ask, b); } } else { it = m_askQueue.erase(it); createTrade(ask, bid); } } else { ++it; } // if we've completely gone through the bid, there's // no point in adding it to the orderbook if (bid.volume() == 0) { return; } } // if we're still here, we weren't able to fully // process the bid auto pos = std::lower_bound(m_bidQueue.begin(), m_bidQueue.end(), bid); m_bidQueue.insert(pos, bid); }
TEST (BidManagerTest, getLastPartnerBid_noBid) { BidManager manager; Bid bid = manager.getLastPartnerBid(); EXPECT_EQ (bid.volume(), NO_BID); }
void TradingEngine::enterAsk(Ask ask) { auto &m_bidQueue = m_bidQueues[ask.instrument()]; auto &m_askQueue = m_askQueues[ask.instrument()]; if (m_askQueue.contains(ask)) { qDebug() << "skipping duplicate ask with id : " << ask.id(); return; } auto it = m_bidQueue.begin(); while (it != m_bidQueue.end()) { Bid bid = *it; if (bid.price() >= ask.price()) { if (bid.volume() != ask.volume()) { if (bid.volume() > ask.volume()) { Bid b = bid.createPartial(ask.volume()); ++it; createTrade(ask, b); } else { Ask a = ask.createPartial(bid.volume()); it = m_bidQueue.erase(it); createTrade(a, bid); } } else { it = m_bidQueue.erase(it); createTrade(ask, bid); } if (ask.volume() == 0) { // already been fully processed return; } } else { ++it; } } m_askQueue.insert(std::lower_bound( m_askQueue.begin(), m_askQueue.end(), ask), ask); }
TEST (BidManagerTest, getLastPartnerBid_Pass) { BidManager manager; manager.addBid(PASS); manager.addBid(PASS); Bid bid = manager.getLastPartnerBid(); EXPECT_EQ (bid.volume(), PASS); }
TEST (BidManagerTest, getLastPartnerBid_RegularBid) { BidManager manager; manager.addBid(Bid(ONE_B, DIAMOND)); manager.addBid(PASS); Bid bid = manager.getLastPartnerBid(); EXPECT_EQ (bid.volume(), ONE_B); EXPECT_EQ (bid.suit(), DIAMOND); }