github.com/diadata-org/diadata@v1.4.593/pkg/dia/Trade.go (about) 1 package dia 2 3 import ( 4 "errors" 5 "fmt" 6 "strconv" 7 "strings" 8 "time" 9 10 "github.com/zekroTJA/timedmap" 11 ) 12 13 // GetBaseToken returns the base token of a trading pair 14 // TO DO (20/11/2020): This method is no longer needed once we switch to new Token/Trade structs 15 func (t *Trade) GetBaseToken() string { 16 17 if t.BaseToken.Symbol != "" { 18 return t.BaseToken.Symbol 19 } 20 21 pair := strings.ToUpper(t.Pair) 22 if len(pair) > 3 { 23 switch t.Source { 24 case KrakenExchange: 25 if pair[len(pair)-3:] == "XBT" { 26 return "BTC" 27 } 28 case BitfinexExchange: 29 if pair[len(pair)-3:] == "USD" { 30 return "USDT" 31 } 32 case HitBTCExchange: 33 if pair[len(pair)-3:] == "USD" { 34 return "USDT" 35 } 36 } 37 } 38 39 second := strings.TrimPrefix(pair, strings.ToUpper(t.Symbol)+"_") 40 if second != pair { 41 return second 42 } 43 second = strings.TrimPrefix(pair, strings.ToUpper(t.Symbol)+"-") 44 if second != pair { 45 return second 46 } 47 second = strings.TrimPrefix(pair, strings.ToUpper(t.Symbol)+"/") 48 if second != pair { 49 return second 50 } 51 52 return strings.TrimPrefix(pair, strings.ToUpper(t.Symbol)) 53 } 54 55 // SwapTrade swaps base and quote token of a trade and inverts the price accordingly 56 func SwapTrade(t Trade) (Trade, error) { 57 if t.Price == 0 { 58 return t, errors.New("zero price. cannot swap trade") 59 } 60 t.BaseToken, t.QuoteToken = t.QuoteToken, t.BaseToken 61 t.Symbol = t.QuoteToken.Symbol 62 t.Pair = t.QuoteToken.Symbol + "-" + t.BaseToken.Symbol 63 t.Volume = -t.Price * t.Volume 64 t.Price = 1 / t.Price 65 66 return t, nil 67 } 68 69 // IdentifyDuplicateFull returns true in case a trade is fully identical to one stored in the timed map @falseDuplicateTrades. 70 func (t *Trade) IdentifyDuplicateFull(falseDuplicateTrades *timedmap.TimedMap, memory time.Duration) (discardTrade bool) { 71 if _, ok := falseDuplicateTrades.GetValue(t.TradeIdentifierFull()).(int); !ok { 72 falseDuplicateTrades.Set(t.TradeIdentifierFull(), 1, memory) 73 } else { 74 discardTrade = true 75 } 76 return 77 } 78 79 // IdentifyDuplicateTagset identifies trades with identical timestamps and tagsets and add a Nanosecond to 80 // the timestamp in order for the trade not to be overwritten in Influx. 81 func (t *Trade) IdentifyDuplicateTagset(duplicateTrades *timedmap.TimedMap, memory time.Duration) { 82 if val, ok := duplicateTrades.GetValue(t.TradeIdentifierTagset()).(int); !ok { 83 duplicateTrades.Set(t.TradeIdentifierTagset(), 1, memory) 84 } else { 85 // Set trade identifier as key with value incremented. 86 duplicateTrades.Set(t.TradeIdentifierTagset(), val+1, memory) 87 // Add old value as Nanosecond to trade time. 88 t.Time = t.Time.Add(time.Duration(val) * time.Nanosecond) 89 } 90 } 91 92 // TradeIdentifierFull returns an identifier with respect to all fields of a trade. 93 func (t *Trade) TradeIdentifierFull() string { 94 timeString := strconv.Itoa(int(t.Time.UnixNano())) 95 priceString := fmt.Sprintf("%f", t.Price) 96 volumeString := fmt.Sprintf("%f", t.Volume) 97 return timeString + 98 priceString + 99 volumeString + 100 t.ForeignTradeID + 101 t.Source + 102 t.QuoteToken.Address + 103 t.QuoteToken.Blockchain + 104 t.BaseToken.Address + 105 t.BaseToken.Blockchain 106 } 107 108 // TradeIdentifierTagset returns an identifier with respect to the tagset of a trade in Influx. 109 // In other words, a trade with this same tagset is overwritten in Influx trades table. 110 func (t *Trade) TradeIdentifierTagset() string { 111 timeString := strconv.Itoa(int(t.Time.UnixNano())) 112 return timeString + 113 t.Symbol + 114 t.Pair + 115 t.Source + 116 t.QuoteToken.Address + 117 t.QuoteToken.Blockchain + 118 t.BaseToken.Address + 119 t.BaseToken.Blockchain 120 }