CoinIndexAgency / hft-limit-order-book

Ultra-fast Node.js Limit Order Book for high-frequency trading (HFT) :rocket::rocket:

Home Page:https://github.com/fasenderos/hft-limit-order-book

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NPM Version Package License NPM Downloads CircleCI Codecov Built with TypeScript

Initially ported from Go orderbook, this order book has been enhanced with new features

hft-limit-order-book

⭐ Star me on GitHub — it motivates me a lot!

Ultra-fast matching engine written in Javascript

Features

  • Standard price-time priority
  • Supports both market and limit orders
  • Supports time in force GTC, FOK and IOC
  • Supports order cancelling
  • Supports order price and/or size updating
  • High performance (above 300k trades per second)

Machine: ASUS ExpertBook, 11th Gen Intel(R) Core(TM) i7-1165G7, 2.80Ghz, 16GB RAM, Node.js v18.4.0.

hft-limit-order-book-benchmark

Installation

Install with npm:

npm install hft-limit-order-book --save

Install with yarn:

yarn add hft-limit-order-book

Usage

To start using order book you need to import OrderBook and create new instance:

import { OrderBook } from 'hft-limit-order-book'

const lob = new OrderBook()

Then you'll be able to use next primary functions:

lob.createOrder(type: 'limit' | 'market', side: 'buy' | 'sell', size: number, price: number, orderID: string)

lob.limit(side: 'buy' | 'sell', orderID: string, size: number, price: number);

lob.market(side: 'buy' | 'sell', size: number);

lob.modify(orderID: string, { side: 'buy' | 'sell', size: number, price: number });

lob.cancel(orderID: string);

About primary functions

To add an order to the order book you can call the general createOrder() function or calling the underlying limit() or market() functions

Create Order

// Create a limit order
createOrder('limit', side: 'buy' | 'sell', size: number, price: number, orderID: string);

// Create a market order
createOrder('market', side: 'buy' | 'sell', size: number);

Create Limit Order

// Places new limit 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

limit(side: 'buy' | 'sell', orderID: string, size: number, price: number);

For example:

limit("sell", "uinqueID", 55, 100);

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

done    - nil
partial - nil
limit("buy", "uinqueID", 7, 120);

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

done    - 2 (or more orders)
partial - uinqueID order
limit("buy", "uinqueID", 3, 120);

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

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

Create Market Order

// Places new market order to the OrderBook. 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

market(side: 'buy' | 'sell', size: number);

For example:

market('sell', 6);

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
market('buy', 10);

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

done         - 2 (or more orders)
partial      - nil
quantityLeft - 4

Modify an existing order

// Modify an existing order with given ID
modify(orderID: string, { side: 'buy' | 'sell', size: number, price: number });

For example:

limit("sell", "uinqueID", 55, 100);

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

// Modify the size from 55 to 65
modify("uinqueID", { side: "sell", size: 65, price: 100 })

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


// Modify the price from 100 to 110
modify("uinqueID", { side: "sell", size: 65, price: 110 })

asks: 110 -> 5
      100 -> 66     110 -> 71
--------------  ->  --------------
bids: 90  -> 5      90  -> 5
      80  -> 1      80  -> 1

Cancel Order

// Removes order with given ID from the order book
cancel(orderID: string);

For example:

cancel("myUniqueID-Sell-1-with-100")

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

Development

Build

Build production (distribution) files in your dist folder:

npm run build

Testing

To run all the unit-test

npm run test

Coverage

Run testing coverage

npm run test:cov

Benchmarking

Before running benchmark, make sure to have builded the source code with npm run build first

npm run bench

Contributing

I would greatly appreciate any contributions to make this project better. Please make sure to follow the below guidelines before getting your hands dirty.

  1. Fork the repository
  2. Create your branch (git checkout -b my-branch)
  3. Commit any changes to your branch
  4. Push your changes to your remote branch
  5. Open a pull request

Donation

If this project help you reduce time to develop, you can give me a cup of coffee 🍵 :)

ETH: 0xEE45AA08D65352d49344f42d9E0EAf14AA3D812d

License

Copyright Andrea Fassina, Licensed under MIT.

About

Ultra-fast Node.js Limit Order Book for high-frequency trading (HFT) :rocket::rocket:

https://github.com/fasenderos/hft-limit-order-book

License:MIT License


Languages

Language:TypeScript 82.5%Language:JavaScript 16.8%Language:Shell 0.8%