summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjp <plutakuba@gmail.com>2021-09-05 18:15:35 +0200
committerGitHub <noreply@github.com>2021-09-05 17:15:35 +0100
commit28e3970912b3f81b59ca2de5d77e6034c7e581c1 (patch)
tree932154039fabd19d3ff6ddaf83df6429275b17f9
parenta78f3463d4a1ad853c9ac1205bbb5e8380f03b96 (diff)
Refactoring crypto menu 2nd part (#724)
* Add separate view for finbrain for crypto curreny sentiment analysis * Move json with symbols to separate directory, little refactoring, update readme * Add screenshot of finbrain for PolkaDot * Remove not used methods, remove binance_view, binance_model from discovery menu (It's not needed, as we use all_coins view for finding coins from all sources * Refactoring Due Diligence menu. Changing views, moving argparsers to controller * Refactor cryptomenu. Overview, Discovery, DD menu - move argparsers to controllers, add typing hints, change names of views/models, adjust tests * Adjust tests * Move finbrain and find/coins method to controller * Move report argparser into controller. Adjust tests * Adjust docstrings * Add helper method to take care about retry/wait for coingecko scraping * Fix failing test * Adjust newlines, docstrings, cmd descriptions * Add use tabulate df flag for all crypto views * Add status code for coingecko * Add note, that some coingecko commands can fail Co-authored-by: Jakub Pluta <jakub.pluta@cdq.com>
-rw-r--r--gamestonk_terminal/cryptocurrency/coinpaprika_helpers.py8
-rw-r--r--gamestonk_terminal/cryptocurrency/crypto_controller.py439
-rw-r--r--gamestonk_terminal/cryptocurrency/cryptocurrency_helpers.py750
-rw-r--r--gamestonk_terminal/cryptocurrency/dataframe_helpers.py12
-rw-r--r--gamestonk_terminal/cryptocurrency/discovery/binance_model.py20
-rw-r--r--gamestonk_terminal/cryptocurrency/discovery/binance_view.py88
-rw-r--r--gamestonk_terminal/cryptocurrency/discovery/coinmarketcap_model.py39
-rw-r--r--gamestonk_terminal/cryptocurrency/discovery/coinmarketcap_view.py101
-rw-r--r--gamestonk_terminal/cryptocurrency/discovery/coinpaprika_model.py18
-rw-r--r--gamestonk_terminal/cryptocurrency/discovery/coinpaprika_view.py289
-rw-r--r--gamestonk_terminal/cryptocurrency/discovery/discovery_controller.py1212
-rw-r--r--gamestonk_terminal/cryptocurrency/discovery/pycoingecko_model.py79
-rw-r--r--gamestonk_terminal/cryptocurrency/discovery/pycoingecko_view.py1032
-rw-r--r--gamestonk_terminal/cryptocurrency/due_diligence/binance_model.py33
-rw-r--r--gamestonk_terminal/cryptocurrency/due_diligence/binance_view.py444
-rw-r--r--gamestonk_terminal/cryptocurrency/due_diligence/coinpaprika_model.py112
-rw-r--r--gamestonk_terminal/cryptocurrency/due_diligence/coinpaprika_view.py799
-rw-r--r--gamestonk_terminal/cryptocurrency/due_diligence/dd_controller.py888
-rw-r--r--gamestonk_terminal/cryptocurrency/due_diligence/finbrain_crypto_view.py84
-rw-r--r--gamestonk_terminal/cryptocurrency/due_diligence/pycoingecko_model.py161
-rw-r--r--gamestonk_terminal/cryptocurrency/due_diligence/pycoingecko_view.py559
-rw-r--r--gamestonk_terminal/cryptocurrency/overview/coinpaprika_model.py54
-rw-r--r--gamestonk_terminal/cryptocurrency/overview/coinpaprika_view.py668
-rw-r--r--gamestonk_terminal/cryptocurrency/overview/overview_controller.py1351
-rw-r--r--gamestonk_terminal/cryptocurrency/overview/pycoingecko_model.py94
-rw-r--r--gamestonk_terminal/cryptocurrency/overview/pycoingecko_view.py1093
-rw-r--r--gamestonk_terminal/cryptocurrency/pycoingecko_helpers.py80
-rw-r--r--gamestonk_terminal/cryptocurrency/report/crypto_market_view.py100
-rw-r--r--gamestonk_terminal/cryptocurrency/report/report_controller.py32
-rw-r--r--gamestonk_terminal/cryptocurrency/technical_analysis/ta_controller.py50
-rw-r--r--tests/cassettes/test_cryptocurrency/test_coingecko/test_coin_gainers.yaml1493
-rw-r--r--tests/cassettes/test_cryptocurrency/test_coingecko/test_coin_holding_comapnies.yaml542
-rw-r--r--tests/cassettes/test_cryptocurrency/test_coingecko/test_coin_losers.yaml1491
-rw-r--r--tests/cassettes/test_cryptocurrency/test_coingecko/test_coin_overview.yaml541
-rw-r--r--tests/test_cryptocurrency/test_coingecko_crypto.py121
-rw-r--r--tests/test_cryptocurrency/test_coinpaprika_view.py107
36 files changed, 10390 insertions, 4594 deletions
diff --git a/gamestonk_terminal/cryptocurrency/coinpaprika_helpers.py b/gamestonk_terminal/cryptocurrency/coinpaprika_helpers.py
index b2efd22364a..fbd2b882f2b 100644
--- a/gamestonk_terminal/cryptocurrency/coinpaprika_helpers.py
+++ b/gamestonk_terminal/cryptocurrency/coinpaprika_helpers.py
@@ -30,11 +30,13 @@ class PaprikaSession:
"search": "/search",
}
- def __init__(self, max_retries=5):
+ def __init__(self, max_retries: int = 5):
self.session = requests.Session()
self.session.mount(self.PAPRIKA_BASE_URL, HTTPAdapter(max_retries=max_retries))
- def make_request(self, endpoint: str, payload: Optional[Any] = None, **kwargs):
+ def make_request(
+ self, endpoint: str, payload: Optional[Any] = None, **kwargs: Any
+ ) -> dict:
"""Helper method that handles request for coinpaprika api.
It prepares URL for given endpoint and payload if it's part of requests
@@ -50,8 +52,8 @@ class PaprikaSession:
Returns
-------
dict with response data
-
"""
+
url = f"{self.PAPRIKA_BASE_URL}{endpoint}"
if payload is None:
payload = {}
diff --git a/gamestonk_terminal/cryptocurrency/crypto_controller.py b/gamestonk_terminal/cryptocurrency/crypto_controller.py
index 4a76eec2858..851dbbac310 100644
--- a/gamestonk_terminal/cryptocurrency/crypto_controller.py
+++ b/gamestonk_terminal/cryptocurrency/crypto_controller.py
@@ -7,8 +7,13 @@ import os
import matplotlib.pyplot as plt
import pandas as pd
from prompt_toolkit.completion import NestedCompleter
+from binance.client import Client
from gamestonk_terminal import feature_flags as gtff
-from gamestonk_terminal.helper_funcs import get_flair
+from gamestonk_terminal.helper_funcs import (
+ get_flair,
+ parse_known_args_and_warn,
+ check_positive,
+)
from gamestonk_terminal.menu import session
from gamestonk_terminal.cryptocurrency.technical_analysis import ta_controller
from gamestonk_terminal.cryptocurrency.overview import overview_controller
@@ -24,9 +29,19 @@ from gamestonk_terminal.cryptocurrency.discovery import (
from gamestonk_terminal.cryptocurrency.due_diligence import (
finbrain_crypto_view,
)
+from gamestonk_terminal.cryptocurrency.due_diligence.finbrain_crypto_view import COINS
-from gamestonk_terminal.cryptocurrency.cryptocurrency_helpers import load, find
+from gamestonk_terminal.cryptocurrency.cryptocurrency_helpers import (
+ load,
+ find,
+ load_ta_data,
+ plot_chart,
+)
from gamestonk_terminal.cryptocurrency.report import report_controller
+from gamestonk_terminal.cryptocurrency.due_diligence.binance_model import (
+ show_available_pairs_for_given_symbol,
+)
+import gamestonk_terminal.config_terminal as cfg
class CryptoController:
@@ -100,6 +115,8 @@ What do you want to do?
else "\nSource: ?\n"
)
help_text += """
+Note: Some of CoinGecko commands can fail. Team is working on fix.
+
load load a specific cryptocurrency for analysis
chart view a candle chart for a specific cryptocurrency
find alternate way to search for coins
@@ -160,18 +177,185 @@ What do you want to do?
def call_load(self, other_args):
"""Process load command"""
try:
- self.current_coin, self.source = load(
- coin=self.current_coin, other_args=other_args
+ parser = argparse.ArgumentParser(
+ add_help=False,
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ prog="load",
+ description="Load crypto currency to perform analysis on. "
+ "Available data sources are CoinGecko, CoinPaprika, and Binance"
+ "By default main source used for analysis is CoinGecko (cg). To change it use --source flag",
)
+
+ parser.add_argument(
+ "-c",
+ "--coin",
+ help="Coin to get",
+ dest="coin",
+ type=str,
+ required="-h" not in other_args,
+ )
+
+ parser.add_argument(
+ "-s",
+ "--source",
+ help="Source of data",
+ dest="source",
+ choices=("cp", "cg", "bin"),
+ default="cg",
+ required=False,
+ )
+
+ try:
+ if other_args:
+ if not other_args[0][0] == "-":
+ other_args.insert(0, "-c")
+
+ ns_parser = parse_known_args_and_warn(parser, other_args)
+
+ if not ns_parser:
+ self.current_coin, self.source = self.current_coin, None
+ return
+
+ source = ns_parser.source
+
+ for arg in ["--source", source]:
+ if arg in other_args:
+ other_args.remove(arg)
+
+ self.current_coin, self.source = load(
+ coin=ns_parser.coin, source=ns_parser.source
+ )
+
+ except Exception as e:
+ print(e, "\n")
+ self.current_coin, self.source = self.current_coin, None
+
except TypeError:
print("Couldn't load data\n")
def call_chart(self, other_args):
"""Process chart command"""
if self.current_coin:
- getattr(self.DD_VIEWS_MAPPING[self.source], "chart")(
- self.current_coin, other_args
+ parser = argparse.ArgumentParser(
+ add_help=False,
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ prog="chart",
+ description="""Loads data for technical analysis. You can specify currency vs which you want
+ to show chart and also number of days to get data for.
+ By default currency: usd and days: 30.
+ E.g. if you loaded in previous step Ethereum and you want to see it's price vs btc
+ in last 90 days range use `ta --vs btc --days 90`""",
)
+
+ if self.source == "cp":
+ parser.add_argument(
+ "--vs",
+ default="usd",
+ dest="vs",
+ help="Currency to display vs coin",
+ choices=["usd", "btc", "BTC", "USD"],
+ type=str,
+ )
+
+ parser.add_argument(
+ "-d",
+ "--days",
+ default=30,
+ dest="days",
+ help="Number of days to get data for",
+ type=check_positive,
+ )
+
+ if self.source == "cg":
+ parser.add_argument(
+ "--vs", default="usd", dest="vs", help="Currency to display vs coin"
+ )
+
+ parser.add_argument(
+ "-d",
+ "--days",
+ default=30,
+ dest="days",
+ help="Number of days to get data for",
+ )
+
+ if self.source == "bin":
+ client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET)
+ interval_map = {
+ "1day": client.KLINE_INTERVAL_1DAY,
+ "3day": client.KLINE_INTERVAL_3DAY,
+ "1hour": client.KLINE_INTERVAL_1HOUR,
+ "2hour": client.KLINE_INTERVAL_2HOUR,
+ "4hour": client.KLINE_INTERVAL_4HOUR,
+ "6hour": client.KLINE_INTERVAL_6HOUR,
+ "8hour": client.KLINE_INTERVAL_8HOUR,
+ "12hour": client.KLINE_INTERVAL_12HOUR,
+ "1week": client.KLINE_INTERVAL_1WEEK,
+ "1min": client.KLINE_INTERVAL_1MINUTE,
+ "3min": client.KLINE_INTERVAL_3MINUTE,
+ "5min": client.KLINE_INTERVAL_5MINUTE,
+ "15min": client.KLINE_INTERVAL_15MINUTE,
+ "30min": client.KLINE_INTERVAL_30MINUTE,
+ "1month": client.KLINE_INTERVAL_1MONTH,
+ }
+
+ _, quotes = show_available_pairs_for_given_symbol(self.current_coin)
+
+ parser.add_argument(
+ "--vs",
+ help="Quote currency (what to view coin vs)",
+ dest="vs",
+ type=str,
+ default="USDT",
+ choices=quotes,
+ )
+
+ parser.add_argument(
+ "-i",
+ "--interval",
+ help="Interval to get data",
+ choices=list(interval_map.keys()),
+ dest="interval",
+ default="1day",
+ type=str,
+ )
+
+ parser.add_argument(
+ "-l",
+ "--limit",
+ dest="limit",
+ default=100,
+ help="Number to get",
+ type=check_positive,
+ )
+
+ try:
+ ns_parser = parse_known_args_and_warn(parser, other_args)
+
+ if not ns_parser:
+ return
+
+ if self.source == "bin":
+ limit = ns_parser.limit
+ interval = ns_parser.interval
+ days = 0
+ else:
+ limit = 0
+ interval = "1day"
+ days = ns_parser.days
+
+ plot_chart(
+ coin=self.current_coin,
+ limit=limit,
+ interval=interval,
+ days=days,
+ currency=ns_parser.vs,
+ source=self.source,
+ )
+
+ except Exception as e:
+ print(e, "\n")
+
else:
print(
"No coin selected. Use 'load' to load the coin you want to look at.\n"
@@ -181,9 +365,125 @@ What do you want to do?
"""Process ta command"""
# TODO: Play with this to get correct usage
if self.current_coin:
- self.current_df, self.current_currency = getattr(
- self.DD_VIEWS_MAPPING[self.source], "load_ta_data"
- )(self.current_coin, other_args)
+ parser = argparse.ArgumentParser(
+ add_help=False,
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ prog="ta",
+ description="""Loads data for technical analysis. You can specify currency vs which you want
+ to show chart and also number of days to get data for.
+ By default currency: usd and days: 30.
+ E.g. if you loaded in previous step Ethereum and you want to see it's price vs btc
+ in last 90 days range use `ta --vs btc --days 90`""",
+ )
+
+ if self.source == "cp":
+ parser.add_argument(
+ "--vs",
+ default="usd",
+ dest="vs",
+ help="Currency to display vs coin",
+ choices=["usd", "btc", "BTC", "USD"],
+ type=str,
+ )
+
+ parser.add_argument(
+ "-d",
+ "--days",
+ default=30,
+ dest="days",
+ help="Number of days to get data for",
+ type=check_positive,
+ )
+
+ if self.source == "cg":
+ parser.add_argument(
+ "--vs", default="usd", dest="vs", help="Currency to display vs coin"
+ )
+
+ parser.add_argument(
+ "-d",
+ "--days",
+ default=30,
+ dest="days",
+ help="Number of days to get data for",
+ )
+
+ if self.source == "bin":
+ client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET)
+ interval_map = {
+ "1day": client.KLINE_INTERVAL_1DAY,
+ "3day": client.KLINE_INTERVAL_3DAY,
+ "1hour": client.KLINE_INTERVAL_1HOUR,
+ "2hour": client.KLINE_INTERVAL_2HOUR,
+ "4hour": client.KLINE_INTERVAL_4HOUR,
+ "6hour": client.KLINE_INTERVAL_6HOUR,
+ "8hour": client.KLINE_INTERVAL_8HOUR,
+ "12hour": client.KLINE_INTERVAL_12HOUR,
+ "1week": client.KLINE_INTERVAL_1WEEK,
+ "1min": client.KLINE_INTERVAL_1MINUTE,
+ "3min": client.KLINE_INTERVAL_3MINUTE,
+ "5min": client.KLINE_INTERVAL_5MINUTE,
+ "15min": client.KLINE_INTERVAL_15MINUTE,
+ "30min": client.KLINE_INTERVAL_30MINUTE,
+ "1month": client.KLINE_INTERVAL_1MONTH,
+ }
+
+ _, quotes = show_available_pairs_for_given_symbol(self.current_coin)
+ parser.add_argument(
+ "--vs",
+ help="Quote currency (what to view coin vs)",
+ dest="vs",
+ type=str,
+ default="USDT",
+ choices=quotes,
+ )
+
+ parser.add_argument(
+ "-i",
+ "--interval",
+ help="Interval to get data",
+ choices=list(interval_map.keys()),
+ dest="interval",
+ default="1day",
+ type=str,
+ )
+
+ parser.add_argument(
+ "-l",
+ "--limit",
+ dest="limit",
+ default=100,
+ help="Number to get",
+ type=check_positive,
+ )
+
+ try:
+ ns_parser = parse_known_args_and_warn(parser, other_args)
+
+ if not ns_parser:
+ return
+
+ if self.source == "bin":
+ limit = ns_parser.limit
+ interval = ns_parser.interval
+ days = 0
+ else:
+ limit = 0
+ interval = "1day"
+ days = ns_parser.days
+
+ self.current_df, self.current_currency = load_ta_data(
+ coin=self.current_coin,
+ source=self.source,
+ currency=ns_parser.vs,
+ days=days,
+ limit=limit,
+ interval=interval,
+ )
+
+ except Exception as e:
+ print(e, "\n")
+
if self.current_currency != "" and not self.current_df.empty:
try:
quit = ta_controller.menu(
@@ -225,7 +525,44 @@ What do you want to do?
def call_finbrain(self, other_args):
"""Process finbrain command"""
- finbrain_crypto_view.crypto_sentiment_analysis(other_args=other_args)
+ parser = argparse.ArgumentParser(
+ add_help=False,
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ prog="finbrain",
+ description="""Display sentiment analysis from FinBrain for chosen Cryptocurrencies""",
+ )
+
+ parser.add_argument(
+ "-c",
+ "--coin",
+ default="BTC",
+ type=str,
+ dest="coin",
+ help="Symbol of coin to load data for, ~100 symbols are available",
+ choices=COINS,
+ )
+
+ parser.add_argument(
+ "--export",
+ choices=["csv", "json", "xlsx"],
+ default="",
+ type=str,
+ dest="export",
+ help="Export dataframe data to csv,json,xlsx file",
+ )
+
+ try:
+ ns_parser = parse_known_args_and_warn(parser, other_args)
+
+ if not ns_parser:
+ return
+
+ finbrain_crypto_view.display_crypto_sentiment_analysis(
+ coin=ns_parser.coin, export=ns_parser.export
+ )
+
+ except Exception as e:
+ print(e, "\n")
def call_dd(self, _):
"""Process dd command"""
@@ -251,7 +588,87 @@ What do you want to do?
def call_find(self, other_args):
"""Process find command"""
- find(other_args=other_args)
+ parser = argparse.ArgumentParser(
+ prog="find",
+ add_help=False,
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ description="""
+ Find similar coin by coin name,symbol or id. If you don't remember exact name or id of the Coin at CoinGecko,
+ Binance or CoinPaprika you can use this command to display coins with similar name, symbol or id
+ to your search query.
+ Example of usage: coin name is something like "polka". So I can try: find -c polka -k name -t 25
+ It will search for coin that has similar name to polka and display top 25 matches.
+ -c, --coin stands for coin - you provide here your search query
+ -k, --key it's a searching key. You can search by symbol, id or name of coin
+ -t, --top it displays top N number of records.""",
+ )
+
+ parser.add_argument(
+ "-c",
+ "--coin",
+ help="Symbol Name or Id of Coin",
+ dest="coin",
+ required="-h" not in other_args,
+ type=str,
+ )
+
+ parser.add_argument(
+ "-k",
+ "--key",
+ dest="key",
+ help="Specify by which column you would like to search: symbol, name, id",