Solaxun / order_matcher

Clojure implementation of an order matching engine with several different matching strategies.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Build Status

order-matcher

An immutable limit order book implementing FIFO price/time priority matching. Orders are matched first by price, and if two orders have the same price, then by time with the oldest trades matched first. Modifications to orders result in a re-queing and a new priority for the trade will be set according to the updated price and time of such modification.

Immutability buys us the convenience of safe multi-threaded access, but the there is a cost for that convenience paid in speed. Currently the orderbook can handle ~50k orders/second (benchmarked on late 2013 macbook pro 2.4 GHz Intel Core i5). For certain applications, e.g. HFT, this may not be sufficient.

Examples

Create an order with the order function. The following keys are required:

  • :order-type (either :limit or :market)
  • :price (for limit orders only)
  • :amount (quantity of the purchase)
  • :ticker (ticker of the security to be purchased or sold)
  • :side (either :bid or :ask)

The following keys will be added for you when the Order is created:

  • :trade-id (UUID representing an individual trade)
    • This will be used to retrieve, modify, and cancel trades from the book, so be sure to store a reference to it.
  • :order-time (time at which the trade was entered)

Create a limit order to buy 4 shares of aapl at a price of 114.1 or better:

(ns order-matcher.orderbook)

(def my-order1 
  (order {:order-type :limit
          :side       :bid
          :price      114.1
          :amount     4
          :ticker     "aapl"})

;; => {:trade-id #uuid"7d858974-2584-45df-bf19-1f1fe65e8704",
;;     :trade {:order-type :limit,
;;             :side :bid,
;;             :price 114.1,
;;             :amount 4,
;;             :ticker "aapl",
;;             :order-time #object[java.time.LocalDateTime 0x31fc86c3 "2020-11-30T16:52:19.747"],
;;             :trade-id #uuid"7d858974-2584-45df-bf19-1f1fe65e8704"}}

Create a new limit order book:

(def aapl-book 
  (new-fifo-book "aapl"))

Submit the order to the limit order book:

(ns order-matcher.orderbook
 (:require [order-matcher.protocols :as protocols]))
 
(protocols/fill-order aapl-book my-order1)

As soon as the Order is added, the engine will attempt to find a match. If a match is found, the trade will be executed immediately, otherwise it will be added to the orderbook until a matching trade occurs.

After running the above example, the FifoBook records the limit order under the :bid key where it will rest until a matching :ask is submitted:

#order_matcher.orderbook.FifoBook{:ticker "aapl",
                                  :bid {#uuid"586807eb-eb8e-4b36-afd5-f1e393cfba91" {:order-type :limit,
                                                                                     :side :bid,
                                                                                     :price 114.1,
                                                                                     :amount 4,
                                                                                     :ticker "aapl",
                                                                                     :order-time #object[java.time.LocalDateTime
                                                                                                         0x3bbcd70c
                                                                                                         "2020-11-26T20:32:35.494"],
                                                                                     :trade-id #uuid"586807eb-eb8e-4b36-afd5-f1e393cfba91"}},
                                  :ask {},
                                  :last-execution {},
                                  :executed-trades {},
                                  :trade-status {:status :pending,
                                                 :trade-id #uuid"586807eb-eb8e-4b36-afd5-f1e393cfba91",
                                                 :amount-remaining 4,
                                                 :fills []},
                                  :price->quantity {:bid {114.1 4}, :ask {}}}

The FifoBook Record consists of several fields:

  • :price->quantity aggregates limit order amounts on the bid and ask side of the book at each price level, providing a view of the current state of the order book.
  • :executed-trades any time an order is placed and matches an existing trade in the book, the matched trades which execute will appear here.
  • :trade-status shows the status and details of the entered order. Within this map the :fills vector will show the prices and amounts of each fill in the event a trade results in several partial fills as it runs through the opposite side of the book.

Future Work

  • Implement a variety of other order matching strategies, for example: Supported Matching Algorithms
  • Allow different order types, for example Good till Canceled (GTC), Stop Limits, Day Orders, etc.

License

Copyright © 2020 Mark Woodworth

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

About

Clojure implementation of an order matching engine with several different matching strategies.

License:Eclipse Public License 1.0


Languages

Language:Clojure 100.0%