diff --git a/README.md b/README.md index f204eb32be6..f35535093b3 100644 --- a/README.md +++ b/README.md @@ -230,10 +230,11 @@ These are the ones where a key is necessary: * Oanda API: https://developer.oanda.com * CoinMarketCap API: https://coinmarketcap.com/api/ * Finhub API: https://finnhub.io + * Binance: https://binance.us (US) / https://binance.com (Outside US) When these are obtained, don't forget to update [config_terminal.py](/gamestonk_terminal/config_terminal.py). -Alternatively, you can also set them to the following environment variables: GT_API_KEY_ALPHAVANTAGE, GT_API_KEY_FINANCIALMODELINGPREP, GT_API_KEY_QUANDL, GT_API_REDDIT_CLIENT_ID, GT_API_REDDIT_CLIENT_SECRET, GT_API_REDDIT_USERNAME, GT_API_REDDIT_USER_AGENT, GT_API_REDDIT_PASSWORD, GT_API_TWITTER_KEY, GT_API_TWITTER_SECRET_KEY, GT_API_TWITTER_BEARER_TOKEN, GT_API_POLYGON_KEY, GT_FRED_API_KEY, GT_API_NEWS_TOKEN, GT_OANDA_TOKEN, GT_OANDA_ACCOUNT, GT_TRADIER_TOKEN, GT_CMC_API_KEY, GT_CMC_API_KEY, API_FINNHUB_KEY. +Alternatively, you can also set them to the following environment variables: GT_API_KEY_ALPHAVANTAGE, GT_API_KEY_FINANCIALMODELINGPREP, GT_API_KEY_QUANDL, GT_API_REDDIT_CLIENT_ID, GT_API_REDDIT_CLIENT_SECRET, GT_API_REDDIT_USERNAME, GT_API_REDDIT_USER_AGENT, GT_API_REDDIT_PASSWORD, GT_API_TWITTER_KEY, GT_API_TWITTER_SECRET_KEY, GT_API_TWITTER_BEARER_TOKEN, GT_API_POLYGON_KEY, GT_FRED_API_KEY, GT_API_NEWS_TOKEN, GT_OANDA_TOKEN, GT_OANDA_ACCOUNT, GT_TRADIER_TOKEN, GT_CMC_API_KEY, GT_CMC_API_KEY, API_FINNHUB_KEY, GT_API_BINANCE_KEY, GT_API_BINANCE_SECRET. Example: ``` diff --git a/ROADMAP.md b/ROADMAP.md index e2ddc7cf15d..b7c80d2c599 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -199,11 +199,11 @@ ___ ## Cryptocurrencies * [x] Add Coingecko (@jmaslek) - [PR #283](#https://github.com/DidierRLopes/GamestonkTerminal/pull/283) * [x] view top coins from coinmarketcap (@jmaslek) - [PR #378](https://github.com/DidierRLopes/GamestonkTerminal/pull/378) +* [x] Add binance (@jmaslek) [PR #428](#https://github.com/DidierRLopes/GamestonkTerminal/pull/428) **NEXT** * [ ] Add [Coinpaprika](https://coinpaprika.com/api/) * [ ] Add crypto charts -* [ ] Add binance * [ ] Add top altcoin lists --- diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index 5ac456b0be8..32a42a6e67a 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -275,9 +275,17 @@ Command|Description Command|Description ------ | ------------ -`load`| load cryptocurrency data -`view`| load and view cryptocurrency data +[coingecko](#https://www.coingecko.com/en)| +`load`| load cryptocurrency data +`view`| view loaded cryptocurrency data +`trend`| view top 7 coins +[coinmarketcap](#http://coinmarketcap.com)| `top` | view top coins from coinmarketcap +[binance](#http://binance.us)| +`select` | Select a coin/currency +`book`| show order book +`candle`| get klines/candles and plot +`balance`| show coin balance   diff --git a/gamestonk_terminal/config_terminal.py b/gamestonk_terminal/config_terminal.py index 3dfa270ae34..3685f88e7dd 100644 --- a/gamestonk_terminal/config_terminal.py +++ b/gamestonk_terminal/config_terminal.py @@ -33,7 +33,7 @@ API_TWITTER_SECRET_KEY = os.getenv("GT_API_TWITTER_SECRET_KEY") or "REPLACE_ME" API_TWITTER_BEARER_TOKEN = os.getenv("GT_API_TWITTER_BEARER_TOKEN") or "REPLACE_ME" # https://fred.stlouisfed.org/docs/api/api_key.html -API_FRED_KEY = os.getenv("GT_FRED_API_KEY") or "b98e15f1fde39212bce9213f2e3e5afb" +API_FRED_KEY = os.getenv("GT_API_FRED_KEY") or "REPLACE_ME" # https://newsapi.org API_NEWS_TOKEN = os.getenv("GT_API_NEWS_TOKEN") or "REPLACE_ME" @@ -51,14 +51,18 @@ OANDA_ACCOUNT = os.getenv("GT_OANDA_ACCOUNT") or "REPLACE ME" OANDA_TOKEN = os.getenv("GT_OANDA_TOKEN") or "REPLACE ME" # https://tradier.com/products/market-data-api -TRADIER_TOKEN = os.getenv("GT_TRADIER_TOKEN") or "REPLACE_ME" +TRADIER_TOKEN = os.getenv("GT_API_TRADIER_TOKEN") or "REPLACE_ME" # Selenium Webbrowser drivers can be found at https://selenium-python.readthedocs.io/installation.html WEBDRIVER_TO_USE = "chrome" PATH_TO_SELENIUM_DRIVER = None # Replace with "PATH" # https://coinmarketcap.com/api/ -COINMARKETCAP_KEY = os.getenv("GT_CMC_API_KEY") or "REPLACE_ME" +API_CMC_KEY = os.getenv("GT_API_CMC_KEY") or "REPLACE_ME" + +# https://www.binance.com/en/ +API_BINANCE_KEY = os.getenv("GT_API_BINANCE_KEY") or "REPLACE_ME" +API_BINANCE_SECRET = os.getenv("GT_API_BINANCE_SECRET") or "REPLACE_ME" # https://finnhub.io API_FINNHUB_KEY = os.getenv("GT_API_FINNHUB_KEY") or "REPLACE_ME" diff --git a/gamestonk_terminal/cryptocurrency/README.md b/gamestonk_terminal/cryptocurrency/README.md index 4a1b7b48fea..7b2dbabe1db 100644 --- a/gamestonk_terminal/cryptocurrency/README.md +++ b/gamestonk_terminal/cryptocurrency/README.md @@ -2,14 +2,29 @@ This menu aims to explore crypto world, and the usage of the following commands along with an example will be exploited below. +[COINGECKO](#COINGECKO) * [load](#load) * load a given coin vs a given currency [CoinGecko] * [view](#view) * plot the loaded crypto data +* [trend](#trend) + * show top 7 trending coins + +[COINMARKETCAP](#COINMARKETCAP) * [top](#top) * view top coins from coinmarketcap [coinmarketcap.com] +[BINANCE](#BINANCE) +* [select](#select) + * select coin/currency to use +* [book](#book) + * show order book +* [candle](#candle) + * get klines/candles and plot +* [balance](#balance) + * show coin balance +# COINGECKO ## load ```` @@ -35,6 +50,13 @@ Plot the loaded crypto data. ![crypto_view](https://user-images.githubusercontent.com/25267873/115787452-20889a80-a3ba-11eb-9216-f7fd1ffc98cf.png) +## trend +```` +usage: trend +```` +Print the top 7 trending coins from coingecko + +# COINMARKETCAP ## top @@ -50,3 +72,45 @@ This command displays the top n cryptocurrencies from coinmarketcap.com. crypto +# BINANCE +## select + +```` +usage: select [-c --coin] [-q --quote] +```` +Select a coin/currency to the current object. Note that in binance, the exchange "ticker" is usually COINCURR, such as BTCEUR +for BTC to EURO. There is no USD, but it uses a coin tethered to the USD (USDT), which is the default. Some symbols +are a combination of coins, as `ETHBTC` is a valid symbol + +* -c/--coin Coin to load. If not specified, BTC will be loaded to prevent errors later. +* -q/--quote Quote currency. Defaults to `USDT` (which is 1-to-1 with USD) + +*Note that the usage `select btc` will also work, as it will add `-c` if not detected. + +## book +```` +usage: book -l/--limit +```` +Gets and shows the order book for the given coin/currency. Shows the cumulative amount of orders. + +* -l/--limit Number of orders to get on each side. One of [5,10,20,50,100,500,1000,5000]. Defaults to 100. + +## candle +```` +usage: candle [-i --interval] [-l --limit] +```` +Show candle chart for loaded coin/currency. (Terminal will quit if coin is not defined). + +* -i/--interval. Interval for candles. One of [1day,3day,1hour,2hour,4hour,6hour,8hour,12hour,1week,1min,3min,5min,15min,30min,1month]. + Defaults to 1day. +* -l/--limit. Number of candles to get. Defaults to 100. +Example output (using 3day interval and 50 candles) + + +![im](https://user-images.githubusercontent.com/18151143/116797645-f455d380-aab5-11eb-8dbb-df257425302d.png) + +## balance +```` +usage: balance +```` +Shows the current holding balance in your account. diff --git a/gamestonk_terminal/cryptocurrency/binance_model.py b/gamestonk_terminal/cryptocurrency/binance_model.py new file mode 100644 index 00000000000..f1f6b179ada --- /dev/null +++ b/gamestonk_terminal/cryptocurrency/binance_model.py @@ -0,0 +1,258 @@ +"""Binance model""" +__docformat__ = "numpy" + +import argparse +from typing import List +import pandas as pd +import numpy as np +from binance.client import Client +from binance.exceptions import BinanceAPIException +from tabulate import tabulate +from gamestonk_terminal.main_helper import parse_known_args_and_warn +import gamestonk_terminal.config_terminal as cfg +from gamestonk_terminal.cryptocurrency.binance_view import plot_order_book, plot_candles + + +def check_valid_binance_str(symbol: str) -> str: + """Check if symbol is in defined binance""" + client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET) + try: + client.get_avg_price(symbol=symbol.upper()) + return symbol.upper() + except BinanceAPIException as e: + raise argparse.ArgumentTypeError( + f"{symbol} is not a valid binance symbol" + ) from e + + +# pylint: disable=inconsistent-return-statements +def select_binance_coin(other_args: List[str]): + """ + Define current_coin from binance + + Parameters + ---------- + other_args: List[str] + Argparse arguments + + Returns + ------- + coin: str + Coin that is defined on binance + """ + parser = argparse.ArgumentParser( + prog="select", + add_help=False, + description="Define the coin to be used from binance", + ) + parser.add_argument( + "-c", "--coin", help="Coin to get", dest="coin", type=str, default="BTC" + ) + parser.add_argument( + "-q", + "--quote", + help="Quote currency (what to view coin vs)", + dest="quote", + type=str, + default="USDT", + ) + try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-c") + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return None, None + + coin = ns_parser.coin + ns_parser.quote + if check_valid_binance_str(coin): + print(f"{ns_parser.coin.upper()} loaded vs {ns_parser.quote.upper()}") + return ns_parser.coin.upper(), ns_parser.quote.upper() + + except Exception as e: + print(e, "\n") + return None, None + + +def order_book(coin: str, other_args: List[str]): + """ + Get order book for currency + + Parameters + ---------- + coin: str + Coin to get order book for + other_args: List[str] + Argparse arguments + + Returns + ------- + + """ + limit_list = [5, 10, 20, 50, 100, 500, 1000, 5000] + parser = argparse.ArgumentParser( + prog="book", add_help=False, description="Get the order book for selected coin" + ) + parser.add_argument( + "-l", + "--limit", + dest="limit", + help="Limit parameter. Adjusts the weight", + default=100, + type=int, + choices=limit_list, + ) + + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET) + market_book = client.get_order_book(symbol=coin, limit=ns_parser.limit) + bids = np.asarray(market_book["bids"], dtype=float) + asks = np.asarray(market_book["asks"], dtype=float) + bids = np.insert(bids, 2, bids[:, 1].cumsum(), axis=1) + asks = np.insert(asks, 2, np.flipud(asks[:, 1]).cumsum(), axis=1) + plot_order_book(bids, asks, coin) + + except Exception as e: + print(e, "\n") + + +def show_candles(coin: str, other_args: List[str]): + """ + Get klines/candles for coin + + Parameters + ---------- + coin: str + Coin to get symbol of + other_args: List[str] + Argparse arguments + + Returns + ------- + + """ + 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, + } + interval_choices = list(interval_map.keys()) + + parser = argparse.ArgumentParser( + prog="candle", + add_help=False, + description="Program to plot candles for binance data", + ) + parser.add_argument( + "-i", + "--interval", + help="Interval to get data", + choices=interval_choices, + dest="interval", + default="1day", + type=str, + ) + + parser.add_argument( + "-l", "--limit", dest="limit", default=100, help="Number to get", type=int + ) + + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + candles = client.get_klines( + symbol=coin, + interval=interval_map[ns_parser.interval], + limit=ns_parser.limit, + ) + + # Response + # 1499040000000, // Open time + # "0.01634790", // Open + # "0.80000000", // High + # "0.01575800", // Low + # "0.01577100", // Close + # "148976.11427815", // Volume + # 1499644799999, // Close time + # "2434.19055334", // Quote asset volume + # 308, // Number of trades + # "1756.87402397", // Taker buy base asset volume + # "28.46694368", // Taker buy quote asset volume + # "17928899.62484339" // Ignore. + + candles_df = pd.DataFrame(candles).astype(float).iloc[:, :7] + + candles_df.columns = [ + "Time0", + "Open", + "High", + "Low", + "Close", + "Volume", + "Time1", + ] + candles_df.index = pd.to_datetime( + (candles_df["Time0"] + candles_df["Time1"]) / 2, unit="ms" + ) + + plot_candles( + candles_df, + f"{coin} from {candles_df.index[0].strftime('%Y/%m/%d')} to " + f"{candles_df.index[-1].strftime('%Y/%m/%d')}", + ) + + except Exception as e: + print(e, "\n") + + +def balance(coin: str): + """ + Get account holdings for asset + + Parameters + ---------- + coin: str + Coin to get holdings of + + Returns + ------- + + """ + client = Client(cfg.API_BINANCE_KEY, cfg.API_BINANCE_SECRET) + try: + current_balance = client.get_asset_balance(asset=coin) + if current_balance is None: + print("Check loaded coin") + return + print("") + amounts = [float(current_balance["free"]), float(current_balance["locked"])] + total = np.sum(amounts) + df = pd.DataFrame(amounts).apply(lambda x: str(float(x))) + df.columns = ["Amount"] + df.index = ["Free", "Locked"] + df["Percent"] = df.div(df.sum(axis=0), axis=1).round(3) + print(f"You currently have {total} coins and the breakdown is:") + print(tabulate(df, headers=df.columns, showindex=True, tablefmt="fancy_grid")) + print("") + return + except Exception as e: + print(e, "\n") + return diff --git a/gamestonk_terminal/cryptocurrency/binance_view.py b/gamestonk_terminal/cryptocurrency/binance_view.py new file mode 100644 index 00000000000..8ddbebee199 --- /dev/null +++ b/gamestonk_terminal/cryptocurrency/binance_view.py @@ -0,0 +1,78 @@ +"""Binance view functions""" +__docformat__ = "numpy" + +import numpy as np +import matplotlib.pyplot as plt +import mplfinance as mpf +import pandas as pd +from gamestonk_terminal.main_helper import plot_autoscale +from gamestonk_terminal.config_plot import PLOT_DPI +from gamestonk_terminal.feature_flags import USE_ION as ion + + +def plot_order_book(bids: np.array, asks: np.array, coin: str): + """ + Plots Bid/Ask + Parameters + ---------- + bids : np.array + array of bids with columns: price, size, cumulative size + asks : np.array + array of asks with columns: price, size, cumulative size + coin : str + Coin being plotted + + Returns + ------- + + """ + _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + ax.plot(bids[:, 0], bids[:, 2], "g", label="bids") + ax.fill_between(bids[:, 0], bids[:, 2], color="g", alpha=0.4) + ax.plot(asks[:, 0], asks[:, 2], "r", label="asks") + ax.fill_between(asks[:, 0], asks[:, 2], color="r", alpha=0.4) + plt.grid(b=True, which="major", color="#666666", linestyle="-") + plt.minorticks_on() + plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2) + plt.legend(loc=0) + plt.xlabel("Price") + plt.ylabel("Size (Coins) ") + plt.title(f"Order Book for {coin}") + if ion: + plt.ion() + plt.show() + print("") + + +def plot_candles(candles_df: pd.DataFrame, title: str): + """ + Plot candle chart from dataframe + Parameters + ---------- + candles_df: pd.DataFrame + Dataframe containing time and OHLVC + title: str + title of graph + + Returns + ------- + + """ + mpf.plot( + candles_df, + type="candle", + volume=True, + title=f"{title}", + xrotation=20, + style="binance", + figratio=(10, 7), + figscale=1.10, + figsize=(plot_autoscale()), + update_width_config=dict( + candle_linewidth=1.0, candle_width=0.8, volume_linewidth=1.0 + ), + ) + if ion: + plt.ion() + plt.show() + print("") diff --git a/gamestonk_terminal/cryptocurrency/coinmarketcap_view.py b/gamestonk_terminal/cryptocurrency/coinmarketcap_view.py index a8820889d33..981b55ec092 100644 --- a/gamestonk_terminal/cryptocurrency/coinmarketcap_view.py +++ b/gamestonk_terminal/cryptocurrency/coinmarketcap_view.py @@ -6,7 +6,7 @@ from typing import List import pandas as pd from tabulate import tabulate from coinmarketcapapi import CoinMarketCapAPI -from gamestonk_terminal.config_terminal import COINMARKETCAP_KEY +import gamestonk_terminal.config_terminal as cfg from gamestonk_terminal.helper_funcs import parse_known_args_and_warn sort_options = ["Symbol", "CMC_Rank", "LastPrice", "DayPctChange", "MarketCap"] @@ -62,7 +62,7 @@ def get_cmc_top_n(other_args: List[str]): if not ns_parser: return - cmc = CoinMarketCapAPI(COINMARKETCAP_KEY) + cmc = CoinMarketCapAPI(cfg.API_CMC_KEY) ratings = cmc.cryptocurrency_listings_latest().data symbol, rank, price, pchange1d, mkt_cap = [], [], [], [], [] diff --git a/gamestonk_terminal/cryptocurrency/crypto_controller.py b/gamestonk_terminal/cryptocurrency/crypto_controller.py index 0361dcbbb23..60a9359631c 100644 --- a/gamestonk_terminal/cryptocurrency/crypto_controller.py +++ b/gamestonk_terminal/cryptocurrency/crypto_controller.py @@ -1,3 +1,4 @@ +"""Cryptocurrency Controller""" __docformat__ = "numpy" import argparse @@ -7,13 +8,29 @@ from prompt_toolkit.completion import NestedCompleter from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import get_flair from gamestonk_terminal.menu import session -from gamestonk_terminal.cryptocurrency import pycoingecko_view -from gamestonk_terminal.cryptocurrency import coinmarketcap_view as cmc_view +from gamestonk_terminal.cryptocurrency import ( + binance_model, + pycoingecko_view, + coinmarketcap_view as cmc_view, +) class CryptoController: - CHOICES = ["help", "q", "quit", "load", "view", "top"] + CHOICES = [ + "help", + "q", + "quit", + "load", + "view", + "top", + "trend", + "book", + "trades", + "candle", + "balance", + "select", + ] def __init__(self): """CONSTRUCTOR""" @@ -21,22 +38,31 @@ class CryptoController: self.crypto_parser = argparse.ArgumentParser(add_help=False, prog="crypto") self.crypto_parser.add_argument("cmd", choices=self.CHOICES) self.current_coin = None + self.current_currency = None self.current_df = pd.DataFrame() - @staticmethod - def print_help(current_coin): + def print_help(self): """Print help""" print("\nCryptocurrency:") print(" help show this menu again") print(" q quit this menu, and shows back to main menu") print(" quit quit to abandon program") - print(f"\nCurrent Coin: {current_coin}") + print(f"\nCurrent Coin: {self.current_coin}") print("") + print("Coingecko:") print(" load load cryptocurrency data") print(" view load and view cryptocurrency data") + print(" trend show top 7 trending coins") print("") + print("CoinMarketCap:") print(" top view top coins from coinmarketcap") print("") + print("Binance:") + print(" select select coin/currency to use") + print(" book show order book") + print(" candle get klines/candles and plot") + print(" balance show coin balance") + print("") def switch(self, an_input: str): """Process and dispatch input @@ -56,7 +82,7 @@ class CryptoController: def call_help(self, _): """Process Help command""" - self.print_help(self.current_coin) + self.print_help() def call_q(self, _): """Process Q command - quit the menu""" @@ -67,9 +93,11 @@ class CryptoController: return True def call_load(self, other_args): + """Process load command""" self.current_coin, self.current_df = pycoingecko_view.load(other_args) def call_view(self, other_args): + """Process view command""" if self.current_coin: pycoingecko_view.view(self.current_coin, self.current_df, other_args) @@ -77,13 +105,39 @@ class CryptoController: print("No coin selected. Use 'load' to load the coin you want to look at.") print("") + def call_trend(self, _): + """Process trend command""" + pycoingecko_view.trend() + def call_top(self, other_args): + """Process top command""" cmc_view.get_cmc_top_n(other_args) + def call_book(self, other_args): + """Process book command""" + binance_model.order_book(self.current_coin + self.current_currency, other_args) + + def call_candle(self, other_args): + """Process candle command""" + binance_model.show_candles( + self.current_coin + self.current_currency, other_args + ) + + def call_balance(self, _): + """Process balance command""" + binance_model.balance(self.current_coin) + + def call_select(self, other_args): + """Process select command""" + self.current_coin, self.current_currency = binance_model.select_binance_coin( + other_args + ) + print("") + def menu(): crypto_controller = CryptoController() - crypto_controller.print_help(crypto_controller.current_coin) + crypto_controller.print_help() plt.close("all") while True: # Get input command from user diff --git a/gamestonk_terminal/cryptocurrency/crypto_helper.py b/gamestonk_terminal/cryptocurrency/crypto_helper.py deleted file mode 100644 index f895f264bd5..00000000000 --- a/gamestonk_terminal/cryptocurrency/crypto_helper.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Helper script that generates a dictionary to convert between symbols and IDs. -This allows the user to input (for example) "btc" instead of the expected "bitcoin" - -""" -from pycoingecko import CoinGeckoAPI - -cg = CoinGeckoAPI() -coins = cg.get_coins() -coin_symbol_to_id = {} -coin_ids = [] - -for coin in coins: - coin_symbol_to_id[coin["symbol"]] = coin["id"] - coin_ids.append(coin["id"]) diff --git a/gamestonk_terminal/cryptocurrency/pycoingecko_view.py b/gamestonk_terminal/cryptocurrency/pycoingecko_view.py index 3dd11a7663f..c4f6fca5f3c 100644 --- a/gamestonk_terminal/cryptocurrency/pycoingecko_view.py +++ b/gamestonk_terminal/cryptocurrency/pycoingecko_view.py @@ -6,12 +6,23 @@ from typing import List import pandas as pd from pandas.plotting import register_matplotlib_converters import matplotlib.pyplot as plt +from tabulate import tabulate from pycoingecko import CoinGeckoAPI from gamestonk_terminal.helper_funcs import parse_known_args_and_warn, plot_autoscale -from gamestonk_terminal.cryptocurrency.crypto_helper import coin_symbol_to_id, coin_ids from gamestonk_terminal.config_plot import PLOT_DPI register_matplotlib_converters() + +# Generate a list of valid coins to be checked against later +cg_api = CoinGeckoAPI() +coins = cg_api.get_coins() +coin_symbol_to_id = {} +coin_ids = [] + +for single_coin in coins: + coin_symbol_to_id[single_coin["symbol"]] = single_coin["id"] + coin_ids.append(single_coin["id"]) + # pylint: disable=inconsistent-return-statements @@ -135,3 +146,33 @@ def view(coin: str, prices: pd.DataFrame, other_args: List[str]): except Exception as e: print(e) print("") + + +def trend(): + """Prints top 7 coins from pycoingecko""" + + cg = CoinGeckoAPI() + trending = cg.get_search_trending()["coins"] + name, symbol, price, rank = [], [], [], [] + for coin in trending: + name.append(coin["item"]["name"]) + symbol.append(coin["item"]["symbol"]) + coin_id = coin["item"]["id"] + price.append(cg.get_price(coin_id, vs_currencies="USD")[coin_id]["usd"]) + rank.append(coin["item"]["market_cap_rank"]) + + df = pd.DataFrame() + df["name"] = name + df["symbol"] = symbol + df["last_price"] = price + df["market_cap_rank"] = rank + print( + tabulate( + df, + headers=df.columns, + floatfmt=".2f", + showindex=False, + tablefmt="fancy_grid", + ) + ) + print("") diff --git a/gamestonk_terminal/main_helper.py b/gamestonk_terminal/main_helper.py index 5723f7b3460..30ef54f0af0 100644 --- a/gamestonk_terminal/main_helper.py +++ b/gamestonk_terminal/main_helper.py @@ -59,7 +59,9 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open): print( " > pa portfolio analysis, \t\t supports: robinhood, alpaca, ally " ) - print(" > crypto cryptocurrencies, \t\t uses coingecko api") + print( + " > crypto cryptocurrencies, \t\t from: coingecko, coinmarketcap, binance" + ) print( " > po portfolio optimization, \t optimal portfolio weights from pyportfolioopt" ) diff --git a/poetry.lock b/poetry.lock index 3b481c673f8..6b62906f552 100644 --- a/poetry.lock +++ b/poetry.lock @@ -436,6 +436,23 @@ category = "main" optional = false python-versions = ">=3.6, <3.7" +[[package]] +name = "dateparser" +version = "1.0.0" +description = "Date parsing library designed to parse dates from HTML pages" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.dependencies] +python-dateutil = "*" +pytz = "*" +regex = "!=2019.02.19" +tzlocal = "*" + +[package.extras] +calendars = ["convertdate", "hijri-converter", "convertdate"] + [[package]] name = "datetime" version = "4.3" @@ -712,7 +729,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "gdown" -version = "3.12.2" +version = "3.13.0" description = "Google Drive direct download of big files." category = "main" optional = true @@ -720,7 +737,7 @@ python-versions = "*" [package.dependencies] filelock = "*" -requests = {version = "*", extras = ["socks"]} +requests = {version = ">=2.12.0", extras = ["socks"]} six = "*" tqdm = "*" @@ -2009,7 +2026,7 @@ python-versions = "*" [[package]] name = "pyobjc-core" -version = "7.1" +version = "7.2" description = "Python<->ObjC Interoperability Module" category = "main" optional = false @@ -2017,14 +2034,14 @@ python-versions = ">=3.6" [[package]] name = "pyobjc-framework-cocoa" -version = "7.1" +version = "7.2" description = "Wrappers for the Cocoa frameworks on macOS" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -pyobjc-core = ">=7.1" +pyobjc-core = ">=7.2" [[package]] name = "pyotp" @@ -2120,6 +2137,22 @@ toml = "*" [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +[[package]] +name = "python-binance" +version = "1.0.1" +description = "Binance REST API python implementation" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +aiohttp = "*" +dateparser = "*" +requests = "*" +six = "*" +ujson = "*" +websockets = "*" + [[package]] name = "python-coinmarketcap" version = "0.2" @@ -2173,7 +2206,7 @@ python-versions = "*" [[package]] name = "pyupgrade" -version = "2.13.0" +version = "2.14.0" description = "A tool to automatically upgrade syntax for newer versions." category = "dev" optional = false @@ -2232,7 +2265,7 @@ scipy = ">=0.13.2" [[package]] name = "qtconsole" -version = "5.0.3" +version = "5.1.0" description = "Jupyter Qt console" category = "main" optional = false @@ -2863,6 +2896,25 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "tzlocal" +version = "2.1" +description = "tzinfo object for the local timezone" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pytz = "*" + +[[package]] +name = "ujson" +version = "4.0.2" +description = "Ultra fast JSON encoder and decoder for Python" +category = "main" +optional = false +python-versions = ">=3.6" + [[package]] name = "update-checker" version = "0.18.0" @@ -3036,7 +3088,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "51e9191a579c58d229a6a32b419f3f8d891d2e7ce12decb6f74a283fb46a851a" +content-hash = "9f2c8b046494863b5a83e395b8a79edbca42fd2b61b5e977877e08aedc53e165" [metadata.files] absl-py = [ @@ -3329,6 +3381,10 @@ dataclasses = [ {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, {file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"}, ] +dateparser = [ + {file = "dateparser-1.0.0-py2.py3-none-any.whl", hash = "sha256:17202df32c7a36e773136ff353aa3767e987f8b3e27374c39fd21a30a803d6f8"}, + {file = "dateparser-1.0.0.tar.gz", hash = "sha256:159cc4e01a593706a15cd4e269a0b3345edf3aef8bf9278a57dac8adf5bf1e4a"}, +] datetime = [ {file = "DateTime-4.3-py2.py3-none-any.whl", hash = "sha256:371dba07417b929a4fa685c2f7a3eaa6a62d60c02947831f97d4df9a9e70dfd0"}, {file = "DateTime-4.3.tar.gz", hash = "sha256:5cef605bab8259ff61281762cdf3290e459fbf0b4719951d5fab967d5f2ea0ea"}, @@ -3458,7 +3514,7 @@ gast = [ {file = "gast-0.3.3.tar.gz", hash = "sha256:b881ef288a49aa81440d2c5eb8aeefd4c2bb8993d5f50edae7413a85bfdb3b57"}, ] gdown = [ - {file = "gdown-3.12.2.tar.gz", hash = "sha256:4b3a1301e57bfd8dce939bf25ef8fbb4b23967fd0f878eede328bdcc41386bac"}, + {file = "gdown-3.13.0.tar.gz", hash = "sha256:d5f9389539673875712beba4936c4ace95d24324953c6f0408a858c534c0bf21"}, ] gensim = [ {file = "gensim-3.8.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:61eed1d6b5fbe6dda0586ea447ebc2dc7890a7f70c2ed953d5abc3fe3cfb94bb"}, @@ -4335,20 +4391,20 @@ pymeeus = [ {file = "PyMeeus-0.5.11.tar.gz", hash = "sha256:bb9d670818d8b0594317b48a7dadea02a0594e5344263bf2054e1a011c8fed55"}, ] pyobjc-core = [ - {file = "pyobjc-core-7.1.tar.gz", hash = "sha256:a0616d5d816b4471f8f782c3a9a8923d2cc85014d88ad4f7fec694be9e6ea349"}, - {file = "pyobjc_core-7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9fb45c9916f2a03ecd6b9ecde4c35d1d0f1a590ae2ea2372f9d9a360226ac1d"}, - {file = "pyobjc_core-7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff8e87358c6195a2937004f279050cce3d4c02cd77acd73c5ad367307def855"}, - {file = "pyobjc_core-7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:afb38efd3f2960eb49eb78552d465cfd025a9d6efa06cd4cd8694dafbe7c6e06"}, - {file = "pyobjc_core-7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7cb329c4119044fe83bcb3c5d4794d636c706ff0cb7c1c77d36ef5c373100082"}, - {file = "pyobjc_core-7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7913d7b20217c294900537faf58e5cc15942ed7af277bf05db25667d18255114"}, + {file = "pyobjc-core-7.2.tar.gz", hash = "sha256:9e9ec482d80ea030cdb1613d05a247f31eedabe6666d884d42dd890cc5fb0e05"}, + {file = "pyobjc_core-7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:94b4d9de9d228db52dd35012096d63bdf8c1ace58ea3be1d5f6f39313cd502f2"}, + {file = "pyobjc_core-7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:971cbd7189ae1aa03ef0d16124aa5bcd053779e0e6b6011a41c3dbd5b4ea7e88"}, + {file = "pyobjc_core-7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9d93b20394008373d6d2856d49aaff26f4b97ff42d924a14516c8a82313ec8c0"}, + {file = "pyobjc_core-7.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:860183540d1be792c26426018139ac8ba75e85f675c59ba080ccdc52d8e74c7a"}, + {file = "pyobjc_core-7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ffe61d3c2a404354daf2d895e34e38c5044453353581b3c396bf5365de26250c"}, ] pyobjc-framework-cocoa = [ - {file = "pyobjc-framework-Cocoa-7.1.tar.gz", hash = "sha256:67966152b3d38a0225176fceca2e9f56d849c8e7445548da09a00cb13155ec3e"}, - {file = "pyobjc_framework_Cocoa-7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:bef77eafaac5eaf1d91d479d5483fd02216caa3edc27e8f5adc9af0b3fecdac3"}, - {file = "pyobjc_framework_Cocoa-7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2ea3582c456827dc20e648c905fdbcf8d3dfae89434f981e9b761cd07262049"}, - {file = "pyobjc_framework_Cocoa-7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a4050f2d776f40c2409a151c6f7896420e936934b3bdbfabedf91509637ed9b"}, - {file = "pyobjc_framework_Cocoa-7.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f68f022f1f6d5985c418e10c6608c562fcf4bfe3714ec64fd10ce3dc6221bd4"}, - {file = "pyobjc_framework_Cocoa-7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ecfefd4c48dae42275c18679c69f6f2fff970e711097515a0a8732fc10194018"}, + {file = "pyobjc-framework-Cocoa-7.2.tar.gz", hash = "sha256:c8b23f03dc3f4436d36c0fd006a8a084835c4f6015187df7c3aa5de8ecd5c653"}, + {file = "pyobjc_framework_Cocoa-7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8e5dd5daa0096755937ec24c345a4b07c3fa131a457f99e0fdeeb01979178ec7"}, + {file = "pyobjc_framework_Cocoa-7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:828d183947fc7746953fd0c9b1092cc423745ba0b49719e7b7d1e1614aaa20ec"}, + {file = "pyobjc_framework_Cocoa-7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e4c6d7baa0c2ab5ea5efb8836ad0b3b3976cffcfc6195c1f195e826c6eb5744"}, + {file = "pyobjc_framework_Cocoa-7.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9a9d1d49cc5a810773c88d6de821e60c8cc41d01113cf1b9e7662938f5f7d66"}, + {file = "pyobjc_framework_Cocoa-7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:506c2cd09f421eac92b9008a0142174c3d1d70ecd4b0e3fa2b924767995fd14e"}, ] pyotp = [ {file = "pyotp-2.6.0-py2.py3-none-any.whl", hash = "sha256:9d144de0f8a601d6869abe1409f4a3f75f097c37b50a36a3bf165810a6e23f28"}, @@ -4400,6 +4456,10 @@ pytest = [ {file = "pytest-6.2.3-py3-none-any.whl", hash = "sha256:6ad9c7bdf517a808242b998ac20063c41532a570d088d77eec1ee12b0b5574bc"}, {file = "pytest-6.2.3.tar.gz", hash = "sha256:671238a46e4df0f3498d1c3270e5deb9b32d25134c99b7d75370a68cfbe9b634"}, ] +python-binance = [ + {file = "python-binance-1.0.1.tar.gz", hash = "sha256:7987189651938bb81a4e2f86993a32c77c55255d9c33891efb1d2bca918b8142"}, + {file = "python_binance-1.0.1-py2.py3-none-any.whl", hash = "sha256:80dc4402837103024c44f0f57c5ac90c43e5ebe1da4f53104ebd4b9b788bd17d"}, +] python-coinmarketcap = [ {file = "python-coinmarketcap-0.2.tar.gz", hash = "sha256:b1e0e8b098fc910a5ec943a06774d5ee3b190e915123366e2f16238ef0a8a433"}, {file = "python_coinmarketcap-0.2-py2-none-any.whl", hash = "sha256:54c278154ee11ca78837fb73eae8c322a60af93dc0ce75b515fecf895d181cf5"}, @@ -4422,8 +4482,8 @@ pytz = [ {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, ] pyupgrade = [ - {file = "pyupgrade-2.13.0-py2.py3-none-any.whl", hash = "sha256:1cb5a15573fc63824b952bf7dde5b96f9672a1179ec779ac2d159a845da743c8"}, - {file = "pyupgrade-2.13.0.tar.gz", hash = "sha256:dc6b580b7bc82f357acb354bbba03d8d69da51425ecd5993a2651059bca80518"}, + {file = "pyupgrade-2.14.0-py2.py3-none-any.whl", hash = "sha256:19bd23babd4c09171be66d393d83a53e5ae8d54c6534001c4b7ad92c4d560d69"}, + {file = "pyupgrade-2.14.0.tar.gz", hash = "sha256:34f5dfa57d8007f6cd455a0a423e06e96753b07e4711bac63e3d5c4f3af97cea"}, ] pywin32 = [ {file = "pywin32-300-cp35-cp35m-win32.whl", hash = "sha256:1c204a81daed2089e55d11eefa4826c05e604d27fe2be40b6bf8db7b6a39da63"}, @@ -4528,8 +4588,8 @@ qdldl = [ {file = "qdldl-0.1.5.post0.tar.gz", hash = "sha256:c392c7427651d8b226423c7aba4a0f2338a1f38a4bbdabac6bc4afd8bc934f06"}, ] qtconsole = [ - {file = "qtconsole-5.0.3-py3-none-any.whl", hash = "sha256:4a38053993ca2da058f76f8d75b3d8906efbf9183de516f92f222ac8e37d9614"}, - {file = "qtconsole-5.0.3.tar.gz", hash = "sha256:c091a35607d2a2432e004c4a112d241ce908086570cf68594176dd52ccaa212d"}, + {file = "qtconsole-5.1.0-py3-none-any.whl", hash = "sha256:3a2adecc43ff201a08972fb2179df22e7b3a08d71b9ed680f46ad1bfd4fb9132"}, + {file = "qtconsole-5.1.0.tar.gz", hash = "sha256:12c734494901658787339dea9bbd82f3dc0d5e394071377a1c77b4a0954d7d8b"}, ] qtpy = [ {file = "QtPy-1.9.0-py2.py3-none-any.whl", hash = "sha256:fa0b8363b363e89b2a6f49eddc162a04c0699ae95e109a6be3bb145a913190ea"}, @@ -5009,6 +5069,33 @@ typing-extensions = [ {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, ] +tzlocal = [ + {file = "tzlocal-2.1-py2.py3-none-any.whl", hash = "sha256:e2cb6c6b5b604af38597403e9852872d7f534962ae2954c7f35efcb1ccacf4a4"}, + {file = "tzlocal-2.1.tar.gz", hash = "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44"}, +] +ujson = [ + {file = "ujson-4.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e390df0dcc7897ffb98e17eae1f4c442c39c91814c298ad84d935a3c5c7a32fa"}, + {file = "ujson-4.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:84b1dca0d53b0a8d58835f72ea2894e4d6cf7a5dd8f520ab4cbd698c81e49737"}, + {file = "ujson-4.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:91396a585ba51f84dc71c8da60cdc86de6b60ba0272c389b6482020a1fac9394"}, + {file = "ujson-4.0.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:eb6b25a7670c7537a5998e695fa62ff13c7f9c33faf82927adf4daa460d5f62e"}, + {file = "ujson-4.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f8aded54c2bc554ce20b397f72101737dd61ee7b81c771684a7dd7805e6cca0c"}, + {file = "ujson-4.0.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:30962467c36ff6de6161d784cd2a6aac1097f0128b522d6e9291678e34fb2b47"}, + {file = "ujson-4.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:fc51e545d65689c398161f07fd405104956ec27f22453de85898fa088b2cd4bb"}, + {file = "ujson-4.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e6e90330670c78e727d6637bb5a215d3e093d8e3570d439fd4922942f88da361"}, + {file = "ujson-4.0.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:5e1636b94c7f1f59a8ead4c8a7bab1b12cc52d4c21ababa295ffec56b445fd2a"}, + {file = "ujson-4.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:e2cadeb0ddc98e3963bea266cc5b884e5d77d73adf807f0bda9eca64d1c509d5"}, + {file = "ujson-4.0.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:a214ba5a21dad71a43c0f5aef917cd56a2d70bc974d845be211c66b6742a471c"}, + {file = "ujson-4.0.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:0190d26c0e990c17ad072ec8593647218fe1c675d11089cd3d1440175b568967"}, + {file = "ujson-4.0.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:f273a875c0b42c2a019c337631bc1907f6fdfbc84210cc0d1fff0e2019bbfaec"}, + {file = "ujson-4.0.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:d3a87888c40b5bfcf69b4030427cd666893e826e82cc8608d1ba8b4b5e04ea99"}, + {file = "ujson-4.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:7333e8bc45ea28c74ae26157eacaed5e5629dbada32e0103c23eb368f93af108"}, + {file = "ujson-4.0.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b3a6dcc660220539aa718bcc9dbd6dedf2a01d19c875d1033f028f212e36d6bb"}, + {file = "ujson-4.0.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:0ea07fe57f9157118ca689e7f6db72759395b99121c0ff038d2e38649c626fb1"}, + {file = "ujson-4.0.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4d6d061563470cac889c0a9fd367013a5dbd8efc36ad01ab3e67a57e56cad720"}, + {file = "ujson-4.0.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b5c70704962cf93ec6ea3271a47d952b75ae1980d6c56b8496cec2a722075939"}, + {file = "ujson-4.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:aad6d92f4d71e37ea70e966500f1951ecd065edca3a70d3861b37b176dd6702c"}, + {file = "ujson-4.0.2.tar.gz", hash = "sha256:c615a9e9e378a7383b756b7e7a73c38b22aeb8967a8bfbffd4741f7ffd043c4d"}, +] update-checker = [ {file = "update_checker-0.18.0-py3-none-any.whl", hash = "sha256:cbba64760a36fe2640d80d85306e8fe82b6816659190993b7bdabadee4d4bbfd"}, {file = "update_checker-0.18.0.tar.gz", hash = "sha256:6a2d45bb4ac585884a6b03f9eade9161cedd9e8111545141e9aa9058932acb13"}, diff --git a/pyproject.toml b/pyproject.toml index 65ac1931eb2..43efb105290 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,6 +63,7 @@ oandapyV20 = "^0.6.3" degiroapi = "^0.9.5" valinvest = "^0.0.2" bt = "^0.2.9" +python-binance = "^1.0.1" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements-full.txt b/requirements-full.txt index a8c07a921e4..a3f79bc3a5d 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -149,6 +149,7 @@ pyportfolioopt==1.4.1; python_full_version >= "3.6.1" and python_full_version < pyrsistent==0.14.11 pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" pystan==2.19.1.1 +python-binance==1.0.1 python-coinmarketcap==0.2 python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "2.7" and python_version < "4" and python_full_version >= "3.3.0") python-dotenv==0.17.0; python_version >= "3" diff --git a/requirements-old.txt b/requirements-old.txt index 77b359de143..71b5b6d736b 100644 --- a/requirements-old.txt +++ b/requirements-old.txt @@ -94,6 +94,7 @@ pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6" pyportfolioopt==1.4.1 pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" pystan==2.18 +python-binance==1.0.1 python-coinmarketcap==0.2 python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.5" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "2.7" and python_version < "4" and python_full_version >= "3.3.0") pytest==6.2.2; python_version >= "3.6" diff --git a/requirements-win.txt b/requirements-win.txt index 1f658e78cc9..b12bd43282f 100644 --- a/requirements-win.txt +++ b/requirements-win.txt @@ -96,6 +96,7 @@ pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6" pyportfolioopt==1.4.1 pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" pystan==2.19.1.1 +python-binance==1.0.1 python-coinmarketcap==0.2 python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.5" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") and (python_version >= "2.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "2.7" and python_version < "4" and python_full_version >= "3.3.0") pytest==6.2.2; python_version >= "3.6" diff --git a/requirements.txt b/requirements.txt index 4a189ab8556..04cdb8207db 100644 --- a/requirements.txt +++ b/requirements.txt @@ -113,6 +113,7 @@ pyparsing==2.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or p pyportfolioopt==1.4.1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" pyrsistent==0.14.11 pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" +python-binance==1.0.1 python-coinmarketcap==0.2 python-dateutil==2.8.1; python_full_version >= "3.6.1" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6") and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0") python-dotenv==0.17.0; python_version >= "3"