Files
OpenBB/openbb_terminal/cryptocurrency/overview/pycoingecko_model.py
montezdesousa b2f0e07349 Fix [Bug] SDK - openbb.crpyto.ov.stables - Error: 'rank' (works in Terminal though) (#3557)
* fix stables

* add examples

* small fix

Co-authored-by: Henrique Joaquim <h.joaquim@campus.fct.unl.pt>
2022-11-24 18:44:59 +00:00

539 lines
13 KiB
Python

"""CoinGecko model"""
__docformat__ = "numpy"
# pylint: disable=C0301, E1101
# pylint: disable=unsupported-assignment-operation
import logging
import re
from typing import List, Union
import numpy as np
import pandas as pd
from pycoingecko import CoinGeckoAPI
from openbb_terminal.cryptocurrency.dataframe_helpers import (
create_df_index,
lambda_long_number_format_with_type_check,
lambda_replace_underscores_in_column_names,
)
from openbb_terminal.cryptocurrency.discovery.pycoingecko_model import get_coins
from openbb_terminal.decorators import log_start_end
logger = logging.getLogger(__name__)
# pylint: disable=unsupported-assignment-operation
HOLD_COINS = ["ethereum", "bitcoin"]
NEWS_FILTERS = ["Index", "Title", "Author", "Posted"]
CATEGORIES_FILTERS = [
"Rank",
"Name",
"Change_1h",
"Change_24h",
"Change_7d",
"Market_Cap",
"Volume_24h",
"Coins",
]
STABLES_FILTERS = [
"Rank",
"Name",
"Symbol",
"Price",
"Change_24h",
"Exchanges",
"Market_Cap",
"Change_30d",
]
PRODUCTS_FILTERS = [
"Rank",
"Platform",
"Identifier",
"Supply_Rate",
"Borrow_Rate",
]
PLATFORMS_FILTERS = ["Rank", "Name", "Category", "Centralized"]
EXCHANGES_FILTERS = [
"Rank",
"Trust_Score",
"Id",
"Name",
"Country",
"Year Established",
"Trade_Volume_24h_BTC",
]
EXRATES_FILTERS = ["Index", "Name", "Unit", "Value", "Type"]
INDEXES_FILTERS = ["Rank", "Name", "Id", "Market", "Last", "MultiAsset"]
DERIVATIVES_FILTERS = [
"Rank",
"Market",
"Symbol",
"Price",
"Pct_Change_24h",
"Contract_Type",
"Basis",
"Spread",
"Funding_Rate",
"Volume_24h",
]
COINS_COLUMNS = [
"symbol",
"name",
"current_price",
"market_cap",
"market_cap_rank",
"price_change_percentage_7d_in_currency",
"price_change_percentage_24h_in_currency",
"total_volume",
]
@log_start_end(log=logger)
def get_holdings_overview(endpoint: str = "bitcoin") -> List[Union[str, pd.DataFrame]]:
"""Returns public companies that holds ethereum or bitcoin [Source: CoinGecko]
Parameters
----------
endpoint : str
"bitcoin" or "ethereum"
Returns
-------
List[Union[str, pd.DataFrame]]
- str: Overall statistics
- pd.DataFrame: Companies holding crypto
"""
cg = CoinGeckoAPI()
data = cg.get_companies_public_treasury_by_coin_id(coin_id=endpoint)
stats_str = f"""{len(data["companies"])} companies hold a total of {lambda_long_number_format_with_type_check(data["total_holdings"])} {endpoint} ({data["market_cap_dominance"]}% of market cap dominance) with the current value of {lambda_long_number_format_with_type_check(int(data["total_value_usd"]))} USD dollars""" # noqa
df = pd.json_normalize(data, record_path=["companies"])
df.columns = list(
map(
lambda x: lambda_replace_underscores_in_column_names(x)
if isinstance(x, str)
else x,
df.columns,
)
)
return [stats_str, df]
SORT_VALUES = [
"market_cap_desc",
"market_cap_asc",
"name_desc",
"name_asc",
"market_cap_change_24h_desc",
"market_cap_change_24h_asc",
]
def lambda_coin_formatter(n):
# TODO: can be improved
coins = []
re_str = "small/(.*)(.jpg|.png|.JPG|.PNG)"
for coin in n:
if re.search(re_str, coin):
coin_stripped = re.search(re_str, coin).group(1)
coins.append(coin_stripped)
return ",".join(coins)
@log_start_end(log=logger)
def get_top_crypto_categories(sort_filter: str = SORT_VALUES[0]) -> pd.DataFrame:
"""Returns top crypto categories [Source: CoinGecko]
Parameters
----------
sort_filter : str
Can be one of - "market_cap_desc", "market_cap_asc", "name_desc", "name_asc",
"market_cap_change_24h_desc", "market_cap_change_24h_asc"
Returns
-------
pd.DataFrame
Rank, Name, Change_1h, Change_7d, Market_Cap, Volume_24h,Coins, Url
"""
if sort_filter in SORT_VALUES:
client = CoinGeckoAPI()
data = client.get_coins_categories()
df = pd.DataFrame(data)
del df["id"]
del df["content"]
del df["updated_at"]
df["top_3_coins"] = df["top_3_coins"].apply(lambda_coin_formatter)
df.columns = [
lambda_replace_underscores_in_column_names(col)
if isinstance(col, str)
else col
for col in df.columns
]
return df
return pd.DataFrame()
# TODO: add string with overview
@log_start_end(log=logger)
def get_stable_coins(
limit: int = 15, sortby: str = "Market_Cap_[$]", ascend: bool = False
) -> pd.DataFrame:
"""Returns top stable coins [Source: CoinGecko]
Parameters
----------
limit: int
How many rows to show
sortby: str
Key by which to sort data, default is Market_Cap_[$]
ascend: bool
Flag to sort data ascending
Returns
-------
pd.DataFrame
Dataframe with stable coins data
Examples
--------
>>> from openbb_terminal.sdk import openbb
>>> openbb.crypto.ov.stables(sortby="Volume_[$]", ascend=True, limit=10)
"""
df = get_coins(limit=limit, category="stablecoins")
df = df[COINS_COLUMNS]
df = df.set_axis(
[
"Symbol",
"Name",
"Price_[$]",
"Market_Cap_[$]",
"Market_Cap_Rank",
"Change_7d_[%]",
"Change_24h_[%]",
"Volume_[$]",
],
axis=1,
copy=False,
)
total_market_cap = int(df["Market_Cap_[$]"].sum())
df[f"Percentage_[%]_of_top_{limit}"] = (
df["Market_Cap_[$]"] / total_market_cap
) * 100
sortby = sortby.replace(" ", "_")
df = df.sort_values(by=sortby, ascending=ascend)
return df
@log_start_end(log=logger)
def get_exchanges(sortby: str = "Rank", ascend: bool = True) -> pd.DataFrame:
"""Get list of top exchanges from CoinGecko API [Source: CoinGecko]
Parameters
----------
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data descending
Returns
-------
pd.DataFrame
Trust_Score, Id, Name, Country, Year_Established, Trade_Volume_24h_BTC, Url
"""
client = CoinGeckoAPI()
df = pd.DataFrame(client.get_exchanges_list(per_page=250))
df.replace({float(np.NaN): None}, inplace=True)
df = df[
[
"trust_score",
"id",
"name",
"country",
"year_established",
"trade_volume_24h_btc",
"url",
]
]
df.columns = [
"Trust_Score",
"Id",
"Name",
"Country",
"Year_Established",
"Trade_Volume_24h_BTC",
"Url",
]
create_df_index(df, "Rank")
if sortby == "Rank":
df = df.sort_values(by=sortby, ascending=not ascend)
else:
df = df.sort_values(by=sortby, ascending=ascend)
return df
@log_start_end(log=logger)
def get_financial_platforms(sortby: str = "Name", ascend: bool = True) -> pd.DataFrame:
"""Get list of financial platforms from CoinGecko API [Source: CoinGecko]
Parameters
----------
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data ascending
Returns
-------
pd.DataFrame
Rank, Name, Category, Centralized, Url
"""
client = CoinGeckoAPI()
df = pd.DataFrame(client.get_finance_platforms())
df.drop("facts", axis=1, inplace=True)
create_df_index(df, "rank")
df.columns = ["Rank", "Name", "Category", "Centralized", "Url"]
df = df.sort_values(by=sortby, ascending=ascend)
return df
@log_start_end(log=logger)
def get_finance_products(sortby: str = "Name", ascend: bool = True) -> pd.DataFrame:
"""Get list of financial products from CoinGecko API
Parameters
----------
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data ascending
Returns
-------
pd.DataFrame
Rank, Platform, Identifier, Supply_Rate, Borrow_Rate
"""
client = CoinGeckoAPI()
df = pd.DataFrame(
client.get_finance_products(per_page=250),
columns=[
"platform",
"identifier",
"supply_rate_percentage",
"borrow_rate_percentage",
],
)
df.columns = ["Platform", "Identifier", "Supply_Rate", "Borrow_Rate"]
create_df_index(df, "Rank")
df = df.sort_values(by=sortby, ascending=ascend)
return df
@log_start_end(log=logger)
def get_indexes(sortby: str = "Name", ascend: bool = True) -> pd.DataFrame:
"""Get list of crypto indexes from CoinGecko API [Source: CoinGecko]
Parameters
----------
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data ascending
Returns
-------
pd.DataFrame
Name, Id, Market, Last, MultiAsset
"""
client = CoinGeckoAPI()
df = pd.DataFrame(client.get_indexes(per_page=250))
df.columns = ["Name", "Id", "Market", "Last", "MultiAsset"]
create_df_index(df, "Rank")
df = df.sort_values(by=sortby, ascending=ascend)
return df
@log_start_end(log=logger)
def get_derivatives(sortby: str = "Rank", ascend: bool = False) -> pd.DataFrame:
"""Get list of crypto derivatives from CoinGecko API [Source: CoinGecko]
Parameters
----------
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data descending
Returns
-------
pd.DataFrame
Rank, Market, Symbol, Price, Pct_Change_24h, Contract_Type, Basis, Spread,
Funding_Rate, Volume_24h,
"""
client = CoinGeckoAPI()
df = pd.DataFrame(client.get_derivatives(include_tickers="unexpired"))
df.drop(
["index", "last_traded_at", "expired_at", "index_id", "open_interest"],
axis=1,
inplace=True,
)
df.rename(columns={"price_percentage_change_24h": "pct_change_24h"}, inplace=True)
create_df_index(df, "rank")
df["price"] = df["price"].apply(
lambda x: "" if not x else float(x.strip("$").replace(",", ""))
)
df.columns = [
"Rank",
"Market",
"Symbol",
"Price",
"Pct_Change_24h",
"Contract_Type",
"Basis",
"Spread",
"Funding_Rate",
"Volume_24h",
]
df = df.sort_values(by=sortby, ascending=ascend)
return df
@log_start_end(log=logger)
def get_exchange_rates(sortby: str = "Name", ascend: bool = False) -> pd.DataFrame:
"""Get list of crypto, fiats, commodity exchange rates from CoinGecko API [Source: CoinGecko]
Parameters
----------
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data ascending
Returns
-------
pd.DataFrame
Index, Name, Unit, Value, Type
"""
client = CoinGeckoAPI()
df = pd.DataFrame(client.get_exchange_rates()["rates"]).T.reset_index()
df.drop("index", axis=1, inplace=True)
create_df_index(df, "index")
df.columns = ["Index", "Name", "Unit", "Value", "Type"]
df = df.sort_values(by=sortby, ascending=ascend)
return df
@log_start_end(log=logger)
def get_global_info() -> pd.DataFrame:
"""Get global statistics about crypto from CoinGecko API like:
- market cap change
- number of markets
- icos
- number of active crypto
[Source: CoinGecko]
Returns
-------
pd.DataFrame
Metric, Value
"""
client = CoinGeckoAPI()
results = client.get_global()
total_mcap = results.pop("market_cap_percentage")
btc, eth = total_mcap.get("btc"), total_mcap.get("eth")
for key in ["total_market_cap", "total_volume", "updated_at"]:
del results[key]
results["btc_market_cap_in_pct"] = btc
results["eth_market_cap_in_pct"] = eth
results["altcoin_market_cap_in_pct"] = 100 - (float(eth) + float(btc))
df = pd.Series(results).reset_index()
df.columns = ["Metric", "Value"]
df["Metric"] = df["Metric"].apply(
lambda x: lambda_replace_underscores_in_column_names(x)
if isinstance(x, str)
else x
)
return df
@log_start_end(log=logger)
def get_global_markets_info() -> pd.DataFrame:
"""Get global statistics about crypto markets from CoinGecko API like:
Market_Cap, Volume, Market_Cap_Percentage
[Source: CoinGecko]
Returns
-------
pd.DataFrame
Market_Cap, Volume, Market_Cap_Percentage
"""
columns = [
"Market_Cap",
"Volume",
"Market_Cap_Percentage",
]
data = []
client = CoinGeckoAPI()
results = client.get_global()
for key in columns:
data.append(results.get(key))
df = pd.DataFrame(data).T
df.columns = columns
df.replace({float("nan"): None}, inplace=True)
return df.reset_index()
@log_start_end(log=logger)
def get_global_defi_info() -> pd.DataFrame:
"""Get global statistics about Decentralized Finances [Source: CoinGecko]
Returns
-------
pd.DataFrame
Metric, Value
"""
client = CoinGeckoAPI()
results = client.get_global_decentralized_finance_defi()
for key, value in results.items():
try:
results[key] = round(float(value), 4)
except (ValueError, TypeError):
pass
df = pd.Series(results).reset_index()
df.columns = ["Metric", "Value"]
df["Metric"] = df["Metric"].apply(
lambda x: lambda_replace_underscores_in_column_names(x)
if isinstance(x, str)
else x
)
return df