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.

+## 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.
+# 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)
+
+
+
+
+## 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"