diff --git a/price-feeder/oracle/oracle.go b/price-feeder/oracle/oracle.go index 1b09744399..6654dffa0c 100644 --- a/price-feeder/oracle/oracle.go +++ b/price-feeder/oracle/oracle.go @@ -34,9 +34,11 @@ const ( tickerTimeout = 1000 * time.Millisecond ) -// deviationThreshold defines how many 𝜎 a provider can be away from the mean -// without being considered faulty. -var deviationThreshold = sdk.MustNewDecFromStr("2") +var ( + // deviationThreshold defines how many 𝜎 a provider can be away from the mean + // without being considered faulty. + deviationThreshold = sdk.MustNewDecFromStr("2") +) // PreviousPrevote defines a structure for defining the previous prevote // submitted on-chain. @@ -188,13 +190,13 @@ func (o *Oracle) SetPrices(ctx context.Context, acceptList oracletypes.DenomList g.Go(func() error { prices, err := priceProvider.GetTickerPrices(acceptedPairs...) if err != nil { - telemetry.IncrCounter(1, "failure", "provider") + telemetry.IncrCounter(1, "failure", "provider", "type", "ticker") return err } candles, err := priceProvider.GetCandlePrices(acceptedPairs...) if err != nil { - telemetry.IncrCounter(1, "failure", "provider") + telemetry.IncrCounter(1, "failure", "provider", "type", "candle") return err } @@ -221,11 +223,11 @@ func (o *Oracle) SetPrices(ctx context.Context, acceptList oracletypes.DenomList if !pricesOk && !candlesOk { mtx.Unlock() - return fmt.Errorf("failed to find any exchange rates in provider response") + return fmt.Errorf("failed to find any exchange rates in provider responses") } } - mtx.Unlock() + mtx.Unlock() return nil }) } @@ -239,7 +241,7 @@ func (o *Oracle) SetPrices(ctx context.Context, acceptList oracletypes.DenomList return err } - // attempt to use candles for tvwap calculations + // attempt to use candles for TVWAP calculations tvwapPrices, err := ComputeTVWAP(filteredCandles) if err != nil { return err @@ -397,12 +399,12 @@ func (o *Oracle) filterTickerDeviations( priceMap = make(map[string]map[string]sdk.Dec) ) - for providerName, providerPrices := range prices { + for providerName, priceTickers := range prices { if _, ok := priceMap[providerName]; !ok { priceMap[providerName] = make(map[string]sdk.Dec) } - for base, price := range providerPrices { - priceMap[providerName][base] = price.Price + for base, tp := range priceTickers { + priceMap[providerName][base] = tp.Price } } @@ -413,18 +415,22 @@ func (o *Oracle) filterTickerDeviations( // accept any prices that are within 2𝜎, or for which we couldn't get 𝜎 for providerName, priceTickers := range prices { - for base, ticker := range priceTickers { + for base, tp := range priceTickers { if _, ok := deviations[base]; !ok || - (ticker.Price.GTE(means[base].Sub(deviations[base].Mul(deviationThreshold))) && - ticker.Price.LTE(means[base].Add(deviations[base].Mul(deviationThreshold)))) { + (tp.Price.GTE(means[base].Sub(deviations[base].Mul(deviationThreshold))) && + tp.Price.LTE(means[base].Add(deviations[base].Mul(deviationThreshold)))) { if _, ok := filteredPrices[providerName]; !ok { filteredPrices[providerName] = make(map[string]provider.TickerPrice) } - filteredPrices[providerName][base] = ticker + + filteredPrices[providerName][base] = tp } else { - telemetry.IncrCounter(1, "failure", "provider") - o.logger.Warn().Str("base", base).Str("provider", providerName).Str( - "price", ticker.Price.String()).Msg("provider deviating from other prices") + telemetry.IncrCounter(1, "failure", "provider", "type", "ticker") + o.logger.Warn(). + Str("base", base). + Str("provider", providerName). + Str("price", tp.Price.String()). + Msg("provider deviating from other prices") } } } @@ -442,14 +448,15 @@ func (o *Oracle) filterCandleDeviations( tvwaps = make(map[string]map[string]sdk.Dec) ) - for providerName, c := range candles { + for providerName, priceCandles := range candles { candlePrices := make(provider.AggregatedProviderCandles) - for assetName, asset := range c { + for base, cp := range priceCandles { if _, ok := candlePrices[providerName]; !ok { candlePrices[providerName] = make(map[string][]provider.CandlePrice) } - candlePrices[providerName][assetName] = asset + + candlePrices[providerName][base] = cp } tvwap, err := ComputeTVWAP(candlePrices) @@ -457,11 +464,12 @@ func (o *Oracle) filterCandleDeviations( return nil, err } - for assetName, asset := range tvwap { + for base, asset := range tvwap { if _, ok := tvwaps[providerName]; !ok { tvwaps[providerName] = make(map[string]sdk.Dec) } - tvwaps[providerName][assetName] = asset + + tvwaps[providerName][base] = asset } } @@ -479,11 +487,15 @@ func (o *Oracle) filterCandleDeviations( if _, ok := filteredCandles[providerName]; !ok { filteredCandles[providerName] = make(map[string][]provider.CandlePrice) } + filteredCandles[providerName][base] = candles[providerName][base] } else { - telemetry.IncrCounter(1, "failure", "provider") - o.logger.Warn().Str("base", base).Str("provider", providerName).Str( - "price", price.String()).Msg("provider deviating from other candles") + telemetry.IncrCounter(1, "failure", "provider", "type", "candle") + o.logger.Warn(). + Str("base", base). + Str("provider", providerName). + Str("price", price.String()). + Msg("provider deviating from other candles") } } } diff --git a/price-feeder/oracle/util.go b/price-feeder/oracle/util.go index 24b22d7b0e..43b608efd8 100644 --- a/price-feeder/oracle/util.go +++ b/price-feeder/oracle/util.go @@ -9,10 +9,14 @@ import ( "github.com/umee-network/umee/price-feeder/oracle/provider" ) -var minimumTimeWeight = sdk.MustNewDecFromStr("0.2") +var ( + minimumTimeWeight = sdk.MustNewDecFromStr("0.2") +) -// tvwapCandlePeriod represents the time period we use for tvwap in minutes. -const tvwapCandlePeriod = 3 * time.Minute +const ( + // tvwapCandlePeriod represents the time period we use for tvwap in minutes + tvwapCandlePeriod = 3 * time.Minute +) // compute VWAP for each base by dividing the Σ {P * V} by Σ {V} func vwap(weightedPrices map[string]sdk.Dec, volumeSum map[string]sdk.Dec) (map[string]sdk.Dec, error) { @@ -121,9 +125,8 @@ func ComputeTVWAP(prices provider.AggregatedProviderCandles) (map[string]sdk.Dec // StandardDeviation returns maps of the standard deviations and means of assets. // Will skip calculating for an asset if there are less than 3 prices. func StandardDeviation( - prices map[string]map[string]sdk.Dec) ( - map[string]sdk.Dec, map[string]sdk.Dec, error, -) { + prices map[string]map[string]sdk.Dec, +) (map[string]sdk.Dec, map[string]sdk.Dec, error) { var ( deviations = make(map[string]sdk.Dec) means = make(map[string]sdk.Dec) @@ -132,7 +135,7 @@ func StandardDeviation( ) for _, providerPrices := range prices { - for base, tp := range providerPrices { + for base, p := range providerPrices { if _, ok := priceSums[base]; !ok { priceSums[base] = sdk.ZeroDec() } @@ -140,8 +143,8 @@ func StandardDeviation( priceSlice[base] = []sdk.Dec{} } - priceSums[base] = priceSums[base].Add(tp) - priceSlice[base] = append(priceSlice[base], tp) + priceSums[base] = priceSums[base].Add(p) + priceSlice[base] = append(priceSlice[base], p) } } diff --git a/price-feeder/oracle/util_test.go b/price-feeder/oracle/util_test.go index 9043ac8c43..01a9963115 100644 --- a/price-feeder/oracle/util_test.go +++ b/price-feeder/oracle/util_test.go @@ -184,6 +184,7 @@ func TestStandardDeviation(t *testing.T) { require.NoError(t, err) require.Len(t, deviation, len(tc.expected)) require.Len(t, mean, len(tc.expected)) + for k, v := range tc.expected { require.Equalf(t, v.deviation, deviation[k], "unexpected deviation for %s", k) require.Equalf(t, v.mean, mean[k], "unexpected mean for %s", k)