Skip to content

Commit

Permalink
multi_index instead of unordered_map - performance improvement, adds …
Browse files Browse the repository at this point in the history
…boost dependancy
  • Loading branch information
Denis Ivaykin committed Aug 25, 2015
1 parent 2f1b19f commit 58546cd
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 21 deletions.
6 changes: 5 additions & 1 deletion .travis.yml
Expand Up @@ -4,18 +4,22 @@ compiler:
- gcc

env:
- LIBUV_VERSION=1.0.2
- LIBUV_VERSION=1.0.2 BOOST_VERSION=1.59.0

before_install:
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- sudo apt-get update -qq
- if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.9; fi
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
- sudo apt-get install -y build-essential python-dev autotools-dev libicu-dev build-essential libbz2-dev

before_script:
# install libuv
- curl -L http://dist.libuv.org/dist/v${LIBUV_VERSION}/libuv-v${LIBUV_VERSION}.tar.gz | tar xzf -
- (cd libuv-v${LIBUV_VERSION} && ./autogen.sh && ./configure --prefix=/usr && make && sudo make install)
# install boost
- curl -L http://sourceforge.net/projects/boost/files/boost/${BOOST_VERSION}/boost_`echo ${BOOST_VERSION} | tr . _`.tar.bz2/download | tar xjf -
- (cd boost_`echo ${BOOST_VERSION} | tr . _` && ./bootstrap.sh --prefix=/usr && sudo ./b2 --with=all -j 2 install)
# generate makefile
- cmake .

Expand Down
18 changes: 14 additions & 4 deletions include/helix/order_book.hh
Expand Up @@ -6,6 +6,11 @@
/// querying per-asset order book state such as top and depth of book bid
/// and ask price and size.

#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>

#include <unordered_map>
#include <cstdint>
#include <utility>
Expand Down Expand Up @@ -88,16 +93,21 @@ struct price_level {
/// \brief Order book is a price-time prioritized list of buy and sell
/// orders.

using namespace boost::multi_index;

typedef multi_index_container<order, indexed_by<
hashed_unique<member<order, uint64_t, &order::id>>>> order_set;

class order_book {
private:
std::string _symbol;
uint64_t _timestamp;
trading_state _state;
std::unordered_map<uint64_t, order> _orders;
order_set _orders;
std::map<uint64_t, price_level, std::greater<uint64_t>> _bids;
std::map<uint64_t, price_level, std::less <uint64_t>> _asks;
public:
using iterator = std::unordered_map<uint64_t, order>::iterator;
using iterator = order_set::iterator;

order_book(const std::string& symbol, uint64_t timestamp, size_t max_orders = 0);
~order_book();
Expand Down Expand Up @@ -146,7 +156,7 @@ private:
void remove(iterator& iter);

template<typename T>
void remove(order& o, T& levels);
void remove(const order& o, T& levels);

template<typename T>
price_level& lookup_or_create(T& levels, uint64_t price);
Expand All @@ -156,4 +166,4 @@ private:

}

}
}
33 changes: 17 additions & 16 deletions src/order_book.cc
Expand Up @@ -39,7 +39,7 @@ void order_book::add(order&& order)
default:
throw invalid_argument(string("invalid side: ") + static_cast<char>(order.side));
}
_orders.emplace(order.id, std::move(order));
_orders.emplace(std::move(order));
}

void order_book::cancel(uint64_t order_id, uint64_t quantity)
Expand All @@ -48,10 +48,11 @@ void order_book::cancel(uint64_t order_id, uint64_t quantity)
if (it == _orders.end()) {
throw invalid_argument(string("invalid order id: ") + to_string(order_id));
}
auto&& order = it->second;
order.quantity -= quantity;
order.level->size -= quantity;
if (!order.quantity) {
_orders.modify(it, [quantity](order& order) {
order.quantity -= quantity;
order.level->size -= quantity;
});
if (!it->quantity) {
remove(it);
}
}
Expand All @@ -62,15 +63,15 @@ std::pair<uint64_t, side_type> order_book::execute(uint64_t order_id, uint64_t q
if (it == _orders.end()) {
throw invalid_argument(string("invalid order id: ") + to_string(order_id));
}
auto& order = it->second;
uint64_t price = order.price;
side_type s = order.side;
order.quantity -= quantity;
order.level->size -= quantity;
if (!order.quantity) {
auto ret = std::make_pair(it->price, it->side);
_orders.modify(it, [quantity](order& order) {
order.quantity -= quantity;
order.level->size -= quantity;
});
if (!it->quantity) {
remove(it);
}
return std::make_pair(price, s);
return ret;
}

void order_book::remove(uint64_t order_id)
Expand All @@ -84,7 +85,7 @@ void order_book::remove(uint64_t order_id)

void order_book::remove(iterator& iter)
{
auto&& order = iter->second;
auto && order = *iter;
switch (order.side) {
case side_type::buy: {
remove(order, _bids);
Expand All @@ -101,7 +102,7 @@ void order_book::remove(iterator& iter)
}

template<typename T>
void order_book::remove(order& o, T& levels)
void order_book::remove(const order& o, T& levels)
{
auto it = levels.find(o.price);
if (it == levels.end()) {
Expand Down Expand Up @@ -133,7 +134,7 @@ side_type order_book::side(uint64_t order_id) const
if (it == _orders.end()) {
throw invalid_argument(string("invalid order id: ") + to_string(order_id));
}
return it->second.side;
return it->side;
}


Expand Down Expand Up @@ -213,4 +214,4 @@ uint64_t order_book::midprice(size_t level) const

}

}
}

0 comments on commit 58546cd

Please sign in to comment.