Matching Engine for Limit Order Book in Golang

Go orderbook

Improved matching engine written in Go (Golang)

Go Report Card GoDoc gocover.run Stability: Active Build Status

Features

  • Standard price-time priority
  • Supports both market and limit orders
  • Supports order cancelling
  • High performance (above 300k trades per second)
  • Optimal memory usage
  • JSON Marshalling and Unmarsalling
  • Calculating market price for definite quantity

Usage

To start using order book you need to create object:

import (
  "fmt" 
  ob "github.com/muzykantov/orderbook"
)

func main() {
  orderBook := ob.NewOrderBook()
  fmt.Println(orderBook)
}

Then you be able to use next primary functions:

func (ob *OrderBook) ProcessLimitOrder(side Side, orderID string, quantity, price decimal.Decimal) (done []*Order, partial *Order, err error) { ... }

func (ob *OrderBook) ProcessMarketOrder(side Side, quantity decimal.Decimal) (done []*Order, partial *Order, quantityLeft decimal.Decimal, err error) { .. }

func (ob *OrderBook) CancelOrder(orderID string) *Order { ... }

About primary functions

ProcessLimitOrder

// ProcessLimitOrder places new order to the OrderBook
// Arguments:
//      side     - what do you want to do (ob.Sell or ob.Buy)
//      orderID  - unique order ID in depth
//      quantity - how much quantity you want to sell or buy
//      price    - no more expensive (or cheaper) this price
//      * to create new decimal number you should use decimal.New() func
//        read more at https://github.com/shopspring/decimal
// Return:
//      error   - not nil if quantity (or price) is less or equal 0. Or if order with given ID is exists
//      done    - not nil if your order produces ends of anoter order, this order will add to
//                the "done" slice. If your order have done too, it will be places to this array too
//      partial - not nil if your order has done but top order is not fully done. Or if your order is
//                partial done and placed to the orderbook without full quantity - partial will contain
//                your order with quantity to left
//      partialQuantityProcessed - if partial order is not nil this result contains processed quatity from partial order
func (ob *OrderBook) ProcessLimitOrder(side Side, orderID string, quantity, price decimal.Decimal) (done []*Order, partial *Order, err error) { ... }

For example:

ProcessLimitOrder(ob.Sell, "uinqueID", decimal.New(55, 0), decimal.New(100, 0))

asks: 110 -> 5      110 -> 5
      100 -> 1      100 -> 56
--------------  ->  --------------
bids: 90  -> 5      90  -> 5
      80  -> 1      80  -> 1

done    - nil
partial - nil

ProcessLimitOrder(ob.Buy, "uinqueID", decimal.New(7, 0), decimal.New(120, 0))

asks: 110 -> 5
      100 -> 1
--------------  ->  --------------
bids: 90  -> 5      120 -> 1
      80  -> 1      90  -> 5
                    80  -> 1

done    - 2 (or more orders)
partial - uinqueID order

ProcessLimitOrder(ob.Buy, "uinqueID", decimal.New(3, 0), decimal.New(120, 0))

asks: 110 -> 5
      100 -> 1      110 -> 3
--------------  ->  --------------
bids: 90  -> 5      90  -> 5
      80  -> 1      90  -> 5

done    - 1 order with 100 price, (may be also few orders with 110 price) + uinqueID order
partial - 1 order with price 110

ProcessMarketOrder

// ProcessMarketOrder immediately gets definite quantity from the order book with market price
// Arguments:
//      side     - what do you want to do (ob.Sell or ob.Buy)
//      quantity - how much quantity you want to sell or buy
//      * to create new decimal number you should use decimal.New() func
//        read more at https://github.com/shopspring/decimal
// Return:
//      error        - not nil if price is less or equal 0
//      done         - not nil if your market order produces ends of anoter orders, this order will add to
//                     the "done" slice
//      partial      - not nil if your order has done but top order is not fully done
//      partialQuantityProcessed - if partial order is not nil this result contains processed quatity from partial order
//      quantityLeft - more than zero if it is not enought orders to process all quantity
func (ob *OrderBook) ProcessMarketOrder(side Side, quantity decimal.Decimal) (done []*Order, partial *Order, quantityLeft decimal.Decimal, err error) { .. }

For example:

ProcessMarketOrder(ob.Sell, decimal.New(6, 0))

asks: 110 -> 5      110 -> 5
      100 -> 1      100 -> 1
--------------  ->  --------------
bids: 90  -> 5      80 -> 1
      80  -> 2

done         - 2 (or more orders)
partial      - 1 order with price 80
quantityLeft - 0

ProcessMarketOrder(ob.Buy, decimal.New(10, 0))

asks: 110 -> 5
      100 -> 1
--------------  ->  --------------
bids: 90  -> 5      90  -> 5
      80  -> 1      80  -> 1
                    
done         - 2 (or more orders)
partial      - nil
quantityLeft - 4

CancelOrder

// CancelOrder removes order with given ID from the order book
func (ob *OrderBook) CancelOrder(orderID string) *Order { ... }
CancelOrder("myUinqueID-Sell-1-with-100")

asks: 110 -> 5
      100 -> 1      110 -> 5
--------------  ->  --------------
bids: 90  -> 5      90  -> 5
      80  -> 1      80  -> 1
                    
done         - 2 (or more orders)
partial      - nil
quantityLeft - 4

License

The MIT License (MIT)

See LICENSE and AUTHORS files

Owner
Karlson Lee
Trained as physicist, now software engineer/data scientist, do Go and Python, left Java
Karlson Lee
Comments
  • If matching server crash, orders will be lost ?

    If matching server crash, orders will be lost ?

    Hi,

    Is there a way to recover orders in case of server crashed for some reasons ?

    300k orders processed per second is this right ? What are the characteristics of the server used for that (RAM, Processor etc.) ?

    Thank you

  • ProcessMarketOrder do not have UniqID argument

    ProcessMarketOrder do not have UniqID argument

    Hi,

    Limit order function contain UniqID argument but not ProcessMarketOrder ?

    Generating order ID and pass it to the function is better and let you backup it before returning the final result after matching.

  • Task - add travis file

    Task - add travis file

    Context; We currently have some great tests, but we are not running them everytime when we merge!

    Solution: Add travis CI that automaticlly run tests and linter for us, in order to avoid regression and keep high code quality

    Tests: Tests passing

  • Create Changelog

    Create Changelog

    Context: Previously, we don't have versioning and no documents for documenting changes or compatibility being broken

    Solution: Add changelog and start release cycle process

  • Adding a tabular representation of the orderbook

    Adding a tabular representation of the orderbook

    In some cases, users should see a brief overview of the orderbook. For instance, user A should see the following representation of both the queues in the orderbook:

             Asks (  qty,   price)                              Bids ( qty,   price)
                          2       1.5                                             4     1
                          3       1.8                                              3     0.8
                          3        2                                                2     0.75
    

    In the suggested changes, I have added a MarketView method that delivers the expected info in the map[string]decimal.Decimal in which keys are prices and the values are quantities.

    Why strings as the keys? I used built-in string type rather than decimal.Decimal since the latter creates two objects for very same numbers:

    	a := decimal.NewFromFloat(1)
    	b := decimal.NewFromFloat(1)
    	fmt.Printf("%v and %v are equal? %v\n", a, b, a == b)
            //  1 and 1 are equal? false
    
  • Trying to implement it to a real project

    Trying to implement it to a real project

    Hi

    I wanted to implement it to a real project, but it's a bit complicated.

    Is there a way that for each rotation, I will get this rows: -> Complete result for each BUY orders processed -> Complete result for each SELL orders processed

    Returning both of them no matter it is a BID or ASK.

    SO I can for example update users balance, send notifications via websocket to update orderbook, update database order history etc...

    Your help will be appreciated !

  • Any sample implementation with an Exchange?

    Any sample implementation with an Exchange?

    Thanks for sharing. I wonder if you could share a sample code of an implementation with an exchange for e.g. with Binance Go API. I appreciate if you do.

money and currency formatting for golang

accounting - money and currency formatting for golang accounting is a library for money and currency formatting. (inspired by accounting.js) Quick Sta

Dec 21, 2022
Golang library for querying and parsing OFX

OFXGo OFXGo is a library for querying OFX servers and/or parsing the responses. It also provides an example command-line client to demonstrate the use

Jan 3, 2023
Technical Analysis Library for Golang

Techan TechAn is a technical analysis library for Go! It provides a suite of tools and frameworks to analyze financial data and make trading decisions

Dec 30, 2022
Package to easily consume the Dolarpy API in golang.

dolarpy-go Package to easily consume the Dolarpy API in golang. https://github.com/melizeche/dolarPy - by melizeche Install import "github.com/bitebai

Apr 11, 2022
Go-finproto - a collection of finance-related protocols implemented in Golang

go-finproto go-finproto is a collection of finance-related protocols implemented

Dec 25, 2022
Matching Engine for Limit Order Book in Golang

Go orderbook Improved matching engine written in Go (Golang) Features Standard price-time priority Supports both market and limit orders Supports orde

Dec 22, 2022
A distributed fault-tolerant order book matching engine
A distributed fault-tolerant order book matching engine

Go - Between A distributed fault-tolerant order book matching engine. Features Limit orders Market orders Order book depth Calculate market price for

Dec 24, 2021
an online REST renting book platform which you can authenticate, order, reserve a book in your account.
an online REST renting book platform which you can authenticate, order, reserve a book in your account.

BOOK MAN an online REST renting book platform which you can authenticate, order, reserve a book in your account. it's a microservices project with hig

Jul 22, 2022
A simulation to create an order book.

order-book-demo A simulation to create an order book. Operations The order book will require the following operations Add - Submits and Order Cancel -

Jun 27, 2022
Book Catalogue, Order RESTful API

Book Catalogue, Order RESTful API try on heroku: https://pacific-island-57943.herokuapp.com Note: '/' endpoint redirect to github repository for docum

Dec 13, 2021
The library solves the task of recalculating the exchange order book

fastme (fast golang matching engine) library Design The library solves the task of recalculating the exchange order book. A classic matching engine co

Aug 10, 2022
Courier Order Provider is a service that receives signals from core server in order to emit this orders to courier groups.

Courier Order Provider Courier Order Provider is a service that receives signals(messages) from core server in order to emit this orders to courier gr

Nov 4, 2021
Andrews-monitor - A Go program to monitor when times were available to order for Brown's Andrews dining hall. Used during the portion of the pandemic when the dining hall was only available for online order.

Andrews Dining Hall Monitor A Go program to monitor when times were available to order for Brown's Andrews dining hall. Used during the portion of the

Jan 1, 2022
fastme - Fast extensible matching engine Go implementation.

fastme (fast golang matching engine) library Design The library solves the task of recalculating the exchange order book. A classic matching engine co

Sep 26, 2022
SizedWaitGroup has the same role and close to the same API as the Golang sync.WaitGroup but it adds a limit on the amount of goroutines started concurrently.

SizedWaitGroup SizedWaitGroup has the same role and API as sync.WaitGroup but it adds a limit of the amount of goroutines started concurrently. SizedW

Jan 8, 2023
A Golang blocking leaky-bucket rate limit implementation

Go rate limiter This package provides a Golang implementation of the leaky-bucket rate limit algorithm. This implementation refills the bucket based o

Jan 2, 2023
Dynamic limit golang

uses channel and a timer goroutine to set a dynamic limit for a process (using timeout rather than hard limit)

Jan 30, 2022
Ratelimit - This package provides a Golang implementation of the leaky-bucket rate limit algorithm

Go rate limiter This package provides a Golang implementation of the leaky-bucke

Jul 26, 2022
An extremely fast Go (golang) HTTP router that supports regular expression route matching. Comes with full support for building RESTful APIs.

ozzo-routing You may consider using go-rest-api to jumpstart your new RESTful applications with ozzo-routing. Description ozzo-routing is a Go package

Dec 31, 2022
agrep-like fuzzy matching, but made faster using Golang and precomputation.

goagrep There are situations where you want to take the user's input and match a primary key in a database. But, immediately a problem is introduced:

Oct 8, 2022