-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathconstituents.py
42 lines (29 loc) · 1.71 KB
/
constituents.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import json
from math import exp, log, sqrt
from market_data import get_market_data
from settings import CONSTITUENTS_AMOUNT, CONSTITUENTS_FILE, DEFAULT_RATIO, PAIRING, RESELECT_CONSTITUENTS
def calculate_weights():
if RESELECT_CONSTITUENTS:
coin_ids = None
else:
try:
with open(CONSTITUENTS_FILE) as f:
coin_ids = json.load(f)
except FileNotFoundError:
coin_ids = None
market_data = get_market_data(coin_ids)
adjusted_market_caps = {c: _ewma(m['market_caps']) for (c, m) in market_data.items()}
adjusted_market_caps = dict(sorted(adjusted_market_caps.items(), key=lambda i: i[1], reverse=True)[:CONSTITUENTS_AMOUNT])
with open(CONSTITUENTS_FILE, 'w') as f:
json.dump(list(adjusted_market_caps.keys()), f)
weights = _constituents_weights(adjusted_market_caps)
default_ratio = DEFAULT_RATIO if PAIRING not in [market_data[c]['symbol'] for c in weights] else 0
return {**{PAIRING: default_ratio}, **{market_data[c]['symbol']: (1 - default_ratio) * w for (c, w) in weights.items()}}
def _ewma(series, half_life=3):
decay_rate = log(2) / half_life
return sum([market_cap * exp(- decay_rate * i) for i, market_cap in enumerate(series)]) / \
sum([exp(- decay_rate * i) for i in range(len(series))])
def _constituents_weights(adjusted_market_caps):
sqrt_adjusted_market_caps = {coin_id: sqrt(adjusted_market_cap) for (coin_id, adjusted_market_cap) in adjusted_market_caps.items()}
sqrt_adjusted_market_caps_sum = sum(sqrt_adjusted_market_caps.values())
return {coin_id: sqrt_adjusted_market_cap / sqrt_adjusted_market_caps_sum for (coin_id, sqrt_adjusted_market_cap) in sqrt_adjusted_market_caps.items()}