Merge pull request #428 from jmaslek/add_binance

Add binance
This commit is contained in:
DidierRLopes
2021-05-03 14:12:26 +01:00
committed by GitHub
18 changed files with 646 additions and 59 deletions

View File

@@ -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:
```

View File

@@ -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
---

View File

@@ -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
 

View File

@@ -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"

View File

@@ -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 <a name="COINGECKO"></a>
## load <a name="load"></a>
````
@@ -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 <a name="trend"></a>
````
usage: trend
````
Print the top 7 trending coins from coingecko
# COINMARKETCAP <a name="COINMARKETCAP"></a>
## top <a name="top"></a>
@@ -50,3 +72,45 @@ This command displays the top n cryptocurrencies from coinmarketcap.com.
<img width="990" alt="crypto" src="https://user-images.githubusercontent.com/25267873/115787544-4746d100-a3ba-11eb-9433-b7cb9142404a.png">
# BINANCE <a name="BINANCE"></a>
## select <a name="select"></a>
````
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 <a name="book"></a>
````
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 <a name="candle"></a>
````
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 <a name="balance"></a>
````
usage: balance
````
Shows the current holding balance in your account.

View File

@@ -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

View File

@@ -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("")

View File

@@ -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 = [], [], [], [], []

View File

@@ -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

View File

@@ -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"])

View File

@@ -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("")

View File

@@ -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"
)

137
poetry.lock generated
View File

@@ -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"},

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"