Files
OpenBB/openbb_terminal/cryptocurrency/discovery/pycoingecko_model.py
teh_coderer 59d8b36bb0 [IMPROVE] Fix Docstring formatting/Fix missing, incomplete type hints (#3412)
* Fixes

* Update stocks_helper.py

* update git-actions set-output to new format

* Update stocks_helper.py

* Update terminal_helper.py

* removed LineAnnotateDrawer from qa_view

* lint

* few changes

* updates

* sdk auto gen modules done

* Update stocks_helper.py

* updates to changed imports, and remove first sdk_modules

* Update generate_sdk.py

* Update generate_sdk.py

* pylint

* revert stocks_helper

* Update generate_sdk.py

* Update sdk.py

* Update generate_sdk.py

* full auto generation, added sdk.py/controllers creation

* missed enable forecasting

* added running black in subprocess after sdk files generation completes

* removed deleted sdk_arg_logger

* comment out tests

* property doc fix

* clean up

* Update generate_sdk.py

* make trailmap classes useable for doc generation

* Update generate_sdk.py

* added lineon to trailmap class for linking to func in markdown

* changed lineon to dict

* added full_path to trailmap for linking in docs

* updated portfolio

* feat: initial files

* feat: added meta head

* feat: added funcdef

* added func_def to trailmap attributes for markdown in docs, added missing type hints to covid functions

* feat: added view and merged with jaun

* Update generate_sdk.py

* Update generate_sdk.py

* Update generate_sdk.py

* Update generate_sdk.py

* init

* fix returns

* fix: random stuff

* fix: random

* fixed encoding issue on windows

* fix: generate tabs

* update

* Update generate_sdk_markdown.py

* Create .pydocstyle.ini

* added type hint classes for views

* fixes

* alt, ba

* alt-economy

* Update finviz_compare_model.py

* fixs

* Update substack_model.py

* Update generate_sdk.py

* last of my section

* porfolio

* po

* Update optimizer_model.py

* fixing more things

* few more

* keys done

* update

* fixes

* Update generate_sdk_markdown.py

* Update generate_sdk_markdown.py

* mypy forecast fix

* Update generate_sdk_markdown.py

* Update generate_sdk_markdown.py

* Update generate_sdk_markdown.py

* fixes

* forecast fixes

* one more fix

* Update coinbase_model.py

* Update generate_sdk_markdown.py

Co-authored-by: Colin Delahunty <72827203+colin99d@users.noreply.github.com>
Co-authored-by: James Maslek <jmaslek11@gmail.com>
Co-authored-by: jose-donato <zmcdonato@gmail.com>
Co-authored-by: andrewkenreich <andrew.kenreich@gmail.com>
2022-11-15 16:37:49 -05:00

403 lines
10 KiB
Python

"""CoinGecko model"""
__docformat__ = "numpy"
import json
import logging
import os
from typing import List
import pandas as pd
from pycoingecko import CoinGeckoAPI
from openbb_terminal.decorators import log_start_end
logger = logging.getLogger(__name__)
COINS_COLUMNS_MAP = {
"Symbol": "symbol",
"Name": "name",
"Volume [$]": "total_volume",
"Market Cap": "market_cap",
"Market Cap Rank": "market_cap_rank",
"7D Change [%]": "price_change_percentage_7d_in_currency",
"24H Change [%]": "price_change_percentage_24h_in_currency",
}
PERIODS = {
"1h": "?time=h1",
"24h": "?time=h24",
"7d": "?time=d7",
"14d": "?time=d14",
"30d": "?time=d30",
"60d": "?time=d60",
"1y": "?time=y1",
}
API_PERIODS = ["14d", "1h", "1y", "200d", "24h", "30d", "7d"]
CATEGORIES = {
"trending": 0,
"most_voted": 1,
"positive_sentiment": 2,
"recently_added": 3,
"most_visited": 4,
}
GAINERS_FILTERS = ["Rank", "Symbol", "Name", "Volume", "Price", "Change"]
TRENDING_FILTERS = [
"Rank",
"Name",
"Price_BTC",
"Price_USD",
]
RECENTLY_FILTERS = [
"Rank",
"Name",
"Symbol",
"Price",
"Change_1h",
"Change_24h",
"Added",
"Url",
]
YFARMS_FILTERS = [
"Rank",
"Name",
"Value_Locked",
"Return_Year",
]
CAP_FILTERS = [
"Rank",
"Name",
"Symbol",
"Price",
"Change_1h",
"Change_24h",
"Change_7d",
"Volume_24h",
"Market_Cap",
]
DEX_FILTERS = [
"Name",
"Rank",
"Volume_24h",
"Coins",
"Pairs",
"Visits",
"Most_Traded",
"Market_Share",
]
GAINERS_LOSERS_COLUMNS = [
"Symbol",
"Name",
"Price [$]",
"Market Cap",
"Market Cap Rank",
"Volume [$]",
]
@log_start_end(log=logger)
def read_file_data(file_name: str) -> dict:
if file_name.split(".")[1] != "json":
raise TypeError("Please load json file")
par_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
path = os.path.join(par_dir, "data", file_name)
with open(path, encoding="utf8") as f:
data = json.load(f)
return data
@log_start_end(log=logger)
def get_categories_keys() -> List[str]:
"""Get list of categories keys
Returns
-------
List[str]
List of categories keys
"""
categories = read_file_data("coingecko_categories.json")
return list(categories.keys())
@log_start_end(log=logger)
def get_coins(
limit: int = 250,
category: str = "",
sortby: str = "Symbol",
ascend: bool = False,
) -> pd.DataFrame:
"""Get N coins from CoinGecko [Source: CoinGecko]
Parameters
----------
limit: int
Number of top coins to grab from CoinGecko
category: str
Category of the coins we want to retrieve
sortby: str
Key to sort data
ascend: bool
Sort data in ascending order
Returns
-------
pd.DataFrame
N coins
"""
client = CoinGeckoAPI()
df = pd.DataFrame()
table_size = limit
# CoinGecko's API returns all coins without limit when the category is set.
if category:
kwargs = {
"vs_currency": "usd",
"order": "market_cap_desc",
"per_page": limit,
"sparkline": False,
"price_change_percentage": "1h,24h,7d,14d,30d,200d,1y",
"category": category,
}
data = client.get_coins_markets(**kwargs)
df = pd.concat([df, pd.DataFrame(data)], ignore_index=True)
else:
page_size = min(limit, 250)
page = 1
while limit > 0:
kwargs = {
"vs_currency": "usd",
"order": "market_cap_desc",
"per_page": page_size,
"sparkline": False,
"price_change_percentage": "1h,24h,7d,14d,30d,200d,1y",
"page": page,
}
data = client.get_coins_markets(**kwargs)
df = pd.concat([df, pd.DataFrame(data)], ignore_index=True)
limit -= page_size
page += 1
if sortby in COINS_COLUMNS_MAP:
df = df[(df["total_volume"].notna()) & (df["market_cap"].notna())]
df = df.sort_values(by=COINS_COLUMNS_MAP[sortby], ascending=ascend)
df = df.astype({"market_cap_rank": "Int64"})
return df.head(table_size)
@log_start_end(log=logger)
def get_gainers_or_losers(
limit: int = 20,
interval: str = "1h",
typ: str = "gainers",
sortby: str = "market_cap",
) -> pd.DataFrame:
"""Returns data about top gainers - coins which gain the most in given period and
top losers - coins that lost the most in given period of time. [Source: CoinGecko]
Parameters
----------
limit: int
Num of coins to get
sortby: str
Key to sort data. The table can be sorted by every of its columns. Refer to
API documentation (see /coins/markets in https://www.coingecko.com/en/api/documentation)
interval: str
One from {14d,1h,1y,200d,24h,30d,7d}
typ: str
Either "gainers" or "losers"
Returns
-------
pd.DataFrame
Top Gainers / Top Losers - coins which gain/lost most in price in given period of time.
Columns: Symbol, Name, Volume, Price, %Change_{interval}, Url
"""
if interval not in API_PERIODS:
raise ValueError(
f"Wrong time period\nPlease chose one from list: {API_PERIODS}"
)
df = get_coins(limit)
sorted_df = df.sort_values(
by=[f"price_change_percentage_{interval}_in_currency"],
ascending=typ != "gainers",
)
sorted_df = sorted_df[
[
"symbol",
"name",
"current_price",
"market_cap",
"market_cap_rank",
"total_volume",
f"price_change_percentage_{interval}_in_currency",
]
]
sorted_df = sorted_df.set_axis(
GAINERS_LOSERS_COLUMNS + [f"Change {interval} [%]"],
axis=1,
copy=True,
)
if sortby in GAINERS_LOSERS_COLUMNS:
sorted_df = sorted_df[
(sorted_df["Volume [$]"].notna()) & (sorted_df["Market Cap"].notna())
]
sorted_df = sorted_df.sort_values(by=sortby, ascending=True)
return sorted_df
def get_gainers(
interval: str = "1h",
limit: int = 50,
sortby: str = "market_cap_rank",
) -> pd.DataFrame:
"""Shows Largest Gainers - coins which gain the most in given period. [Source: CoinGecko]
Parameters
----------
interval: str
Time interval by which data is displayed. One from [1h, 24h, 7d, 14d, 30d, 60d, 1y]
limit: int
Number of records to display
sortby: str
Key to sort data. The table can be sorted by every of its columns. Refer to
API documentation (see /coins/markets in https://www.coingecko.com/en/api/documentation)
Returns
-------
pd.DataFrame
Top Gainers - coins which gain most in price in given period of time.
Columns: Symbol, Name, Volume, Price, %Change_{interval}, Url
"""
return get_gainers_or_losers(
limit=limit, interval=interval, typ="gainers", sortby=sortby
)
def get_losers(
interval: str = "1h",
limit: int = 50,
sortby: str = "market_cap_rank",
) -> pd.DataFrame:
"""Shows Largest Losers - coins which lose the most in given period. [Source: CoinGecko]
Parameters
----------
interval: str
Time interval by which data is displayed. One from [1h, 24h, 7d, 14d, 30d, 60d, 1y]
limit: int
Number of records to display
sortby: str
Key to sort data. The table can be sorted by every of its columns. Refer to
API documentation (see /coins/markets in https://www.coingecko.com/en/api/documentation)
Returns
-------
pd.DataFrame
Top Losers - coins which lost most in price in given period of time.
Columns: Symbol, Name, Volume, Price, %Change_{interval}, Url
"""
return get_gainers_or_losers(
limit=limit, interval=interval, typ="losers", sortby=sortby
)
@log_start_end(log=logger)
def get_trending_coins() -> pd.DataFrame:
"""Returns trending coins [Source: CoinGecko]
Parameters
----------
Returns
-------
pd.DataFrame
Trending Coins
"""
client = CoinGeckoAPI()
data = client.get_search_trending()
coins = data["coins"]
df = pd.DataFrame(columns=["Symbol", "Name", "market_cap Cap Rank"])
for i, coin in enumerate(coins):
coin = coin["item"]
df.loc[i] = [coin["id"], coin["name"], coin["market_cap_rank"]]
return df
@log_start_end(log=logger)
def get_coin_list() -> pd.DataFrame:
"""Get list of coins available on CoinGecko [Source: CoinGecko]
Returns
-------
pd.DataFrame
Coins available on CoinGecko
Columns: id, symbol, name
"""
client = CoinGeckoAPI()
return pd.DataFrame(
client.get_coins_list(),
columns=["id", "symbol", "name"],
).reset_index()
@log_start_end(log=logger)
def get_coins_for_given_exchange(exchange_id: str = "binance", page: int = 1) -> dict:
"""Helper method to get all coins available on binance exchange [Source: CoinGecko]
Parameters
----------
exchange_id: str
id of exchange
page: int
number of page. One page contains 100 records
Returns
-------
dict
dictionary with all trading pairs on binance
"""
client = CoinGeckoAPI()
binance_coins = client.get_exchanges_tickers_by_id(id=exchange_id, page=page)
return binance_coins["tickers"]
@log_start_end(log=logger)
def get_mapping_matrix_for_exchange(exchange_id: str, pages: int = 12) -> dict:
"""Creates a matrix with all coins available on Binance with corresponding coingecko coin_id. [Source: CoinGecko]
Parameters
----------
exchange_id: str
id of exchange: binance
pages: int
number of pages. One page contains 100 records
Returns
-------
dict
dictionary with all coins: {"ETH" : "ethereum"}
"""
coins_dct = {}
for i in range(pages):
coins = get_coins_for_given_exchange(exchange_id=exchange_id, page=i)
for coin in coins:
bin_symbol, gecko_id = coin["base"], coin["coin_id"]
if bin_symbol not in coins_dct:
coins_dct[bin_symbol] = gecko_id
return coins_dct