-
Notifications
You must be signed in to change notification settings - Fork 1
/
cryptoindex.py
152 lines (128 loc) · 5.83 KB
/
cryptoindex.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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from polygon import RESTClient
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
def calc_dates(date: datetime = datetime.now()) -> tuple:
this_year = date - timedelta(days=date.day-1)
one_year = this_year + timedelta(days=-365)
return (one_year.strftime("%Y-%m-%d"), this_year.strftime("%Y-%m-%d"))
def do_sharpe(ser, days=True):
mins_in_year = 60 * 24 * 365
days_in_year = 365
if days:
themean = ser.pct_change().mean() * days_in_year
thestd = ser.pct_change().std() * np.sqrt(days_in_year)
else:
themean = ser.pct_change().mean() * mins_in_year
thestd = ser.pct_change().std() * np.sqrt(mins_in_year)
sharpe = themean/thestd
return themean, thestd, sharpe, format_output(themean, thestd, sharpe)
def format_output(mymean, mystandarddeviation, mysharpe):
output = f"""
| Metric | Value |
|--------------------|----------------------|
| Mean | {mymean:.2f} |
| Standard Deviation | {mystandarddeviation:.2f} |
| Sharpe-Rivin | {mysharpe:.3f} |
"""
return output
import os
api_key = os.getenv("POLYGON_KEY")
import pandas as pd
from polygon import RESTClient
client = RESTClient(api_key)
def get_ticker_trade(ticker: str):
coinname = ticker[2:-3]
thetrade = client.get_last_crypto_trade(coinname, "USD")
return thetrade.price
def update_df(last_day):
last_day["price"] = last_day.ticker.map(get_ticker_trade)
weights = last_day.weight
return np.average(last_day.price, weights = weights)
def get_daily_bars(ticker:str, dete = datetime.now()):
thedate = dete.strftime("%Y-%m-%d")
bars = client.get_aggs(ticker=ticker, multiplier=1, timespan="minute", from_= thedate, to=thedate, limit=50000)
thedf = pd.DataFrame(bars)[['timestamp', "close"]]
thedf.set_index(pd.to_datetime(thedf.timestamp, unit='ms'), inplace = True)
thedf.drop("timestamp", axis = 1, inplace = True)
thedf.rename({"close": ticker}, axis = 1, inplace = True)
return thedf
def update_day(last_day, func =np.sqrt):
dflist = []
for ticker in last_day.ticker:
dflist.append(get_daily_bars(ticker))
newdf = pd.concat(dflist, axis = 1)
oldind = newdf.index
last_day_r = last_day.reset_index(drop=True)
newdf_r = newdf.reset_index(drop=True)
close_column = last_day['close']
#newdf_r = newdf_r.div(close_column, axis=0)
newdf_r.index = oldind
newdf_r["indprice"] = newdf_r.apply(lambda x: np.average(x, weights=func(last_day.weight)), axis = 1)
return newdf_r.indprice.ffill()
etfs = ['VOO','SOXL','TQQQ','LQD','HYG','QQQ', 'IVV','SPY', 'IWM', 'DJI', 'IXIC', 'VIX', 'TLT', 'IEF', 'GLD', 'SLV', 'USO', 'UNG',
'VXX', 'FXE', 'FXY', 'FXB', 'FXA', 'FXC', 'FXF', 'XAU', 'XAG', 'XPT', 'XPD', 'XME', 'XHB', 'XLF', 'XLY', 'XLC', 'XLI', 'XLE',
'XLV', 'XLP', 'XLRE', 'XLK', 'XLU', 'XLC', 'XLB', 'XITK', 'XNTK', 'XNWK', 'XNGK']
def fetch_crypto_data(start_date, end_date, *, locale = 'global', market_type = 'crypto'):
# Generate the date range
dates = pd.date_range(start=start_date, end=end_date, freq='D')
all_data = []
for date in dates:
formatted_date = date.strftime('%Y-%m-%d')
daily_data = pd.DataFrame(client.get_grouped_daily_aggs(formatted_date, locale=locale, market_type=market_type))
all_data.append(daily_data)
newdata = pd.concat(all_data)
if market_type == 'crypto':
newdata= newdata[newdata['ticker'].str.endswith('USD')]
elif market_type == 'stocks':
newdata= newdata[~newdata['ticker'].isin(etfs)]
else:
pass
newdata["totalvol"] = newdata.volume*newdata.close
newdata["totalvol2"] = newdata.volume/newdata.close
# Sort the data by timestamp to ensure correct EMA calculation
newdata.sort_values(by='timestamp', inplace=True)
# Calculate the EMA of the `totalvol` column
# `span` is set to 30 for a 30-day EMA
newdata['totalvol_ema'] = newdata.groupby('ticker')['totalvol'].transform(lambda x: x.ewm(span=30, adjust=False).mean())
newdata['totalvol2_ema'] = newdata.groupby('ticker')['totalvol2'].transform(lambda x: x.ewm(span=30, adjust=False).mean())
return newdata
# Example usage
#start_date = '2020-01-01'
#end_date = '2024-03-27'
#crypto_data = fetch_crypto_data(start_date, end_date)
def get_crypto_index(crypto_data, howmany = 20, func = lambda x: x):
ser = pd.Series(np.ones(howmany)).map(func)
p = pd.Series(np.ones(howmany))
valdict = {}
dfdict = {}
crypto_data.sort_values('timestamp', inplace = True, ascending = True)
for d, df in crypto_data.groupby('timestamp'):
df = df[df.open > 0.01]
df = df.sort_values('totalvol_ema', ascending=False).head(howmany)
#indopen =np.average(df.open/p, weights = ser)
indopen = np.average(df.open.values, weights=ser.values)
#indclose =np.average(df.close/p, weights = ser)
indclose = np.average(df.close.values, weights=ser.values)
ser = df.totalvol_ema.map(func)
p = df.close
valdict[d] = {'open': indopen, 'close': indclose}
dfdict[d] = pd.DataFrame({'ticker':df.ticker, 'weight':ser, 'close': df.close})
first_key = next(iter(valdict))
del valdict[first_key]
del dfdict[first_key]
vals = pd.DataFrame(valdict).T
vals.index = pd.to_datetime(vals.index, unit = 'ms')
vallist =[]
for key, val in dfdict.items():
val['date'] = pd.to_datetime(key, unit = 'ms')
vallist.append(val)
dfs = pd.concat(vallist)
return vals, dfs
def update_weights(fname="/tmp/wts.csv", **kwargs):
start_date, end_date = calc_dates()
crypto_data = fetch_crypto_data(start_date, end_date, **kwargs)
_, dfs = get_crypto_index(crypto_data)
retval = dfs[dfs.date == dfs.date.max()]
retval.to_csv(fname, index = False)
return retval