/
matcher.go
134 lines (104 loc) · 3.5 KB
/
matcher.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
package main
type Matcher struct {
orderbooks map[string]map[string]*Orderbook
symbols map[string]bool
bcs *Blockchains
matchCh chan Match
updated bool
}
func StartMatcher(bcs *Blockchains, matchCh chan Match) (matcher *Matcher) {
orderbooks := make(map[string]map[string]*Orderbook)
symbols := make(map[string]bool)
if bcs != nil {
Log("Starting order matcher")
matcher = &Matcher{orderbooks, symbols, bcs, nil, false}
} else {
Log("Simulating order matcher")
matcher = &Matcher{orderbooks, symbols, nil, matchCh, false}
}
return matcher
}
func (mr *Matcher) AddOrder(order Order, sellSymbol string) {
buySymbol := order.BuySymbol
Log("Adding order %v to %s", order.ID, GetBookName(buySymbol, sellSymbol))
orderbook := mr.getOrderbook(buySymbol, sellSymbol)
orderbook.Add(&order, sellSymbol)
}
func (mr *Matcher) AddCancelOrder(cancelOrder CancelOrder, sellSymbol string) {
//TODO
}
func (mr *Matcher) RemoveOrder(order Order, sellSymbol string) {
buySymbol := order.BuySymbol
Log("Removing order %v from %s", order.ID, GetBookName(buySymbol, sellSymbol))
orderbook := mr.getOrderbook(buySymbol, sellSymbol)
orderbook.Cancel(&order, sellSymbol)
}
func (mr *Matcher) AddMatch(match Match) {
Log("Adding match %v/%v to %s", match.BuyOrderID, match.SellOrderID, GetBookName(match.BuySymbol, match.SellSymbol))
orderbook := mr.getOrderbook(match.BuySymbol, match.SellSymbol)
orderbook.ApplyMatch(&match)
}
// TODO: vanish amt argument
func (mr *Matcher) RemoveMatch(match Match, buyOrder Order, sellOrder Order) {
Log("Removing match %v/%v from %s", match.BuyOrderID, match.SellOrderID, GetBookName(match.BuySymbol, match.SellSymbol))
orderbook := mr.getOrderbook(match.BuySymbol, match.SellSymbol)
orderbook.UnapplyMatch(&match, &buyOrder, &sellOrder)
}
func (mr *Matcher) RemoveCancelOrder(cancelOrder CancelOrder) {
//TODO:
}
func (mr *Matcher) CheckMatch(orderbook *Orderbook) {
found, match := orderbook.FindMatch()
if found {
Log("Found match on %s/%s: %v/%v", orderbook.QuoteSymbol, orderbook.BaseSymbol, match.BuyOrderID, match.SellOrderID)
mr.returnMatch(match)
}
}
func (mr *Matcher) FindAllMatches() {
Log("Finding all matches")
for baseSymbol, baseBooks := range mr.orderbooks {
for quoteSymbol, orderbook := range baseBooks {
if !orderbook.Dirty {
continue
}
Log("%s is dirty", GetBookName(baseSymbol, quoteSymbol))
orderbook.Dirty = false
matches := orderbook.FindAllMatches()
for _, match := range matches {
mr.returnMatch(match)
}
}
}
}
func (mr *Matcher) returnMatch(match *Match) {
if mr.bcs != nil {
tx := GenericTransaction{*match, MATCH}
mr.bcs.AddTransactionToMempool(tx, MATCH_CHAIN, true)
} else {
mr.AddMatch(*match)
mr.matchCh <- *match
}
}
func (mr *Matcher) SerializeOrderbook(symbol1, symbol2 string) string {
orderbook := mr.getOrderbook(symbol1, symbol2)
return orderbook.Serial()
}
func (mr *Matcher) addSymbol(newSymbol string) {
Log("Adding symbol %s to matcher", newSymbol)
mr.orderbooks[newSymbol] = make(map[string]*Orderbook)
for oldSymbol := range mr.symbols {
base, quote := GetBaseQuote(newSymbol, oldSymbol)
mr.orderbooks[base][quote] = NewOrderbook(base, quote)
}
mr.symbols[newSymbol] = true
}
func (mr *Matcher) getOrderbook(symbol1, symbol2 string) *Orderbook {
if _, exists := mr.symbols[symbol1]; !exists {
mr.addSymbol(symbol1)
}
if _, exists := mr.symbols[symbol2]; !exists {
mr.addSymbol(symbol2)
}
base, quote := GetBaseQuote(symbol1, symbol2)
return mr.orderbooks[base][quote]
}