github.com/diadata-org/diadata@v1.4.593/internal/pkg/filtersBlockService/FilterVWAP.go (about) 1 package filters 2 3 import ( 4 "math" 5 "strconv" 6 "time" 7 8 "github.com/diadata-org/diadata/pkg/dia" 9 log "github.com/sirupsen/logrus" 10 ) 11 12 // FilterVWAP ... 13 type FilterVWAP struct { 14 asset dia.Asset 15 exchange string 16 currentTime time.Time 17 prices []float64 18 volumes []float64 19 lastTrade dia.Trade 20 param int 21 value float64 22 filterName string 23 nativeDenomination bool 24 modified bool 25 } 26 27 // NewFilterVWAP ... 28 func NewFilterVWAP(asset dia.Asset, exchange string, currentTime time.Time, param int, nativeDenomination bool) *FilterVWAP { 29 s := &FilterVWAP{ 30 asset: asset, 31 exchange: exchange, 32 prices: []float64{}, 33 volumes: []float64{}, 34 currentTime: currentTime, 35 param: param, 36 filterName: "VWAP" + strconv.Itoa(param), 37 nativeDenomination: nativeDenomination, 38 } 39 return s 40 } 41 42 // Compute ... 43 func (s *FilterVWAP) Compute(trade dia.Trade) { 44 s.compute(trade) 45 } 46 47 func (filter *FilterVWAP) compute(trade dia.Trade) { 48 filter.modified = true 49 if filter.lastTrade != (dia.Trade{}) { 50 if trade.Time.Before(filter.currentTime) { 51 log.Errorln("FilterVWAP: Ignoring Trade out of order ", filter.currentTime, trade.Time) 52 return 53 } 54 } 55 filter.fill(trade) 56 filter.lastTrade = trade 57 } 58 59 // fill just adds a trade to the prices and volumes slices. 60 func (filter *FilterVWAP) fill(trade dia.Trade) { 61 // filter.currentTime is the timestamp of the last filled trade. 62 filter.processDataPoint(trade) 63 filter.currentTime = trade.Time 64 } 65 66 func (filter *FilterVWAP) processDataPoint(trade dia.Trade) { 67 if !filter.nativeDenomination { 68 filter.prices = append([]float64{trade.EstimatedUSDPrice}, filter.prices...) 69 } else { 70 filter.prices = append([]float64{trade.Price}, filter.prices...) 71 } 72 filter.volumes = append([]float64{trade.Volume}, filter.volumes...) 73 } 74 75 // FinalCompute ... 76 func (s *FilterVWAP) FinalCompute(t time.Time) float64 { 77 return s.finalCompute(t) 78 } 79 80 func (s *FilterVWAP) finalCompute(t time.Time) float64 { 81 log.Infof("computed value %v at time %v ", s.value, t) 82 if s.lastTrade == (dia.Trade{}) { 83 return 0.0 84 } 85 86 var totalVolume float64 = 0 87 var priceVolume []float64 88 var totalPriceVolume float64 = 0 89 90 for index, price := range s.prices { 91 priceVolume = append(priceVolume, price*math.Abs(s.volumes[index])) 92 } 93 94 for _, v := range s.volumes { 95 totalVolume += math.Abs(v) 96 } 97 98 for _, v := range priceVolume { 99 totalPriceVolume += v 100 } 101 102 if totalVolume > 0 { 103 s.value = totalPriceVolume / totalVolume 104 } 105 106 return s.value 107 } 108 109 // FilterPointForBlock ... 110 func (s *FilterVWAP) FilterPointForBlock() *dia.FilterPoint { 111 return s.filterPointForBlock() 112 } 113 func (s *FilterVWAP) filterPointForBlock() *dia.FilterPoint { 114 if s.exchange != "" { 115 return &dia.FilterPoint{ 116 Value: s.value, 117 Name: "VWAP" + strconv.Itoa(s.param), 118 Time: s.currentTime, 119 Asset: s.asset, 120 } 121 } else { 122 return &dia.FilterPoint{ 123 Value: s.value, 124 Name: "VWAP" + strconv.Itoa(s.param), 125 Time: s.currentTime, 126 Asset: s.asset, 127 } 128 } 129 }