-
Notifications
You must be signed in to change notification settings - Fork 0
/
swiper.go
123 lines (98 loc) · 2.21 KB
/
swiper.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 main
import (
"fmt"
"sync"
)
var (
DefaultConfig = Config{
CopyOnFetcher: true,
CopycatClients: nil,
Ratio: 4,
}
)
type Config struct {
CopyOnFetcher bool
CopycatClients []Client
Ratio float64
}
type Swiper struct {
mu sync.Mutex
client Client
config Config
lastTickOrders map[string]*Order
}
func NewSwiper(client Client, config *Config) *Swiper {
if config == nil {
config = &DefaultConfig
}
s := &Swiper{
client: client,
config: *config,
}
return s
}
func (s *Swiper) Run() (map[*Order][]*Order, error) {
s.mu.Lock()
defer s.mu.Unlock()
orders, err := s.client.ClosedOrders()
if err != nil {
return nil, fmt.Errorf("cannot get closed orders: %s", err.Error())
}
newOrders := s.findNewOrders(orders)
s.lastTickOrders = orders
result, err := s.copy(newOrders)
if err != nil {
return nil, fmt.Errorf("cannot process new orders: %s", err.Error())
}
return result, nil
}
func (s *Swiper) findNewOrders(orders map[string]*Order) []*Order {
var newOrders []*Order
if len(s.lastTickOrders) == 0 {
return newOrders
}
for index, order := range orders {
if s.lastTickOrders[index] == nil {
newOrders = append(newOrders, order)
}
}
return newOrders
}
func makeCopyOrder(order *Order, ratio float64) *Order {
return &Order{
Symbol: order.Symbol,
Type: order.Type,
Quantity: order.Quantity * ratio,
Side: order.Side,
}
}
func (s *Swiper) copy(orders []*Order) (map[*Order][]*Order, error) {
res := make(map[*Order][]*Order, len(orders))
// TODO: parallelize this with chan
for _, order := range orders {
copyOrders, err := s.sendOrder(makeCopyOrder(order, s.config.Ratio))
if err != nil {
return nil, err
}
res[order] = copyOrders
}
return res, nil
}
func (s *Swiper) sendOrder(order *Order) ([]*Order, error) {
var copyOrders []*Order
if s.config.CopyOnFetcher {
copyOrder, err := s.client.NewOrder(order)
if err != nil {
return nil, err
}
copyOrders = append(copyOrders, copyOrder)
}
for _, client := range s.config.CopycatClients {
copyOrder, err := client.NewOrder(order)
if err != nil {
return nil, err
}
copyOrders = append(copyOrders, copyOrder)
}
return copyOrders, nil
}