-
Notifications
You must be signed in to change notification settings - Fork 4
/
stopbook.go
123 lines (98 loc) · 2.15 KB
/
stopbook.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package matchingo
import (
"fmt"
"strings"
"github.com/nikolaydubina/fpdecimal"
)
// StopBook implements facade to operations with Stop Orders
type StopBook struct {
prices map[string]*OrderQueue
orders map[string]*Order
numOrders int
}
// NewStopBook creates new OrderSide manager
func NewStopBook() *StopBook {
return &StopBook{
prices: map[string]*OrderQueue{},
orders: map[string]*Order{},
}
}
// Len returns amount of Orders
func (sb *StopBook) Len() int {
return sb.numOrders
}
// Append appends Order to definite Price level
func (sb *StopBook) Append(o *Order) {
_, ok := sb.orders[o.ID()]
if ok {
return
}
price := o.StopPrice()
strPrice := price.String()
priceQueue, ok := sb.prices[strPrice]
if !ok {
priceQueue = NewOrderQueue(price)
sb.prices[strPrice] = priceQueue
}
priceQueue.Append(o)
sb.orders[o.ID()] = o
sb.numOrders++
}
// Activate Orders by Stop Price
func (sb *StopBook) Activate(price fpdecimal.Decimal) []Order {
strPrice := price.String()
priceQueue, ok := sb.prices[strPrice]
if !ok {
return nil
}
slice := priceQueue.Slice()
if priceQueue.Len() == 0 {
delete(sb.prices, strPrice)
}
sb.numOrders = sb.numOrders - len(slice)
return slice
}
// Remove removes Order from definite Price level
func (sb *StopBook) Remove(order *Order) *Order {
price := order.StopPrice().String()
priceQueue := sb.prices[price]
priceQueue.Remove(order)
if priceQueue.Len() == 0 {
delete(sb.prices, price)
}
sb.numOrders--
return order
}
// RemoveByID removes Order by ID
func (sb *StopBook) RemoveByID(id string) *Order {
order, ok := sb.orders[id]
if !ok {
return nil
}
price := order.StopPrice()
strPrice := price.String()
priceQueue, ok := sb.prices[strPrice]
if ok {
priceQueue.Remove(order)
if priceQueue.Len() == 0 {
delete(sb.prices, strPrice)
}
}
delete(sb.orders, id)
sb.numOrders--
return order
}
// String implements fmt.Stringer interface
func (sb *StopBook) String() string {
builder := strings.Builder{}
for price, queue := range sb.prices {
builder.WriteString(
fmt.Sprintf(
"\n%s -> size: %d",
price,
queue.Len(),
),
)
}
return builder.String()
}