/
index_strategy.go
77 lines (62 loc) · 2.36 KB
/
index_strategy.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
package quotes
import (
"time"
"github.com/shopspring/decimal"
"github.com/layer-3/clearsync/pkg/safe"
)
var defaultWeightsMap = map[DriverType]decimal.Decimal{
DriverKraken: decimal.NewFromInt(15),
DriverBinance: decimal.NewFromInt(20),
DriverUniswapV3: decimal.NewFromInt(50),
DriverSyncswap: decimal.NewFromInt(50),
DriverQuickswap: decimal.NewFromInt(50),
DriverSectaV2: decimal.NewFromInt(50),
DriverSectaV3: decimal.NewFromInt(50),
DriverInternal: decimal.NewFromInt(75),
}
type ConfFunc func(*indexStrategy)
type indexStrategy struct {
weights map[DriverType]decimal.Decimal
priceCache *PriceCache
}
// newIndexStrategy creates a new instance of Weighted Price index price calculator.
func newIndexStrategy(configs ...ConfFunc) priceCalculator {
s := indexStrategy{
priceCache: newPriceCache(defaultWeightsMap, 20, 15*time.Minute),
weights: defaultWeightsMap,
}
for _, conf := range configs {
conf(&s)
}
return s
}
// WithCustomWeights configures custom drivers weights. Should be passed as an argument to the NewStrategy() constructor.
func WithCustomWeights(driversWeights map[DriverType]decimal.Decimal) ConfFunc {
return func(strategy *indexStrategy) {
strategy.weights = driversWeights
strategy.priceCache.weights = safe.NewMapWithData(driversWeights)
}
}
// withCustomPriceCache configures price cache. Should be passed as an argument to the NewStrategy() constructor.
func withCustomPriceCache(priceCache *PriceCache) ConfFunc {
return func(strategy *indexStrategy) { strategy.priceCache = priceCache }
}
// calculateIndexPrice returns indexPrice based on Volume Weighted Average Price of last 20 trades.
func (a indexStrategy) calculateIndexPrice(event TradeEvent) (decimal.Decimal, bool) {
sourceWeight := a.weights[event.Source]
if event.Market.IsEmpty() || event.Price.IsZero() || event.Amount.IsZero() || sourceWeight.IsZero() {
return decimal.Zero, false
}
timeEmpty := time.Time{}
if event.CreatedAt == timeEmpty {
event.CreatedAt = time.Now()
}
a.priceCache.AddTrade(event.Market, event.Price, event.Amount, event.CreatedAt, event.Source)
return a.priceCache.GetIndexPrice(&event)
}
func (a indexStrategy) getLastPrice(market Market) decimal.Decimal {
return a.priceCache.getLastPrice(market)
}
func (a indexStrategy) setLastPrice(market Market, price decimal.Decimal) {
a.priceCache.setLastPrice(market, price)
}