From 07fc037441d55ece4d03c2fb978430a3f27747af Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Mon, 12 Jul 2021 20:46:34 +0100 Subject: [PATCH] Allow to load data from IEX (#536) * Allow to load data from IEX * update poetry lock * add intraday iex data * Allow to print raw dataframe loaded data * Move export flag to view command * fix -h for load function * more refactoring * Update README.md * fix view help * FTD command improved * Update README.md * forgot this one * fix issue --- .gitignore | 1 + gamestonk_terminal/README.md | 10 +- gamestonk_terminal/config_terminal.py | 3 + gamestonk_terminal/due_diligence/README.md | 13 +- .../due_diligence/dd_controller.py | 2 +- gamestonk_terminal/due_diligence/sec_view.py | 203 +++++++++--- gamestonk_terminal/helper_funcs.py | 9 - gamestonk_terminal/main_helper.py | 298 +++++++++++------- poetry.lock | 140 ++++++-- pyproject.toml | 1 + requirements-full.txt | 1 + requirements.txt | 1 + terminal.py | 7 - 13 files changed, 476 insertions(+), 213 deletions(-) diff --git a/.gitignore b/.gitignore index f88c6941dcb..c9ae237cbb7 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ notebooks/reports/* reports/* !notebooks/reports/.gitkeep .python-version +exports/* diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index efece6b5f55..8b00d3cb36b 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -30,10 +30,11 @@ The main menu allows the following commands: ``` -load -t S_TICKER [-s S_START_DATE] [-i {1,5,15,30,60}] +usage: load [-t S_TICKER] [-s S_START_DATE] [-i {1,5,15,30,60}] [--source {yf,av,iex}] [-p] ``` * Load stock ticker to perform analysis on. When the data source is 'yf', an Indian ticker can be loaded by using '.NS' at the end, e.g. 'SBIN.NS'. See available market in . + * -t : Stock ticker * -s : The starting date (format YYYY-MM-DD) of the stock * -i : Intraday stock minutes * --source : Source of historical data. 'yf' and 'av' available. Default 'yf' @@ -42,19 +43,22 @@ load -t S_TICKER [-s S_START_DATE] [-i {1,5,15,30,60}] **Note:** Until a ticker is loaded, the menu will only show *disc* and *sen* menu, as the others require a ticker being provided. ``` -clear +usage: clear ``` * Clear previously loaded stock ticker. ``` -view -t S_TICKER [-s S_START_DATE] [-i {1,5,15,30,60}] [--type N_TYPE] +usage: view [-t S_TICKER] [-s S_START_DATE] [-i {1,5,15,30,60}] [--type TYPE] [--raw] [--export {csv,json,xlsx}] ``` * Visualise historical data of a stock. An alpha_vantage key is necessary. + * -t : Stock ticker * -s : The starting date (format YYYY-MM-DD) of the stock * -i : Intraday stock minutes * --type : 1234 corresponds to types: 1. open; 2. high; 3.low; 4. close; while 14 corresponds to types: 1.open; 4. close + * --raw : Print raw data. + * --export : Export dataframe data to csv,json,xlsx file ![GNUS](https://user-images.githubusercontent.com/25267873/108925137-f2920e80-7633-11eb-8274-6e3bb6a19592.png) diff --git a/gamestonk_terminal/config_terminal.py b/gamestonk_terminal/config_terminal.py index 8039f5e3c5d..b09c6671f47 100644 --- a/gamestonk_terminal/config_terminal.py +++ b/gamestonk_terminal/config_terminal.py @@ -67,3 +67,6 @@ 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" + +# https://iexcloud.io +API_IEX_TOKEN = os.getenv("GT_API_IEX_KEY") or "REPLACE_ME" diff --git a/gamestonk_terminal/due_diligence/README.md b/gamestonk_terminal/due_diligence/README.md index c3db5073bac..1218e92e227 100644 --- a/gamestonk_terminal/due_diligence/README.md +++ b/gamestonk_terminal/due_diligence/README.md @@ -197,14 +197,19 @@ Display barchart of dark pool (ATS) and OTC (Non ATS) data ## ftd ```text -usage: ftd [-n N_NUM] +usage: ftd [-s START] [-e END] [-n N_NUM] [--raw] [--export {csv,json,xlsx}] ``` -The fails-to-deliver data collected by SEC. Fails to deliver on a given day are a cumulative number of all fails outstanding until that day, plus new fails that occur that day, less fails that settle that day. See . [Source: SEC] +The fails-to-deliver data collected by SEC. Fails to deliver on a given day are a cumulative number of all fails outstanding until that day, plus new fails that occur that day, less fails that settle that day. See . Note that FTD is 1 month delayed. [Source: SEC] -* -n : number of latest fails-to-deliver being printed. Default 20. +* -n : number of latest fails-to-deliver being printed. Default 0. Overrules start and end FTD datetime. +* -s : start of datetime to see FTD. Default 20 days in past. +* -e : end of datetime to see FTD. Default today. +* --raw : Print raw data. +* --export : Export dataframe data to csv,json,xlsx file + +![ftd](https://user-images.githubusercontent.com/25267873/125202513-d520b280-e26b-11eb-8091-5b221636a5ce.png) -![ftd](https://user-images.githubusercontent.com/25267873/115201750-93a9bc80-a0ed-11eb-8f13-68508749259e.png) ## shortview diff --git a/gamestonk_terminal/due_diligence/dd_controller.py b/gamestonk_terminal/due_diligence/dd_controller.py index d0cc6e7f28f..c738a314e6b 100644 --- a/gamestonk_terminal/due_diligence/dd_controller.py +++ b/gamestonk_terminal/due_diligence/dd_controller.py @@ -229,7 +229,7 @@ class DueDiligenceController: def call_ftd(self, other_args: List[str]): """Process ftd command""" - sec_view.fails_to_deliver(other_args, self.ticker) + sec_view.fails_to_deliver(other_args, self.ticker, self.stock) def call_shortview(self, other_args: List[str]): """Process shortview command""" diff --git a/gamestonk_terminal/due_diligence/sec_view.py b/gamestonk_terminal/due_diligence/sec_view.py index 9eb3f02e8f8..45eebe59465 100644 --- a/gamestonk_terminal/due_diligence/sec_view.py +++ b/gamestonk_terminal/due_diligence/sec_view.py @@ -2,8 +2,10 @@ __docformat__ = "numpy" import argparse +import os from typing import List -from datetime import datetime +from datetime import datetime, timedelta +from tabulate import tabulate import requests import pandas as pd from bs4 import BeautifulSoup @@ -14,10 +16,12 @@ from gamestonk_terminal.helper_funcs import ( get_user_agent, check_positive, parse_known_args_and_warn, + valid_date, + export_data, ) -def fails_to_deliver(other_args: List[str], ticker: str): +def fails_to_deliver(other_args: List[str], ticker: str, stock: pd.DataFrame): """Display fails-to-deliver data for a given ticker Parameters @@ -26,6 +30,8 @@ def fails_to_deliver(other_args: List[str], ticker: str): argparse other args - ["-n", "10"] ticker : str Stock ticker + stock : pd.DataFrame + Stock data """ parser = argparse.ArgumentParser( @@ -33,57 +39,148 @@ def fails_to_deliver(other_args: List[str], ticker: str): prog="ftd", description="""Prints latest fails-to-deliver data. [Source: SEC]""", ) + parser.add_argument( + "-s", + "--start", + action="store", + dest="start", + type=valid_date, + default=(datetime.now() - timedelta(days=60)).strftime("%Y-%m-%d"), + help="start of datetime to see FTD", + ) + parser.add_argument( + "-e", + "--end", + action="store", + dest="end", + type=valid_date, + default=datetime.now().strftime("%Y-%m-%d"), + help="end of datetime to see FTD", + ) parser.add_argument( "-n", "--num", action="store", dest="n_num", type=check_positive, - default=20, + default=0, help="number of latest fails-to-deliver being printed", ) + parser.add_argument( + "--raw", + action="store_true", + default=False, + dest="raw", + help="Print raw data.", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - url_ftds = "https://www.sec.gov/data/foiadocsfailsdatahtm" - text_soup_ftds = BeautifulSoup( - requests.get(url_ftds, headers={"User-Agent": get_user_agent()}).text, - "lxml", - ) - - table = text_soup_ftds.find("table", {"class": "list"}) - links = table.findAll("a") - link_idx = 0 ftds_data = pd.DataFrame() - while len(ftds_data) < ns_parser.n_num: - if link_idx > len(links): - break - link = links[link_idx] - url = "https://www.sec.gov" + link["href"] - all_ftds = pd.read_csv( - url, - compression="zip", - sep="|", - engine="python", - skipfooter=2, - usecols=[0, 2, 3, 5], - dtype={"QUANTITY (FAILS)": "int"}, - ) - tmp_ftds = all_ftds[all_ftds["SYMBOL"] == ticker] - del tmp_ftds["PRICE"] - del tmp_ftds["SYMBOL"] - # merge the data from this archive - ftds_data = pd.concat([ftds_data, tmp_ftds], ignore_index=True) - link_idx += 1 - # clip away extra rows - ftds_data = ftds_data.sort_values("SETTLEMENT DATE")[-ns_parser.n_num :] - ftds_data["SETTLEMENT DATE"] = ftds_data["SETTLEMENT DATE"].apply( - lambda x: datetime.strptime(str(x), "%Y%m%d") - ) + # Filter by number of last FTD + if ns_parser.n_num > 0: + url_ftds = "https://www.sec.gov/data/foiadocsfailsdatahtm" + text_soup_ftds = BeautifulSoup( + requests.get(url_ftds, headers={"User-Agent": get_user_agent()}).text, + "lxml", + ) + + table = text_soup_ftds.find("table", {"class": "list"}) + links = table.findAll("a") + link_idx = 0 + + while len(ftds_data) < ns_parser.n_num: + if link_idx > len(links): + break + link = links[link_idx] + url = "https://www.sec.gov" + link["href"] + all_ftds = pd.read_csv( + url, + compression="zip", + sep="|", + engine="python", + skipfooter=2, + usecols=[0, 2, 3, 5], + dtype={"QUANTITY (FAILS)": "int"}, + ) + tmp_ftds = all_ftds[all_ftds["SYMBOL"] == ticker] + del tmp_ftds["PRICE"] + del tmp_ftds["SYMBOL"] + # merge the data from this archive + ftds_data = pd.concat([ftds_data, tmp_ftds], ignore_index=True) + link_idx += 1 + + # clip away extra rows + ftds_data = ftds_data.sort_values("SETTLEMENT DATE")[-ns_parser.n_num :] + + ftds_data["SETTLEMENT DATE"] = ftds_data["SETTLEMENT DATE"].apply( + lambda x: datetime.strptime(str(x), "%Y%m%d") + ) + + # Filter by start and end dates for FTD + else: + + base_url = "https://www.sec.gov/files/data/fails-deliver-data/cnsfails" + ftd_dates = list() + + for y in range(ns_parser.start.year, ns_parser.end.year + 1): + if y < ns_parser.end.year: + for m in range(ns_parser.start.month, 13): + month = "%02d" % m + if m == ns_parser.start.month and y == ns_parser.start.year: + if ns_parser.start.day < 16: + ftd_dates.append(str(y) + month + "a") + ftd_dates.append(str(y) + month + "b") + else: + ftd_dates.append(str(y) + month + "a") + ftd_dates.append(str(y) + month + "b") + + else: + for m in range(1, ns_parser.end.month): + month = "%02d" % m + if m == ns_parser.end.month - 1: + ftd_dates.append(str(y) + month + "a") + if ns_parser.end.day > 15: + ftd_dates.append(str(y) + month + "b") + else: + ftd_dates.append(str(y) + month + "a") + ftd_dates.append(str(y) + month + "b") + + ftd_urls = [base_url + ftd_date + ".zip" for ftd_date in ftd_dates] + + for ftd_link in ftd_urls: + all_ftds = pd.read_csv( + ftd_link, + compression="zip", + sep="|", + engine="python", + skipfooter=2, + usecols=[0, 2, 3, 5], + dtype={"QUANTITY (FAILS)": "int"}, + ) + tmp_ftds = all_ftds[all_ftds["SYMBOL"] == ticker] + del tmp_ftds["PRICE"] + del tmp_ftds["SYMBOL"] + # merge the data from this archive + ftds_data = pd.concat([ftds_data, tmp_ftds], ignore_index=True) + + ftds_data["SETTLEMENT DATE"] = ftds_data["SETTLEMENT DATE"].apply( + lambda x: datetime.strptime(str(x), "%Y%m%d") + ) + + ftds_data = ftds_data[ftds_data["SETTLEMENT DATE"] > ns_parser.start] + ftds_data = ftds_data[ftds_data["SETTLEMENT DATE"] < ns_parser.end] plt.bar( ftds_data["SETTLEMENT DATE"], @@ -97,12 +194,42 @@ def fails_to_deliver(other_args: List[str], ticker: str): plt.gcf().autofmt_xdate() plt.xlabel("Days") + _ = plt.gca().twinx() + + if ns_parser.n_num > 0: + stock_ftd = stock[ + stock.index > (datetime.now() - timedelta(days=ns_parser.n_num + 31)) + ] + else: + stock_ftd = stock[stock.index > ns_parser.start] + stock_ftd = stock_ftd[stock_ftd.index < ns_parser.end] + plt.plot(stock_ftd.index, stock_ftd["Adj Close"], color="tab:orange") + plt.ylabel("Share Price [$]") + if gtff.USE_ION: plt.ion() plt.show() - print("") + if ns_parser.raw: + print( + tabulate( + ftds_data, + headers=ftds_data.columns, + tablefmt="fancy_grid", + stralign="right", + showindex=False, + ) + ) + print("") + + export_data( + ns_parser.export, + os.path.dirname(os.path.abspath(__file__)), + "ftd", + ftds_data.reset_index(), + ) + except Exception as e: print(e, "\n") diff --git a/gamestonk_terminal/helper_funcs.py b/gamestonk_terminal/helper_funcs.py index 56bf154c42a..e28ca71efe1 100644 --- a/gamestonk_terminal/helper_funcs.py +++ b/gamestonk_terminal/helper_funcs.py @@ -458,15 +458,6 @@ def lett_to_num(word: str) -> str: return word -def check_sources(source: str) -> str: - available_historical_price_sources = ["yf", "av"] - if source in available_historical_price_sources: - return source - raise argparse.ArgumentTypeError( - "This source for historical data is not available." - ) - - def get_flair() -> str: flair = { "rocket": "(🚀🚀)", diff --git a/gamestonk_terminal/main_helper.py b/gamestonk_terminal/main_helper.py index 952c8b3c696..98944fe44ab 100644 --- a/gamestonk_terminal/main_helper.py +++ b/gamestonk_terminal/main_helper.py @@ -16,11 +16,12 @@ from alpha_vantage.timeseries import TimeSeries import mplfinance as mpf import yfinance as yf import pytz +import pyEX from tabulate import tabulate # import git -# pylint: disable=no-member +# pylint: disable=no-member,too-many-branches from gamestonk_terminal.helper_funcs import ( valid_date, @@ -28,8 +29,8 @@ from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, check_ohlc, lett_to_num, - check_sources, plot_autoscale, + export_data, ) from gamestonk_terminal import config_terminal as cfg @@ -99,7 +100,7 @@ def load(other_args: List[str], s_ticker, s_start, s_interval, df_stock): "--ticker", action="store", dest="s_ticker", - required=True, + required="-h" not in other_args, help="Stock ticker", ) parser.add_argument( @@ -124,9 +125,9 @@ def load(other_args: List[str], s_ticker, s_start, s_interval, df_stock): "--source", action="store", dest="source", - type=check_sources, + choices=["yf", "av", "iex"], default="yf", - help="Source of historical data. 'yf' and 'av' available.", + help="Source of historical data.", ) parser.add_argument( "-p", @@ -140,7 +141,7 @@ def load(other_args: List[str], s_ticker, s_start, s_interval, df_stock): try: # For the case where a user uses: 'load BB' if other_args: - if "-t" not in other_args: + if "-t" not in other_args and "-h" not in other_args: other_args.insert(0, "-t") ns_parser = parse_known_args_and_warn(parser, other_args) @@ -194,6 +195,36 @@ def load(other_args: List[str], s_ticker, s_start, s_interval, df_stock): df_stock_candidate.index.name = "date" + # IEX Cloud Source + elif ns_parser.source == "iex": + client = pyEX.Client(api_token=cfg.API_IEX_TOKEN, version="v1") + + df_stock_candidate = client.chartDF(ns_parser.s_ticker) + + # Check that loading a stock was not successful + if df_stock_candidate.empty: + print("") + return [s_ticker, s_start, s_interval, df_stock] + + df_stock_candidate = df_stock_candidate[ + ["uClose", "uHigh", "uLow", "uOpen", "fClose", "volume"] + ] + df_stock_candidate = df_stock_candidate.rename( + columns={ + "uClose": "Close", + "uHigh": "High", + "uLow": "Low", + "uOpen": "Open", + "fClose": "Adj Close", + "volume": "Volume", + } + ) + + df_stock_candidate.sort_index(ascending=True, inplace=True) + + # Slice dataframe from the starting date YYYY-MM-DD selected + df_stock_candidate = df_stock_candidate[ns_parser.s_start_date :] + # Check if start time from dataframe is more recent than specified if df_stock_candidate.index[0] > pd.to_datetime(ns_parser.s_start_date): s_start = df_stock_candidate.index[0] @@ -246,7 +277,7 @@ def load(other_args: List[str], s_ticker, s_start, s_interval, df_stock): # Yahoo Finance Source elif ns_parser.source == "yf": s_int = str(ns_parser.n_interval) + "m" - s_interval = s_int + s_interval = s_int + "in" d_granularity = {"1m": 6, "5m": 59, "15m": 59, "30m": 59, "60m": 729} s_start_dt = datetime.utcnow() - timedelta(days=d_granularity[s_int]) @@ -284,6 +315,53 @@ def load(other_args: List[str], s_ticker, s_start, s_interval, df_stock): df_stock_candidate.index.name = "date" + # IEX Cloud Source + elif ns_parser.source == "iex": + + s_interval = str(ns_parser.n_interval) + "min" + client = pyEX.Client(api_token=cfg.API_IEX_TOKEN, version="v1") + + df_stock_candidate = client.chartDF(ns_parser.s_ticker) + + df_stock_candidate = client.intradayDF(ns_parser.s_ticker).iloc[ + 0 :: ns_parser.n_interval + ] + + df_stock_candidate = df_stock_candidate[ + ["close", "high", "low", "open", "volume", "close"] + ] + df_stock_candidate.columns = [ + x.capitalize() for x in df_stock_candidate.columns + ] + + df_stock_candidate.columns = list(df_stock_candidate.columns[:-1]) + [ + "Adj Close" + ] + + df_stock_candidate.sort_index(ascending=True, inplace=True) + + new_index = list() + for idx in range(len(df_stock_candidate)): + dt_time = datetime.strptime( + df_stock_candidate.index[idx][1], "%H:%M" + ) + new_index.append( + df_stock_candidate.index[idx][0] + + timedelta(hours=dt_time.hour, minutes=dt_time.minute) + ) + + df_stock_candidate.index = pd.DatetimeIndex(new_index) + df_stock_candidate.index.name = "date" + + # Slice dataframe from the starting date YYYY-MM-DD selected + df_stock_candidate = df_stock_candidate[ns_parser.s_start_date :] + + # Check if start time from dataframe is more recent than specified + if df_stock_candidate.index[0] > pd.to_datetime(ns_parser.s_start_date): + s_start = df_stock_candidate.index[0] + else: + s_start = ns_parser.s_start_date + s_intraday = (f"Intraday {s_interval}", "Daily")[ns_parser.n_interval == 1440] print( @@ -468,7 +546,7 @@ def view(other_args: List[str], s_ticker: str, s_start, s_interval, df_stock): parser = argparse.ArgumentParser( add_help=False, prog="view", - description="Visualize historical data of a stock. An alpha_vantage key is necessary.", + description="Visualize historical data of a stock.", ) if s_ticker: parser.add_argument( @@ -485,7 +563,7 @@ def view(other_args: List[str], s_ticker: str, s_start, s_interval, df_stock): "--ticker", action="store", dest="s_ticker", - required=True, + required="-h" not in other_args, help="Stock ticker", ) parser.add_argument( @@ -493,7 +571,7 @@ def view(other_args: List[str], s_ticker: str, s_start, s_interval, df_stock): "--start", type=valid_date, dest="s_start_date", - default=s_start, + default=s_start if s_start else "2019-01-01", help="The starting date (format YYYY-MM-DD) of the stock", ) parser.add_argument( @@ -517,135 +595,117 @@ def view(other_args: List[str], s_ticker: str, s_start, s_interval, df_stock): "while oc corresponds to types: open; close" ), ) + parser.add_argument( + "--raw", + action="store_true", + default=False, + dest="b_raw", + help="Print raw data.", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - except SystemExit: - print("") - return + # Update values: + if ns_parser.s_ticker != s_ticker: + if ns_parser.n_interval > 0: + s_ticker, s_start, s_interval, df_stock = load( + [ + "-t", + ns_parser.s_ticker, + "-s", + ns_parser.s_start_date.strftime("%Y-%m-%d"), + "-i", + ns_parser.n_interval, + ], + s_ticker, + s_start, + s_interval, + df_stock, + ) + else: + s_ticker, s_start, s_interval, df_stock = load( + [ + "-t", + ns_parser.s_ticker, + "-s", + ns_parser.s_start_date.strftime("%Y-%m-%d"), + ], + s_ticker, + s_start, + s_interval, + df_stock, + ) - # Update values: - if ns_parser.s_ticker != s_ticker: - if ns_parser.n_interval > 0: - s_ticker, s_start, s_interval, df_stock = load( - [ - "-t", - ns_parser.s_ticker, - "-s", - ns_parser.s_start_date.strftime("%Y-%m-%d"), - "-i", - ns_parser.n_interval, - ], - s_ticker, - s_start, - s_interval, - df_stock, - ) - else: - s_ticker, s_start, s_interval, df_stock = load( - [ - "-t", - ns_parser.s_ticker, - "-s", - ns_parser.s_start_date.strftime("%Y-%m-%d"), - ], - s_ticker, - s_start, - s_interval, - df_stock, - ) + # A new interval intraday period was given + if ns_parser.n_interval != 0: + s_interval = str(ns_parser.n_interval) + "min" - # A new interval intraday period was given - if ns_parser.n_interval != 0: - s_interval = str(ns_parser.n_interval) + "min" + type_candles = lett_to_num(ns_parser.type) - type_candles = lett_to_num(ns_parser.type) + df_stock.sort_index(ascending=True, inplace=True) - df_stock.sort_index(ascending=True, inplace=True) - - # Daily - if s_interval == "1440min": - # The default doesn't exist for intradaily data - ln_col_idx = [int(x) - 1 for x in list(type_candles)] - # Check that the types given are not bigger than 4, as there are only 5 types (0-4) - # pylint: disable=len-as-condition - if len([i for i in ln_col_idx if i > 4]) > 0: - print("An index bigger than 4 was given, which is wrong. Try again") - return - # Append last column of df to be filtered which corresponds to: Volume - ln_col_idx.append(5) - # Slice dataframe from the starting date YYYY-MM-DD selected - df_stock = df_stock[ns_parser.s_start_date :] - # Intraday - else: - # The default doesn't exist for intradaily data - # JM edit 6-7-21 -- It seems it does - if ns_parser.type == "a": - ln_col_idx = [4] - else: + # Daily + if s_interval == "1440min": + # The default doesn't exist for intradaily data ln_col_idx = [int(x) - 1 for x in list(type_candles)] + # Check that the types given are not bigger than 4, as there are only 5 types (0-4) + # pylint: disable=len-as-condition + if len([i for i in ln_col_idx if i > 4]) > 0: + print("An index bigger than 4 was given, which is wrong. Try again") + return + # Append last column of df to be filtered which corresponds to: Volume + ln_col_idx.append(5) + # Slice dataframe from the starting date YYYY-MM-DD selected + df_stock = df_stock[ns_parser.s_start_date :] + # Intraday + else: + # The default doesn't exist for intradaily data + # JM edit 6-7-21 -- It seems it does + if ns_parser.type == "a": + ln_col_idx = [4] + else: + ln_col_idx = [int(x) - 1 for x in list(type_candles)] - # Append last column of df to be filtered which corresponds to: 5. Volume - ln_col_idx.append(5) - # Slice dataframe from the starting date YYYY-MM-DD selected - df_stock = df_stock[ns_parser.s_start_date.strftime("%Y-%m-%d") :] + # Append last column of df to be filtered which corresponds to: 5. Volume + ln_col_idx.append(5) + # Slice dataframe from the starting date YYYY-MM-DD selected + df_stock = df_stock[ns_parser.s_start_date.strftime("%Y-%m-%d") :] - # Plot view of the stock - plot_view_stock(df_stock.iloc[:, ln_col_idx], ns_parser.s_ticker, s_interval) + # Plot view of the stock + plot_view_stock(df_stock.iloc[:, ln_col_idx], ns_parser.s_ticker, s_interval) + if ns_parser.b_raw: + print( + tabulate( + df_stock, + headers=df_stock.columns, + tablefmt="fancy_grid", + stralign="right", + ) + ) + print("") -def export(other_args: List[str], df_stock): - parser = argparse.ArgumentParser( - add_help=False, - prog="export", - description="Exports the historical data from this ticker to a file or stdout.", - ) - parser.add_argument( - "-f", - "--filename", - type=str, - dest="s_filename", - default=sys.stdout, - help="Name of file to save the historical data exported (stdout if unspecified)", - ) - parser.add_argument( - "-F", - "--format", - dest="s_format", - type=str, - default="csv", - help="Export historical data into following formats: csv, json, excel, clipboard", - ) - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return + export_data( + ns_parser.export, + os.path.dirname(os.path.abspath(__file__)), + "view", + df_stock, + ) except SystemExit: print("") return - if df_stock.empty: - print("No data loaded yet to export.") - return - - if ns_parser.s_format == "csv": - df_stock.to_csv(ns_parser.s_filename) - - elif ns_parser.s_format == "json": - df_stock.to_json(ns_parser.s_filename) - - elif ns_parser.s_format == "excel": - df_stock.to_excel(ns_parser.s_filename) - - elif ns_parser.s_format == "clipboard": - df_stock.to_clipboard() - - print("") - def print_goodbye(): goodbye_msg = [ diff --git a/poetry.lock b/poetry.lock index adea115fa48..9737f2de3d1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -496,6 +496,17 @@ wrapt = "*" lint = ["flake8"] tests = ["pytest"] +[[package]] +name = "deprecation" +version = "2.1.0" +description = "A library to handle automated deprecations" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +packaging = "*" + [[package]] name = "detecta" version = "0.0.5" @@ -639,6 +650,14 @@ python-versions = "*" [package.dependencies] pandas = "*" +[[package]] +name = "frozendict" +version = "2.0.3" +description = "A simple immutable dictionary" +category = "main" +optional = false +python-versions = ">=3.6" + [[package]] name = "fundamentalanalysis" version = "0.2.10" @@ -1841,6 +1860,31 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +[[package]] +name = "pyex" +version = "0.5.0" +description = "Rest API to IEX" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +deprecation = ">=2.0.6" +ipython = ">=7.2.0" +pandas = ">=0.22" +Pillow = ">=5.3.0" +pytz = ">=2019.1" +requests = ">=2.21.0" +six = "*" +socketIO-client-nexus = ">=0.7.6" +sseclient = ">=0.0.22" +temporal-cache = ">=0.1.1" + +[package.extras] +async = ["deprecation (>=2.0.6)", "ipython (>=7.2.0)", "Pillow (>=5.3.0)", "pandas (>=0.22)", "pytz (>=2019.1)", "requests (>=2.21.0)", "six", "socketIO-client-nexus (>=0.7.6)", "sseclient (>=0.0.22)", "temporal-cache (>=0.1.1)", "aiohttp (>=3.2)", "aiohttp-sse-client (>=0.2.0)", "aiostream (>=0.3.1)"] +dev = ["deprecation (>=2.0.6)", "ipython (>=7.2.0)", "Pillow (>=5.3.0)", "pandas (>=0.22)", "pytz (>=2019.1)", "requests (>=2.21.0)", "six", "socketIO-client-nexus (>=0.7.6)", "sseclient (>=0.0.22)", "temporal-cache (>=0.1.1)", "aiohttp (>=3.2)", "aiohttp-sse-client (>=0.2.0)", "aiostream (>=0.3.1)", "TA-Lib (>=0.4.17)", "black (>=20)", "bump2version (>=1.0.0)", "flake8 (>=3.7.8)", "flake8-black (>=0.2.1)", "mock", "pytest (>=4.3.0)", "pytest-cov (>=2.6.1)", "recommonmark", "Sphinx (>=1.8.4)", "sphinx-markdown-builder (>=0.5.2)", "sphinx-rtd-theme"] +studies = ["TA-Lib (>=0.4.17)"] + [[package]] name = "pyflakes" version = "2.3.1" @@ -2347,6 +2391,19 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "socketio-client-nexus" +version = "0.7.6" +description = "A socket.io client library" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +requests = ">=2.7.0" +six = "*" +websocket-client = "*" + [[package]] name = "soupsieve" version = "2.2.1" @@ -2472,6 +2529,18 @@ python-versions = ">=3.5" lint = ["flake8", "mypy", "docutils-stubs"] test = ["pytest"] +[[package]] +name = "sseclient" +version = "0.0.27" +description = "Python client library for reading Server Sent Event streams." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +requests = ">=2.9" +six = "*" + [[package]] name = "statsmodels" version = "0.12.2" @@ -2502,6 +2571,21 @@ python-versions = "*" [package.extras] widechars = ["wcwidth"] +[[package]] +name = "temporal-cache" +version = "0.1.4" +description = "Time based function caching" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +frozendict = ">=1.2" +tzlocal = ">=2.0.0" + +[package.extras] +dev = ["black (>=20)", "bump2version (>=1.0.0)", "flake8 (>=3.7.8)", "flake8-black (>=0.2.1)", "mock", "pytest (>=4.3.0)", "pytest-cov (>=2.6.1)", "Sphinx (>=1.8.4)", "sphinx-markdown-builder (>=0.5.2)", "frozendict (>=1.2)", "tzlocal (>=2.0.0)"] + [[package]] name = "tenacity" version = "7.0.0" @@ -2933,7 +3017,7 @@ prediction = ["tensorflow", "pmdarima"] [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "25a6b84904e2d1523dbd3cb88dbf551c3931d1bcc10811f8bb60cff5b9caa729" +content-hash = "d6c9d143d3bd881bb77cc1f46da2f70687505cc9c1a108deab377e56a249bfa5" [metadata.files] absl-py = [ @@ -3022,10 +3106,6 @@ argon2-cffi = [ {file = "argon2_cffi-20.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:9dfd5197852530294ecb5795c97a823839258dfd5eb9420233c7cfedec2058f2"}, {file = "argon2_cffi-20.1.0-cp39-cp39-win32.whl", hash = "sha256:e2db6e85c057c16d0bd3b4d2b04f270a7467c147381e8fd73cbbe5bc719832be"}, {file = "argon2_cffi-20.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:8a84934bd818e14a17943de8099d41160da4a336bcc699bb4c394bbb9b94bd32"}, - {file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-macosx_10_7_x86_64.whl", hash = "sha256:b94042e5dcaa5d08cf104a54bfae614be502c6f44c9c89ad1535b2ebdaacbd4c"}, - {file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:8282b84ceb46b5b75c3a882b28856b8cd7e647ac71995e71b6705ec06fc232c3"}, - {file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3aa804c0e52f208973845e8b10c70d8957c9e5a666f702793256242e9167c4e0"}, - {file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:36320372133a003374ef4275fbfce78b7ab581440dfca9f9471be3dd9a522428"}, ] astroid = [ {file = "astroid-2.5.6-py3-none-any.whl", hash = "sha256:4db03ab5fc3340cf619dbc25e42c2cc3755154ce6009469766d7143d1fc2ee4e"}, @@ -3115,36 +3195,24 @@ cffi = [ {file = "cffi-1.14.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058"}, {file = "cffi-1.14.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5"}, {file = "cffi-1.14.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132"}, - {file = "cffi-1.14.5-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24ec4ff2c5c0c8f9c6b87d5bb53555bf267e1e6f70e52e5a9740d32861d36b6f"}, - {file = "cffi-1.14.5-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c3f39fa737542161d8b0d680df2ec249334cd70a8f420f71c9304bd83c3cbed"}, - {file = "cffi-1.14.5-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:681d07b0d1e3c462dd15585ef5e33cb021321588bebd910124ef4f4fb71aef55"}, {file = "cffi-1.14.5-cp36-cp36m-win32.whl", hash = "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53"}, {file = "cffi-1.14.5-cp36-cp36m-win_amd64.whl", hash = "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813"}, {file = "cffi-1.14.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73"}, {file = "cffi-1.14.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06"}, {file = "cffi-1.14.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1"}, {file = "cffi-1.14.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49"}, - {file = "cffi-1.14.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06d7cd1abac2ffd92e65c0609661866709b4b2d82dd15f611e602b9b188b0b69"}, - {file = "cffi-1.14.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f861a89e0043afec2a51fd177a567005847973be86f709bbb044d7f42fc4e05"}, - {file = "cffi-1.14.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc5a8e069b9ebfa22e26d0e6b97d6f9781302fe7f4f2b8776c3e1daea35f1adc"}, {file = "cffi-1.14.5-cp37-cp37m-win32.whl", hash = "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62"}, {file = "cffi-1.14.5-cp37-cp37m-win_amd64.whl", hash = "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4"}, {file = "cffi-1.14.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053"}, {file = "cffi-1.14.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0"}, {file = "cffi-1.14.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e"}, {file = "cffi-1.14.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827"}, - {file = "cffi-1.14.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04c468b622ed31d408fea2346bec5bbffba2cc44226302a0de1ade9f5ea3d373"}, - {file = "cffi-1.14.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:06db6321b7a68b2bd6df96d08a5adadc1fa0e8f419226e25b2a5fbf6ccc7350f"}, - {file = "cffi-1.14.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:293e7ea41280cb28c6fcaaa0b1aa1f533b8ce060b9e701d78511e1e6c4a1de76"}, {file = "cffi-1.14.5-cp38-cp38-win32.whl", hash = "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e"}, {file = "cffi-1.14.5-cp38-cp38-win_amd64.whl", hash = "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396"}, {file = "cffi-1.14.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea"}, {file = "cffi-1.14.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322"}, {file = "cffi-1.14.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c"}, {file = "cffi-1.14.5-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee"}, - {file = "cffi-1.14.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bf1ac1984eaa7675ca8d5745a8cb87ef7abecb5592178406e55858d411eadc0"}, - {file = "cffi-1.14.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:df5052c5d867c1ea0b311fb7c3cd28b19df469c056f7fdcfe88c7473aa63e333"}, - {file = "cffi-1.14.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24a570cd11895b60829e941f2613a4f79df1a27344cbbb82164ef2e0116f09c7"}, {file = "cffi-1.14.5-cp39-cp39-win32.whl", hash = "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396"}, {file = "cffi-1.14.5-cp39-cp39-win_amd64.whl", hash = "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d"}, {file = "cffi-1.14.5.tar.gz", hash = "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c"}, @@ -3188,8 +3256,6 @@ cssselect = [ {file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"}, ] cvxpy = [ - {file = "cvxpy-1.1.12-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:48e9bae36a43453659ca5d0c85e78f1eb0dfe629b8aa0f023f65aa59d0ac04d7"}, - {file = "cvxpy-1.1.12-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fe0bcb7f83b5d4deb760bf033cb72ab97c8e0770b116e08d96e9726cb1a52c01"}, {file = "cvxpy-1.1.12-cp36-cp36m-win_amd64.whl", hash = "sha256:86f8e4aa1a79482431b89aa526249d9fda04c74e04a3ec224d1175d281643d71"}, {file = "cvxpy-1.1.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:90b09a7361b9c614166fa673e1fe9321317df6939135330e1621b9a0bf10e3a8"}, {file = "cvxpy-1.1.12-cp37-cp37m-win_amd64.whl", hash = "sha256:084e5292f2a13133a1cd28d68f5af1df33a5119b0f1aec7cecf834eea3e2d11d"}, @@ -3197,8 +3263,6 @@ cvxpy = [ {file = "cvxpy-1.1.12-cp38-cp38-win_amd64.whl", hash = "sha256:76d04444cb50ad2840bbc72a625ac246b5eeeeb580ee20c71bec057822667738"}, {file = "cvxpy-1.1.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2de5e0e75316839bc71b5df2c2db0131cee7ef06dac566c6c44dc852c091502b"}, {file = "cvxpy-1.1.12-cp39-cp39-win_amd64.whl", hash = "sha256:9fa4d033ab31855aea090e4b358017b36880390a7d0e6e97ecc5226c77eab489"}, - {file = "cvxpy-1.1.12-py3.5-macosx-10.9-x86_64.egg", hash = "sha256:27ff263c80700b097d3714ba34161bd284f736f3029dfa89a95bf4c4a2801cb9"}, - {file = "cvxpy-1.1.12-py3.6-macosx-10.7-x86_64.egg", hash = "sha256:7c1c5371dda78580f0892fba6776abb6e43bdb45589311c3179a057f1a984110"}, {file = "cvxpy-1.1.12-py3.6-win-amd64.egg", hash = "sha256:d2c28e0eea1b6dc70262c9ed8b63c5c1747d85c28b3ec24cbaab07583b3ad729"}, {file = "cvxpy-1.1.12-py3.7-win-amd64.egg", hash = "sha256:44d0e3d60693831ac70bdc9b2e23faf84401347bfcdef4eb5da5ae22ac57f5ff"}, {file = "cvxpy-1.1.12-py3.8-win-amd64.egg", hash = "sha256:c86f8de9a63ccbd45844a4482df8099824688b5329060f089aad1c3beb939190"}, @@ -3268,6 +3332,10 @@ degiro-connector = [ {file = "degiro-connector-1.0.0.tar.gz", hash = "sha256:e4e694d3065bbc718cf32205c6880f621ec64be0d6003fb2e539f696e770e8dd"}, {file = "degiro_connector-1.0.0-py3-none-any.whl", hash = "sha256:948b93e2e917b432b59facf05736dad0a3f033b2284199af1ed536b17bfc1dba"}, ] +deprecation = [ + {file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"}, + {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, +] detecta = [ {file = "detecta-0.0.5-py3-none-any.whl", hash = "sha256:dbaf1938e5d785386c904034e2553824e2aa31793e967984ca65983aca06d23e"}, {file = "detecta-0.0.5.tar.gz", hash = "sha256:d2ea7d13dfbbc994d6ce385a7f8dc0a85fe675a8a8e712a64ec56e54c40603ed"}, @@ -3331,6 +3399,10 @@ fredapi = [ {file = "fredapi-0.4.3-py3-none-any.whl", hash = "sha256:e06075592eabddadfe0635f3c59e9072c9f48647430328b4582171ea10f7df2f"}, {file = "fredapi-0.4.3.tar.gz", hash = "sha256:d9b3194fb60541991bd33f019c710d4a9580ecfb5e47efbf2d2571888a2aac02"}, ] +frozendict = [ + {file = "frozendict-2.0.3-py3-none-any.whl", hash = "sha256:58143e2d3d11699bc295d9e7e05f10dde99a727e2295d7f43542ecdc42c5ec70"}, + {file = "frozendict-2.0.3.tar.gz", hash = "sha256:163c616188beb97fdc8ef6e73ec2ebd70a844d4cf19d2e383aa94d1b8376653d"}, +] fundamentalanalysis = [ {file = "FundamentalAnalysis-0.2.10-py3-none-any.whl", hash = "sha256:bca61d350e7a938e8e544b70871e9751ded9909f193ddeac7baa44a431297184"}, {file = "FundamentalAnalysis-0.2.10.tar.gz", hash = "sha256:b6f2224e1a369b4eb7c3af0a4e62049c0fb1a34fc9535b454b6b13cefe530191"}, @@ -3603,40 +3675,30 @@ lxml = [ {file = "lxml-4.6.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4"}, {file = "lxml-4.6.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51"}, {file = "lxml-4.6.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586"}, - {file = "lxml-4.6.3-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:4c61b3a0db43a1607d6264166b230438f85bfed02e8cff20c22e564d0faff354"}, - {file = "lxml-4.6.3-cp35-cp35m-manylinux2014_x86_64.whl", hash = "sha256:5c8c163396cc0df3fd151b927e74f6e4acd67160d6c33304e805b84293351d16"}, {file = "lxml-4.6.3-cp35-cp35m-win32.whl", hash = "sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2"}, {file = "lxml-4.6.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4"}, {file = "lxml-4.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4"}, {file = "lxml-4.6.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3"}, {file = "lxml-4.6.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d"}, - {file = "lxml-4.6.3-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d916d31fd85b2f78c76400d625076d9124de3e4bda8b016d25a050cc7d603f24"}, {file = "lxml-4.6.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec"}, - {file = "lxml-4.6.3-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:c47ff7e0a36d4efac9fd692cfa33fbd0636674c102e9e8d9b26e1b93a94e7617"}, {file = "lxml-4.6.3-cp36-cp36m-win32.whl", hash = "sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04"}, {file = "lxml-4.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a"}, {file = "lxml-4.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654"}, {file = "lxml-4.6.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0"}, {file = "lxml-4.6.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3"}, - {file = "lxml-4.6.3-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:36108c73739985979bf302006527cf8a20515ce444ba916281d1c43938b8bb96"}, {file = "lxml-4.6.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2"}, - {file = "lxml-4.6.3-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:cdaf11d2bd275bf391b5308f86731e5194a21af45fbaaaf1d9e8147b9160ea92"}, {file = "lxml-4.6.3-cp37-cp37m-win32.whl", hash = "sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade"}, {file = "lxml-4.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b"}, {file = "lxml-4.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa"}, {file = "lxml-4.6.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a"}, {file = "lxml-4.6.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927"}, - {file = "lxml-4.6.3-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:e1cbd3f19a61e27e011e02f9600837b921ac661f0c40560eefb366e4e4fb275e"}, {file = "lxml-4.6.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791"}, - {file = "lxml-4.6.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:1b38116b6e628118dea5b2186ee6820ab138dbb1e24a13e478490c7db2f326ae"}, {file = "lxml-4.6.3-cp38-cp38-win32.whl", hash = "sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28"}, {file = "lxml-4.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7"}, {file = "lxml-4.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0"}, {file = "lxml-4.6.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1"}, {file = "lxml-4.6.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23"}, - {file = "lxml-4.6.3-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:3082c518be8e97324390614dacd041bb1358c882d77108ca1957ba47738d9d59"}, {file = "lxml-4.6.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969"}, - {file = "lxml-4.6.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:6f12e1427285008fd32a6025e38e977d44d6382cf28e7201ed10d6c1698d2a9a"}, {file = "lxml-4.6.3-cp39-cp39-win32.whl", hash = "sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f"}, {file = "lxml-4.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83"}, {file = "lxml-4.6.3.tar.gz", hash = "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468"}, @@ -4046,7 +4108,6 @@ pillow = [ {file = "Pillow-8.2.0-pp37-pypy37_pp73-manylinux2010_i686.whl", hash = "sha256:aac00e4bc94d1b7813fe882c28990c1bc2f9d0e1aa765a5f2b516e8a6a16a9e4"}, {file = "Pillow-8.2.0-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:22fd0f42ad15dfdde6c581347eaa4adb9a6fc4b865f90b23378aa7914895e120"}, {file = "Pillow-8.2.0-pp37-pypy37_pp73-win32.whl", hash = "sha256:e98eca29a05913e82177b3ba3d198b1728e164869c613d76d0de4bde6768a50e"}, - {file = "Pillow-8.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:8b56553c0345ad6dcb2e9b433ae47d67f95fc23fe28a0bde15a120f25257e291"}, {file = "Pillow-8.2.0.tar.gz", hash = "sha256:a787ab10d7bb5494e5f76536ac460741788f1fbce851068d73a87ca7c35fc3e1"}, ] plotly = [ @@ -4174,6 +4235,10 @@ pycparser = [ {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] +pyex = [ + {file = "pyEX-0.5.0-py2.py3-none-any.whl", hash = "sha256:8860b8eb9c15d91e5f552786fbe8f8ecd46c4c4931e5cb82ba41187eb603f742"}, + {file = "pyEX-0.5.0.tar.gz", hash = "sha256:e85c392733aec3717b00d05640bd7efcfc87bf949064a7f31112293fe395c27e"}, +] pyflakes = [ {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, @@ -4589,6 +4654,10 @@ snowballstemmer = [ {file = "snowballstemmer-2.1.0-py2.py3-none-any.whl", hash = "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2"}, {file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"}, ] +socketio-client-nexus = [ + {file = "socketIO-client-nexus-0.7.6.tar.gz", hash = "sha256:41e6aaaff981f6729690f472eb2c7a5d1dda07349077e34444527b9700b0aea5"}, + {file = "socketIO_client_nexus-0.7.6-py2.py3-none-any.whl", hash = "sha256:9f44d705c38e405fcb334f95c1d5d5878a8daabdfeaca3ba56e974b69f42e643"}, +] soupsieve = [ {file = "soupsieve-2.2.1-py3-none-any.whl", hash = "sha256:c2c1c2d44f158cdbddab7824a9af8c4f83c76b1e23e049479aa432feb6c4c23b"}, {file = "soupsieve-2.2.1.tar.gz", hash = "sha256:052774848f448cf19c7e959adf5566904d525f33a3f8b6ba6f6f8f26ec7de0cc"}, @@ -4625,6 +4694,9 @@ sphinxcontrib-serializinghtml = [ {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, ] +sseclient = [ + {file = "sseclient-0.0.27.tar.gz", hash = "sha256:b2fe534dcb33b1d3faad13d60c5a7c718e28f85987f2a034ecf5ec279918c11c"}, +] statsmodels = [ {file = "statsmodels-0.12.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:c1d98ce2072f5e772cbf91d05475490368da5d3ee4a3150062330c7b83221ceb"}, {file = "statsmodels-0.12.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4184487e9c281acad3d0bda19445c69db292f0dbb18f25ebf56a7966a0a28eef"}, @@ -4652,6 +4724,10 @@ tabulate = [ {file = "tabulate-0.8.9-py3-none-any.whl", hash = "sha256:d7c013fe7abbc5e491394e10fa845f8f32fe54f8dc60c6622c6cf482d25d47e4"}, {file = "tabulate-0.8.9.tar.gz", hash = "sha256:eb1d13f25760052e8931f2ef80aaf6045a6cceb47514db8beab24cded16f13a7"}, ] +temporal-cache = [ + {file = "temporal-cache-0.1.4.tar.gz", hash = "sha256:b6dd850359c46bd4a5c59fc3b953f8924e429b1179a351b3508d07c214738b50"}, + {file = "temporal_cache-0.1.4-py2.py3-none-any.whl", hash = "sha256:8d9a83bc247b8e1fc51bcbae0fe650ae510fa67818a19a688f93ae27a9298e7d"}, +] tenacity = [ {file = "tenacity-7.0.0-py2.py3-none-any.whl", hash = "sha256:a0ce48587271515db7d3a5e700df9ae69cce98c4b57c23a4886da15243603dd8"}, {file = "tenacity-7.0.0.tar.gz", hash = "sha256:5bd16ef5d3b985647fe28dfa6f695d343aa26479a04e8792b9d3c8f49e361ae1"}, diff --git a/pyproject.toml b/pyproject.toml index 56071d32dcc..c1781262092 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,6 +74,7 @@ degiro-connector = "1.0.0" mypy = "^0.901" GitPython = "^3.1.17" fear-greed-index = "^0.1.3" +pyEX = "^0.5.0" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements-full.txt b/requirements-full.txt index 864bca7c9d8..63273fa9612 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -136,6 +136,7 @@ pyasn1-modules==0.2.8; python_version >= "2.7" and python_full_version < "3.0.0" pyasn1==0.4.8; python_version >= "3.5" and python_full_version < "3.0.0" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") or python_version >= "3.5" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") and python_full_version >= "3.6.0" pycoingecko==1.4.1 pycparser==2.20; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +pyEX==0.5.0 pygments==2.9.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6" pymeeus==0.5.11; python_version >= "3.5" pyobjc-core==7.3; python_version >= "3.6" and sys_platform == "darwin" diff --git a/requirements.txt b/requirements.txt index 117477d4b54..8dbb06f129b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -122,6 +122,7 @@ py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" and implem pyally==1.1.2 pycoingecko==1.4.1 pycparser==2.20; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +pyEX==0.5.0 pygments==2.9.0; python_full_version >= "3.6.8" and python_full_version < "4.0.0" and python_version >= "3.6" pymeeus==0.5.11; python_version >= "3.5" pyobjc-core==7.3; python_version >= "3.6" and sys_platform == "darwin" diff --git a/terminal.py b/terminal.py index ca9fd678951..492c3524a13 100644 --- a/terminal.py +++ b/terminal.py @@ -15,7 +15,6 @@ from prompt_toolkit.completion import NestedCompleter from gamestonk_terminal.helper_funcs import b_is_stock_market_open, get_flair from gamestonk_terminal.main_helper import ( clear, - export, load, view, candle, @@ -87,7 +86,6 @@ class TerminalController: "quote", "candle", "view", - "export", "disc", "scr", "mill", @@ -172,7 +170,6 @@ Contexts: help_text += """quote view the current price for a specific stock ticker candle view a candle chart for a specific stock ticker view view and load a specific stock ticker for technical analysis - export export the currently loaded dataframe to a file or stdout > dd in-depth due-diligence, \t e.g.: news, analyst, shorts, insider, sec > ba behavioural analysis, \t from: reddit, stocktwits, twitter, google @@ -275,10 +272,6 @@ Contexts: """Process view command""" view(other_args, self.ticker, self.start, self.interval, self.stock) - def call_export(self, other_args: List[str]): - """Process export command""" - export(other_args, self.stock) - def call_disc(self, _): """Process disc command""" return disc_controller.menu()