From fa2a9931730fe79fbd87e37b3b64ae8993fecec8 Mon Sep 17 00:00:00 2001 From: cardosofede Date: Thu, 14 Jul 2022 19:55:27 +0200 Subject: [PATCH] (feat) add protocols analysis page --- .gitignore | 2 + pages/5_🦉_TVL_vs_MCAP_Analysis.py | 83 ++++++++++++++++++++++++++++++ requirements.txt | 66 ++++++++++++------------ utils/coingecko_utils 2.py | 54 ------------------- utils/miner_utils 2.py | 62 ---------------------- 5 files changed, 119 insertions(+), 148 deletions(-) create mode 100644 pages/5_🦉_TVL_vs_MCAP_Analysis.py delete mode 100644 utils/coingecko_utils 2.py delete mode 100644 utils/miner_utils 2.py diff --git a/.gitignore b/.gitignore index ef05c56..a2fed59 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ __pycache__/ # C extensions *. +*.ipynb + .idea/* # Distribution / packaging diff --git a/pages/5_🦉_TVL_vs_MCAP_Analysis.py b/pages/5_🦉_TVL_vs_MCAP_Analysis.py new file mode 100644 index 0000000..ddc199f --- /dev/null +++ b/pages/5_🦉_TVL_vs_MCAP_Analysis.py @@ -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!") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 46f5563..61fc12f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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 diff --git a/utils/coingecko_utils 2.py b/utils/coingecko_utils 2.py deleted file mode 100644 index 919793b..0000000 --- a/utils/coingecko_utils 2.py +++ /dev/null @@ -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 diff --git a/utils/miner_utils 2.py b/utils/miner_utils 2.py deleted file mode 100644 index 5ad0f6e..0000000 --- a/utils/miner_utils 2.py +++ /dev/null @@ -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