ridulfo/Order-Matching-Engine

not accumulated volumes

marmooli opened this issue · 3 comments

Hi,
thank you for developing and sharing this matching engine.
I tested your engine and noticed that it does not add up the volumes in the order book for orders with the same price. The order book simply lists them one below the other. But usually such orders are registered in the order book as a single order with an accumulated volume.

Thank you for taking your time to create these issues! #3 #2

You raise a very good point! Feel free to implement this feature yourself and make a pull request if you want.
Otherwise, I would be happy to add this feature myself. It might take some time though.

@nicoloridulfo Checking in to see if there's any updates or forks that have implemented this.

If not, what is the general algorithm/approach that can be used to implement this?

Hi @athenawisdoms,
This is quite easy to implement if the data structure would have been different. This is a C++ orderbook that I wrote that has this feature:

//Orderbook.h
#include <limits>
#include <ostream>
#include <unordered_map>

using std::shared_ptr;

struct Limit;
struct Order {
    Order(uint64_t id, uint64_t time, uint size, uint remaining, uint price):
    id{id}, time{time}, size{size}, remaining{remaining}, price{price}{};
    uint64_t id;
    uint64_t time;
    uint size, remaining;
    uint price;
    shared_ptr<Order> nextOrder{nullptr};
    shared_ptr<Order> prevOrder{nullptr};
    shared_ptr<Limit> parentLimit{nullptr};
};

struct Limit{
    Limit(uint price):price{price}{};
    const uint price{0};
    uint totalVolume{0};
    uint size{0};
    //Limit* parent{nullptr};
    shared_ptr<Limit> next{nullptr};
    shared_ptr<Order> front{nullptr};
    shared_ptr<Order> tail{nullptr};
};

class Book {
    public:
    uint64_t sendLimitOrder(bool isBuy, uint size, double price);
    uint64_t sendMarketOrder(bool, uint size);
    uint64_t sendCancelOrder(uint64_t id);
    double getBid() const;
    double getAsk() const;
    uint size(){return numOrders;};
    uint count(){return numOrders;};
    std::string ladder(int depth);

    private:
    Order createOrder(uint size, double price);
    void addOrder(bool isBuy, uint size, uint remaining, uint price);
    shared_ptr<Order> execute(shared_ptr<Order> order);

    std::shared_ptr<Limit> createLimit(bool isbuy, uint price);
    std::unordered_map<uint64_t, std::shared_ptr<Order>> orderids{};
    std::unordered_map<uint, shared_ptr<Limit>> buylimitmap{};
    std::unordered_map<uint, shared_ptr<Limit>> selllimitmap{};
    uint64_t nextid{0};
    std::shared_ptr<Limit> lowestSell;
    std::shared_ptr<Limit> highestBuy;
    uint numOrders{0};
};

It relies on having each price level as an object. Each price level object stores the sum of the orders volumes. In the case of this repo, I do not really know how it could be done efficiently. Perhaps keeping a dictionary of all price levels and their volumes. When adding an order you could increment the volume, and when it is executed the volume would be decremented.