From f2f90bd9482536b1ed4101b9ad8295cc232345d5 Mon Sep 17 00:00:00 2001 From: satsbaba <106560507+satsbaba@users.noreply.github.com> Date: Sat, 25 Jun 2022 12:44:32 +0200 Subject: [PATCH 1/3] replaced weighted mean to weighted median This commit changes the weighted mean to the weighted median for the calculation of the premium displayed on the robosats. --- api/utils.py | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/api/utils.py b/api/utils.py index 8cf2b12a..7eacdea8 100644 --- a/api/utils.py +++ b/api/utils.py @@ -143,16 +143,57 @@ def compute_premium_percentile(order): return round(np.sum(rates < order_rate) / len(rates), 2) +def weighted_median(values, sample_weight=None, quantiles= 0.5, values_sorted=False): + """Very close to numpy.percentile, but it supports weights. + NOTE: quantiles should be in [0, 1]! + :param values: numpy.array with data + :param quantiles: array-like with many quantiles needed. For weighted median 0.5 + :param sample_weight: array-like of the same length as `array` + :param values_sorted: bool, if True, then will avoid sorting of + initial array assuming array is already sorted + :return: numpy.array with computed quantiles. + """ + values = np.array(values) + quantiles = np.array(quantiles) + if sample_weight is None: + sample_weight = np.ones(len(values)) + sample_weight = np.array(sample_weight) + assert np.all(quantiles >= 0) and np.all(quantiles <= 1), \ + 'quantiles should be in [0, 1]' + + if not values_sorted: + sorter = np.argsort(values) + values = values[sorter] + sample_weight = sample_weight[sorter] + + weighted_quantiles = np.cumsum(sample_weight) - 0.5 * sample_weight + weighted_quantiles -= weighted_quantiles[0] + weighted_quantiles /= weighted_quantiles[-1] + + return np.interp(quantiles, weighted_quantiles, values) + def compute_avg_premium(queryset): - weighted_premiums = [] + premiums = [] volumes = [] # We exclude BTC, as LN <-> BTC swap premiums should not be mixed with FIAT. + for tick in queryset.exclude(currency=1000): - weighted_premiums.append(tick.premium * tick.volume) + premiums.append(tick.premium) volumes.append(tick.volume) + total_volume = sum(volumes) + + # weighted_median_premium is the weighted median of the premiums by volume + + weighted_median_premium = weighted_median(values=premiums, + sample_weight=volumes, + quantiles=0.5, + values_sorted=False) + + return weighted_median_premium, total_volume + total_volume = sum(volumes) # Avg_premium is the weighted average of the premiums by volume avg_premium = sum(weighted_premiums) / total_volume - return avg_premium, total_volume \ No newline at end of file + return avg_premium, total_volume From f4caa98eeffc2d414331c3d833867dc59d809aef Mon Sep 17 00:00:00 2001 From: satsbaba <106560507+satsbaba@users.noreply.github.com> Date: Sat, 25 Jun 2022 12:47:35 +0200 Subject: [PATCH 2/3] replaced weighted mean to weighted median This commit changes the weighted mean to the weighted median for the calculation of the premium displayed on the robosats. --- api/utils.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/api/utils.py b/api/utils.py index 7eacdea8..e4dc7e79 100644 --- a/api/utils.py +++ b/api/utils.py @@ -192,8 +192,3 @@ def compute_avg_premium(queryset): values_sorted=False) return weighted_median_premium, total_volume - - total_volume = sum(volumes) - # Avg_premium is the weighted average of the premiums by volume - avg_premium = sum(weighted_premiums) / total_volume - return avg_premium, total_volume From 0866109072cbc27e38510ffa920b652853129c61 Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Wed, 29 Jun 2022 02:41:59 -0700 Subject: [PATCH 3/3] Fix bug on weighted median --- api/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/utils.py b/api/utils.py index e4dc7e79..816a8159 100644 --- a/api/utils.py +++ b/api/utils.py @@ -179,8 +179,8 @@ def compute_avg_premium(queryset): # We exclude BTC, as LN <-> BTC swap premiums should not be mixed with FIAT. for tick in queryset.exclude(currency=1000): - premiums.append(tick.premium) - volumes.append(tick.volume) + premiums.append(float(tick.premium)) + volumes.append(float(tick.volume)) total_volume = sum(volumes)