Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

server/book: automatic book reallocation #794

Merged
merged 1 commit into from Nov 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 10 additions & 29 deletions server/book/book.go
Expand Up @@ -12,10 +12,9 @@ import (
)

const (
// DefaultBookHalfCapacity is the default capacity of one side (buy or sell)
// of the order book. It is set to 2^20 orders (1 mebiorders = 1,048,576
// orders) per book side.
DefaultBookHalfCapacity uint32 = 1 << 20
// initBookHalfCapacity is the default capacity of one side (buy or sell) of
// the order book. It is set to 2^16 orders (65536 orders) per book side.
initBookHalfCapacity uint32 = 1 << 16
)

// Book is a market's order book. The Book uses a configurable lot size, of
Expand All @@ -26,42 +25,25 @@ const (
type Book struct {
mtx sync.RWMutex
lotSize uint64
halfCap uint32
buys *OrderPQ
sells *OrderPQ
}

// New creates a new order book with the given lot size, and optional order
// capacity of each side of the book. To change capacity of an existing Book,
// use the Realloc method.
func New(lotSize uint64, halfCapacity ...uint32) *Book {
halfCap := DefaultBookHalfCapacity
if len(halfCapacity) > 0 {
halfCap = halfCapacity[0]
}
// New creates a new order book with the given lot size.
func New(lotSize uint64) *Book {
return &Book{
lotSize: lotSize,
halfCap: halfCap,
buys: NewMaxOrderPQ(halfCap),
sells: NewMinOrderPQ(halfCap),
buys: NewMaxOrderPQ(initBookHalfCapacity),
sells: NewMinOrderPQ(initBookHalfCapacity),
}
}

// Clear reset the order book with configured capacity.
func (b *Book) Clear() {
b.mtx.Lock()
b.buys, b.sells = nil, nil
chappjc marked this conversation as resolved.
Show resolved Hide resolved
b.buys = NewMaxOrderPQ(b.halfCap)
b.sells = NewMinOrderPQ(b.halfCap)
b.mtx.Unlock()
}

// Realloc changes the capacity of the order book given the specified capacity
// of both buy and sell sides of the book.
func (b *Book) Realloc(newHalfCap uint32) {
b.mtx.Lock()
b.buys.Realloc(newHalfCap)
b.sells.Realloc(newHalfCap)
b.buys = NewMaxOrderPQ(initBookHalfCapacity)
b.sells = NewMinOrderPQ(initBookHalfCapacity)
b.mtx.Unlock()
}

Expand Down Expand Up @@ -107,8 +89,7 @@ func (b *Book) Best() (bestBuy, bestSell *order.LimitOrder) {
// integer multiple of the Book's lot size, the order will not be inserted.
func (b *Book) Insert(o *order.LimitOrder) bool {
if o.Quantity%b.lotSize != 0 {
log.Warnf("(*Book).Insert: Refusing to insert an order with a " +
"quantity that is not a multiple of lot size.")
log.Warnf("(*Book).Insert: Refusing to insert an order with a quantity that is not a multiple of lot size.")
return false
}
b.mtx.Lock()
Expand Down
6 changes: 4 additions & 2 deletions server/book/book_test.go
Expand Up @@ -91,7 +91,7 @@ var (
func newBook(t *testing.T) *Book {
resetMakers()

b := New(LotSize, DefaultBookHalfCapacity)
b := New(LotSize)

for _, o := range bookBuyOrders {
if ok := b.Insert(o); !ok {
Expand Down Expand Up @@ -156,7 +156,9 @@ func TestBook(t *testing.T) {
len(buys), b.BuyCount())
}

b.Realloc(DefaultBookHalfCapacity * 2)
// Hit the OrderPQ's Realloc function manually.
b.buys.realloc(initBookHalfCapacity * 2)
b.sells.realloc(initBookHalfCapacity * 2)

buys2 := b.BuyOrders()
if len(buys) != len(buys2) {
Expand Down