orderbook

package module
v0.2.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 16, 2019 License: MIT Imports: 10 Imported by: 0

README

Go orderbook

Improved matching engine written in Go (Golang)

Go Report Card GoDoc gocover.run 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

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidQuantity      = errors.New("orderbook: invalid order quantity")
	ErrInvalidPrice         = errors.New("orderbook: invalid order price")
	ErrOrderExists          = errors.New("orderbook: order already exists")
	ErrOrderNotExists       = errors.New("orderbook: order does not exist")
	ErrInsufficientQuantity = errors.New("orderbook: insufficient quantity to calculate price")
)

OrderBook erros

Functions

This section is empty.

Types

type Order

type Order struct {
	// contains filtered or unexported fields
}

Order strores information about request

func NewOrder

func NewOrder(orderID string, side Side, quantity, price decimal.Decimal, timestamp time.Time) *Order

NewOrder creates new constant object Order

func (*Order) ID

func (o *Order) ID() string

ID returns orderID field copy

func (*Order) MarshalJSON added in v0.1.0

func (o *Order) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler interface

func (*Order) Price

func (o *Order) Price() decimal.Decimal

Price returns price field copy

func (*Order) Quantity

func (o *Order) Quantity() decimal.Decimal

Quantity returns quantity field copy

func (*Order) Side

func (o *Order) Side() Side

Side returns side of the order

func (*Order) String

func (o *Order) String() string

String implements Stringer interface

func (*Order) Time

func (o *Order) Time() time.Time

Time returns timestamp field copy

func (*Order) UnmarshalJSON added in v0.1.0

func (o *Order) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler interface

type OrderBook

type OrderBook struct {
	// contains filtered or unexported fields
}

OrderBook implements standard matching algorithm

func NewOrderBook

func NewOrderBook() *OrderBook

NewOrderBook creates Orderbook object

func (*OrderBook) CalculateMarketPrice added in v0.1.0

func (ob *OrderBook) CalculateMarketPrice(side Side, quantity decimal.Decimal) (price decimal.Decimal, err error)

CalculateMarketPrice returns total market price for requested quantity if err is not nil price returns total price of all levels in side

func (*OrderBook) CancelOrder

func (ob *OrderBook) CancelOrder(orderID string) *Order

CancelOrder removes order with given ID from the order book

func (*OrderBook) Depth added in v0.2.1

func (ob *OrderBook) Depth() (asks, bids []*PriceLevel)

Depth returns price levels and volume at price level

func (*OrderBook) MarshalJSON added in v0.1.0

func (ob *OrderBook) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler interface

func (*OrderBook) Order added in v0.2.1

func (ob *OrderBook) Order(orderID string) *Order

Order returns order by id

func (*OrderBook) ProcessLimitOrder

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

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 (*OrderBook) ProcessMarketOrder

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

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 (*OrderBook) String

func (ob *OrderBook) String() string

String implements fmt.Stringer interface

func (*OrderBook) UnmarshalJSON added in v0.1.0

func (ob *OrderBook) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler interface

type OrderQueue

type OrderQueue struct {
	// contains filtered or unexported fields
}

OrderQueue stores and manage chain of orders

func NewOrderQueue

func NewOrderQueue(price decimal.Decimal) *OrderQueue

NewOrderQueue creates and initialize OrderQueue object

func (*OrderQueue) Append

func (oq *OrderQueue) Append(o *Order) *list.Element

Append adds order to tail of the queue

func (*OrderQueue) Head

func (oq *OrderQueue) Head() *list.Element

Head returns top order in queue

func (*OrderQueue) Len

func (oq *OrderQueue) Len() int

Len returns amount of orders in queue

func (*OrderQueue) MarshalJSON added in v0.1.0

func (oq *OrderQueue) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler interface

func (*OrderQueue) Price

func (oq *OrderQueue) Price() decimal.Decimal

Price returns price level of the queue

func (*OrderQueue) Remove

func (oq *OrderQueue) Remove(e *list.Element) *Order

Remove removes order from the queue and link order chain

func (*OrderQueue) String

func (oq *OrderQueue) String() string

String implements fmt.Stringer interface

func (*OrderQueue) Tail

func (oq *OrderQueue) Tail() *list.Element

Tail returns bottom order in queue

func (*OrderQueue) UnmarshalJSON added in v0.1.0

func (oq *OrderQueue) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler interface

func (*OrderQueue) Update

func (oq *OrderQueue) Update(e *list.Element, o *Order) *list.Element

Update sets up new order to list value

func (*OrderQueue) Volume

func (oq *OrderQueue) Volume() decimal.Decimal

Volume returns total orders volume

type OrderSide

type OrderSide struct {
	// contains filtered or unexported fields
}

OrderSide implements facade to operations with order queue

func NewOrderSide

func NewOrderSide() *OrderSide

NewOrderSide creates new OrderSide manager

func (*OrderSide) Append

func (os *OrderSide) Append(o *Order) *list.Element

Append appends order to definite price level

func (*OrderSide) Depth

func (os *OrderSide) Depth() int

Depth returns depth of market

func (*OrderSide) GreaterThan added in v0.1.0

func (os *OrderSide) GreaterThan(price decimal.Decimal) *OrderQueue

GreaterThan returns nearest OrderQueue with price greater than given

func (*OrderSide) Len

func (os *OrderSide) Len() int

Len returns amount of orders

func (*OrderSide) LessThan added in v0.1.0

func (os *OrderSide) LessThan(price decimal.Decimal) *OrderQueue

LessThan returns nearest OrderQueue with price less than given

func (*OrderSide) MarshalJSON added in v0.1.0

func (os *OrderSide) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler interface

func (*OrderSide) MaxPriceQueue

func (os *OrderSide) MaxPriceQueue() *OrderQueue

MaxPriceQueue returns maximal level of price

func (*OrderSide) MinPriceQueue

func (os *OrderSide) MinPriceQueue() *OrderQueue

MinPriceQueue returns maximal level of price

func (*OrderSide) Orders added in v0.1.0

func (os *OrderSide) Orders() (orders []*list.Element)

Orders returns all of *list.Element orders

func (*OrderSide) Remove

func (os *OrderSide) Remove(e *list.Element) *Order

Remove removes order from definite price level

func (*OrderSide) String

func (os *OrderSide) String() string

String implements fmt.Stringer interface

func (*OrderSide) UnmarshalJSON added in v0.1.0

func (os *OrderSide) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler interface

func (*OrderSide) Volume added in v0.1.0

func (os *OrderSide) Volume() decimal.Decimal

Volume returns total amount of quantity in side

type PriceLevel added in v0.2.1

type PriceLevel struct {
	Price    decimal.Decimal `json:"price"`
	Quantity decimal.Decimal `json:"quantity"`
}

PriceLevel contains price and volume in depth

type Side

type Side int

Side of the order

const (
	Sell Side = iota
	Buy
)

Sell (asks) or Buy (bids)

func (Side) MarshalJSON added in v0.1.0

func (s Side) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler interface

func (Side) String

func (s Side) String() string

String implements fmt.Stringer interface

func (*Side) UnmarshalJSON added in v0.1.0

func (s *Side) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler interface

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL