mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-28 21:12:16 +00:00
* fix stables * add examples * small fix Co-authored-by: Henrique Joaquim <h.joaquim@campus.fct.unl.pt>
539 lines
13 KiB
Python
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
|