mirror of
https://github.com/aljazceru/hummingbot-dashboard.git
synced 2025-12-29 03:04:19 +01:00
(feat) add protocols analysis page
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,6 +6,8 @@ __pycache__/
|
||||
# C extensions
|
||||
*.
|
||||
|
||||
*.ipynb
|
||||
|
||||
.idea/*
|
||||
|
||||
# Distribution / packaging
|
||||
|
||||
83
pages/5_🦉_TVL_vs_MCAP_Analysis.py
Normal file
83
pages/5_🦉_TVL_vs_MCAP_Analysis.py
Normal file
@@ -0,0 +1,83 @@
|
||||
from xml.dom.pulldom import default_bufsize
|
||||
import numpy as np
|
||||
import streamlit as st
|
||||
import pandas as pd
|
||||
import plotly.express as px
|
||||
from defillama import DefiLlama
|
||||
from traitlets import default
|
||||
|
||||
MIN_TVL = 1000000.
|
||||
MIN_MCAP = 1000000.
|
||||
|
||||
@st.cache
|
||||
def get_tvl_mcap_data():
|
||||
# initialize api client
|
||||
llama = DefiLlama()
|
||||
# Get all protocols data
|
||||
df = pd.DataFrame(llama.get_all_protocols())
|
||||
tvl_mcap_df = df.loc[(df["tvl"]>0) & (df["mcap"]>0), ["name", "tvl", "mcap", "chain", "category", "slug"]].sort_values(by=["mcap"], ascending=False)
|
||||
return tvl_mcap_df[(tvl_mcap_df["tvl"] > MIN_TVL) & (tvl_mcap_df["mcap"]> MIN_MCAP)]
|
||||
|
||||
def get_protocols_by_chain_category(protocols: pd.DataFrame, group_by: list, nth: list):
|
||||
return protocols.sort_values('tvl', ascending=False).groupby(group_by).nth(nth).reset_index()
|
||||
|
||||
|
||||
st.set_page_config(layout='wide')
|
||||
st.title("🦉 TVL vs MCAP Analysis")
|
||||
st.write("---")
|
||||
st.code("💡 Source: [DefiLlama](https://defillama.com/)")
|
||||
with st.spinner(text='In progress'):
|
||||
tvl_mcap_df = get_tvl_mcap_data()
|
||||
|
||||
default_chains = ["Ethereum", "Solana", "Binance", "Polygon", "Multi-Chain", "Avalanche"]
|
||||
# st.write("### Protocols filter 🦅")
|
||||
# tokens = st.multiselect(
|
||||
# "Select the protocols to analyze:",
|
||||
# options=tvl_mcap_df["name"],
|
||||
# default=tvl_mcap_df[tvl_mcap_df["chain"].isin(default_chains)]["name"])
|
||||
|
||||
st.sidebar.write("### Chains filter 🔗")
|
||||
chains = st.sidebar.multiselect(
|
||||
"Select the chains to analyze:",
|
||||
options=tvl_mcap_df["chain"].unique(),
|
||||
default=default_chains)
|
||||
|
||||
scatter = px.scatter(
|
||||
data_frame=tvl_mcap_df[tvl_mcap_df["chain"].isin(chains)],
|
||||
x="tvl",
|
||||
y="mcap",
|
||||
color="chain",
|
||||
trendline="ols",
|
||||
log_x=True,
|
||||
log_y=True,
|
||||
height=800,
|
||||
hover_data=["name"],
|
||||
template="plotly_dark",
|
||||
title="TVL vs MCAP",
|
||||
labels={
|
||||
"tvl": 'TVL (USD)',
|
||||
'mcap': 'Market Cap (USD)'
|
||||
})
|
||||
|
||||
st.plotly_chart(scatter, use_container_width=True)
|
||||
|
||||
st.sidebar.write("---")
|
||||
st.sidebar.write("### SunBurst filter 🔗")
|
||||
groupby = st.sidebar.selectbox('Group by:', [['chain', 'category'], ['category', 'chain']])
|
||||
nth = st.sidebar.slider('Top protocols by Category', min_value=1, max_value=5)
|
||||
|
||||
proto_agg = get_protocols_by_chain_category(tvl_mcap_df[tvl_mcap_df["chain"].isin(chains)], groupby, np.arange(0, nth, 1).tolist())
|
||||
groupby.append("slug")
|
||||
sunburst = px.sunburst(
|
||||
proto_agg,
|
||||
path=groupby,
|
||||
values='tvl',
|
||||
height=800,
|
||||
title="SunBurst",
|
||||
template="plotly_dark",)
|
||||
|
||||
|
||||
st.plotly_chart(sunburst, use_container_width=True)
|
||||
|
||||
st.sidebar.write("# Data filters 🏷")
|
||||
st.sidebar.code("🧳 New filters coming. \nReach us on discord \nif you want to propose one!")
|
||||
@@ -5,19 +5,19 @@ argon2-cffi-bindings==21.2.0
|
||||
asttokens==2.0.5
|
||||
attrs==21.4.0
|
||||
backcall==0.2.0
|
||||
backports.zoneinfo==0.2.1
|
||||
beautifulsoup4==4.11.1
|
||||
bleach==5.0.0
|
||||
bleach==5.0.1
|
||||
blinker==1.4
|
||||
boltons==21.0.0
|
||||
cachetools==5.2.0
|
||||
certifi==2022.5.18.1
|
||||
cffi==1.15.0
|
||||
charset-normalizer==2.0.12
|
||||
certifi==2022.6.15
|
||||
cffi==1.15.1
|
||||
charset-normalizer==2.1.0
|
||||
click==8.1.3
|
||||
commonmark==0.9.1
|
||||
debugpy==1.6.0
|
||||
debugpy==1.6.2
|
||||
decorator==5.1.1
|
||||
DeFiLlama==1.1.0
|
||||
defusedxml==0.7.1
|
||||
entrypoints==0.4
|
||||
executing==0.8.3
|
||||
@@ -27,38 +27,38 @@ gitdb==4.0.9
|
||||
GitPython==3.1.27
|
||||
glom==22.1.0
|
||||
idna==3.3
|
||||
importlib-metadata==4.11.4
|
||||
importlib-resources==5.7.1
|
||||
ipykernel==6.13.1
|
||||
importlib-metadata==4.12.0
|
||||
ipykernel==6.15.1
|
||||
ipython==8.4.0
|
||||
ipython-genutils==0.2.0
|
||||
ipywidgets==7.7.0
|
||||
ipywidgets==7.7.1
|
||||
jedi==0.18.1
|
||||
Jinja2==3.1.2
|
||||
jsonschema==4.6.0
|
||||
jupyter-client==7.3.3
|
||||
jupyter-core==4.10.0
|
||||
jsonschema==4.7.2
|
||||
jupyter-client==7.3.4
|
||||
jupyter-core==4.11.1
|
||||
jupyterlab-pygments==0.2.2
|
||||
jupyterlab-widgets==1.1.0
|
||||
jupyterlab-widgets==1.1.1
|
||||
MarkupSafe==2.1.1
|
||||
matplotlib-inline==0.1.3
|
||||
mistune==0.8.4
|
||||
nbclient==0.6.4
|
||||
nbclient==0.6.6
|
||||
nbconvert==6.5.0
|
||||
nbformat==5.4.0
|
||||
nest-asyncio==1.5.5
|
||||
notebook==6.4.12
|
||||
numpy==1.22.4
|
||||
numpy==1.23.1
|
||||
packaging==21.3
|
||||
pandas==1.4.2
|
||||
pandas==1.4.3
|
||||
pandocfilters==1.5.0
|
||||
parso==0.8.3
|
||||
patsy==0.5.2
|
||||
pexpect==4.8.0
|
||||
pickleshare==0.7.5
|
||||
Pillow==9.1.1
|
||||
plotly==5.8.0
|
||||
Pillow==9.2.0
|
||||
plotly==5.9.0
|
||||
prometheus-client==0.14.1
|
||||
prompt-toolkit==3.0.29
|
||||
prompt-toolkit==3.0.30
|
||||
protobuf==3.20.1
|
||||
psutil==5.9.1
|
||||
ptyprocess==0.7.0
|
||||
@@ -74,30 +74,32 @@ pyrsistent==0.18.1
|
||||
python-dateutil==2.8.2
|
||||
pytz==2022.1
|
||||
pytz-deprecation-shim==0.1.0.post0
|
||||
pyzmq==23.1.0
|
||||
requests==2.27.1
|
||||
rich==12.4.4
|
||||
pyzmq==23.2.0
|
||||
requests==2.28.1
|
||||
rich==12.5.1
|
||||
scipy==1.8.1
|
||||
semver==2.13.0
|
||||
Send2Trash==1.8.0
|
||||
six==1.16.0
|
||||
smmap==5.0.0
|
||||
soupsieve==2.3.2.post1
|
||||
stack-data==0.2.0
|
||||
stack-data==0.3.0
|
||||
statsmodels==0.13.2
|
||||
streamlit==1.10.0
|
||||
tenacity==8.0.1
|
||||
terminado==0.15.0
|
||||
tinycss2==1.1.1
|
||||
toml==0.10.2
|
||||
toolz==0.11.2
|
||||
tornado==6.1
|
||||
traitlets==5.2.2.post1
|
||||
typing_extensions==4.2.0
|
||||
toolz==0.12.0
|
||||
tornado==6.2
|
||||
traitlets==5.3.0
|
||||
typing_extensions==4.3.0
|
||||
tzdata==2022.1
|
||||
tzlocal==4.2
|
||||
urllib3==1.26.9
|
||||
urllib3==1.26.10
|
||||
validators==0.20.0
|
||||
watchdog==2.1.8
|
||||
watchdog==2.1.9
|
||||
wcwidth==0.2.5
|
||||
webencodings==0.5.1
|
||||
widgetsnbextension==3.6.0
|
||||
zipp==3.8.0
|
||||
widgetsnbextension==3.6.1
|
||||
zipp==3.8.1
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import time
|
||||
|
||||
from pycoingecko import CoinGeckoAPI
|
||||
import pandas as pd
|
||||
import re
|
||||
|
||||
|
||||
class CoinGeckoUtils:
|
||||
def __init__(self):
|
||||
self.connector = CoinGeckoAPI()
|
||||
|
||||
def get_all_coins_df(self):
|
||||
coin_list = self.connector.get_coins_list()
|
||||
return pd.DataFrame(coin_list)
|
||||
|
||||
def get_all_coins_markets_df(self):
|
||||
coin_list = self.connector.get_coins_markets(vs_currency="USD")
|
||||
return pd.DataFrame(coin_list)
|
||||
|
||||
def get_coin_tickers_by_id(self, coin_id: str):
|
||||
coin_tickers = self.connector.get_coin_ticker_by_id(id=coin_id)
|
||||
coin_tickers_df = pd.DataFrame(coin_tickers["tickers"])
|
||||
coin_tickers_df["token_id"] = coin_id
|
||||
return coin_tickers_df
|
||||
|
||||
def get_coin_tickers_by_id_list(self, coins_id: list):
|
||||
dfs = []
|
||||
for coin_id in coins_id:
|
||||
df = self.get_coin_tickers_by_id(coin_id)
|
||||
dfs.append(df)
|
||||
time.sleep(1)
|
||||
|
||||
coin_tickers_df = pd.concat(dfs)
|
||||
coin_tickers_df["exchange"] = coin_tickers_df["market"].apply(
|
||||
lambda x: re.sub("Exchange", "", x["name"]))
|
||||
coin_tickers_df.drop(columns="market", inplace=True)
|
||||
coin_tickers_df["trading_pair"] = coin_tickers_df.base + "-" + coin_tickers_df.target
|
||||
return coin_tickers_df
|
||||
|
||||
def get_all_exchanges_df(self):
|
||||
exchanges_list = self.connector.get_exchanges_list()
|
||||
return pd.DataFrame(exchanges_list)
|
||||
|
||||
def get_exchanges_markets_info_by_id_list(self, exchanges_id: list):
|
||||
dfs = []
|
||||
for exchange_id in exchanges_id:
|
||||
df = pd.DataFrame(self.connector.get_exchanges_by_id(exchange_id)["tickers"])
|
||||
dfs.append(df)
|
||||
exchanges_spreads_df = pd.concat(dfs)
|
||||
exchanges_spreads_df["exchange"] = exchanges_spreads_df["market"].apply(
|
||||
lambda x: re.sub("Exchange", "", x["name"]))
|
||||
exchanges_spreads_df.drop(columns="market", inplace=True)
|
||||
exchanges_spreads_df["trading_pair"] = exchanges_spreads_df.base + "-" + exchanges_spreads_df.target
|
||||
return exchanges_spreads_df
|
||||
@@ -1,62 +0,0 @@
|
||||
import pandas as pd
|
||||
import requests
|
||||
from glom import *
|
||||
|
||||
|
||||
class MinerUtils:
|
||||
MARKETS_ENDPOINT = "https://api.hummingbot.io/bounty/markets"
|
||||
|
||||
@staticmethod
|
||||
def reward_splitter(base, reward_dict):
|
||||
tmp = {"rewards_HBOT": 0, "rewards_STABLE": 0, "rewards_base": 0, }
|
||||
if "HBOT" in reward_dict:
|
||||
tmp["rewards_HBOT"] += reward_dict["HBOT"]
|
||||
if "USDC" in reward_dict:
|
||||
tmp["rewards_STABLE"] += reward_dict["USDC"]
|
||||
if "USDT" in reward_dict:
|
||||
tmp["rewards_STABLE"] += reward_dict["USDT"]
|
||||
if base in reward_dict:
|
||||
tmp["rewards_base"] += reward_dict[base]
|
||||
|
||||
return pd.Series(tmp, dtype=float)
|
||||
|
||||
@staticmethod
|
||||
def exchange_coingecko_id(exchange: str):
|
||||
converter = {
|
||||
"kucoin": "kucoin",
|
||||
"binance": "binance",
|
||||
"gateio": "gate",
|
||||
"ascendex": "bitmax"
|
||||
}
|
||||
return converter[exchange]
|
||||
|
||||
def get_miner_stats_df(self):
|
||||
miner_data = requests.get(self.MARKETS_ENDPOINT).json()
|
||||
spec = {
|
||||
'market_id': ('markets', ['market_id']),
|
||||
'trading_pair': ('markets', ['trading_pair']),
|
||||
'exchange': ('markets', ['exchange_name']),
|
||||
'base': ('markets', ['base_asset']),
|
||||
'quote': ('markets', ['quote_asset']),
|
||||
'start_timestamp': ('markets', [("active_bounty_periods", ['start_timestamp'])]),
|
||||
'end_timestamp': ('markets', [("active_bounty_periods", ['end_timestamp'])]),
|
||||
'budget': ('markets', [("active_bounty_periods", ['budget'])]),
|
||||
'spread_max': ('markets', [("active_bounty_periods", ['spread_max'])]),
|
||||
'payout_asset': ('markets', [("active_bounty_periods", ['payout_asset'])]),
|
||||
'return': ('markets', ['return']),
|
||||
'last_snapshot_ts': ('markets', ['last_snapshot_ts']),
|
||||
'hourly_payout_usd': ('markets', ['hourly_payout_usd']),
|
||||
'bots': ('markets', ['bots']),
|
||||
'last_hour_bots': ('markets', ['last_hour_bots']),
|
||||
'filled_24h_volume': ('markets', ['filled_24h_volume']),
|
||||
'weekly_reward_in_usd': ('markets', ['weekly_reward_in_usd']),
|
||||
'weekly_reward': ('markets', ['weekly_reward']),
|
||||
'market_24h_usd_volume': ('markets', ['market_24h_usd_volume'])
|
||||
}
|
||||
|
||||
r = glom(miner_data, spec)
|
||||
df = pd.DataFrame(r)
|
||||
df = pd.concat([df, df.apply(lambda x: self.reward_splitter(x.base, x.weekly_reward), axis=1)], axis=1)
|
||||
df["trading_pair"] = df.apply(lambda x: x.base + "-" + x.quote, axis=1)
|
||||
df["exchange_coingecko_id"] = df.apply(lambda x: self.exchange_coingecko_id(x.exchange), axis=1)
|
||||
return df
|
||||
Reference in New Issue
Block a user