-
Notifications
You must be signed in to change notification settings - Fork 153
/
order.go
151 lines (128 loc) · 3.52 KB
/
order.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package orderbook
import (
"encoding/json"
"fmt"
"time"
"github.com/shopspring/decimal"
)
// Order strores information about request
type Order struct {
side Side
id string
timestamp time.Time
quantity decimal.Decimal
price decimal.Decimal
}
// MarketView represents order book in a glance
type MarketView struct {
Asks map[string]decimal.Decimal `json:"asks"`
Bids map[string]decimal.Decimal `json:"bids"`
}
// NewOrder creates new constant object Order
func NewOrder(orderID string, side Side, quantity, price decimal.Decimal, timestamp time.Time) *Order {
return &Order{
id: orderID,
side: side,
quantity: quantity,
price: price,
timestamp: timestamp,
}
}
// ID returns orderID field copy
func (o *Order) ID() string {
return o.id
}
// Side returns side of the order
func (o *Order) Side() Side {
return o.side
}
// Quantity returns quantity field copy
func (o *Order) Quantity() decimal.Decimal {
return o.quantity
}
// Price returns price field copy
func (o *Order) Price() decimal.Decimal {
return o.price
}
// Time returns timestamp field copy
func (o *Order) Time() time.Time {
return o.timestamp
}
// String implements Stringer interface
func (o *Order) String() string {
return fmt.Sprintf("\n\"%s\":\n\tside: %s\n\tquantity: %s\n\tprice: %s\n\ttime: %s\n", o.ID(), o.Side(), o.Quantity(), o.Price(), o.Time())
}
// MarshalJSON implements json.Marshaler interface
func (o *Order) MarshalJSON() ([]byte, error) {
return json.Marshal(
&struct {
S Side `json:"side"`
ID string `json:"id"`
Timestamp time.Time `json:"timestamp"`
Quantity decimal.Decimal `json:"quantity"`
Price decimal.Decimal `json:"price"`
}{
S: o.Side(),
ID: o.ID(),
Timestamp: o.Time(),
Quantity: o.Quantity(),
Price: o.Price(),
},
)
}
// UnmarshalJSON implements json.Unmarshaler interface
func (o *Order) UnmarshalJSON(data []byte) error {
obj := struct {
S Side `json:"side"`
ID string `json:"id"`
Timestamp time.Time `json:"timestamp"`
Quantity decimal.Decimal `json:"quantity"`
Price decimal.Decimal `json:"price"`
}{}
if err := json.Unmarshal(data, &obj); err != nil {
return err
}
o.side = obj.S
o.id = obj.ID
o.timestamp = obj.Timestamp
o.quantity = obj.Quantity
o.price = obj.Price
return nil
}
// GetOrderSide gets the orderside along with its orders in one side of the market
func (ob *OrderBook) GetOrderSide(side Side) *OrderSide {
switch side {
case Buy:
return ob.bids
default:
return ob.asks
}
}
// MarketOverview gives an overview of the market including the quantities and prices of each side in the market
// asks: qty price bids: qty price
// 0.2 14 0.9 13
// 0.1 14.5 5 14
// 0.8 16 2 16
func (ob *OrderBook) MarketOverview() *MarketView {
return &MarketView{
Asks: compileOrders(ob.asks),
Bids: compileOrders(ob.bids),
}
}
// compileOrders compiles orders in the following format
func compileOrders(orders *OrderSide) map[string]decimal.Decimal {
// show queue
queue := make(map[string]decimal.Decimal)
if orders != nil {
level := orders.MaxPriceQueue()
for level != nil {
if q, exists := queue[level.Price().String()]; exists {
queue[level.Price().String()] = q.Add(level.Volume())
} else {
queue[level.Price().String()] = level.Volume()
}
level = orders.LessThan(level.Price())
}
}
return queue
}