-
Notifications
You must be signed in to change notification settings - Fork 2
/
order_container.go
102 lines (92 loc) · 2.75 KB
/
order_container.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
package tome
import (
"log"
"sort"
)
// Container object that stores bids an asks for a specified instrument.
// It doesn't store Orders, but OrderTrackers (for faster operation)
// Handles fast and efficient insertion, removal, retrieval, sorting and filtering of orders.
type orderContainer struct {
Bids, Asks *orderMap
trackers map[uint64]OrderTracker
}
// Create a new order container with specified LessFuncs.
func NewOrderContainer(bidLess, askLess LessFunc) *orderContainer {
return &orderContainer{
Bids: newOrderMap(bidLess),
Asks: newOrderMap(askLess),
trackers: make(map[uint64]OrderTracker),
}
}
// Add an order tracker.
func (o *orderContainer) Add(tracker OrderTracker) {
if tracker.Side == SideBuy {
o.Bids.Set(tracker, true)
} else {
o.Asks.Set(tracker, true)
}
o.trackers[tracker.OrderID] = tracker
}
// Remove an order tracker.
func (o *orderContainer) Remove(id uint64) {
tracker, ok := o.trackers[id]
if !ok {
log.Printf("cannot remove order: no tracker for id %d", id)
return
}
delete(o.trackers, id)
if tracker.Side == SideBuy {
o.Bids.Del(tracker)
} else {
o.Asks.Del(tracker)
}
}
// Get a tracker by its order ID.
func (o *orderContainer) Get(id uint64) (OrderTracker, bool) {
t, ok := o.trackers[id]
return t, ok
}
// Get an OrderTracker iterator which iterates through sorted bids or asks.
func (o *orderContainer) Iterator(side OrderSide) forwardIteratorOrderMap {
if side == SideBuy {
return o.Bids.Iterator()
}
return o.Asks.Iterator()
}
// Returns the number of bids or asks in the container.
func (o *orderContainer) Len(side OrderSide) int {
if side == SideBuy {
return o.Bids.Len()
}
return o.Asks.Len()
}
// Get ask trackers below or equal the price. Sorted by time ascending.
func (o *orderContainer) GetAsksAbove(price float64) []OrderTracker {
trackers := make([]OrderTracker, 0)
for iter := o.Asks.Iterator(); iter.Valid(); iter.Next() {
if iter.Key().Price >= price {
trackers = append(trackers, iter.Key())
} else {
break // iterator returns a sorted array, if price is bigger we don't have to look any further
}
}
sort.Slice(trackers, func(i, j int) bool {
return trackers[i].Timestamp < trackers[j].Timestamp
})
return trackers
}
// Get bid trackers above or equal the price. Sorted by time ascending.
func (o *orderContainer) GetBidsBelow(price float64) []OrderTracker {
trackers := make([]OrderTracker, 0)
for iter := o.Bids.Iterator(); iter.Valid(); iter.Next() {
if iter.Key().Price <= price {
trackers = append(trackers, iter.Key())
} else {
break // iterator returns a sorted array, if price is bigger we don't have to look any further
}
}
sort.Slice(trackers, func(i, j int) bool {
return trackers[i].Timestamp < trackers[j].Timestamp
})
return trackers
}