Files
OpenBB/openbb_terminal/cryptocurrency/overview/pycoingecko_view.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

681 lines
19 KiB
Python

"""CoinGecko view"""
__docformat__ = "numpy"
import logging
import os
from typing import List, Optional
import squarify
from matplotlib import pyplot as plt
from matplotlib import ticker
from matplotlib import cm
from pandas.plotting import register_matplotlib_converters
from openbb_terminal import config_terminal as cfg
import openbb_terminal.cryptocurrency.overview.pycoingecko_model as gecko
from openbb_terminal import feature_flags as obbff
from openbb_terminal.config_plot import PLOT_DPI
from openbb_terminal.cryptocurrency.dataframe_helpers import (
lambda_long_number_format_with_type_check,
)
from openbb_terminal.decorators import log_start_end
from openbb_terminal.helper_funcs import (
export_data,
plot_autoscale,
print_rich_table,
is_valid_axes_count,
)
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
register_matplotlib_converters()
# pylint: disable=R0904, C0302
@log_start_end(log=logger)
def display_crypto_heatmap(
category: str = "",
limit: int = 15,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Shows cryptocurrencies heatmap [Source: CoinGecko]
Parameters
----------
caterogy: str
Category (e.g., stablecoins). Empty for no category (default: )
limit: int
Number of top cryptocurrencies to display
export: str
Export dataframe data to csv,json,xlsx
external_axes : Optional[List[plt.Axes]], optional
External axes (1 axis is expected in the list), by default None
"""
df = gecko.get_coins(limit, category)
if df.empty:
console.print("\nNo cryptocurrencies found\n")
else:
df = df.fillna(
0
) # to prevent errors with rounding when values aren't available
max_abs = max(
-df.price_change_percentage_24h_in_currency.min(),
df.price_change_percentage_24h_in_currency.max(),
)
cmapred = cm.get_cmap("Reds", 100)
cmapgreen = cm.get_cmap("Greens", 100)
colors = list()
for val in df.price_change_percentage_24h_in_currency / max_abs:
if val > 0:
colors.append(cmapgreen(round(val * 100)))
else:
colors.append(cmapred(-round(val * 100)))
# This plot has 1 axis
if external_axes is None:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
elif is_valid_axes_count(external_axes, 1):
(ax,) = external_axes
else:
return
category_str = f"[{category}]" if category else ""
df_copy = df
the_row = "price_change_percentage_24h_in_currency"
df_copy["symbol"] = df_copy.apply(
lambda row: f"{row['symbol'].upper()}\n{round(row[the_row], 2)}%",
axis=1,
)
# index needs to get sorted - was matching with different values
df.sort_index(inplace=True)
df_copy.sort_index(inplace=True)
squarify.plot(
df["market_cap"],
alpha=0.5,
color=colors,
)
text_sizes = squarify.normalize_sizes(df["market_cap"], 100, 100)
rects = squarify.squarify(text_sizes, 0, 0, 100, 100)
for la, r in zip(df_copy["symbol"], rects):
x, y, dx, dy = r["x"], r["y"], r["dx"], r["dy"]
ax.text(
x + dx / 2,
y + dy / 2,
la,
va="center",
ha="center",
color="black",
size=(
text_sizes[df_copy.index[df_copy["symbol"] == la].tolist()[0]]
** 0.5
* 0.8
),
)
ax.set_title(f"Top {limit} Cryptocurrencies {category_str}")
ax.set_axis_off()
cfg.theme.style_primary_axis(ax)
if not external_axes:
cfg.theme.visualize_output()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"hm",
df,
)
@log_start_end(log=logger)
def display_holdings_overview(
symbol: str, show_bar: bool = False, export: str = "", limit: int = 15
) -> None:
"""Shows overview of public companies that holds ethereum or bitcoin. [Source: CoinGecko]
Parameters
----------
symbol: str
Cryptocurrency: ethereum or bitcoin
show_bar : bool
Whether to show a bar graph for the data
export: str
Export dataframe data to csv,json,xlsx
limit: int
The number of rows to show
"""
res = gecko.get_holdings_overview(symbol)
stats_string = res[0]
df = res[1]
df = df.head(limit)
if df.empty:
console.print("\nZero companies holding this crypto\n")
else:
if show_bar:
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
for _, row in df.iterrows():
ax.bar(x=row["Symbol"], height=row["Total Holdings"])
if symbol == "bitcoin":
ax.set_ylabel("BTC Number")
else:
ax.set_ylabel("ETH Number")
ax.get_yaxis().set_major_formatter(
ticker.FuncFormatter(
lambda x, _: lambda_long_number_format_with_type_check(x)
)
)
ax.set_xlabel("Company Symbol")
fig.tight_layout(pad=8)
if symbol == "bitcoin":
ax.set_title("Total BTC Holdings per company")
else:
ax.set_title("Total ETH Holdings per company")
ax.tick_params(axis="x", labelrotation=90)
console.print(f"\n{stats_string}\n")
df = df.applymap(lambda x: lambda_long_number_format_with_type_check(x))
print_rich_table(
df,
headers=list(df.columns),
show_index=False,
title="Public Companies Holding BTC or ETH",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"cghold",
df,
)
@log_start_end(log=logger)
def display_exchange_rates(
sortby: str = "Name", ascend: bool = False, limit: int = 15, export: str = ""
) -> None:
"""Shows list of crypto, fiats, commodity exchange rates. [Source: CoinGecko]
Parameters
----------
limit: int
Number of records to display
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data ascending
export : str
Export dataframe data to csv,json,xlsx file
"""
df = gecko.get_exchange_rates(sortby, ascend)
if not df.empty:
print_rich_table(
df.head(limit),
headers=list(df.columns),
show_index=False,
title="Exchange Rates",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"exrates",
df,
)
else:
console.print("Unable to retrieve data from CoinGecko.")
@log_start_end(log=logger)
def display_global_market_info(pie: bool = False, export: str = "") -> None:
"""Shows global statistics about crypto. [Source: CoinGecko]
- market cap change
- number of markets
- icos
- number of active crypto
- market_cap_pct
Parameters
----------
pie: bool
Whether to show a pie chart
export : str
Export dataframe data to csv,json,xlsx file
"""
df = gecko.get_global_info()
if not df.empty:
if pie:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
ax.pie(
[
round(
df.loc[df["Metric"] == "Btc Market Cap In Pct"]["Value"].item(),
2,
),
round(
df.loc[df["Metric"] == "Eth Market Cap In Pct"]["Value"].item(),
2,
),
round(
df.loc[df["Metric"] == "Altcoin Market Cap In Pct"][
"Value"
].item(),
2,
),
],
labels=["BTC", "ETH", "Altcoins"],
wedgeprops={"linewidth": 0.5, "edgecolor": "white"},
labeldistance=1.05,
autopct="%1.0f%%",
startangle=90,
)
ax.set_title("Market cap distribution")
if obbff.USE_ION:
plt.ion()
plt.show()
print_rich_table(
df, headers=list(df.columns), show_index=False, title="Global Statistics"
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"cgglobal",
df,
)
else:
console.print("Unable to retrieve data from CoinGecko.")
@log_start_end(log=logger)
def display_global_defi_info(export: str = "") -> None:
"""Shows global statistics about Decentralized Finances. [Source: CoinGecko]
Parameters
----------
export : str
Export dataframe data to csv,json,xlsx file
"""
df = gecko.get_global_defi_info()
if not df.empty:
print_rich_table(
df,
headers=list(df.columns),
show_index=False,
title="Global DEFI Statistics",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"defi",
df,
)
else:
console.print("Unable to retrieve data from CoinGecko.")
@log_start_end(log=logger)
def display_stablecoins(
limit: int = 15,
export: str = "",
sortby: str = "Market_Cap_[$]",
ascend: bool = False,
pie: bool = True,
) -> None:
"""Shows stablecoins data [Source: CoinGecko]
Parameters
----------
limit: int
Number of records to display
sortby: str
Key by which to sort data, default is Market_Cap_[$]
ascend: bool
Flag to sort data ascending
pie: bool
Whether to show a pie chart, default is True
export : str
Export dataframe data to csv,json,xlsx file
pie : bool
Whether to show a pie chart
Examples
--------
>>> from openbb_terminal.sdk import openbb
>>> openbb.crypto.ov.stables_chart(sortby="Volume_[$]", ascend=True, limit=10)
"""
df = gecko.get_stable_coins(limit, sortby=sortby, ascend=ascend)
if not df.empty:
total_market_cap = int(df["Market_Cap_[$]"].sum())
df.columns = df.columns.str.replace("_", " ")
if pie:
stables_to_display = df[df[f"Percentage [%] of top {limit}"] >= 1]
other_stables = df[df[f"Percentage [%] of top {limit}"] < 1]
values_list = list(
stables_to_display[f"Percentage [%] of top {limit}"].values
)
values_list.append(other_stables[f"Percentage [%] of top {limit}"].sum())
labels_list = list(stables_to_display["Name"].values)
labels_list.append("Others")
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
ax.pie(
values_list,
labels=labels_list,
wedgeprops={"linewidth": 0.5, "edgecolor": "white"},
labeldistance=1.05,
autopct="%1.0f%%",
startangle=90,
)
ax.set_title(f"Market cap distribution of top {limit} Stablecoins")
if obbff.USE_ION:
plt.ion()
plt.show()
console.print(
f"First {limit} stablecoins have a total "
f"{lambda_long_number_format_with_type_check(total_market_cap)}"
"dollars of market cap.\n"
)
df = df.applymap(lambda x: lambda_long_number_format_with_type_check(x))
print_rich_table(
df.head(limit),
headers=list(df.columns),
show_index=False,
title="Stablecoin Data",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"cgstables",
df,
)
else:
console.print("\nUnable to retrieve data from CoinGecko.\n")
@log_start_end(log=logger)
def display_categories(
sortby: str = "market_cap_desc",
limit: int = 15,
export: str = "",
pie: bool = False,
) -> None:
"""Shows top cryptocurrency categories by market capitalization
The cryptocurrency category ranking is based on market capitalization. [Source: CoinGecko]
Parameters
----------
sortby: str
Key by which to sort data
limit: int
Number of records to display
export: str
Export dataframe data to csv,json,xlsx file
pie: bool
Whether to show the pie chart
"""
df = gecko.get_top_crypto_categories(sortby)
df_data = df
if not df.empty:
if pie:
df_data[f"% relative to top {limit}"] = (
df_data["Market Cap"] / df_data["Market Cap"].sum()
) * 100
stables_to_display = df_data[df_data[f"% relative to top {limit}"] >= 1]
other_stables = df_data[df_data[f"% relative to top {limit}"] < 1]
values_list = list(stables_to_display[f"% relative to top {limit}"].values)
values_list.append(other_stables[f"% relative to top {limit}"].sum())
labels_list = list(stables_to_display["Name"].values)
labels_list.append("Others")
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
ax.pie(
values_list,
labels=labels_list,
wedgeprops={"linewidth": 0.5, "edgecolor": "white"},
autopct="%1.0f%%",
startangle=90,
)
ax.set_title(f"Market Cap distribution of top {limit} crypto categories")
if obbff.USE_ION:
plt.ion()
plt.show()
df = df.applymap(lambda x: lambda_long_number_format_with_type_check(x))
print_rich_table(
df.head(limit),
headers=list(df.columns),
floatfmt=".2f",
show_index=False,
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"cgcategories",
df_data,
)
else:
console.print("\nUnable to retrieve data from CoinGecko.\n")
@log_start_end(log=logger)
def display_exchanges(
sortby: str = "Rank",
ascend: bool = False,
limit: int = 15,
links: bool = False,
export: str = "",
) -> None:
"""Shows list of top exchanges from CoinGecko. [Source: CoinGecko]
Parameters
----------
limit: int
Number of records to display
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data descending
links: bool
Flag to display urls
export : str
Export dataframe data to csv,json,xlsx file
"""
df = gecko.get_exchanges(sortby, ascend)
if not df.empty:
if links is True:
df = df[["Rank", "Name", "Url"]]
else:
df.drop("Url", axis=1, inplace=True)
print_rich_table(
df.head(limit),
headers=list(df.columns),
show_index=False,
title="Top CoinGecko Exchanges",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"exchanges",
df,
)
else:
console.print("Unable to retrieve data from CoinGecko.")
@log_start_end(log=logger)
def display_platforms(
sortby: str = "Name", ascend: bool = True, limit: int = 15, export: str = ""
) -> None:
"""Shows list of financial platforms. [Source: CoinGecko]
Parameters
----------
limit: int
Number of records to display
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data ascending
export : str
Export dataframe data to csv,json,xlsx file
"""
df = gecko.get_financial_platforms(sortby, ascend)
if not df.empty:
print_rich_table(
df.head(limit),
headers=list(df.columns),
show_index=False,
title="Financial Platforms",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"platforms",
df,
)
else:
console.print("\nUnable to retrieve data from CoinGecko.\n")
@log_start_end(log=logger)
def display_products(
sortby: str = "Platform", ascend: bool = False, limit: int = 15, export: str = ""
) -> None:
"""Shows list of financial products. [Source: CoinGecko]
Parameters
----------
limit: int
Number of records to display
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data descending
export : str
Export dataframe data to csv,json,xlsx file
"""
df = gecko.get_finance_products(sortby=sortby, ascend=ascend)
if not df.empty:
print_rich_table(
df.head(limit),
headers=list(df.columns),
show_index=False,
title="Financial Products",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"products",
df,
)
else:
console.print("Unable to retrieve data from CoinGecko.")
@log_start_end(log=logger)
def display_indexes(
sortby: str = "Name", ascend: bool = True, limit: int = 15, export: str = ""
) -> None:
"""Shows list of crypto indexes. [Source: CoinGecko]
Parameters
----------
limit: int
Number of records to display
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data descending
export : str
Export dataframe data to csv,json,xlsx file
"""
df = gecko.get_indexes(sortby=sortby, ascend=ascend)
if not df.empty:
print_rich_table(
df.head(limit),
headers=list(df.columns),
show_index=False,
title="Crypto Indexes",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"indexes",
df,
)
else:
console.print("Unable to retrieve data from CoinGecko.")
@log_start_end(log=logger)
def display_derivatives(
sortby: str = "Rank", ascend: bool = False, limit: int = 15, export: str = ""
) -> None:
"""Shows list of crypto derivatives. [Source: CoinGecko]
Parameters
----------
limit: int
Number of records to display
sortby: str
Key by which to sort data
ascend: bool
Flag to sort data descending
export : str
Export dataframe data to csv,json,xlsx file
"""
df = gecko.get_derivatives(sortby=sortby, ascend=ascend)
if not df.empty:
print_rich_table(
df.head(limit),
headers=list(df.columns),
show_index=False,
title="Crypto Derivatives",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"derivatives",
df,
)
else:
console.print("Unable to retrieve data from CoinGecko.")