cryptoindex / cryptoindex.py
igriv's picture
Prepare for HF Spaces deployment
15e1317
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_API_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