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.
This commit is contained in:
satsbaba 2022-06-25 12:44:32 +02:00 committed by GitHub
parent 27d28f4e0e
commit f2f90bd948
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -143,16 +143,57 @@ def compute_premium_percentile(order):
return round(np.sum(rates < order_rate) / len(rates), 2) 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): def compute_avg_premium(queryset):
weighted_premiums = [] premiums = []
volumes = [] volumes = []
# We exclude BTC, as LN <-> BTC swap premiums should not be mixed with FIAT. # We exclude BTC, as LN <-> BTC swap premiums should not be mixed with FIAT.
for tick in queryset.exclude(currency=1000): for tick in queryset.exclude(currency=1000):
weighted_premiums.append(tick.premium * tick.volume) premiums.append(tick.premium)
volumes.append(tick.volume) 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) total_volume = sum(volumes)
# Avg_premium is the weighted average of the premiums by volume # Avg_premium is the weighted average of the premiums by volume
avg_premium = sum(weighted_premiums) / total_volume avg_premium = sum(weighted_premiums) / total_volume
return avg_premium, total_volume return avg_premium, total_volume