From a7e00f1761769d5bac7b3bd58227bf7928f325e5 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Wed, 14 Apr 2021 11:18:18 -0700 Subject: [PATCH 001/114] Refactor fa_controller --- .../fundamental_analysis/fa_controller.py | 316 ++++++++++++++++++ .../fundamental_analysis/fa_menu.py | 193 ----------- terminal.py | 6 +- 3 files changed, 319 insertions(+), 196 deletions(-) create mode 100644 gamestonk_terminal/fundamental_analysis/fa_controller.py delete mode 100644 gamestonk_terminal/fundamental_analysis/fa_menu.py diff --git a/gamestonk_terminal/fundamental_analysis/fa_controller.py b/gamestonk_terminal/fundamental_analysis/fa_controller.py new file mode 100644 index 00000000000..b1e6a852e0a --- /dev/null +++ b/gamestonk_terminal/fundamental_analysis/fa_controller.py @@ -0,0 +1,316 @@ +""" Fundamental Analysis Controller """ +__docformat__ = "numpy" + +import argparse +from typing import List +from prompt_toolkit.completion import NestedCompleter + +from gamestonk_terminal.fundamental_analysis import alpha_vantage_api as av_api +from gamestonk_terminal.fundamental_analysis import business_insider_api as bi_api +from gamestonk_terminal.fundamental_analysis import ( + financial_modeling_prep_api as fmp_api, +) +from gamestonk_terminal.fundamental_analysis import finviz_api as fvz_api +from gamestonk_terminal.fundamental_analysis import market_watch_api as mw_api +from gamestonk_terminal.fundamental_analysis import yahoo_finance_api as yf_api +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import b_is_stock_market_open, get_flair +from gamestonk_terminal.menu import session + + +class FundamentalAnalysisController: + """ Fundamental Analysis Controller """ + + # Command choices + CHOICES = [ + "help", + "q", + "quit", + "screener", + "income", + "balance", + "cash", + "mgmt", + "info", + "shrs", + "sust", + "cal", + "av", + "fmp", + ] + + def __init__(self, ticker: str, start: str, interval: str): + self.ticker = ticker + self.start = start + self.interval = interval + + self.fa_parser = argparse.ArgumentParser(add_help=False, prog="fa") + self.fa_parser.add_argument( + "cmd", + choices=self.CHOICES, + ) + + def print_help(self): + """ Print help """ + + intraday = (f"Intraday {self.interval}", "Daily")[self.interval == "1440min"] + + if self.start: + print( + f"\n{intraday} Stock: {self.ticker} (from {self.start.strftime('%Y-%m-%d')})" + ) + else: + print(f"\n{intraday} Stock: {self.ticker}") + + print( + "\nFundamental Analysis:" + ) # https://github.com/JerBouma/FundamentalAnalysis + print(" help show this fundamental analysis menu again") + print(" q quit this menu, and shows back to main menu") + print(" quit quit to abandon program") + print("") + print(" screener screen info about the company [Finviz]") + print(" mgmt management team of the company [Business Insider]") + print("") + print("Market Watch API") + print(" income income statement of the company") + print(" balance balance sheet of the company") + print(" cash cash flow statement of the company") + print("") + print("Yahoo Finance API") + print(" info information scope of the company") + print(" shrs shareholders of the company") + print(" sust sustainability values of the company") + print(" cal calendar earnings and estimates of the company") + print("") + print("Other Sources:") + print("> av Alpha Vantage MENU") + print("> fmp Financial Modeling Prep MENU") + print("") + + def switch(self, an_input: str): + """Process and dispatch input + + Returns + ------- + True, False or None + False - quit the menu + True - quit the program + None - continue in the menu + """ + (known_args, other_args) = self.fa_parser.parse_known_args(an_input.split()) + + return getattr( + self, "call_" + known_args.cmd, lambda: "Command not recognized!" + )(other_args) + + def call_help(self, _): + """Process Help command""" + self.print_help() + + def call_q(self, _): + """Process Q command - quit the menu""" + return False + + def call_quit(self, _): + """Process Quit command - quit the program""" + return True + + def call_mgmt(self, other_args: List[str]): + """ Process mgmt command """ + bi_api.management(other_args, self.ticker) + + def call_screener(self, other_args: List[str]): + """ Process screener command """ + fvz_api.screener(other_args, self.ticker) + + def call_income(self, other_args: List[str]): + """ Process income command """ + mw_api.income(other_args, self.ticker) + + def call_balance(self, other_args: List[str]): + """ Process balance command """ + mw_api.balance(other_args, self.ticker) + + def call_cash(self, other_args: List[str]): + """ Process cash command """ + mw_api.cash(other_args, self.ticker) + + def call_info(self, other_args: List[str]): + """ Process info command """ + yf_api.info(other_args, self.ticker) + + def call_shrs(self, other_args: List[str]): + """ Process shrs command """ + yf_api.shareholders(other_args, self.ticker) + + def call_sust(self, other_args: List[str]): + """ Process sust command """ + yf_api.sustainability(other_args, self.ticker) + + def call_cal(self, other_args: List[str]): + """ Process cal command """ + yf_api.calendar_earnings(other_args, self.ticker) + + def call_av(self, other_args: List[str]): + """ Process av command """ + ret = av_api.menu(self.ticker, self.start, self.interval) + + if ret is not True: + self.print_help() + + def call_fmp(self, other_args: List[str]): + """ Process fmp command """ + ret = fmp_api.menu(self.ticker, self.start, self.interval) + + if ret is not True: + self.print_help() + + +def key_metrics_explained(l_args): + parser = argparse.ArgumentParser( + add_help=False, + prog="info", + description=""" + Provides information about main key metrics. Namely: EBITDA, + EPS, P/E, PEG, FCF, P/B, ROE, DPR, P/S, Dividend Yield Ratio, D/E, and Beta. + """, + ) + + try: + (_, l_unknown_args) = parser.parse_known_args(l_args) + + if l_unknown_args: + print(f"The following args couldn't be interpreted: {l_unknown_args}") + + filepath = "fundamental_analysis/key_metrics_explained.txt" + with open(filepath) as fp: + line = fp.readline() + while line: + print(f"{line.strip()}") + line = fp.readline() + print("") + + except Exception as e: + print(e) + print("ERROR!\n") + return + + +# pylint: disable=too-many-branches +def menu(ticker: str, start: str, interval: str): + + fa_controller = FundamentalAnalysisController(ticker, start, interval) + fa_controller.call_help(None) + + while True: + # Get input command from user + if session and gtff.USE_PROMPT_TOOLKIT: + completer = NestedCompleter.from_nested_dict( + {c: None for c in fa_controller.CHOICES} + ) + + an_input = session.prompt( + f"{get_flair()} (fa)> ", + completer=completer, + ) + else: + an_input = input(f"{get_flair()} (fa)> ") + + try: + process_input = fa_controller.switch(an_input) + + if process_input is not None: + return process_input + + except SystemExit: + print("The command selected doesn't exist\n") + continue + + # should_print_help = True + + # # Loop forever and ever + # while True: + # if should_print_help: + # print_fundamental_analysis(s_ticker, s_start, s_interval) + # should_print_help = False + + # # Get input command from user + # if session and gtff.USE_PROMPT_TOOLKIT: + # as_input = session.prompt( + # f"{get_flair()} (fa)> ", + # completer=completer, + # ) + # else: + # as_input = input(f"{get_flair()} (fa)> ") + + # # Parse fundamental analysis command of the list of possible commands + # try: + # (ns_known_args, l_args) = fa_parser.parse_known_args(as_input.split()) + + # except SystemExit: + # print("The command selected doesn't exist\n") + # continue + + # if ns_known_args.cmd == "help": + # should_print_help = True + + # elif ns_known_args.cmd == "q": + # # Just leave the FA menu + # return False + + # elif ns_known_args.cmd == "quit": + # # Abandon the program + # return True + + # # BUSINESS INSIDER API + # elif ns_known_args.cmd == "mgmt": + # bi_api.management(l_args, s_ticker) + + # # FINVIZ API + # elif ns_known_args.cmd == "screener": + # fvz_api.screener(l_args, s_ticker) + + # # MARKET WATCH API + # elif ns_known_args.cmd == "income": + # mw_api.income(l_args, s_ticker) + + # elif ns_known_args.cmd == "balance": + # mw_api.balance(l_args, s_ticker) + + # elif ns_known_args.cmd == "cash": + # mw_api.cash(l_args, s_ticker) + + # # YAHOO FINANCE API + # elif ns_known_args.cmd == "info": + # yf_api.info(l_args, s_ticker) + + # elif ns_known_args.cmd == "shrs": + # yf_api.shareholders(l_args, s_ticker) + + # elif ns_known_args.cmd == "sust": + # yf_api.sustainability(l_args, s_ticker) + + # elif ns_known_args.cmd == "cal": + # yf_api.calendar_earnings(l_args, s_ticker) + + # # ALPHA VANTAGE API + # elif ns_known_args.cmd == "av": + # b_quit = av_api.menu(s_ticker, s_start, s_interval) + + # if b_quit: + # return True + # else: + # should_print_help = True + + # # FINANCIAL MODELING PREP API + # elif ns_known_args.cmd == "fmp": + # b_quit = fmp_api.menu(s_ticker, s_start, s_interval) + + # if b_quit: + # return True + # else: + # should_print_help = True + + # else: + # print("Command not recognized!") diff --git a/gamestonk_terminal/fundamental_analysis/fa_menu.py b/gamestonk_terminal/fundamental_analysis/fa_menu.py deleted file mode 100644 index 426fa418526..00000000000 --- a/gamestonk_terminal/fundamental_analysis/fa_menu.py +++ /dev/null @@ -1,193 +0,0 @@ -import argparse - -from gamestonk_terminal.fundamental_analysis import alpha_vantage_api as av_api -from gamestonk_terminal.fundamental_analysis import business_insider_api as bi_api -from gamestonk_terminal.fundamental_analysis import ( - financial_modeling_prep_api as fmp_api, -) -from gamestonk_terminal.fundamental_analysis import finviz_api as fvz_api -from gamestonk_terminal.fundamental_analysis import market_watch_api as mw_api -from gamestonk_terminal.fundamental_analysis import yahoo_finance_api as yf_api -from gamestonk_terminal import feature_flags as gtff -from gamestonk_terminal.helper_funcs import get_flair -from gamestonk_terminal.menu import session -from prompt_toolkit.completion import NestedCompleter - - -def print_fundamental_analysis(s_ticker, s_start, s_interval): - """ Print help """ - - s_intraday = (f"Intraday {s_interval}", "Daily")[s_interval == "1440min"] - - if s_start: - print(f"\n{s_intraday} Stock: {s_ticker} (from {s_start.strftime('%Y-%m-%d')})") - else: - print(f"\n{s_intraday} Stock: {s_ticker}") - - print("\nFundamental Analysis:") # https://github.com/JerBouma/FundamentalAnalysis - print(" help show this fundamental analysis menu again") - print(" q quit this menu, and shows back to main menu") - print(" quit quit to abandon program") - print("") - print(" screener screen info about the company [Finviz]") - print(" mgmt management team of the company [Business Insider]") - print("") - print("Market Watch API") - print(" income income statement of the company") - print(" balance balance sheet of the company") - print(" cash cash flow statement of the company") - print("") - print("Yahoo Finance API") - print(" info information scope of the company") - print(" shrs shareholders of the company") - print(" sust sustainability values of the company") - print(" cal calendar earnings and estimates of the company") - print("") - print("Other Sources:") - print("> av Alpha Vantage MENU") - print("> fmp Financial Modeling Prep MENU") - print("") - return - - -def key_metrics_explained(l_args): - parser = argparse.ArgumentParser( - add_help=False, - prog="info", - description=""" - Provides information about main key metrics. Namely: EBITDA, - EPS, P/E, PEG, FCF, P/B, ROE, DPR, P/S, Dividend Yield Ratio, D/E, and Beta. - """, - ) - - try: - (_, l_unknown_args) = parser.parse_known_args(l_args) - - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}") - - filepath = "fundamental_analysis/key_metrics_explained.txt" - with open(filepath) as fp: - line = fp.readline() - while line: - print(f"{line.strip()}") - line = fp.readline() - print("") - - except Exception as e: - print(e) - print("ERROR!\n") - return - - -# pylint: disable=too-many-branches -def fa_menu(s_ticker, s_start, s_interval): - - # Add list of arguments that the fundamental analysis parser accepts - fa_parser = argparse.ArgumentParser(prog="fa", add_help=False) - choices = [ - "help", - "q", - "quit", - "screener", - "income", - "balance", - "cash", - "mgmt", - "info", - "shrs", - "sust", - "cal", - "av", - "fmp", - ] - fa_parser.add_argument("cmd", choices=choices) - completer = NestedCompleter.from_nested_dict({c: None for c in choices}) - - should_print_help = True - - # Loop forever and ever - while True: - if should_print_help: - print_fundamental_analysis(s_ticker, s_start, s_interval) - should_print_help = False - - # Get input command from user - if session and gtff.USE_PROMPT_TOOLKIT: - as_input = session.prompt( - f"{get_flair()} (fa)> ", - completer=completer, - ) - else: - as_input = input(f"{get_flair()} (fa)> ") - - # Parse fundamental analysis command of the list of possible commands - try: - (ns_known_args, l_args) = fa_parser.parse_known_args(as_input.split()) - - except SystemExit: - print("The command selected doesn't exist\n") - continue - - if ns_known_args.cmd == "help": - should_print_help = True - - elif ns_known_args.cmd == "q": - # Just leave the FA menu - return False - - elif ns_known_args.cmd == "quit": - # Abandon the program - return True - - # BUSINESS INSIDER API - elif ns_known_args.cmd == "mgmt": - bi_api.management(l_args, s_ticker) - - # FINVIZ API - elif ns_known_args.cmd == "screener": - fvz_api.screener(l_args, s_ticker) - - # MARKET WATCH API - elif ns_known_args.cmd == "income": - mw_api.income(l_args, s_ticker) - - elif ns_known_args.cmd == "balance": - mw_api.balance(l_args, s_ticker) - - elif ns_known_args.cmd == "cash": - mw_api.cash(l_args, s_ticker) - - # YAHOO FINANCE API - elif ns_known_args.cmd == "info": - yf_api.info(l_args, s_ticker) - - elif ns_known_args.cmd == "shrs": - yf_api.shareholders(l_args, s_ticker) - - elif ns_known_args.cmd == "sust": - yf_api.sustainability(l_args, s_ticker) - - elif ns_known_args.cmd == "cal": - yf_api.calendar_earnings(l_args, s_ticker) - - # ALPHA VANTAGE API - elif ns_known_args.cmd == "av": - b_quit = av_api.menu(s_ticker, s_start, s_interval) - - if b_quit: - return True - else: - should_print_help = True - - # FINANCIAL MODELING PREP API - elif ns_known_args.cmd == "fmp": - b_quit = fmp_api.menu(s_ticker, s_start, s_interval) - - if b_quit: - return True - else: - should_print_help = True - - else: - print("Command not recognized!") diff --git a/terminal.py b/terminal.py index f2441ccbdab..42437fa9707 100644 --- a/terminal.py +++ b/terminal.py @@ -16,7 +16,7 @@ from gamestonk_terminal import thought_of_the_day as thought from gamestonk_terminal import res_menu as rm from gamestonk_terminal.discovery import disc_controller from gamestonk_terminal.due_diligence import dd_controller -from gamestonk_terminal.fundamental_analysis import fa_menu as fam +from gamestonk_terminal.fundamental_analysis import fa_controller from gamestonk_terminal.helper_funcs import b_is_stock_market_open, get_flair from gamestonk_terminal.main_helper import clear, export, load, print_help, view, candle from gamestonk_terminal.menu import session @@ -202,7 +202,7 @@ def main(): b_quit = ca_controller.menu(df_stock, s_ticker, s_start, s_interval) elif ns_known_args.opt == "fa": - b_quit = fam.fa_menu(s_ticker, s_start, s_interval) + b_quit = fa_controller.menu(s_ticker, s_start, s_interval) elif ns_known_args.opt == "ta": b_quit = ta_controller.menu(df_stock, s_ticker, s_start, s_interval) @@ -283,7 +283,7 @@ def main(): df_stock_pred = df_stock_pred.sort_index(ascending=True) df_stock_pred = df_stock_pred[s_start:] b_quit = pred_controller.menu( - df_stock_pred, s_ticker, s_start, s_interval="1440min" + df_stock_pred, s_ticker, s_start, interval="1440min" ) except Exception as e: print(e) From f5022fd099e1a854f8fa28dd6dd71cf126131b21 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Wed, 14 Apr 2021 11:24:25 -0700 Subject: [PATCH 002/114] Removing unused import --- gamestonk_terminal/fundamental_analysis/fa_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/fundamental_analysis/fa_controller.py b/gamestonk_terminal/fundamental_analysis/fa_controller.py index b1e6a852e0a..10f654e8178 100644 --- a/gamestonk_terminal/fundamental_analysis/fa_controller.py +++ b/gamestonk_terminal/fundamental_analysis/fa_controller.py @@ -14,7 +14,7 @@ from gamestonk_terminal.fundamental_analysis import finviz_api as fvz_api from gamestonk_terminal.fundamental_analysis import market_watch_api as mw_api from gamestonk_terminal.fundamental_analysis import yahoo_finance_api as yf_api from gamestonk_terminal import feature_flags as gtff -from gamestonk_terminal.helper_funcs import b_is_stock_market_open, get_flair +from gamestonk_terminal.helper_funcs import get_flair from gamestonk_terminal.menu import session From 0e4cdd6b69f82146a47b524a4653a4b6153a42a2 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Thu, 15 Apr 2021 09:10:41 -0700 Subject: [PATCH 003/114] Adding docstrings and removing unused comments --- .../fundamental_analysis/fa_controller.py | 119 +++++------------- 1 file changed, 28 insertions(+), 91 deletions(-) diff --git a/gamestonk_terminal/fundamental_analysis/fa_controller.py b/gamestonk_terminal/fundamental_analysis/fa_controller.py index 10f654e8178..9d323a55b87 100644 --- a/gamestonk_terminal/fundamental_analysis/fa_controller.py +++ b/gamestonk_terminal/fundamental_analysis/fa_controller.py @@ -40,6 +40,18 @@ class FundamentalAnalysisController: ] def __init__(self, ticker: str, start: str, interval: str): + """Constructor + + Parameters + ---------- + ticker : str + Fundamental analysis ticker symbol + start : str + Stat date of the stock data + interval : str + Stock data interval + """ + self.ticker = ticker self.start = start self.interval = interval @@ -98,6 +110,7 @@ class FundamentalAnalysisController: True - quit the program None - continue in the menu """ + (known_args, other_args) = self.fa_parser.parse_known_args(an_input.split()) return getattr( @@ -152,6 +165,7 @@ class FundamentalAnalysisController: """ Process cal command """ yf_api.calendar_earnings(other_args, self.ticker) + # pylint: disable=unused-argument def call_av(self, other_args: List[str]): """ Process av command """ ret = av_api.menu(self.ticker, self.start, self.interval) @@ -159,6 +173,7 @@ class FundamentalAnalysisController: if ret is not True: self.print_help() + # pylint: disable=unused-argument def call_fmp(self, other_args: List[str]): """ Process fmp command """ ret = fmp_api.menu(self.ticker, self.start, self.interval) @@ -167,7 +182,7 @@ class FundamentalAnalysisController: self.print_help() -def key_metrics_explained(l_args): +def key_metrics_explained(other_args: List[str]): parser = argparse.ArgumentParser( add_help=False, prog="info", @@ -178,7 +193,7 @@ def key_metrics_explained(l_args): ) try: - (_, l_unknown_args) = parser.parse_known_args(l_args) + (_, l_unknown_args) = parser.parse_known_args(other_args) if l_unknown_args: print(f"The following args couldn't be interpreted: {l_unknown_args}") @@ -197,8 +212,18 @@ def key_metrics_explained(l_args): return -# pylint: disable=too-many-branches def menu(ticker: str, start: str, interval: str): + """Fundamental Analysis menu + + Parameters + ---------- + ticker : str + Fundamental analysis ticker symbol + start : str + Start date of the stock data + interval : str + Stock data interval + """ fa_controller = FundamentalAnalysisController(ticker, start, interval) fa_controller.call_help(None) @@ -226,91 +251,3 @@ def menu(ticker: str, start: str, interval: str): except SystemExit: print("The command selected doesn't exist\n") continue - - # should_print_help = True - - # # Loop forever and ever - # while True: - # if should_print_help: - # print_fundamental_analysis(s_ticker, s_start, s_interval) - # should_print_help = False - - # # Get input command from user - # if session and gtff.USE_PROMPT_TOOLKIT: - # as_input = session.prompt( - # f"{get_flair()} (fa)> ", - # completer=completer, - # ) - # else: - # as_input = input(f"{get_flair()} (fa)> ") - - # # Parse fundamental analysis command of the list of possible commands - # try: - # (ns_known_args, l_args) = fa_parser.parse_known_args(as_input.split()) - - # except SystemExit: - # print("The command selected doesn't exist\n") - # continue - - # if ns_known_args.cmd == "help": - # should_print_help = True - - # elif ns_known_args.cmd == "q": - # # Just leave the FA menu - # return False - - # elif ns_known_args.cmd == "quit": - # # Abandon the program - # return True - - # # BUSINESS INSIDER API - # elif ns_known_args.cmd == "mgmt": - # bi_api.management(l_args, s_ticker) - - # # FINVIZ API - # elif ns_known_args.cmd == "screener": - # fvz_api.screener(l_args, s_ticker) - - # # MARKET WATCH API - # elif ns_known_args.cmd == "income": - # mw_api.income(l_args, s_ticker) - - # elif ns_known_args.cmd == "balance": - # mw_api.balance(l_args, s_ticker) - - # elif ns_known_args.cmd == "cash": - # mw_api.cash(l_args, s_ticker) - - # # YAHOO FINANCE API - # elif ns_known_args.cmd == "info": - # yf_api.info(l_args, s_ticker) - - # elif ns_known_args.cmd == "shrs": - # yf_api.shareholders(l_args, s_ticker) - - # elif ns_known_args.cmd == "sust": - # yf_api.sustainability(l_args, s_ticker) - - # elif ns_known_args.cmd == "cal": - # yf_api.calendar_earnings(l_args, s_ticker) - - # # ALPHA VANTAGE API - # elif ns_known_args.cmd == "av": - # b_quit = av_api.menu(s_ticker, s_start, s_interval) - - # if b_quit: - # return True - # else: - # should_print_help = True - - # # FINANCIAL MODELING PREP API - # elif ns_known_args.cmd == "fmp": - # b_quit = fmp_api.menu(s_ticker, s_start, s_interval) - - # if b_quit: - # return True - # else: - # should_print_help = True - - # else: - # print("Command not recognized!") From 1e103ff8c24819403803f3f7d0d08fabed332fb0 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Thu, 15 Apr 2021 10:12:38 -0700 Subject: [PATCH 004/114] Refactoring Alpha Vantage --- .../alpha_vantage_controller.py | 162 ++++++++++++++++++ ...a_vantage_api.py => alpha_vantage_view.py} | 144 +++------------- .../fundamental_analysis/fa_controller.py | 4 +- 3 files changed, 192 insertions(+), 118 deletions(-) create mode 100644 gamestonk_terminal/fundamental_analysis/alpha_vantage_controller.py rename gamestonk_terminal/fundamental_analysis/{alpha_vantage_api.py => alpha_vantage_view.py} (80%) mode change 100644 => 100755 diff --git a/gamestonk_terminal/fundamental_analysis/alpha_vantage_controller.py b/gamestonk_terminal/fundamental_analysis/alpha_vantage_controller.py new file mode 100644 index 00000000000..546527edb2b --- /dev/null +++ b/gamestonk_terminal/fundamental_analysis/alpha_vantage_controller.py @@ -0,0 +1,162 @@ +""" Alpha Vantage Controller """ +__docformat__ = "numpy" + +import argparse +from typing import List +from prompt_toolkit.completion import NestedCompleter + +from gamestonk_terminal.fundamental_analysis import alpha_vantage_view as avv +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import get_flair +from gamestonk_terminal.menu import session + + +class AlphaVantageController: + """ Alpha Vantage Controller """ + + # Command choices + CHOICES = [ + "help", + "q", + "quit", + "overview", + "income", + "balance", + "cash", + "earnings", + ] + + def __init__(self, ticker: str, start: str, interval: str): + """Constructor + + Parameters + ---------- + ticker : str + Fundamental analysis ticker symbol + start : str + Stat date of the stock data + interval : str + Stock data interval + """ + + self.ticker = ticker + self.start = start + self.interval = interval + self.av_parser = argparse.ArgumentParser(add_help=False, prog="av") + self.av_parser.add_argument( + "cmd", + choices=self.CHOICES, + ) + + def print_help(self): + """ Print help """ + + intraday = (f"Intraday {self.interval}", "Daily")[self.interval == "1440min"] + + if self.start: + print( + f"\n{intraday} Stock: {self.ticker} (from {self.start.strftime('%Y-%m-%d')})" + ) + else: + print(f"\n{intraday} Stock: {self.ticker}") + + print("\nAlpha Vantage:") + print(" help show this alpha vantage menu again") + print(" q quit this menu, and shows back to main menu") + print(" quit quit to abandon program") + print("") + print(" overview overview of the company") + print(" income income statements of the company") + print(" balance balance sheet of the company") + print(" cash cash flow of the company") + print(" earnings earnings dates and reported EPS") + print("") + + def switch(self, an_input: str): + """Process and dispatch input + + Returns + ------- + True, False or None + False - quit the menu + True - quit the program + None - continue in the menu + """ + (known_args, other_args) = self.av_parser.parse_known_args(an_input.split()) + + return getattr( + self, "call_" + known_args.cmd, lambda: "Command not recognized!" + )(other_args) + + def call_help(self, _): + """Process Help command""" + self.print_help() + + def call_q(self, _): + """Process Q command - quit the menu""" + return False + + def call_quit(self, _): + """Process Quit command - quit the program""" + return True + + def call_overview(self, other_args: List[str]): + """ Process overview command """ + avv.overview(other_args, self.ticker) + + def call_income(self, other_args: List[str]): + """ Process income command """ + avv.income_statement(other_args, self.ticker) + + def call_balance(self, other_args: List[str]): + """ Process balance command """ + avv.balance_sheet(other_args, self.ticker) + + def call_cash(self, other_args: List[str]): + """ Process cash command """ + avv.cash_flow(other_args, self.ticker) + + def call_earnings(self, other_args: List[str]): + """ Process earnings command """ + avv.earnings(other_args, self.ticker) + + +def menu(ticker: str, start: str, interval: str): + """Alpha Vantage menu + + Parameters + ---------- + ticker : str + Fundamental analysis ticker symbol + start : str + Start date of the stock data + interval : str + Stock data interval + """ + + av_controller = AlphaVantageController(ticker, start, interval) + av_controller.call_help(None) + + while True: + # Get input command from user + if session and gtff.USE_PROMPT_TOOLKIT: + completer = NestedCompleter.from_nested_dict( + {c: None for c in av_controller.CHOICES} + ) + + an_input = session.prompt( + f"{get_flair()} (fa)>(av)> ", + completer=completer, + ) + else: + an_input = input(f"{get_flair()} (fa)>(av)> ") + + try: + process_input = av_controller.switch(an_input) + + if process_input is not None: + return process_input + + except SystemExit: + print("The command selected doesn't exist\n") + continue diff --git a/gamestonk_terminal/fundamental_analysis/alpha_vantage_api.py b/gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py old mode 100644 new mode 100755 similarity index 80% rename from gamestonk_terminal/fundamental_analysis/alpha_vantage_api.py rename to gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py index 36c648b614c..8066938c18d --- a/gamestonk_terminal/fundamental_analysis/alpha_vantage_api.py +++ b/gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py @@ -1,112 +1,24 @@ +""" Alpha Vantage View """ +__docformat__ = "numpy" + import argparse +from typing import List import requests + from alpha_vantage.fundamentaldata import FundamentalData import pandas as pd from pandas.io.json import json_normalize + from gamestonk_terminal import config_terminal as cfg from gamestonk_terminal.dataframe_helpers import clean_df_index from gamestonk_terminal.helper_funcs import ( check_positive, long_number_format, parse_known_args_and_warn, - get_flair, ) -from gamestonk_terminal.menu import session -from prompt_toolkit.completion import NestedCompleter -def print_menu(s_ticker, s_start, s_interval): - """ Print help """ - - s_intraday = (f"Intraday {s_interval}", "Daily")[s_interval == "1440min"] - - if s_start: - print(f"\n{s_intraday} Stock: {s_ticker} (from {s_start.strftime('%Y-%m-%d')})") - else: - print(f"\n{s_intraday} Stock: {s_ticker}") - - print("\nAlpha Vantage:") - print(" help show this alpha vantage menu again") - print(" q quit this menu, and shows back to main menu") - print(" quit quit to abandon program") - print("") - print(" overview overview of the company") - print(" income income statements of the company") - print(" balance balance sheet of the company") - print(" cash cash flow of the company") - print(" earnings earnings dates and reported EPS") - print("") - - -def menu(s_ticker, s_start, s_interval): - - # Add list of arguments that the fundamental analysis parser accepts - av_parser = argparse.ArgumentParser(prog="av", add_help=False) - choices = [ - "help", - "q", - "quit", - "overview", - "income", - "balance", - "cash", - "earnings", - ] - av_parser.add_argument("cmd", choices=choices) - completer = NestedCompleter.from_nested_dict({c: None for c in choices}) - - print_menu(s_ticker, s_start, s_interval) - - # Loop forever and ever - while True: - # Get input command from user - if session: - as_input = session.prompt( - f"{get_flair()} (fa)>(av)> ", - completer=completer, - ) - else: - as_input = input(f"{get_flair()} (fa)>(av)> ") - - # Parse alpha vantage command of the list of possible commands - try: - (ns_known_args, l_args) = av_parser.parse_known_args(as_input.split()) - - except SystemExit: - print("The command selected doesn't exist\n") - continue - - if ns_known_args.cmd == "help": - print_menu(s_ticker, s_start, s_interval) - - elif ns_known_args.cmd == "q": - # Just leave the menu - return False - - elif ns_known_args.cmd == "quit": - # Abandon the program - return True - - elif ns_known_args.cmd == "overview": - overview(l_args, s_ticker) - - elif ns_known_args.cmd == "income": - income_statement(l_args, s_ticker) - - elif ns_known_args.cmd == "balance": - balance_sheet(l_args, s_ticker) - - elif ns_known_args.cmd == "cash": - cash_flow(l_args, s_ticker) - - elif ns_known_args.cmd == "earnings": - earnings(l_args, s_ticker) - - else: - print("Command not recognized!") - - -def overview(l_args, s_ticker): +def overview(other_args: List[str], ticker: str): parser = argparse.ArgumentParser( add_help=False, prog="overview", @@ -128,12 +40,12 @@ def overview(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return # Request OVERVIEW data from Alpha Vantage API - s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" + s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" result = requests.get(s_req, stream=True) # If the returned data was successful @@ -182,7 +94,7 @@ def overview(l_args, s_ticker): return -def key(l_args, s_ticker): +def key(other_args: List[str], ticker: str): parser = argparse.ArgumentParser( add_help=False, prog="key", @@ -196,12 +108,12 @@ def key(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return # Request OVERVIEW data - s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" + s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" result = requests.get(s_req, stream=True) # If the returned data was successful @@ -248,10 +160,10 @@ def key(l_args, s_ticker): return -def income_statement(l_args, s_ticker): +def income_statement(other_args: List[str], ticker: str): parser = argparse.ArgumentParser( add_help=False, - prog="incom", + prog="income", description=""" Prints a complete income statement over time. This can be either quarterly or annually. The following fields are expected: Accepted date, Cost and expenses, Cost of revenue, @@ -283,7 +195,7 @@ def income_statement(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -295,10 +207,10 @@ def income_statement(l_args, s_ticker): fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") if ns_parser.b_quarter: # pylint: disable=unbalanced-tuple-unpacking - df_fa, _ = fd.get_income_statement_quarterly(symbol=s_ticker) + df_fa, _ = fd.get_income_statement_quarterly(symbol=ticker) else: # pylint: disable=unbalanced-tuple-unpacking - df_fa, _ = fd.get_income_statement_annual(symbol=s_ticker) + df_fa, _ = fd.get_income_statement_annual(symbol=ticker) df_fa = clean_fundamentals_df(df_fa, num=ns_parser.n_num) print(df_fa) @@ -310,7 +222,7 @@ def income_statement(l_args, s_ticker): return -def balance_sheet(l_args, s_ticker): +def balance_sheet(other_args: List[str], ticker: str): parser = argparse.ArgumentParser( add_help=False, prog="balance", @@ -351,7 +263,7 @@ def balance_sheet(l_args, s_ticker): ) try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (ns_parser, l_unknown_args) = parser.parse_known_args(other_args) if l_unknown_args: print(f"The following args couldn't be interpreted: {l_unknown_args}\n") @@ -365,10 +277,10 @@ def balance_sheet(l_args, s_ticker): fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") if ns_parser.b_quarter: # pylint: disable=unbalanced-tuple-unpacking - df_fa, _ = fd.get_balance_sheet_quarterly(symbol=s_ticker) + df_fa, _ = fd.get_balance_sheet_quarterly(symbol=ticker) else: # pylint: disable=unbalanced-tuple-unpacking - df_fa, _ = fd.get_balance_sheet_annual(symbol=s_ticker) + df_fa, _ = fd.get_balance_sheet_annual(symbol=ticker) df_fa = clean_fundamentals_df(df_fa, num=ns_parser.n_num) print(df_fa) @@ -380,7 +292,7 @@ def balance_sheet(l_args, s_ticker): return -def cash_flow(l_args, s_ticker): +def cash_flow(other_args: List[str], ticker: str): parser = argparse.ArgumentParser( add_help=False, prog="cash", @@ -419,7 +331,7 @@ def cash_flow(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -431,10 +343,10 @@ def cash_flow(l_args, s_ticker): fd = FundamentalData(key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas") if ns_parser.b_quarter: # pylint: disable=unbalanced-tuple-unpacking - df_fa, _ = fd.get_cash_flow_quarterly(symbol=s_ticker) + df_fa, _ = fd.get_cash_flow_quarterly(symbol=ticker) else: # pylint: disable=unbalanced-tuple-unpacking - df_fa, _ = fd.get_cash_flow_annual(symbol=s_ticker) + df_fa, _ = fd.get_cash_flow_annual(symbol=ticker) df_fa = clean_fundamentals_df(df_fa, num=ns_parser.n_num) print(df_fa) @@ -446,7 +358,7 @@ def cash_flow(l_args, s_ticker): return -def earnings(l_args, s_ticker): +def earnings(other_args: List[str], ticker: str): parser = argparse.ArgumentParser( add_help=False, prog="earnings", @@ -475,7 +387,7 @@ def earnings(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -487,7 +399,7 @@ def earnings(l_args, s_ticker): # Request EARNINGS data from Alpha Vantage API s_req = ( "https://www.alphavantage.co/query?function=EARNINGS&" - f"symbol={s_ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" + f"symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" ) result = requests.get(s_req, stream=True) diff --git a/gamestonk_terminal/fundamental_analysis/fa_controller.py b/gamestonk_terminal/fundamental_analysis/fa_controller.py index 9d323a55b87..4e00181b6ab 100644 --- a/gamestonk_terminal/fundamental_analysis/fa_controller.py +++ b/gamestonk_terminal/fundamental_analysis/fa_controller.py @@ -5,7 +5,7 @@ import argparse from typing import List from prompt_toolkit.completion import NestedCompleter -from gamestonk_terminal.fundamental_analysis import alpha_vantage_api as av_api +from gamestonk_terminal.fundamental_analysis import alpha_vantage_controller as avc from gamestonk_terminal.fundamental_analysis import business_insider_api as bi_api from gamestonk_terminal.fundamental_analysis import ( financial_modeling_prep_api as fmp_api, @@ -168,7 +168,7 @@ class FundamentalAnalysisController: # pylint: disable=unused-argument def call_av(self, other_args: List[str]): """ Process av command """ - ret = av_api.menu(self.ticker, self.start, self.interval) + ret = avc.menu(self.ticker, self.start, self.interval) if ret is not True: self.print_help() From 22740d95442dbaefbd7fbc3ac971c02b79532dc1 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Thu, 15 Apr 2021 10:13:15 -0700 Subject: [PATCH 005/114] File permissions --- gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py diff --git a/gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py b/gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py old mode 100755 new mode 100644 From e674d7dae057a920dcb8881d90374bb339005f08 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Thu, 15 Apr 2021 10:28:41 -0700 Subject: [PATCH 006/114] Adding docstrings --- .../alpha_vantage_controller.py | 6 ++ .../alpha_vantage_view.py | 67 +++++++++++++++++-- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/gamestonk_terminal/fundamental_analysis/alpha_vantage_controller.py b/gamestonk_terminal/fundamental_analysis/alpha_vantage_controller.py index 546527edb2b..01d029a569c 100644 --- a/gamestonk_terminal/fundamental_analysis/alpha_vantage_controller.py +++ b/gamestonk_terminal/fundamental_analysis/alpha_vantage_controller.py @@ -20,6 +20,7 @@ class AlphaVantageController: "q", "quit", "overview", + "key", "income", "balance", "cash", @@ -66,6 +67,7 @@ class AlphaVantageController: print(" quit quit to abandon program") print("") print(" overview overview of the company") + print(" key company key metrics") print(" income income statements of the company") print(" balance balance sheet of the company") print(" cash cash flow of the company") @@ -104,6 +106,10 @@ class AlphaVantageController: """ Process overview command """ avv.overview(other_args, self.ticker) + def call_key(self, other_args: List[str]): + """ Process overview command """ + avv.key(other_args, self.ticker) + def call_income(self, other_args: List[str]): """ Process income command """ avv.income_statement(other_args, self.ticker) diff --git a/gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py b/gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py index 8066938c18d..2adb4f8d177 100644 --- a/gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py +++ b/gamestonk_terminal/fundamental_analysis/alpha_vantage_view.py @@ -7,7 +7,6 @@ import requests from alpha_vantage.fundamentaldata import FundamentalData import pandas as pd -from pandas.io.json import json_normalize from gamestonk_terminal import config_terminal as cfg from gamestonk_terminal.dataframe_helpers import clean_df_index @@ -19,6 +18,16 @@ from gamestonk_terminal.helper_funcs import ( def overview(other_args: List[str], ticker: str): + """Alpha Vantage stock ticker overview + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="overview", @@ -51,7 +60,7 @@ def overview(other_args: List[str], ticker: str): # If the returned data was successful if result.status_code == 200: # Parse json data to dataframe - df_fa = json_normalize(result.json()) + df_fa = pd.json_normalize(result.json()) # Keep json data sorting in dataframe df_fa = df_fa[list(result.json().keys())].T df_fa = df_fa.applymap(lambda x: long_number_format(x)) @@ -95,6 +104,16 @@ def overview(other_args: List[str], ticker: str): def key(other_args: List[str], ticker: str): + """Alpha Vantage key metrics + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="key", @@ -118,7 +137,7 @@ def key(other_args: List[str], ticker: str): # If the returned data was successful if result.status_code == 200: - df_fa = json_normalize(result.json()) + df_fa = pd.json_normalize(result.json()) df_fa = df_fa[list(result.json().keys())].T df_fa = df_fa.applymap(lambda x: long_number_format(x)) clean_df_index(df_fa) @@ -161,6 +180,16 @@ def key(other_args: List[str], ticker: str): def income_statement(other_args: List[str], ticker: str): + """Alpha Vantage income statement + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="income", @@ -223,6 +252,16 @@ def income_statement(other_args: List[str], ticker: str): def balance_sheet(other_args: List[str], ticker: str): + """Alpha Vantage balance sheet + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="balance", @@ -293,6 +332,16 @@ def balance_sheet(other_args: List[str], ticker: str): def cash_flow(other_args: List[str], ticker: str): + """Alpha Vantage cash flow + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="cash", @@ -359,6 +408,16 @@ def cash_flow(other_args: List[str], ticker: str): def earnings(other_args: List[str], ticker: str): + """Alpha Vantage earnings + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="earnings", @@ -405,7 +464,7 @@ def earnings(other_args: List[str], ticker: str): # If the returned data was successful if result.status_code == 200: - df_fa = json_normalize(result.json()) + df_fa = pd.json_normalize(result.json()) if ns_parser.b_quarter: df_fa = pd.DataFrame(df_fa["quarterlyEarnings"][0]) df_fa = df_fa[ From 753175e25b1c134c30679f9cc9030a5dfc14fae3 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Thu, 15 Apr 2021 10:47:01 -0700 Subject: [PATCH 007/114] Refactoring business insider --- ...nsider_api.py => business_insider_view.py} | 24 +++++++++++++++---- .../fundamental_analysis/fa_controller.py | 4 ++-- ...pi.py => test_fa_business_insider_view.py} | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) rename gamestonk_terminal/fundamental_analysis/{business_insider_api.py => business_insider_view.py} (86%) rename tests/{test_fa_business_insider_api.py => test_fa_business_insider_view.py} (69%) diff --git a/gamestonk_terminal/fundamental_analysis/business_insider_api.py b/gamestonk_terminal/fundamental_analysis/business_insider_view.py similarity index 86% rename from gamestonk_terminal/fundamental_analysis/business_insider_api.py rename to gamestonk_terminal/fundamental_analysis/business_insider_view.py index 4811c2585be..bb0d4db3d6c 100644 --- a/gamestonk_terminal/fundamental_analysis/business_insider_api.py +++ b/gamestonk_terminal/fundamental_analysis/business_insider_view.py @@ -1,4 +1,8 @@ +""" Business Insider View """ +__docformat__ = "numpy" + import argparse +from typing import List import requests from bs4 import BeautifulSoup import pandas as pd @@ -6,7 +10,17 @@ from rapidfuzz import fuzz from gamestonk_terminal.helper_funcs import get_user_agent, parse_known_args_and_warn -def management(l_args, s_ticker): +def management(other_args: List[str], ticker: str): + """Display company's managers + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Stock ticker + """ + parser = argparse.ArgumentParser( add_help=False, prog="mgmt", @@ -17,12 +31,12 @@ def management(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return url_market_business_insider = ( - f"https://markets.businessinsider.com/stocks/{s_ticker.lower()}-stock" + f"https://markets.businessinsider.com/stocks/{ticker.lower()}-stock" ) text_soup_market_business_insider = BeautifulSoup( requests.get( @@ -42,7 +56,7 @@ def management(l_args, s_ticker): found_h2s[next_h2.text] = next_table if found_h2s.get("Management") is None: - print(f"No management information in Business Insider for {s_ticker}") + print(f"No management information in Business Insider for {ticker}") print("") return @@ -73,7 +87,7 @@ def management(l_args, s_ticker): for s_name in df_management.index: df_management.loc[s_name][ "Info" - ] = f"http://www.google.com/search?q={s_name} {s_ticker.upper()}".replace( + ] = f"http://www.google.com/search?q={s_name} {ticker.upper()}".replace( " ", "%20" ) diff --git a/gamestonk_terminal/fundamental_analysis/fa_controller.py b/gamestonk_terminal/fundamental_analysis/fa_controller.py index 4e00181b6ab..c077295bedc 100644 --- a/gamestonk_terminal/fundamental_analysis/fa_controller.py +++ b/gamestonk_terminal/fundamental_analysis/fa_controller.py @@ -6,7 +6,7 @@ from typing import List from prompt_toolkit.completion import NestedCompleter from gamestonk_terminal.fundamental_analysis import alpha_vantage_controller as avc -from gamestonk_terminal.fundamental_analysis import business_insider_api as bi_api +from gamestonk_terminal.fundamental_analysis import business_insider_view as biw from gamestonk_terminal.fundamental_analysis import ( financial_modeling_prep_api as fmp_api, ) @@ -131,7 +131,7 @@ class FundamentalAnalysisController: def call_mgmt(self, other_args: List[str]): """ Process mgmt command """ - bi_api.management(other_args, self.ticker) + biw.management(other_args, self.ticker) def call_screener(self, other_args: List[str]): """ Process screener command """ diff --git a/tests/test_fa_business_insider_api.py b/tests/test_fa_business_insider_view.py similarity index 69% rename from tests/test_fa_business_insider_api.py rename to tests/test_fa_business_insider_view.py index 35d7c23205c..b9d35af0af9 100644 --- a/tests/test_fa_business_insider_api.py +++ b/tests/test_fa_business_insider_view.py @@ -1,7 +1,7 @@ """ fundamental_analysis/business_insider_api.py tests """ import unittest -from gamestonk_terminal.fundamental_analysis.business_insider_api import management +from gamestonk_terminal.fundamental_analysis.business_insider_view import management class TestFaBusinessInsiderApi(unittest.TestCase): From cbe09d177ef23a289353c7f8595638e8db9b4f8d Mon Sep 17 00:00:00 2001 From: Jamie Perkins Date: Fri, 16 Apr 2021 16:44:07 -0700 Subject: [PATCH 008/114] enter api keys in .env file --- gamestonk_terminal/config_terminal.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gamestonk_terminal/config_terminal.py b/gamestonk_terminal/config_terminal.py index 4189a27ce4e..43e53e39409 100644 --- a/gamestonk_terminal/config_terminal.py +++ b/gamestonk_terminal/config_terminal.py @@ -1,4 +1,7 @@ import os +from dotenv import load_dotenv + +load_dotenv() # https://www.alphavantage.co API_KEY_ALPHAVANTAGE = os.getenv("GT_API_KEY_ALPHAVANTAGE") or "REPLACE_ME" From 57d290ccbb3fe78c4916ef31ee9e5efb71238c86 Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 18 Apr 2021 02:06:19 +0100 Subject: [PATCH 009/114] Add dark pools (ATS) vs Non-ATS data over time --- .../due_diligence/dd_controller.py | 7 + .../due_diligence/finra_view.py | 272 ++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 gamestonk_terminal/due_diligence/finra_view.py diff --git a/gamestonk_terminal/due_diligence/dd_controller.py b/gamestonk_terminal/due_diligence/dd_controller.py index 14ecab8fc40..1324cf79cd1 100644 --- a/gamestonk_terminal/due_diligence/dd_controller.py +++ b/gamestonk_terminal/due_diligence/dd_controller.py @@ -13,6 +13,7 @@ from gamestonk_terminal.due_diligence import market_watch_view as mw_view from gamestonk_terminal.due_diligence import quandl_view as q_view from gamestonk_terminal.due_diligence import reddit_view as r_view from gamestonk_terminal.due_diligence import news_view +from gamestonk_terminal.due_diligence import finra_view from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import get_flair from gamestonk_terminal.menu import session @@ -37,6 +38,7 @@ class DueDiligenceController: "analyst", "warnings", "sec", + "dp", ] def __init__(self, stock: DataFrame, ticker: str, start: str, interval: str): @@ -97,6 +99,7 @@ class DueDiligenceController: print( " warnings company warnings according to Sean Seah book [Market Watch]" ) + print(" dp dark pools vs OTC data [FINRA]") print("") def switch(self, an_input: str): @@ -175,6 +178,10 @@ class DueDiligenceController: """ Process short command """ q_view.short_interest(other_args, self.ticker, self.start) + def call_dp(self, other_args: List[str]): + """ Process dp command """ + finra_view.dark_pool(other_args, self.ticker) + def menu(stock: DataFrame, ticker: str, start: str, interval: str): """Due Diligence Menu diff --git a/gamestonk_terminal/due_diligence/finra_view.py b/gamestonk_terminal/due_diligence/finra_view.py new file mode 100644 index 00000000000..13767897840 --- /dev/null +++ b/gamestonk_terminal/due_diligence/finra_view.py @@ -0,0 +1,272 @@ +""" FINRA View """ +__docformat__ = "numpy" + +import argparse +from typing import List +import requests +import pandas as pd +from matplotlib import pyplot as plt +import matplotlib.dates as mdates +from gamestonk_terminal.config_plot import PLOT_DPI +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import parse_known_args_and_warn, plot_autoscale + + +def getFINRAweeks(tier, is_ats) -> List: + """Get FINRA weeks + + Parameters + ---------- + tier : str + Stock tier between T1, T2, or OTCE + is_ats : bool + ATS data if true, NON-ATS otherwise + + Returns + ---------- + List + List of response data + """ + req_hdr = {"Accept": "application/json", "Content-Type": "application/json"} + + req_data = { + "compareFilters": [ + { + "compareType": "EQUAL", + "fieldName": "summaryTypeCode", + "fieldValue": "ATS_W_SMBL" if is_ats else "OTC_W_SMBL", + }, + { + "compareType": "EQUAL", + "fieldName": "tierIdentifier", + "fieldValue": tier, + }, + ], + "delimiter": "|", + "fields": ["weekStartDate"], + "limit": 27, + "quoteValues": False, + "sortFields": ["-weekStartDate"], + } + + response = requests.post( + "https://api.finra.org/data/group/otcMarket/name/weeklyDownloadDetails", + headers=req_hdr, + json=req_data, + ) + + return response.json() if response.status_code == 200 else list() + + +def getFINRAdata(weekStartDate, tier, ticker, is_ats) -> List: + """Get FINRA data + + Parameters + ---------- + weekStartDate : str + Weekly data to get FINRA data + tier : str + Stock tier between T1, T2, or OTCE + ticker : str + Stock ticker to get data from + is_ats : bool + ATS data if true, NON-ATS otherwise + + Returns + ---------- + str + Status code from request + List + List of response data + """ + req_hdr = {"Accept": "application/json", "Content-Type": "application/json"} + + l_cmp_filters = [ + { + "compareType": "EQUAL", + "fieldName": "weekStartDate", + "fieldValue": weekStartDate, + }, + {"compareType": "EQUAL", "fieldName": "tierIdentifier", "fieldValue": tier}, + { + "compareType": "EQUAL", + "description": "", + "fieldName": "summaryTypeCode", + "fieldValue": "ATS_W_SMBL" if is_ats else "OTC_W_SMBL", + }, + ] + + if ticker: + l_cmp_filters.append( + { + "compareType": "EQUAL", + "fieldName": "issueSymbolIdentifier", + "fieldValue": ticker, + } + ) + + req_data = { + "compareFilters": l_cmp_filters, + "delimiter": "|", + "fields": [ + "issueSymbolIdentifier", + "totalWeeklyShareQuantity", + "totalWeeklyTradeCount", + "lastUpdateDate", + ], + "limit": 5000, + "quoteValues": False, + "sortFields": ["totalWeeklyShareQuantity"], + } + + response = requests.post( + "https://api.finra.org/data/group/otcMarket/name/weeklySummary", + headers=req_hdr, + json=req_data, + ) + + return ( + response.status_code, + response.json() if response.status_code == 200 else list(), + ) + + +def getTickerFINRAdata(ticker): + """Get all FINRA data associated with a ticker + + Parameters + ---------- + ticker : str + Stock ticker to get data from + + Returns + ---------- + pd.DataFrame + Dark Pools (ATS) Data + pd.DataFrame + OTC (Non-ATS) Data + """ + tiers = ["T1", "T2", "OTCE"] + + l_data = list() + for tier in tiers: + for d_week in getFINRAweeks(tier, is_ats=True): + status_code, response = getFINRAdata( + d_week["weekStartDate"], tier, ticker, True + ) + if status_code == 200: + if response: + d_data = response[0] + d_data.update(d_week) + l_data.append(d_data) + else: + break + + df_ats = pd.DataFrame(l_data) + df_ats = df_ats.sort_values("weekStartDate") + df_ats = df_ats.set_index("weekStartDate") + + l_data = list() + for tier in tiers: + for d_week in getFINRAweeks(tier, is_ats=False): + status_code, response = getFINRAdata( + d_week["weekStartDate"], tier, ticker, False + ) + if status_code == 200: + if response: + d_data = response[0] + d_data.update(d_week) + l_data.append(d_data) + else: + break + + df_otc = pd.DataFrame(l_data) + df_otc = df_otc.sort_values("weekStartDate") + df_otc = df_otc.set_index("weekStartDate") + + return df_ats, df_otc + + +def plot_dark_pools(ticker: str, ats: pd.DataFrame, otc: pd.DataFrame): + """Plots ATS and NON-ATS data + + Parameters + ---------- + ticker : str + Stock ticker to get data from + ats : pd.DataFrame + Dark Pools (ATS) Data + otc : pd.DataFrame + OTC (Non-ATS) Data + """ + _, axData = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + + plt.subplot(3, 1, (1, 2)) + plt.bar( + ats.index, + (ats["totalWeeklyShareQuantity"] + otc["totalWeeklyShareQuantity"]) / 1_000_000, + color="tab:orange", + ) + plt.bar(otc.index, otc["totalWeeklyShareQuantity"] / 1_000_000, color="tab:blue") + plt.ylabel("Total Weekly Shares [Million]") + plt.legend(["ATS", "OTC"]) + plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2) + plt.title(f"Dark Pools (ATS) vs OTC (Non-ATS) Data for {ticker}") + + # _ = axData.twinx() + plt.subplot(313) + plt.plot( + ats.index, + ats["totalWeeklyShareQuantity"] / ats["totalWeeklyTradeCount"], + color="tab:orange", + ) + plt.plot( + otc.index, + otc["totalWeeklyShareQuantity"] / otc["totalWeeklyTradeCount"], + color="tab:blue", + ) + plt.ylabel("Shares per Trade") + plt.legend(["ATS", "OTC"]) + plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2) + plt.gcf().autofmt_xdate() + plt.xlabel("Weeks") + + if gtff.USE_ION: + plt.ion() + + plt.show() + + +def dark_pool(other_args: List[str], ticker: str): + """Display barchart of dark pool (ATS) and OTC (Non ATS) data + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Stock ticker + """ + parser = argparse.ArgumentParser( + add_help=False, + prog="dp", + description="Display barchart of dark pool (ATS) and OTC (Non ATS) data [Source: FINRA]", + ) + + if 1: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + df_ats, df_otc = getTickerFINRAdata(ticker) + + plot_dark_pools(ticker, df_ats, df_otc) + + print("") + + """ + except Exception as e: + print(e) + print("") + return + """ From 0032e12abc99486538ab9e8c8cdb2852eb203bad Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 18 Apr 2021 02:08:54 +0100 Subject: [PATCH 010/114] Update README.md --- gamestonk_terminal/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index 192f21ca288..eb3dfae535b 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -213,6 +213,7 @@ Command|Description|Source `sec` |SEC filings |[MarketWatch](https://www.marketwatch.com/) `short` |short interest |[Quandl](https://www.quandl.com/) `warnings` |company warnings according to Sean Seah book |[MarketWatch](https://www.marketwatch.com/) +`dp` |dark pools (ATS) vs OTC data [FINRA](https://www.finra.org/#/)   From e04e4053c0ebdba9eff7e5065808d0874767bb6c Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 18 Apr 2021 02:09:58 +0100 Subject: [PATCH 011/114] remove unused import --- gamestonk_terminal/due_diligence/finra_view.py | 1 - 1 file changed, 1 deletion(-) diff --git a/gamestonk_terminal/due_diligence/finra_view.py b/gamestonk_terminal/due_diligence/finra_view.py index 13767897840..a3358a71a5b 100644 --- a/gamestonk_terminal/due_diligence/finra_view.py +++ b/gamestonk_terminal/due_diligence/finra_view.py @@ -6,7 +6,6 @@ from typing import List import requests import pandas as pd from matplotlib import pyplot as plt -import matplotlib.dates as mdates from gamestonk_terminal.config_plot import PLOT_DPI from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import parse_known_args_and_warn, plot_autoscale From 477751915c448841bac6c1849f8153bcf0676b7f Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 18 Apr 2021 02:12:19 +0100 Subject: [PATCH 012/114] Update README.md --- gamestonk_terminal/due_diligence/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/gamestonk_terminal/due_diligence/README.md b/gamestonk_terminal/due_diligence/README.md index 70bfb49340b..472867b0f7e 100644 --- a/gamestonk_terminal/due_diligence/README.md +++ b/gamestonk_terminal/due_diligence/README.md @@ -24,6 +24,8 @@ This menu aims to help in due-diligence of a pre-loaded stock, and the usage of * short interest [Quandl] * [warnings](#warnings) * company warnings according to Sean Seah book [Market Watch] +* [dp](#dp) + * dark pools (ATS) vs OTC data [FINRA] ## news @@ -157,3 +159,15 @@ Sean Seah warnings. Check: Consistent historical earnings per share; Consistentl * -d : print insights into warnings calculation. Default False. warnings + +## dp + +```text +usage: dp +``` + +Display barchart of dark pool (ATS) and OTC (Non ATS) data + +![dp](https://user-images.githubusercontent.com/25267873/115130908-7987b580-9feb-11eb-8bca-1999174178d0.png) + + From 73681c2d75eff6dfb6fc88599849914eb9d6184f Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 18 Apr 2021 02:35:30 +0100 Subject: [PATCH 013/114] Improve code of dd/dp --- .../due_diligence/dd_controller.py | 2 +- .../due_diligence/finra_view.py | 88 +++++++++++++------ 2 files changed, 63 insertions(+), 27 deletions(-) diff --git a/gamestonk_terminal/due_diligence/dd_controller.py b/gamestonk_terminal/due_diligence/dd_controller.py index 1324cf79cd1..378499f05cd 100644 --- a/gamestonk_terminal/due_diligence/dd_controller.py +++ b/gamestonk_terminal/due_diligence/dd_controller.py @@ -99,7 +99,7 @@ class DueDiligenceController: print( " warnings company warnings according to Sean Seah book [Market Watch]" ) - print(" dp dark pools vs OTC data [FINRA]") + print(" dp dark pools (ATS) vs OTC data [FINRA]") print("") def switch(self, an_input: str): diff --git a/gamestonk_terminal/due_diligence/finra_view.py b/gamestonk_terminal/due_diligence/finra_view.py index a3358a71a5b..ea3e80bfa71 100644 --- a/gamestonk_terminal/due_diligence/finra_view.py +++ b/gamestonk_terminal/due_diligence/finra_view.py @@ -2,7 +2,7 @@ __docformat__ = "numpy" import argparse -from typing import List +from typing import List, Any import requests import pandas as pd from matplotlib import pyplot as plt @@ -57,7 +57,7 @@ def getFINRAweeks(tier, is_ats) -> List: return response.json() if response.status_code == 200 else list() -def getFINRAdata(weekStartDate, tier, ticker, is_ats) -> List: +def getFINRAdata(weekStartDate, tier, ticker, is_ats) -> [int, List]: """Get FINRA data Parameters @@ -130,7 +130,7 @@ def getFINRAdata(weekStartDate, tier, ticker, is_ats) -> List: ) -def getTickerFINRAdata(ticker): +def getTickerFINRAdata(ticker) -> [pd.DataFrame, pd.DataFrame]: """Get all FINRA data associated with a ticker Parameters @@ -162,8 +162,9 @@ def getTickerFINRAdata(ticker): break df_ats = pd.DataFrame(l_data) - df_ats = df_ats.sort_values("weekStartDate") - df_ats = df_ats.set_index("weekStartDate") + if not df_ats.empty: + df_ats = df_ats.sort_values("weekStartDate") + df_ats = df_ats.set_index("weekStartDate") l_data = list() for tier in tiers: @@ -180,8 +181,9 @@ def getTickerFINRAdata(ticker): break df_otc = pd.DataFrame(l_data) - df_otc = df_otc.sort_values("weekStartDate") - df_otc = df_otc.set_index("weekStartDate") + if not df_otc.empty: + df_otc = df_otc.sort_values("weekStartDate") + df_otc = df_otc.set_index("weekStartDate") return df_ats, df_otc @@ -201,31 +203,62 @@ def plot_dark_pools(ticker: str, ats: pd.DataFrame, otc: pd.DataFrame): _, axData = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) plt.subplot(3, 1, (1, 2)) - plt.bar( - ats.index, - (ats["totalWeeklyShareQuantity"] + otc["totalWeeklyShareQuantity"]) / 1_000_000, - color="tab:orange", - ) - plt.bar(otc.index, otc["totalWeeklyShareQuantity"] / 1_000_000, color="tab:blue") + if not ats.empty and not otc.empty: + plt.bar( + ats.index, + (ats["totalWeeklyShareQuantity"] + otc["totalWeeklyShareQuantity"]) + / 1_000_000, + color="tab:orange", + ) + plt.bar( + otc.index, otc["totalWeeklyShareQuantity"] / 1_000_000, color="tab:blue" + ) + plt.legend(["ATS", "OTC"]) + + elif not ats.empty: + plt.bar( + ats.index, + ats["totalWeeklyShareQuantity"] / 1_000_000, + color="tab:orange", + ) + plt.legend(["ATS"]) + + elif not otc.empty: + plt.bar( + otc.index, otc["totalWeeklyShareQuantity"] / 1_000_000, color="tab:blue" + ) + plt.legend(["OTC"]) + plt.ylabel("Total Weekly Shares [Million]") - plt.legend(["ATS", "OTC"]) plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2) plt.title(f"Dark Pools (ATS) vs OTC (Non-ATS) Data for {ticker}") - # _ = axData.twinx() plt.subplot(313) - plt.plot( - ats.index, - ats["totalWeeklyShareQuantity"] / ats["totalWeeklyTradeCount"], - color="tab:orange", - ) - plt.plot( - otc.index, - otc["totalWeeklyShareQuantity"] / otc["totalWeeklyTradeCount"], - color="tab:blue", - ) + if not ats.empty: + plt.plot( + ats.index, + ats["totalWeeklyShareQuantity"] / ats["totalWeeklyTradeCount"], + color="tab:orange", + ) + plt.legend(["ATS"]) + + if not otc.empty: + plt.plot( + otc.index, + otc["totalWeeklyShareQuantity"] / otc["totalWeeklyTradeCount"], + color="tab:blue", + ) + plt.legend(["ATS", "OTC"]) + + else: + plt.plot( + otc.index, + otc["totalWeeklyShareQuantity"] / otc["totalWeeklyTradeCount"], + color="tab:blue", + ) + plt.legend(["OTC"]) + plt.ylabel("Shares per Trade") - plt.legend(["ATS", "OTC"]) plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2) plt.gcf().autofmt_xdate() plt.xlabel("Weeks") @@ -259,6 +292,9 @@ def dark_pool(other_args: List[str], ticker: str): df_ats, df_otc = getTickerFINRAdata(ticker) + if df_ats.empty and df_otc.empty: + print("No ticker data found!") + plot_dark_pools(ticker, df_ats, df_otc) print("") From eae456cc3f9c1022957a77888c16964150c4e18d Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 18 Apr 2021 02:37:29 +0100 Subject: [PATCH 014/114] remove unused import --- gamestonk_terminal/due_diligence/finra_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/due_diligence/finra_view.py b/gamestonk_terminal/due_diligence/finra_view.py index ea3e80bfa71..47ce2f7c817 100644 --- a/gamestonk_terminal/due_diligence/finra_view.py +++ b/gamestonk_terminal/due_diligence/finra_view.py @@ -2,7 +2,7 @@ __docformat__ = "numpy" import argparse -from typing import List, Any +from typing import List import requests import pandas as pd from matplotlib import pyplot as plt From e02a4a8baaa0c7cbfedb679e501a03512ca5b559 Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 18 Apr 2021 02:49:25 +0100 Subject: [PATCH 015/114] fix typing --- gamestonk_terminal/due_diligence/finra_view.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gamestonk_terminal/due_diligence/finra_view.py b/gamestonk_terminal/due_diligence/finra_view.py index 47ce2f7c817..ab4fc2465aa 100644 --- a/gamestonk_terminal/due_diligence/finra_view.py +++ b/gamestonk_terminal/due_diligence/finra_view.py @@ -2,7 +2,7 @@ __docformat__ = "numpy" import argparse -from typing import List +from typing import List, Tuple import requests import pandas as pd from matplotlib import pyplot as plt @@ -57,7 +57,7 @@ def getFINRAweeks(tier, is_ats) -> List: return response.json() if response.status_code == 200 else list() -def getFINRAdata(weekStartDate, tier, ticker, is_ats) -> [int, List]: +def getFINRAdata(weekStartDate, tier, ticker, is_ats) -> Tuple[int, List]: """Get FINRA data Parameters @@ -130,7 +130,7 @@ def getFINRAdata(weekStartDate, tier, ticker, is_ats) -> [int, List]: ) -def getTickerFINRAdata(ticker) -> [pd.DataFrame, pd.DataFrame]: +def getTickerFINRAdata(ticker) -> Tuple[pd.DataFrame, pd.DataFrame]: """Get all FINRA data associated with a ticker Parameters From 33ced3512928597a9754d89b53a9f42fd6f09418 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 18 Apr 2021 20:14:28 +0100 Subject: [PATCH 016/114] Update ROADMAP.md --- ROADMAP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ROADMAP.md b/ROADMAP.md index 82d5b910ed9..d47c8d9c7d3 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -79,6 +79,7 @@ --- ## Due Diligence +* [x] Add dark pools (ATS) vs Non-ATS data over time (@didier) - [PR #363](https://github.com/DidierRLopes/GamestonkTerminal/pull/363) **NEXT** From c66c74a26d051712bac4719fd35ae8d013e96a63 Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 18 Apr 2021 21:52:29 +0100 Subject: [PATCH 017/114] fix bug for yahoo finance tickers from other markets (e.g. SBIN.NS) --- terminal.py | 63 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/terminal.py b/terminal.py index b4c9e2754f9..3db2b090158 100644 --- a/terminal.py +++ b/terminal.py @@ -196,26 +196,51 @@ def main(): b_quit = mill.papermill_menu() elif ns_known_args.opt == "ba": - b_quit = ba_controller.menu(s_ticker, s_start) + b_quit = ba_controller.menu( + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, s_start + ) elif ns_known_args.opt == "res": - b_quit = rm.res_menu(s_ticker, s_start, s_interval) + b_quit = rm.res_menu( + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, + s_start, + s_interval, + ) elif ns_known_args.opt == "ca": b_quit = ca_controller.menu(df_stock, s_ticker, s_start, s_interval) elif ns_known_args.opt == "fa": - b_quit = fam.fa_menu(s_ticker, s_start, s_interval) + b_quit = fam.fa_menu( + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, + s_start, + s_interval, + ) elif ns_known_args.opt == "ta": - b_quit = ta_controller.menu(df_stock, s_ticker, s_start, s_interval) + b_quit = ta_controller.menu( + df_stock, + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, + s_start, + s_interval, + ) elif ns_known_args.opt == "dd": - b_quit = dd_controller.menu(df_stock, s_ticker, s_start, s_interval) + b_quit = dd_controller.menu( + df_stock, + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, + s_start, + s_interval, + ) elif ns_known_args.opt == "eda": if s_interval == "1440min": - b_quit = eda_controller.menu(df_stock, s_ticker, s_start, s_interval) + b_quit = eda_controller.menu( + df_stock, + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, + s_start, + s_interval, + ) else: df_stock = yf.download(s_ticker, start=s_start, progress=False) df_stock = df_stock.rename( @@ -231,7 +256,12 @@ def main(): df_stock.index.name = "date" s_interval = "1440min" - b_quit = eda_controller.menu(df_stock, s_ticker, s_start, s_interval) + b_quit = eda_controller.menu( + df_stock, + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, + s_start, + s_interval, + ) elif ns_known_args.opt == "op": b_quit = op_controller.menu( @@ -273,7 +303,12 @@ def main(): continue if s_interval == "1440min": - b_quit = pred_controller.menu(df_stock, s_ticker, s_start, s_interval) + b_quit = pred_controller.menu( + df_stock, + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, + s_start, + s_interval, + ) # If stock data is intradaily, we need to get data again as prediction # techniques work on daily adjusted data. By default we load data from # Alpha Vantage because the historical data loaded gives a larger @@ -291,7 +326,10 @@ def main(): df_stock_pred = df_stock_pred.sort_index(ascending=True) df_stock_pred = df_stock_pred[s_start:] b_quit = pred_controller.menu( - df_stock_pred, s_ticker, s_start, s_interval="1440min" + df_stock_pred, + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, + s_start, + s_interval="1440min", ) except Exception as e: print(e) @@ -299,7 +337,12 @@ def main(): return elif ns_known_args.opt == "ra": - b_quit = ra_controller.menu(df_stock, s_ticker, s_start, s_interval) + b_quit = ra_controller.menu( + df_stock, + s_ticker.split(".")[0] if "." in s_ticker else s_ticker, + s_start, + s_interval, + ) elif ns_known_args.opt == "scr": b_quit = screener_controller.menu() From 304585cdb1f0c7e9f31e5f48cca5630c06e9acd6 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 18 Apr 2021 22:01:13 +0100 Subject: [PATCH 018/114] add discord server to readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 84a6007fdd1..df5e46c0181 100644 --- a/README.md +++ b/README.md @@ -363,6 +363,9 @@ Distributed under the MIT License. See [LICENSE](https://github.com/DidierRLopes [Artem Veremy](https://www.linkedin.com/in/veremey/) - artem@veremey.net [James Maslek](https://www.linkedin.com/in/james-maslek-b6810186/) - jmaslek11@gmail.com + +Feel free to share porn loss, memes or any questions at https://discord.gg/FmKjHKMn + ## Acknowledgments * [VICE article](https://www.vice.com/en/article/qjp9vp/gamestonk-terminal-is-a-diy-meme-stock-version-of-bloomberg-terminal) From bfeaa2b9a0be7232fef8f35954af4fc0dacd3137 Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Sun, 18 Apr 2021 23:01:21 +0200 Subject: [PATCH 019/114] add ftd command to dd menu --- gamestonk_terminal/due_diligence/README.md | 14 +++ .../due_diligence/dd_controller.py | 7 ++ gamestonk_terminal/due_diligence/sec_view.py | 89 +++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 gamestonk_terminal/due_diligence/sec_view.py diff --git a/gamestonk_terminal/due_diligence/README.md b/gamestonk_terminal/due_diligence/README.md index 70bfb49340b..297d07428fa 100644 --- a/gamestonk_terminal/due_diligence/README.md +++ b/gamestonk_terminal/due_diligence/README.md @@ -24,6 +24,8 @@ This menu aims to help in due-diligence of a pre-loaded stock, and the usage of * short interest [Quandl] * [warnings](#warnings) * company warnings according to Sean Seah book [Market Watch] +* [ftd](#ftd) + * fails-to-deliver data [SEC] ## news @@ -157,3 +159,15 @@ Sean Seah warnings. Check: Consistent historical earnings per share; Consistentl * -d : print insights into warnings calculation. Default False. warnings + +## ftd + +```text +usage: ftd [-n] +``` + +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] + +* -n : number of latest fails-to-deliver being printed. Default 10. + +ftd diff --git a/gamestonk_terminal/due_diligence/dd_controller.py b/gamestonk_terminal/due_diligence/dd_controller.py index 14ecab8fc40..808df2ef426 100644 --- a/gamestonk_terminal/due_diligence/dd_controller.py +++ b/gamestonk_terminal/due_diligence/dd_controller.py @@ -13,6 +13,7 @@ from gamestonk_terminal.due_diligence import market_watch_view as mw_view from gamestonk_terminal.due_diligence import quandl_view as q_view from gamestonk_terminal.due_diligence import reddit_view as r_view from gamestonk_terminal.due_diligence import news_view +from gamestonk_terminal.due_diligence import sec_view from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import get_flair from gamestonk_terminal.menu import session @@ -37,6 +38,7 @@ class DueDiligenceController: "analyst", "warnings", "sec", + "ftd", ] def __init__(self, stock: DataFrame, ticker: str, start: str, interval: str): @@ -97,6 +99,7 @@ class DueDiligenceController: print( " warnings company warnings according to Sean Seah book [Market Watch]" ) + print(" ftd fails-to-deliver data [SEC]") print("") def switch(self, an_input: str): @@ -175,6 +178,10 @@ class DueDiligenceController: """ Process short command """ q_view.short_interest(other_args, self.ticker, self.start) + def call_ftd(self, other_args: List[str]): + """ Process ftd command """ + sec_view.fails_to_deliver(other_args, self.ticker) + def menu(stock: DataFrame, ticker: str, start: str, interval: str): """Due Diligence Menu diff --git a/gamestonk_terminal/due_diligence/sec_view.py b/gamestonk_terminal/due_diligence/sec_view.py new file mode 100644 index 00000000000..35f19df8b1c --- /dev/null +++ b/gamestonk_terminal/due_diligence/sec_view.py @@ -0,0 +1,89 @@ +""" SEC View """ +__docformat__ = "numpy" + +import argparse +from typing import List +import requests +import pandas as pd +from bs4 import BeautifulSoup +from gamestonk_terminal.helper_funcs import ( + get_user_agent, + check_positive, + parse_known_args_and_warn, +) + + +def fails_to_deliver(other_args: List[str], ticker: str): + """Display fails-to-deliver data for a given ticker + + Parameters + ---------- + other_args : List[str] + argparse other args - ["-n", "10"] + ticker : str + Stock ticker + """ + + parser = argparse.ArgumentParser( + add_help=False, + prog="ftd", + description="""Prints latest fails-to-deliver data. [Source: SEC]""", + ) + parser.add_argument( + "-n", + "--num", + action="store", + dest="n_num", + type=check_positive, + default=10, + help="number of latest fails-to-deliver being printed", + ) + + 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", ascending=False)[ + 0 : ns_parser.n_num + ] + print( + ftds_data.rename( + columns={"SETTLEMENT DATE": "Date", "QUANTITY (FAILS)": "Quantity"} + ).to_string(index=False) + ) + + except Exception as e: + print(e, "\n") From 76de01a024c108d0969fc52d9eb311f8ec89ca06 Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 18 Apr 2021 22:27:06 +0100 Subject: [PATCH 020/114] improve bar width of option calls/puts --- gamestonk_terminal/options/volume_view.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gamestonk_terminal/options/volume_view.py b/gamestonk_terminal/options/volume_view.py index a4f3062a960..4d32126c682 100644 --- a/gamestonk_terminal/options/volume_view.py +++ b/gamestonk_terminal/options/volume_view.py @@ -351,8 +351,9 @@ def plot_calls_volume_open_interest( df_calls["strike"], df_calls["volume"] + df_calls["openInterest"], color="lightgreen", + width=0.45, ) - plt.bar(df_calls["strike"], df_calls["volume"], color="green") + plt.bar(df_calls["strike"], df_calls["volume"], color="green", width=0.45) plt.title(f"{ticker} calls volumes for {exp_date} ") plt.legend(["Stock Price", "Open Interest", "Volume"]) @@ -443,8 +444,9 @@ def plot_puts_volume_open_interest( df_puts["strike"], -df_puts["volume"] - df_puts["openInterest"], color="pink", + width=0.45, ) - plt.bar(df_puts["strike"], -df_puts["volume"], color="red") + plt.bar(df_puts["strike"], -df_puts["volume"], color="red", width=0.45) plt.title(f"{ticker} puts volumes for {exp_date} ") plt.legend(["Stock Price", "Open Interest", "Volume"]) From 8407cccedb72ce76d3dbb3766c0da6fe3373bc73 Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 18 Apr 2021 22:29:15 +0100 Subject: [PATCH 021/114] Add new line after option chains --- gamestonk_terminal/options/chains_view.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index c05552a909e..8bc63ef24a4 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -201,6 +201,7 @@ def display_chains(symbol: str, expiry: str, other_args: List[str]): floatfmt=".2f", ) ) + print("") except Exception as e: print(e) From e9b5c2262cd53079251df5ac3e127cb71d67ad5c Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Sun, 18 Apr 2021 23:46:49 +0200 Subject: [PATCH 022/114] update dd controller and README. --- gamestonk_terminal/due_diligence/README.md | 12 ++++++++++++ gamestonk_terminal/due_diligence/dd_controller.py | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/gamestonk_terminal/due_diligence/README.md b/gamestonk_terminal/due_diligence/README.md index 472867b0f7e..2d0c9fb2d0c 100644 --- a/gamestonk_terminal/due_diligence/README.md +++ b/gamestonk_terminal/due_diligence/README.md @@ -26,6 +26,8 @@ This menu aims to help in due-diligence of a pre-loaded stock, and the usage of * company warnings according to Sean Seah book [Market Watch] * [dp](#dp) * dark pools (ATS) vs OTC data [FINRA] +* [ftd](#ftd) + * fails-to-deliver data [SEC] ## news @@ -170,4 +172,14 @@ Display barchart of dark pool (ATS) and OTC (Non ATS) data ![dp](https://user-images.githubusercontent.com/25267873/115130908-7987b580-9feb-11eb-8bca-1999174178d0.png) +## ftd +```text +usage: ftd [-n] +``` + +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] + +* -n : number of latest fails-to-deliver being printed. Default 10. + +ftd diff --git a/gamestonk_terminal/due_diligence/dd_controller.py b/gamestonk_terminal/due_diligence/dd_controller.py index 378499f05cd..2dbe1379927 100644 --- a/gamestonk_terminal/due_diligence/dd_controller.py +++ b/gamestonk_terminal/due_diligence/dd_controller.py @@ -14,6 +14,7 @@ from gamestonk_terminal.due_diligence import quandl_view as q_view from gamestonk_terminal.due_diligence import reddit_view as r_view from gamestonk_terminal.due_diligence import news_view from gamestonk_terminal.due_diligence import finra_view +from gamestonk_terminal.due_diligence import sec_view from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import get_flair from gamestonk_terminal.menu import session @@ -39,6 +40,7 @@ class DueDiligenceController: "warnings", "sec", "dp", + "ftd", ] def __init__(self, stock: DataFrame, ticker: str, start: str, interval: str): @@ -100,6 +102,7 @@ class DueDiligenceController: " warnings company warnings according to Sean Seah book [Market Watch]" ) print(" dp dark pools (ATS) vs OTC data [FINRA]") + print(" ftd fails-to-deliver data [SEC]") print("") def switch(self, an_input: str): @@ -182,6 +185,10 @@ class DueDiligenceController: """ Process dp command """ finra_view.dark_pool(other_args, self.ticker) + def call_ftd(self, other_args: List[str]): + """ Process ftd command """ + sec_view.fails_to_deliver(other_args, self.ticker) + def menu(stock: DataFrame, ticker: str, start: str, interval: str): """Due Diligence Menu From d348d867ae0c2b1ee002d070da6190abeeb187ab Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 18 Apr 2021 22:54:09 +0100 Subject: [PATCH 023/114] Improve options data readme --- gamestonk_terminal/options/README.md | 93 ++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/gamestonk_terminal/options/README.md b/gamestonk_terminal/options/README.md index 980be7495c4..4742badb005 100644 --- a/gamestonk_terminal/options/README.md +++ b/gamestonk_terminal/options/README.md @@ -1,50 +1,89 @@ -# OPTIONS DATA +# OPTIONS -This menu aims to give insight on options. options can cause significant share price movement, and option pricing gives -info about market sentiment for a ticker. +This menu aims to give insight on options. -* [volume](#volume) - * Show traded options for a given expiry [Yahoo Finance] +This menu aims to give insight on options. Options can cause significant share price movement, and option pricing gives info about market sentiment for a ticker. The usage of the following commands along with an example will be exploited below: +* [exp](#exp) + * See/set expiry date [Yahoo Finance] +* [voi](#voi) + * Volume + open interest options trading plot [Yahoo Finance] +* [vcalls](#vcalls) + * Calls volume + open interest plot [Yahoo Finance] +* [vputs](#vputs) + * Puts volume + open interest plot [Yahoo Finance] * [chains](#chains) - * Display option chains for + * Display option chains [Source: Tradier] -## volume + +## exp ```text -usage: volume -e yyyy-mm-dd +usage: exp [-d {0,1,2,3,4,5,6,7,8,9,10,11}] ``` -or +See/set expiry dates. [Source: Yahoo Finance] + +* -d : Expiry date index to set. + +exp + + +## voi ```text -usage: volume --expiry yyyy-mm-dd +usage: voi [-v MIN_VOL] [-m MIN_SP] [-M MAX_SP] ``` +Plots Volume + Open Interest of calls vs puts. [Source: Yahoo Finance] -Display volume graph for a date. [Source: Yahoo Finance] +* -v : Minimum volume (considering open interest) threshold of the plot. +* -m : Minimum strike price to consider in the plot. +* -M : Maximum strike price to consider in the plot. + +![voinio](https://user-images.githubusercontent.com/25267873/115161878-f7a19600-a097-11eb-889b-e9cc945f174d.png) + + +## vcalls + +```text +usage: vcalls [-m MIN_SP] [-M MAX_SP] +``` + +Plots Calls Volume + Open Interest. [Source: Yahoo Finance] + +* -m : Minimum strike price to consider in the plot. +* -M : Maximum strike price to consider in the plot. + +![vcalls](https://user-images.githubusercontent.com/25267873/115161874-f5d7d280-a097-11eb-93e2-3a2b20292f09.png) + + +## vputs + +```text +usage: vputs [-m MIN_SP] [-M MAX_SP] +``` + +Plots Puts Volume + Open Interest. [Source: Yahoo Finance] + +* -m : Minimum strike price to consider in the plot. +* -M : Maximum strike price to consider in the plot. + +![vputs](https://user-images.githubusercontent.com/25267873/115161873-f40e0f00-a097-11eb-8334-3d4f14b56766.png) -* -e, --expiry : expiration date. ## chains -Display a table of options chains. - -This data requires a Tradier sandbox developer account, which can be made [here](#https://tradier.com/products/market-data-api) ```` -usage: chains [--calls] [--puts] [-m MIN] [-M MAX] +usage: chains [--calls] [--puts] [-m MIN_SP] [-M MAX_SP] ```` -* --calls : Flag to only display call options -* --puts : Flag to display only put options -* -m : Minimum strike price to show -* -M : Maximum strike price to show -For combines tables, call options are on the left and put options are on the right of the strike +Display options chains. [Source: Tradier] -As an example, if I load my ticker and select an expiry, to view the options chain for strikes between $129 and $135, one would use: +* --calls : Flag to show calls only +* --puts : Flag to show puts only +* -m : Minimum strike price to consider. +* -M : Maximum strike price to consider. -```` -chains -m 129 -M 135 -```` -Which outputs: -![im](https://user-images.githubusercontent.com/18151143/115068041-b191da00-9ebf-11eb-941e-4e255787ab94.png) + +chains From b2932efee156223c534daec103f2ac74d10bb3b2 Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 18 Apr 2021 23:00:59 +0100 Subject: [PATCH 024/114] minor improvements --- gamestonk_terminal/options/chains_view.py | 4 +++- gamestonk_terminal/options/op_controller.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index 8bc63ef24a4..d1a99a9d1e3 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -88,7 +88,9 @@ def get_option_chains(symbol: str, expiry: str) -> pd.DataFrame: def display_chains(symbol: str, expiry: str, other_args: List[str]): parser = argparse.ArgumentParser( - prog="chains", add_help=False, description="Display options chains" + prog="chains", + add_help=False, + description="Display option chains [Source: Tradier]", ) parser.add_argument( diff --git a/gamestonk_terminal/options/op_controller.py b/gamestonk_terminal/options/op_controller.py index 4caa51dbd63..4a37d485327 100644 --- a/gamestonk_terminal/options/op_controller.py +++ b/gamestonk_terminal/options/op_controller.py @@ -38,7 +38,7 @@ class OptionsController: parser = argparse.ArgumentParser( add_help=False, prog="exp", - description="""See expiry dates.""", + description="""See/set expiry dates. [Source: Yahoo Finance]""", ) parser.add_argument( "-d", From 84c80be012f2756828599b77a4eb65e892acf75e Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Mon, 19 Apr 2021 00:12:33 +0200 Subject: [PATCH 025/114] fix date formatting --- gamestonk_terminal/due_diligence/sec_view.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gamestonk_terminal/due_diligence/sec_view.py b/gamestonk_terminal/due_diligence/sec_view.py index 35f19df8b1c..01a512b552d 100644 --- a/gamestonk_terminal/due_diligence/sec_view.py +++ b/gamestonk_terminal/due_diligence/sec_view.py @@ -3,6 +3,7 @@ __docformat__ = "numpy" import argparse from typing import List +from datetime import datetime import requests import pandas as pd from bs4 import BeautifulSoup @@ -79,6 +80,9 @@ def fails_to_deliver(other_args: List[str], ticker: str): ftds_data = ftds_data.sort_values("SETTLEMENT DATE", ascending=False)[ 0 : ns_parser.n_num ] + ftds_data["SETTLEMENT DATE"] = ftds_data["SETTLEMENT DATE"].apply( + lambda x: datetime.strptime(str(x), "%Y%m%d").strftime("%Y-%m-%d") + ) print( ftds_data.rename( columns={"SETTLEMENT DATE": "Date", "QUANTITY (FAILS)": "Quantity"} From 58320dc09dd954fec9a7cbb394ae879c8d2a1576 Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Mon, 19 Apr 2021 00:36:20 +0200 Subject: [PATCH 026/114] update ROADMAP --- ROADMAP.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index d47c8d9c7d3..277662bd9a8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -80,6 +80,7 @@ ## Due Diligence * [x] Add dark pools (ATS) vs Non-ATS data over time (@didier) - [PR #363](https://github.com/DidierRLopes/GamestonkTerminal/pull/363) +* [x] Add failure to deliver command (@hinxx) - [PR #366](#https://github.com/DidierRLopes/GamestonkTerminal/pull/366) **NEXT** @@ -148,7 +149,7 @@ * [ ] Refactoring * [ ] Summaries / tear sheets (@jmaslek) -___ +___ ## Portfolio Optimization * [x] Basic Optimization through PyPortFolioOpt(@jmaslek) - [PR #329](https://github.com/DidierRLopes/GamestonkTerminal/pull/329) From 48d48cae1c9175d803aed651be5040eccccda975 Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Mon, 19 Apr 2021 01:01:14 +0200 Subject: [PATCH 027/114] plot bars instead of printing to console --- gamestonk_terminal/due_diligence/sec_view.py | 24 ++++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/gamestonk_terminal/due_diligence/sec_view.py b/gamestonk_terminal/due_diligence/sec_view.py index 01a512b552d..7dc0ee7ae4e 100644 --- a/gamestonk_terminal/due_diligence/sec_view.py +++ b/gamestonk_terminal/due_diligence/sec_view.py @@ -7,6 +7,9 @@ from datetime import datetime import requests import pandas as pd from bs4 import BeautifulSoup +from matplotlib import pyplot as plt +from gamestonk_terminal.config_plot import PLOT_DPI +from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import ( get_user_agent, check_positive, @@ -77,17 +80,24 @@ def fails_to_deliver(other_args: List[str], ticker: str): link_idx += 1 # clip away extra rows - ftds_data = ftds_data.sort_values("SETTLEMENT DATE", ascending=False)[ - 0 : ns_parser.n_num - ] + 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").strftime("%Y-%m-%d") ) - print( - ftds_data.rename( - columns={"SETTLEMENT DATE": "Date", "QUANTITY (FAILS)": "Quantity"} - ).to_string(index=False) + + plt.bar( + ftds_data["SETTLEMENT DATE"], + ftds_data["QUANTITY (FAILS)"], ) + plt.ylabel("Number of shares") + plt.title(f"Fails-to-deliver Data for {ticker}") + plt.gcf().autofmt_xdate() + plt.xlabel("Days") + + if gtff.USE_ION: + plt.ion() + + plt.show() except Exception as e: print(e, "\n") From 79c3d0a40f71c3bb2e6b431bcc8844d44f0a007a Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Mon, 19 Apr 2021 01:03:51 +0200 Subject: [PATCH 028/114] fix checks --- gamestonk_terminal/due_diligence/sec_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/due_diligence/sec_view.py b/gamestonk_terminal/due_diligence/sec_view.py index 7dc0ee7ae4e..94dabc09a57 100644 --- a/gamestonk_terminal/due_diligence/sec_view.py +++ b/gamestonk_terminal/due_diligence/sec_view.py @@ -80,7 +80,7 @@ def fails_to_deliver(other_args: List[str], ticker: str): link_idx += 1 # clip away extra rows - ftds_data = ftds_data.sort_values("SETTLEMENT DATE")[-ns_parser.n_num:] + 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").strftime("%Y-%m-%d") ) From e0e9745cdd7199982179fc94315659f5445424d7 Mon Sep 17 00:00:00 2001 From: Hinko Kocevar Date: Mon, 19 Apr 2021 01:37:11 +0200 Subject: [PATCH 029/114] fix plot output --- gamestonk_terminal/due_diligence/sec_view.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gamestonk_terminal/due_diligence/sec_view.py b/gamestonk_terminal/due_diligence/sec_view.py index 94dabc09a57..803cf8ecf3c 100644 --- a/gamestonk_terminal/due_diligence/sec_view.py +++ b/gamestonk_terminal/due_diligence/sec_view.py @@ -8,7 +8,7 @@ import requests import pandas as pd from bs4 import BeautifulSoup from matplotlib import pyplot as plt -from gamestonk_terminal.config_plot import PLOT_DPI +import matplotlib.dates as mdates from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import ( get_user_agent, @@ -82,15 +82,18 @@ def fails_to_deliver(other_args: List[str], ticker: str): # 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").strftime("%Y-%m-%d") + lambda x: datetime.strptime(str(x), "%Y%m%d") ) plt.bar( ftds_data["SETTLEMENT DATE"], - ftds_data["QUANTITY (FAILS)"], + ftds_data["QUANTITY (FAILS)"] / 1000, ) - plt.ylabel("Number of shares") + plt.ylabel("Shares [K]") plt.title(f"Fails-to-deliver Data for {ticker}") + plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2) + plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y/%m/%d")) + plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=7)) plt.gcf().autofmt_xdate() plt.xlabel("Days") From ca7a4da4302f92501fdd6d6fb87c7b697aa19e36 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Mon, 19 Apr 2021 08:44:44 +0100 Subject: [PATCH 030/114] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index df5e46c0181..7724ad3300c 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ Distributed under the MIT License. See [LICENSE](https://github.com/DidierRLopes [James Maslek](https://www.linkedin.com/in/james-maslek-b6810186/) - jmaslek11@gmail.com -Feel free to share porn loss, memes or any questions at https://discord.gg/FmKjHKMn +Feel free to share loss porn, memes or any questions at https://discord.gg/FmKjHKMn ## Acknowledgments From 4ab29f483bba47fe00980f7e3c08d74c86c83705 Mon Sep 17 00:00:00 2001 From: didier Date: Mon, 19 Apr 2021 08:51:44 +0100 Subject: [PATCH 031/114] minor fixes --- gamestonk_terminal/README.md | 1 + gamestonk_terminal/due_diligence/sec_view.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index eb3dfae535b..fdaa9118d84 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -214,6 +214,7 @@ Command|Description|Source `short` |short interest |[Quandl](https://www.quandl.com/) `warnings` |company warnings according to Sean Seah book |[MarketWatch](https://www.marketwatch.com/) `dp` |dark pools (ATS) vs OTC data [FINRA](https://www.finra.org/#/) +`ftd` |display fails-to-deliver data [SEC](https://www.sec.gov)   diff --git a/gamestonk_terminal/due_diligence/sec_view.py b/gamestonk_terminal/due_diligence/sec_view.py index 803cf8ecf3c..9a8ecba46ed 100644 --- a/gamestonk_terminal/due_diligence/sec_view.py +++ b/gamestonk_terminal/due_diligence/sec_view.py @@ -102,5 +102,7 @@ def fails_to_deliver(other_args: List[str], ticker: str): plt.show() + print("") + except Exception as e: print(e, "\n") From ec0cab1b0dd263d7ed4ac94934dc259643ab1b7c Mon Sep 17 00:00:00 2001 From: didier Date: Mon, 19 Apr 2021 08:54:58 +0100 Subject: [PATCH 032/114] add a bit more dates to ftd --- gamestonk_terminal/due_diligence/sec_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/due_diligence/sec_view.py b/gamestonk_terminal/due_diligence/sec_view.py index 9a8ecba46ed..a2528f87387 100644 --- a/gamestonk_terminal/due_diligence/sec_view.py +++ b/gamestonk_terminal/due_diligence/sec_view.py @@ -93,7 +93,7 @@ def fails_to_deliver(other_args: List[str], ticker: str): plt.title(f"Fails-to-deliver Data for {ticker}") plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2) plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y/%m/%d")) - plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=7)) + plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=3)) plt.gcf().autofmt_xdate() plt.xlabel("Days") From b74d70a3d30cd68caa342596627ad7d85c56250c Mon Sep 17 00:00:00 2001 From: didier Date: Mon, 19 Apr 2021 08:58:13 +0100 Subject: [PATCH 033/114] update default shown to 1 month --- gamestonk_terminal/due_diligence/sec_view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gamestonk_terminal/due_diligence/sec_view.py b/gamestonk_terminal/due_diligence/sec_view.py index a2528f87387..9eb3f02e8f8 100644 --- a/gamestonk_terminal/due_diligence/sec_view.py +++ b/gamestonk_terminal/due_diligence/sec_view.py @@ -39,7 +39,7 @@ def fails_to_deliver(other_args: List[str], ticker: str): action="store", dest="n_num", type=check_positive, - default=10, + default=20, help="number of latest fails-to-deliver being printed", ) @@ -93,7 +93,7 @@ def fails_to_deliver(other_args: List[str], ticker: str): plt.title(f"Fails-to-deliver Data for {ticker}") plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2) plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y/%m/%d")) - plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=3)) + plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=7)) plt.gcf().autofmt_xdate() plt.xlabel("Days") From 5fe3746546223a92a5f34549361e977da09981a2 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Mon, 19 Apr 2021 09:00:03 +0100 Subject: [PATCH 034/114] Update README.md --- gamestonk_terminal/due_diligence/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gamestonk_terminal/due_diligence/README.md b/gamestonk_terminal/due_diligence/README.md index 2d0c9fb2d0c..cb8854b78e5 100644 --- a/gamestonk_terminal/due_diligence/README.md +++ b/gamestonk_terminal/due_diligence/README.md @@ -175,11 +175,12 @@ Display barchart of dark pool (ATS) and OTC (Non ATS) data ## ftd ```text -usage: ftd [-n] +usage: ftd [-n N_NUM] ``` 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] -* -n : number of latest fails-to-deliver being printed. Default 10. +* -n : number of latest fails-to-deliver being printed. Default 20. + +![ftd](https://user-images.githubusercontent.com/25267873/115201750-93a9bc80-a0ed-11eb-8f13-68508749259e.png) -ftd From ceb3bc11ae19c5c9d3571b81997babfc32b284a2 Mon Sep 17 00:00:00 2001 From: Prabhakar Chaganti Date: Mon, 19 Apr 2021 11:59:27 -0400 Subject: [PATCH 035/114] Add vega and gamma to option chains display --- gamestonk_terminal/options/chains_view.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index d1a99a9d1e3..920eeb6e368 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -129,7 +129,9 @@ def display_chains(symbol: str, expiry: str, other_args: List[str]): default_columns = [ "mid_iv", + "vega", "delta", + "gamma", "volume", "open_interest", "bid", From afee28a997a32eab6203e5498e53aba4ae403736 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 19 Apr 2021 13:57:40 -0400 Subject: [PATCH 036/114] add option to configure options that get shown --- gamestonk_terminal/options/README.md | 11 +++++++ gamestonk_terminal/options/chains_view.py | 35 +++++++++++++++-------- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/gamestonk_terminal/options/README.md b/gamestonk_terminal/options/README.md index 4742badb005..842f95859f5 100644 --- a/gamestonk_terminal/options/README.md +++ b/gamestonk_terminal/options/README.md @@ -84,6 +84,17 @@ Display options chains. [Source: Tradier] * --puts : Flag to show puts only * -m : Minimum strike price to consider. * -M : Maximum strike price to consider. +* -d : Columns to display. Should be comma separated. Must be in `['bid', 'ask', 'strike', 'bidsize', 'asksize', 'volume', 'open_interest', + 'delta', 'gamma', 'theta', 'vega', 'ask_iv', 'bid_iv','mid_iv']` chains + +To change what columns are displayed, one can use the `-d` flag. To show the same as above, but only the ask, ask size +delta and theta variables, we would do: +```` +chains -m 129 -M 135 -d ask,ask_size,delta,theta +```` +Which outputs +![im2](https://user-images.githubusercontent.com/18151143/115276719-640cab80-a111-11eb-84a2-4dc6a1685946.png) + diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index d1a99a9d1e3..e29047ebb88 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -27,6 +27,15 @@ greek_columns = ["delta", "gamma", "theta", "vega", "ask_iv", "bid_iv", "mid_iv" df_columns = option_columns + greek_columns column_map = {"mid_iv": "iv", "open_interest": "oi", "volume": "vol"} +default_columns = [ + "mid_iv", + "delta", + "volume", + "open_interest", + "bid", + "ask", +] + def process_chains(response: requests.models.Response) -> pd.DataFrame: """ @@ -124,25 +133,26 @@ def display_chains(symbol: str, expiry: str, other_args: List[str]): default=-1, help="maximum strike price to consider.", ) + parser.add_argument( + "-d", + "--display", + dest="to_display", + default=default_columns, + help="columns to look at", + ) chains_df = get_option_chains(symbol, expiry) - default_columns = [ - "mid_iv", - "delta", - "volume", - "open_interest", - "bid", - "ask", - "strike", - "option_type", - ] - chains_df = chains_df[default_columns].rename(columns=column_map) - try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return + if isinstance(ns_parser.to_display, str): + columns = list(ns_parser.to_display.split(",")) + ["strike", "option_type"] + if isinstance(ns_parser.to_display, list): + columns = ns_parser.to_display + ["strike", "option_type"] + + chains_df = chains_df[columns].rename(columns=column_map) if ns_parser.max_sp == -1 and ns_parser.min_sp == -1: min_strike = np.percentile(chains_df["strike"], 25) max_strike = np.percentile(chains_df["strike"], 75) @@ -209,3 +219,4 @@ def display_chains(symbol: str, expiry: str, other_args: List[str]): print(e) print("") return + From 2e0f5b98b9101c9a721dd0da97f62a0dac18fbea Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 19 Apr 2021 14:00:47 -0400 Subject: [PATCH 037/114] fix black --- gamestonk_terminal/options/chains_view.py | 1 - 1 file changed, 1 deletion(-) diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index e29047ebb88..b1fc911cf28 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -219,4 +219,3 @@ def display_chains(symbol: str, expiry: str, other_args: List[str]): print(e) print("") return - From 134a9429bfbd41e60e1d765efc36480bb7c37819 Mon Sep 17 00:00:00 2001 From: Prabhakar Chaganti Date: Mon, 19 Apr 2021 14:04:53 -0400 Subject: [PATCH 038/114] Added theta to the default display columns for option chain --- gamestonk_terminal/options/chains_view.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index 920eeb6e368..afd8c577648 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -132,6 +132,7 @@ def display_chains(symbol: str, expiry: str, other_args: List[str]): "vega", "delta", "gamma", + "theta", "volume", "open_interest", "bid", From e55ec6c4f8b8389710d7a19a01d01b7a3f5c543c Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 19 Apr 2021 14:05:34 -0400 Subject: [PATCH 039/114] change default display columns --- gamestonk_terminal/options/chains_view.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index b1fc911cf28..3fd5aacddb6 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -29,6 +29,9 @@ column_map = {"mid_iv": "iv", "open_interest": "oi", "volume": "vol"} default_columns = [ "mid_iv", + "vega", + "theta", + "gamma", "delta", "volume", "open_interest", From a4914b775b9bdab9fcecda93ddfd9f5ac3ecf329 Mon Sep 17 00:00:00 2001 From: DJ Date: Mon, 19 Apr 2021 12:08:00 -0600 Subject: [PATCH 040/114] Requested Changes --- gamestonk_terminal/forex/fx_controller.py | 56 ++-- gamestonk_terminal/forex/fx_view.py | 334 +++++++++++++++++----- 2 files changed, 299 insertions(+), 91 deletions(-) diff --git a/gamestonk_terminal/forex/fx_controller.py b/gamestonk_terminal/forex/fx_controller.py index d867fe0b476..14f1eb7e151 100644 --- a/gamestonk_terminal/forex/fx_controller.py +++ b/gamestonk_terminal/forex/fx_controller.py @@ -43,7 +43,7 @@ class ForexController: self.instrument = None @staticmethod - def print_help(): + def print_help(self): """Print help""" print("\nForex Mode:") @@ -51,21 +51,23 @@ class ForexController: print(" q Quit this menu and goes back to main menu") print(" quit Quit to abandon program") print("") - print(" cancel Cancel a pending order by ID -i order ID") - print(" candles Show candles") - print(" calendar Show calendar") - print(" closetrade Close a trade by id") - print(" list List order history") print(" load Load an instrument to use") - print(" order Place limit order -u # of units -p price") - print(" orderbook Print orderbook") - print(" pending Get information on pending orders") - print(" positionbook Print positionbook") - print(" positions Get open positions") - print(" price Shows price for selected instrument") print(" summary Shows account summary") + print(" calendar Show calendar") + print(" list List order history") + print(" pending Get information on pending orders") + print(" cancel Cancel a pending order by ID -i order ID") + print(" positions Get open positions") print(" trades List open trades") + print(" closetrade Close a trade by id") print("") + if self.instrument is not None: + print(" candles Show candles") + print(" price Shows price for selected instrument") + print(" order Place limit order -u # of units -p price") + print(" orderbook Print orderbook") + print(" positionbook Print positionbook") + print("") def switch(self, an_input: str): """Process and dispatch input @@ -84,7 +86,7 @@ class ForexController: def call_help(self, _): """Process Help Command""" - self.print_help() + self.print_help(self) def call_q(self, _): """Process Q command - quit the menu""" @@ -94,24 +96,24 @@ class ForexController: """Process Quit command - exit the program""" return True - def call_price(self, _): + def call_price(self, other_args): """Process Price Command""" - fx_view.get_fx_price(account, self.instrument) + fx_view.get_fx_price(account, self.instrument, other_args) def call_load(self, other_args): self.instrument = fx_view.load(other_args) - def call_summary(self, _): + def call_summary(self, other_args): """Process account summary command""" - fx_view.get_account_summary(account) + fx_view.get_account_summary(account, other_args) - def call_orderbook(self, _): + def call_orderbook(self, other_args): """Process Oanda Order Book""" - fx_view.get_order_book(self.instrument) + fx_view.get_order_book(self.instrument, other_args) - def call_positionbook(self, _): + def call_positionbook(self, other_args): """Process Oanda Position Book""" - fx_view.get_position_book(self.instrument) + fx_view.get_position_book(self.instrument, other_args) def call_list(self, other_args: List[str]): """Process list orders command""" @@ -125,13 +127,13 @@ class ForexController: """Cancel pending order by ID""" fx_view.cancel_pending_order(account, other_args) - def call_positions(self, _): + def call_positions(self, other_args): """Get Open Positions""" - fx_view.get_open_positions(account) + fx_view.get_open_positions(account, other_args) - def call_pending(self, _): + def call_pending(self, other_args): """See up to 25 pending orders""" - fx_view.get_pending_orders(account) + fx_view.get_pending_orders(account, other_args) def call_closetrade(self, other_args: List[str]): """Close a trade by id""" @@ -140,9 +142,9 @@ class ForexController: def call_candles(self, other_args: List[str]): fx_view.show_candles(account, self.instrument, other_args) - def call_trades(self, _): + def call_trades(self, other_args): """List open trades""" - fx_view.get_open_trades(account) + fx_view.get_open_trades(account, other_args) def call_calendar(self, other_args: List[str]): """Call calendar""" diff --git a/gamestonk_terminal/forex/fx_view.py b/gamestonk_terminal/forex/fx_view.py index fafa478f9ad..97f54f342ac 100644 --- a/gamestonk_terminal/forex/fx_view.py +++ b/gamestonk_terminal/forex/fx_view.py @@ -25,7 +25,16 @@ client = API(access_token=cfg.OANDA_TOKEN, environment="live") account = cfg.OANDA_ACCOUNT -def get_fx_price(accountID, instrument): +def get_fx_price(accountID, instrument, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + prog="price", + description="Get price for selected instrument.", + ) + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + try: parameters = {"instruments": instrument} request = pricing.PricingInfo(accountID=accountID, params=parameters) @@ -34,11 +43,24 @@ def get_fx_price(accountID, instrument): ask = response["prices"][0]["asks"][0]["price"] print(instrument + " Bid: " + bid) print(instrument + " Ask: " + ask) + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") -def get_account_summary(accountID): +def get_account_summary(accountID, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + prog="summary", + description="Print some information about your account.", + ) + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + try: request = accounts.AccountSummary(accountID=accountID) response = client.request(request) @@ -65,21 +87,37 @@ def get_account_summary(accountID): print(f"Margin Closeout {margin_closeout}") print(f"Margin Closeout Percent: {margin_closeout_percent}") print(f"Margin Closeout Position Value: {margin_closeout_position_value}") + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") def list_orders(accountID, other_args: List[str]): parser = argparse.ArgumentParser( add_help=False, - prog="listorders", + prog="list", description="List order history", ) parser.add_argument( - "-s", "--state", dest="state", action="store", default="ALL", required=False + "-s", + "--state", + dest="state", + action="store", + default="ALL", + required=False, + help="Select state for order list. ", ) parser.add_argument( - "-c", "--count", dest="count", action="store", default=50, required=False + "-c", + "--count", + dest="count", + action="store", + default=50, + required=False, + help="the number of orders to retrive ", ) ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: @@ -92,14 +130,31 @@ def list_orders(accountID, other_args: List[str]): try: request = orders.OrderList(accountID, parameters) response = client.request(request) - df = pd.DataFrame.from_dict(response["orders"]) - df = df[["id", "instrument", "units", "price", "state", "type"]] - print(df) + try: + df = pd.DataFrame.from_dict(response["orders"]) + df = df[["id", "instrument", "units", "price", "state", "type"]] + print(df) + print("") + except KeyError: + print("No orders were found") + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") -def get_order_book(instrument): +def get_order_book(instrument, other_args): + parser = argparse.ArgumentParser( + add_help=False, + prog="orderbook", + description="Plot the orderbook for the instrument if Oanda provides one.", + ) + + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return parameters = {"bucketWidth": "1"} try: request = instruments.InstrumentsOrderBook( @@ -110,11 +165,24 @@ def get_order_book(instrument): pd.set_option("display.max_rows", None) df = df.take(range(527, 727, 1)) book_plot(df, instrument, "Order Book") + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") -def get_position_book(instrument): +def get_position_book(instrument, other_args): + parser = argparse.ArgumentParser( + add_help=False, + prog="positionbook", + description="Plot the positionbook for the instrument if Oanda provides one.", + ) + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + try: request = instruments.InstrumentsPositionBook(instrument=instrument) response = client.request(request) @@ -122,14 +190,18 @@ def get_position_book(instrument): pd.set_option("display.max_rows", None) df = df.take(range(219, 415, 1)) book_plot(df, instrument, "Position Book") + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") def create_order(accountID, instrument, other_args: List[str]): parser = argparse.ArgumentParser( add_help=False, - prog="create_order", + prog="order", description="Create order", ) parser.add_argument( @@ -140,6 +212,8 @@ def create_order(accountID, instrument, other_args: List[str]): type=int, default=0, required=True, + help="The number of units to place in the order request. Positive for " + + "a long position and negative for a short position ", ) parser.add_argument( "-p", @@ -148,6 +222,7 @@ def create_order(accountID, instrument, other_args: List[str]): action="store", type=float, required=True, + help="The price to set for the limit order. ", ) ns_parser = parse_known_args_and_warn(parser, other_args) @@ -167,16 +242,52 @@ def create_order(accountID, instrument, other_args: List[str]): try: request = orders.OrderCreate(accountID, data) response = client.request(request) - print(response) + try: + if "orderFillTransaction" in response["orderCreateTransaction"]: + order_id = response["orderCreateTransaction"]["orderFillTransaction"][ + "id" + ] + order_instrument = response["orderCreateTransaction"][ + "orderFillTransaction" + ]["instrument"] + units = response["orderCreateTransaction"]["orderFillTransaction"][ + "units" + ] + price = response["orderCreateTransaction"]["orderFillTransaction"][ + "price" + ] + print("Order Filled:") + print(f"ID: {order_id}") + print(f"Instrument: {order_instrument}") + print(f"Units: {units}") + print(f"Price: {price}") + print("") + else: + order_creation_id = response["orderCreateTransaction"]["id"] + order_instrument = response["orderCreateTransaction"]["instrument"] + units = response["orderCreateTransaction"]["units"] + price = response["orderCreateTransaction"]["price"] + print("Order created:") + print(f"ID: {order_creation_id}") + print(f"Instrument: {order_instrument}") + print(f"Units: {units}") + print(f"Price: {price}") + print("") + + except Exception as e: + print(e) except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") def cancel_pending_order(accountID, other_args: List[str]): parser = argparse.ArgumentParser( add_help=False, - prog="cancelpendingorder", - description="Cancel Pending Order", + prog="pending", + description="Cancel Pending Order ", ) parser.add_argument( "-i", @@ -184,19 +295,37 @@ def cancel_pending_order(accountID, other_args: List[str]): dest="orderID", action="store", type=str, - required=True, + help="The pending order ID to cancel ", ) + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-i") ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return try: request = orders.OrderCancel(accountID, ns_parser.orderID) - client.request(request) + response = client.request(request) + order_id = response["orderCancelTransaction"]["orderID"] + print(f"Order {order_id} canceled.") + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") -def get_pending_orders(accountID): +def get_pending_orders(accountID, other_args): + parser = argparse.ArgumentParser( + add_help=False, + prog="pending", + description="Gets information about pending orders.", + ) + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + try: request = orders.OrdersPending(accountID) response = client.request(request) @@ -217,11 +346,23 @@ def get_pending_orders(accountID): print("-" * 30) except IndexError: break + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") -def get_open_positions(accountID): +def get_open_positions(accountID, other_args): + parser = argparse.ArgumentParser( + add_help=False, + prog="positions", + description="Gets information about open positions.", + ) + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return try: request = positions.OpenPositions(accountID) response = client.request(request) @@ -241,44 +382,65 @@ def get_open_positions(accountID): print(f"Total Short P/L: {short_pl}") print(f"Short Unrealized P/L: {short_upl}") print("-" * 30 + "\n") + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") -def get_open_trades(accountID): +def get_open_trades(accountID, other_args): + parser = argparse.ArgumentParser( + add_help=False, + prog="trades", + description="Gets information about open trades.", + ) + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + try: request = trades.OpenTrades(accountID) response = client.request(request) - df = pd.DataFrame.from_dict(response["trades"]) - df = df[ - [ - "id", - "instrument", - "initialUnits", - "currentUnits", - "price", - "unrealizedPL", + try: + df = pd.DataFrame.from_dict(response["trades"]) + df = df[ + [ + "id", + "instrument", + "initialUnits", + "currentUnits", + "price", + "unrealizedPL", + ] ] - ] - df = df.rename( - columns={ - "id": "ID", - "instrument": "Instrument", - "initialUnits": "Initial Units", - "currentUnits": "Current Units", - "price": "Entry Price", - } - ) - print(df) + df = df.rename( + columns={ + "id": "ID", + "instrument": "Instrument", + "initialUnits": "Initial Units", + "currentUnits": "Current Units", + "price": "Entry Price", + } + ) + print(df) + print("") + except KeyError: + print("No trades were found") + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") def close_trade(accountID, other_args: List[str]): parser = argparse.ArgumentParser( add_help=False, - prog="close_trade", - description="close a trade", + prog="closetrade", + description="Close a trade by id.", ) parser.add_argument( "-i", @@ -287,6 +449,7 @@ def close_trade(accountID, other_args: List[str]): action="store", type=str, required=True, + help="The Trade ID to close. ", ) parser.add_argument( "-u", @@ -295,25 +458,55 @@ def close_trade(accountID, other_args: List[str]): action="store", type=str, required=False, + help="The number of units on the trade to close. If not set it " + + "defaults to all units. ", ) + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-i") ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - data = { - "units": ns_parser.units, - } + data = {} + if ns_parser.units is not None: + data["units"] = (ns_parser.units,) try: request = trades.TradeClose(accountID, ns_parser.orderID, data) response = client.request(request) - print(response) + try: + order_id = response["orderCreateTransaction"]["tradeClose"]["tradeID"] + order_instrument = response["orderFillTransaction"]["instrument"] + units = response["orderCreateTransaction"]["units"] + price = response["orderFillTransaction"]["price"] + pl = response["orderFillTransaction"]["pl"] + print("Order closed:") + print(f"ID: {order_id}") + print(f"Instrument: {order_instrument}") + print(f"Units: {units}") + print(f"Price: {price}") + print(f"P/L: {pl}") + print("") + except Exception as e: + print(e) + print("") + except V20Error as e: - print(e) + if "orderRejectTransaction" in e.msg: + msg_length = len(e.msg) + order_id = e.msg[355 : msg_length - 149] + print(f"Order ID {order_id} doesn't exist") + print("") + else: + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") def show_candles(accountID, instrument, other_args: List[str]): parser = argparse.ArgumentParser( add_help=False, - prog="show_candles", + prog="candles", description="Display Candle Data", ) parser.add_argument( @@ -324,6 +517,9 @@ def show_candles(accountID, instrument, other_args: List[str]): type=str, default="D", required=False, + help="The timeframe to get for the candle chart (Seconds: S5, S10, S15, S30 " + + "Minutes: M1, M2, M4, M5, M10, M15, M30 Hours: H1, H2, H3, H4, H6, H8, H12 " + + "Day (default): D, Wee: W Month: M", ) parser.add_argument( "-c", @@ -333,6 +529,7 @@ def show_candles(accountID, instrument, other_args: List[str]): default=180, type=int, required=False, + help="The number of candles to retrieve. Default:180 ", ) ns_parser = parse_known_args_and_warn(parser, other_args) @@ -359,10 +556,12 @@ def show_candles(accountID, instrument, other_args: List[str]): volume=True, title=f"{instrument} {ns_parser.granularity}", ) - except Exception as e: - print(e) - except NameError as e: - print(e) + print("") + except V20Error as e: + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") def process_candle_response(response): @@ -414,6 +613,8 @@ def calendar(instrument, other_args: List[str]): type=int, default=7, required=False, + help="The number of days to search for, up to 30 forward or backward " + + "use negative numbers to search back. ", ) ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: @@ -469,15 +670,20 @@ def calendar(instrument, other_args: List[str]): else: print(f"Previous: {previous}") print("-" * 30) + print("") except V20Error as e: - print(e) + msg_length = len(e.msg) + msg = e.msg[17 : msg_length - 2] + print(msg) + print("") + print("") def load(other_args: List[str]): """Load a forex instrument to use""" parser = argparse.ArgumentParser( add_help=False, - prog="Forex", + prog="load", description="Forex using oanda", ) @@ -487,7 +693,7 @@ def load(other_args: List[str]): required=True, type=str, dest="instrument", - help="Instrument to use for function calls", + help="Forex pair to use. ", ) try: From 64e198f62122131067bfd2683c1c3fd8fd3abf2f Mon Sep 17 00:00:00 2001 From: DJ Date: Mon, 19 Apr 2021 12:12:16 -0600 Subject: [PATCH 041/114] Spelling --- gamestonk_terminal/forex/fx_view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gamestonk_terminal/forex/fx_view.py b/gamestonk_terminal/forex/fx_view.py index 97f54f342ac..fd8b0668cb9 100644 --- a/gamestonk_terminal/forex/fx_view.py +++ b/gamestonk_terminal/forex/fx_view.py @@ -117,7 +117,7 @@ def list_orders(accountID, other_args: List[str]): action="store", default=50, required=False, - help="the number of orders to retrive ", + help="the number of orders to retrieve ", ) ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: @@ -519,7 +519,7 @@ def show_candles(accountID, instrument, other_args: List[str]): required=False, help="The timeframe to get for the candle chart (Seconds: S5, S10, S15, S30 " + "Minutes: M1, M2, M4, M5, M10, M15, M30 Hours: H1, H2, H3, H4, H6, H8, H12 " - + "Day (default): D, Wee: W Month: M", + + "Day (default): D, Week: W Month: M", ) parser.add_argument( "-c", From e25ac791a1edecd96e7029956d418bfa17fd805c Mon Sep 17 00:00:00 2001 From: DJ Date: Mon, 19 Apr 2021 12:15:28 -0600 Subject: [PATCH 042/114] Added current instrument to help --- gamestonk_terminal/forex/fx_controller.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gamestonk_terminal/forex/fx_controller.py b/gamestonk_terminal/forex/fx_controller.py index 14f1eb7e151..3b96f5c2911 100644 --- a/gamestonk_terminal/forex/fx_controller.py +++ b/gamestonk_terminal/forex/fx_controller.py @@ -51,6 +51,8 @@ class ForexController: print(" q Quit this menu and goes back to main menu") print(" quit Quit to abandon program") print("") + if self.instrument is not None: + print("Currently loaded instrument " + self.instrument) print(" load Load an instrument to use") print(" summary Shows account summary") print(" calendar Show calendar") From a36bbc4d3d98934c687892cb9f4f73ce85c61314 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 11:54:42 -0700 Subject: [PATCH 043/114] Refactoring Financial Modeling Prep --- .../fundamental_analysis/fa_controller.py | 4 +- .../financial_modeling_prep_controller.py | 194 +++++++++++ ...api.py => financial_modeling_prep_view.py} | 317 +++++++++--------- terminal.py | 2 +- 4 files changed, 355 insertions(+), 162 deletions(-) create mode 100644 gamestonk_terminal/fundamental_analysis/financial_modeling_prep_controller.py rename gamestonk_terminal/fundamental_analysis/{financial_modeling_prep_api.py => financial_modeling_prep_view.py} (77%) mode change 100644 => 100755 diff --git a/gamestonk_terminal/fundamental_analysis/fa_controller.py b/gamestonk_terminal/fundamental_analysis/fa_controller.py index c077295bedc..57ec653d7fa 100644 --- a/gamestonk_terminal/fundamental_analysis/fa_controller.py +++ b/gamestonk_terminal/fundamental_analysis/fa_controller.py @@ -8,7 +8,7 @@ from prompt_toolkit.completion import NestedCompleter from gamestonk_terminal.fundamental_analysis import alpha_vantage_controller as avc from gamestonk_terminal.fundamental_analysis import business_insider_view as biw from gamestonk_terminal.fundamental_analysis import ( - financial_modeling_prep_api as fmp_api, + financial_modeling_prep_controller as fmpc, ) from gamestonk_terminal.fundamental_analysis import finviz_api as fvz_api from gamestonk_terminal.fundamental_analysis import market_watch_api as mw_api @@ -176,7 +176,7 @@ class FundamentalAnalysisController: # pylint: disable=unused-argument def call_fmp(self, other_args: List[str]): """ Process fmp command """ - ret = fmp_api.menu(self.ticker, self.start, self.interval) + ret = fmpc.menu(self.ticker, self.start, self.interval) if ret is not True: self.print_help() diff --git a/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_controller.py b/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_controller.py new file mode 100644 index 00000000000..e68077aa0f9 --- /dev/null +++ b/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_controller.py @@ -0,0 +1,194 @@ +""" Financial Modeling Prep Controller """ +__docformat__ = "numpy" + +import argparse +from typing import List +from prompt_toolkit.completion import NestedCompleter + +from gamestonk_terminal.fundamental_analysis import financial_modeling_prep_view as fmpv +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import ( + get_flair, +) +from gamestonk_terminal.menu import session + + +class FinancialModelingPrepController: + """ Financial Modeling Prep Controller """ + + # Command choices + CHOICES = [ + "help", + "q", + "quit", + "profile", + "quote", + "enterprise", + "dcf", + "income", + "balance", + "cash", + "metrics", + "ratios", + "growth", + ] + + def __init__(self, ticker: str, start: str, interval: str): + """Constructor + + Parameters + ---------- + ticker : str + Fundamental analysis ticker symbol + start : str + Stat date of the stock data + interval : str + Stock data interval + """ + + self.ticker = ticker + self.start = start + self.interval = interval + self.fmp_parser = argparse.ArgumentParser(add_help=False, prog="fmp") + self.fmp_parser.add_argument( + "cmd", + choices=self.CHOICES, + ) + + def print_help(self): + """ Print help """ + + intraday = (f"Intraday {self.interval}", "Daily")[self.interval == "1440min"] + + if self.start: + print( + f"\n{intraday} Stock: {self.ticker} (from {self.start.strftime('%Y-%m-%d')})" + ) + else: + print(f"\n{intraday} Stock: {self.ticker}") + + print("\nFinancial Modeling Prep API") + print(" help show this financial modeling prep menu again") + print(" q quit this menu, and shows back to main menu") + print(" quit quit to abandon program") + print("") + print(" profile profile of the company") + print(" quote quote of the company") + print(" enterprise enterprise value of the company over time") + print(" dcf discounted cash flow of the company over time") + print(" income income statements of the company") + print(" balance balance sheet of the company") + print(" cash cash flow statement of the company") + print(" metrics key metrics of the company") + print(" ratios financial ratios of the company") + print(" growth financial statement growth of the company") + print("") + + def switch(self, an_input: str): + """Process and dispatch input + + Returns + ------- + True, False or None + False - quit the menu + True - quit the program + None - continue in the menu + """ + (known_args, other_args) = self.fmp_parser.parse_known_args(an_input.split()) + + return getattr( + self, "call_" + known_args.cmd, lambda: "Command not recognized!" + )(other_args) + + def call_help(self, _): + """Process Help command""" + self.print_help() + + def call_q(self, _): + """Process Q command - quit the menu""" + return False + + def call_quit(self, _): + """Process Quit command - quit the program""" + return True + + def call_profile(self, other_args: List[str]): + """ Process profile command """ + fmpv.profile(other_args, self.ticker) + + def call_quote(self, other_args: List[str]): + """ Process quote command """ + fmpv.quote(other_args, self.ticker) + + def call_enterprise(self, other_args: List[str]): + """ Process income command """ + fmpv.enterprise(other_args, self.ticker) + + def call_dcf(self, other_args: List[str]): + """ Process dcf command """ + fmpv.discounted_cash_flow(other_args, self.ticker) + + def call_income(self, other_args: List[str]): + """ Process income command """ + fmpv.income_statement(other_args, self.ticker) + + def call_balance(self, other_args: List[str]): + """ Process balance command """ + fmpv.balance_sheet(other_args, self.ticker) + + def call_cash(self, other_args: List[str]): + """ Process cash command """ + fmpv.cash_flow(other_args, self.ticker) + + def call_metrics(self, other_args: List[str]): + """ Process metrics command """ + fmpv.key_metrics(other_args, self.ticker) + + def call_ratios(self, other_args: List[str]): + """ Process cash command """ + fmpv.financial_ratios(other_args, self.ticker) + + def call_growth(self, other_args: List[str]): + """ Process cash command """ + fmpv.financial_statement_growth(other_args, self.ticker) + + +def menu(ticker: str, start: str, interval: str): + """Financial Modeling Prep menu + + Parameters + ---------- + ticker : str + Fundamental analysis ticker symbol + start : str + Start date of the stock data + interval : str + Stock data interval + """ + + fmp_controller = FinancialModelingPrepController(ticker, start, interval) + fmp_controller.call_help(None) + + while True: + # Get input command from user + if session and gtff.USE_PROMPT_TOOLKIT: + completer = NestedCompleter.from_nested_dict( + {c: None for c in fmp_controller.CHOICES} + ) + + an_input = session.prompt( + f"{get_flair()} (fa)>(fmp)> ", + completer=completer, + ) + else: + an_input = input(f"{get_flair()} (fa)>(fmp)> ") + + try: + process_input = fmp_controller.switch(an_input) + + if process_input is not None: + return process_input + + except SystemExit: + print("The command selected doesn't exist\n") + continue diff --git a/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_api.py b/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py old mode 100644 new mode 100755 similarity index 77% rename from gamestonk_terminal/fundamental_analysis/financial_modeling_prep_api.py rename to gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py index 7189fce3fd5..68e22a86281 --- a/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_api.py +++ b/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py @@ -1,139 +1,31 @@ +""" Financial Modeling Prep View """ +__docformat__ = "numpy" + import argparse +from typing import List from datetime import datetime import pandas as pd import FundamentalAnalysis as fa # Financial Modeling Prep -from prompt_toolkit.completion import NestedCompleter from gamestonk_terminal import config_terminal as cfg from gamestonk_terminal.dataframe_helpers import clean_df_index from gamestonk_terminal.helper_funcs import ( long_number_format, check_positive, parse_known_args_and_warn, - get_flair, ) -from gamestonk_terminal.menu import session -def print_menu(s_ticker, s_start, s_interval): - """ Print help """ +def profile(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker profile - s_intraday = (f"Intraday {s_interval}", "Daily")[s_interval == "1440min"] + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ - if s_start: - print(f"\n{s_intraday} Stock: {s_ticker} (from {s_start.strftime('%Y-%m-%d')})") - else: - print(f"\n{s_intraday} Stock: {s_ticker}") - - print("\nFinancial Modeling Prep API") - print(" help show this financial modeling prep menu again") - print(" q quit this menu, and shows back to main menu") - print(" quit quit to abandon program") - print("") - print(" profile profile of the company") - print(" quote quote of the company") - print(" enterprise enterprise value of the company over time") - print(" dcf discounted cash flow of the company over time") - print(" income income statements of the company") - print(" balance balance sheet of the company") - print(" cash cash flow statement of the company") - print(" metrics key metrics of the company") - print(" ratios financial ratios of the company") - print(" growth financial statement growth of the company") - print("") - - -def menu(s_ticker, s_start, s_interval): - - # Add list of arguments that the fundamental analysis parser accepts - fmp_parser = argparse.ArgumentParser(prog="fmp", add_help=False) - choices = [ - "help", - "q", - "quit", - "profile", - "quote", - "enterprise", - "dcf", - "fmp_income", - "fmp_balance", - "fmp_cash", - "metrics", - "ratios", - "growth", - ] - fmp_parser.add_argument("cmd", choices=choices) - completer = NestedCompleter.from_nested_dict({c: None for c in choices}) - - print_menu(s_ticker, s_start, s_interval) - - # Loop forever and ever - while True: - # Get input command from user - if session: - as_input = session.prompt( - f"{get_flair()} (fa)>(fmp)> ", - completer=completer, - ) - else: - as_input = input(f"{get_flair()} (fa)>(av)> ") - - # Parse alpha vantage command of the list of possible commands - try: - (ns_known_args, l_args) = fmp_parser.parse_known_args(as_input.split()) - - except SystemExit: - print("The command selected doesn't exist\n") - continue - - if ns_known_args.cmd == "help": - print_menu(s_ticker, s_start, s_interval) - - elif ns_known_args.cmd == "q": - # Just leave the menu - return False - - elif ns_known_args.cmd == "quit": - # Abandon the program - return True - - # Details: - elif ns_known_args.cmd == "profile": - profile(l_args, s_ticker) - - elif ns_known_args.cmd == "quote": - quote(l_args, s_ticker) - - elif ns_known_args.cmd == "enterprise": - enterprise(l_args, s_ticker) - - elif ns_known_args.cmd == "dcf": - discounted_cash_flow(l_args, s_ticker) - - # Financial statement: - elif ns_known_args.cmd == "income": - income_statement(l_args, s_ticker) - - elif ns_known_args.cmd == "balance": - balance_sheet(l_args, s_ticker) - - elif ns_known_args.cmd == "cash": - cash_flow(l_args, s_ticker) - - # Ratios: - elif ns_known_args.cmd == "metrics": - key_metrics(l_args, s_ticker) - - elif ns_known_args.cmd == "ratios": - financial_ratios(l_args, s_ticker) - - elif ns_known_args.cmd == "growth": - financial_statement_growth(l_args, s_ticker) - - else: - print("Command not recognized!") - - -def profile(l_args, s_ticker): parser = argparse.ArgumentParser( add_help=False, prog="profile", @@ -148,11 +40,11 @@ def profile(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - df_fa = fa.profile(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa = fa.profile(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) clean_df_index(df_fa) print(df_fa.drop(index=["Description", "Image"]).to_string(header=False)) @@ -166,7 +58,17 @@ def profile(l_args, s_ticker): return -def quote(l_args, s_ticker): +def quote(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker quote + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="quote", @@ -181,11 +83,11 @@ def quote(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - df_fa = fa.quote(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa = fa.quote(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) clean_df_index(df_fa) @@ -211,7 +113,17 @@ def quote(l_args, s_ticker): return -def enterprise(l_args, s_ticker): +def enterprise(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker enterprise + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="enterprise", @@ -242,7 +154,7 @@ def enterprise(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -253,10 +165,10 @@ def enterprise(l_args, s_ticker): if ns_parser.b_quarter: df_fa = fa.enterprise( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" + ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" ) else: - df_fa = fa.enterprise(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa = fa.enterprise(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num, mask=False) @@ -269,7 +181,17 @@ def enterprise(l_args, s_ticker): return -def discounted_cash_flow(l_args, s_ticker): +def discounted_cash_flow(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker discounted cash flow + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="dcf", @@ -298,7 +220,7 @@ def discounted_cash_flow(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -309,10 +231,10 @@ def discounted_cash_flow(l_args, s_ticker): if ns_parser.b_quarter: df_fa = fa.discounted_cash_flow( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" + ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" ) else: - df_fa = fa.discounted_cash_flow(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa = fa.discounted_cash_flow(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num, mask=False) @@ -325,7 +247,17 @@ def discounted_cash_flow(l_args, s_ticker): return -def income_statement(l_args, s_ticker): +def income_statement(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker income statement + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="inc", @@ -361,7 +293,7 @@ def income_statement(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -372,10 +304,10 @@ def income_statement(l_args, s_ticker): if ns_parser.b_quarter: df_fa = fa.income_statement( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" + ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" ) else: - df_fa = fa.income_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa = fa.income_statement(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num) @@ -394,7 +326,17 @@ def income_statement(l_args, s_ticker): return -def balance_sheet(l_args, s_ticker): +def balance_sheet(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker balance sheet + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="bal", @@ -435,7 +377,7 @@ def balance_sheet(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -446,11 +388,11 @@ def balance_sheet(l_args, s_ticker): if ns_parser.b_quarter: df_fa = fa.balance_sheet_statement( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" + ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" ) else: df_fa = fa.balance_sheet_statement( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP + ticker, cfg.API_KEY_FINANCIALMODELINGPREP ) df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num) @@ -470,7 +412,17 @@ def balance_sheet(l_args, s_ticker): return -def cash_flow(l_args, s_ticker): +def cash_flow(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker cash flow + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="cash", @@ -509,7 +461,7 @@ def cash_flow(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -520,10 +472,10 @@ def cash_flow(l_args, s_ticker): if ns_parser.b_quarter: df_fa = fa.cash_flow_statement( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" + ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" ) else: - df_fa = fa.cash_flow_statement(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa = fa.cash_flow_statement(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num) @@ -542,7 +494,17 @@ def cash_flow(l_args, s_ticker): return -def key_metrics(l_args, s_ticker): +def key_metrics(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker key metrics + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="metrics", @@ -560,7 +522,7 @@ def key_metrics(l_args, s_ticker): Inventory turnover, Market cap, Net current asset value, Net debt to EBITDA, Net income per share, Operating cash flow per share, Payables turnover, Payout ratio, Pb ratio, Pe ratio, Pfcf ratio, Pocfratio, Price to sales ratio, Ptb ratio, Receivables turnover, - Research and ddevelopement to revenue, Return on tangible assets, Revenue per share, + Research and development to revenue, Return on tangible assets, Revenue per share, Roe, Roic, Sales general and administrative to revenue, Shareholders equity per share, Stock based compensation to revenue, Tangible book value per share, and Working capital. [Source: Financial Modeling Prep] @@ -586,7 +548,7 @@ def key_metrics(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -597,10 +559,10 @@ def key_metrics(l_args, s_ticker): if ns_parser.b_quarter: df_fa = fa.key_metrics( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" + ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" ) else: - df_fa = fa.key_metrics(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa = fa.key_metrics(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num) @@ -613,7 +575,17 @@ def key_metrics(l_args, s_ticker): return -def financial_ratios(l_args, s_ticker): +def financial_ratios(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker ratios + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="ratios", @@ -658,7 +630,7 @@ def financial_ratios(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -669,10 +641,10 @@ def financial_ratios(l_args, s_ticker): if ns_parser.b_quarter: df_fa = fa.financial_ratios( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" + ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" ) else: - df_fa = fa.financial_ratios(s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + df_fa = fa.financial_ratios(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num) @@ -685,7 +657,17 @@ def financial_ratios(l_args, s_ticker): return -def financial_statement_growth(l_args, s_ticker): +def financial_statement_growth(other_args: List[str], ticker: str): + """Financial Modeling Prep ticker growth + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="growth", @@ -726,7 +708,7 @@ def financial_statement_growth(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -737,11 +719,11 @@ def financial_statement_growth(l_args, s_ticker): if ns_parser.b_quarter: df_fa = fa.financial_statement_growth( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" + ticker, cfg.API_KEY_FINANCIALMODELINGPREP, period="quarter" ) else: df_fa = fa.financial_statement_growth( - s_ticker, cfg.API_KEY_FINANCIALMODELINGPREP + ticker, cfg.API_KEY_FINANCIALMODELINGPREP ) df_fa = clean_metrics_df(df_fa, num=ns_parser.n_num) @@ -756,6 +738,23 @@ def financial_statement_growth(l_args, s_ticker): def clean_metrics_df(df_fa: pd.DataFrame, num: int, mask: bool = True) -> pd.DataFrame: + """Clean metrics data frame + + Parameters + ---------- + df_fa : pd.DataFrame + Metrics data frame + num : int + Number of columns to clean + mask : bool, optional + Apply mask, by default True + + Returns + ------- + pd.DataFrame + Cleaned metrics data frame + """ + df_fa = df_fa.iloc[:, 0:num] if mask: df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["None"])).dropna() diff --git a/terminal.py b/terminal.py index 2a54ea0287f..6f637eba85e 100644 --- a/terminal.py +++ b/terminal.py @@ -329,7 +329,7 @@ def main(): df_stock_pred, s_ticker.split(".")[0] if "." in s_ticker else s_ticker, s_start, - s_interval="1440min", + interval="1440min", ) except Exception as e: print(e) From 2b70c521c0c132d31a74f8d212d9f05e411f1619 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 11:55:08 -0700 Subject: [PATCH 044/114] Filemod --- .../fundamental_analysis/financial_modeling_prep_view.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py diff --git a/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py b/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py old mode 100755 new mode 100644 From 90300b472e6881d09ac2508a3a5963d1c67b7d13 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 12:43:55 -0700 Subject: [PATCH 045/114] Refactoring Market Watch, FinViz, Yahoo Finance FA --- .../fundamental_analysis/fa_controller.py | 22 +-- .../{finviz_api.py => finviz_view.py} | 21 ++- .../market_watch_model.py | 111 ++++++++++++ ...rket_watch_api.py => market_watch_view.py} | 161 +++++------------- ...o_finance_api.py => yahoo_finance_view.py} | 73 ++++++-- ...ch_api.yaml => fa_market_watch_model.yaml} | 0 ..._unit.py => test_fa_market_watch_model.py} | 6 +- ...ch_api.py => test_fa_market_watch_view.py} | 2 +- ...e_api.py => test_fa_yahoo_finance_view.py} | 2 +- 9 files changed, 251 insertions(+), 147 deletions(-) rename gamestonk_terminal/fundamental_analysis/{finviz_api.py => finviz_view.py} (78%) create mode 100644 gamestonk_terminal/fundamental_analysis/market_watch_model.py rename gamestonk_terminal/fundamental_analysis/{market_watch_api.py => market_watch_view.py} (70%) rename gamestonk_terminal/fundamental_analysis/{yahoo_finance_api.py => yahoo_finance_view.py} (85%) rename tests/data/{fa_market_watch_api.yaml => fa_market_watch_model.yaml} (100%) rename tests/{test_fa_market_watch_api_unit.py => test_fa_market_watch_model.py} (86%) rename tests/{test_fa_market_watch_api.py => test_fa_market_watch_view.py} (69%) rename tests/{test_fa_yahoo_finance_api.py => test_fa_yahoo_finance_view.py} (84%) diff --git a/gamestonk_terminal/fundamental_analysis/fa_controller.py b/gamestonk_terminal/fundamental_analysis/fa_controller.py index 57ec653d7fa..2cad209fd82 100644 --- a/gamestonk_terminal/fundamental_analysis/fa_controller.py +++ b/gamestonk_terminal/fundamental_analysis/fa_controller.py @@ -10,9 +10,9 @@ from gamestonk_terminal.fundamental_analysis import business_insider_view as biw from gamestonk_terminal.fundamental_analysis import ( financial_modeling_prep_controller as fmpc, ) -from gamestonk_terminal.fundamental_analysis import finviz_api as fvz_api -from gamestonk_terminal.fundamental_analysis import market_watch_api as mw_api -from gamestonk_terminal.fundamental_analysis import yahoo_finance_api as yf_api +from gamestonk_terminal.fundamental_analysis import finviz_view +from gamestonk_terminal.fundamental_analysis import market_watch_view +from gamestonk_terminal.fundamental_analysis import yahoo_finance_view from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import get_flair from gamestonk_terminal.menu import session @@ -135,35 +135,35 @@ class FundamentalAnalysisController: def call_screener(self, other_args: List[str]): """ Process screener command """ - fvz_api.screener(other_args, self.ticker) + finviz_view.screener(other_args, self.ticker) def call_income(self, other_args: List[str]): """ Process income command """ - mw_api.income(other_args, self.ticker) + market_watch_view.income(other_args, self.ticker) def call_balance(self, other_args: List[str]): """ Process balance command """ - mw_api.balance(other_args, self.ticker) + market_watch_view.balance(other_args, self.ticker) def call_cash(self, other_args: List[str]): """ Process cash command """ - mw_api.cash(other_args, self.ticker) + market_watch_view.cash(other_args, self.ticker) def call_info(self, other_args: List[str]): """ Process info command """ - yf_api.info(other_args, self.ticker) + yahoo_finance_view.info(other_args, self.ticker) def call_shrs(self, other_args: List[str]): """ Process shrs command """ - yf_api.shareholders(other_args, self.ticker) + yahoo_finance_view.shareholders(other_args, self.ticker) def call_sust(self, other_args: List[str]): """ Process sust command """ - yf_api.sustainability(other_args, self.ticker) + yahoo_finance_view.sustainability(other_args, self.ticker) def call_cal(self, other_args: List[str]): """ Process cal command """ - yf_api.calendar_earnings(other_args, self.ticker) + yahoo_finance_view.calendar_earnings(other_args, self.ticker) # pylint: disable=unused-argument def call_av(self, other_args: List[str]): diff --git a/gamestonk_terminal/fundamental_analysis/finviz_api.py b/gamestonk_terminal/fundamental_analysis/finviz_view.py similarity index 78% rename from gamestonk_terminal/fundamental_analysis/finviz_api.py rename to gamestonk_terminal/fundamental_analysis/finviz_view.py index 3bdc999ff62..59fa1679498 100644 --- a/gamestonk_terminal/fundamental_analysis/finviz_api.py +++ b/gamestonk_terminal/fundamental_analysis/finviz_view.py @@ -1,10 +1,25 @@ +""" FinViz View """ +__docformat__ = "numpy" + import argparse +from typing import List import finviz import pandas as pd + from gamestonk_terminal.helper_funcs import parse_known_args_and_warn -def screener(l_args, s_ticker): +def screener(other_args: List[str], ticker: str): + """FinViz ticker screener + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="screener", @@ -24,11 +39,11 @@ def screener(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - d_finviz_stock = finviz.get_stock(s_ticker) + d_finviz_stock = finviz.get_stock(ticker) df_fa = pd.DataFrame.from_dict( d_finviz_stock, orient="index", columns=["Values"] ) diff --git a/gamestonk_terminal/fundamental_analysis/market_watch_model.py b/gamestonk_terminal/fundamental_analysis/market_watch_model.py new file mode 100644 index 00000000000..fc1715949da --- /dev/null +++ b/gamestonk_terminal/fundamental_analysis/market_watch_model.py @@ -0,0 +1,111 @@ +""" Fundamental Analysis Market Watch Model """ +__docformat__ = "numpy" + +import requests +import pandas as pd +from bs4 import BeautifulSoup + +from gamestonk_terminal.helper_funcs import ( + get_user_agent, +) + + +def prepare_df_financials( + ticker: str, statement: str, quarter: bool = False +) -> pd.DataFrame: + """Builds a DataFrame with financial statements for a given company + + Parameters + ---------- + ticker : str + Company's stock ticker + statement : str + Either income, balance or cashflow + quarter : bool, optional + Return quarterly financial statements instead of annual, by default False + + Returns + ------- + pd.DataFrame + A DataFrame with financial info + + Raises + ------ + ValueError + If statement is not income, balance or cashflow + """ + financial_urls = { + "income": { + "quarter": "https://www.marketwatch.com/investing/stock/{}/financials/income/quarter", + "annual": "https://www.marketwatch.com/investing/stock/{}/financials/income", + }, + "balance": { + "quarter": "https://www.marketwatch.com/investing/stock/{}/financials/balance-sheet/quarter", + "annual": "https://www.marketwatch.com/investing/stock/{}/financials/balance-sheet", + }, + "cashflow": { + "quarter": "https://www.marketwatch.com/investing/stock/{}/financials/cash-flow/quarter", + "annual": "https://www.marketwatch.com/investing/stock/{}/financials/cash-flow", + }, + } + + if statement not in financial_urls.keys(): + raise ValueError(f"type {statement} is not in {financial_urls.keys()}") + + if quarter: + period = "quarter" + else: + period = "annual" + + text_soup_financials = BeautifulSoup( + requests.get( + financial_urls[statement][period].format(ticker), + headers={"User-Agent": get_user_agent()}, + ).text, + "lxml", + ) + + # Define financials columns + a_financials_header = list() + for financials_header in text_soup_financials.findAll( + "th", {"class": "overflow__heading"} + ): + a_financials_header.append(financials_header.text.strip("\n").split("\n")[0]) + + s_header_end_trend = ("5-year trend", "5- qtr trend")[quarter] + df_financials = pd.DataFrame( + columns=a_financials_header[0 : a_financials_header.index(s_header_end_trend)] + ) + + find_table = text_soup_financials.findAll( + "div", {"class": "element element--table table--fixed financials"} + ) + + if not find_table: + return df_financials + + financials_rows = find_table[0].findAll( + "tr", {"class": ["table__row is-highlighted", "table__row"]} + ) + + for a_row in financials_rows: + constructed_row = list() + financial_columns = a_row.findAll( + "td", {"class": ["overflow__cell", "overflow__cell fixed--column"]} + ) + + if not financial_columns: + continue + + for a_column in financial_columns: + column_to_text = a_column.text.strip() + if "\n" in column_to_text: + column_to_text = column_to_text.split("\n")[0] + + if column_to_text == "": + continue + constructed_row.append(column_to_text) + + df_financials.loc[len(df_financials)] = constructed_row + + return df_financials diff --git a/gamestonk_terminal/fundamental_analysis/market_watch_api.py b/gamestonk_terminal/fundamental_analysis/market_watch_view.py similarity index 70% rename from gamestonk_terminal/fundamental_analysis/market_watch_api.py rename to gamestonk_terminal/fundamental_analysis/market_watch_view.py index db94fcf0fbe..795f88e7b7c 100644 --- a/gamestonk_terminal/fundamental_analysis/market_watch_api.py +++ b/gamestonk_terminal/fundamental_analysis/market_watch_view.py @@ -1,12 +1,12 @@ -""" Fundamental Analysis Market Watch API """ +""" Fundamental Analysis Market Watch View """ __docformat__ = "numpy" import argparse -import requests +from typing import List import pandas as pd -from bs4 import BeautifulSoup + +from gamestonk_terminal.fundamental_analysis import market_watch_model as mwm from gamestonk_terminal.helper_funcs import ( - get_user_agent, parse_known_args_and_warn, patch_pandas_text_adjustment, financials_colored_values, @@ -14,7 +14,17 @@ from gamestonk_terminal.helper_funcs import ( from gamestonk_terminal import feature_flags as gtff -def income(l_args, s_ticker): +def income(other_args: List[str], ticker: str): + """Market Watch ticker income statement + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="income", @@ -50,11 +60,11 @@ def income(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - df_financials = prepare_df_financials(s_ticker, "income", ns_parser.b_quarter) + df_financials = mwm.prepare_df_financials(ticker, "income", ns_parser.b_quarter) if gtff.USE_COLOR: df_financials = df_financials.applymap(financials_colored_values) @@ -72,7 +82,17 @@ def income(l_args, s_ticker): return -def balance(l_args, s_ticker): +def balance(other_args: List[str], ticker: str): + """Market Watch ticker balance statement + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="balance", @@ -120,11 +140,13 @@ def balance(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - df_financials = prepare_df_financials(s_ticker, "balance", ns_parser.b_quarter) + df_financials = mwm.prepare_df_financials( + ticker, "balance", ns_parser.b_quarter + ) if gtff.USE_COLOR: df_financials = df_financials.applymap(financials_colored_values) @@ -142,7 +164,17 @@ def balance(l_args, s_ticker): return -def cash(l_args, s_ticker): +def cash(other_args: List[str], ticker: str): + """Market Watch ticker cash flow statement + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="cash_flow", @@ -186,11 +218,13 @@ def cash(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - df_financials = prepare_df_financials(s_ticker, "cashflow", ns_parser.b_quarter) + df_financials = mwm.prepare_df_financials( + ticker, "cashflow", ns_parser.b_quarter + ) if gtff.USE_COLOR: df_financials = df_financials.applymap(financials_colored_values) @@ -206,104 +240,3 @@ def cash(l_args, s_ticker): print(e) print("") return - - -def prepare_df_financials( - ticker: str, statement: str, quarter: bool = False -) -> pd.DataFrame: - """Builds a DataFrame with financial statements for a given company - - Parameters - ---------- - ticker : str - Company's stock ticker - statement : str - Either income, balance or cashflow - quarter : bool, optional - Return quarterly financial statements instead of annual, by default False - - Returns - ------- - pd.DataFrame - A DataFrame with financial info - - Raises - ------ - ValueError - If statement is not income, balance or cashflow - """ - financial_urls = { - "income": { - "quarter": "https://www.marketwatch.com/investing/stock/{}/financials/income/quarter", - "annual": "https://www.marketwatch.com/investing/stock/{}/financials/income", - }, - "balance": { - "quarter": "https://www.marketwatch.com/investing/stock/{}/financials/balance-sheet/quarter", - "annual": "https://www.marketwatch.com/investing/stock/{}/financials/balance-sheet", - }, - "cashflow": { - "quarter": "https://www.marketwatch.com/investing/stock/{}/financials/cash-flow/quarter", - "annual": "https://www.marketwatch.com/investing/stock/{}/financials/cash-flow", - }, - } - - if statement not in financial_urls.keys(): - raise ValueError(f"type {statement} is not in {financial_urls.keys()}") - - if quarter: - period = "quarter" - else: - period = "annual" - - text_soup_financials = BeautifulSoup( - requests.get( - financial_urls[statement][period].format(ticker), - headers={"User-Agent": get_user_agent()}, - ).text, - "lxml", - ) - - # Define financials columns - a_financials_header = list() - for financials_header in text_soup_financials.findAll( - "th", {"class": "overflow__heading"} - ): - a_financials_header.append(financials_header.text.strip("\n").split("\n")[0]) - - s_header_end_trend = ("5-year trend", "5- qtr trend")[quarter] - df_financials = pd.DataFrame( - columns=a_financials_header[0 : a_financials_header.index(s_header_end_trend)] - ) - - find_table = text_soup_financials.findAll( - "div", {"class": "element element--table table--fixed financials"} - ) - - if not find_table: - return df_financials - - financials_rows = find_table[0].findAll( - "tr", {"class": ["table__row is-highlighted", "table__row"]} - ) - - for a_row in financials_rows: - constructed_row = list() - financial_columns = a_row.findAll( - "td", {"class": ["overflow__cell", "overflow__cell fixed--column"]} - ) - - if not financial_columns: - continue - - for a_column in financial_columns: - column_to_text = a_column.text.strip() - if "\n" in column_to_text: - column_to_text = column_to_text.split("\n")[0] - - if column_to_text == "": - continue - constructed_row.append(column_to_text) - - df_financials.loc[len(df_financials)] = constructed_row - - return df_financials diff --git a/gamestonk_terminal/fundamental_analysis/yahoo_finance_api.py b/gamestonk_terminal/fundamental_analysis/yahoo_finance_view.py similarity index 85% rename from gamestonk_terminal/fundamental_analysis/yahoo_finance_api.py rename to gamestonk_terminal/fundamental_analysis/yahoo_finance_view.py index f7eef62eb8a..d2192875f17 100644 --- a/gamestonk_terminal/fundamental_analysis/yahoo_finance_api.py +++ b/gamestonk_terminal/fundamental_analysis/yahoo_finance_view.py @@ -1,7 +1,12 @@ +""" Yahoo Finance View """ +__docformat__ = "numpy" + import argparse +from typing import List from datetime import datetime import yfinance as yf import pandas as pd + from gamestonk_terminal.dataframe_helpers import clean_df_index from gamestonk_terminal.helper_funcs import ( long_number_format, @@ -9,7 +14,17 @@ from gamestonk_terminal.helper_funcs import ( ) -def info(l_args, s_ticker): +def info(other_args: List[str], ticker: str): + """Yahoo Finance ticker info + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="info", @@ -36,11 +51,11 @@ def info(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - stock = yf.Ticker(s_ticker) + stock = yf.Ticker(ticker) df_info = pd.DataFrame(stock.info.items(), columns=["Metric", "Value"]) df_info = df_info.set_index("Metric") @@ -86,7 +101,17 @@ def info(l_args, s_ticker): return -def shareholders(l_args, s_ticker): +def shareholders(other_args: List[str], ticker: str): + """Yahoo Finance ticker shareholders + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="shrs", @@ -95,11 +120,11 @@ def shareholders(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - stock = yf.Ticker(s_ticker) + stock = yf.Ticker(ticker) pd.set_option("display.max_colwidth", None) # Major holders @@ -154,7 +179,17 @@ def shareholders(l_args, s_ticker): return -def sustainability(l_args, s_ticker): +def sustainability(other_args: List[str], ticker: str): + """Yahoo Finance ticker sustainability + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="sust", @@ -169,17 +204,17 @@ def sustainability(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - stock = yf.Ticker(s_ticker) + stock = yf.Ticker(ticker) pd.set_option("display.max_colwidth", None) df_sustainability = stock.sustainability if not df_sustainability: - print(f"No sustainability information in Yahoo for {s_ticker}") + print(f"No sustainability information in Yahoo for {ticker}") print("") return @@ -209,7 +244,17 @@ def sustainability(l_args, s_ticker): return -def calendar_earnings(l_args, s_ticker): +def calendar_earnings(other_args: List[str], ticker: str): + """Yahoo Finance ticker calendar earnings + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + parser = argparse.ArgumentParser( add_help=False, prog="cal", @@ -220,15 +265,15 @@ def calendar_earnings(l_args, s_ticker): ) try: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - stock = yf.Ticker(s_ticker) + stock = yf.Ticker(ticker) df_calendar = stock.calendar if df_calendar.empty: - print(f"No earnings calendar information in Yahoo for {s_ticker}") + print(f"No earnings calendar information in Yahoo for {ticker}") print("") return diff --git a/tests/data/fa_market_watch_api.yaml b/tests/data/fa_market_watch_model.yaml similarity index 100% rename from tests/data/fa_market_watch_api.yaml rename to tests/data/fa_market_watch_model.yaml diff --git a/tests/test_fa_market_watch_api_unit.py b/tests/test_fa_market_watch_model.py similarity index 86% rename from tests/test_fa_market_watch_api_unit.py rename to tests/test_fa_market_watch_model.py index b48d03445d5..4e671236f00 100644 --- a/tests/test_fa_market_watch_api_unit.py +++ b/tests/test_fa_market_watch_model.py @@ -8,7 +8,7 @@ from gamestonk_terminal.test_helper import ( # noqa: F401 pytest_generate_tests, ) -from gamestonk_terminal.fundamental_analysis.market_watch_api import ( +from gamestonk_terminal.fundamental_analysis.market_watch_model import ( prepare_df_financials, ) @@ -16,10 +16,10 @@ assertions = unittest.TestCase("__init__") class TestFaMarketWatchApiUnit: - @mock.patch("gamestonk_terminal.fundamental_analysis.market_watch_api.requests") + @mock.patch("gamestonk_terminal.fundamental_analysis.market_watch_model.requests") @parameterize_from_file( "test_prepare_df_financials", - "../tests/data/fa_market_watch_api.yaml", + "../tests/data/fa_market_watch_model.yaml", ) # pylint: disable=too-many-arguments def test_prepare_df_financials( diff --git a/tests/test_fa_market_watch_api.py b/tests/test_fa_market_watch_view.py similarity index 69% rename from tests/test_fa_market_watch_api.py rename to tests/test_fa_market_watch_view.py index da8057c5d38..9ebe411fdb3 100644 --- a/tests/test_fa_market_watch_api.py +++ b/tests/test_fa_market_watch_view.py @@ -1,7 +1,7 @@ """ fundamental_analysis/market_watch_api.py tests """ import unittest -from gamestonk_terminal.fundamental_analysis.market_watch_api import income +from gamestonk_terminal.fundamental_analysis.market_watch_view import income class TestFaMarketWatchApi(unittest.TestCase): diff --git a/tests/test_fa_yahoo_finance_api.py b/tests/test_fa_yahoo_finance_view.py similarity index 84% rename from tests/test_fa_yahoo_finance_api.py rename to tests/test_fa_yahoo_finance_view.py index 211c2f006d4..fb068647595 100644 --- a/tests/test_fa_yahoo_finance_api.py +++ b/tests/test_fa_yahoo_finance_view.py @@ -2,7 +2,7 @@ import unittest # pylint: disable=unused-import -from gamestonk_terminal.fundamental_analysis.yahoo_finance_api import ( # noqa: F401 +from gamestonk_terminal.fundamental_analysis.yahoo_finance_view import ( # noqa: F401 info, sustainability, calendar_earnings, From 2658a017fe8b17056960213c9b8bc3ae7e1cdaec Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 19 Apr 2021 16:37:29 -0400 Subject: [PATCH 046/114] update -d type and readme --- gamestonk_terminal/options/README.md | 12 +----------- gamestonk_terminal/options/chains_view.py | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/gamestonk_terminal/options/README.md b/gamestonk_terminal/options/README.md index 842f95859f5..536ba329147 100644 --- a/gamestonk_terminal/options/README.md +++ b/gamestonk_terminal/options/README.md @@ -84,17 +84,7 @@ Display options chains. [Source: Tradier] * --puts : Flag to show puts only * -m : Minimum strike price to consider. * -M : Maximum strike price to consider. -* -d : Columns to display. Should be comma separated. Must be in `['bid', 'ask', 'strike', 'bidsize', 'asksize', 'volume', 'open_interest', - 'delta', 'gamma', 'theta', 'vega', 'ask_iv', 'bid_iv','mid_iv']` +* -d : Columns to display. Should be comma separated. Must be in * -d : Columns to display from the following selection: bid, ask, strike, bidsize, asksize, volume, open_interest, delta, gamma, theta, vega, ask_iv, bid_iv, mid_iv. Default: mid_iv,vega_theta_gamma,delta,volume,open_interest,bid,ask. Note that they are separated by comma. chains - -To change what columns are displayed, one can use the `-d` flag. To show the same as above, but only the ask, ask size -delta and theta variables, we would do: -```` -chains -m 129 -M 135 -d ask,ask_size,delta,theta -```` -Which outputs -![im2](https://user-images.githubusercontent.com/18151143/115276719-640cab80-a111-11eb-84a2-4dc6a1685946.png) - diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index 3fd5aacddb6..2ae85fba4af 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -40,6 +40,16 @@ default_columns = [ ] +def check_valid_option_chains_headers(headers: str) -> str: + columns = [str(item) for item in headers.split(",")] + + for header in columns: + if header not in df_columns: + raise argparse.ArgumentTypeError("Invalid option chains header selected!") + + return columns + + def process_chains(response: requests.models.Response) -> pd.DataFrame: """ Function to take in the requests.get and return a DataFrame @@ -141,7 +151,9 @@ def display_chains(symbol: str, expiry: str, other_args: List[str]): "--display", dest="to_display", default=default_columns, - help="columns to look at", + type=check_valid_option_chains_headers, + help="columns to look at. Columns can be: {bid, ask, strike, bidsize, asksize, volume, open_interest, delta, " + "gamma, theta, vega, ask_iv, bid_iv, mid_iv} ", ) chains_df = get_option_chains(symbol, expiry) @@ -150,11 +162,7 @@ def display_chains(symbol: str, expiry: str, other_args: List[str]): ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return - if isinstance(ns_parser.to_display, str): - columns = list(ns_parser.to_display.split(",")) + ["strike", "option_type"] - if isinstance(ns_parser.to_display, list): - columns = ns_parser.to_display + ["strike", "option_type"] - + columns = ns_parser.to_display + ["strike", "option_type"] chains_df = chains_df[columns].rename(columns=column_map) if ns_parser.max_sp == -1 and ns_parser.min_sp == -1: min_strike = np.percentile(chains_df["strike"], 25) From 19302c9558c62e8bb5a2b37985113a5bfc89a877 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 19 Apr 2021 16:38:39 -0400 Subject: [PATCH 047/114] correct default order to avoid merge conflict --- gamestonk_terminal/options/chains_view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index 2ae85fba4af..b1c30a4609b 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -30,9 +30,9 @@ column_map = {"mid_iv": "iv", "open_interest": "oi", "volume": "vol"} default_columns = [ "mid_iv", "vega", - "theta", - "gamma", "delta", + "gamma", + "theta", "volume", "open_interest", "bid", From 9fd31e97c917b120237126425f03bcb9efbd2349 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 19 Apr 2021 16:49:40 -0400 Subject: [PATCH 048/114] mypy --- gamestonk_terminal/options/chains_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index b1c30a4609b..c038daa36a0 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -40,7 +40,7 @@ default_columns = [ ] -def check_valid_option_chains_headers(headers: str) -> str: +def check_valid_option_chains_headers(headers: List[str]) -> str: columns = [str(item) for item in headers.split(",")] for header in columns: From 1b10ade46fe2f48653f880afb6a7b042fc5b979e Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 15:43:29 -0700 Subject: [PATCH 049/114] Fix filemod --- gamestonk_terminal/discovery/marketbeat_model.py | 0 gamestonk_terminal/discovery/seeking_alpha_model.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 gamestonk_terminal/discovery/marketbeat_model.py mode change 100755 => 100644 gamestonk_terminal/discovery/seeking_alpha_model.py diff --git a/gamestonk_terminal/discovery/marketbeat_model.py b/gamestonk_terminal/discovery/marketbeat_model.py old mode 100755 new mode 100644 diff --git a/gamestonk_terminal/discovery/seeking_alpha_model.py b/gamestonk_terminal/discovery/seeking_alpha_model.py old mode 100755 new mode 100644 From eb842ead704503f806e77298192cd24fabf1f090 Mon Sep 17 00:00:00 2001 From: Jamie Date: Mon, 19 Apr 2021 18:47:42 -0400 Subject: [PATCH 050/114] mypy again --- gamestonk_terminal/options/chains_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/options/chains_view.py b/gamestonk_terminal/options/chains_view.py index c038daa36a0..b87b57460b6 100644 --- a/gamestonk_terminal/options/chains_view.py +++ b/gamestonk_terminal/options/chains_view.py @@ -40,7 +40,7 @@ default_columns = [ ] -def check_valid_option_chains_headers(headers: List[str]) -> str: +def check_valid_option_chains_headers(headers: str) -> List[str]: columns = [str(item) for item in headers.split(",")] for header in columns: From 00ff6e0ad3fd6e9debad6d6cfaef199267e0b384 Mon Sep 17 00:00:00 2001 From: didier Date: Mon, 19 Apr 2021 23:51:31 +0100 Subject: [PATCH 051/114] improve fx_view code --- gamestonk_terminal/forex/fx_controller.py | 42 +-- gamestonk_terminal/forex/fx_view.py | 362 ++++++++++------------ 2 files changed, 193 insertions(+), 211 deletions(-) diff --git a/gamestonk_terminal/forex/fx_controller.py b/gamestonk_terminal/forex/fx_controller.py index 3b96f5c2911..b1ab4dc7c68 100644 --- a/gamestonk_terminal/forex/fx_controller.py +++ b/gamestonk_terminal/forex/fx_controller.py @@ -47,29 +47,29 @@ class ForexController: """Print help""" print("\nForex Mode:") - print(" help Show this menu again") - print(" q Quit this menu and goes back to main menu") - print(" quit Quit to abandon program") + print(" help show this menu again") + print(" q quit this menu and goes back to main menu") + print(" quit quit to abandon program") print("") - if self.instrument is not None: - print("Currently loaded instrument " + self.instrument) - print(" load Load an instrument to use") - print(" summary Shows account summary") - print(" calendar Show calendar") - print(" list List order history") - print(" pending Get information on pending orders") - print(" cancel Cancel a pending order by ID -i order ID") - print(" positions Get open positions") - print(" trades List open trades") - print(" closetrade Close a trade by id") + print(" summary shows account summary") + print(" calendar show calendar") + print(" list list order history") + print(" pending get information on pending orders") + print(" cancel cancel a pending order by ID -i order ID") + print(" positions get open positions") + print(" trades list open trades") + print(" closetrade close a trade by id") + print("") + print(f"Loaded instrument: {self.instrument if self.instrument else ''}") + print("") + print(" load load an instrument to use") + if self.instrument: + print(" candles show candles") + print(" price shows price for selected instrument") + print(" order place limit order -u # of units -p price") + print(" orderbook print orderbook") + print(" positionbook print positionbook") print("") - if self.instrument is not None: - print(" candles Show candles") - print(" price Shows price for selected instrument") - print(" order Place limit order -u # of units -p price") - print(" orderbook Print orderbook") - print(" positionbook Print positionbook") - print("") def switch(self, an_input: str): """Process and dispatch input diff --git a/gamestonk_terminal/forex/fx_view.py b/gamestonk_terminal/forex/fx_view.py index fd8b0668cb9..ca5742e5640 100644 --- a/gamestonk_terminal/forex/fx_view.py +++ b/gamestonk_terminal/forex/fx_view.py @@ -44,11 +44,10 @@ def get_fx_price(accountID, instrument, other_args: List[str]): print(instrument + " Bid: " + bid) print(instrument + " Ask: " + ask) print("") + except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["message"], "\n") def get_account_summary(accountID, other_args: List[str]): @@ -64,35 +63,46 @@ def get_account_summary(accountID, other_args: List[str]): try: request = accounts.AccountSummary(accountID=accountID) response = client.request(request) - balance = response["account"]["balance"] - margin_available = response["account"]["marginAvailable"] - margin_closeout = response["account"]["marginCloseoutNAV"] - margin_closeout_percent = response["account"]["marginCloseoutPercent"] - margin_closeout_position_value = response["account"][ - "marginCloseoutPositionValue" - ] - margin_used = response["account"]["marginUsed"] - net_asset_value = response["account"]["NAV"] - open_trade_count = response["account"]["openTradeCount"] - total_pl = response["account"]["pl"] - unrealized_pl = response["account"]["unrealizedPL"] - print(f"Balance: {balance}") - print(f"NAV: {net_asset_value}") - print(f"Unrealized P/L: {unrealized_pl}") - print(f"Total P/L: {total_pl}") - print(f"Open Trade Count: {open_trade_count}") - print(f"Margin Available: ${margin_available}") - print(f"Margin Used: ${margin_used}") - print(f"Margin Closeout {margin_closeout}") - print(f"Margin Closeout Percent: {margin_closeout_percent}") - print(f"Margin Closeout Position Value: {margin_closeout_position_value}") + df_summary = pd.DataFrame( + [ + {"Type": "Balance", "Value": response["account"]["balance"]}, + {"Type": "NAV", "Value": response["account"]["NAV"]}, + { + "Type": "Unrealized P/L", + "Value": response["account"]["unrealizedPL"], + }, + {"Type": "Total P/L", "Value": response["account"]["pl"]}, + { + "Type": "Open Trade Count", + "Value": response["account"]["openTradeCount"], + }, + { + "Type": "Margin Available", + "Value": response["account"]["marginAvailable"], + }, + {"Type": "Margin Used", "Value": response["account"]["marginUsed"]}, + { + "Type": "Margin Closeout", + "Value": response["account"]["marginCloseoutNAV"], + }, + { + "Type": "Margin Closeout Percent", + "Value": response["account"]["marginCloseoutPercent"], + }, + { + "Type": "Margin Closeout Position Value", + "Value": response["account"]["marginCloseoutPositionValue"], + }, + ] + ) + + print(df_summary.to_string(index=False, header=False)) + print("") except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") def list_orders(accountID, other_args: List[str]): @@ -130,20 +140,18 @@ def list_orders(accountID, other_args: List[str]): try: request = orders.OrderList(accountID, parameters) response = client.request(request) - try: - df = pd.DataFrame.from_dict(response["orders"]) - df = df[["id", "instrument", "units", "price", "state", "type"]] - print(df) - print("") - except KeyError: - print("No orders were found") - print("") - except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) + + df = pd.DataFrame.from_dict(response["orders"]) + df = df[["id", "instrument", "units", "price", "state", "type"]] + print(df) print("") + except KeyError: + print("No orders were found\n") + except V20Error as e: + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") + def get_order_book(instrument, other_args): parser = argparse.ArgumentParser( @@ -166,11 +174,10 @@ def get_order_book(instrument, other_args): df = df.take(range(527, 727, 1)) book_plot(df, instrument, "Order Book") print("") + except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") def get_position_book(instrument, other_args): @@ -191,11 +198,10 @@ def get_position_book(instrument, other_args): df = df.take(range(219, 415, 1)) book_plot(df, instrument, "Position Book") print("") + except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") def create_order(accountID, instrument, other_args: List[str]): @@ -242,45 +248,37 @@ def create_order(accountID, instrument, other_args: List[str]): try: request = orders.OrderCreate(accountID, data) response = client.request(request) - try: - if "orderFillTransaction" in response["orderCreateTransaction"]: - order_id = response["orderCreateTransaction"]["orderFillTransaction"][ - "id" - ] - order_instrument = response["orderCreateTransaction"][ - "orderFillTransaction" - ]["instrument"] - units = response["orderCreateTransaction"]["orderFillTransaction"][ - "units" - ] - price = response["orderCreateTransaction"]["orderFillTransaction"][ - "price" - ] - print("Order Filled:") - print(f"ID: {order_id}") - print(f"Instrument: {order_instrument}") - print(f"Units: {units}") - print(f"Price: {price}") - print("") - else: - order_creation_id = response["orderCreateTransaction"]["id"] - order_instrument = response["orderCreateTransaction"]["instrument"] - units = response["orderCreateTransaction"]["units"] - price = response["orderCreateTransaction"]["price"] - print("Order created:") - print(f"ID: {order_creation_id}") - print(f"Instrument: {order_instrument}") - print(f"Units: {units}") - print(f"Price: {price}") - print("") - except Exception as e: - print(e) + if "orderFillTransaction" in response["orderCreateTransaction"]: + order_id = response["orderCreateTransaction"]["orderFillTransaction"]["id"] + order_instrument = response["orderCreateTransaction"][ + "orderFillTransaction" + ]["instrument"] + units = response["orderCreateTransaction"]["orderFillTransaction"]["units"] + price = response["orderCreateTransaction"]["orderFillTransaction"]["price"] + print("Order Filled:") + print(f"ID: {order_id}") + print(f"Instrument: {order_instrument}") + print(f"Units: {units}") + print(f"Price: {price}") + print("") + else: + order_creation_id = response["orderCreateTransaction"]["id"] + order_instrument = response["orderCreateTransaction"]["instrument"] + units = response["orderCreateTransaction"]["units"] + price = response["orderCreateTransaction"]["price"] + print("Order created:") + print(f"ID: {order_creation_id}") + print(f"Instrument: {order_instrument}") + print(f"Units: {units}") + print(f"Price: {price}") + print("") + + except Exception as e: + print(e) except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["message"], "\n") def cancel_pending_order(accountID, other_args: List[str]): @@ -310,10 +308,8 @@ def cancel_pending_order(accountID, other_args: List[str]): print(f"Order {order_id} canceled.") print("") except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") def get_pending_orders(accountID, other_args): @@ -330,28 +326,23 @@ def get_pending_orders(accountID, other_args): request = orders.OrdersPending(accountID) response = client.request(request) for i in range(len(response["orders"])): - try: - order_id = response["orders"][i]["id"] - instrument = response["orders"][i]["instrument"] - price = response["orders"][i]["price"] - units = response["orders"][i]["units"] - create_time = response["orders"][i]["createTime"] - time_in_force = response["orders"][i]["timeInForce"] - print(f"Order ID: {order_id}") - print(f"Instrument: {instrument}") - print(f"Price: {price}") - print(f"Units: {units}") - print(f"Time created: {create_time}") - print(f"Time in force: {time_in_force}") - print("-" * 30) - except IndexError: - break + order_id = response["orders"][i]["id"] + instrument = response["orders"][i]["instrument"] + price = response["orders"][i]["price"] + units = response["orders"][i]["units"] + create_time = response["orders"][i]["createTime"] + time_in_force = response["orders"][i]["timeInForce"] + print(f"Order ID: {order_id}") + print(f"Instrument: {instrument}") + print(f"Price: {price}") + print(f"Units: {units}") + print(f"Time created: {create_time}") + print(f"Time in force: {time_in_force}") + print("-" * 30) print("") except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") def get_open_positions(accountID, other_args): @@ -383,11 +374,10 @@ def get_open_positions(accountID, other_args): print(f"Short Unrealized P/L: {short_upl}") print("-" * 30 + "\n") print("") + except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") def get_open_trades(accountID, other_args): @@ -467,40 +457,33 @@ def close_trade(accountID, other_args: List[str]): ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return + data = {} if ns_parser.units is not None: data["units"] = (ns_parser.units,) try: request = trades.TradeClose(accountID, ns_parser.orderID, data) response = client.request(request) - try: - order_id = response["orderCreateTransaction"]["tradeClose"]["tradeID"] - order_instrument = response["orderFillTransaction"]["instrument"] - units = response["orderCreateTransaction"]["units"] - price = response["orderFillTransaction"]["price"] - pl = response["orderFillTransaction"]["pl"] - print("Order closed:") - print(f"ID: {order_id}") - print(f"Instrument: {order_instrument}") - print(f"Units: {units}") - print(f"Price: {price}") - print(f"P/L: {pl}") - print("") - except Exception as e: - print(e) - print("") + order_id = response["orderCreateTransaction"]["tradeClose"]["tradeID"] + order_instrument = response["orderFillTransaction"]["instrument"] + units = response["orderCreateTransaction"]["units"] + price = response["orderFillTransaction"]["price"] + pl = response["orderFillTransaction"]["pl"] + print("Order closed:") + print(f"ID: {order_id}") + print(f"Instrument: {order_instrument}") + print(f"Units: {units}") + print(f"Price: {price}") + print(f"P/L: {pl}") + print("") + + except Exception as e: + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") except V20Error as e: - if "orderRejectTransaction" in e.msg: - msg_length = len(e.msg) - order_id = e.msg[355 : msg_length - 149] - print(f"Order ID {order_id} doesn't exist") - print("") - else: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") def show_candles(accountID, instrument, other_args: List[str]): @@ -558,10 +541,8 @@ def show_candles(accountID, instrument, other_args: List[str]): ) print("") except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) - print("") + d_error = eval(e.msg) + print(d_error["errorMessage"], "\n") def process_candle_response(response): @@ -624,59 +605,57 @@ def calendar(instrument, other_args: List[str]): try: request = labs.Calendar(params=parameters) response = client.request(request) + + l_data = [] for i in range(len(response)): - if "title" in response[i]: - title = response[i]["title"] - print(f"Title: {title}") - if "timestamp" in response[i]: - timestamp = response[i]["timestamp"] - time = datetime.fromtimestamp(timestamp) - print(f"Time: {time}") - if "impact" in response[i]: - impact = response[i]["impact"] - print(f"Impact: {impact}") if "forecast" in response[i]: forecast = response[i]["forecast"] - unit = response[i]["unit"] - if unit != "Index": - print(f"Forecast: {forecast}{unit}") - else: - print(f"Forecast: {forecast}") + if response[i]["unit"] != "Index": + forecast += response[i]["unit"] + else: + forecast = "" + if "market" in response[i]: market = response[i]["market"] - unit = response[i]["unit"] - if unit != "Index": - print(f"Market Forecast: {market}{unit}") - else: - print(f"Market Forecast: {market}") - if "currency" in response[i]: - currency = response[i]["currency"] - print(f"Currency: {currency}") - if "region" in response[i]: - region = response[i]["region"] - print(f"Region: {region}") + if response[i]["unit"] != "Index": + market += response[i]["unit"] + else: + market = "" + if "actual" in response[i]: actual = response[i]["actual"] - unit = response[i]["unit"] - if unit != "Index": - print(f"Actual: {actual}{unit}") - else: - print(f"Actual: {actual}") + if response[i]["unit"] != "Index": + actual += response[i]["unit"] + else: + actual = "" + if "previous" in response[i]: previous = response[i]["previous"] - unit = response[i]["unit"] - if unit != "Index": - print(f"Previous: {previous}{unit}") - else: - print(f"Previous: {previous}") - print("-" * 30) - print("") - except V20Error as e: - msg_length = len(e.msg) - msg = e.msg[17 : msg_length - 2] - print(msg) + if response[i]["unit"] != "Index": + previous += response[i]["unit"] + else: + previous = "" + + l_data.append( + { + "Title": response[i]["title"], + "Time": datetime.fromtimestamp(response[i]["timestamp"]), + "Impact": response[i]["impact"], + "Forecast": forecast, + "Market Forecast": market, + "Currency": response[i]["currency"], + "Region": response[i]["region"], + "Actual": actual, + "Previous": previous, + } + ) + + print(pd.DataFrame(l_data).to_string(index=False)) print("") - print("") + + except V20Error as e: + d_error = eval(e.msg) + print(d_error["message"], "\n") def load(other_args: List[str]): @@ -702,12 +681,15 @@ def load(other_args: List[str]): other_args.insert(0, "-i") ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: return + + print("") return ns_parser.instrument.upper() + except Exception as e: - print(e) + print(e, "\n") + return None def book_plot(df, instrument, book_type): From 99bbcb6a319a1441b33e2d7a120470fb9fd81e89 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 15:55:46 -0700 Subject: [PATCH 052/114] Add start and exit test --- .github/workflows/Mac.yml | 5 +++++ .github/workflows/test.yml | 11 +++++++++++ .github/workflows/windows.yml | 4 ++++ gamestonk_terminal/feature_flags.py | 3 +++ terminal.py | 4 ++++ 5 files changed, 27 insertions(+) diff --git a/.github/workflows/Mac.yml b/.github/workflows/Mac.yml index 75a8a6f540b..6459d5b055a 100644 --- a/.github/workflows/Mac.yml +++ b/.github/workflows/Mac.yml @@ -2,6 +2,7 @@ name: Mac OS X Full Clean Build with ML env: GTFF_USE_PROMPT_TOOLKIT: false GTFF_USE_ION: false + GTFF_ENABLE_QUICK_EXIT: true on: push: branches: @@ -63,3 +64,7 @@ jobs: - name: Run tests (Bash) shell: bash -l {0} run: pytest tests/ + + - name: Start Terminal and exit + shell: bash -l {0} + run: python terminal.py diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 17f52d31bea..5e6ead3f4d6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,6 +2,7 @@ name: Tests env: GTFF_USE_PROMPT_TOOLKIT: false GTFF_USE_ION: false + GTFF_ENABLE_QUICK_EXIT: true on: [pull_request, push] jobs: linting: @@ -72,6 +73,9 @@ jobs: run: | source $VENV pytest tests/ + + - name: Start Terminal and exit + run: python terminal.py tests-python: name: Python (${{ matrix.python-version }}, ${{ matrix.os }}) needs: test @@ -120,6 +124,9 @@ jobs: run: | source $VENV pytest tests/ + + - name: Start Terminal and exit + run: python terminal.py tests-conda: name: Conda (${{ matrix.python-version }}, ${{ matrix.os }}) needs: test @@ -187,3 +194,7 @@ jobs: - name: Run tests (Bash) shell: bash -l {0} run: pytest tests/ + + - name: Start Terminal and exit + shell: bash -l {0} + run: python terminal.py diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 93723499e8c..d66f19c6e73 100755 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -2,6 +2,7 @@ name: Windows 10 Full Clean Build with ML env: GTFF_USE_PROMPT_TOOLKIT: false GTFF_USE_ION: false + GTFF_ENABLE_QUICK_EXIT: true on: push: branches: @@ -72,3 +73,6 @@ jobs: shell: bash -l {0} run: pytest tests/ + - name: Start Terminal and exit + shell: bash -l {0} + run: python terminal.py diff --git a/gamestonk_terminal/feature_flags.py b/gamestonk_terminal/feature_flags.py index 5c4910a1ab2..6cea32c0c28 100644 --- a/gamestonk_terminal/feature_flags.py +++ b/gamestonk_terminal/feature_flags.py @@ -24,3 +24,6 @@ USE_PLOT_AUTOSCALING = strtobool(os.getenv("GTFF_USE_PLOT_AUTOSCALING", "False") # Enable thoughts of the day ENABLE_THOUGHTS_DAY = strtobool(os.getenv("GTFF_ENABLE_THOUGHTS_DAY", "False")) + +# Quick exit for testing +ENABLE_QUICK_EXIT = strtobool(os.getenv("GTFF_ENABLE_QUICK_EXIT", "False")) diff --git a/terminal.py b/terminal.py index 6f637eba85e..e39ba1ff2b9 100644 --- a/terminal.py +++ b/terminal.py @@ -115,6 +115,10 @@ def main(): print_help(s_ticker, s_start, s_interval, b_is_stock_market_open()) should_print_help = False + if gtff.ENABLE_QUICK_EXIT: + print("Quick exit enabled") + break + # Get input command from stdin or user if not parsed_stdin and len(sys.argv) > 1: as_input = " ".join(sys.argv[1:]) From 9e2da2d4731c3c12846e7b62a1bd203f44ffb9b5 Mon Sep 17 00:00:00 2001 From: didier Date: Tue, 20 Apr 2021 00:01:56 +0100 Subject: [PATCH 053/114] fix mypy --- gamestonk_terminal/forex/fx_view.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gamestonk_terminal/forex/fx_view.py b/gamestonk_terminal/forex/fx_view.py index ca5742e5640..63f378495aa 100644 --- a/gamestonk_terminal/forex/fx_view.py +++ b/gamestonk_terminal/forex/fx_view.py @@ -479,8 +479,7 @@ def close_trade(accountID, other_args: List[str]): print("") except Exception as e: - d_error = eval(e.msg) - print(d_error["errorMessage"], "\n") + print(e, "\n") except V20Error as e: d_error = eval(e.msg) print(d_error["errorMessage"], "\n") From 4fae397a90f6d1405adc84aa77be45d32065dd2f Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 16:08:31 -0700 Subject: [PATCH 054/114] Updating poetry dependencies and requirements.txt --- poetry.lock | 758 +++++++++++++++++++++--------------------- requirements-full.txt | 125 ++++--- requirements.txt | 105 +++--- 3 files changed, 519 insertions(+), 469 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0a01734d46e..a2faa511bcd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -31,7 +31,7 @@ speedups = ["aiodns", "brotlipy", "cchardet"] [[package]] name = "alpaca-trade-api" -version = "1.1.0" +version = "1.2.0" description = "Alpaca API python client" category = "main" optional = false @@ -104,7 +104,7 @@ tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"] [[package]] name = "astroid" -version = "2.5.1" +version = "2.5.3" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false @@ -225,7 +225,7 @@ webencodings = "*" [[package]] name = "bpemb" -version = "0.3.2" +version = "0.3.3" description = "Byte-pair embeddings in 275 languages" category = "main" optional = true @@ -354,7 +354,7 @@ test = ["coverage"] [[package]] name = "cryptography" -version = "3.4.6" +version = "3.4.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false @@ -530,23 +530,26 @@ python-versions = "*" [[package]] name = "finviz" -version = "1.3.4" -description = "Unofficial API for finviz.com" +version = "1.4.1" +description = "Unofficial API for FinViz.com" category = "main" optional = false python-versions = "*" [package.dependencies] aiohttp = "*" +beautifulsoup4 = "*" cssselect = "*" lxml = "*" requests = "*" +tenacity = "*" +tqdm = "*" urllib3 = "*" user_agent = "*" [[package]] name = "finvizfinance" -version = "0.9.3" +version = "0.9.6" description = "Finviz Finance. Information downloader." category = "main" optional = false @@ -593,7 +596,7 @@ transformers = ">=3.5.0,<=3.5.1" [[package]] name = "flake8" -version = "3.9.0" +version = "3.9.1" description = "the modular source code checker: pep8 pyflakes and co" category = "dev" optional = false @@ -626,18 +629,21 @@ pandas = "*" [[package]] name = "ftfy" -version = "5.9" +version = "6.0.1" description = "Fixes some problems with Unicode text after the fact" category = "main" optional = true -python-versions = ">=3.5" +python-versions = ">=3.6" [package.dependencies] wcwidth = "*" +[package.extras] +docs = ["furo", "sphinx"] + [[package]] name = "fundamentalanalysis" -version = "0.2.6" +version = "0.2.7" description = "Fully-fledged Fundamental Analysis package capable of collecting 20 years of Company Profiles, Financial Statements, Ratios and Stock Data of 13.000+ companies." category = "main" optional = false @@ -695,7 +701,7 @@ test-win = ["pytest", "pytest-rerunfailures", "mock", "cython", "testfixtures", [[package]] name = "google-auth" -version = "1.28.0" +version = "1.29.0" description = "Google Authentication Library" category = "main" optional = true @@ -710,10 +716,11 @@ six = ">=1.9.0" [package.extras] aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)"] pyopenssl = ["pyopenssl (>=20.0.0)"] +reauth = ["pyu2f (>=0.1.5)"] [[package]] name = "google-auth-oauthlib" -version = "0.4.3" +version = "0.4.4" description = "Google Authentication Library" category = "main" optional = true @@ -830,7 +837,7 @@ idna = ">=2.0" [[package]] name = "importlib-metadata" -version = "3.7.3" +version = "4.0.0" description = "Read metadata from Python packages" category = "main" optional = false @@ -842,7 +849,7 @@ zipp = ">=0.5" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] [[package]] name = "inflection" @@ -862,7 +869,7 @@ python-versions = "*" [[package]] name = "ipykernel" -version = "5.5.0" +version = "5.5.3" description = "IPython Kernel for Jupyter" category = "main" optional = false @@ -946,7 +953,7 @@ python-versions = "*" [[package]] name = "isort" -version = "5.7.0" +version = "5.8.0" description = "A Python utility / library to sort Python imports." category = "dev" optional = false @@ -999,7 +1006,7 @@ name = "joblib" version = "1.0.1" description = "Lightweight pipelining with Python functions" category = "main" -optional = true +optional = false python-versions = ">=3.6" [[package]] @@ -1038,14 +1045,15 @@ qtconsole = "*" [[package]] name = "jupyter-client" -version = "6.1.12" +version = "6.2.0" description = "Jupyter protocol implementation and client libraries" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6.1" [package.dependencies] jupyter-core = ">=4.6.0" +nest-asyncio = ">=1.5" python-dateutil = ">=2.1" pyzmq = ">=13" tornado = ">=4.1" @@ -1053,11 +1061,11 @@ traitlets = "*" [package.extras] doc = ["sphinx (>=1.3.6)", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] -test = ["async-generator", "ipykernel", "ipython", "mock", "pytest-asyncio", "pytest-timeout", "pytest", "jedi (<0.18)"] +test = ["async-generator", "ipykernel", "ipython", "mock", "pytest-asyncio", "pytest-timeout", "pytest", "mypy", "pre-commit", "jedi (<0.18)"] [[package]] name = "jupyter-console" -version = "6.3.0" +version = "6.4.0" description = "Jupyter terminal console" category = "main" optional = false @@ -1131,16 +1139,14 @@ python-versions = ">=3.6" [[package]] name = "konoha" -version = "4.6.4" +version = "4.6.3" description = "A tiny sentence/word tokenizer for Japanese text written in Python" category = "main" optional = true python-versions = ">=3.6.1,<4.0.0" [package.dependencies] -importlib-metadata = ">=3.7.0,<4.0.0" overrides = ">=3.0.0,<4.0.0" -requests = ">=2.25.1,<3.0.0" [package.extras] janome = ["janome (>=0.3.10,<0.4.0)"] @@ -1177,11 +1183,11 @@ six = "*" [[package]] name = "lazy-object-proxy" -version = "1.5.2" +version = "1.6.0" description = "A fast and thorough lazy object proxy." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [[package]] name = "lunarcalendar" @@ -1198,7 +1204,7 @@ pytz = "*" [[package]] name = "lxml" -version = "4.6.2" +version = "4.6.3" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." category = "main" optional = false @@ -1295,7 +1301,7 @@ python-versions = "*" [[package]] name = "mplfinance" -version = "0.12.7a10" +version = "0.12.7a12" description = "Utilities for the visualization, and visual analysis, of financial data" category = "main" optional = false @@ -1405,7 +1411,7 @@ webpdf = ["pyppeteer (==0.2.2)"] [[package]] name = "nbformat" -version = "5.1.2" +version = "5.1.3" description = "The Jupyter Notebook format" category = "main" optional = false @@ -1431,14 +1437,14 @@ python-versions = ">=3.5" [[package]] name = "networkx" -version = "2.5" +version = "2.5.1" description = "Python package for creating and manipulating graphs and networks" category = "main" optional = true python-versions = ">=3.6" [package.dependencies] -decorator = ">=4.3.0" +decorator = ">=4.3,<5" [package.extras] all = ["numpy", "scipy", "pandas", "matplotlib", "pygraphviz", "pydot", "pyyaml", "lxml", "pytest"] @@ -1455,11 +1461,11 @@ scipy = ["scipy"] [[package]] name = "notebook" -version = "6.2.0" +version = "6.3.0" description = "A web-based notebook environment for interactive computing" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" [package.dependencies] argon2-cffi = "*" @@ -1620,7 +1626,7 @@ test = ["boto3", "botocore", "codecov", "coverage", "google-compute-engine", "ip [[package]] name = "parso" -version = "0.8.1" +version = "0.8.2" description = "A Python Parser" category = "main" optional = false @@ -1775,18 +1781,18 @@ tests = ["pytest", "pytest-cov"] [[package]] name = "prometheus-client" -version = "0.9.0" +version = "0.10.1" description = "Python client for the Prometheus monitoring system." category = "main" optional = false -python-versions = "*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.extras] twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.17" +version = "3.0.18" description = "Library for building powerful interactive command lines in Python" category = "main" optional = false @@ -1797,7 +1803,7 @@ wcwidth = "*" [[package]] name = "protobuf" -version = "3.15.6" +version = "3.15.8" description = "Protocol Buffers" category = "main" optional = true @@ -1876,7 +1882,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pycoingecko" -version = "1.4.0" +version = "1.4.1" description = "Python wrapper around the CoinGecko API" category = "main" optional = false @@ -1895,7 +1901,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pyflakes" -version = "2.3.0" +version = "2.3.1" description = "passive checker of Python programs" category = "dev" optional = false @@ -1911,14 +1917,14 @@ python-versions = ">=3.5" [[package]] name = "pylint" -version = "2.7.2" +version = "2.7.4" description = "python code static checker" category = "dev" optional = false python-versions = "~=3.6" [package.dependencies] -astroid = ">=2.5.1,<2.6" +astroid = ">=2.5.2,<2.7" colorama = {version = "*", markers = "sys_platform == \"win32\""} isort = ">=4.2.5,<6" mccabe = ">=0.6,<0.7" @@ -2020,7 +2026,7 @@ numpy = ">=1.7" [[package]] name = "pytest" -version = "6.2.2" +version = "6.2.3" description = "pytest: simple powerful testing with Python" category = "dev" optional = false @@ -2053,8 +2059,8 @@ six = ">=1.5" [[package]] name = "python-dotenv" -version = "0.15.0" -description = "Add .env support to your django/flask apps in development and deployments" +version = "0.17.0" +description = "Read key-value pairs from a .env file and set them as environment variables" category = "main" optional = false python-versions = "*" @@ -2085,7 +2091,7 @@ python-versions = "*" [[package]] name = "pyupgrade" -version = "2.11.0" +version = "2.12.0" description = "A tool to automatically upgrade syntax for newer versions." category = "dev" optional = false @@ -2191,7 +2197,7 @@ six = "*" [[package]] name = "rapidfuzz" -version = "1.3.0" +version = "1.4.1" description = "rapid fuzzy string matching" category = "main" optional = false @@ -2277,7 +2283,7 @@ pyasn1 = ">=0.1.3" [[package]] name = "sacremoses" -version = "0.0.43" +version = "0.0.45" description = "SacreMoses" category = "main" optional = true @@ -2295,7 +2301,7 @@ name = "scikit-learn" version = "0.24.1" description = "A set of python modules for machine learning and data mining" category = "main" -optional = true +optional = false python-versions = ">=3.6" [package.dependencies] @@ -2336,7 +2342,7 @@ pyobjc-framework-Cocoa = {version = "*", markers = "sys_platform == \"darwin\""} [[package]] name = "scs" -version = "2.1.2" +version = "2.1.3" description = "scs: splitting conic solver" category = "main" optional = false @@ -2405,7 +2411,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "smart-open" -version = "4.2.0" +version = "5.0.0" description = "Utils for streaming large files (S3, HDFS, GCS, Azure Blob Storage, gzip, bz2...)" category = "main" optional = true @@ -2414,10 +2420,10 @@ python-versions = ">=3.6.*" [package.extras] all = ["boto3", "google-cloud-storage", "azure-storage-blob", "azure-common", "azure-core", "requests"] azure = ["azure-storage-blob", "azure-common", "azure-core"] -gcp = ["google-cloud-storage"] +gcs = ["google-cloud-storage"] http = ["requests"] s3 = ["boto3"] -test = ["boto3", "google-cloud-storage", "azure-storage-blob", "azure-common", "azure-core", "requests", "mock", "moto[server] (==1.3.14)", "pathlib2", "responses", "boto3", "paramiko", "parameterizedtestcase", "pytest", "pytest-rerunfailures"] +test = ["boto3", "google-cloud-storage", "azure-storage-blob", "azure-common", "azure-core", "requests", "mock", "moto[server] (==1.3.14)", "pathlib2", "responses", "paramiko", "parameterizedtestcase", "pytest", "pytest-rerunfailures"] webhdfs = ["requests"] [[package]] @@ -2482,7 +2488,7 @@ doc = ["reno", "sphinx", "tornado (>=4.5)"] [[package]] name = "tensorboard" -version = "2.4.1" +version = "2.5.0" description = "TensorBoard lets you watch Tensors Flow" category = "main" optional = true @@ -2497,10 +2503,18 @@ markdown = ">=2.6.8" numpy = ">=1.12.0" protobuf = ">=3.6.0" requests = ">=2.21.0,<3" -six = ">=1.10.0" +tensorboard-data-server = ">=0.6.0,<0.7.0" tensorboard-plugin-wit = ">=1.6.0" werkzeug = ">=0.11.15" +[[package]] +name = "tensorboard-data-server" +version = "0.6.0" +description = "Fast data loading for TensorBoard" +category = "main" +optional = true +python-versions = ">=3.6" + [[package]] name = "tensorboard-plugin-wit" version = "1.8.0" @@ -2554,7 +2568,7 @@ python-versions = "*" [[package]] name = "terminado" -version = "0.9.3" +version = "0.9.4" description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." category = "main" optional = false @@ -2565,6 +2579,9 @@ ptyprocess = {version = "*", markers = "os_name != \"nt\""} pywinpty = {version = ">=0.5", markers = "os_name == \"nt\""} tornado = ">=4" +[package.extras] +test = ["pytest"] + [[package]] name = "testpath" version = "0.4.4" @@ -2589,7 +2606,7 @@ name = "threadpoolctl" version = "2.1.0" description = "threadpoolctl" category = "main" -optional = true +optional = false python-versions = ">=3.5" [[package]] @@ -2660,7 +2677,7 @@ python-versions = ">= 3.5" [[package]] name = "tqdm" -version = "4.59.0" +version = "4.60.0" description = "Fast, Extensible Progress Meter" category = "main" optional = false @@ -2739,7 +2756,7 @@ torch = ["torch (>=1.0)"] [[package]] name = "typed-ast" -version = "1.4.2" +version = "1.4.3" description = "a fork of Python 2 and 3 ast modules with type comment support" category = "main" optional = false @@ -2874,7 +2891,7 @@ typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} [[package]] name = "yfinance" -version = "0.1.55" +version = "0.1.59" description = "Yahoo! Finance market data downloader" category = "main" optional = false @@ -2901,7 +2918,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt [[package]] name = "zope.interface" -version = "5.3.0" +version = "5.4.0" description = "Interfaces for Python" category = "main" optional = false @@ -2918,7 +2935,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "623e5809320b1fb71c692bdd6cdcb9ea3419f3a5b3592e6c755816bd493769bc" +content-hash = "bc7a1735d2e1abb9e5773bfafaeb58d8b53babffb2e0f37f04cb751a218782d4" [metadata.files] absl-py = [ @@ -2965,8 +2982,8 @@ aiohttp = [ {file = "aiohttp-3.7.4.post0.tar.gz", hash = "sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf"}, ] alpaca-trade-api = [ - {file = "alpaca-trade-api-1.1.0.tar.gz", hash = "sha256:751e06db061cf69aeaf6e21e7cce1baee652cc222a4c00c9f3c2074f7711f757"}, - {file = "alpaca_trade_api-1.1.0-py3-none-any.whl", hash = "sha256:098cde3d3ce70a000c643131e6750f372184db79998e91bf9c5ed787a0da3b13"}, + {file = "alpaca-trade-api-1.2.0.tar.gz", hash = "sha256:9f383c361bc5076ffbe4366b0887289399dfa6ac36799580ffa480cf589037ef"}, + {file = "alpaca_trade_api-1.2.0-py3-none-any.whl", hash = "sha256:9184895e74bd59b9f7014ad0b54e6504878b2d54e9f4293db6860767e4462210"}, ] alpha-vantage = [ {file = "alpha_vantage-2.3.1-py3-none-any.whl", hash = "sha256:5d05355febe6f0fafc4bd11dc6ce3504a02d9d3c105d60202539855c0f608661"}, @@ -3005,8 +3022,8 @@ argon2-cffi = [ {file = "argon2_cffi-20.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:8a84934bd818e14a17943de8099d41160da4a336bcc699bb4c394bbb9b94bd32"}, ] astroid = [ - {file = "astroid-2.5.1-py3-none-any.whl", hash = "sha256:21d735aab248253531bb0f1e1e6d068f0ee23533e18ae8a6171ff892b98297cf"}, - {file = "astroid-2.5.1.tar.gz", hash = "sha256:cfc35498ee64017be059ceffab0a25bedf7548ab76f2bea691c5565896e7128d"}, + {file = "astroid-2.5.3-py3-none-any.whl", hash = "sha256:bea3f32799fbb8581f58431c12591bc20ce11cbc90ad82e2ea5717d94f2080d5"}, + {file = "astroid-2.5.3.tar.gz", hash = "sha256:ad63b8552c70939568966811a088ef0bc880f99a24a00834abd0e3681b514f91"}, ] astunparse = [ {file = "astunparse-1.6.3-py2.py3-none-any.whl", hash = "sha256:c2652417f2c8b5bb325c885ae329bdf3f86424075c4fd1a128674bc6fba4b8e8"}, @@ -3045,8 +3062,8 @@ bleach = [ {file = "bleach-3.3.0.tar.gz", hash = "sha256:98b3170739e5e83dd9dc19633f074727ad848cbedb6026708c8ac2d3b697a433"}, ] bpemb = [ - {file = "bpemb-0.3.2-py3-none-any.whl", hash = "sha256:2a84d0ef963221d01a41b2a4c5d26ef2978992d6558e7289bbe58f7fd03a6446"}, - {file = "bpemb-0.3.2.tar.gz", hash = "sha256:7ef2564f656ec48c4621f555c4431c4ec71900f3c45c8d2203f9c78446e8391c"}, + {file = "bpemb-0.3.3-py3-none-any.whl", hash = "sha256:061d033d28d7aea7d4a6eb6c91b282805ad216b61dfaf1517dc87f8a02a3ef2f"}, + {file = "bpemb-0.3.3.tar.gz", hash = "sha256:ad86ba9b1623ecc3be6fcc5ba4408e23a30e118b7e1d683d292f4be788798ffe"}, ] bs4 = [ {file = "bs4-0.0.1.tar.gz", hash = "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"}, @@ -3127,18 +3144,18 @@ convertdate = [ {file = "convertdate-2.3.2.tar.gz", hash = "sha256:57df962a6047534f1452c390ad48e3dc5c83052ad83ad6dd78d60ae22f99214c"}, ] cryptography = [ - {file = "cryptography-3.4.6-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:57ad77d32917bc55299b16d3b996ffa42a1c73c6cfa829b14043c561288d2799"}, - {file = "cryptography-3.4.6-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:4169a27b818de4a1860720108b55a2801f32b6ae79e7f99c00d79f2a2822eeb7"}, - {file = "cryptography-3.4.6-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:93cfe5b7ff006de13e1e89830810ecbd014791b042cbe5eec253be11ac2b28f3"}, - {file = "cryptography-3.4.6-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:5ecf2bcb34d17415e89b546dbb44e73080f747e504273e4d4987630493cded1b"}, - {file = "cryptography-3.4.6-cp36-abi3-manylinux2014_x86_64.whl", hash = "sha256:fec7fb46b10da10d9e1d078d1ff8ed9e05ae14f431fdbd11145edd0550b9a964"}, - {file = "cryptography-3.4.6-cp36-abi3-win32.whl", hash = "sha256:df186fcbf86dc1ce56305becb8434e4b6b7504bc724b71ad7a3239e0c9d14ef2"}, - {file = "cryptography-3.4.6-cp36-abi3-win_amd64.whl", hash = "sha256:66b57a9ca4b3221d51b237094b0303843b914b7d5afd4349970bb26518e350b0"}, - {file = "cryptography-3.4.6-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:066bc53f052dfeda2f2d7c195cf16fb3e5ff13e1b6b7415b468514b40b381a5b"}, - {file = "cryptography-3.4.6-pp36-pypy36_pp73-manylinux2014_x86_64.whl", hash = "sha256:600cf9bfe75e96d965509a4c0b2b183f74a4fa6f5331dcb40fb7b77b7c2484df"}, - {file = "cryptography-3.4.6-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:0923ba600d00718d63a3976f23cab19aef10c1765038945628cd9be047ad0336"}, - {file = "cryptography-3.4.6-pp37-pypy37_pp73-manylinux2014_x86_64.whl", hash = "sha256:9e98b452132963678e3ac6c73f7010fe53adf72209a32854d55690acac3f6724"}, - {file = "cryptography-3.4.6.tar.gz", hash = "sha256:2d32223e5b0ee02943f32b19245b61a62db83a882f0e76cc564e1cec60d48f87"}, + {file = "cryptography-3.4.7-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:3d8427734c781ea5f1b41d6589c293089704d4759e34597dce91014ac125aad1"}, + {file = "cryptography-3.4.7-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:8e56e16617872b0957d1c9742a3f94b43533447fd78321514abbe7db216aa250"}, + {file = "cryptography-3.4.7-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:37340614f8a5d2fb9aeea67fd159bfe4f5f4ed535b1090ce8ec428b2f15a11f2"}, + {file = "cryptography-3.4.7-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:240f5c21aef0b73f40bb9f78d2caff73186700bf1bc6b94285699aff98cc16c6"}, + {file = "cryptography-3.4.7-cp36-abi3-manylinux2014_x86_64.whl", hash = "sha256:1e056c28420c072c5e3cb36e2b23ee55e260cb04eee08f702e0edfec3fb51959"}, + {file = "cryptography-3.4.7-cp36-abi3-win32.whl", hash = "sha256:0f1212a66329c80d68aeeb39b8a16d54ef57071bf22ff4e521657b27372e327d"}, + {file = "cryptography-3.4.7-cp36-abi3-win_amd64.whl", hash = "sha256:de4e5f7f68220d92b7637fc99847475b59154b7a1b3868fb7385337af54ac9ca"}, + {file = "cryptography-3.4.7-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:26965837447f9c82f1855e0bc8bc4fb910240b6e0d16a664bb722df3b5b06873"}, + {file = "cryptography-3.4.7-pp36-pypy36_pp73-manylinux2014_x86_64.whl", hash = "sha256:eb8cc2afe8b05acbd84a43905832ec78e7b3873fb124ca190f574dca7389a87d"}, + {file = "cryptography-3.4.7-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:7ec5d3b029f5fa2b179325908b9cd93db28ab7b85bb6c1db56b10e0b54235177"}, + {file = "cryptography-3.4.7-pp37-pypy37_pp73-manylinux2014_x86_64.whl", hash = "sha256:ee77aa129f481be46f8d92a1a7db57269a2f23052d5f2433b4621bb457081cc9"}, + {file = "cryptography-3.4.7.tar.gz", hash = "sha256:3d10de8116d25649631977cb37da6cbdd2d6fa0e0281d014a5b7d337255ca713"}, ] cssselect = [ {file = "cssselect-1.1.0-py2.py3-none-any.whl", hash = "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf"}, @@ -3285,19 +3302,19 @@ filelock = [ {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, ] finviz = [ - {file = "finviz-1.3.4.tar.gz", hash = "sha256:3e850019c1b239dbaa6a75e982b513805182c205f6e957db48425a5f41fbd788"}, + {file = "finviz-1.4.1.tar.gz", hash = "sha256:7b1a2a730ce8e09dfe64aad30b499a3adaf0fdf2d52cba6dd3ef9813248182be"}, ] finvizfinance = [ - {file = "finvizfinance-0.9.3-py3-none-any.whl", hash = "sha256:7a342012b9d97e3390d9942c3a87c615628ed5733eeb1ccf1083328a7c486a43"}, - {file = "finvizfinance-0.9.3.tar.gz", hash = "sha256:45dfaf8f6d0df214d5dd86a37c11b1a67ccaa524066d93299236d21bad8a3bd8"}, + {file = "finvizfinance-0.9.6-py3-none-any.whl", hash = "sha256:18db3403bac6c3e6dae9d2c8d555df10d228e34daf02e4d50bb69c46e578cb7d"}, + {file = "finvizfinance-0.9.6.tar.gz", hash = "sha256:9a5f5a1a1e67e810e4f6819cda0e3966f95313ff27d06466ae8a91e5a0e0cdbe"}, ] flair = [ {file = "flair-0.7-py3-none-any.whl", hash = "sha256:42c7e8074f67eeac722d68f4d5a9ad602377a76f5c4a2a190b916645b9be6ff2"}, {file = "flair-0.7.tar.gz", hash = "sha256:50cfe5382b41ba88d9cd7096fb82d21d7f938b167fc7de2c8365bf53f3576ef4"}, ] flake8 = [ - {file = "flake8-3.9.0-py2.py3-none-any.whl", hash = "sha256:12d05ab02614b6aee8df7c36b97d1a3b2372761222b19b58621355e82acddcff"}, - {file = "flake8-3.9.0.tar.gz", hash = "sha256:78873e372b12b093da7b5e5ed302e8ad9e988b38b063b61ad937f26ca58fc5f0"}, + {file = "flake8-3.9.1-py2.py3-none-any.whl", hash = "sha256:3b9f848952dddccf635be78098ca75010f073bfe14d2c6bda867154bea728d2a"}, + {file = "flake8-3.9.1.tar.gz", hash = "sha256:1aa8990be1e689d96c745c5682b687ea49f2e05a443aff1f8251092b0014e378"}, ] flatbuffers = [ {file = "flatbuffers-1.12-py2.py3-none-any.whl", hash = "sha256:9e9ef47fa92625c4721036e7c4124182668dc6021d9e7c73704edd395648deb9"}, @@ -3308,10 +3325,11 @@ fredapi = [ {file = "fredapi-0.4.3.tar.gz", hash = "sha256:d9b3194fb60541991bd33f019c710d4a9580ecfb5e47efbf2d2571888a2aac02"}, ] ftfy = [ - {file = "ftfy-5.9.tar.gz", hash = "sha256:8c4fb2863c0b82eae2ab3cf353d9ade268dfbde863d322f78d6a9fd5cefb31e9"}, + {file = "ftfy-6.0.1.tar.gz", hash = "sha256:9eb68533eb2a6124e96ed7f63049e6c519194fda3fae92629b5e0b5753cb2c8f"}, ] fundamentalanalysis = [ - {file = "FundamentalAnalysis-0.2.6.tar.gz", hash = "sha256:0033d51784ae6c75a7347942ec3114bfb9d5db494e5fbd67eb693c6ed6fee4fa"}, + {file = "FundamentalAnalysis-0.2.7-py3-none-any.whl", hash = "sha256:dff63a9c8792a6f4cadbffc9c5ce7b5c7636a890ffac1cdd9d265beedd2f1090"}, + {file = "FundamentalAnalysis-0.2.7.tar.gz", hash = "sha256:9ef0fbf52b7d0be3038103739db9d6a789adc98d2fde5335f427d1bba5291944"}, ] future = [ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, @@ -3348,12 +3366,12 @@ gensim = [ {file = "gensim-3.8.2.win32-py3.7.exe", hash = "sha256:3234cbd52c0a4d548f385393040277fab03593358fee5673533e7ee6ed2f406c"}, ] google-auth = [ - {file = "google-auth-1.28.0.tar.gz", hash = "sha256:9bd436d19ab047001a1340720d2b629eb96dd503258c524921ec2af3ee88a80e"}, - {file = "google_auth-1.28.0-py2.py3-none-any.whl", hash = "sha256:dcaba3aa9d4e0e96fd945bf25a86b6f878fcb05770b67adbeb50a63ca4d28a5e"}, + {file = "google-auth-1.29.0.tar.gz", hash = "sha256:010f011c4e27d3d5eb01106fba6aac39d164842dfcd8709955c4638f5b11ccf8"}, + {file = "google_auth-1.29.0-py2.py3-none-any.whl", hash = "sha256:f30a672a64d91cc2e3137765d088c5deec26416246f7a9e956eaf69a8d7ed49c"}, ] google-auth-oauthlib = [ - {file = "google-auth-oauthlib-0.4.3.tar.gz", hash = "sha256:54431535309cfab50897d9c181e8c2226268825aa6e42e930b05b99c5041a18c"}, - {file = "google_auth_oauthlib-0.4.3-py2.py3-none-any.whl", hash = "sha256:dabffbf594a6be2fd6d054060846d1201569252efb10dfb749b504a7591f8af0"}, + {file = "google-auth-oauthlib-0.4.4.tar.gz", hash = "sha256:09832c6e75032f93818edf1affe4746121d640c625a5bef9b5c96af676e98eee"}, + {file = "google_auth_oauthlib-0.4.4-py2.py3-none-any.whl", hash = "sha256:0e92aacacfb94978de3b7972cf4b0f204c3cd206f74ddd0dc0b31e91164e6317"}, ] google-pasta = [ {file = "google-pasta-0.2.0.tar.gz", hash = "sha256:c9f2c8dfc8f96d0d5808299920721be30c9eec37f2389f28904f454565c8a16e"}, @@ -3454,8 +3472,8 @@ idna-ssl = [ {file = "idna-ssl-1.1.0.tar.gz", hash = "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"}, ] importlib-metadata = [ - {file = "importlib_metadata-3.7.3-py3-none-any.whl", hash = "sha256:b74159469b464a99cb8cc3e21973e4d96e05d3024d337313fedb618a6e86e6f4"}, - {file = "importlib_metadata-3.7.3.tar.gz", hash = "sha256:742add720a20d0467df2f444ae41704000f50e1234f46174b51f9c6031a1bd71"}, + {file = "importlib_metadata-4.0.0-py3-none-any.whl", hash = "sha256:19192b88d959336bfa6bdaaaef99aeafec179eca19c47c804e555703ee5f07ef"}, + {file = "importlib_metadata-4.0.0.tar.gz", hash = "sha256:2e881981c9748d7282b374b68e759c87745c25427b67ecf0cc67fb6637a1bff9"}, ] inflection = [ {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, @@ -3466,8 +3484,8 @@ iniconfig = [ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] ipykernel = [ - {file = "ipykernel-5.5.0-py3-none-any.whl", hash = "sha256:efd07253b54d84d26e0878d268c8c3a41582a18750da633c2febfd2ece0d467d"}, - {file = "ipykernel-5.5.0.tar.gz", hash = "sha256:98321abefdf0505fb3dc7601f60fc4087364d394bd8fad53107eb1adee9ff475"}, + {file = "ipykernel-5.5.3-py3-none-any.whl", hash = "sha256:21abd584543759e49010975a4621603b3cf871b1039cb3879a14094717692614"}, + {file = "ipykernel-5.5.3.tar.gz", hash = "sha256:a682e4f7affd86d9ce9b699d21bcab6d5ec9fbb2bfcb194f2706973b252bc509"}, ] ipython = [ {file = "ipython-7.16.1-py3-none-any.whl", hash = "sha256:2dbcc8c27ca7d3cfe4fcdff7f45b27f9a8d3edfa70ff8024a71c7a8eb5f09d64"}, @@ -3486,8 +3504,8 @@ iso8601 = [ {file = "iso8601-0.1.14.tar.gz", hash = "sha256:8aafd56fa0290496c5edbb13c311f78fa3a241f0853540da09d9363eae3ebd79"}, ] isort = [ - {file = "isort-5.7.0-py3-none-any.whl", hash = "sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc"}, - {file = "isort-5.7.0.tar.gz", hash = "sha256:c729845434366216d320e936b8ad6f9d681aab72dc7cbc2d51bedc3582f3ad1e"}, + {file = "isort-5.8.0-py3-none-any.whl", hash = "sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d"}, + {file = "isort-5.8.0.tar.gz", hash = "sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6"}, ] janome = [ {file = "Janome-0.4.1-py2.py3-none-any.whl", hash = "sha256:a650e2684e80af72f869eff17566f31dd4444f5443c4771dca1ada60cea5c251"}, @@ -3515,12 +3533,12 @@ jupyter = [ {file = "jupyter-1.0.0.zip", hash = "sha256:3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7"}, ] jupyter-client = [ - {file = "jupyter_client-6.1.12-py3-none-any.whl", hash = "sha256:e053a2c44b6fa597feebe2b3ecb5eea3e03d1d91cc94351a52931ee1426aecfc"}, - {file = "jupyter_client-6.1.12.tar.gz", hash = "sha256:c4bca1d0846186ca8be97f4d2fa6d2bae889cce4892a167ffa1ba6bd1f73e782"}, + {file = "jupyter_client-6.2.0-py3-none-any.whl", hash = "sha256:9715152067e3f7ea3b56f341c9a0f9715c8c7cc316ee0eb13c3c84f5ca0065f5"}, + {file = "jupyter_client-6.2.0.tar.gz", hash = "sha256:e2ab61d79fbf8b56734a4c2499f19830fbd7f6fefb3e87868ef0545cb3c17eb9"}, ] jupyter-console = [ - {file = "jupyter_console-6.3.0-py3-none-any.whl", hash = "sha256:092283ba2c9b5ceb53f32d95891ecc59ed4bfeb69e36fe017db176213daa5b0e"}, - {file = "jupyter_console-6.3.0.tar.gz", hash = "sha256:947f66bbdeee2221b4fb3a6b78225d337b8f10832f14cecf7932183635abe1d9"}, + {file = "jupyter_console-6.4.0-py3-none-any.whl", hash = "sha256:7799c4ea951e0e96ba8260575423cb323ea5a03fcf5503560fa3e15748869e27"}, + {file = "jupyter_console-6.4.0.tar.gz", hash = "sha256:242248e1685039cd8bff2c2ecb7ce6c1546eb50ee3b08519729e6e881aec19c7"}, ] jupyter-core = [ {file = "jupyter_core-4.7.1-py3-none-any.whl", hash = "sha256:8c6c0cac5c1b563622ad49321d5ec47017bd18b94facb381c6973a0486395f8e"}, @@ -3573,8 +3591,8 @@ kiwisolver = [ {file = "kiwisolver-1.3.1.tar.gz", hash = "sha256:950a199911a8d94683a6b10321f9345d5a3a8433ec58b217ace979e18f16e248"}, ] konoha = [ - {file = "konoha-4.6.4-py3-none-any.whl", hash = "sha256:4d6fd63f4977dda9a55bb5fdc3c626d03d6be0d491fa7e098ac971a346290515"}, - {file = "konoha-4.6.4.tar.gz", hash = "sha256:7c6f24b3bd37d3ac5a27db68fcf59d9a71c1cd0471431639459c3d6fb1eec2be"}, + {file = "konoha-4.6.3-py3-none-any.whl", hash = "sha256:b5c79c6c3ccbe03ed19ed0a562e1a924256e416c8b9e5812a0cce095351b6689"}, + {file = "konoha-4.6.3.tar.gz", hash = "sha256:24a93d27bd428b846dcfacc53bcec9a1b94154062feabf67f3d4ea41c6428c14"}, ] korean-lunar-calendar = [ {file = "korean_lunar_calendar-0.2.1-py3-none-any.whl", hash = "sha256:a619ea88610129019267467b85cc9faf0fab6e1694b2e782d1aeb610cdd382d5"}, @@ -3585,73 +3603,70 @@ langdetect = [ {file = "langdetect-1.0.8.tar.gz", hash = "sha256:363795ea005f1243c958e953245dac5d814fabdc025c9afa91588c5fa6b2fa83"}, ] lazy-object-proxy = [ - {file = "lazy-object-proxy-1.5.2.tar.gz", hash = "sha256:5944a9b95e97de1980c65f03b79b356f30a43de48682b8bdd90aa5089f0ec1f4"}, - {file = "lazy_object_proxy-1.5.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:e960e8be509e8d6d618300a6c189555c24efde63e85acaf0b14b2cd1ac743315"}, - {file = "lazy_object_proxy-1.5.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:522b7c94b524389f4a4094c4bf04c2b02228454ddd17c1a9b2801fac1d754871"}, - {file = "lazy_object_proxy-1.5.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3782931963dc89e0e9a0ae4348b44762e868ea280e4f8c233b537852a8996ab9"}, - {file = "lazy_object_proxy-1.5.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:429c4d1862f3fc37cd56304d880f2eae5bd0da83bdef889f3bd66458aac49128"}, - {file = "lazy_object_proxy-1.5.2-cp35-cp35m-win32.whl", hash = "sha256:cd1bdace1a8762534e9a36c073cd54e97d517a17d69a17985961265be6d22847"}, - {file = "lazy_object_proxy-1.5.2-cp35-cp35m-win_amd64.whl", hash = "sha256:ddbdcd10eb999d7ab292677f588b658372aadb9a52790f82484a37127a390108"}, - {file = "lazy_object_proxy-1.5.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ecb5dd5990cec6e7f5c9c1124a37cb2c710c6d69b0c1a5c4aa4b35eba0ada068"}, - {file = "lazy_object_proxy-1.5.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:b6577f15d5516d7d209c1a8cde23062c0f10625f19e8dc9fb59268859778d7d7"}, - {file = "lazy_object_proxy-1.5.2-cp36-cp36m-win32.whl", hash = "sha256:c8fe2d6ff0ff583784039d0255ea7da076efd08507f2be6f68583b0da32e3afb"}, - {file = "lazy_object_proxy-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:fa5b2dee0e231fa4ad117be114251bdfe6afe39213bd629d43deb117b6a6c40a"}, - {file = "lazy_object_proxy-1.5.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1d33d6f789697f401b75ce08e73b1de567b947740f768376631079290118ad39"}, - {file = "lazy_object_proxy-1.5.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:57fb5c5504ddd45ed420b5b6461a78f58cbb0c1b0cbd9cd5a43ad30a4a3ee4d0"}, - {file = "lazy_object_proxy-1.5.2-cp37-cp37m-win32.whl", hash = "sha256:e7273c64bccfd9310e9601b8f4511d84730239516bada26a0c9846c9697617ef"}, - {file = "lazy_object_proxy-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6f4e5e68b7af950ed7fdb594b3f19a0014a3ace0fedb86acb896e140ffb24302"}, - {file = "lazy_object_proxy-1.5.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cadfa2c2cf54d35d13dc8d231253b7985b97d629ab9ca6e7d672c35539d38163"}, - {file = "lazy_object_proxy-1.5.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e7428977763150b4cf83255625a80a23dfdc94d43be7791ce90799d446b4e26f"}, - {file = "lazy_object_proxy-1.5.2-cp38-cp38-win32.whl", hash = "sha256:2f2de8f8ac0be3e40d17730e0600619d35c78c13a099ea91ef7fb4ad944ce694"}, - {file = "lazy_object_proxy-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:38c3865bd220bd983fcaa9aa11462619e84a71233bafd9c880f7b1cb753ca7fa"}, - {file = "lazy_object_proxy-1.5.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:8a44e9901c0555f95ac401377032f6e6af66d8fc1fbfad77a7a8b1a826e0b93c"}, - {file = "lazy_object_proxy-1.5.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fa7fb7973c622b9e725bee1db569d2c2ee64d2f9a089201c5e8185d482c7352d"}, - {file = "lazy_object_proxy-1.5.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:71a1ef23f22fa8437974b2d60fedb947c99a957ad625f83f43fd3de70f77f458"}, - {file = "lazy_object_proxy-1.5.2-cp39-cp39-win32.whl", hash = "sha256:ef3f5e288aa57b73b034ce9c1f1ac753d968f9069cd0742d1d69c698a0167166"}, - {file = "lazy_object_proxy-1.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:37d9c34b96cca6787fe014aeb651217944a967a5b165e2cacb6b858d2997ab84"}, + {file = "lazy-object-proxy-1.6.0.tar.gz", hash = "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win32.whl", hash = "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93"}, + {file = "lazy_object_proxy-1.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win32.whl", hash = "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f"}, + {file = "lazy_object_proxy-1.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win32.whl", hash = "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd"}, + {file = "lazy_object_proxy-1.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-win32.whl", hash = "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8"}, + {file = "lazy_object_proxy-1.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-win32.whl", hash = "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61"}, + {file = "lazy_object_proxy-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"}, ] lunarcalendar = [ {file = "LunarCalendar-0.0.9-py2.py3-none-any.whl", hash = "sha256:5ef25883d73898b37edb54da9e0f04215aaa68b897fd12e9d4b79756ff91c8cb"}, {file = "LunarCalendar-0.0.9.tar.gz", hash = "sha256:681142f22fc353c3abca4b25699e3d1aa7083ad1c268dce36ba297eca04bed5a"}, ] lxml = [ - {file = "lxml-4.6.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a9d6bc8642e2c67db33f1247a77c53476f3a166e09067c0474facb045756087f"}, - {file = "lxml-4.6.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:791394449e98243839fa822a637177dd42a95f4883ad3dec2a0ce6ac99fb0a9d"}, - {file = "lxml-4.6.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:68a5d77e440df94011214b7db907ec8f19e439507a70c958f750c18d88f995d2"}, - {file = "lxml-4.6.2-cp27-cp27m-win32.whl", hash = "sha256:fc37870d6716b137e80d19241d0e2cff7a7643b925dfa49b4c8ebd1295eb506e"}, - {file = "lxml-4.6.2-cp27-cp27m-win_amd64.whl", hash = "sha256:69a63f83e88138ab7642d8f61418cf3180a4d8cd13995df87725cb8b893e950e"}, - {file = "lxml-4.6.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:42ebca24ba2a21065fb546f3e6bd0c58c3fe9ac298f3a320147029a4850f51a2"}, - {file = "lxml-4.6.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:f83d281bb2a6217cd806f4cf0ddded436790e66f393e124dfe9731f6b3fb9afe"}, - {file = "lxml-4.6.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:535f067002b0fd1a4e5296a8f1bf88193080ff992a195e66964ef2a6cfec5388"}, - {file = "lxml-4.6.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:366cb750140f221523fa062d641393092813b81e15d0e25d9f7c6025f910ee80"}, - {file = "lxml-4.6.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:97db258793d193c7b62d4e2586c6ed98d51086e93f9a3af2b2034af01450a74b"}, - {file = "lxml-4.6.2-cp35-cp35m-win32.whl", hash = "sha256:648914abafe67f11be7d93c1a546068f8eff3c5fa938e1f94509e4a5d682b2d8"}, - {file = "lxml-4.6.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4e751e77006da34643ab782e4a5cc21ea7b755551db202bc4d3a423b307db780"}, - {file = "lxml-4.6.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:681d75e1a38a69f1e64ab82fe4b1ed3fd758717bed735fb9aeaa124143f051af"}, - {file = "lxml-4.6.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:127f76864468d6630e1b453d3ffbbd04b024c674f55cf0a30dc2595137892d37"}, - {file = "lxml-4.6.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4fb85c447e288df535b17ebdebf0ec1cf3a3f1a8eba7e79169f4f37af43c6b98"}, - {file = "lxml-4.6.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:5be4a2e212bb6aa045e37f7d48e3e1e4b6fd259882ed5a00786f82e8c37ce77d"}, - {file = "lxml-4.6.2-cp36-cp36m-win32.whl", hash = "sha256:8c88b599e226994ad4db29d93bc149aa1aff3dc3a4355dd5757569ba78632bdf"}, - {file = "lxml-4.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:6e4183800f16f3679076dfa8abf2db3083919d7e30764a069fb66b2b9eff9939"}, - {file = "lxml-4.6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d8d3d4713f0c28bdc6c806a278d998546e8efc3498949e3ace6e117462ac0a5e"}, - {file = "lxml-4.6.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:8246f30ca34dc712ab07e51dc34fea883c00b7ccb0e614651e49da2c49a30711"}, - {file = "lxml-4.6.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:923963e989ffbceaa210ac37afc9b906acebe945d2723e9679b643513837b089"}, - {file = "lxml-4.6.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:1471cee35eba321827d7d53d104e7b8c593ea3ad376aa2df89533ce8e1b24a01"}, - {file = "lxml-4.6.2-cp37-cp37m-win32.whl", hash = "sha256:2363c35637d2d9d6f26f60a208819e7eafc4305ce39dc1d5005eccc4593331c2"}, - {file = "lxml-4.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:f4822c0660c3754f1a41a655e37cb4dbbc9be3d35b125a37fab6f82d47674ebc"}, - {file = "lxml-4.6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0448576c148c129594d890265b1a83b9cd76fd1f0a6a04620753d9a6bcfd0a4d"}, - {file = "lxml-4.6.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:60a20bfc3bd234d54d49c388950195d23a5583d4108e1a1d47c9eef8d8c042b3"}, - {file = "lxml-4.6.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2e5cc908fe43fe1aa299e58046ad66981131a66aea3129aac7770c37f590a644"}, - {file = "lxml-4.6.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:50c348995b47b5a4e330362cf39fc503b4a43b14a91c34c83b955e1805c8e308"}, - {file = "lxml-4.6.2-cp38-cp38-win32.whl", hash = "sha256:94d55bd03d8671686e3f012577d9caa5421a07286dd351dfef64791cf7c6c505"}, - {file = "lxml-4.6.2-cp38-cp38-win_amd64.whl", hash = "sha256:7a7669ff50f41225ca5d6ee0a1ec8413f3a0d8aa2b109f86d540887b7ec0d72a"}, - {file = "lxml-4.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e0bfe9bb028974a481410432dbe1b182e8191d5d40382e5b8ff39cdd2e5c5931"}, - {file = "lxml-4.6.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:6fd8d5903c2e53f49e99359b063df27fdf7acb89a52b6a12494208bf61345a03"}, - {file = "lxml-4.6.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7e9eac1e526386df7c70ef253b792a0a12dd86d833b1d329e038c7a235dfceb5"}, - {file = "lxml-4.6.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:7ee8af0b9f7de635c61cdd5b8534b76c52cd03536f29f51151b377f76e214a1a"}, - {file = "lxml-4.6.2-cp39-cp39-win32.whl", hash = "sha256:2e6fd1b8acd005bd71e6c94f30c055594bbd0aa02ef51a22bbfa961ab63b2d75"}, - {file = "lxml-4.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:535332fe9d00c3cd455bd3dd7d4bacab86e2d564bdf7606079160fa6251caacf"}, - {file = "lxml-4.6.2.tar.gz", hash = "sha256:cd11c7e8d21af997ee8079037fff88f16fda188a9776eb4b81c7e4c9c0a7d7fc"}, + {file = "lxml-4.6.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:df7c53783a46febb0e70f6b05df2ba104610f2fb0d27023409734a3ecbb78fb2"}, + {file = "lxml-4.6.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1b7584d421d254ab86d4f0b13ec662a9014397678a7c4265a02a6d7c2b18a75f"}, + {file = "lxml-4.6.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:079f3ae844f38982d156efce585bc540c16a926d4436712cf4baee0cce487a3d"}, + {file = "lxml-4.6.3-cp27-cp27m-win32.whl", hash = "sha256:bc4313cbeb0e7a416a488d72f9680fffffc645f8a838bd2193809881c67dd106"}, + {file = "lxml-4.6.3-cp27-cp27m-win_amd64.whl", hash = "sha256:8157dadbb09a34a6bd95a50690595e1fa0af1a99445e2744110e3dca7831c4ee"}, + {file = "lxml-4.6.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7728e05c35412ba36d3e9795ae8995e3c86958179c9770e65558ec3fdfd3724f"}, + {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-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-manylinux2014_aarch64.whl", hash = "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec"}, + {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-manylinux2014_aarch64.whl", hash = "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2"}, + {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-manylinux2014_aarch64.whl", hash = "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791"}, + {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-manylinux2014_aarch64.whl", hash = "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969"}, + {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"}, ] markdown = [ {file = "Markdown-3.3.4-py3-none-any.whl", hash = "sha256:96c3ba1261de2f7547b46a00ea8463832c921d3f9d6aba3f255a6f71386db20c"}, @@ -3758,8 +3773,8 @@ mpld3 = [ {file = "mpld3-0.3.tar.gz", hash = "sha256:4d455884a211bf99b37ecc760759435c7bb6a5955de47d8daf4967e301878ab7"}, ] mplfinance = [ - {file = "mplfinance-0.12.7a10-py3-none-any.whl", hash = "sha256:aa4d9759a1befadfed190f9fc72ac8389d80fb61bc6f8ce6693d9c2627e88021"}, - {file = "mplfinance-0.12.7a10.tar.gz", hash = "sha256:f3745ad29ec834cd5505aa510f401f2c44b44328f92c781d093b3bb597641545"}, + {file = "mplfinance-0.12.7a12-py3-none-any.whl", hash = "sha256:e1ae6e763b9ea5c7b74037c04f5e85af42272053d938592b5b54a610fc16ab6c"}, + {file = "mplfinance-0.12.7a12.tar.gz", hash = "sha256:5e48d4eab079457c025cfae37ae95a8693b5f3a2ba64e7a08104fbaf1462a400"}, ] msgpack = [ {file = "msgpack-1.0.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:b6d9e2dae081aa35c44af9c4298de4ee72991305503442a5c74656d82b581fe9"}, @@ -3870,20 +3885,20 @@ nbconvert = [ {file = "nbconvert-6.0.7.tar.gz", hash = "sha256:cbbc13a86dfbd4d1b5dee106539de0795b4db156c894c2c5dc382062bbc29002"}, ] nbformat = [ - {file = "nbformat-5.1.2-py3-none-any.whl", hash = "sha256:3949fdc8f5fa0b1afca16fb307546e78494fa7a7bceff880df8168eafda0e7ac"}, - {file = "nbformat-5.1.2.tar.gz", hash = "sha256:1d223e64a18bfa7cdf2db2e9ba8a818312fc2a0701d2e910b58df66809385a56"}, + {file = "nbformat-5.1.3-py3-none-any.whl", hash = "sha256:eb8447edd7127d043361bc17f2f5a807626bc8e878c7709a1c647abda28a9171"}, + {file = "nbformat-5.1.3.tar.gz", hash = "sha256:b516788ad70771c6250977c1374fcca6edebe6126fd2adb5a69aa5c2356fd1c8"}, ] nest-asyncio = [ {file = "nest_asyncio-1.5.1-py3-none-any.whl", hash = "sha256:76d6e972265063fe92a90b9cc4fb82616e07d586b346ed9d2c89a4187acea39c"}, {file = "nest_asyncio-1.5.1.tar.gz", hash = "sha256:afc5a1c515210a23c461932765691ad39e8eba6551c055ac8d5546e69250d0aa"}, ] networkx = [ - {file = "networkx-2.5-py3-none-any.whl", hash = "sha256:8c5812e9f798d37c50570d15c4a69d5710a18d77bafc903ee9c5fba7454c616c"}, - {file = "networkx-2.5.tar.gz", hash = "sha256:7978955423fbc9639c10498878be59caf99b44dc304c2286162fd24b458c1602"}, + {file = "networkx-2.5.1-py3-none-any.whl", hash = "sha256:0635858ed7e989f4c574c2328380b452df892ae85084144c73d8cd819f0c4e06"}, + {file = "networkx-2.5.1.tar.gz", hash = "sha256:109cd585cac41297f71103c3c42ac6ef7379f29788eb54cb751be5a663bb235a"}, ] notebook = [ - {file = "notebook-6.2.0-py3-none-any.whl", hash = "sha256:25ad93c982b623441b491e693ef400598d1a46cdf11b8c9c0b3be6c61ebbb6cd"}, - {file = "notebook-6.2.0.tar.gz", hash = "sha256:0464b28e18e7a06cec37e6177546c2322739be07962dd13bf712bcb88361f013"}, + {file = "notebook-6.3.0-py3-none-any.whl", hash = "sha256:cb271af1e8134e3d6fc6d458bdc79c40cbfc84c1eb036a493f216d58f0880e92"}, + {file = "notebook-6.3.0.tar.gz", hash = "sha256:cbc9398d6c81473e9cdb891d2cae9c0d3718fca289dda6d26df5cb660fcadc7d"}, ] numpy = [ {file = "numpy-1.19.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff"}, @@ -3996,8 +4011,8 @@ papermill = [ {file = "papermill-2.3.3.tar.gz", hash = "sha256:349aecd526c15c39f73a08df836467e2fead877c474d82c7df349f27ad272525"}, ] parso = [ - {file = "parso-0.8.1-py2.py3-none-any.whl", hash = "sha256:15b00182f472319383252c18d5913b69269590616c947747bc50bf4ac768f410"}, - {file = "parso-0.8.1.tar.gz", hash = "sha256:8519430ad07087d4c997fda3a7918f7cfa27cb58972a8c89c2a0295a1c940e9e"}, + {file = "parso-0.8.2-py2.py3-none-any.whl", hash = "sha256:a8c4922db71e4fdb90e0d0bc6e50f9b273d3397925e5e60a717e719201778d22"}, + {file = "parso-0.8.2.tar.gz", hash = "sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398"}, ] pathspec = [ {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, @@ -4086,34 +4101,34 @@ prettytable = [ {file = "prettytable-2.1.0.tar.gz", hash = "sha256:5882ed9092b391bb8f6e91f59bcdbd748924ff556bb7c634089d5519be87baa0"}, ] prometheus-client = [ - {file = "prometheus_client-0.9.0-py2.py3-none-any.whl", hash = "sha256:b08c34c328e1bf5961f0b4352668e6c8f145b4a087e09b7296ef62cbe4693d35"}, - {file = "prometheus_client-0.9.0.tar.gz", hash = "sha256:9da7b32f02439d8c04f7777021c304ed51d9ec180604700c1ba72a4d44dceb03"}, + {file = "prometheus_client-0.10.1-py2.py3-none-any.whl", hash = "sha256:030e4f9df5f53db2292eec37c6255957eb76168c6f974e4176c711cf91ed34aa"}, + {file = "prometheus_client-0.10.1.tar.gz", hash = "sha256:b6c5a9643e3545bcbfd9451766cbaa5d9c67e7303c7bc32c750b6fa70ecb107d"}, ] prompt-toolkit = [ - {file = "prompt_toolkit-3.0.17-py3-none-any.whl", hash = "sha256:4cea7d09e46723885cb8bc54678175453e5071e9449821dce6f017b1d1fbfc1a"}, - {file = "prompt_toolkit-3.0.17.tar.gz", hash = "sha256:9397a7162cf45449147ad6042fa37983a081b8a73363a5253dd4072666333137"}, + {file = "prompt_toolkit-3.0.18-py3-none-any.whl", hash = "sha256:bf00f22079f5fadc949f42ae8ff7f05702826a97059ffcc6281036ad40ac6f04"}, + {file = "prompt_toolkit-3.0.18.tar.gz", hash = "sha256:e1b4f11b9336a28fa11810bc623c357420f69dfdb6d2dac41ca2c21a55c033bc"}, ] protobuf = [ - {file = "protobuf-3.15.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1771ef20e88759c4d81db213e89b7a1fc53937968e12af6603c658ee4bcbfa38"}, - {file = "protobuf-3.15.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1a66261a402d05c8ad8c1fde8631837307bf8d7e7740a4f3941fc3277c2e1528"}, - {file = "protobuf-3.15.6-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:eac23a3e56175b710f3da9a9e8e2aa571891fbec60e0c5a06db1c7b1613b5cfd"}, - {file = "protobuf-3.15.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ec220d90eda8bb7a7a1434a8aed4fe26d7e648c1a051c2885f3f5725b6aa71a"}, - {file = "protobuf-3.15.6-cp35-cp35m-win32.whl", hash = "sha256:88d8f21d1ac205eedb6dea943f8204ed08201b081dba2a966ab5612788b9bb1e"}, - {file = "protobuf-3.15.6-cp35-cp35m-win_amd64.whl", hash = "sha256:eaada29bbf087dea7d8bce4d1d604fc768749e8809e9c295922accd7c8fce4d5"}, - {file = "protobuf-3.15.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:256c0b2e338c1f3228d3280707606fe5531fde85ab9d704cde6fdeb55112531f"}, - {file = "protobuf-3.15.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:b9069e45b6e78412fba4a314ea38b4a478686060acf470d2b131b3a2c50484ec"}, - {file = "protobuf-3.15.6-cp36-cp36m-win32.whl", hash = "sha256:24f4697f57b8520c897a401b7f9a5ae45c369e22c572e305dfaf8053ecb49687"}, - {file = "protobuf-3.15.6-cp36-cp36m-win_amd64.whl", hash = "sha256:d9ed0955b794f1e5f367e27f8a8ff25501eabe34573f003f06639c366ca75f73"}, - {file = "protobuf-3.15.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:822ac7f87fc2fb9b24edd2db390538b60ef50256e421ca30d65250fad5a3d477"}, - {file = "protobuf-3.15.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:74ac159989e2b02d761188a2b6f4601ff5e494d9b9d863f5ad6e98e5e0c54328"}, - {file = "protobuf-3.15.6-cp37-cp37m-win32.whl", hash = "sha256:30fe4249a364576f9594180589c3f9c4771952014b5f77f0372923fc7bafbbe2"}, - {file = "protobuf-3.15.6-cp37-cp37m-win_amd64.whl", hash = "sha256:45a91fc6f9aa86d3effdeda6751882b02de628519ba06d7160daffde0c889ff8"}, - {file = "protobuf-3.15.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83c7c7534f050cb25383bb817159416601d1cc46c40bc5e851ec8bbddfc34a2f"}, - {file = "protobuf-3.15.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9ec20a6ded7d0888e767ad029dbb126e604e18db744ac0a428cf746e040ccecd"}, - {file = "protobuf-3.15.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0f2da2fcc4102b6c3b57f03c9d8d5e37c63f8bc74deaa6cb54e0cc4524a77247"}, - {file = "protobuf-3.15.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:70054ae1ce5dea7dec7357db931fcf487f40ea45b02cb719ee6af07eb1e906fb"}, - {file = "protobuf-3.15.6-py2.py3-none-any.whl", hash = "sha256:1655fc0ba7402560d749de13edbfca1ac45d1753d8f4e5292989f18f5a00c215"}, - {file = "protobuf-3.15.6.tar.gz", hash = "sha256:2b974519a2ae83aa1e31cff9018c70bbe0e303a46a598f982943c49ae1d4fcd3"}, + {file = "protobuf-3.15.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fad4f971ec38d8df7f4b632c819bf9bbf4f57cfd7312cf526c69ce17ef32436a"}, + {file = "protobuf-3.15.8-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:f17b352d7ce33c81773cf81d536ca70849de6f73c96413f17309f4b43ae7040b"}, + {file = "protobuf-3.15.8-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:4a054b0b5900b7ea7014099e783fb8c4618e4209fffcd6050857517b3f156e18"}, + {file = "protobuf-3.15.8-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:efa4c4d4fc9ba734e5e85eaced70e1b63fb3c8d08482d839eb838566346f1737"}, + {file = "protobuf-3.15.8-cp35-cp35m-win32.whl", hash = "sha256:07eec4e2ccbc74e95bb9b3afe7da67957947ee95bdac2b2e91b038b832dd71f0"}, + {file = "protobuf-3.15.8-cp35-cp35m-win_amd64.whl", hash = "sha256:f9cadaaa4065d5dd4d15245c3b68b967b3652a3108e77f292b58b8c35114b56c"}, + {file = "protobuf-3.15.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2dc0e8a9e4962207bdc46a365b63a3f1aca6f9681a5082a326c5837ef8f4b745"}, + {file = "protobuf-3.15.8-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f80afc0a0ba13339bbab25ca0409e9e2836b12bb012364c06e97c2df250c3343"}, + {file = "protobuf-3.15.8-cp36-cp36m-win32.whl", hash = "sha256:c5566f956a26cda3abdfacc0ca2e21db6c9f3d18f47d8d4751f2209d6c1a5297"}, + {file = "protobuf-3.15.8-cp36-cp36m-win_amd64.whl", hash = "sha256:dab75b56a12b1ceb3e40808b5bd9dfdaef3a1330251956e6744e5b6ed8f8830b"}, + {file = "protobuf-3.15.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3053f13207e7f13dc7be5e9071b59b02020172f09f648e85dc77e3fcb50d1044"}, + {file = "protobuf-3.15.8-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1f0b5d156c3df08cc54bc2c8b8b875648ea4cd7ebb2a9a130669f7547ec3488c"}, + {file = "protobuf-3.15.8-cp37-cp37m-win32.whl", hash = "sha256:90270fe5732c1f1ff664a3bd7123a16456d69b4e66a09a139a00443a32f210b8"}, + {file = "protobuf-3.15.8-cp37-cp37m-win_amd64.whl", hash = "sha256:f42c2f5fb67da5905bfc03733a311f72fa309252bcd77c32d1462a1ad519521e"}, + {file = "protobuf-3.15.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6077db37bfa16494dca58a4a02bfdacd87662247ad6bc1f7f8d13ff3f0013e1"}, + {file = "protobuf-3.15.8-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:510e66491f1a5ac5953c908aa8300ec47f793130097e4557482803b187a8ee05"}, + {file = "protobuf-3.15.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5ff9fa0e67fcab442af9bc8d4ec3f82cb2ff3be0af62dba047ed4187f0088b7d"}, + {file = "protobuf-3.15.8-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1c0e9e56202b9dccbc094353285a252e2b7940b74fdf75f1b4e1b137833fabd7"}, + {file = "protobuf-3.15.8-py2.py3-none-any.whl", hash = "sha256:a0a08c6b2e6d6c74a6eb5bf6184968eefb1569279e78714e239d33126e753403"}, + {file = "protobuf-3.15.8.tar.gz", hash = "sha256:0277f62b1e42210cafe79a71628c1d553348da81cbd553402a7f7549c50b11d0"}, ] psaw = [ {file = "psaw-0.0.12-py3-none-any.whl", hash = "sha256:cfbfdf1953ee5f31ca9d4ec6d471873ace960da9fbc7234b9d19a059d5cfa2d6"}, @@ -4165,24 +4180,24 @@ pycodestyle = [ {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, ] pycoingecko = [ - {file = "pycoingecko-1.4.0-py3-none-any.whl", hash = "sha256:bc6e2d87a59bda88bd01a241b37d49c30104842534fdf65ba96616c90419d756"}, - {file = "pycoingecko-1.4.0.tar.gz", hash = "sha256:082949e83b49ab89090d19b88b6177c9458679dc4a98323db950bd4cef7afa2e"}, + {file = "pycoingecko-1.4.1-py3-none-any.whl", hash = "sha256:289e5d129872439c7d76cb60037078e72a84f6d24b6034dde12bb5dc87fccb82"}, + {file = "pycoingecko-1.4.1.tar.gz", hash = "sha256:de754cccc398feaf9230f710f93a15500af7457e86192fbceedf96ddfe8cabd4"}, ] pycparser = [ {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] pyflakes = [ - {file = "pyflakes-2.3.0-py2.py3-none-any.whl", hash = "sha256:910208209dcea632721cb58363d0f72913d9e8cf64dc6f8ae2e02a3609aba40d"}, - {file = "pyflakes-2.3.0.tar.gz", hash = "sha256:e59fd8e750e588358f1b8885e5a4751203a0516e0ee6d34811089ac294c8806f"}, + {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, + {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, ] pygments = [ {file = "Pygments-2.8.1-py3-none-any.whl", hash = "sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8"}, {file = "Pygments-2.8.1.tar.gz", hash = "sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94"}, ] pylint = [ - {file = "pylint-2.7.2-py3-none-any.whl", hash = "sha256:d09b0b07ba06bcdff463958f53f23df25e740ecd81895f7d2699ec04bbd8dc3b"}, - {file = "pylint-2.7.2.tar.gz", hash = "sha256:0e21d3b80b96740909d77206d741aa3ce0b06b41be375d92e1f3244a274c1f8a"}, + {file = "pylint-2.7.4-py3-none-any.whl", hash = "sha256:209d712ec870a0182df034ae19f347e725c1e615b2269519ab58a35b3fcbbe7a"}, + {file = "pylint-2.7.4.tar.gz", hash = "sha256:bd38914c7731cdc518634a8d3c5585951302b6e2b6de60fbb3f7a0220e21eeee"}, ] pymeeus = [ {file = "PyMeeus-0.5.11.tar.gz", hash = "sha256:bb9d670818d8b0594317b48a7dadea02a0594e5344263bf2054e1a011c8fed55"}, @@ -4246,16 +4261,16 @@ pystan = [ {file = "pystan-2.19.1.1.tar.gz", hash = "sha256:fa8bad8dbc0da22bbe6f36af56c9abbfcf10f92df8ce627d59a36bd8d25eb038"}, ] pytest = [ - {file = "pytest-6.2.2-py3-none-any.whl", hash = "sha256:b574b57423e818210672e07ca1fa90aaf194a4f63f3ab909a2c67ebb22913839"}, - {file = "pytest-6.2.2.tar.gz", hash = "sha256:9d1edf9e7d0b84d72ea3dbcdfd22b35fb543a5e8f2a60092dd578936bf63d7f9"}, + {file = "pytest-6.2.3-py3-none-any.whl", hash = "sha256:6ad9c7bdf517a808242b998ac20063c41532a570d088d77eec1ee12b0b5574bc"}, + {file = "pytest-6.2.3.tar.gz", hash = "sha256:671238a46e4df0f3498d1c3270e5deb9b32d25134c99b7d75370a68cfbe9b634"}, ] python-dateutil = [ {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, ] python-dotenv = [ - {file = "python-dotenv-0.15.0.tar.gz", hash = "sha256:587825ed60b1711daea4832cf37524dfd404325b7db5e25ebe88c495c9f807a0"}, - {file = "python_dotenv-0.15.0-py2.py3-none-any.whl", hash = "sha256:0c8d1b80d1a1e91717ea7d526178e3882732420b03f08afea0406db6402e220e"}, + {file = "python-dotenv-0.17.0.tar.gz", hash = "sha256:471b782da0af10da1a80341e8438fca5fadeba2881c54360d5fd8d03d03a4f4a"}, + {file = "python_dotenv-0.17.0-py2.py3-none-any.whl", hash = "sha256:49782a97c9d641e8a09ae1d9af0856cc587c8d2474919342d5104d85be9890b2"}, ] pytrends = [ {file = "pytrends-4.7.3-py3-none-any.whl", hash = "sha256:88d92e398b9408c79fd92946ddc2b03fa622301233bc49f16804042eb2897328"}, @@ -4266,8 +4281,8 @@ pytz = [ {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, ] pyupgrade = [ - {file = "pyupgrade-2.11.0-py2.py3-none-any.whl", hash = "sha256:47cd92db1675a9043bebbe0b67a103b66527883b35e22634060a6bcb99138baa"}, - {file = "pyupgrade-2.11.0.tar.gz", hash = "sha256:5dcae14b1c9b7ecce5ec42210528eb30a1a2408613da744f2ba4a9b54b344cf6"}, + {file = "pyupgrade-2.12.0-py2.py3-none-any.whl", hash = "sha256:024fc6be99c2ccdbc1c9354ac0ab8d5b9e5bf69a5477384677b6c9d8f2ce63bf"}, + {file = "pyupgrade-2.12.0.tar.gz", hash = "sha256:eef4d77e44e57dfbae897a9a61543be1f34701dbbe51cc18462210021bd28dcf"}, ] pywin32 = [ {file = "pywin32-300-cp35-cp35m-win32.whl", hash = "sha256:1c204a81daed2089e55d11eefa4826c05e604d27fe2be40b6bf8db7b6a39da63"}, @@ -4300,26 +4315,18 @@ pyyaml = [ {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, @@ -4389,67 +4396,67 @@ quandl = [ {file = "Quandl-3.6.1.tar.gz", hash = "sha256:84414e5f8e870a9c8a9392e9dc639d50e839c5f5e07737a09bb57dd8b14b264b"}, ] rapidfuzz = [ - {file = "rapidfuzz-1.3.0-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d49956421daad639040e44dc12b301eb3f105f2ca4a5e9b32ed6c9650f02789a"}, - {file = "rapidfuzz-1.3.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1d5a8f133fb85ea2ed882ab7053d69d0a60cc0c0a7e8bc30bb5e306066279508"}, - {file = "rapidfuzz-1.3.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9059004a081a86f3fbdb44e3d36897264196883a339f740476d1869dd41e4068"}, - {file = "rapidfuzz-1.3.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:c524cb3267a48ff826f54b70a396e0bc6eb5ba997f2900bc6eff242e43aaafb4"}, - {file = "rapidfuzz-1.3.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:ec74086dd1e00f8beeeda14aab80657c7dd84a8c4a7ab67bddce1f2ad41dbe1f"}, - {file = "rapidfuzz-1.3.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:b08e8f3dbfd718832dfc77ea87484a8b8942c4f3fafacfd92b1204679d97d8fd"}, - {file = "rapidfuzz-1.3.0-cp35-cp35m-manylinux2014_ppc64le.whl", hash = "sha256:3f07c9e13457620e32caa8192aa04e8bf8b99dab2d93a9679ef829c86e98fede"}, - {file = "rapidfuzz-1.3.0-cp35-cp35m-manylinux2014_s390x.whl", hash = "sha256:e61d8870134c3f419634387c9baa3997f4e5c4294fe620de39662562089212cf"}, - {file = "rapidfuzz-1.3.0-cp35-cp35m-win32.whl", hash = "sha256:aa19c9c1b53f6019de4d2451a62b2cba1dee49e53f58905c84215e17a4ba3fed"}, - {file = "rapidfuzz-1.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:3d2d91358994e2b8379dc529399521c2a3ec727bfdcea7552b0877be1ec54117"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:03d4fefc4a4ca0512040d0753d0be79d920d22e56cd2bc25f2ee6bdcd4176dc9"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:525634b52c0d9544b19105230fe0e09d2dce43901fa5f019a547d8667299f2b8"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c3679dad6789183219dea5ddb927bf62211dc1fdf5b6d17ad49971d2895f9518"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:6f18c4d9fc65caf6068e306acc40192ade6d9af88939eeda3617864b4d2e8abf"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:9aa106d30859a57a1447346cdeddeb7015748281f43f2054e3276551406c39c5"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:3efb9f3c0d1ea0ec82d38075306f7e721dd88fb9ec0684dd350d73d83df6ba53"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:ed0387466970882468535a4a49bc14336783c55035a7e5d0edb36d05e253b8fe"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:78b4e66dec10f9f3d7cc35e6924442b8c121bdaa8a0dbd70311561fd9ff87170"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-win32.whl", hash = "sha256:1cb927ea0904caad8f2923dfdfa0975c93fdc8528b882feda78cbfc373ffa229"}, - {file = "rapidfuzz-1.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2ba61d15d0ac83800f7a283b4c188ab54ac8595b1181714cc06b5f04ef33542a"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:076943f5b318483c263584cec59763d1aac70ea0dab5f5653fde495cd1e6395f"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:d25d6f7d94b17a962526c2261cc8fc2e292c5a071db810aeb9d48771ae9ec3e6"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d282448a4121a947daa540fdf0e9a8808adcf81168cfca0da9786768f6209fbb"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:bdb9942565fb10bca30e707b8c96e6e5544bd4c604394fc92596355c34fef258"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:324f6b13274abdbed51d709d6a930cf1408c26a8013e279283f0131b5fc29ac0"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:aae04e463205b363f95ca6971d7f9e3ed39f65a5ef7fee35b01775bba1dde374"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:67a0af6e486bc706f9f64cbd024a0d8d8b63726df95bb7c7a155791391f19567"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:9931dad05f4d51cc4a610db3f33cc3631c4547412b4925380cca7f6f07041cb0"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-win32.whl", hash = "sha256:eeb6e1c0d63dc4909dfb7daa105c035ff6713189b5ea1c312f7e760f986296c0"}, - {file = "rapidfuzz-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f22193795ef02f9a6bf90e3898a81b927dfdb80c62c6cd3e59d87330a6d4bcf1"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a73a69108cc96fad0f57f374315107eef9e80f997da7483799a262616cc0ef31"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9d97ae27902ffc2efa87b272a79a7376ddea1639b969bf995f2b521c88c2d99e"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:a2122c78ffcae47f562450928be439a5b94ddb5b0e0d8e365ee1d08e8fe6874f"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:b4e16aacf5969f0a24dc530d0aa610df105d8fa7dd2aa282a7db98a8039c1719"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:1b52b7139b98d559bbd977bd28b7e68a8d75dc2345122ca8fcf938e7ff72b295"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:25edcf5a805479dd434155ea88e9e76e9b3677b670800d5e95e04556e1a4a0e0"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:92ee666f0cfa47e74e745e2bb794b43c6eeba2931c873a91b45b3439018cae77"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:4ab4513fbe47618dab0ffbdea7beb73695d730a424b8df719aee80e48f8d00ff"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-win32.whl", hash = "sha256:3db9d3ea27f0926a137f0e0169f5b29dd49b88fb0171ed7dfce224b890a86f11"}, - {file = "rapidfuzz-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:41b28235f68475a865a94b4c0bee3259f525aac523d182432b68f5cafa35d9a1"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7891ecf01052b69c0e0cc94695a506dd1374636292eca26e061a0c1dc3165f02"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:096b445dca7972161cdd1f856969414dde7cc9b09ff420005092d7b31139d41c"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:66c5579effe2a846117b4f499ab6910d164804c8fe31846a80981992d1b78e6e"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2997f73a0cb5abc3a31e8c740a908be426d71db38827486881728470cc60b2c5"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4fbbe7129df9ecd818f259136f598241206a6ac10b09763eafcf6fd1ca0fe83f"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:24a8af40f7fc41795892be937cf3480d5cd8ae1f62ef6a845e7258d05c9ab35c"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f02b615ad69279e6ed61a7ba072494cd05cfddde210472956139d3361f8f20d1"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:45d20908601158d06c65d9ed4a54585dc32bd49cadefc385374f77b9a4696368"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:0e3570ea068e0704f7b43d5228e97c45954dec370114071139fdd9cf731a1750"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:f027a7df163f5f1d13d9ea60bf06d8bc0730194a2d584c3185c3a77c1a145916"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-win32.whl", hash = "sha256:460bacd89c129cf1aefc56ae465f642c712aa9b620e74305040a1cf6975cc510"}, - {file = "rapidfuzz-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:5afa7539fb45b3c97fed67ca75a99ad7affce14561a3bd11e1c8d665b20ea8ab"}, - {file = "rapidfuzz-1.3.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5cadbd3f5df7e02dc11b819af860cb1a5365a49de515b76bf5dad62a3724ebaf"}, - {file = "rapidfuzz-1.3.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:7e2196346ae5a1a2ac79c780d63983df93c1dbbea8aed910c43ad13c67bddc35"}, - {file = "rapidfuzz-1.3.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:ac3bc9341d8f265eb65a66ec88f351851e89a0f22be916ed4e74590e347f159e"}, - {file = "rapidfuzz-1.3.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:3438c6db485dd5a3716a7f2e92a262b05db959f03712c4423b68a32453a5957d"}, - {file = "rapidfuzz-1.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ac6016f99dc36d490251c8b0910d7445921ca950ac204a4d299c0a298db8f0c"}, - {file = "rapidfuzz-1.3.0-pp37-pypy37_pp73-manylinux1_x86_64.whl", hash = "sha256:9573c989a78866269ced934a5a345ea44d05f4b69576d91c7e5b21771d19e030"}, - {file = "rapidfuzz-1.3.0-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:6f97fdca7a43ddb4258ddc2d6a8e960b0f5b369346d8bac02cc20b7b51721eb1"}, - {file = "rapidfuzz-1.3.0-pp37-pypy37_pp73-win32.whl", hash = "sha256:c92b7e3148a90ac9f8740e4235c64cf5a02d15a4cfbd3aa580e62327e22d4d6a"}, - {file = "rapidfuzz-1.3.0.tar.gz", hash = "sha256:f6a95ed17d7750ca75f11751ab46365c58f37a5d846e2b21d072d7a0e77ffa72"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:72878878d6744883605b5453c382361716887e9e552f677922f76d93d622d8cb"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:56a67a5b3f783e9af73940f6945366408b3a2060fc6ab18466e5a2894fd85617"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f5d396b64f8ae3a793633911a1fb5d634ac25bf8f13d440139fa729131be42d8"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:4990698233e7eda7face7c09f5874a09760c7524686045cbb10317e3a7f3225f"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a87e212855b18a951e79ec71d71dbd856d98cd2019d0c2bd46ec30688a8aa68a"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1897d2ef03f5b51bc19bdb2d0398ae968766750fa319843733f0a8f12ddde986"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-manylinux2014_ppc64le.whl", hash = "sha256:e1fc4fd219057f5f1fa40bb9bc5e880f8ef45bf19350d4f5f15ca2ce7f61c99b"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-manylinux2014_s390x.whl", hash = "sha256:21300c4d048798985c271a8bf1ed1611902ebd4479fcacda1a3eaaebbad2f744"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:d2659967c6ac74211a87a1109e79253e4bc179641057c64800ef4e2dc0534fdb"}, + {file = "rapidfuzz-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:26ac4bfe564c516e053fc055f1543d2b2433338806738c7582e1f75ed0485f7e"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3b485c98ad1ce3c04556f65aaab5d6d6d72121cde656d43505169c71ae956476"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:59db06356eaf22c83f44b0dded964736cbb137291cdf2cf7b4974c0983b94932"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fef95249af9a535854b617a68788c38cd96308d97ee14d44bc598cc73e986167"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:7d8c186e8270e103d339b26ef498581cf3178470ccf238dfd5fd0e47d80e4c7d"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:9246b9c5c8992a83a08ac7813c8bbff2e674ad0b681f9b3fb1ec7641eff6c21f"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:f58c17f7a82b1bcc2ce304942cae14287223e6b6eead7071241273da7d9b9770"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:ed708620b23a09ac52eaaec0761943c1bbc9a62d19ecd2feb4da8c3f79ef9d37"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:bdec9ae5fd8a8d4d8813b4aac3505c027b922b4033a32a7aab66a9b2f03a7b47"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:fc668fd706ad1162ce14f26ca2957b4690d47770d23609756536c918a855ced0"}, + {file = "rapidfuzz-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f9f35df5dd9b02669ff6b1d4a386607ff56982c86a7e57d95eb08c6afbab4ddd"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8427310ea29ce2968e1c6f6779ae5a458b3a4984f9150fc4d16f92b96456f848"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1430dc745476e3798742ad835f61f6e6bf5d3e9a22cf9cd0288b28b7440a9872"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1d20311da611c8f4638a09e2bc5e04b327bae010cb265ef9628d9c13c6d5da7b"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7881965e428cf6fe248d6e702e6d5857da02278ab9b21313bee717c080e443e"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:f76c965f15861ec4d39e904bd65b84a39121334439ac17bfb8b900d1e6779a93"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:61167f989415e701ac379de247e6b0a21ea62afc86c54d8a79f485b4f0173c02"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:645cfb9456229f0bd5752b3eda69f221d825fbb8cbb8855433516bc185111506"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:c28be57c9bc47b3d7f484340fab1bec8ed4393dee1090892c2774a4584435eb8"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:3c94b6d3513c693f253ff762112cc4580d3bd377e4abacb96af31a3d606fbe14"}, + {file = "rapidfuzz-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:506d50a066451502ee2f8bf016bc3ba3e3b04eede7a4059d7956248e2dd96179"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:80b375098658bb3db14215a975d354f6573d3943ac2ae0c4627c7760d57ce075"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:ba8f7cbd8fdbd3ae115f4484888f3cb94bc2ac7cbd4eb1ca95a3d4f874261ff8"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5fa8570720b0fdfc52f24f5663d66c52ea88ba19cb8b1ff6a39a8bc0b925b33b"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:f35c8a4c690447fd335bfd77df4da42dfea37cfa06a8ecbf22543d86dc720e12"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:27f9eef48e212d73e78f0f5ceedc62180b68f6a25fa0752d2ccfaedc3a840bec"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:31e99216e2a04aec4f281d472b28a683921f1f669a429cf605d11526623eaeed"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:f22bf7ba6eddd59764457f74c637ab5c3ed976c5fcfaf827e1d320cc0478e12b"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:c43ddb354abd00e56f024ce80affb3023fa23206239bb81916d5877cba7f2d1e"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-win32.whl", hash = "sha256:62c1f4ac20c8019ce8d481fb27235306ef3912a8d0b9a60b17905699f43ff072"}, + {file = "rapidfuzz-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:2963f356c70b710dc6337b012ec976ce2fc2b81c2a9918a686838fead6eb4e1d"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c07f301fd549b266410654850c6918318d7dcde8201350e9ac0819f0542cf147"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa4c8b6fc7e93e3a3fb9be9566f1fe7ef920735eadcee248a0d70f3ca8941341"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c200bd813bbd3b146ba0fd284a9ad314bbad9d95ed542813273bdb9d0ee4e796"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2cccc84e1f0c6217747c09cafe93164e57d3644e18a334845a2dfbdd2073cd2c"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f2033e3d61d1e498f618123b54dc7436d50510b0d18fd678d867720e8d7b2f23"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:26b7f48b3ddd9d97cf8482a88f0f6cba47ac13ff16e63386ea7ce06178174770"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:bf18614f87fe3bfff783f0a3d0fad0eb59c92391e52555976e55570a651d2330"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:8cb5c2502ff06028a1468bdf61323b53cc3a37f54b5d62d62c5371795b81086a"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:f37f80c1541d6e0a30547261900086b8c0bac519ebc12c9cd6b61a9a43a7e195"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:c13cd1e840aa93639ac1d131fbfa740a609fd20dfc2a462d5cd7bce747a2398d"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-win32.whl", hash = "sha256:0ec346f271e96c485716c091c8b0b78ba52da33f7c6ebb52a349d64094566c2d"}, + {file = "rapidfuzz-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:5208ce1b1989a10e6fc5b5ef5d0bb7d1ffe5408838f3106abde241aff4dab08c"}, + {file = "rapidfuzz-1.4.1-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4fa195ea9ca35bacfa2a4319c6d4ab03aa6a283ad2089b70d2dfa0f6a7d9c1bc"}, + {file = "rapidfuzz-1.4.1-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:6e336cfd8103b0b38e107e01502e9d6bf7c7f04e49b970fb11a4bf6c7a932b94"}, + {file = "rapidfuzz-1.4.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:c798c5b87efe8a7e63f408e07ff3bc03ba8b94f4498a89b48eaab3a9f439d52c"}, + {file = "rapidfuzz-1.4.1-pp36-pypy36_pp73-win32.whl", hash = "sha256:bb16a10b40f5bd3c645f7748fbd36f49699a03f550c010a2c665905cc8937de8"}, + {file = "rapidfuzz-1.4.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2278001924031d9d75f821bff2c5fef565c8376f252562e04d8eec8857475c36"}, + {file = "rapidfuzz-1.4.1-pp37-pypy37_pp73-manylinux1_x86_64.whl", hash = "sha256:a89d11f3b5da35fdf3e839186203b9367d56e2be792e8dccb098f47634ec6eb9"}, + {file = "rapidfuzz-1.4.1-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:f8c79cd11b4778d387366a59aa747f5268433f9d68be37b00d16f4fb08fdf850"}, + {file = "rapidfuzz-1.4.1-pp37-pypy37_pp73-win32.whl", hash = "sha256:4364db793ed4b439f9dd28a335bee14e2a828283d3b93c2d2686cc645eeafdd5"}, + {file = "rapidfuzz-1.4.1.tar.gz", hash = "sha256:de20550178376d21bfe1b34a7dc42ab107bb282ef82069cf6dfe2805a0029e26"}, ] regex = [ {file = "regex-2020.11.13-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85"}, @@ -4514,7 +4521,8 @@ rsa = [ {file = "rsa-4.7.2.tar.gz", hash = "sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9"}, ] sacremoses = [ - {file = "sacremoses-0.0.43.tar.gz", hash = "sha256:123c1bf2664351fb05e16f87d3786dbe44a050cfd7b85161c09ad9a63a8e2948"}, + {file = "sacremoses-0.0.45-py3-none-any.whl", hash = "sha256:fa93db44bc04542553ba6090818b892f603d02aa0d681e6c5c3023baf17e8564"}, + {file = "sacremoses-0.0.45.tar.gz", hash = "sha256:58176cc28391830789b763641d0f458819bebe88681dac72b41a19c0aedc07e9"}, ] scikit-learn = [ {file = "scikit-learn-0.24.1.tar.gz", hash = "sha256:a0334a1802e64d656022c3bfab56a73fbd6bf4b1298343f3688af2151810bbdf"}, @@ -4523,7 +4531,6 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c658432d8a20e95398f6bb95ff9731ce9dfa343fdf21eea7ec6a7edfacd4b4d9"}, {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9dfa564ef27e8e674aa1cc74378416d580ac4ede1136c13dd555a87996e13422"}, {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:9c6097b6a9b2bafc5e0f31f659e6ab5e131383209c30c9e978c5b8abdac5ed2a"}, - {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:5580eba7345a4d3b097be2f067cc71a306c44bab19e8717a30361f279c929bea"}, {file = "scikit_learn-0.24.1-cp36-cp36m-win32.whl", hash = "sha256:7b04691eb2f41d2c68dbda8d1bd3cb4ef421bdc43aaa56aeb6c762224552dfb6"}, {file = "scikit_learn-0.24.1-cp36-cp36m-win_amd64.whl", hash = "sha256:1adf483e91007a87171d7ce58c34b058eb5dab01b5fee6052f15841778a8ecd8"}, {file = "scikit_learn-0.24.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:ddb52d088889f5596bc4d1de981f2eca106b58243b6679e4782f3ba5096fd645"}, @@ -4531,7 +4538,6 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0567a2d29ad08af98653300c623bd8477b448fe66ced7198bef4ed195925f082"}, {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:99349d77f54e11f962d608d94dfda08f0c9e5720d97132233ebdf35be2858b2d"}, {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:83b21ff053b1ff1c018a2d24db6dd3ea339b1acfbaa4d9c881731f43748d8b3b"}, - {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:abe835a851610f87201819cb315f8d554e1a3e8128912783a31e87264ba5ffb7"}, {file = "scikit_learn-0.24.1-cp37-cp37m-win32.whl", hash = "sha256:c3deb3b19dd9806acf00cf0d400e84562c227723013c33abefbbc3cf906596e9"}, {file = "scikit_learn-0.24.1-cp37-cp37m-win_amd64.whl", hash = "sha256:d54dbaadeb1425b7d6a66bf44bee2bb2b899fe3e8850b8e94cfb9c904dcb46d0"}, {file = "scikit_learn-0.24.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:3c4f07f47c04e81b134424d53c3f5e16dfd7f494e44fd7584ba9ce9de2c5e6c1"}, @@ -4539,7 +4545,6 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4ddd2b6f7449a5d539ff754fa92d75da22de261fd8fdcfb3596799fadf255101"}, {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:826b92bf45b8ad80444814e5f4ac032156dd481e48d7da33d611f8fe96d5f08b"}, {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:259ec35201e82e2db1ae2496f229e63f46d7f1695ae68eef9350b00dc74ba52f"}, - {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:9599a3f3bf33f73fed0fe06d1dfa4e6081365a58c1c807acb07271be0dce9733"}, {file = "scikit_learn-0.24.1-cp38-cp38-win32.whl", hash = "sha256:8772b99d683be8f67fcc04789032f1b949022a0e6880ee7b75a7ec97dbbb5d0b"}, {file = "scikit_learn-0.24.1-cp38-cp38-win_amd64.whl", hash = "sha256:ed9d65594948678827f4ff0e7ae23344e2f2b4cabbca057ccaed3118fdc392ca"}, {file = "scikit_learn-0.24.1-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:8aa1b3ac46b80eaa552b637eeadbbce3be5931e4b5002b964698e33a1b589e1e"}, @@ -4547,7 +4552,6 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:087dfede39efb06ab30618f9ab55a0397f29c38d63cd0ab88d12b500b7d65fd7"}, {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:895dbf2030aa7337649e36a83a007df3c9811396b4e2fa672a851160f36ce90c"}, {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:9a24d1ccec2a34d4cd3f2a1f86409f3f5954cc23d4d2270ba0d03cf018aa4780"}, - {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:54be0a60a5a35005ad69c75902e0f5c9f699db4547ead427e97ef881c3242e6f"}, {file = "scikit_learn-0.24.1-cp39-cp39-win32.whl", hash = "sha256:fab31f48282ebf54dd69f6663cd2d9800096bad1bb67bbc9c9ac84eb77b41972"}, {file = "scikit_learn-0.24.1-cp39-cp39-win_amd64.whl", hash = "sha256:4562dcf4793e61c5d0f89836d07bc37521c3a1889da8f651e2c326463c4bd697"}, ] @@ -4582,7 +4586,7 @@ screeninfo = [ {file = "screeninfo-0.6.7.tar.gz", hash = "sha256:1c4bac1ca329da3f68cbc4d2fbc92256aa9bb8ff8583ee3e14f91f0a7baa69cb"}, ] scs = [ - {file = "scs-2.1.2.tar.gz", hash = "sha256:667ed6019bb4e2f925bd9291161d2c61cc0077443094437b703ea905333fd585"}, + {file = "scs-2.1.3.tar.gz", hash = "sha256:7c9ca6730638abcbd004909e7f4816b9e2c1486d3e864b1a26261ca84002cbf0"}, ] seaborn = [ {file = "seaborn-0.11.1-py3-none-any.whl", hash = "sha256:4e1cce9489449a1c6ff3c567f2113cdb41122f727e27a984950d004a88ef3c5c"}, @@ -4630,7 +4634,8 @@ six = [ {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] smart-open = [ - {file = "smart_open-4.2.0.tar.gz", hash = "sha256:d9f5a0f173ccb9bbae528db5a3804f57145815774f77ef755b9b0f3b4b2a9dcb"}, + {file = "smart_open-5.0.0-py3-none-any.whl", hash = "sha256:ed310ac51a797051b42f9437a566ac8149a3abf8c80ab994a8bd92d96fb7cf44"}, + {file = "smart_open-5.0.0.tar.gz", hash = "sha256:02e5e02207d955a1f9fd924c37900ac272536bd24393ae731b6945d4f766015f"}, ] soupsieve = [ {file = "soupsieve-2.2.1-py3-none-any.whl", hash = "sha256:c2c1c2d44f158cdbddab7824a9af8c4f83c76b1e23e049479aa432feb6c4c23b"}, @@ -4671,7 +4676,12 @@ tenacity = [ {file = "tenacity-7.0.0.tar.gz", hash = "sha256:5bd16ef5d3b985647fe28dfa6f695d343aa26479a04e8792b9d3c8f49e361ae1"}, ] tensorboard = [ - {file = "tensorboard-2.4.1-py3-none-any.whl", hash = "sha256:7b8c53c396069b618f6f276ec94fc45d17e3282d668979216e5d30be472115e4"}, + {file = "tensorboard-2.5.0-py3-none-any.whl", hash = "sha256:e167460085b6528956b33bab1c970c989cdce47a6616273880733f5e7bde452e"}, +] +tensorboard-data-server = [ + {file = "tensorboard_data_server-0.6.0-py3-none-any.whl", hash = "sha256:a4b8e1c3fc85237b3afeef450db06c9a9b25f5854ad27c21667a90808acd1822"}, + {file = "tensorboard_data_server-0.6.0-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:2d723d73e3a3b0a4498f56c64c39e2e26ac192414891df22c9f152b7058fd6bc"}, + {file = "tensorboard_data_server-0.6.0-py3-none-manylinux2010_x86_64.whl", hash = "sha256:b620e520d3d535ceb896557acca0029fd7fd2f9f408af35abc2d2dad91f0345d"}, ] tensorboard-plugin-wit = [ {file = "tensorboard_plugin_wit-1.8.0-py3-none-any.whl", hash = "sha256:2a80d1c551d741e99b2f197bb915d8a133e24adb8da1732b840041860f91183a"}, @@ -4694,8 +4704,8 @@ termcolor = [ {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"}, ] terminado = [ - {file = "terminado-0.9.3-py3-none-any.whl", hash = "sha256:430e876ec9d4d93a4fd8a49e82dcfae0c25f846540d0c5ca774b397533e237e8"}, - {file = "terminado-0.9.3.tar.gz", hash = "sha256:261c0b7825fecf629666e1820b484a5380f7e54d6b8bd889fa482e99dcf9bde4"}, + {file = "terminado-0.9.4-py3-none-any.whl", hash = "sha256:daed77f9fad7b32558fa84b226a76f45a02242c20813502f36c4e1ade6d8f1ad"}, + {file = "terminado-0.9.4.tar.gz", hash = "sha256:9a7dbcfbc2778830eeb70261bf7aa9d98a3eac8631a3afe3febeb57c12f798be"}, ] testpath = [ {file = "testpath-0.4.4-py2.py3-none-any.whl", hash = "sha256:bfcf9411ef4bf3db7579063e0546938b1edda3d69f4e1fb8756991f5951f85d4"}, @@ -4795,8 +4805,8 @@ tornado = [ {file = "tornado-6.1.tar.gz", hash = "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791"}, ] tqdm = [ - {file = "tqdm-4.59.0-py2.py3-none-any.whl", hash = "sha256:9fdf349068d047d4cfbe24862c425883af1db29bcddf4b0eeb2524f6fbdb23c7"}, - {file = "tqdm-4.59.0.tar.gz", hash = "sha256:d666ae29164da3e517fcf125e41d4fe96e5bb375cd87ff9763f6b38b5592fe33"}, + {file = "tqdm-4.60.0-py2.py3-none-any.whl", hash = "sha256:daec693491c52e9498632dfbe9ccfc4882a557f5fa08982db1b4d3adbe0887c3"}, + {file = "tqdm-4.60.0.tar.gz", hash = "sha256:ebdebdb95e3477ceea267decfc0784859aa3df3e27e22d23b83e9b272bf157ae"}, ] tradingview-ta = [ {file = "tradingview_ta-3.2.3-py3-none-any.whl", hash = "sha256:5f6101239f452044d8c9421e80c7591befd717f159a562fb0fe66a306d63807e"}, @@ -4811,36 +4821,36 @@ transformers = [ {file = "transformers-3.5.1.tar.gz", hash = "sha256:0d637c6cecc13b12f33f9e79bf5757c85f433c851e3ae7845ff20b6c49f41441"}, ] typed-ast = [ - {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70"}, - {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487"}, - {file = "typed_ast-1.4.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412"}, - {file = "typed_ast-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400"}, - {file = "typed_ast-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606"}, - {file = "typed_ast-1.4.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64"}, - {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07"}, - {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc"}, - {file = "typed_ast-1.4.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a"}, - {file = "typed_ast-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151"}, - {file = "typed_ast-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3"}, - {file = "typed_ast-1.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41"}, - {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f"}, - {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581"}, - {file = "typed_ast-1.4.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37"}, - {file = "typed_ast-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd"}, - {file = "typed_ast-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496"}, - {file = "typed_ast-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc"}, - {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"}, - {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea"}, - {file = "typed_ast-1.4.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787"}, - {file = "typed_ast-1.4.2-cp38-cp38-win32.whl", hash = "sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2"}, - {file = "typed_ast-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937"}, - {file = "typed_ast-1.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1"}, - {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6"}, - {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166"}, - {file = "typed_ast-1.4.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d"}, - {file = "typed_ast-1.4.2-cp39-cp39-win32.whl", hash = "sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b"}, - {file = "typed_ast-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440"}, - {file = "typed_ast-1.4.2.tar.gz", hash = "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a"}, + {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, + {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, + {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"}, + {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"}, + {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"}, + {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"}, + {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"}, + {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"}, + {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"}, + {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"}, + {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"}, + {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"}, + {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"}, + {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"}, + {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"}, + {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"}, + {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"}, + {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"}, + {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"}, + {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"}, + {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"}, + {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"}, + {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"}, + {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"}, + {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"}, + {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"}, + {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"}, + {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"}, + {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"}, + {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, ] typing-extensions = [ {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"}, @@ -4945,62 +4955,62 @@ yarl = [ {file = "yarl-1.6.3.tar.gz", hash = "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10"}, ] yfinance = [ - {file = "yfinance-0.1.55.tar.gz", hash = "sha256:65d39bccf16bef35f6a08bf0df33650c0515b5ce8ea3c53924601f5fe00590cb"}, + {file = "yfinance-0.1.59.tar.gz", hash = "sha256:fe4dc46807eceadc6604bf51ece7297b752dc5402a38a87385094fbfc7565fa0"}, ] zipp = [ {file = "zipp-3.4.1-py3-none-any.whl", hash = "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"}, {file = "zipp-3.4.1.tar.gz", hash = "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76"}, ] "zope.interface" = [ - {file = "zope.interface-5.3.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:2ec58e1e1691dde4fbbd97f8610de0f8f1b1a38593653f7d3b8e931b9cd6d67f"}, - {file = "zope.interface-5.3.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:d3cd9bad547a8e5fbe712a1dc1413aff1b917e8d39a2cd1389a6f933b7a21460"}, - {file = "zope.interface-5.3.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:672668729edcba0f2ee522ab177fcad91c81cfce991c24d8767765e2637d3515"}, - {file = "zope.interface-5.3.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:79b6db1a18253db86e9bf1e99fa829d60fd3fc7ac04f4451c44e4bdcf6756a42"}, - {file = "zope.interface-5.3.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:74b331c5d5efdddf5bbd9e1f7d8cb91a0d6b9c4ba45ca3e9003047a84dca1a3b"}, - {file = "zope.interface-5.3.0-cp27-cp27m-win32.whl", hash = "sha256:9c7044dbbf8c58420a9ef4ed6901f5a8b7698d90cd984d7f57a18c78474686f6"}, - {file = "zope.interface-5.3.0-cp27-cp27m-win_amd64.whl", hash = "sha256:96c2e68385f3848d58f19b2975a675532abdb65c8fa5f04d94b95b27b6b1ffa7"}, - {file = "zope.interface-5.3.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:c7b6032dc4490b0dcaf078f09f5b382dc35493cb7f473840368bf0de3196c2b6"}, - {file = "zope.interface-5.3.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:0378a42ec284b65706d9ef867600a4a31701a0d6773434e6537cfc744e3343f4"}, - {file = "zope.interface-5.3.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:823d1b4a6a028b8327e64865e2c81a8959ae9f4e7c9c8e0eec814f4f9b36b362"}, - {file = "zope.interface-5.3.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:67aa26097e194947d29f2b5a123830e03da1519bcce10cac034a51fcdb99c34f"}, - {file = "zope.interface-5.3.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:b4d59ab3608538e550a72cea13d3c209dd72b6e19e832688da7884081c01594e"}, - {file = "zope.interface-5.3.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:28d8157f8c77662a1e0796a7d3cfa8910289131d4b4dd4e10b2686ab1309b67b"}, - {file = "zope.interface-5.3.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:26109c50ccbcc10f651f76277cfc05fba8418a907daccc300c9247f24b3158a2"}, - {file = "zope.interface-5.3.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:416feb6500f7b6fc00d32271f6b8495e67188cb5eb51fc8e289b81fdf465a9cb"}, - {file = "zope.interface-5.3.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:b51d3f1cd87f488455f43046d72003689024b0fa9b2d53635db7523033b19996"}, - {file = "zope.interface-5.3.0-cp35-cp35m-win32.whl", hash = "sha256:0e6cdbdd94ae94d1433ab51f46a76df0f2cd041747c31baec1c1ffa4e76bd0c1"}, - {file = "zope.interface-5.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:2c51689b7b40c7d9c7e8a678350e73dc647945a13b4e416e7a02bbf0c37bdb01"}, - {file = "zope.interface-5.3.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:f966765f54b536e791541458de84a737a6adba8467190f17a8fe7f85354ba908"}, - {file = "zope.interface-5.3.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:61b8454190b9cc87279232b6de28dee0bad040df879064bb2f0e505cda907918"}, - {file = "zope.interface-5.3.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8af4b3116e4a37059bc8c7fe36d4a73d7c1d8802a1d8b6e549f1380d13a40160"}, - {file = "zope.interface-5.3.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:7d79cd354ae0a033ac7b86a2889c9e8bb0bb48243a6ed27fc5064ce49b842ada"}, - {file = "zope.interface-5.3.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:54243053316b5eec92affe43bbace7c8cd946bc0974a4aa39ff1371df0677b22"}, - {file = "zope.interface-5.3.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:7426bea25bdf92f00fa52c7b30fcd2a2f71c21cf007178971b1f248b6c2d3145"}, - {file = "zope.interface-5.3.0-cp36-cp36m-win32.whl", hash = "sha256:92195df3913c1de80062635bf64cd7bd0d0934a7fa1689b6d287d1cbbd16922c"}, - {file = "zope.interface-5.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:c95b355dba2aaf5177dff943b25ded0529a7feb80021d5fdb114a99f0a1ef508"}, - {file = "zope.interface-5.3.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f3c37b0dc1898e305aad4f7a1d75f6da83036588c28a9ce0afc681ff5245a601"}, - {file = "zope.interface-5.3.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:527415b5ca201b4add44026f70278fbc0b942cf0801a26ca5527cb0389b6151e"}, - {file = "zope.interface-5.3.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c980ae87863d76b1ea9a073d6d95554b4135032d34bc541be50c07d4a085821b"}, - {file = "zope.interface-5.3.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:8b4b0034e6c7f30133fa64a1cc276f8f1a155ef9529e7eb93a3c1728b40c0f5c"}, - {file = "zope.interface-5.3.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:c02105deda867d09cdd5088d08708f06d75759df6f83d8f7007b06f422908a30"}, - {file = "zope.interface-5.3.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e8809b01f27f679e3023b9e2013051e0a3f17abff4228cb5197663afd8a0f2c7"}, - {file = "zope.interface-5.3.0-cp37-cp37m-win32.whl", hash = "sha256:221b41442cf4428fcda7fc958c9721c916709e2a3a9f584edd70f1493a09a762"}, - {file = "zope.interface-5.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:07d289358a8c565ea09e426590dd1179f93cf5ac3dd17d43fcc4fc63c1a9d275"}, - {file = "zope.interface-5.3.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:89a6091f2d07936c8a96ce56f2000ecbef20fb420a94845e7d53913c558a6378"}, - {file = "zope.interface-5.3.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a413c424199bcbab71bf5fa7538246f27177fbd6dd74b2d9c5f34878658807f8"}, - {file = "zope.interface-5.3.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:12588a46ae0a99f172c4524cbbc3bb870f32e0f8405e9fa11a5ef3fa3a808ad7"}, - {file = "zope.interface-5.3.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:11354fb8b8bdc5cdd66358ed4f1f0ce739d78ff6d215d33b8f3ae282258c0f11"}, - {file = "zope.interface-5.3.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:6e7305e42b5f54e5ccf51820de46f0a7c951ba7cb9e3f519e908545b0f5628d0"}, - {file = "zope.interface-5.3.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:520352b18adea5478bbf387e9c77910a914985671fe36bc5ef19fdcb67a854bc"}, - {file = "zope.interface-5.3.0-cp38-cp38-win32.whl", hash = "sha256:d12895cd083e35e9e032eb4b57645b91116f8979527381a8d864d1f6b8cb4a2e"}, - {file = "zope.interface-5.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:18c478b89b6505756f007dcf76a67224a23dcf0f365427742ed0c0473099caa4"}, - {file = "zope.interface-5.3.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:fa939c2e2468142c9773443d4038e7c915b0cc1b670d3c9192bdc503f7ea73e9"}, - {file = "zope.interface-5.3.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:02d3535aa18e34ce97c58d241120b7554f7d1cf4f8002fc9675cc7e7745d20e8"}, - {file = "zope.interface-5.3.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fcc5c1f95102989d2e116ffc8467963554ce89f30a65a3ea86a4d06849c498d8"}, - {file = "zope.interface-5.3.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:16caa44a06f6b0b2f7626ced4b193c1ae5d09c1b49c9b4962c93ae8aa2134f55"}, - {file = "zope.interface-5.3.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:8715717a5861932b7fe7f3cbd498c82ff4132763e2fea182cc95e53850394ec1"}, - {file = "zope.interface-5.3.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a1937efed7e3fe0ee74630e1960df887d8aa83c571e1cf4db9d15b9c181d457d"}, - {file = "zope.interface-5.3.0-cp39-cp39-win32.whl", hash = "sha256:7234ac6782ca43617de803735949f79b894f0c5d353fbc001d745503c69e6d1d"}, - {file = "zope.interface-5.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:a38c10423a475a1658e2cb8f52cf84ec20a4c0adff724dd43a6b45183f499bc1"}, - {file = "zope.interface-5.3.0.tar.gz", hash = "sha256:b18a855f8504743e0a2d8b75d008c7720d44e4c76687e13f959e35d9a13eb397"}, + {file = "zope.interface-5.4.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:7df1e1c05304f26faa49fa752a8c690126cf98b40b91d54e6e9cc3b7d6ffe8b7"}, + {file = "zope.interface-5.4.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:2c98384b254b37ce50eddd55db8d381a5c53b4c10ee66e1e7fe749824f894021"}, + {file = "zope.interface-5.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:08f9636e99a9d5410181ba0729e0408d3d8748026ea938f3b970a0249daa8192"}, + {file = "zope.interface-5.4.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ea1d73b7c9dcbc5080bb8aaffb776f1c68e807767069b9ccdd06f27a161914a"}, + {file = "zope.interface-5.4.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:273f158fabc5ea33cbc936da0ab3d4ba80ede5351babc4f577d768e057651531"}, + {file = "zope.interface-5.4.0-cp27-cp27m-win32.whl", hash = "sha256:a1e6e96217a0f72e2b8629e271e1b280c6fa3fe6e59fa8f6701bec14e3354325"}, + {file = "zope.interface-5.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:877473e675fdcc113c138813a5dd440da0769a2d81f4d86614e5d62b69497155"}, + {file = "zope.interface-5.4.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f7ee479e96f7ee350db1cf24afa5685a5899e2b34992fb99e1f7c1b0b758d263"}, + {file = "zope.interface-5.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:b0297b1e05fd128d26cc2460c810d42e205d16d76799526dfa8c8ccd50e74959"}, + {file = "zope.interface-5.4.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:af310ec8335016b5e52cae60cda4a4f2a60a788cbb949a4fbea13d441aa5a09e"}, + {file = "zope.interface-5.4.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:9a9845c4c6bb56e508651f005c4aeb0404e518c6f000d5a1123ab077ab769f5c"}, + {file = "zope.interface-5.4.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0b465ae0962d49c68aa9733ba92a001b2a0933c317780435f00be7ecb959c702"}, + {file = "zope.interface-5.4.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:5dd9ca406499444f4c8299f803d4a14edf7890ecc595c8b1c7115c2342cadc5f"}, + {file = "zope.interface-5.4.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:469e2407e0fe9880ac690a3666f03eb4c3c444411a5a5fddfdabc5d184a79f05"}, + {file = "zope.interface-5.4.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:52de7fc6c21b419078008f697fd4103dbc763288b1406b4562554bd47514c004"}, + {file = "zope.interface-5.4.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:3dd4952748521205697bc2802e4afac5ed4b02909bb799ba1fe239f77fd4e117"}, + {file = "zope.interface-5.4.0-cp35-cp35m-win32.whl", hash = "sha256:dd93ea5c0c7f3e25335ab7d22a507b1dc43976e1345508f845efc573d3d779d8"}, + {file = "zope.interface-5.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:3748fac0d0f6a304e674955ab1365d515993b3a0a865e16a11ec9d86fb307f63"}, + {file = "zope.interface-5.4.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:66c0061c91b3b9cf542131148ef7ecbecb2690d48d1612ec386de9d36766058f"}, + {file = "zope.interface-5.4.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:d0c1bc2fa9a7285719e5678584f6b92572a5b639d0e471bb8d4b650a1a910920"}, + {file = "zope.interface-5.4.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2876246527c91e101184f63ccd1d716ec9c46519cc5f3d5375a3351c46467c46"}, + {file = "zope.interface-5.4.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:334701327f37c47fa628fc8b8d28c7d7730ce7daaf4bda1efb741679c2b087fc"}, + {file = "zope.interface-5.4.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:71aace0c42d53abe6fc7f726c5d3b60d90f3c5c055a447950ad6ea9cec2e37d9"}, + {file = "zope.interface-5.4.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:5bb3489b4558e49ad2c5118137cfeaf59434f9737fa9c5deefc72d22c23822e2"}, + {file = "zope.interface-5.4.0-cp36-cp36m-win32.whl", hash = "sha256:1c0e316c9add0db48a5b703833881351444398b04111188069a26a61cfb4df78"}, + {file = "zope.interface-5.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f0c02cbb9691b7c91d5009108f975f8ffeab5dff8f26d62e21c493060eff2a1"}, + {file = "zope.interface-5.4.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:7d97a4306898b05404a0dcdc32d9709b7d8832c0c542b861d9a826301719794e"}, + {file = "zope.interface-5.4.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:867a5ad16892bf20e6c4ea2aab1971f45645ff3102ad29bd84c86027fa99997b"}, + {file = "zope.interface-5.4.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5f931a1c21dfa7a9c573ec1f50a31135ccce84e32507c54e1ea404894c5eb96f"}, + {file = "zope.interface-5.4.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:194d0bcb1374ac3e1e023961610dc8f2c78a0f5f634d0c737691e215569e640d"}, + {file = "zope.interface-5.4.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:8270252effc60b9642b423189a2fe90eb6b59e87cbee54549db3f5562ff8d1b8"}, + {file = "zope.interface-5.4.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:15e7d1f7a6ee16572e21e3576d2012b2778cbacf75eb4b7400be37455f5ca8bf"}, + {file = "zope.interface-5.4.0-cp37-cp37m-win32.whl", hash = "sha256:8892f89999ffd992208754851e5a052f6b5db70a1e3f7d54b17c5211e37a98c7"}, + {file = "zope.interface-5.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2e5a26f16503be6c826abca904e45f1a44ff275fdb7e9d1b75c10671c26f8b94"}, + {file = "zope.interface-5.4.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:0f91b5b948686659a8e28b728ff5e74b1be6bf40cb04704453617e5f1e945ef3"}, + {file = "zope.interface-5.4.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:4de4bc9b6d35c5af65b454d3e9bc98c50eb3960d5a3762c9438df57427134b8e"}, + {file = "zope.interface-5.4.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bf68f4b2b6683e52bec69273562df15af352e5ed25d1b6641e7efddc5951d1a7"}, + {file = "zope.interface-5.4.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:63b82bb63de7c821428d513607e84c6d97d58afd1fe2eb645030bdc185440120"}, + {file = "zope.interface-5.4.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:db1fa631737dab9fa0b37f3979d8d2631e348c3b4e8325d6873c2541d0ae5a48"}, + {file = "zope.interface-5.4.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:f44e517131a98f7a76696a7b21b164bcb85291cee106a23beccce454e1f433a4"}, + {file = "zope.interface-5.4.0-cp38-cp38-win32.whl", hash = "sha256:a9506a7e80bcf6eacfff7f804c0ad5350c8c95b9010e4356a4b36f5322f09abb"}, + {file = "zope.interface-5.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:3c02411a3b62668200910090a0dff17c0b25aaa36145082a5a6adf08fa281e54"}, + {file = "zope.interface-5.4.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:0cee5187b60ed26d56eb2960136288ce91bcf61e2a9405660d271d1f122a69a4"}, + {file = "zope.interface-5.4.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:a8156e6a7f5e2a0ff0c5b21d6bcb45145efece1909efcbbbf48c56f8da68221d"}, + {file = "zope.interface-5.4.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:205e40ccde0f37496904572035deea747390a8b7dc65146d30b96e2dd1359a83"}, + {file = "zope.interface-5.4.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:3f24df7124c323fceb53ff6168da70dbfbae1442b4f3da439cd441681f54fe25"}, + {file = "zope.interface-5.4.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:5208ebd5152e040640518a77827bdfcc73773a15a33d6644015b763b9c9febc1"}, + {file = "zope.interface-5.4.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:17776ecd3a1fdd2b2cd5373e5ef8b307162f581c693575ec62e7c5399d80794c"}, + {file = "zope.interface-5.4.0-cp39-cp39-win32.whl", hash = "sha256:d4d9d6c1a455d4babd320203b918ccc7fcbefe308615c521062bc2ba1aa4d26e"}, + {file = "zope.interface-5.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:0cba8477e300d64a11a9789ed40ee8932b59f9ee05f85276dbb4b59acee5dd09"}, + {file = "zope.interface-5.4.0.tar.gz", hash = "sha256:5dba5f530fec3f0988d83b78cc591b58c0b6eb8431a85edd1569a0539a8a5a0e"}, ] diff --git a/requirements-full.txt b/requirements-full.txt index 1c51e43294a..c572e8e2936 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -1,20 +1,20 @@ absl-py==0.12.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" aiohttp==3.7.4.post0; python_version >= "3.6" -alpaca-trade-api==1.1.0 +alpaca-trade-api==1.2.0 alpha-vantage==2.3.1 ansiwrap==0.8.4; python_version >= "3.6" appdirs==1.4.4; python_version >= "3.6" appnope==0.1.2; platform_system == "Darwin" and python_version >= "3.6" and sys_platform == "darwin" -argon2-cffi==20.1.0; python_version >= "3.5" +argon2-cffi==20.1.0; python_version >= "3.6" astunparse==1.6.3 async-generator==1.10; python_full_version >= "3.6.1" and python_version >= "3.6" async-timeout==3.0.1; python_full_version >= "3.5.3" and python_version >= "3.6" attrs==20.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" backcall==0.2.0; python_version >= "3.6" -beautifulsoup4==4.9.3 +beautifulsoup4==4.9.3; python_version >= "3.5" black==20.8b1; python_version >= "3.6" bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -bpemb==0.3.2; python_version >= "3.6" +bpemb==0.3.3; python_version >= "3.6" bs4==0.0.1 cachetools==4.2.1; python_version >= "3.5" and python_version < "4.0" and (python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0") certifi==2020.12.5; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" @@ -24,32 +24,36 @@ click==7.1.2; python_full_version >= "3.6.0" and python_version >= "3.6" cloudpickle==1.6.0; python_version >= "3.6" cmdstanpy==0.4.0 colorama==0.4.4; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") -convertdate==2.3.1; python_version >= "3.5" +convertdate==2.3.2; python_version >= "3.5" +cryptography==3.4.7; python_version >= "3.6" cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" +cvxpy==1.1.12; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" cycler==0.10.0; python_version >= "3.6" -cython==0.29.14; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" +cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and python_version >= "3.6" and sys_platform == "darwin" dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.6.2" +datetime==4.3; python_version >= "3.5" decorator==4.4.2; 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.2.0" and python_version >= "3.6") defusedxml==0.7.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -deprecated==1.2.11; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" -detecta==0.0.5 +deprecated==1.2.12; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +detecta==0.0.5; python_version >= "3.6" +ecos==2.0.7.post1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" entrypoints==0.3; python_version >= "3.6" ephem==3.7.7.1; python_version >= "2.7" and python_version < "4" fbprophet==0.6 filelock==3.0.12; python_full_version >= "3.6.0" and python_version >= "3.6" -finviz==1.3.4 -finvizfinance==0.9.3 +finviz==1.4.1 +finvizfinance==0.9.6; python_version >= "3.5" flair==0.7; python_version >= "3.6" flatbuffers==1.12 fredapi==0.4.3 -ftfy==5.9; python_version >= "3.6" -fundamentalanalysis==0.2.6 +ftfy==6.0.1; python_version >= "3.6" +fundamentalanalysis==0.2.7 future==0.18.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" gast==0.3.3; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" gdown==3.12.2; python_version >= "3.6" -gensim==3.8.3; python_version >= "3.6" -google-auth-oauthlib==0.4.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" -google-auth==1.27.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" +gensim==3.8.2; python_version >= "3.6" +google-auth-oauthlib==0.4.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" +google-auth==1.29.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" google-pasta==0.2.0 grpcio==1.32.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" h5py==2.10.0 @@ -58,9 +62,9 @@ holidays==0.10.5.2 hyperopt==0.2.5; python_version >= "3.6" idna-ssl==1.1.0; python_version < "3.7" and python_version >= "3.6" idna==2.10; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version < "3.7" and python_version >= "3.6" and python_full_version >= "3.5.0" -importlib-metadata==3.7.2; python_version < "3.8" and python_version >= "3.6" and python_full_version >= "3.6.1" and python_full_version < "4.0.0" and (python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_full_version >= "3.2.0" and python_version >= "3.6" and python_version < "3.8") +importlib-metadata==4.0.0; python_version < "3.8" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_full_version >= "3.2.0" and python_version >= "3.6" and python_version < "3.8") inflection==0.5.1; python_version >= "3.5" -ipykernel==5.5.0; python_version >= "3.6" +ipykernel==5.5.3; python_version >= "3.6" ipython-genutils==0.2.0; python_full_version >= "3.6.1" and python_version >= "3.6" ipython==7.16.1; python_version >= "3.6" ipywidgets==7.6.3 @@ -70,112 +74,121 @@ jedi==0.18.0; python_version >= "3.6" jinja2==2.11.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" joblib==1.0.1; python_version >= "3.6" and python_full_version >= "3.6.0" jsonschema==3.2.0; python_version >= "3.6" -jupyter-client==6.1.11; python_full_version >= "3.6.1" and python_version >= "3.6" -jupyter-console==6.2.0; python_version >= "3.6" +jupyter-client==6.2.0; python_full_version >= "3.6.1" and python_version >= "3.6" +jupyter-console==6.4.0; python_version >= "3.6" jupyter-core==4.7.1; python_full_version >= "3.6.1" and python_version >= "3.6" jupyter==1.0.0 jupyterlab-pygments==0.1.2; python_version >= "3.6" jupyterlab-widgets==1.0.0; python_version >= "3.6" keras-preprocessing==1.1.2 kiwisolver==1.3.1; python_version >= "3.6" -konoha==4.6.4; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" +konoha==4.6.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" korean-lunar-calendar==0.2.1 langdetect==1.0.8; python_version >= "3.6" lunarcalendar==0.0.9; python_version >= "2.7" and python_version < "4" -lxml==4.6.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +lxml==4.6.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" markdown==3.3.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" markupsafe==1.1.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" matplotlib==3.3.4; python_version >= "3.6" mistune==0.8.4; python_version >= "3.6" more-itertools==8.7.0; python_version >= "3.5" mpld3==0.3; python_version >= "3.6" -mplfinance==0.12.7a7 +mplfinance==0.12.7a12 +msgpack==1.0.2 multidict==5.1.0; python_version >= "3.6" multitasking==0.0.9 mypy-extensions==0.4.3; python_version >= "3.6" nbclient==0.5.3; python_full_version >= "3.6.1" and python_version >= "3.6" nbconvert==6.0.7; python_version >= "3.6" -nbformat==5.1.2; python_full_version >= "3.6.1" and python_version >= "3.6" +nbformat==5.1.3; python_full_version >= "3.6.1" and python_version >= "3.6" nest-asyncio==1.5.1; python_full_version >= "3.6.1" and python_version >= "3.6" -networkx==2.5; python_version >= "3.6" -notebook==6.2.0; python_version >= "3.5" -numpy==1.19.5; python_version >= "3.6" and python_full_version >= "3.6.2" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6") -oauthlib==3.1.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +networkx==2.5.1; python_version >= "3.6" +notebook==6.3.0; python_version >= "3.6" +numpy==1.19.5; python_version >= "3.6" +oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" opt-einsum==3.3.0; python_version >= "3.5" +osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" overrides==3.1.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" packaging==20.9; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") pandas-ta==0.2.45b pandas==1.1.5; python_full_version >= "3.6.1" pandocfilters==1.4.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" papermill==2.3.3; python_version >= "3.6" -parso==0.8.1; python_version >= "3.6" +parso==0.8.2; python_version >= "3.6" pathspec==0.8.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" patsy==0.5.1; python_version >= "3.6" pexpect==4.8.0; sys_platform != "win32" and python_version >= "3.6" pickleshare==0.7.5; python_version >= "3.6" -pillow==8.1.2; python_version >= "3.6" +pillow==8.2.0; python_version >= "3.6" plotly==4.14.3 pmdarima==1.8.0; python_version >= "3.6" praw==7.2.0; python_version >= "3.6" and python_version < "4.0" prawcore==2.0.0; python_version >= "3.6" and python_version < "4.0" prettytable==2.1.0; python_version >= "3.6" -prometheus-client==0.9.0; python_version >= "3.5" -prompt-toolkit==3.0.17; python_full_version >= "3.6.1" -protobuf==3.15.6; python_full_version >= "3.6.0" and python_version >= "3.6" +prometheus-client==0.10.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +prompt-toolkit==3.0.18; python_full_version >= "3.6.1" +protobuf==3.15.8; python_full_version >= "3.6.0" and python_version >= "3.6" psaw==0.0.12; python_version >= "3" ptyprocess==0.7.0; os_name != "nt" and python_version >= "3.6" and sys_platform != "win32" py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" and implementation_name == "pypy" or implementation_name == "pypy" and python_version >= "3.6" and python_full_version >= "3.4.0" pyally==1.1.2 pyasn1-modules==0.2.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.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.0 -pycparser==2.20; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.5" +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" pygments==2.8.1; python_version >= "3.6" -pymeeus==0.5.9; python_version >= "3.5" +pymeeus==0.5.11; python_version >= "3.5" +pyobjc-core==7.1; python_version >= "3.6" and sys_platform == "darwin" +pyobjc-framework-cocoa==7.1; python_version >= "3.6" and sys_platform == "darwin" +pyotp==2.6.0; python_version >= "3" pyparsing==2.4.7; python_full_version >= "3.6.0" 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") -pyportfolioopt==1.4.1 -pyrsistent==0.17.3; python_version >= "3.6" +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" pystan==2.19.1.1 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" pytrends==4.7.3 pytz==2021.1; python_full_version >= "3.6.1" and python_version >= "3.5" and python_version < "4" pywin32==300; sys_platform == "win32" and python_version >= "3.6" pywinpty==0.5.7; os_name == "nt" and python_version >= "3.6" pyyaml==5.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" pyzmq==22.0.3; python_full_version >= "3.6.1" and python_version >= "3.6" -qtconsole==5.0.2; python_version >= "3.6" +qdldl==0.1.5.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +qtconsole==5.0.3; python_version >= "3.6" qtpy==1.9.0; python_version >= "3.6" quandl==3.6.1; python_version >= "3.5" -rapidfuzz==1.2.1; python_version >= "2.7" -regex==2020.11.13; python_full_version >= "3.6.0" and python_version >= "3.6" +rapidfuzz==1.4.1; python_version >= "3.5" +regex==2020.11.13 requests-oauthlib==1.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" requests==2.25.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") retrying==1.3.3 -robin-stocks==2.0.3 +robin-stocks==2.0.3; python_version >= "3" rsa==4.7.2; 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") -sacremoses==0.0.43; python_full_version >= "3.6.0" and python_version >= "3.6" +sacremoses==0.0.45; python_full_version >= "3.6.0" and python_version >= "3.6" scikit-learn==0.24.1; python_version >= "3.6" scipy==1.5.4; python_version >= "3.6" +screeninfo==0.6.7 +scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" seaborn==0.11.1; python_version >= "3.6" segtok==1.5.10; python_version >= "3.6" -send2trash==1.5.0; python_version >= "3.5" +send2trash==1.5.0; python_version >= "3.6" sentencepiece==0.1.91; python_full_version >= "3.6.0" and python_version >= "3.6" setuptools-git==1.2 -six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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.6.0") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.5") -smart-open==4.2.0; python_version >= "3.6" -soupsieve==2.2; python_version >= "3.6" +six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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.6.0") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") +smart-open==5.0.0; python_version >= "3.6" +soupsieve==2.2.1; python_version >= "3.6" sqlitedict==1.7.0; python_version >= "3.6" statsmodels==0.12.2; python_version >= "3.6" -screeninfo==0.6.7; -tabulate==0.8.9; python_version >= "3.6" +tabulate==0.8.9 tenacity==7.0.0; python_version >= "3.6" +tensorboard-data-server==0.6.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" tensorboard-plugin-wit==1.8.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" -tensorboard==2.4.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" +tensorboard==2.5.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" tensorflow-estimator==2.4.0 tensorflow==2.4.1 termcolor==1.1.0 -terminado==0.9.2; python_version >= "3.6" +terminado==0.9.4; python_version >= "3.6" testpath==0.4.4; python_version >= "3.6" textwrap3==0.9.2; python_version >= "3.6" threadpoolctl==2.1.0; python_version >= "3.6" @@ -184,21 +197,23 @@ tokenizers==0.9.3; python_full_version >= "3.6.0" and python_version >= "3.6" toml==0.10.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" torch==1.7.1; python_full_version >= "3.6.2" tornado==6.1; python_full_version >= "3.6.1" and python_version >= "3.6" -tqdm==4.59.0; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6") +tqdm==4.60.0; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6") +tradingview-ta==3.2.3; python_version >= "3.5" traitlets==4.3.3; python_full_version >= "3.6.1" and python_version >= "3.6" -tradingview-ta==3.2.3 transformers==3.5.1; python_full_version >= "3.6.0" -typed-ast==1.4.2; python_version >= "3.6" +typed-ast==1.4.3; python_version >= "3.6" typing-extensions==3.7.4.3; python_full_version >= "3.6.2" and python_version >= "3.6" and python_version < "3.8" update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0" -urllib3==1.26.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6" +urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6" user-agent==0.1.9 wcwidth==0.2.5; python_version >= "3.6" and python_full_version >= "3.6.1" webencodings==0.5.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" websocket-client==0.58.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0" +websockets==8.1; python_full_version >= "3.6.1" werkzeug==1.0.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" widgetsnbextension==3.5.1 wrapt==1.12.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" yarl==1.6.3; python_version >= "3.6" -yfinance==0.1.55 +yfinance==0.1.59 zipp==3.4.1; python_version < "3.8" and python_version >= "3.6" +zope.interface==5.4.0; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" diff --git a/requirements.txt b/requirements.txt index 4f4ba01310a..b73282d30c2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,15 @@ aiohttp==3.7.4.post0; python_version >= "3.6" -alpaca-trade-api==1.1.0 +alpaca-trade-api==1.2.0 alpha-vantage==2.3.1 ansiwrap==0.8.4; python_version >= "3.6" appdirs==1.4.4; python_version >= "3.6" appnope==0.1.2; platform_system == "Darwin" and python_version >= "3.6" and sys_platform == "darwin" -argon2-cffi==20.1.0; python_version >= "3.5" +argon2-cffi==20.1.0; python_version >= "3.6" async-generator==1.10; python_full_version >= "3.6.1" and python_version >= "3.6" async-timeout==3.0.1; python_full_version >= "3.5.3" and python_version >= "3.6" attrs==20.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" backcall==0.2.0; python_version >= "3.6" -beautifulsoup4==4.9.3 +beautifulsoup4==4.9.3; python_version >= "3.5" black==20.8b1; python_version >= "3.6" bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" bs4==0.0.1 @@ -18,124 +18,149 @@ cffi==1.14.5; implementation_name == "pypy" and python_version >= "3.6" chardet==4.0.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" click==7.1.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" colorama==0.4.4; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") -convertdate==2.3.1; python_version >= "3.5" +convertdate==2.3.2; python_version >= "3.5" +cryptography==3.4.7; python_version >= "3.6" cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" +cvxpy==1.1.12; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" cycler==0.10.0; python_version >= "3.6" +cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and python_version >= "3.6" and sys_platform == "darwin" dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" +datetime==4.3; python_version >= "3.5" decorator==4.4.2; 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.2.0" and python_version >= "3.6") defusedxml==0.7.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -detecta==0.0.5 +detecta==0.0.5; python_version >= "3.6" +ecos==2.0.7.post1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" entrypoints==0.3; python_version >= "3.6" -finviz==1.3.4 -finvizfinance==0.9.3 +finviz==1.4.1 +finvizfinance==0.9.6; python_version >= "3.5" fredapi==0.4.3 -fundamentalanalysis==0.2.6 +fundamentalanalysis==0.2.7 +h5py==2.10.0 hijri-converter==2.1.1; python_version >= "3.6" holidays==0.10.5.2 idna-ssl==1.1.0; python_version < "3.7" and python_version >= "3.6" idna==2.10; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version < "3.7" and python_version >= "3.6" and python_full_version >= "3.5.0" -importlib-metadata==3.7.2; python_version < "3.8" and python_version >= "3.6" +importlib-metadata==4.0.0; python_version < "3.8" and python_version >= "3.6" inflection==0.5.1; python_version >= "3.5" -ipykernel==5.5.0; python_version >= "3.6" +ipykernel==5.5.3; python_version >= "3.6" ipython-genutils==0.2.0; python_full_version >= "3.6.1" and python_version >= "3.6" ipython==7.16.1; python_version >= "3.6" ipywidgets==7.6.3 iso8601==0.1.14 jedi==0.18.0; python_version >= "3.6" jinja2==2.11.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +joblib==1.0.1; python_version >= "3.6" jsonschema==3.2.0; python_version >= "3.6" -jupyter-client==6.1.11; python_full_version >= "3.6.1" and python_version >= "3.6" -jupyter-console==6.2.0; python_version >= "3.6" +jupyter-client==6.2.0; python_full_version >= "3.6.1" and python_version >= "3.6" +jupyter-console==6.4.0; python_version >= "3.6" jupyter-core==4.7.1; python_full_version >= "3.6.1" and python_version >= "3.6" jupyter==1.0.0 jupyterlab-pygments==0.1.2; python_version >= "3.6" jupyterlab-widgets==1.0.0; python_version >= "3.6" kiwisolver==1.3.1; python_version >= "3.6" korean-lunar-calendar==0.2.1 -lxml==4.6.2; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" +lxml==4.6.3; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" markupsafe==1.1.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" matplotlib==3.3.4; python_version >= "3.6" mistune==0.8.4; python_version >= "3.6" more-itertools==8.7.0; python_version >= "3.5" -mplfinance==0.12.7a7 +mplfinance==0.12.7a12 +msgpack==1.0.2 multidict==5.1.0; python_version >= "3.6" multitasking==0.0.9 mypy-extensions==0.4.3; python_version >= "3.6" nbclient==0.5.3; python_full_version >= "3.6.1" and python_version >= "3.6" nbconvert==6.0.7; python_version >= "3.6" -nbformat==5.1.2; python_full_version >= "3.6.1" and python_version >= "3.6" +nbformat==5.1.3; python_full_version >= "3.6.1" and python_version >= "3.6" nest-asyncio==1.5.1; python_full_version >= "3.6.1" and python_version >= "3.6" -notebook==6.2.0; python_version >= "3.5" -numpy==1.19.5; python_version >= "3.6" and python_full_version >= "3.6.1" +notebook==6.3.0; python_version >= "3.6" +numpy==1.19.5; python_version >= "3.6" +oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" +osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" packaging==20.9; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pandas-ta==0.2.45b pandas==1.1.5; python_full_version >= "3.6.1" pandocfilters==1.4.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" papermill==2.3.3; python_version >= "3.6" -parso==0.8.1; python_version >= "3.6" +parso==0.8.2; python_version >= "3.6" pathspec==0.8.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +patsy==0.5.1; python_version >= "3.6" pexpect==4.8.0; sys_platform != "win32" and python_version >= "3.6" pickleshare==0.7.5; python_version >= "3.6" -pillow==8.1.2; python_version >= "3.6" +pillow==8.2.0; python_version >= "3.6" plotly==4.14.3 +pmdarima==1.8.0; python_version >= "3.6" praw==7.2.0; python_version >= "3.6" and python_version < "4.0" prawcore==2.0.0; python_version >= "3.6" and python_version < "4.0" prettytable==2.1.0; python_version >= "3.6" -prometheus-client==0.9.0; python_version >= "3.5" -prompt-toolkit==3.0.17; python_full_version >= "3.6.1" +prometheus-client==0.10.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +prompt-toolkit==3.0.18; python_full_version >= "3.6.1" psaw==0.0.12; python_version >= "3" ptyprocess==0.7.0; os_name != "nt" and python_version >= "3.6" and sys_platform != "win32" py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" and implementation_name == "pypy" or implementation_name == "pypy" and python_version >= "3.6" and python_full_version >= "3.4.0" pyally==1.1.2 -pycoingecko==1.4.0 -pycparser==2.20; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.5" +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" pygments==2.8.1; python_version >= "3.6" -pymeeus==0.5.9; python_version >= "3.5" +pymeeus==0.5.11; python_version >= "3.5" +pyobjc-core==7.1; python_version >= "3.6" and sys_platform == "darwin" +pyobjc-framework-cocoa==7.1; python_version >= "3.6" and sys_platform == "darwin" +pyotp==2.6.0; python_version >= "3" pyparsing==2.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -pyportfolioopt==1.4.1 -pyrsistent==0.17.3; python_version >= "3.6" +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-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" pytrends==4.7.3 pytz==2021.1; python_full_version >= "3.6.1" and python_version >= "3.5" pywin32==300; sys_platform == "win32" and python_version >= "3.6" pywinpty==0.5.7; os_name == "nt" and python_version >= "3.6" pyyaml==5.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" pyzmq==22.0.3; python_full_version >= "3.6.1" and python_version >= "3.6" -qtconsole==5.0.2; python_version >= "3.6" +qdldl==0.1.5.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +qtconsole==5.0.3; python_version >= "3.6" qtpy==1.9.0; python_version >= "3.6" quandl==3.6.1; python_version >= "3.5" -rapidfuzz==1.2.1; python_version >= "2.7" -regex==2020.11.13; python_version >= "3.6" +rapidfuzz==1.4.1; python_version >= "3.5" +regex==2020.11.13 +requests-oauthlib==1.3.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" requests==2.25.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") retrying==1.3.3 -robin-stocks==2.0.3 +robin-stocks==2.0.3; python_version >= "3" +scikit-learn==0.24.1; python_version >= "3.6" scipy==1.5.4; python_version >= "3.6" +screeninfo==0.6.7 +scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" seaborn==0.11.1; python_version >= "3.6" -send2trash==1.5.0; python_version >= "3.5" -six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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 >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.5") -soupsieve==2.2; python_version >= "3.6" -screeninfo==0.6.7; +send2trash==1.5.0; python_version >= "3.6" +six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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 >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") +soupsieve==2.2.1; python_version >= "3.6" statsmodels==0.12.2; python_version >= "3.6" +tabulate==0.8.9 tenacity==7.0.0; python_version >= "3.6" -terminado==0.9.2; python_version >= "3.6" +termcolor==1.1.0 +terminado==0.9.4; python_version >= "3.6" testpath==0.4.4; python_version >= "3.6" textwrap3==0.9.2; python_version >= "3.6" +threadpoolctl==2.1.0; python_version >= "3.6" timeseriescrossvalidation @ git+https://github.com/DidierRLopes/TimeSeriesCrossValidation.git@master toml==0.10.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" tornado==6.1; python_full_version >= "3.6.1" and python_version >= "3.6" -tqdm==4.59.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" -tradingview-ta==3.2.3 +tqdm==4.60.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +tradingview-ta==3.2.3; python_version >= "3.5" traitlets==4.3.3; python_full_version >= "3.6.1" and python_version >= "3.6" -typed-ast==1.4.2; python_version >= "3.6" +typed-ast==1.4.3; python_version >= "3.6" typing-extensions==3.7.4.3; python_version < "3.8" and python_version >= "3.6" update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0" -urllib3==1.26.3; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" +urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6" user-agent==0.1.9 wcwidth==0.2.5; python_version >= "3.6" and python_full_version >= "3.6.1" webencodings==0.5.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" websocket-client==0.58.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0" +websockets==8.1; python_full_version >= "3.6.1" widgetsnbextension==3.5.1 yarl==1.6.3; python_version >= "3.6" -yfinance==0.1.55 +yfinance==0.1.59 zipp==3.4.1; python_version < "3.8" and python_version >= "3.6" +zope.interface==5.4.0; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" From d2bfbc83c2f90c8012bcc47b61d3f613cafa2f63 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 16:10:26 -0700 Subject: [PATCH 055/114] Adding a test step to list installed packages --- .github/workflows/test.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5e6ead3f4d6..a3703ca4445 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -118,6 +118,10 @@ jobs: - name: Install Package run: poetry install --no-interaction + - name: List installed packages + shell: bash -l {0} + run: pip list + - name: Run tests env: MPLBACKEND: Agg @@ -182,14 +186,18 @@ jobs: shell: cmd /C CALL {0} run: >- c:\windows\system32\icacls C:\Users\runneradmin\AppData\Local\Temp /grant "everyone":F /t + - name: Install dependencies (Bash) shell: bash -l {0} run: | conda info pip install --user --requirement requirements.txt + - name: List installed packages (Bash) shell: bash -l {0} - run: conda list + run: | + conda list + pip list - name: Run tests (Bash) shell: bash -l {0} From 04810f5a472d00b8915ee7a77c7ff40df2b4b568 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 16:20:44 -0700 Subject: [PATCH 056/114] Add sourcing of the VENV --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a3703ca4445..c997b318483 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -130,7 +130,9 @@ jobs: pytest tests/ - name: Start Terminal and exit - run: python terminal.py + run: | + source $VENV + python terminal.py tests-conda: name: Conda (${{ matrix.python-version }}, ${{ matrix.os }}) needs: test From 5313b6ed228a8371ddef737a816e9fe8bc64f636 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 16:29:43 -0700 Subject: [PATCH 057/114] Add sourcing of the VENV --- .github/workflows/test.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c997b318483..5dcfee935ef 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -75,7 +75,9 @@ jobs: pytest tests/ - name: Start Terminal and exit - run: python terminal.py + run: | + source $VENV + python terminal.py tests-python: name: Python (${{ matrix.python-version }}, ${{ matrix.os }}) needs: test @@ -120,7 +122,9 @@ jobs: - name: List installed packages shell: bash -l {0} - run: pip list + run: | + source $VENV + pip list - name: Run tests env: From 6d09f68cbf556ef5c4f8733fcc88b8a106d47d26 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 17:05:23 -0700 Subject: [PATCH 058/114] Downgrading cvxpy and pyportfolioopt to fix Windows dependencies --- poetry.lock | 83 ++++++++++++++++++++++++++++++++----------- pyproject.toml | 3 +- requirements-full.txt | 13 +++---- requirements.txt | 13 +++---- 4 files changed, 78 insertions(+), 34 deletions(-) diff --git a/poetry.lock b/poetry.lock index a2faa511bcd..028b5ab9937 100644 --- a/poetry.lock +++ b/poetry.lock @@ -379,9 +379,17 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +[[package]] +name = "cvxopt" +version = "1.2.6" +description = "Convex optimization package" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "cvxpy" -version = "1.1.12" +version = "1.1.7" description = "A domain-specific language for modeling convex optimization problems in Python." category = "main" optional = false @@ -1978,20 +1986,21 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "pyportfolioopt" -version = "1.4.1" -description = "Financial portfolio optimization in python" +version = "1.3.1" +description = "Financial portfolio optimisation in python" category = "main" optional = false -python-versions = ">=3.6.1,<4.0.0" +python-versions = ">=3.6,<4.0" [package.dependencies] -cvxpy = ">=1.1.10,<2.0.0" +cvxopt = ">=1.2,<1.2.5.post1 || >1.2.5.post1,<2.0" +cvxpy = ">=1.0,<2.0" numpy = ">=1.12,<2.0" pandas = ">=0.19" scipy = ">=1.3,<2.0" [package.extras] -optionals = ["cvxopt (>=1.2,!=1.2.5.post1,<2.0)", "scikit-learn (>=0.24.1,<0.25.0)", "matplotlib (>=3.2.0,<4.0.0)"] +optionals = ["scikit-learn (>=0.19,<0.20)", "matplotlib (>=3.2.0,<4.0.0)"] [[package]] name = "pyrsistent" @@ -2935,7 +2944,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "bc7a1735d2e1abb9e5773bfafaeb58d8b53babffb2e0f37f04cb751a218782d4" +content-hash = "9899ba8a681b20ba61231b3d8340043ef65912edc44db6cc12bc0343e853cdeb" [metadata.files] absl-py = [ @@ -3161,19 +3170,51 @@ cssselect = [ {file = "cssselect-1.1.0-py2.py3-none-any.whl", hash = "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf"}, {file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"}, ] +cvxopt = [ + {file = "cvxopt-1.2.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b5b2288a467c0c3996899c10783c8d78878aeb01d43a66697e9993ff76ac5cae"}, + {file = "cvxopt-1.2.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:c57d7d2347ba98432a2ed5af3169026db6d191274c49fccb5357a7cdfb410e5b"}, + {file = "cvxopt-1.2.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0cd32bed5fec871d36d32f0a86c927e2837b9c60fc23b6f777108c3a95f248e5"}, + {file = "cvxopt-1.2.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:0b335bf18f7e42326105f9090e5bb7bbdecfce3c3b4c612ca4e538b00383e937"}, + {file = "cvxopt-1.2.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:97f7624837bd2e072bd909d4c53155b13a427dac6e0c2ea3d5e471443c289489"}, + {file = "cvxopt-1.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:5980abb9a7e43a072dfd95e7c542e43afc2cb487f11000e33be2854dafcf15fe"}, + {file = "cvxopt-1.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:5f2e9e308d931bd52f4dbb55073edebd03073e5f1627f82959da4b95321f89dd"}, + {file = "cvxopt-1.2.6-cp35-cp35m-win32.whl", hash = "sha256:fa5568d4d64e4cc24da4094c0066c67308e805287a742ad298f122f0cad360ca"}, + {file = "cvxopt-1.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:d505932dfe734ff14ee0c3c04fc5618bb7cc744f59e0edfed4a8851deab8ee42"}, + {file = "cvxopt-1.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6ab795743b0e42529d015b889576783a1264e6056417f54870c42db191482065"}, + {file = "cvxopt-1.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fb1149e2764e5284b560434cbc5ee7e60199fc7eaf850d5ba26d02fbc24d4006"}, + {file = "cvxopt-1.2.6-cp36-cp36m-win32.whl", hash = "sha256:7db648536ecef417df42108b7b779891946a6cc791b74e843d23d846c5576d1a"}, + {file = "cvxopt-1.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:7cd9f1c8404ed507257550f485b3394b1a38087da4ff70032dca964a73e138f3"}, + {file = "cvxopt-1.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1e76dabd13377f6876073041beee67e4613879a1ac6a572a9254aafa8ca7f7fe"}, + {file = "cvxopt-1.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:368caf7d2130670e6e48af0d611ae41713a98d7643f7d64a6aeabefad50e76c4"}, + {file = "cvxopt-1.2.6-cp37-cp37m-win32.whl", hash = "sha256:95b2cd31d57341279e98888479c71496529eade2eccf5582e671ce96ef575c38"}, + {file = "cvxopt-1.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:f343ddd406caec05408d007e313022a073a7466c0356ac96e20256d0b542916b"}, + {file = "cvxopt-1.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fdeb3ce110708229ee4acbd4c894ffe031e2dafb2ba6469068fed0cc20671b89"}, + {file = "cvxopt-1.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c420cf196c8d2733022f29e77ace46871b82f2f2a25edcb585a20c0c76bec02d"}, + {file = "cvxopt-1.2.6-cp38-cp38-win32.whl", hash = "sha256:ba75971b78777ec10361de81a1feb6f27757b505054dbe3cfde5a4f19cccbe2e"}, + {file = "cvxopt-1.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:b7a9ee4d3ecdd0f2a190e935613073c15594b52f581e0327ba4e869277f793f7"}, + {file = "cvxopt-1.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:edae9dafec8f52594ae6312b9ff811ad10d0504ca935e09aa66a309e6d7c2397"}, + {file = "cvxopt-1.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2bac183859127ebc473b9bc66be17c0dbc8a3c8bd0939d460cfe6d141bc545db"}, + {file = "cvxopt-1.2.6-cp39-cp39-win32.whl", hash = "sha256:3eb14814b7b79f765e107c50b0961e71d47a36a760ccf3f1fde2ca65d75a9f11"}, + {file = "cvxopt-1.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:6e05d9f541368950bfb7b0ab1f648087397a60728fd4699fe29e90462931ac39"}, + {file = "cvxopt-1.2.6.tar.gz", hash = "sha256:a4c433706fd0ad9d47e7f222773a7f7601766fb8e74b633524b3c3fce29aa73e"}, +] cvxpy = [ - {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"}, - {file = "cvxpy-1.1.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:575f6e1c70274008961edff97a7494701faed20b40fbd49327010c0e7d186256"}, - {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.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"}, - {file = "cvxpy-1.1.12-py3.9-win-amd64.egg", hash = "sha256:08c720706abd94c25903a4db5dd2171232e72d0969b874a5de9a8181f96357d5"}, - {file = "cvxpy-1.1.12.tar.gz", hash = "sha256:b499ebfae4fc645e9523621573ffcb1c5b6854a1b5c0ce1d66a8a9a458605807"}, + {file = "cvxpy-1.1.7-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a4a7ca9af06775dfe63dfb0a5937ab3e83cee6f5fdc1472c09a36a32cc3beeb8"}, + {file = "cvxpy-1.1.7-cp35-cp35m-win_amd64.whl", hash = "sha256:0a57b866d36783fb122c563453f36860b877fda2c45763e872ed4a007c289af6"}, + {file = "cvxpy-1.1.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6718b6555f3719f6da9bd729fb810f860cf8dcd7b48212a223a41532c5cca6dd"}, + {file = "cvxpy-1.1.7-cp36-cp36m-win_amd64.whl", hash = "sha256:e5512489a5ba83801579fb142e711fda8df72c055df5652ffae4e51a96d437d6"}, + {file = "cvxpy-1.1.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40f8a446446070c7d336270ba69a553a9b139af264b09675e9c85d3751d3c840"}, + {file = "cvxpy-1.1.7-cp37-cp37m-win_amd64.whl", hash = "sha256:46b29e622c7e9cb5463f514e7d9fc5f17129b89991a753c215f021f59442e386"}, + {file = "cvxpy-1.1.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:51e6d0e6a6d85b885e99fa443d60f5a07d2a3153b033eae325290f9bfaa48939"}, + {file = "cvxpy-1.1.7-cp38-cp38-win_amd64.whl", hash = "sha256:57cca8490a0d9ea0545ada8da61dfc6bcec91f9a213153224b8b360875d984c7"}, + {file = "cvxpy-1.1.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:53dee27264455368db873854db4eca9adb57b6cd783ccf1d47741f147e9d1f64"}, + {file = "cvxpy-1.1.7-cp39-cp39-win_amd64.whl", hash = "sha256:9d4cf4fbfb95bf4036553ac460a939e2b30c03c986bcbd69ceebb6ea61c12b86"}, + {file = "cvxpy-1.1.7-py3.5-win-amd64.egg", hash = "sha256:2bbd7377aa56352923889a83feb1c4ec2f68c862c556b96e7f0471fa63123a86"}, + {file = "cvxpy-1.1.7-py3.6-win-amd64.egg", hash = "sha256:4247938236794c3c5c34cf26b11869dc15404cfe951b1f4080e9d510fcf81182"}, + {file = "cvxpy-1.1.7-py3.7-win-amd64.egg", hash = "sha256:ae67a06616bf19bf0ee02732b2d7a47fe4a265cbcd56fb500107eba712281440"}, + {file = "cvxpy-1.1.7-py3.8-win-amd64.egg", hash = "sha256:6b2d01c12c9544d17439238ac51eb568e31bc99717f53429b7c4099cd5e46730"}, + {file = "cvxpy-1.1.7-py3.9-win-amd64.egg", hash = "sha256:f1c839762efe3b2c4a1fb1030cc8addefd4154c1a83ccd29b4b81313714e0747"}, + {file = "cvxpy-1.1.7.tar.gz", hash = "sha256:330eb76e8369c360b68d9231c6eb350848e373b5952134f9bfebaed1a4c4211f"}, ] cycler = [ {file = "cycler-0.10.0-py2.py3-none-any.whl", hash = "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d"}, @@ -4227,8 +4268,8 @@ pyparsing = [ {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pyportfolioopt = [ - {file = "PyPortfolioOpt-1.4.1-py3-none-any.whl", hash = "sha256:73f0b4ac2a5d879879a7a91af038b4d7ff82e9998fb2cad7c249302294e8c09e"}, - {file = "PyPortfolioOpt-1.4.1.tar.gz", hash = "sha256:e6c8e983db92cd13caf41d87fb4dcd945d37053f28b75dd19b5be699b6b1d19e"}, + {file = "PyPortfolioOpt-1.3.1-py3-none-any.whl", hash = "sha256:81b9e85c170c84e478a1b1cfc1500198edf4bf7e62b1cc256376bf68f9a7b585"}, + {file = "PyPortfolioOpt-1.3.1.tar.gz", hash = "sha256:d947aaa97bc52b5a5205675bb8df9752dee01f2b4d00c1f27692613f80dc8e8b"}, ] pyrsistent = [ {file = "pyrsistent-0.14.11.tar.gz", hash = "sha256:3ca82748918eb65e2d89f222b702277099aca77e34843c5eb9d52451173970e2"}, diff --git a/pyproject.toml b/pyproject.toml index 12ccd7ebcc8..22e44941a4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,9 +54,10 @@ detecta = "^0.0.5" tradingview-ta = "^3.2.3" finvizfinance = "^0.9.3" Pillow = "^8.2.0" -pyportfolioopt = "^1.4.1" statsmodels = "^0.12.2" tabulate = "^0.8.9" +cvxpy = "1.1.7" +pyportfolioopt = "1.3.1" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements-full.txt b/requirements-full.txt index c572e8e2936..8a781d293fe 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -27,7 +27,8 @@ colorama==0.4.4; (python_version >= "2.7" and python_full_version < "3.0.0") or convertdate==2.3.2; python_version >= "3.5" cryptography==3.4.7; python_version >= "3.6" cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" -cvxpy==1.1.12; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +cvxopt==1.2.6; python_version >= "3.6" and python_version < "4.0" +cvxpy==1.1.7; python_version >= "3.5" cycler==0.10.0; python_version >= "3.6" cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and python_version >= "3.6" and sys_platform == "darwin" dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.6.2" @@ -36,7 +37,7 @@ decorator==4.4.2; python_full_version >= "3.6.1" and python_version >= "3.6" and defusedxml==0.7.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" deprecated==1.2.12; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" detecta==0.0.5; python_version >= "3.6" -ecos==2.0.7.post1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +ecos==2.0.7.post1; python_version >= "3.6" and python_version < "4.0" entrypoints==0.3; python_version >= "3.6" ephem==3.7.7.1; python_version >= "2.7" and python_version < "4" fbprophet==0.6 @@ -107,7 +108,7 @@ notebook==6.3.0; python_version >= "3.6" numpy==1.19.5; python_version >= "3.6" oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" opt-einsum==3.3.0; python_version >= "3.5" -osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +osqp==0.6.2.post0; python_version >= "3.6" and python_version < "4.0" overrides==3.1.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" packaging==20.9; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") pandas-ta==0.2.45b @@ -142,7 +143,7 @@ pyobjc-core==7.1; python_version >= "3.6" and sys_platform == "darwin" pyobjc-framework-cocoa==7.1; python_version >= "3.6" and sys_platform == "darwin" pyotp==2.6.0; python_version >= "3" pyparsing==2.4.7; python_full_version >= "3.6.0" 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") -pyportfolioopt==1.4.1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" +pyportfolioopt==1.3.1; python_version >= "3.6" and python_version < "4.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" pystan==2.19.1.1 @@ -154,7 +155,7 @@ pywin32==300; sys_platform == "win32" and python_version >= "3.6" pywinpty==0.5.7; os_name == "nt" and python_version >= "3.6" pyyaml==5.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" pyzmq==22.0.3; python_full_version >= "3.6.1" and python_version >= "3.6" -qdldl==0.1.5.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +qdldl==0.1.5.post0; python_version >= "3.5" qtconsole==5.0.3; python_version >= "3.6" qtpy==1.9.0; python_version >= "3.6" quandl==3.6.1; python_version >= "3.5" @@ -169,7 +170,7 @@ sacremoses==0.0.45; python_full_version >= "3.6.0" and python_version >= "3.6" scikit-learn==0.24.1; python_version >= "3.6" scipy==1.5.4; python_version >= "3.6" screeninfo==0.6.7 -scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +scs==2.1.3; python_version >= "3.6" and python_version < "4.0" seaborn==0.11.1; python_version >= "3.6" segtok==1.5.10; python_version >= "3.6" send2trash==1.5.0; python_version >= "3.6" diff --git a/requirements.txt b/requirements.txt index b73282d30c2..3567ce5b791 100644 --- a/requirements.txt +++ b/requirements.txt @@ -21,7 +21,8 @@ colorama==0.4.4; (python_version >= "2.7" and python_full_version < "3.0.0") or convertdate==2.3.2; python_version >= "3.5" cryptography==3.4.7; python_version >= "3.6" cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" -cvxpy==1.1.12; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +cvxopt==1.2.6; python_version >= "3.6" and python_version < "4.0" +cvxpy==1.1.7; python_version >= "3.5" cycler==0.10.0; python_version >= "3.6" cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and python_version >= "3.6" and sys_platform == "darwin" dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" @@ -29,7 +30,7 @@ datetime==4.3; python_version >= "3.5" decorator==4.4.2; 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.2.0" and python_version >= "3.6") defusedxml==0.7.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" detecta==0.0.5; python_version >= "3.6" -ecos==2.0.7.post1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +ecos==2.0.7.post1; python_version >= "3.6" and python_version < "4.0" entrypoints==0.3; python_version >= "3.6" finviz==1.4.1 finvizfinance==0.9.6; python_version >= "3.5" @@ -76,7 +77,7 @@ nest-asyncio==1.5.1; python_full_version >= "3.6.1" and python_version >= "3.6" notebook==6.3.0; python_version >= "3.6" numpy==1.19.5; python_version >= "3.6" oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" -osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +osqp==0.6.2.post0; python_version >= "3.6" and python_version < "4.0" packaging==20.9; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pandas-ta==0.2.45b pandas==1.1.5; python_full_version >= "3.6.1" @@ -107,7 +108,7 @@ pyobjc-core==7.1; python_version >= "3.6" and sys_platform == "darwin" pyobjc-framework-cocoa==7.1; python_version >= "3.6" and sys_platform == "darwin" pyotp==2.6.0; python_version >= "3" pyparsing==2.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -pyportfolioopt==1.4.1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" +pyportfolioopt==1.3.1; python_version >= "3.6" and python_version < "4.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-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") @@ -118,7 +119,7 @@ pywin32==300; sys_platform == "win32" and python_version >= "3.6" pywinpty==0.5.7; os_name == "nt" and python_version >= "3.6" pyyaml==5.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" pyzmq==22.0.3; python_full_version >= "3.6.1" and python_version >= "3.6" -qdldl==0.1.5.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +qdldl==0.1.5.post0; python_version >= "3.5" qtconsole==5.0.3; python_version >= "3.6" qtpy==1.9.0; python_version >= "3.6" quandl==3.6.1; python_version >= "3.5" @@ -131,7 +132,7 @@ robin-stocks==2.0.3; python_version >= "3" scikit-learn==0.24.1; python_version >= "3.6" scipy==1.5.4; python_version >= "3.6" screeninfo==0.6.7 -scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" +scs==2.1.3; python_version >= "3.6" and python_version < "4.0" seaborn==0.11.1; python_version >= "3.6" send2trash==1.5.0; python_version >= "3.6" six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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 >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") From 761d06ff250b5cea3e42f5a5acdc6bce4d9a7998 Mon Sep 17 00:00:00 2001 From: DJ Date: Mon, 19 Apr 2021 18:05:38 -0600 Subject: [PATCH 059/114] changed message to errorMessage --- gamestonk_terminal/forex/fx_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/forex/fx_view.py b/gamestonk_terminal/forex/fx_view.py index 63f378495aa..bf8b50c14ea 100644 --- a/gamestonk_terminal/forex/fx_view.py +++ b/gamestonk_terminal/forex/fx_view.py @@ -47,7 +47,7 @@ def get_fx_price(accountID, instrument, other_args: List[str]): except V20Error as e: d_error = eval(e.msg) - print(d_error["message"], "\n") + print(d_error["errorMessage"], "\n") def get_account_summary(accountID, other_args: List[str]): From d875c20a0ef0f0e34cd3216735c5a1b18d87de28 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Tue, 20 Apr 2021 02:19:18 +0100 Subject: [PATCH 060/114] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7724ad3300c..1140c5ce2c4 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,7 @@ Distributed under the MIT License. See [LICENSE](https://github.com/DidierRLopes [James Maslek](https://www.linkedin.com/in/james-maslek-b6810186/) - jmaslek11@gmail.com -Feel free to share loss porn, memes or any questions at https://discord.gg/FmKjHKMn +Feel free to share loss porn, memes or any questions at https://discord.gg/cC2KNt4B ## Acknowledgments From 7102138446af3260f67e1d89589c88ff17f36d90 Mon Sep 17 00:00:00 2001 From: didier Date: Tue, 20 Apr 2021 02:20:47 +0100 Subject: [PATCH 061/114] Add disc/darkpool command --- .../discovery/disc_controller.py | 7 + .../discovery/finra_ats_view.py | 266 ++++++++++++++++++ .../due_diligence/finra_view.py | 5 +- 3 files changed, 274 insertions(+), 4 deletions(-) create mode 100644 gamestonk_terminal/discovery/finra_ats_view.py diff --git a/gamestonk_terminal/discovery/disc_controller.py b/gamestonk_terminal/discovery/disc_controller.py index 2362e8f762b..07e00b2e462 100644 --- a/gamestonk_terminal/discovery/disc_controller.py +++ b/gamestonk_terminal/discovery/disc_controller.py @@ -21,6 +21,7 @@ from gamestonk_terminal.discovery import ( unusual_whales_view, yahoo_finance_view, marketbeat_view, + finra_ats_view, ) @@ -50,6 +51,7 @@ class DiscoveryController: "ratings", "latest", "trending", + "darkpool", ] def __init__(self): @@ -94,6 +96,7 @@ class DiscoveryController: print(" latest latest news [Seeking Alpha]") print(" trending trending news [Seeking Alpha]") print(" ratings top ratings updates [MarketBeat]") + print(" darkpool dark pool tickers with growing activity [FINRA]") print("") def switch(self, an_input: str): @@ -206,6 +209,10 @@ class DiscoveryController: """Process ratings command""" marketbeat_view.ratings_view(other_args) + def call_darkpool(self, other_args: List[str]): + """Process darkpool command""" + finra_ats_view.dark_pool(other_args) + def menu(): """Discovery Menu""" diff --git a/gamestonk_terminal/discovery/finra_ats_view.py b/gamestonk_terminal/discovery/finra_ats_view.py new file mode 100644 index 00000000000..3a3ae4e346f --- /dev/null +++ b/gamestonk_terminal/discovery/finra_ats_view.py @@ -0,0 +1,266 @@ +""" FINRA View """ +__docformat__ = "numpy" + +import argparse +from typing import List, Tuple, Dict +import requests +from scipy import stats +import pandas as pd +from matplotlib import pyplot as plt +import matplotlib.dates as mdates +from gamestonk_terminal.config_plot import PLOT_DPI +from gamestonk_terminal import feature_flags as gtff +from gamestonk_terminal.helper_funcs import ( + parse_known_args_and_warn, + plot_autoscale, + check_positive, +) + + +def getFINRAweeks(tier, is_ats) -> List: + """Get FINRA weeks + + Parameters + ---------- + tier : str + Stock tier between T1, T2, or OTCE + is_ats : bool + ATS data if true, NON-ATS otherwise + + Returns + ---------- + List + List of response data + """ + req_hdr = {"Accept": "application/json", "Content-Type": "application/json"} + + req_data = { + "compareFilters": [ + { + "compareType": "EQUAL", + "fieldName": "summaryTypeCode", + "fieldValue": "ATS_W_SMBL" if is_ats else "OTC_W_SMBL", + }, + { + "compareType": "EQUAL", + "fieldName": "tierIdentifier", + "fieldValue": tier, + }, + ], + "delimiter": "|", + "fields": ["weekStartDate"], + "limit": 27, + "quoteValues": False, + "sortFields": ["-weekStartDate"], + } + + response = requests.post( + "https://api.finra.org/data/group/otcMarket/name/weeklyDownloadDetails", + headers=req_hdr, + json=req_data, + ) + + return response.json() if response.status_code == 200 else list() + + +def getFINRAdata(weekStartDate, tier, ticker, is_ats, offset): + req_hdr = {"Accept": "application/json", "Content-Type": "application/json"} + + l_cmp_filters = [ + { + "compareType": "EQUAL", + "fieldName": "weekStartDate", + "fieldValue": weekStartDate, + }, + {"compareType": "EQUAL", "fieldName": "tierIdentifier", "fieldValue": tier}, + { + "compareType": "EQUAL", + "description": "", + "fieldName": "summaryTypeCode", + "fieldValue": "ATS_W_SMBL" if is_ats else "OTC_W_SMBL", + }, + ] + + if ticker: + l_cmp_filters.append( + { + "compareType": "EQUAL", + "fieldName": "issueSymbolIdentifier", + "fieldValue": ticker, + } + ) + + req_data = { + "compareFilters": l_cmp_filters, + "delimiter": "|", + "fields": [ + "issueSymbolIdentifier", + "totalWeeklyShareQuantity", + "totalWeeklyTradeCount", + "lastUpdateDate", + ], + "limit": 5000, + "offset": offset, + "quoteValues": False, + "sortFields": ["totalWeeklyShareQuantity"], + } + + return requests.post( + "https://api.finra.org/data/group/otcMarket/name/weeklySummary", + headers=req_hdr, + json=req_data, + ) + + +def getATSdata(num_tickers_to_filter: int) -> Tuple[pd.DataFrame, Dict]: + """Get all FINRA ATS data, and parse most promising tickers based on linear regression + + Parameters + ---------- + num_tickers_to_filter : int + Number of tickers to filter from entire ATS data based on the sum of the total weekly shares quantity + + Returns + ---------- + pd.DataFrame + Dark Pools (ATS) Data + Dict + Tickers from Dark Pools with better regression slope + """ + tiers = ["T1", "T2", "OTCE"] + df_ats = pd.DataFrame() + + for tier in tiers: + print(f"Processing Tier {tier} ...") + for d_week in getFINRAweeks(tier, is_ats=True): + offset = 0 + response = getFINRAdata(d_week["weekStartDate"], tier, "", True, offset) + l_data = response.json() + + while len(response.json()) == 5000: + offset += 5000 + response = getFINRAdata(d_week["weekStartDate"], tier, "", True, offset) + l_data += response.json() + + df_ats_week = pd.DataFrame(l_data) + df_ats_week["weekStartDate"] = d_week["weekStartDate"] + + if not df_ats_week.empty: + df_ats = df_ats.append(df_ats_week, ignore_index=True) + + df_ats = df_ats.sort_values("weekStartDate") + df_ats["weekStartDateInt"] = pd.to_datetime(df_ats["weekStartDate"]).apply( + lambda x: x.timestamp() + ) + + print(f"Processing regression on {num_tickers_to_filter} promising tickers ...") + + d_ats_reg = {} + # set(df_ats['issueSymbolIdentifier'].values) this would be iterating through all tickers + # but that is extremely time consuming for little reward. A little filtering is done to + # speed up search for best ATS tickers + for symbol in list( + df_ats.groupby("issueSymbolIdentifier")["totalWeeklyShareQuantity"] + .sum() + .sort_values()[-num_tickers_to_filter:] + .index + ): + slope = stats.linregress( + df_ats[df_ats["issueSymbolIdentifier"] == symbol][ + "weekStartDateInt" + ].values, + df_ats[df_ats["issueSymbolIdentifier"] == symbol][ + "totalWeeklyShareQuantity" + ].values, + )[0] + d_ats_reg[symbol] = slope + + return df_ats, d_ats_reg + + +def plot_dark_pools(ats: pd.DataFrame, top_ats_tickers: List): + """Plots ATS and NON-ATS data + + Parameters + ---------- + ats : pd.DataFrame + Dark Pools (ATS) Data + top_ats_tickers : List + List of tickers from most promising with better linear regression slope + """ + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) + + for symbol in top_ats_tickers: + plt.plot( + pd.to_datetime( + ats[ats["issueSymbolIdentifier"] == symbol]["weekStartDate"] + ), + ats[ats["issueSymbolIdentifier"] == symbol]["totalWeeklyShareQuantity"] + / 1_000_000, + ) + + plt.legend(top_ats_tickers) + plt.ylabel("Total Weekly Shares [Million]") + plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2) + plt.title(f"Dark Pools (ATS)") + plt.gcf().autofmt_xdate() + plt.xlabel("Weeks") + + if gtff.USE_ION: + plt.ion() + + plt.show() + + +def dark_pool(other_args: List[str]): + """Display dark pool (ATS) data of tickers with growing trades activity + + Parameters + ---------- + other_args : List[str] + argparse other args + """ + parser = argparse.ArgumentParser( + add_help=False, + prog="dp", + description="Display dark pool (ATS) data of tickers with growing trades activity", + ) + parser.add_argument( + "-n", + "--num", + action="store", + dest="n_num", + type=check_positive, + default=1000, + help="Number of tickers to filter from entire ATS data based on the sum of the total weekly shares quantity.", + ) + parser.add_argument( + "-t", + "--top", + action="store", + dest="n_top", + type=check_positive, + default=5, + help="List of tickers from most promising with better linear regression slope.", + ) + + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + df_ats, d_ats_reg = getATSdata(ns_parser.n_num) + + top_ats_tickers = list( + dict( + sorted(d_ats_reg.items(), key=lambda item: item[1], reverse=True) + ).keys() + )[: ns_parser.n_top] + + plot_dark_pools(df_ats, top_ats_tickers) + print("") + + except Exception as e: + print(e) + print("") + return diff --git a/gamestonk_terminal/due_diligence/finra_view.py b/gamestonk_terminal/due_diligence/finra_view.py index ab4fc2465aa..baa7884dcea 100644 --- a/gamestonk_terminal/due_diligence/finra_view.py +++ b/gamestonk_terminal/due_diligence/finra_view.py @@ -285,7 +285,7 @@ def dark_pool(other_args: List[str], ticker: str): description="Display barchart of dark pool (ATS) and OTC (Non ATS) data [Source: FINRA]", ) - if 1: + try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -296,12 +296,9 @@ def dark_pool(other_args: List[str], ticker: str): print("No ticker data found!") plot_dark_pools(ticker, df_ats, df_otc) - print("") - """ except Exception as e: print(e) print("") return - """ From 741fbcdc6ff17e0fc4169fcf7db1d08f2e56f3d8 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Tue, 20 Apr 2021 02:24:52 +0100 Subject: [PATCH 062/114] Update README.md --- gamestonk_terminal/discovery/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/gamestonk_terminal/discovery/README.md b/gamestonk_terminal/discovery/README.md index 6b20d1b25f1..1159e591b56 100644 --- a/gamestonk_terminal/discovery/README.md +++ b/gamestonk_terminal/discovery/README.md @@ -38,6 +38,8 @@ This menu aims to discover new stocks, and the usage of the following commands a * trending news [Seeking Alpha] * [ratings](#ratings) * top ratings updates [MarketBeat] +* [darkpool](#darkpool) + * dark pool tickers with growing activity [FINRA] ## map @@ -265,3 +267,18 @@ Top ratings updates. [Source: MarketBeat] ratings + +## darkpool + +``` +usage: darkpool [-n N_NUM] [-t N_TOP] +``` + +Display dark pool (ATS) data of tickers with growing trades activity. [Source: FINRA] + +* -n : Number of tickers to filter from entire ATS data based on the sum of the total weekly shares quantity. Default: 1000. +* -t : List of tickers from most promising with better linear regression slope. Default: 5. + +![darkpool](https://user-images.githubusercontent.com/25267873/115323195-8d642080-a17f-11eb-9ef8-d456ce769ab7.png) + + From 590a6ca69d4a66f18b36b7dbb30a0de4876b7fc0 Mon Sep 17 00:00:00 2001 From: didier Date: Tue, 20 Apr 2021 02:29:24 +0100 Subject: [PATCH 063/114] fix mypy --- gamestonk_terminal/discovery/finra_ats_view.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gamestonk_terminal/discovery/finra_ats_view.py b/gamestonk_terminal/discovery/finra_ats_view.py index 3a3ae4e346f..7480ba16885 100644 --- a/gamestonk_terminal/discovery/finra_ats_view.py +++ b/gamestonk_terminal/discovery/finra_ats_view.py @@ -7,7 +7,6 @@ import requests from scipy import stats import pandas as pd from matplotlib import pyplot as plt -import matplotlib.dates as mdates from gamestonk_terminal.config_plot import PLOT_DPI from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import ( @@ -179,7 +178,7 @@ def getATSdata(num_tickers_to_filter: int) -> Tuple[pd.DataFrame, Dict]: def plot_dark_pools(ats: pd.DataFrame, top_ats_tickers: List): - """Plots ATS and NON-ATS data + """Plots promising tickers based on growing ATS data Parameters ---------- @@ -202,7 +201,7 @@ def plot_dark_pools(ats: pd.DataFrame, top_ats_tickers: List): plt.legend(top_ats_tickers) plt.ylabel("Total Weekly Shares [Million]") plt.grid(b=True, which="major", color="#666666", linestyle="-", alpha=0.2) - plt.title(f"Dark Pools (ATS)") + plt.title("Dark Pool (ATS) growing tickers") plt.gcf().autofmt_xdate() plt.xlabel("Weeks") @@ -222,7 +221,7 @@ def dark_pool(other_args: List[str]): """ parser = argparse.ArgumentParser( add_help=False, - prog="dp", + prog="darkpool", description="Display dark pool (ATS) data of tickers with growing trades activity", ) parser.add_argument( From a3c9614205a8a9b0028b6238f2098351a8e3b28e Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Tue, 20 Apr 2021 02:31:02 +0100 Subject: [PATCH 064/114] Update README.md --- gamestonk_terminal/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index fdaa9118d84..900af3b3be4 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -83,6 +83,7 @@ Command|Description|Source `latest` |latest news |[Seeking Alpha](https://seekingalpha.com/) `trending` |trending news |[Seeking Alpha](https://seekingalpha.com/) `ratings ` |top ratings updates |[MarketBeat](https://marketbeat.com) +`darkpool` |dark pool tickers with growing activity |[FINRA](https://www.finra.org)   From 620b3802c80add07e288b035879de902e1c508b8 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Tue, 20 Apr 2021 02:32:57 +0100 Subject: [PATCH 065/114] Update ROADMAP.md --- ROADMAP.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index 277662bd9a8..d4200888355 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -36,6 +36,8 @@ * [x] Analyse sectors/industry performance, overview and valuation from Finviz (@didier) - [PR #315](https://github.com/DidierRLopes/GamestonkTerminal/pull/315) * [x] Add latest and trending news commands (@hinxx) - [PR #347](https://github.com/DidierRLopes/GamestonkTerminal/pull/347) * [x] Add top ratings updates (@hinxx) - [PR #357](https://github.com/DidierRLopes/GamestonkTerminal/pull/357) +* [x] Add dark pool (ATS) data of tickers with growing trades activity (@didier) - [PR #372](https://github.com/DidierRLopes/GamestonkTerminal/pull/372) + **NEXT** From 725771e02b28004a721724de91a9ad1a38e4f904 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 19:42:09 -0700 Subject: [PATCH 066/114] Install cvxpy through conda --- .github/workflows/Mac.yml | 1 + .github/workflows/test.yml | 2 + .github/workflows/windows.yml | 1 + poetry.lock | 83 +++++++++-------------------------- pyproject.toml | 3 +- requirements-full.txt | 13 +++--- requirements.txt | 13 +++--- 7 files changed, 38 insertions(+), 78 deletions(-) diff --git a/.github/workflows/Mac.yml b/.github/workflows/Mac.yml index 6459d5b055a..b83ed2eedfd 100644 --- a/.github/workflows/Mac.yml +++ b/.github/workflows/Mac.yml @@ -48,6 +48,7 @@ jobs: run: | conda install numpy=1.19.5 conda install gensim=3.8.3 + conda install -c conda-forge cvxpy - name: Install dependencies (Bash) shell: bash -l {0} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5dcfee935ef..e85716d7882 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -197,6 +197,8 @@ jobs: shell: bash -l {0} run: | conda info + conda install numpy=1.19.5 + conda install -c conda-forge cvxpy pip install --user --requirement requirements.txt - name: List installed packages (Bash) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index d66f19c6e73..e91b3bc3a6e 100755 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -56,6 +56,7 @@ jobs: conda install -c conda-forge fbprophet=0.6 conda install spyder conda install gensim=3.8.3 + conda install -c conda-forge cvxpy - name: Install dependencies (Bash) shell: bash -l {0} diff --git a/poetry.lock b/poetry.lock index 028b5ab9937..a2faa511bcd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -379,17 +379,9 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -[[package]] -name = "cvxopt" -version = "1.2.6" -description = "Convex optimization package" -category = "main" -optional = false -python-versions = "*" - [[package]] name = "cvxpy" -version = "1.1.7" +version = "1.1.12" description = "A domain-specific language for modeling convex optimization problems in Python." category = "main" optional = false @@ -1986,21 +1978,20 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "pyportfolioopt" -version = "1.3.1" -description = "Financial portfolio optimisation in python" +version = "1.4.1" +description = "Financial portfolio optimization in python" category = "main" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.6.1,<4.0.0" [package.dependencies] -cvxopt = ">=1.2,<1.2.5.post1 || >1.2.5.post1,<2.0" -cvxpy = ">=1.0,<2.0" +cvxpy = ">=1.1.10,<2.0.0" numpy = ">=1.12,<2.0" pandas = ">=0.19" scipy = ">=1.3,<2.0" [package.extras] -optionals = ["scikit-learn (>=0.19,<0.20)", "matplotlib (>=3.2.0,<4.0.0)"] +optionals = ["cvxopt (>=1.2,!=1.2.5.post1,<2.0)", "scikit-learn (>=0.24.1,<0.25.0)", "matplotlib (>=3.2.0,<4.0.0)"] [[package]] name = "pyrsistent" @@ -2944,7 +2935,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "9899ba8a681b20ba61231b3d8340043ef65912edc44db6cc12bc0343e853cdeb" +content-hash = "bc7a1735d2e1abb9e5773bfafaeb58d8b53babffb2e0f37f04cb751a218782d4" [metadata.files] absl-py = [ @@ -3170,51 +3161,19 @@ cssselect = [ {file = "cssselect-1.1.0-py2.py3-none-any.whl", hash = "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf"}, {file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"}, ] -cvxopt = [ - {file = "cvxopt-1.2.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b5b2288a467c0c3996899c10783c8d78878aeb01d43a66697e9993ff76ac5cae"}, - {file = "cvxopt-1.2.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:c57d7d2347ba98432a2ed5af3169026db6d191274c49fccb5357a7cdfb410e5b"}, - {file = "cvxopt-1.2.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0cd32bed5fec871d36d32f0a86c927e2837b9c60fc23b6f777108c3a95f248e5"}, - {file = "cvxopt-1.2.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:0b335bf18f7e42326105f9090e5bb7bbdecfce3c3b4c612ca4e538b00383e937"}, - {file = "cvxopt-1.2.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:97f7624837bd2e072bd909d4c53155b13a427dac6e0c2ea3d5e471443c289489"}, - {file = "cvxopt-1.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:5980abb9a7e43a072dfd95e7c542e43afc2cb487f11000e33be2854dafcf15fe"}, - {file = "cvxopt-1.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:5f2e9e308d931bd52f4dbb55073edebd03073e5f1627f82959da4b95321f89dd"}, - {file = "cvxopt-1.2.6-cp35-cp35m-win32.whl", hash = "sha256:fa5568d4d64e4cc24da4094c0066c67308e805287a742ad298f122f0cad360ca"}, - {file = "cvxopt-1.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:d505932dfe734ff14ee0c3c04fc5618bb7cc744f59e0edfed4a8851deab8ee42"}, - {file = "cvxopt-1.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6ab795743b0e42529d015b889576783a1264e6056417f54870c42db191482065"}, - {file = "cvxopt-1.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fb1149e2764e5284b560434cbc5ee7e60199fc7eaf850d5ba26d02fbc24d4006"}, - {file = "cvxopt-1.2.6-cp36-cp36m-win32.whl", hash = "sha256:7db648536ecef417df42108b7b779891946a6cc791b74e843d23d846c5576d1a"}, - {file = "cvxopt-1.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:7cd9f1c8404ed507257550f485b3394b1a38087da4ff70032dca964a73e138f3"}, - {file = "cvxopt-1.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1e76dabd13377f6876073041beee67e4613879a1ac6a572a9254aafa8ca7f7fe"}, - {file = "cvxopt-1.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:368caf7d2130670e6e48af0d611ae41713a98d7643f7d64a6aeabefad50e76c4"}, - {file = "cvxopt-1.2.6-cp37-cp37m-win32.whl", hash = "sha256:95b2cd31d57341279e98888479c71496529eade2eccf5582e671ce96ef575c38"}, - {file = "cvxopt-1.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:f343ddd406caec05408d007e313022a073a7466c0356ac96e20256d0b542916b"}, - {file = "cvxopt-1.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fdeb3ce110708229ee4acbd4c894ffe031e2dafb2ba6469068fed0cc20671b89"}, - {file = "cvxopt-1.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:c420cf196c8d2733022f29e77ace46871b82f2f2a25edcb585a20c0c76bec02d"}, - {file = "cvxopt-1.2.6-cp38-cp38-win32.whl", hash = "sha256:ba75971b78777ec10361de81a1feb6f27757b505054dbe3cfde5a4f19cccbe2e"}, - {file = "cvxopt-1.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:b7a9ee4d3ecdd0f2a190e935613073c15594b52f581e0327ba4e869277f793f7"}, - {file = "cvxopt-1.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:edae9dafec8f52594ae6312b9ff811ad10d0504ca935e09aa66a309e6d7c2397"}, - {file = "cvxopt-1.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2bac183859127ebc473b9bc66be17c0dbc8a3c8bd0939d460cfe6d141bc545db"}, - {file = "cvxopt-1.2.6-cp39-cp39-win32.whl", hash = "sha256:3eb14814b7b79f765e107c50b0961e71d47a36a760ccf3f1fde2ca65d75a9f11"}, - {file = "cvxopt-1.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:6e05d9f541368950bfb7b0ab1f648087397a60728fd4699fe29e90462931ac39"}, - {file = "cvxopt-1.2.6.tar.gz", hash = "sha256:a4c433706fd0ad9d47e7f222773a7f7601766fb8e74b633524b3c3fce29aa73e"}, -] cvxpy = [ - {file = "cvxpy-1.1.7-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a4a7ca9af06775dfe63dfb0a5937ab3e83cee6f5fdc1472c09a36a32cc3beeb8"}, - {file = "cvxpy-1.1.7-cp35-cp35m-win_amd64.whl", hash = "sha256:0a57b866d36783fb122c563453f36860b877fda2c45763e872ed4a007c289af6"}, - {file = "cvxpy-1.1.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6718b6555f3719f6da9bd729fb810f860cf8dcd7b48212a223a41532c5cca6dd"}, - {file = "cvxpy-1.1.7-cp36-cp36m-win_amd64.whl", hash = "sha256:e5512489a5ba83801579fb142e711fda8df72c055df5652ffae4e51a96d437d6"}, - {file = "cvxpy-1.1.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40f8a446446070c7d336270ba69a553a9b139af264b09675e9c85d3751d3c840"}, - {file = "cvxpy-1.1.7-cp37-cp37m-win_amd64.whl", hash = "sha256:46b29e622c7e9cb5463f514e7d9fc5f17129b89991a753c215f021f59442e386"}, - {file = "cvxpy-1.1.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:51e6d0e6a6d85b885e99fa443d60f5a07d2a3153b033eae325290f9bfaa48939"}, - {file = "cvxpy-1.1.7-cp38-cp38-win_amd64.whl", hash = "sha256:57cca8490a0d9ea0545ada8da61dfc6bcec91f9a213153224b8b360875d984c7"}, - {file = "cvxpy-1.1.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:53dee27264455368db873854db4eca9adb57b6cd783ccf1d47741f147e9d1f64"}, - {file = "cvxpy-1.1.7-cp39-cp39-win_amd64.whl", hash = "sha256:9d4cf4fbfb95bf4036553ac460a939e2b30c03c986bcbd69ceebb6ea61c12b86"}, - {file = "cvxpy-1.1.7-py3.5-win-amd64.egg", hash = "sha256:2bbd7377aa56352923889a83feb1c4ec2f68c862c556b96e7f0471fa63123a86"}, - {file = "cvxpy-1.1.7-py3.6-win-amd64.egg", hash = "sha256:4247938236794c3c5c34cf26b11869dc15404cfe951b1f4080e9d510fcf81182"}, - {file = "cvxpy-1.1.7-py3.7-win-amd64.egg", hash = "sha256:ae67a06616bf19bf0ee02732b2d7a47fe4a265cbcd56fb500107eba712281440"}, - {file = "cvxpy-1.1.7-py3.8-win-amd64.egg", hash = "sha256:6b2d01c12c9544d17439238ac51eb568e31bc99717f53429b7c4099cd5e46730"}, - {file = "cvxpy-1.1.7-py3.9-win-amd64.egg", hash = "sha256:f1c839762efe3b2c4a1fb1030cc8addefd4154c1a83ccd29b4b81313714e0747"}, - {file = "cvxpy-1.1.7.tar.gz", hash = "sha256:330eb76e8369c360b68d9231c6eb350848e373b5952134f9bfebaed1a4c4211f"}, + {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"}, + {file = "cvxpy-1.1.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:575f6e1c70274008961edff97a7494701faed20b40fbd49327010c0e7d186256"}, + {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.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"}, + {file = "cvxpy-1.1.12-py3.9-win-amd64.egg", hash = "sha256:08c720706abd94c25903a4db5dd2171232e72d0969b874a5de9a8181f96357d5"}, + {file = "cvxpy-1.1.12.tar.gz", hash = "sha256:b499ebfae4fc645e9523621573ffcb1c5b6854a1b5c0ce1d66a8a9a458605807"}, ] cycler = [ {file = "cycler-0.10.0-py2.py3-none-any.whl", hash = "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d"}, @@ -4268,8 +4227,8 @@ pyparsing = [ {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pyportfolioopt = [ - {file = "PyPortfolioOpt-1.3.1-py3-none-any.whl", hash = "sha256:81b9e85c170c84e478a1b1cfc1500198edf4bf7e62b1cc256376bf68f9a7b585"}, - {file = "PyPortfolioOpt-1.3.1.tar.gz", hash = "sha256:d947aaa97bc52b5a5205675bb8df9752dee01f2b4d00c1f27692613f80dc8e8b"}, + {file = "PyPortfolioOpt-1.4.1-py3-none-any.whl", hash = "sha256:73f0b4ac2a5d879879a7a91af038b4d7ff82e9998fb2cad7c249302294e8c09e"}, + {file = "PyPortfolioOpt-1.4.1.tar.gz", hash = "sha256:e6c8e983db92cd13caf41d87fb4dcd945d37053f28b75dd19b5be699b6b1d19e"}, ] pyrsistent = [ {file = "pyrsistent-0.14.11.tar.gz", hash = "sha256:3ca82748918eb65e2d89f222b702277099aca77e34843c5eb9d52451173970e2"}, diff --git a/pyproject.toml b/pyproject.toml index 22e44941a4c..e1333813c84 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,8 +56,7 @@ finvizfinance = "^0.9.3" Pillow = "^8.2.0" statsmodels = "^0.12.2" tabulate = "^0.8.9" -cvxpy = "1.1.7" -pyportfolioopt = "1.3.1" +pyportfolioopt = "^1.4.1" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements-full.txt b/requirements-full.txt index 8a781d293fe..c572e8e2936 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -27,8 +27,7 @@ colorama==0.4.4; (python_version >= "2.7" and python_full_version < "3.0.0") or convertdate==2.3.2; python_version >= "3.5" cryptography==3.4.7; python_version >= "3.6" cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" -cvxopt==1.2.6; python_version >= "3.6" and python_version < "4.0" -cvxpy==1.1.7; python_version >= "3.5" +cvxpy==1.1.12; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" cycler==0.10.0; python_version >= "3.6" cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and python_version >= "3.6" and sys_platform == "darwin" dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.6.2" @@ -37,7 +36,7 @@ decorator==4.4.2; python_full_version >= "3.6.1" and python_version >= "3.6" and defusedxml==0.7.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" deprecated==1.2.12; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" detecta==0.0.5; python_version >= "3.6" -ecos==2.0.7.post1; python_version >= "3.6" and python_version < "4.0" +ecos==2.0.7.post1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" entrypoints==0.3; python_version >= "3.6" ephem==3.7.7.1; python_version >= "2.7" and python_version < "4" fbprophet==0.6 @@ -108,7 +107,7 @@ notebook==6.3.0; python_version >= "3.6" numpy==1.19.5; python_version >= "3.6" oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" opt-einsum==3.3.0; python_version >= "3.5" -osqp==0.6.2.post0; python_version >= "3.6" and python_version < "4.0" +osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" overrides==3.1.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" packaging==20.9; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") pandas-ta==0.2.45b @@ -143,7 +142,7 @@ pyobjc-core==7.1; python_version >= "3.6" and sys_platform == "darwin" pyobjc-framework-cocoa==7.1; python_version >= "3.6" and sys_platform == "darwin" pyotp==2.6.0; python_version >= "3" pyparsing==2.4.7; python_full_version >= "3.6.0" 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") -pyportfolioopt==1.3.1; python_version >= "3.6" and python_version < "4.0" +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" pystan==2.19.1.1 @@ -155,7 +154,7 @@ pywin32==300; sys_platform == "win32" and python_version >= "3.6" pywinpty==0.5.7; os_name == "nt" and python_version >= "3.6" pyyaml==5.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" pyzmq==22.0.3; python_full_version >= "3.6.1" and python_version >= "3.6" -qdldl==0.1.5.post0; python_version >= "3.5" +qdldl==0.1.5.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" qtconsole==5.0.3; python_version >= "3.6" qtpy==1.9.0; python_version >= "3.6" quandl==3.6.1; python_version >= "3.5" @@ -170,7 +169,7 @@ sacremoses==0.0.45; python_full_version >= "3.6.0" and python_version >= "3.6" scikit-learn==0.24.1; python_version >= "3.6" scipy==1.5.4; python_version >= "3.6" screeninfo==0.6.7 -scs==2.1.3; python_version >= "3.6" and python_version < "4.0" +scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" seaborn==0.11.1; python_version >= "3.6" segtok==1.5.10; python_version >= "3.6" send2trash==1.5.0; python_version >= "3.6" diff --git a/requirements.txt b/requirements.txt index 3567ce5b791..b73282d30c2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -21,8 +21,7 @@ colorama==0.4.4; (python_version >= "2.7" and python_full_version < "3.0.0") or convertdate==2.3.2; python_version >= "3.5" cryptography==3.4.7; python_version >= "3.6" cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" -cvxopt==1.2.6; python_version >= "3.6" and python_version < "4.0" -cvxpy==1.1.7; python_version >= "3.5" +cvxpy==1.1.12; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" cycler==0.10.0; python_version >= "3.6" cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and python_version >= "3.6" and sys_platform == "darwin" dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" @@ -30,7 +29,7 @@ datetime==4.3; python_version >= "3.5" decorator==4.4.2; 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.2.0" and python_version >= "3.6") defusedxml==0.7.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" detecta==0.0.5; python_version >= "3.6" -ecos==2.0.7.post1; python_version >= "3.6" and python_version < "4.0" +ecos==2.0.7.post1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" entrypoints==0.3; python_version >= "3.6" finviz==1.4.1 finvizfinance==0.9.6; python_version >= "3.5" @@ -77,7 +76,7 @@ nest-asyncio==1.5.1; python_full_version >= "3.6.1" and python_version >= "3.6" notebook==6.3.0; python_version >= "3.6" numpy==1.19.5; python_version >= "3.6" oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" -osqp==0.6.2.post0; python_version >= "3.6" and python_version < "4.0" +osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" packaging==20.9; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pandas-ta==0.2.45b pandas==1.1.5; python_full_version >= "3.6.1" @@ -108,7 +107,7 @@ pyobjc-core==7.1; python_version >= "3.6" and sys_platform == "darwin" pyobjc-framework-cocoa==7.1; python_version >= "3.6" and sys_platform == "darwin" pyotp==2.6.0; python_version >= "3" pyparsing==2.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -pyportfolioopt==1.3.1; python_version >= "3.6" and python_version < "4.0" +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-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") @@ -119,7 +118,7 @@ pywin32==300; sys_platform == "win32" and python_version >= "3.6" pywinpty==0.5.7; os_name == "nt" and python_version >= "3.6" pyyaml==5.4.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" pyzmq==22.0.3; python_full_version >= "3.6.1" and python_version >= "3.6" -qdldl==0.1.5.post0; python_version >= "3.5" +qdldl==0.1.5.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" qtconsole==5.0.3; python_version >= "3.6" qtpy==1.9.0; python_version >= "3.6" quandl==3.6.1; python_version >= "3.5" @@ -132,7 +131,7 @@ robin-stocks==2.0.3; python_version >= "3" scikit-learn==0.24.1; python_version >= "3.6" scipy==1.5.4; python_version >= "3.6" screeninfo==0.6.7 -scs==2.1.3; python_version >= "3.6" and python_version < "4.0" +scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" seaborn==0.11.1; python_version >= "3.6" send2trash==1.5.0; python_version >= "3.6" six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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 >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") From 907f165fee61f6c3d14e4d2482b63a420011c662 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Mon, 19 Apr 2021 20:02:42 -0700 Subject: [PATCH 067/114] Windows and UTF-8... Omg. --- terminal.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/terminal.py b/terminal.py index e39ba1ff2b9..28c7d7c641c 100644 --- a/terminal.py +++ b/terminal.py @@ -95,6 +95,10 @@ def main(): menu_parser.add_argument("opt", choices=choices) completer = NestedCompleter.from_nested_dict({c: None for c in choices}) + if os.name == "nt": + sys.stdin.reconfigure(encoding="utf-8") + sys.stdout.reconfigure(encoding="utf-8") + # Print first welcome message and help print("\nWelcome to Gamestonk Terminal 🚀\n") should_print_help = True From 0cab663e72676b1e5dc2379fb2db903d25c51bf4 Mon Sep 17 00:00:00 2001 From: Jamie Perkins Date: Mon, 19 Apr 2021 22:15:58 -0700 Subject: [PATCH 068/114] update readme with .env file info --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 1140c5ce2c4..16dc46b38f6 100644 --- a/README.md +++ b/README.md @@ -271,6 +271,11 @@ Example: export GT_API_REDDIT_USERNAME=SexyYear ``` +Environment variables can also be set in a `.env` file at the top of the repo. This file is ignored by git so your API keys will stay secret. The above example stored in `.env` would be: +``` +GT_API_REDDIT_USERNAME=SexyYear +``` + Note that it is not necessary to have a valid Alpha Vantage key to get daily OHLC values. ### Usage From 2b2548f625b33b3858c2d282b763e7fbc0878fc3 Mon Sep 17 00:00:00 2001 From: DJ Date: Tue, 20 Apr 2021 08:41:48 -0600 Subject: [PATCH 069/114] added check for separator --- gamestonk_terminal/forex/fx_view.py | 33 ++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/gamestonk_terminal/forex/fx_view.py b/gamestonk_terminal/forex/fx_view.py index bf8b50c14ea..cc4f1c59842 100644 --- a/gamestonk_terminal/forex/fx_view.py +++ b/gamestonk_terminal/forex/fx_view.py @@ -125,7 +125,7 @@ def list_orders(accountID, other_args: List[str]): "--count", dest="count", action="store", - default=50, + default=20, required=False, help="the number of orders to retrieve ", ) @@ -134,7 +134,7 @@ def list_orders(accountID, other_args: List[str]): return parameters = {} - parameters["state"] = ns_parser.state + parameters["state"] = ns_parser.state.upper() parameters["count"] = ns_parser.count try: @@ -165,6 +165,7 @@ def get_order_book(instrument, other_args): return parameters = {"bucketWidth": "1"} try: + instrument = format_instrument(instrument, "_") request = instruments.InstrumentsOrderBook( instrument=instrument, params=parameters ) @@ -191,6 +192,7 @@ def get_position_book(instrument, other_args): return try: + instrument = format_instrument(instrument, "_") request = instruments.InstrumentsPositionBook(instrument=instrument) response = client.request(request) df = pd.DataFrame.from_dict(response["positionBook"]["buckets"]) @@ -284,7 +286,7 @@ def create_order(accountID, instrument, other_args: List[str]): def cancel_pending_order(accountID, other_args: List[str]): parser = argparse.ArgumentParser( add_help=False, - prog="pending", + prog="cancel", description="Cancel Pending Order ", ) parser.add_argument( @@ -412,6 +414,7 @@ def get_open_trades(accountID, other_args): "initialUnits": "Initial Units", "currentUnits": "Current Units", "price": "Entry Price", + "unrealizedPL": "Unrealized P/L", } ) print(df) @@ -438,7 +441,7 @@ def close_trade(accountID, other_args: List[str]): dest="orderID", action="store", type=str, - required=True, + required=False, help="The Trade ID to close. ", ) parser.add_argument( @@ -446,13 +449,12 @@ def close_trade(accountID, other_args: List[str]): "--units", dest="units", action="store", - type=str, required=False, help="The number of units on the trade to close. If not set it " + "defaults to all units. ", ) if other_args: - if "-" not in other_args[0]: + if "-i" not in other_args[0]: other_args.insert(0, "-i") ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: @@ -460,7 +462,7 @@ def close_trade(accountID, other_args: List[str]): data = {} if ns_parser.units is not None: - data["units"] = (ns_parser.units,) + data["units"] = ns_parser.units try: request = trades.TradeClose(accountID, ns_parser.orderID, data) response = client.request(request) @@ -522,6 +524,7 @@ def show_candles(accountID, instrument, other_args: List[str]): parameters["granularity"] = ns_parser.granularity parameters["count"] = ns_parser.candlecount try: + instrument = format_instrument(instrument, "_") request = instruments.InstrumentsCandles(instrument, params=parameters) response = client.request(request) process_candle_response(response) @@ -635,11 +638,16 @@ def calendar(instrument, other_args: List[str]): else: previous = "" + if "impact" in response[i]: + impact = response[i]["impact"] + else: + impact = "" + l_data.append( { "Title": response[i]["title"], "Time": datetime.fromtimestamp(response[i]["timestamp"]), - "Impact": response[i]["impact"], + "Impact": impact, "Forecast": forecast, "Market Forecast": market, "Currency": response[i]["currency"], @@ -729,3 +737,12 @@ def book_plot(df, instrument, book_type): if gtff.USE_ION: plt.ion() plt.show() + + +def format_instrument(instrument, char): + if char not in instrument: + instrument_list = list(instrument) + instrument_list.pop(3) + instrument_list.insert(3, char) + instrument = "".join(map(str, instrument_list)) + return instrument From ff970751e0371f20a8a03925041649d5eda38676 Mon Sep 17 00:00:00 2001 From: DJ Date: Tue, 20 Apr 2021 08:42:09 -0600 Subject: [PATCH 070/114] added README --- gamestonk_terminal/forex/README.md | 146 +++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 gamestonk_terminal/forex/README.md diff --git a/gamestonk_terminal/forex/README.md b/gamestonk_terminal/forex/README.md new file mode 100644 index 00000000000..4e00e174a20 --- /dev/null +++ b/gamestonk_terminal/forex/README.md @@ -0,0 +1,146 @@ +# Forex + +This menu utilizes oanda to enable support for trading forex. + +* [summary] (#summary) + * Display a summary of your account +* [calendar] (#calendar) + * Get information about past or upcoming events which may impact the price +* [list] (#list) + * List your order history +* [pending] (#pending) + * Get information about pending orders +* [cancel] (#cancel) + * Cancel a pending order by ID +* [positions] (#positions) + * Get information about your positions +* [trades] (#trades) + * See a list of open trades +* [closetrade] (#closetrade) + * Close a trade by ID +* [load] (#load) + *Specify an instrument to use +* [candles] (#candles) + * Get a candlestick chart for the forex instrument +* [price] (#price) + * Show the current price for the forex instrument +* [order] (#order) + * Place a limit order +* [orderbook] (#orderbook) + * Display the orderbook if Oanda provides one for the forex instrument +* [positionbook] (#positionbook) + * Display the positionbook if Oanda provides one for the forex instrument + +## summary + ```text + usage: summary + ``` + + Displays current balance, net asset value, unrealized P/L, total P/L, count of open trades, how much margin is available, how much margin you've used, the margin call value, the percent of margin until closeout, and the total position value. + +## calendar + +```text +usage: calendar [-d DAYS] +``` + +Display information about past or upcoming events up to 30 days before or from todays date. The information includes the Title of the event, the time the event is scheduled, the rated impact, Oanda's forecast, the market forecast, the currency involved, the region from which the event originates, the actual value (for events that have finished), and the previous value. + +* -d : The number of days to search (7 is the default, 30 is the maximum that information is provided for). Use a positive value to search for upcoming events and a negative value to search for past events. + +## list +```text +usage: list [-s STATE] [-c COUNT] +``` + +Retrieves a list of orders you've made. It includes the ID, the instrument, the number of units, the price, the state of the order, and the type of order. + +* -s : The state of the orders to filter. You can specify: pending, filled, triggered, canceled or all. (default=all) +* -c : The number of orders to retrieve. (default = 20) + +## pending +```text +usage: pending +``` +A shortcut to list the pending orders for your account. It includes the ID, the instrument, the price, the number of units, the time the order was created and the time in force. + +## cancel +```text +usage: cancel [-i ORDERID] +``` + +Cancel a pending order by its order ID. + +* -i : Specify the order ID. You don't need to include this, simply include the order number. + +##positions +```text +usage: positions +``` + +Lists your open positions. The information includes the instrument, the current number of long units, the total profit/loss from long positions for the account, the unrealized profit/loss from long positions, the current number of short units, the total profit/loss from short positions for the account, and the unrealized profit/loss from short positions. + +##trades +```text +usage: trades +``` + +Lists the current open trades for your account. The information includes the ID, the instrument, the initial units opened for the trade, the current number of units open for the trade, it's entry price, and the unrealized profit/loss for the trade. + +##closetrade +```text +usage: closetrade [-i ORDERID] [-u UNITS] +``` + +Closes a trade by ID. Displays the order ID closed, the instrument, the number of units that were closed, the price, and the profit/loss + +* -i : Specify the order ID. You don't need to include this, simply include the order number. +* -u : Specify the number of units to close for that trade. (default=all) + +##load +```text +usage: load [-i INSTRUMENT] +``` + +Specify the instrument to use in the format EUR_USD + +* -i : Specify the instrument. You don't need to include this, simply include the instrument. + +##candles +```text +usage: candles [-g GRANULARITY] [-c CANDLECOUNT] +``` + +Retrieve a candlestick chart for the currently loaded instrument. Not a live chart. + +* -g : Specify the granularity, which is the timeframe each candle represents. The available granularities are Seconds: S5, S10, S15, S30 Minutes: M1, M2, M4, M5, M10, M15, M30 Hours: H1, H2, H3, H4, H6, H8, H12 Day: D, Week: W Month: M. (default=D) +* -c : Specify the number of candles to retrieve. (default=180) + +##price +```text +usage: price +``` + +Gets the current price for the currently loaded instrument + +##order +```text +usage: order -u UNITS -p PRICE +``` + +Places a limit order for the specified number of units at the specified price. Both arguments are required. + +* -u : Specify the number of units for the order. +* -p : Specify the price for the limit order. + +##orderbook +```text +usage: orderbook +``` +Plots the current orderbook for loaded instrument if one is provided by Oanda. Not a live chart. + +##positionbook +```text +usage: positionbook +``` +Plots the current positionbook for the loaded instrument if one is provided by Oanda. Not a live chart. From f59f9257a3cc9787169531e8f7de8e56a68d20fe Mon Sep 17 00:00:00 2001 From: DJ Date: Tue, 20 Apr 2021 08:59:47 -0600 Subject: [PATCH 071/114] Delete gamestonk_terminal/oanda directory --- gamestonk_terminal/oanda/__init.py__ | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 gamestonk_terminal/oanda/__init.py__ diff --git a/gamestonk_terminal/oanda/__init.py__ b/gamestonk_terminal/oanda/__init.py__ deleted file mode 100644 index e69de29bb2d..00000000000 From 2e4c4d1becff10821dd184ee7bf552644baf4058 Mon Sep 17 00:00:00 2001 From: DJ Date: Tue, 20 Apr 2021 09:03:24 -0600 Subject: [PATCH 072/114] added a space --- gamestonk_terminal/forex/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamestonk_terminal/forex/README.md b/gamestonk_terminal/forex/README.md index 4e00e174a20..53aca19e373 100644 --- a/gamestonk_terminal/forex/README.md +++ b/gamestonk_terminal/forex/README.md @@ -19,7 +19,7 @@ This menu utilizes oanda to enable support for trading forex. * [closetrade] (#closetrade) * Close a trade by ID * [load] (#load) - *Specify an instrument to use + * Specify an instrument to use * [candles] (#candles) * Get a candlestick chart for the forex instrument * [price] (#price) From a88519dd4be7051edd5097788a8fb3d813d2a370 Mon Sep 17 00:00:00 2001 From: DJ Date: Tue, 20 Apr 2021 09:07:11 -0600 Subject: [PATCH 073/114] removed spaces --- gamestonk_terminal/forex/README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/gamestonk_terminal/forex/README.md b/gamestonk_terminal/forex/README.md index 53aca19e373..4e3f928c4f9 100644 --- a/gamestonk_terminal/forex/README.md +++ b/gamestonk_terminal/forex/README.md @@ -2,33 +2,33 @@ This menu utilizes oanda to enable support for trading forex. -* [summary] (#summary) +* [summary](#summary) * Display a summary of your account -* [calendar] (#calendar) +* [calendar](#calendar) * Get information about past or upcoming events which may impact the price -* [list] (#list) +* [list](#list) * List your order history -* [pending] (#pending) +* [pending](#pending) * Get information about pending orders -* [cancel] (#cancel) +* [cancel](#cancel) * Cancel a pending order by ID -* [positions] (#positions) +* [positions](#positions) * Get information about your positions -* [trades] (#trades) +* [trades](#trades) * See a list of open trades -* [closetrade] (#closetrade) +* [closetrade](#closetrade) * Close a trade by ID -* [load] (#load) +* [load](#load) * Specify an instrument to use -* [candles] (#candles) +* [candles](#candles) * Get a candlestick chart for the forex instrument -* [price] (#price) +* [price](#price) * Show the current price for the forex instrument -* [order] (#order) +* [order](#order) * Place a limit order -* [orderbook] (#orderbook) +* [orderbook](#orderbook) * Display the orderbook if Oanda provides one for the forex instrument -* [positionbook] (#positionbook) +* [positionbook](#positionbook) * Display the positionbook if Oanda provides one for the forex instrument ## summary From 23f12c294c11023dbff2f1090bd3e5e6d578739d Mon Sep 17 00:00:00 2001 From: DJ Date: Tue, 20 Apr 2021 09:08:42 -0600 Subject: [PATCH 074/114] Fix README --- gamestonk_terminal/forex/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/gamestonk_terminal/forex/README.md b/gamestonk_terminal/forex/README.md index 4e3f928c4f9..079b5fb4d5d 100644 --- a/gamestonk_terminal/forex/README.md +++ b/gamestonk_terminal/forex/README.md @@ -73,21 +73,21 @@ Cancel a pending order by its order ID. * -i : Specify the order ID. You don't need to include this, simply include the order number. -##positions +## positions ```text usage: positions ``` Lists your open positions. The information includes the instrument, the current number of long units, the total profit/loss from long positions for the account, the unrealized profit/loss from long positions, the current number of short units, the total profit/loss from short positions for the account, and the unrealized profit/loss from short positions. -##trades +## trades ```text usage: trades ``` Lists the current open trades for your account. The information includes the ID, the instrument, the initial units opened for the trade, the current number of units open for the trade, it's entry price, and the unrealized profit/loss for the trade. -##closetrade +## closetrade ```text usage: closetrade [-i ORDERID] [-u UNITS] ``` @@ -97,7 +97,7 @@ Closes a trade by ID. Displays the order ID closed, the instrument, the number o * -i : Specify the order ID. You don't need to include this, simply include the order number. * -u : Specify the number of units to close for that trade. (default=all) -##load +## load ```text usage: load [-i INSTRUMENT] ``` @@ -106,7 +106,7 @@ Specify the instrument to use in the format EUR_USD * -i : Specify the instrument. You don't need to include this, simply include the instrument. -##candles +## candles ```text usage: candles [-g GRANULARITY] [-c CANDLECOUNT] ``` @@ -116,14 +116,14 @@ Retrieve a candlestick chart for the currently loaded instrument. Not a live cha * -g : Specify the granularity, which is the timeframe each candle represents. The available granularities are Seconds: S5, S10, S15, S30 Minutes: M1, M2, M4, M5, M10, M15, M30 Hours: H1, H2, H3, H4, H6, H8, H12 Day: D, Week: W Month: M. (default=D) * -c : Specify the number of candles to retrieve. (default=180) -##price +## price ```text usage: price ``` Gets the current price for the currently loaded instrument -##order +## order ```text usage: order -u UNITS -p PRICE ``` @@ -133,13 +133,13 @@ Places a limit order for the specified number of units at the specified price. B * -u : Specify the number of units for the order. * -p : Specify the price for the limit order. -##orderbook +## orderbook ```text usage: orderbook ``` Plots the current orderbook for loaded instrument if one is provided by Oanda. Not a live chart. -##positionbook +## positionbook ```text usage: positionbook ``` From b7feb17d597335254476707f24b18b41675cd3a0 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Apr 2021 15:12:10 -0400 Subject: [PATCH 075/114] scrape barchart to get options information, added to poetry and reqs --- gamestonk_terminal/config_terminal.py | 4 + gamestonk_terminal/options/op_controller.py | 8 +- gamestonk_terminal/options/op_scrape_view.py | 102 +++++++++++++++++++ poetry.lock | 27 +++-- pyproject.toml | 1 + requirements-full.txt | 1 + requirements-old.txt | 1 + requirements-win.txt | 1 + requirements.txt | 1 + 9 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 gamestonk_terminal/options/op_scrape_view.py diff --git a/gamestonk_terminal/config_terminal.py b/gamestonk_terminal/config_terminal.py index daf66a26be6..e73b5c2bee4 100644 --- a/gamestonk_terminal/config_terminal.py +++ b/gamestonk_terminal/config_terminal.py @@ -38,3 +38,7 @@ RH_PASSWORD = os.getenv("GT_RH_PASSWORD") or "REPLACE_ME" # https://tradier.com/products/market-data-api TRADIER_TOKEN = os.getenv("GT_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" diff --git a/gamestonk_terminal/options/op_controller.py b/gamestonk_terminal/options/op_controller.py index 4a37d485327..5ba3ad04dc8 100644 --- a/gamestonk_terminal/options/op_controller.py +++ b/gamestonk_terminal/options/op_controller.py @@ -9,7 +9,7 @@ import yfinance as yf from prompt_toolkit.completion import NestedCompleter from gamestonk_terminal.helper_funcs import get_flair, parse_known_args_and_warn from gamestonk_terminal import feature_flags as gtff -from gamestonk_terminal.options import volume_view, chains_view +from gamestonk_terminal.options import volume_view, chains_view, op_scrape_view from gamestonk_terminal.menu import session @@ -17,7 +17,7 @@ class OptionsController: """Options Controller class.""" # Command choices - CHOICES = ["help", "q", "quit", "exp", "voi", "vcalls", "vputs", "chains"] + CHOICES = ["help", "q", "quit", "exp", "voi", "vcalls", "vputs", "chains", "info"] def __init__(self, ticker: str, last_adj_close_price: float): """Construct data.""" @@ -94,6 +94,7 @@ class OptionsController: print(" vputs puts volume + open interest plot") print("") print(" chains display option chains") + print(" info display option information (volatility, IV rank etc)") print("") return @@ -163,6 +164,9 @@ class OptionsController: def call_chains(self, other_args): chains_view.display_chains(self.ticker, self.expiry_date, other_args) + def call_info(self, other_args): + op_scrape_view.print_options_data(self.ticker, other_args) + def menu(ticker: str, last_adj_close_price: float): """ Options Menu. """ diff --git a/gamestonk_terminal/options/op_scrape_view.py b/gamestonk_terminal/options/op_scrape_view.py new file mode 100644 index 00000000000..78b07ac8919 --- /dev/null +++ b/gamestonk_terminal/options/op_scrape_view.py @@ -0,0 +1,102 @@ +"""Helper functions for scraping options data""" +__docformat__ = "numpy" + +import argparse +from typing import List +from selenium import webdriver +from bs4 import BeautifulSoup +from selenium.webdriver.chrome.options import Options as cOpts +from selenium.webdriver.firefox.options import Options as fOpts +import pandas as pd +from tabulate import tabulate +from gamestonk_terminal.config_terminal import ( + PATH_TO_SELENIUM_DRIVER as path_to_driver, + WEBDRIVER_TO_USE as web, +) +from gamestonk_terminal.helper_funcs import parse_known_args_and_warn + +browsers = ["chrome", "firefox"] + + +def print_options_data(stock: str, other_args: List[str]): + """ + Scrapes Barchart.com for the options information + Parameters + ---------- + stock: str + Ticker to get options info for + other_args: List[str] + Other arguments. Currently just accepts a browser flag for selenium + + """ + + if path_to_driver is None: + print("Please specify your selenium driver path in config_terminal.py") + print("") + return + + parser = argparse.ArgumentParser( + prog="info", + add_help=False, + description="Display option data [Source: Barchart.com]", + ) + + parser.add_argument( + "-b", + "--browser", + dest="browser", + help="selenium webdriver to use", + choices=browsers, + default=None, + ) + + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + if ns_parser.browser: + browser = ns_parser.browser + else: + browser = web + + except Exception as e: + print(e) + print("") + return + + try: + if browser == "chrome": + options = cOpts() + options.headless = True + driver = webdriver.Chrome(options=options, executable_path=path_to_driver) + + elif browser == "firefox": + options = fOpts() + options.headless = True + driver = webdriver.Firefox(options=options, executable_path=path_to_driver) + + page = f"https://www.barchart.com/stocks/quotes/{stock}/overview" + driver.get(page) + + soup = BeautifulSoup(driver.page_source, "html.parser") + tags = soup.find( + "div", + attrs={ + "class": "barchart-content-block symbol-fundamentals bc-cot-table-wrapper" + }, + ) + data = tags.find_all("li") + labels = [] + values = [] + print("") + for row in data: + labels.append(row.find_all("span")[0].getText()) + values.append(row.find_all("span")[1].getText()) + + df = pd.DataFrame(data=[labels, values]).T + print(tabulate(df, tablefmt="fancy_grid", showindex=False)) + print("") + + except Exception as e: + print(e) + print("") diff --git a/poetry.lock b/poetry.lock index 0a01734d46e..cf7d0cbe959 100644 --- a/poetry.lock +++ b/poetry.lock @@ -999,7 +999,7 @@ name = "joblib" version = "1.0.1" description = "Lightweight pipelining with Python functions" category = "main" -optional = true +optional = false python-versions = ">=3.6" [[package]] @@ -2295,7 +2295,7 @@ name = "scikit-learn" version = "0.24.1" description = "A set of python modules for machine learning and data mining" category = "main" -optional = true +optional = false python-versions = ">=3.6" [package.dependencies] @@ -2371,6 +2371,17 @@ python-versions = "*" [package.dependencies] regex = "*" +[[package]] +name = "selenium" +version = "3.141.0" +description = "Python bindings for Selenium" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +urllib3 = "*" + [[package]] name = "send2trash" version = "1.5.0" @@ -2589,7 +2600,7 @@ name = "threadpoolctl" version = "2.1.0" description = "threadpoolctl" category = "main" -optional = true +optional = false python-versions = ">=3.5" [[package]] @@ -2918,7 +2929,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "623e5809320b1fb71c692bdd6cdcb9ea3419f3a5b3592e6c755816bd493769bc" +content-hash = "2f3963dac96a208dfe5157d593c45f946d9b4c829b16302f2b297250390367cb" [metadata.files] absl-py = [ @@ -4523,7 +4534,6 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c658432d8a20e95398f6bb95ff9731ce9dfa343fdf21eea7ec6a7edfacd4b4d9"}, {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9dfa564ef27e8e674aa1cc74378416d580ac4ede1136c13dd555a87996e13422"}, {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:9c6097b6a9b2bafc5e0f31f659e6ab5e131383209c30c9e978c5b8abdac5ed2a"}, - {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:5580eba7345a4d3b097be2f067cc71a306c44bab19e8717a30361f279c929bea"}, {file = "scikit_learn-0.24.1-cp36-cp36m-win32.whl", hash = "sha256:7b04691eb2f41d2c68dbda8d1bd3cb4ef421bdc43aaa56aeb6c762224552dfb6"}, {file = "scikit_learn-0.24.1-cp36-cp36m-win_amd64.whl", hash = "sha256:1adf483e91007a87171d7ce58c34b058eb5dab01b5fee6052f15841778a8ecd8"}, {file = "scikit_learn-0.24.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:ddb52d088889f5596bc4d1de981f2eca106b58243b6679e4782f3ba5096fd645"}, @@ -4531,7 +4541,6 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0567a2d29ad08af98653300c623bd8477b448fe66ced7198bef4ed195925f082"}, {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:99349d77f54e11f962d608d94dfda08f0c9e5720d97132233ebdf35be2858b2d"}, {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:83b21ff053b1ff1c018a2d24db6dd3ea339b1acfbaa4d9c881731f43748d8b3b"}, - {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:abe835a851610f87201819cb315f8d554e1a3e8128912783a31e87264ba5ffb7"}, {file = "scikit_learn-0.24.1-cp37-cp37m-win32.whl", hash = "sha256:c3deb3b19dd9806acf00cf0d400e84562c227723013c33abefbbc3cf906596e9"}, {file = "scikit_learn-0.24.1-cp37-cp37m-win_amd64.whl", hash = "sha256:d54dbaadeb1425b7d6a66bf44bee2bb2b899fe3e8850b8e94cfb9c904dcb46d0"}, {file = "scikit_learn-0.24.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:3c4f07f47c04e81b134424d53c3f5e16dfd7f494e44fd7584ba9ce9de2c5e6c1"}, @@ -4539,7 +4548,6 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4ddd2b6f7449a5d539ff754fa92d75da22de261fd8fdcfb3596799fadf255101"}, {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:826b92bf45b8ad80444814e5f4ac032156dd481e48d7da33d611f8fe96d5f08b"}, {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:259ec35201e82e2db1ae2496f229e63f46d7f1695ae68eef9350b00dc74ba52f"}, - {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:9599a3f3bf33f73fed0fe06d1dfa4e6081365a58c1c807acb07271be0dce9733"}, {file = "scikit_learn-0.24.1-cp38-cp38-win32.whl", hash = "sha256:8772b99d683be8f67fcc04789032f1b949022a0e6880ee7b75a7ec97dbbb5d0b"}, {file = "scikit_learn-0.24.1-cp38-cp38-win_amd64.whl", hash = "sha256:ed9d65594948678827f4ff0e7ae23344e2f2b4cabbca057ccaed3118fdc392ca"}, {file = "scikit_learn-0.24.1-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:8aa1b3ac46b80eaa552b637eeadbbce3be5931e4b5002b964698e33a1b589e1e"}, @@ -4547,7 +4555,6 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:087dfede39efb06ab30618f9ab55a0397f29c38d63cd0ab88d12b500b7d65fd7"}, {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:895dbf2030aa7337649e36a83a007df3c9811396b4e2fa672a851160f36ce90c"}, {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:9a24d1ccec2a34d4cd3f2a1f86409f3f5954cc23d4d2270ba0d03cf018aa4780"}, - {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:54be0a60a5a35005ad69c75902e0f5c9f699db4547ead427e97ef881c3242e6f"}, {file = "scikit_learn-0.24.1-cp39-cp39-win32.whl", hash = "sha256:fab31f48282ebf54dd69f6663cd2d9800096bad1bb67bbc9c9ac84eb77b41972"}, {file = "scikit_learn-0.24.1-cp39-cp39-win_amd64.whl", hash = "sha256:4562dcf4793e61c5d0f89836d07bc37521c3a1889da8f651e2c326463c4bd697"}, ] @@ -4591,6 +4598,10 @@ seaborn = [ segtok = [ {file = "segtok-1.5.10.tar.gz", hash = "sha256:2ed6525e840a669ec7ba3be61353a4f660264aecfc726834dbe4b01eb4ef7804"}, ] +selenium = [ + {file = "selenium-3.141.0-py2.py3-none-any.whl", hash = "sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c"}, + {file = "selenium-3.141.0.tar.gz", hash = "sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d"}, +] send2trash = [ {file = "Send2Trash-1.5.0-py3-none-any.whl", hash = "sha256:f1691922577b6fa12821234aeb57599d887c4900b9ca537948d2dac34aea888b"}, {file = "Send2Trash-1.5.0.tar.gz", hash = "sha256:60001cc07d707fe247c94f74ca6ac0d3255aabcb930529690897ca2a39db28b2"}, diff --git a/pyproject.toml b/pyproject.toml index 12ccd7ebcc8..9953f8d9d0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,6 +57,7 @@ Pillow = "^8.2.0" pyportfolioopt = "^1.4.1" statsmodels = "^0.12.2" tabulate = "^0.8.9" +selenium = "^3.141.0" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements-full.txt b/requirements-full.txt index 1c51e43294a..811dfe41ef7 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -159,6 +159,7 @@ scikit-learn==0.24.1; python_version >= "3.6" scipy==1.5.4; python_version >= "3.6" seaborn==0.11.1; python_version >= "3.6" segtok==1.5.10; python_version >= "3.6" +selenium==3.141.0 send2trash==1.5.0; python_version >= "3.5" sentencepiece==0.1.91; python_full_version >= "3.6.0" and python_version >= "3.6" setuptools-git==1.2 diff --git a/requirements-old.txt b/requirements-old.txt index 3a4b6bb05c4..3dd16fb2a3f 100644 --- a/requirements-old.txt +++ b/requirements-old.txt @@ -109,6 +109,7 @@ sacremoses==0.0.43; python_full_version >= "3.6.0" and python_version >= "3.6" scikit-learn==0.24.1; python_version >= "3.6" scipy==1.5.4; python_version >= "3.6" segtok==1.5.10; python_version >= "3.6" +selenium==3.141.0 sentencepiece==0.1.91; python_full_version >= "3.6.0" and python_version >= "3.6" setuptools-git==1.2 six==1.15.0; python_full_version >= "3.6.0" and python_version >= "3.6" and python_version < "4.0" 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.6.0") diff --git a/requirements-win.txt b/requirements-win.txt index 560a2508261..d5b413e1ca6 100644 --- a/requirements-win.txt +++ b/requirements-win.txt @@ -111,6 +111,7 @@ sacremoses==0.0.43; python_full_version >= "3.6.0" and python_version >= "3.6" scikit-learn==0.24.1; python_version >= "3.6" scipy==1.6.1; python_version >= "3.6" segtok==1.5.10; python_version >= "3.6" +selenium==3.141.0 sentencepiece==0.1.91; python_full_version >= "3.6.0" and python_version >= "3.6" setuptools-git==1.2 six==1.15.0; python_full_version >= "3.6.0" and python_version >= "3.6" and python_version < "4.0" 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.6.0") diff --git a/requirements.txt b/requirements.txt index 4f4ba01310a..033adeb8d2b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -112,6 +112,7 @@ retrying==1.3.3 robin-stocks==2.0.3 scipy==1.5.4; python_version >= "3.6" seaborn==0.11.1; python_version >= "3.6" +selenium==3.141.0 send2trash==1.5.0; python_version >= "3.5" six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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 >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.5") soupsieve==2.2; python_version >= "3.6" From 2c304a1b656c1d7c620b6bdd78bbe9a7fbf81741 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Apr 2021 15:42:44 -0400 Subject: [PATCH 076/114] update readme + add test --- gamestonk_terminal/config_terminal.py | 2 +- gamestonk_terminal/options/README.md | 18 +++++++++++ tests/test_op_scrape_view.py | 45 +++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/test_op_scrape_view.py diff --git a/gamestonk_terminal/config_terminal.py b/gamestonk_terminal/config_terminal.py index e73b5c2bee4..589da4b6e07 100644 --- a/gamestonk_terminal/config_terminal.py +++ b/gamestonk_terminal/config_terminal.py @@ -41,4 +41,4 @@ TRADIER_TOKEN = os.getenv("GT_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" +PATH_TO_SELENIUM_DRIVER = None # Replace with "PATH" diff --git a/gamestonk_terminal/options/README.md b/gamestonk_terminal/options/README.md index 536ba329147..300574e5de9 100644 --- a/gamestonk_terminal/options/README.md +++ b/gamestonk_terminal/options/README.md @@ -14,6 +14,9 @@ This menu aims to give insight on options. Options can cause significant share p * Puts volume + open interest plot [Yahoo Finance] * [chains](#chains) * Display option chains [Source: Tradier] +* [info](#info) + * _**This requires selenium webdriver installed**_ + * Display option information [Source: Barchart.com] ## exp @@ -88,3 +91,18 @@ Display options chains. [Source: Tradier] chains + + +## info +This scrapes the options information from barchart.com/stocks overview. This includes information such as Historical Volatility and IV Rank. + +In order to run, the selenium webdriver must be installed. +Currently, this runs on either Chrome or Firefox. The path to the driver should be defined in [config_terminal.py](#config_terminal.py). + +Note this may take more time than other commands to process. +```` +usage: info [-d DRIVER] +```` +* -d/--driver : One of {chrome, firefox}. This indicates which driver you have installed. + +![im](https://user-images.githubusercontent.com/18151143/115454584-efa83a00-a1ee-11eb-9d0f-2558ffa31579.png) \ No newline at end of file diff --git a/tests/test_op_scrape_view.py b/tests/test_op_scrape_view.py new file mode 100644 index 00000000000..52253ec8026 --- /dev/null +++ b/tests/test_op_scrape_view.py @@ -0,0 +1,45 @@ +""" Simple test to make sure selenium installed. Taken from the docs""" +import unittest +from selenium import webdriver +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.chrome.options import Options as cOpts +from selenium.webdriver.firefox.options import Options as fOpts + +from gamestonk_terminal.config_terminal import ( + PATH_TO_SELENIUM_DRIVER as path_to_driver, + WEBDRIVER_TO_USE as web, +) + + +class PythonOrgSearch(unittest.TestCase): + def setUp(self): + if path_to_driver is None: + raise FileNotFoundError("driver path not found in config_terminal.py") + if web == "firefox": + opts = fOpts() + opts.headless = True + self.driver = webdriver.Firefox( + options=opts, executable_path=path_to_driver + ) + elif web == "chrome": + opts = cOpts() + opts.headless = True + self.driver = webdriver.Chrome(options=opts, executable_path=path_to_driver) + else: + raise FileNotFoundError("Webbrowser not found in config_terminal.py") + + def test_search_in_python_org(self): + driver = self.driver + driver.get("http://www.python.org") + self.assertIn("Python", driver.title) + elem = driver.find_element_by_name("q") + elem.send_keys("pycon") + elem.send_keys(Keys.RETURN) + assert "No results found." not in driver.page_source + + def tearDown(self): + self.driver.close() + + +if __name__ == "__main__": + unittest.main() From 6a45ce11af1c903cb187ed772b9dc2a45fd69fdf Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Apr 2021 15:59:35 -0400 Subject: [PATCH 077/114] update requirements after merge --- poetry.lock | 25 ++++++++++++++++++++++++- pyproject.toml | 1 + requirements-full.txt | 1 + requirements.txt | 1 + 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index a2faa511bcd..582cfdfc228 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2377,6 +2377,17 @@ python-versions = "*" [package.dependencies] regex = "*" +[[package]] +name = "selenium" +version = "3.141.0" +description = "Python bindings for Selenium" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +urllib3 = "*" + [[package]] name = "send2trash" version = "1.5.0" @@ -2935,7 +2946,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "bc7a1735d2e1abb9e5773bfafaeb58d8b53babffb2e0f37f04cb751a218782d4" +content-hash = "2f3963dac96a208dfe5157d593c45f946d9b4c829b16302f2b297250390367cb" [metadata.files] absl-py = [ @@ -4315,18 +4326,26 @@ pyyaml = [ {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, + {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, + {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, + {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, + {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, + {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, + {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, + {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, + {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, @@ -4595,6 +4614,10 @@ seaborn = [ segtok = [ {file = "segtok-1.5.10.tar.gz", hash = "sha256:2ed6525e840a669ec7ba3be61353a4f660264aecfc726834dbe4b01eb4ef7804"}, ] +selenium = [ + {file = "selenium-3.141.0-py2.py3-none-any.whl", hash = "sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c"}, + {file = "selenium-3.141.0.tar.gz", hash = "sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d"}, +] send2trash = [ {file = "Send2Trash-1.5.0-py3-none-any.whl", hash = "sha256:f1691922577b6fa12821234aeb57599d887c4900b9ca537948d2dac34aea888b"}, {file = "Send2Trash-1.5.0.tar.gz", hash = "sha256:60001cc07d707fe247c94f74ca6ac0d3255aabcb930529690897ca2a39db28b2"}, diff --git a/pyproject.toml b/pyproject.toml index e1333813c84..53f0f468699 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,6 +57,7 @@ Pillow = "^8.2.0" statsmodels = "^0.12.2" tabulate = "^0.8.9" pyportfolioopt = "^1.4.1" +selenium = "^3.141.0" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements-full.txt b/requirements-full.txt index c572e8e2936..39247ebb9c6 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -172,6 +172,7 @@ screeninfo==0.6.7 scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" seaborn==0.11.1; python_version >= "3.6" segtok==1.5.10; python_version >= "3.6" +selenium==3.141.0 send2trash==1.5.0; python_version >= "3.6" sentencepiece==0.1.91; python_full_version >= "3.6.0" and python_version >= "3.6" setuptools-git==1.2 diff --git a/requirements.txt b/requirements.txt index b73282d30c2..31e6b0412cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -133,6 +133,7 @@ scipy==1.5.4; python_version >= "3.6" screeninfo==0.6.7 scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" seaborn==0.11.1; python_version >= "3.6" +selenium==3.141.0 send2trash==1.5.0; python_version >= "3.6" six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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 >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") soupsieve==2.2.1; python_version >= "3.6" From 8aa85e2b8b12535df22b42f3ce45ae0350fd64ba Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Apr 2021 16:06:38 -0400 Subject: [PATCH 078/114] get rid of test for workflow --- tests/test_op_scrape_view.py | 45 ------------------------------------ 1 file changed, 45 deletions(-) delete mode 100644 tests/test_op_scrape_view.py diff --git a/tests/test_op_scrape_view.py b/tests/test_op_scrape_view.py deleted file mode 100644 index 52253ec8026..00000000000 --- a/tests/test_op_scrape_view.py +++ /dev/null @@ -1,45 +0,0 @@ -""" Simple test to make sure selenium installed. Taken from the docs""" -import unittest -from selenium import webdriver -from selenium.webdriver.common.keys import Keys -from selenium.webdriver.chrome.options import Options as cOpts -from selenium.webdriver.firefox.options import Options as fOpts - -from gamestonk_terminal.config_terminal import ( - PATH_TO_SELENIUM_DRIVER as path_to_driver, - WEBDRIVER_TO_USE as web, -) - - -class PythonOrgSearch(unittest.TestCase): - def setUp(self): - if path_to_driver is None: - raise FileNotFoundError("driver path not found in config_terminal.py") - if web == "firefox": - opts = fOpts() - opts.headless = True - self.driver = webdriver.Firefox( - options=opts, executable_path=path_to_driver - ) - elif web == "chrome": - opts = cOpts() - opts.headless = True - self.driver = webdriver.Chrome(options=opts, executable_path=path_to_driver) - else: - raise FileNotFoundError("Webbrowser not found in config_terminal.py") - - def test_search_in_python_org(self): - driver = self.driver - driver.get("http://www.python.org") - self.assertIn("Python", driver.title) - elem = driver.find_element_by_name("q") - elem.send_keys("pycon") - elem.send_keys(Keys.RETURN) - assert "No results found." not in driver.page_source - - def tearDown(self): - self.driver.close() - - -if __name__ == "__main__": - unittest.main() From 296bb4b32164841749e43648bd6a3e5b3f73f73a Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 13:21:49 -0700 Subject: [PATCH 079/114] Refactoring comparison analysis --- .../comparison_analysis/ca_controller.py | 91 +++++++++++----- .../{finbrain_api.py => finbrain_view.py} | 6 ++ ...rket_watch_api.py => market_watch_view.py} | 3 + ...o_finance_api.py => yahoo_finance_view.py} | 100 ++++++++++++++---- 4 files changed, 155 insertions(+), 45 deletions(-) rename gamestonk_terminal/comparison_analysis/{finbrain_api.py => finbrain_view.py} (99%) rename gamestonk_terminal/comparison_analysis/{market_watch_api.py => market_watch_view.py} (99%) rename gamestonk_terminal/comparison_analysis/{yahoo_finance_api.py => yahoo_finance_view.py} (77%) diff --git a/gamestonk_terminal/comparison_analysis/ca_controller.py b/gamestonk_terminal/comparison_analysis/ca_controller.py index 499b6c9cd39..3772807b71a 100644 --- a/gamestonk_terminal/comparison_analysis/ca_controller.py +++ b/gamestonk_terminal/comparison_analysis/ca_controller.py @@ -2,23 +2,24 @@ __docformat__ = "numpy" import argparse -import requests import random from typing import List from datetime import datetime +import requests import pandas as pd from matplotlib import pyplot as plt +from finvizfinance.screener.overview import Overview +from prompt_toolkit.completion import NestedCompleter + from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal import config_terminal as cfg -from finvizfinance.screener.overview import Overview from gamestonk_terminal.helper_funcs import get_flair, parse_known_args_and_warn -from gamestonk_terminal.comparison_analysis import yahoo_finance_api as yf_api -from gamestonk_terminal.comparison_analysis import market_watch_api as mw_api -from gamestonk_terminal.comparison_analysis import finbrain_api as f_api +from gamestonk_terminal.comparison_analysis import yahoo_finance_view +from gamestonk_terminal.comparison_analysis import market_watch_view +from gamestonk_terminal.comparison_analysis import finbrain_view from gamestonk_terminal.comparison_analysis import finviz_compare_view from gamestonk_terminal.portfolio_optimization import po_controller from gamestonk_terminal.menu import session -from prompt_toolkit.completion import NestedCompleter class ComparisonAnalysisController: @@ -54,9 +55,23 @@ class ComparisonAnalysisController: start: datetime, interval: str, similar: List[str], - user: bool, ): - """Constructor""" + """Constructor + + Parameters + ---------- + stock : pd.DataFrame + Stock data + ticker : str + Stock ticker + start : datetime + Start time + interval : str + Time interval + similar : List[str] + List of similar tickers + """ + self.similar = similar self.user = "" self.stock = stock @@ -69,7 +84,6 @@ class ComparisonAnalysisController: choices=self.CHOICES, ) - @staticmethod def print_help(self): """Print help""" @@ -108,14 +122,21 @@ class ComparisonAnalysisController: print(" performance brief performance comparison") print(" technical brief technical comparison") print("") + if self.similar: print(" > po portfolio optimization for selected tickers") print("") return - @staticmethod def get_similar_companies(self, other_args: List[str]): - """ Get similar companies. [Source: Polygon API] """ + """Get similar companies. [Source: Polygon API] + + Parameters + ---------- + other_args : List[str] + argparse other args + """ + parser = argparse.ArgumentParser( add_help=False, prog="get", @@ -189,9 +210,15 @@ class ComparisonAnalysisController: print("") return - @staticmethod def select_similar_companies(self, other_args: List[str]): - """ Select similar companies, e.g. NIO,XPEV,LI""" + """Select similar companies, e.g. NIO,XPEV,LI + + Parameters + ---------- + other_args : List[str] + argparse other args + """ + parser = argparse.ArgumentParser( add_help=False, prog="select", @@ -242,7 +269,7 @@ class ComparisonAnalysisController: def call_help(self, _): """Process Help command""" - self.print_help(self) + self.print_help() def call_q(self, _): """Process Q command - quit the menu""" @@ -254,43 +281,43 @@ class ComparisonAnalysisController: def call_get(self, other_args: List[str]): """Process get command""" - self.get_similar_companies(self, other_args) + self.get_similar_companies(other_args) def call_select(self, other_args: List[str]): """Process select command""" - self.select_similar_companies(self, other_args) + self.select_similar_companies(other_args) def call_historical(self, other_args: List[str]): """Process historical command""" - yf_api.historical( + yahoo_finance_view.historical( other_args, self.stock, self.ticker, self.start, self.interval, self.similar ) def call_hcorr(self, other_args: List[str]): """Process historical correlation command""" - yf_api.correlation( + yahoo_finance_view.correlation( other_args, self.stock, self.ticker, self.start, self.interval, self.similar ) def call_income(self, other_args: List[str]): """Process income command""" - mw_api.compare_income(other_args, self.ticker, self.similar) + market_watch_view.compare_income(other_args, self.ticker, self.similar) def call_balance(self, other_args: List[str]): """Process balance command""" - mw_api.compare_balance(other_args, self.ticker, self.similar) + market_watch_view.compare_balance(other_args, self.ticker, self.similar) def call_cashflow(self, other_args: List[str]): """Process cashflow command""" - mw_api.compare_cashflow(other_args, self.ticker, self.similar) + market_watch_view.compare_cashflow(other_args, self.ticker, self.similar) def call_sentiment(self, other_args: List[str]): """Process sentiment command""" - f_api.sentiment_compare(other_args, self.ticker, self.similar) + finbrain_view.sentiment_compare(other_args, self.ticker, self.similar) def call_scorr(self, other_args: List[str]): """Process sentiment correlation command""" - f_api.sentiment_correlation(other_args, self.ticker, self.similar) + finbrain_view.sentiment_correlation(other_args, self.ticker, self.similar) def call_overview(self, other_args: List[str]): """Process overview command""" @@ -324,11 +351,21 @@ class ComparisonAnalysisController: def menu(stock: pd.DataFrame, ticker: str, start: datetime, interval: str): - """Comparison Analysis Menu""" + """Comparison Analysis Menu - ca_controller = ComparisonAnalysisController( - stock, ticker, start, interval, [], False - ) + Parameters + ---------- + stock : pd.DataFrame + Stock data + ticker : str + Stock ticker + start : datetime + Time start + interval : str + Time interval + """ + + ca_controller = ComparisonAnalysisController(stock, ticker, start, interval, []) ca_controller.call_help(None) while True: diff --git a/gamestonk_terminal/comparison_analysis/finbrain_api.py b/gamestonk_terminal/comparison_analysis/finbrain_view.py similarity index 99% rename from gamestonk_terminal/comparison_analysis/finbrain_api.py rename to gamestonk_terminal/comparison_analysis/finbrain_view.py index c1cb629d893..cc0ee139d64 100644 --- a/gamestonk_terminal/comparison_analysis/finbrain_api.py +++ b/gamestonk_terminal/comparison_analysis/finbrain_view.py @@ -10,6 +10,7 @@ import pandas as pd from pandas.plotting import register_matplotlib_converters import numpy as np import seaborn as sns + from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, plot_autoscale, @@ -33,6 +34,7 @@ def sentiment_compare(other_args: List[str], ticker: str, similar: List[str]): similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="sentiment_compare", @@ -98,6 +100,7 @@ def sentiment_correlation(other_args: List[str], ticker: str, similar: List[str] similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="sentiment_compare", @@ -164,6 +167,7 @@ def get_sentiments(similar: List[str]) -> pd.DataFrame: DataFrame() Contains sentiment analysis from several tickers """ + df_sentiment = pd.DataFrame() for ticker in similar: result = requests.get(f"https://api.finbrain.tech/v0/sentiments/{ticker}") @@ -196,6 +200,7 @@ def plot_sentiments(df_sentiment: pd.DataFrame, similar: List[str]): similar : List[str] List of similar companies """ + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) for idx, ticker in enumerate(similar): @@ -251,6 +256,7 @@ def plot_correlation(df_sentiment: pd.DataFrame, similar: List[str]): similar : List[str] List of similar companies """ + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) mask = np.zeros((len(similar), len(similar)), dtype=bool) diff --git a/gamestonk_terminal/comparison_analysis/market_watch_api.py b/gamestonk_terminal/comparison_analysis/market_watch_view.py similarity index 99% rename from gamestonk_terminal/comparison_analysis/market_watch_api.py rename to gamestonk_terminal/comparison_analysis/market_watch_view.py index 5067cdeae38..4cef54e2b79 100644 --- a/gamestonk_terminal/comparison_analysis/market_watch_api.py +++ b/gamestonk_terminal/comparison_analysis/market_watch_view.py @@ -27,6 +27,7 @@ def compare_income(other_args: List[str], ticker: str, similar: List[str]): similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="income", @@ -132,6 +133,7 @@ def compare_balance(other_args: List[str], ticker: str, similar: List[str]): similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="compare_balance", @@ -237,6 +239,7 @@ def compare_cashflow(other_args: List[str], ticker: str, similar: List[str]): similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="compare_cashflow", diff --git a/gamestonk_terminal/comparison_analysis/yahoo_finance_api.py b/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py similarity index 77% rename from gamestonk_terminal/comparison_analysis/yahoo_finance_api.py rename to gamestonk_terminal/comparison_analysis/yahoo_finance_view.py index 72df9f825ad..095a506b4f6 100644 --- a/gamestonk_terminal/comparison_analysis/yahoo_finance_api.py +++ b/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py @@ -1,4 +1,9 @@ +""" Comparison Analysis Yahoo Finance View """ +__docformat__ = "numpy" + import argparse +from typing import List +from datetime import datetime import numpy as np import pandas as pd from pandas.plotting import register_matplotlib_converters @@ -21,6 +26,24 @@ d_candle_types = { def check_one_of_ohlca(type_candles: str) -> str: + """Convert a candle type + + Parameters + ---------- + type_candles : str + OHLCA candle type + + Returns + ------- + str + Converted candle type + + Raises + ------ + argparse.ArgumentTypeError + Unknown candle type + """ + if ( type_candles == "o" or type_candles == "h" @@ -32,7 +55,32 @@ def check_one_of_ohlca(type_candles: str) -> str: raise argparse.ArgumentTypeError("The type of candles specified is not recognized") -def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): +def historical( + other_args: List[str], + df_stock: pd.DataFrame, + ticker: str, + start: datetime, + interval: str, + similar: List[str], +): + """Display historical data from Yahoo Finance + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + df_stock : pd.DataFrame + Stock data + ticker : str + Ticker symbol + start : datetime + Time start + interval : str + Time interval + similar : List[str] + List of similar tickers + """ + parser = argparse.ArgumentParser( add_help=False, prog="historical", @@ -66,11 +114,11 @@ def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): ) try: - if s_interval != "1440min": + if interval != "1440min": print("Intraday historical data analysis comparison is not yet available.") # Alpha Vantage only supports 5 calls per minute, we need another API to get intraday data else: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -80,16 +128,14 @@ def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): similar += ns_parser.l_also plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) - plt.title(f"Similar companies to {s_ticker}") - df_stock = yf.download( - s_ticker, start=s_start, progress=False, threads=False - ) + plt.title(f"Similar companies to {ticker}") + df_stock = yf.download(ticker, start=start, progress=False, threads=False) plt.plot( df_stock.index, df_stock[d_candle_types[ns_parser.type_candle]].values ) # plt.plot(df_stock.index, df_stock["5. adjusted close"].values, lw=2) l_min = [df_stock.index[0]] - l_leg = [s_ticker] + l_leg = [ticker] l_stocks = similar[:] @@ -98,7 +144,7 @@ def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): for symbol in l_stocks: try: df_similar_stock = yf.download( - symbol, start=s_start, progress=False, threads=False + symbol, start=start, progress=False, threads=False ) if not df_similar_stock.empty: plt.plot( @@ -141,7 +187,25 @@ def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): print(e, "\n") -def correlation(l_args, df_stock, s_ticker, s_start, s_interval, similar): +def correlation(other_args, df_stock, ticker, start, interval, similar): + """[summary] + + Parameters + ---------- + other_args : [type] + Command line arguments to be processed with argparse + df_stock : pd.DataFrame + Stock data + ticker : str + Ticker symbol + start : datetime + Time start + interval : str + Time interval + similar : [type] + List of similar tickers + """ + parser = argparse.ArgumentParser( add_help=False, prog="corr", @@ -176,11 +240,11 @@ def correlation(l_args, df_stock, s_ticker, s_start, s_interval, similar): ) try: - if s_interval != "1440min": + if interval != "1440min": print("Intraday historical data analysis comparison is not yet available.") # Alpha Vantage only supports 5 calls per minute, we need another API to get intraday data else: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -193,21 +257,21 @@ def correlation(l_args, df_stock, s_ticker, s_start, s_interval, similar): print("Provide at least a similar company for correlation") else: d_stock = {} - d_stock[s_ticker] = yf.download(s_ticker, start=s_start, progress=False) - l_min = [d_stock[s_ticker].index[0]] + d_stock[ticker] = yf.download(ticker, start=start, progress=False) + l_min = [d_stock[ticker].index[0]] for symbol in similar: - d_stock[symbol] = yf.download(symbol, start=s_start, progress=False) + d_stock[symbol] = yf.download(symbol, start=start, progress=False) if not d_stock[symbol].empty: l_min.append(d_stock[symbol].index[0]) min_start_date = max(l_min) - df_stock = d_stock[s_ticker][ + df_stock = d_stock[ticker][ d_candle_types[ns_parser.type_candle] - ].rename(s_ticker) + ].rename(ticker) for symbol in d_stock: - if symbol != s_ticker: + if symbol != ticker: if not d_stock[symbol].empty: df_stock = pd.concat( [ From 7d5a0a1c4a2279e025bfd38e2e053eb5f6634905 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 13:25:51 -0700 Subject: [PATCH 080/114] Adding __init__.py --- gamestonk_terminal/comparison_analysis/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 gamestonk_terminal/comparison_analysis/__init__.py diff --git a/gamestonk_terminal/comparison_analysis/__init__.py b/gamestonk_terminal/comparison_analysis/__init__.py new file mode 100644 index 00000000000..e69de29bb2d From 8d559e4e140454952306011ccb9c8f907ca82135 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 13:37:56 -0700 Subject: [PATCH 081/114] Try a different way to pylint --- .github/workflows/test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e85716d7882..a6e166da0c5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,8 @@ jobs: - run: mypy --ignore-missing-imports . - run: shopt -s globstar && pyupgrade --py36-plus **/*.py - run: safety check - - run: pylint **/*.py + - run: | + find . -name '*.py' -exec pylint {} \; test: name: ubuntu-latest - Python 3.8 needs: linting From 7fbe96ff88c773fc17a7cb68b75958da3773ccb9 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 14:15:45 -0700 Subject: [PATCH 082/114] Updating pylint to actually run --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a6e166da0c5..fceaff60738 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,7 +33,7 @@ jobs: - run: shopt -s globstar && pyupgrade --py36-plus **/*.py - run: safety check - run: | - find . -name '*.py' -exec pylint {} \; + pylint terminal.py gamestonk_terminal tests test: name: ubuntu-latest - Python 3.8 needs: linting From a60ea0b19eda699a0f8c573bd0bfc1e07cc38663 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Apr 2021 17:17:45 -0400 Subject: [PATCH 083/114] minor change --- gamestonk_terminal/options/op_scrape_view.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/gamestonk_terminal/options/op_scrape_view.py b/gamestonk_terminal/options/op_scrape_view.py index 78b07ac8919..40bb5e1e0f9 100644 --- a/gamestonk_terminal/options/op_scrape_view.py +++ b/gamestonk_terminal/options/op_scrape_view.py @@ -47,17 +47,14 @@ def print_options_data(stock: str, other_args: List[str]): dest="browser", help="selenium webdriver to use", choices=browsers, - default=None, + default=web, ) try: ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return + if ns_parser.browser: browser = ns_parser.browser - else: - browser = web except Exception as e: print(e) From 24bc3b8a7d2ef16e9f4ab1668d27245af3f94f0e Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Apr 2021 17:25:48 -0400 Subject: [PATCH 084/114] readme + roadmap --- README.md | 2 +- ROADMAP.md | 4 +++- gamestonk_terminal/README.md | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 16dc46b38f6..a23fb298cbb 100644 --- a/README.md +++ b/README.md @@ -369,7 +369,7 @@ Distributed under the MIT License. See [LICENSE](https://github.com/DidierRLopes [James Maslek](https://www.linkedin.com/in/james-maslek-b6810186/) - jmaslek11@gmail.com -Feel free to share loss porn, memes or any questions at https://discord.gg/cC2KNt4B +Feel free to share loss porn, memes or any questions at https://discord.gg/BsfJk4MQ ## Acknowledgments diff --git a/ROADMAP.md b/ROADMAP.md index d4200888355..ee6fca45d7e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -173,6 +173,7 @@ ___ ## Options * [x] Add Volume graph (@lolrenx) - [PR #209](https://github.com/DidierRLopes/GamestonkTerminal/pull/209) * [x] Add Open Interest graph (@lolrenx) - [PR #209](https://github.com/DidierRLopes/GamestonkTerminal/pull/209) +* [x] Add options information data (IV rank, etc) (@jmaslek) - [PR #375](https://github.com/DidierRLopes/GamestonkTerminal/pull/375) **NEXT** * [ ] Add max pain graph (@lolrenx) @@ -193,7 +194,8 @@ ___ **NEXT** * [ ] Add [Coinpaprika](https://coinpaprika.com/api/) * [ ] Add crypto charts - +* [ ] Add binance +* [ ] Add top altcoin lists --- ## Screener diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index 900af3b3be4..83f8c8b9402 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -344,6 +344,8 @@ Command|Description|Source `volume` | volume + open interest options trading plot |[Yahoo Finance](https://finance.yahoo.com/) `vcalls` | calls volume + open interest plot |[Yahoo Finance](https://finance.yahoo.com/) `vputs` | puts volume + open interest plot |[Yahoo Finance](https://finance.yahoo.com/) +`chains` | displays option chains |[Tradier](https://developer.tradier.com/) +`info` | display option information | [Barchart](https://barchart.com/)   From 407d9d02a781991197d3864877ff49a515fbf014 Mon Sep 17 00:00:00 2001 From: DJ Date: Tue, 20 Apr 2021 17:23:38 -0600 Subject: [PATCH 085/114] Requested changes --- README.md | 2 ++ gamestonk_terminal/config_terminal.py | 2 +- gamestonk_terminal/forex/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7c13cbe50b2..7e6de2c164c 100644 --- a/README.md +++ b/README.md @@ -260,6 +260,8 @@ These are the ones where a key is necessary: * Tradier: https://developer.tradier.com/getting_started * Oanda API: https://developer.oanda.com +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. Example: diff --git a/gamestonk_terminal/config_terminal.py b/gamestonk_terminal/config_terminal.py index 874e1181edc..cc479934ad9 100644 --- a/gamestonk_terminal/config_terminal.py +++ b/gamestonk_terminal/config_terminal.py @@ -36,7 +36,7 @@ API_NEWS_TOKEN = os.getenv("GT_API_NEWS_TOKEN") or "REPLACE_ME" RH_USERNAME = os.getenv("GT_RH_USERNAME") or "REPLACE_ME" RH_PASSWORD = os.getenv("GT_RH_PASSWORD") or "REPLACE_ME" -# Oanda +# https://developer.oanda.com OANDA_ACCOUNT = os.getenv("GT_OANDA_ACCOUNT") or "REPLACE ME" OANDA_TOKEN = os.getenv("GT_OANDA_TOKEN") or "REPLACE ME" diff --git a/gamestonk_terminal/forex/README.md b/gamestonk_terminal/forex/README.md index 079b5fb4d5d..5c27d28a4fd 100644 --- a/gamestonk_terminal/forex/README.md +++ b/gamestonk_terminal/forex/README.md @@ -29,7 +29,7 @@ This menu utilizes oanda to enable support for trading forex. * [orderbook](#orderbook) * Display the orderbook if Oanda provides one for the forex instrument * [positionbook](#positionbook) - * Display the positionbook if Oanda provides one for the forex instrument + * Display the positionbook if Oanda provides one for the forex instrument ## summary ```text @@ -38,7 +38,7 @@ This menu utilizes oanda to enable support for trading forex. Displays current balance, net asset value, unrealized P/L, total P/L, count of open trades, how much margin is available, how much margin you've used, the margin call value, the percent of margin until closeout, and the total position value. -## calendar +## calendar ```text usage: calendar [-d DAYS] From 58663fb7ab42763a17a9bf17511361cf11c97351 Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Apr 2021 20:05:52 -0400 Subject: [PATCH 086/114] updated permanent discord link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a23fb298cbb..d3d2f8966fb 100644 --- a/README.md +++ b/README.md @@ -369,7 +369,7 @@ Distributed under the MIT License. See [LICENSE](https://github.com/DidierRLopes [James Maslek](https://www.linkedin.com/in/james-maslek-b6810186/) - jmaslek11@gmail.com -Feel free to share loss porn, memes or any questions at https://discord.gg/BsfJk4MQ +Feel free to share loss porn, memes or any questions at https://discord.gg/Up2QGbMKHY ## Acknowledgments From fa282b2ce413214e6ff46904a76b48e3eec39e67 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 22:25:29 -0700 Subject: [PATCH 087/114] Fixing pylint errors and warnings --- .pylintrc | 6 +- .../behavioural_analysis/ba_controller.py | 2 +- .../behavioural_analysis/finbrain_view.py | 3 +- .../behavioural_analysis/reddit_view.py | 22 ----- .../comparison_analysis/yahoo_finance_view.py | 9 +- gamestonk_terminal/discovery/finviz_view.py | 15 ++- .../discovery/marketbeat_view.py | 4 +- .../discovery/seeking_alpha_model.py | 4 +- .../discovery/seeking_alpha_view.py | 2 +- .../due_diligence/finra_view.py | 3 +- .../portfolio/port_controller.py | 7 +- .../optimizer_helper.py | 23 +++-- .../portfolio_optimization/optimizer_view.py | 99 +++++++++---------- .../portfolio_optimization/po_controller.py | 9 +- .../prediction_techniques/ets.py | 12 +-- .../prediction_techniques/neural_networks.py | 21 ---- .../prediction_techniques/pred_controller.py | 9 +- .../prediction_techniques/pred_helper.py | 3 +- .../technical_analysis/finviz_view.py | 3 +- .../technical_analysis/overlap.py | 2 +- .../technical_analysis/ta_controller.py | 10 +- .../technical_analysis/tradingview_view.py | 3 +- terminal.py | 14 +-- 23 files changed, 119 insertions(+), 166 deletions(-) diff --git a/.pylintrc b/.pylintrc index ceaa81904dc..c8806cea49c 100644 --- a/.pylintrc +++ b/.pylintrc @@ -54,7 +54,7 @@ confidence= # disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call # disable=too-many-instance-attributes,len-as-condition,too-few-public-methods,anomalous-backslash-in-string,no-else-return,simplifiable-if-statement,too-many-arguments,duplicate-code,no-name-in-module,no-member,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,missing-docstring,invalid-name,bad-whitespace,consider-using-enumerate,unexpected-keyword-arg -disable=useless-return,missing-docstring,invalid-name,import-error,bad-continuation,broad-except,unnecessary-lambda,no-self-use,duplicate-code,consider-using-generator +disable=useless-return,missing-docstring,invalid-name,import-error,bad-continuation,broad-except,unnecessary-lambda,no-self-use,duplicate-code,consider-using-generator,unbalanced-tuple-unpacking # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option @@ -397,7 +397,7 @@ valid-metaclass-classmethod-first-arg=mcs [DESIGN] # Maximum number of arguments for function / method -max-args=5 +max-args=8 # Maximum number of attributes for a class (see R0902). # max-attributes=7 @@ -416,7 +416,7 @@ max-locals=40 max-parents=7 # Maximum number of public methods for a class (see R0904). -max-public-methods=20 +max-public-methods=30 # Maximum number of return / yield for function / method body max-returns=9 diff --git a/gamestonk_terminal/behavioural_analysis/ba_controller.py b/gamestonk_terminal/behavioural_analysis/ba_controller.py index 57e9a66cbe6..e8ae8f60aee 100644 --- a/gamestonk_terminal/behavioural_analysis/ba_controller.py +++ b/gamestonk_terminal/behavioural_analysis/ba_controller.py @@ -4,6 +4,7 @@ __docformat__ = "numpy" import argparse from typing import List from datetime import datetime +from prompt_toolkit.completion import NestedCompleter from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import get_flair @@ -14,7 +15,6 @@ from gamestonk_terminal.behavioural_analysis import ( stocktwits_view, finbrain_view, ) -from prompt_toolkit.completion import NestedCompleter class BehaviouralAnalysisController: diff --git a/gamestonk_terminal/behavioural_analysis/finbrain_view.py b/gamestonk_terminal/behavioural_analysis/finbrain_view.py index 090327aff73..e5d1907e485 100644 --- a/gamestonk_terminal/behavioural_analysis/finbrain_view.py +++ b/gamestonk_terminal/behavioural_analysis/finbrain_view.py @@ -9,13 +9,14 @@ import matplotlib.dates as mdates import pandas as pd from pandas.plotting import register_matplotlib_converters import numpy as np +from colorama import Fore, Style + from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, plot_autoscale, ) from gamestonk_terminal.config_plot import PLOT_DPI from gamestonk_terminal import feature_flags as gtff -from colorama import Fore, Style register_matplotlib_converters() diff --git a/gamestonk_terminal/behavioural_analysis/reddit_view.py b/gamestonk_terminal/behavioural_analysis/reddit_view.py index fdf6b1396d1..231f1728276 100644 --- a/gamestonk_terminal/behavioural_analysis/reddit_view.py +++ b/gamestonk_terminal/behavioural_analysis/reddit_view.py @@ -189,17 +189,6 @@ def popular_tickers(l_args): wallstreetbets """, ) - """ - parser.add_argument( - "-d", - "--days", - action="store", - dest="n_days", - type=check_positive, - default=1, - help="look for the tickers from those n past days.", - ) - """ try: ns_parser = parse_known_args_and_warn(parser, l_args) @@ -502,17 +491,6 @@ def spac(l_args): default=5, help="limit of posts with SPACs retrieved.", ) - """ - parser.add_argument( - "-d", - "--days", - action="store", - dest="n_days", - type=check_positive, - default=5, - help="look for the tickers from those n past days.", - ) - """ try: ns_parser = parse_known_args_and_warn(parser, l_args) diff --git a/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py b/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py index 095a506b4f6..d2552845e61 100644 --- a/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py +++ b/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py @@ -44,14 +44,9 @@ def check_one_of_ohlca(type_candles: str) -> str: Unknown candle type """ - if ( - type_candles == "o" - or type_candles == "h" - or type_candles == "l" - or type_candles == "c" - or type_candles == "a" - ): + if type_candles in ("o", "h", "l", "c", "a"): return type_candles + raise argparse.ArgumentTypeError("The type of candles specified is not recognized") diff --git a/gamestonk_terminal/discovery/finviz_view.py b/gamestonk_terminal/discovery/finviz_view.py index 3bd3e06e8f6..284779960c4 100644 --- a/gamestonk_terminal/discovery/finviz_view.py +++ b/gamestonk_terminal/discovery/finviz_view.py @@ -4,10 +4,11 @@ __docformat__ = "numpy" import argparse from typing import List import webbrowser -from gamestonk_terminal.helper_funcs import parse_known_args_and_warn from finvizfinance.group import valuation, performance, spectrum from PIL import Image +from gamestonk_terminal.helper_funcs import parse_known_args_and_warn + l_GROUPS = [ "Sector", "Industry", @@ -97,6 +98,7 @@ def get_valuation_performance_data(group: str, data_type: str): pd.DataFrame dataframe with valuation/performance data """ + if data_type == "valuation": df_group = valuation.Valuation().ScreenerView(group=group) elif data_type == "performance": @@ -117,6 +119,7 @@ def get_spectrum_data(group: str): data_type : str select data type to see data between valuation or performance """ + spectrum.Spectrum().ScreenerView(group=group) @@ -130,6 +133,7 @@ def view_group_data(other_args: List[str], data_type: str): data_type : str select data type to see data between valuation, performance and spectrum """ + parser = argparse.ArgumentParser( add_help=False, prog="group_data", @@ -156,12 +160,12 @@ def view_group_data(other_args: List[str], data_type: str): ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return + return None if isinstance(ns_parser.group, List): ns_parser.group = ns_parser.group[0] - if data_type == "valuation" or data_type == "performance": + if data_type in ("valuation", "performance"): df_group = get_valuation_performance_data(ns_parser.group, data_type) print(df_group.to_string()) @@ -172,7 +176,7 @@ def view_group_data(other_args: List[str], data_type: str): img.show() print("") - return ns_parser.group + return img else: print( @@ -180,7 +184,8 @@ def view_group_data(other_args: List[str], data_type: str): ) print("") - return "" + return None except SystemExit: print("") + return None diff --git a/gamestonk_terminal/discovery/marketbeat_view.py b/gamestonk_terminal/discovery/marketbeat_view.py index 13ec048ee5c..c2f3c58007d 100644 --- a/gamestonk_terminal/discovery/marketbeat_view.py +++ b/gamestonk_terminal/discovery/marketbeat_view.py @@ -2,14 +2,14 @@ __docformat__ = "numpy" import argparse +from typing import List import numpy as np import pandas as pd -from typing import List + from gamestonk_terminal.helper_funcs import ( check_positive, parse_known_args_and_warn, ) - from gamestonk_terminal.discovery import marketbeat_model diff --git a/gamestonk_terminal/discovery/seeking_alpha_model.py b/gamestonk_terminal/discovery/seeking_alpha_model.py index 6041eb63f67..1a2df5f03a3 100644 --- a/gamestonk_terminal/discovery/seeking_alpha_model.py +++ b/gamestonk_terminal/discovery/seeking_alpha_model.py @@ -2,11 +2,11 @@ __docformat__ = "numpy" from typing import List +from datetime import datetime import requests from bs4 import BeautifulSoup import pandas as pd from pandas.core.frame import DataFrame -from datetime import datetime from gamestonk_terminal.helper_funcs import get_user_agent @@ -180,7 +180,7 @@ def get_trending_list(num: int) -> list: } ) - return articles + return articles[:num] def get_article_data(article_id: int) -> dict: diff --git a/gamestonk_terminal/discovery/seeking_alpha_view.py b/gamestonk_terminal/discovery/seeking_alpha_view.py index 1670cc3e084..ee65fae29d5 100644 --- a/gamestonk_terminal/discovery/seeking_alpha_view.py +++ b/gamestonk_terminal/discovery/seeking_alpha_view.py @@ -3,8 +3,8 @@ __docformat__ = "numpy" import argparse from typing import List -import pandas as pd from datetime import datetime +import pandas as pd from gamestonk_terminal.helper_funcs import ( check_positive, parse_known_args_and_warn, diff --git a/gamestonk_terminal/due_diligence/finra_view.py b/gamestonk_terminal/due_diligence/finra_view.py index baa7884dcea..8182e376cb1 100644 --- a/gamestonk_terminal/due_diligence/finra_view.py +++ b/gamestonk_terminal/due_diligence/finra_view.py @@ -200,7 +200,8 @@ def plot_dark_pools(ticker: str, ats: pd.DataFrame, otc: pd.DataFrame): otc : pd.DataFrame OTC (Non-ATS) Data """ - _, axData = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + + _, _ = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) plt.subplot(3, 1, (1, 2)) if not ats.empty and not otc.empty: diff --git a/gamestonk_terminal/portfolio/port_controller.py b/gamestonk_terminal/portfolio/port_controller.py index d6d5265789e..e9d6b0c1fea 100644 --- a/gamestonk_terminal/portfolio/port_controller.py +++ b/gamestonk_terminal/portfolio/port_controller.py @@ -4,6 +4,7 @@ import argparse from typing import List import pandas as pd 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 @@ -15,6 +16,7 @@ from gamestonk_terminal.portfolio.portfolio_helpers import ( class PortfolioController: + """ Portfolio Controller """ CHOICES = [ "help", @@ -129,6 +131,7 @@ class PortfolioController: if broker in self.BROKERS: api = broker + "_api" try: + # pylint: disable=eval-used eval(api + ".login()") self.broker_list.add(broker) logged_in = True @@ -179,7 +182,9 @@ class PortfolioController: print("Login to desired brokers\n") for broker in self.broker_list: holdings = pd.concat( - [holdings, eval(broker + "_api.return_holdings()")], axis=0 + # pylint: disable=eval-used + [holdings, eval(broker + "_api.return_holdings()")], + axis=0, ) self.merged_holdings = merge_portfolios(holdings) print_portfolio(self.merged_holdings) diff --git a/gamestonk_terminal/portfolio_optimization/optimizer_helper.py b/gamestonk_terminal/portfolio_optimization/optimizer_helper.py index f88ad80463c..8236d01b789 100644 --- a/gamestonk_terminal/portfolio_optimization/optimizer_helper.py +++ b/gamestonk_terminal/portfolio_optimization/optimizer_helper.py @@ -1,4 +1,4 @@ -""" Portfolio Optimization Helper Functions""" +""" Portfolio Optimization Helper Functions """ __docformat__ = "numpy" import argparse @@ -110,12 +110,12 @@ l_valid_property_infos = [ ] -def check_valid_property_type(property: str) -> str: +def check_valid_property_type(aproperty: str) -> str: """ Check that the property selected is valid """ - if property in l_valid_property_infos: - return property - else: - raise argparse.ArgumentTypeError(f"{property} is not a valid info") + if aproperty in l_valid_property_infos: + return aproperty + + raise argparse.ArgumentTypeError(f"{aproperty} is not a valid info") def process_stocks(list_of_stocks: List[str], period: str = "3mo") -> pd.DataFrame: @@ -133,6 +133,7 @@ def process_stocks(list_of_stocks: List[str], period: str = "3mo") -> pd.DataFra stock_closes: DataFrame DataFrame containing daily (adjusted) close prices for each stock in list """ + stock_prices = yf.download( list_of_stocks, period=period, progress=False, group_by="ticker" ) @@ -155,6 +156,7 @@ def prepare_efficient_frontier(stock_prices: pd.DataFrame): ef: EfficientFrontier EfficientFrontier object """ + mu = expected_returns.mean_historical_return(stock_prices) S = risk_models.sample_cov(stock_prices) ef = EfficientFrontier(mu, S) @@ -162,13 +164,14 @@ def prepare_efficient_frontier(stock_prices: pd.DataFrame): def display_weights(weights: dict): - """ - Print weights in a nice format + """Print weights in a nice format + Parameters ---------- weights: dict weights to display. Keys are stocks. Values are either weights or values if -v specified """ + if not weights: return weight_df = pd.DataFrame.from_dict(data=weights, orient="index", columns=["value"]) @@ -185,8 +188,8 @@ def my_autopct(x): """Function for autopct of plt.pie. This results in values not being printed in the pie if they are 'too small'""" if x > 4: return f"{x:.2f} %" - else: - return "" + + return "" def pie_chart_weights(weights: dict, title_opt: str): diff --git a/gamestonk_terminal/portfolio_optimization/optimizer_view.py b/gamestonk_terminal/portfolio_optimization/optimizer_view.py index 6c61666d5bf..884bea7c578 100644 --- a/gamestonk_terminal/portfolio_optimization/optimizer_view.py +++ b/gamestonk_terminal/portfolio_optimization/optimizer_view.py @@ -122,12 +122,8 @@ def property_weighting(stocks: List[str], other_args: List[str]): List of tickers to be included in optimization other_args : List[str] Command line arguments to be processed with argparse - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers """ + parser = argparse.ArgumentParser( add_help=False, prog="property", @@ -136,7 +132,7 @@ def property_weighting(stocks: List[str], other_args: List[str]): parser.add_argument( "-p", "--property", - required=True if "-h" not in other_args else False, + required=bool("-h" not in other_args), type=check_valid_property_type, dest="property", help="""Property info to weigh. Use one of: @@ -217,19 +213,16 @@ def property_weighting(stocks: List[str], other_args: List[str]): def max_sharpe(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that maximises the Sharpe Ratio + """Return a portfolio that maximises the Sharpe Ratio Parameters ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="maxsharpe", description="Maximise the Sharpe Ratio" ) @@ -273,7 +266,7 @@ def max_sharpe(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -309,19 +302,16 @@ def max_sharpe(stocks: List[str], other_args: List[str]): def min_volatility(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that optimizes for minimum volatility + """Return a portfolio that optimizes for minimum volatility Parameters ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="min_volatility", @@ -354,7 +344,7 @@ def min_volatility(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -390,19 +380,16 @@ def min_volatility(stocks: List[str], other_args: List[str]): def max_quadratic_utility(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that maximises the quadratic utility, given some risk aversion + """Return a portfolio that maximises the quadratic utility, given some risk aversion Parameters ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="max_quadratic_utility", @@ -458,7 +445,7 @@ def max_quadratic_utility(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -499,20 +486,15 @@ def max_quadratic_utility(stocks: List[str], other_args: List[str]): def efficient_risk(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that maximises return for a target risk. The resulting portfolio will have - a volatility less than the target (but not guaranteed to be equal) + """Return a portfolio that maximises return for a target risk. The resulting portfolio will have + a volatility less than the target (but not guaranteed to be equal) - Parameters - ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="effrisk", @@ -568,7 +550,7 @@ def efficient_risk(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -609,19 +591,16 @@ def efficient_risk(stocks: List[str], other_args: List[str]): def efficient_return(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that minimises volatility for a given target return ('Markowitz portfolio') + """Displays a portfolio that minimises volatility for a given target return ('Markowitz portfolio') Parameters ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="effret", @@ -676,7 +655,7 @@ def efficient_return(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -717,6 +696,16 @@ def efficient_return(stocks: List[str], other_args: List[str]): def show_ef(stocks: List[str], other_args: List[str]): + """Display efficient frontier + + Parameters + ---------- + stocks : List[str] + List of the stocks to be included in the weights + other_args : List[str] + argparse other args + """ + parser = argparse.ArgumentParser( add_help=False, prog="ef", @@ -756,7 +745,7 @@ def show_ef(stocks: List[str], other_args: List[str]): mu = expected_returns.mean_historical_return(stock_prices) S = risk_models.sample_cov(stock_prices) ef = EfficientFrontier(mu, S) - fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) # Generate random portfolios n_samples = ns_parser.n_port diff --git a/gamestonk_terminal/portfolio_optimization/po_controller.py b/gamestonk_terminal/portfolio_optimization/po_controller.py index c66ca63e846..c4345e8b386 100644 --- a/gamestonk_terminal/portfolio_optimization/po_controller.py +++ b/gamestonk_terminal/portfolio_optimization/po_controller.py @@ -1,7 +1,6 @@ -"""Portfolio Optimization Controller Module""" +""" Portfolio Optimization Controller Module """ __docformat__ = "numpy" - import argparse from typing import List import matplotlib.pyplot as plt @@ -34,6 +33,7 @@ class PortfolioOptimization: "yolo", ] + # pylint: disable=dangerous-default-value def __init__(self, tickers: List[str] = []): """ Construct Portfolio Optimization @@ -113,12 +113,12 @@ class PortfolioOptimization: def call_add(self, other_args: List[str]): """Process add command""" - self.add_stocks(self, other_args) + self.add_stocks(other_args) def call_select(self, other_args: List[str]): """Process select command""" self.tickers = [] - self.add_stocks(self, other_args) + self.add_stocks(other_args) def call_equal(self, other_args: List[str]): """Process equal command""" @@ -168,7 +168,6 @@ class PortfolioOptimization: print({"GME": 200}) print("") - @staticmethod def add_stocks(self, other_args: List[str]): """ Add ticker or Select tickes for portfolio to be optimized """ parser = argparse.ArgumentParser( diff --git a/gamestonk_terminal/prediction_techniques/ets.py b/gamestonk_terminal/prediction_techniques/ets.py index 96e17306d78..c26e6f28a5a 100644 --- a/gamestonk_terminal/prediction_techniques/ets.py +++ b/gamestonk_terminal/prediction_techniques/ets.py @@ -5,6 +5,7 @@ import numpy as np import pandas as pd from pandas.plotting import register_matplotlib_converters from statsmodels.tsa.holtwinters import ExponentialSmoothing + from gamestonk_terminal.helper_funcs import ( check_positive, parse_known_args_and_warn, @@ -18,19 +19,18 @@ from gamestonk_terminal.prediction_techniques.pred_helper import ( price_prediction_backtesting_color, print_prediction_kpis, ) - from gamestonk_terminal.config_plot import PLOT_DPI from gamestonk_terminal import feature_flags as gtff register_matplotlib_converters() -trend = "Ad" # Additive damped, A Additive, N None -seasonal = "N" # None, A Additive, M Multiplicative -seasonal_periods = 5 +# trend = "Ad" # Additive damped, A Additive, N None +# seasonal = "N" # None, A Additive, M Multiplicative +# seasonal_periods = 5 def check_valid_trend(trend: str) -> str: - if trend == "N" or trend == "A" or trend == "Ad": + if trend in ("N", "A", "Ad"): return trend raise argparse.ArgumentTypeError( "Invalid trend selected. Choose between 'N', 'A', and 'Ad'" @@ -38,7 +38,7 @@ def check_valid_trend(trend: str) -> str: def check_valid_seasonal(seasonal: str) -> str: - if seasonal == "N" or seasonal == "A" or seasonal == "M": + if seasonal in ("N", "A", "M"): return seasonal raise argparse.ArgumentTypeError( "Invalid seasonal selected. Choose between 'N', 'A', and 'M'" diff --git a/gamestonk_terminal/prediction_techniques/neural_networks.py b/gamestonk_terminal/prediction_techniques/neural_networks.py index 2e7d63e5db6..d0489619576 100644 --- a/gamestonk_terminal/prediction_techniques/neural_networks.py +++ b/gamestonk_terminal/prediction_techniques/neural_networks.py @@ -408,27 +408,6 @@ def _plot_and_print_results( ) plt.plot(df_pred.index, df_pred[df_pred.columns[0]], lw=2, c="tab:green") else: - """ - # Looks too noisy to output all loops predictions - for idx_loop in range(ns_parser.n_loops): - plt.plot( - [df_stock.index[-1], df_pred.index[0]], - [ - df_stock["5. adjusted close"].values[-1], - df_pred[df_pred.columns[idx_loop]].values[0], - ], - lw=0.5, - c="tab:green", - linestyle="--", - ) - plt.plot( - df_pred.index, - df_pred[df_pred.columns[idx_loop]], - lw=1, - ls="--", - c="tab:green", - ) - """ df_quantiles = pd.DataFrame() df_quantiles["Quantile 10%"] = df_pred.quantile(0.1, axis=1) df_quantiles["Median"] = df_pred.quantile(0.5, axis=1) diff --git a/gamestonk_terminal/prediction_techniques/pred_controller.py b/gamestonk_terminal/prediction_techniques/pred_controller.py index 8d2bdb4b2be..2ca6c8e6443 100644 --- a/gamestonk_terminal/prediction_techniques/pred_controller.py +++ b/gamestonk_terminal/prediction_techniques/pred_controller.py @@ -1,8 +1,10 @@ import argparse from typing import List -import pandas as pd from datetime import datetime +import pandas as pd import matplotlib.pyplot as plt +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 @@ -14,7 +16,6 @@ from gamestonk_terminal.prediction_techniques import ( regression, sma, ) -from prompt_toolkit.completion import NestedCompleter class PredictionTechniquesController: @@ -59,7 +60,6 @@ class PredictionTechniquesController: choices=self.CHOICES, ) - @staticmethod def print_help(self): """ Print help """ @@ -110,7 +110,7 @@ class PredictionTechniquesController: def call_help(self, _): """Process Help command""" - self.print_help(self) + self.print_help() def call_q(self, _): """Process Q command - quit the menu""" @@ -170,6 +170,7 @@ class PredictionTechniquesController: def call_prophet(self, other_args: List[str]): """Process prophet command""" + # pylint: disable=import-outside-toplevel from gamestonk_terminal.prediction_techniques import fbprophet fbprophet.fbprophet(other_args, self.ticker, self.stock) diff --git a/gamestonk_terminal/prediction_techniques/pred_helper.py b/gamestonk_terminal/prediction_techniques/pred_helper.py index 43aba435f39..c69ac5f0616 100644 --- a/gamestonk_terminal/prediction_techniques/pred_helper.py +++ b/gamestonk_terminal/prediction_techniques/pred_helper.py @@ -1,13 +1,14 @@ import numpy as np import pandas as pd from colorama import Fore, Style -from gamestonk_terminal import feature_flags as gtff from sklearn.metrics import ( mean_absolute_error, r2_score, mean_squared_error, ) +from gamestonk_terminal import feature_flags as gtff + def price_prediction_color(val: float, last_val: float) -> str: if float(val) > last_val: diff --git a/gamestonk_terminal/technical_analysis/finviz_view.py b/gamestonk_terminal/technical_analysis/finviz_view.py index 0fc3f794356..1e74144ca48 100644 --- a/gamestonk_terminal/technical_analysis/finviz_view.py +++ b/gamestonk_terminal/technical_analysis/finviz_view.py @@ -3,10 +3,11 @@ __docformat__ = "numpy" import argparse from typing import List -from gamestonk_terminal.helper_funcs import parse_known_args_and_warn from finvizfinance.quote import finvizfinance from PIL import Image +from gamestonk_terminal.helper_funcs import parse_known_args_and_warn + def view(other_args: List[str], ticker: str): """View historical price with trendlines. [Source: Finviz] diff --git a/gamestonk_terminal/technical_analysis/overlap.py b/gamestonk_terminal/technical_analysis/overlap.py index 7509c0ce2f3..a6c4b5d971a 100644 --- a/gamestonk_terminal/technical_analysis/overlap.py +++ b/gamestonk_terminal/technical_analysis/overlap.py @@ -69,7 +69,7 @@ def ema(l_args, s_ticker, s_interval, df_stock): offset=ns_parser.n_offset, ).dropna() - _, axPrice = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + _, _ = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) plt.title(f"{ns_parser.n_length} EMA on {s_ticker}") if s_interval == "1440min": plt.plot( diff --git a/gamestonk_terminal/technical_analysis/ta_controller.py b/gamestonk_terminal/technical_analysis/ta_controller.py index 7362b2edb26..620e13ab55f 100644 --- a/gamestonk_terminal/technical_analysis/ta_controller.py +++ b/gamestonk_terminal/technical_analysis/ta_controller.py @@ -3,10 +3,12 @@ __docformat__ = "numpy" import argparse import os -import pandas as pd from typing import List from datetime import datetime +import pandas as pd import matplotlib.pyplot as plt +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 @@ -18,7 +20,6 @@ from gamestonk_terminal.technical_analysis import volume as ta_volume from gamestonk_terminal.technical_analysis import finbrain_view from gamestonk_terminal.technical_analysis import tradingview_view from gamestonk_terminal.technical_analysis import finviz_view -from prompt_toolkit.completion import NestedCompleter class TechnicalAnalysisController: @@ -65,7 +66,6 @@ class TechnicalAnalysisController: choices=self.CHOICES, ) - @staticmethod def print_help(self): """Print help""" @@ -106,7 +106,6 @@ class TechnicalAnalysisController: print(" ad chaikin accumulation/distribution line values") print(" obv on balance volume") print("") - return def switch(self, an_input: str): """Process and dispatch input @@ -118,6 +117,7 @@ class TechnicalAnalysisController: True - quit the program None - continue in the menu """ + (known_args, other_args) = self.ta_parser.parse_known_args(an_input.split()) # Due to Finviz implementation of Spectrum, we delete the generated spectrum figure @@ -134,7 +134,7 @@ class TechnicalAnalysisController: def call_help(self, _): """Process Help command""" - self.print_help(self) + self.print_help() def call_q(self, _): """Process Q command - quit the menu""" diff --git a/gamestonk_terminal/technical_analysis/tradingview_view.py b/gamestonk_terminal/technical_analysis/tradingview_view.py index 61d2faf0723..b2f1668dfb4 100644 --- a/gamestonk_terminal/technical_analysis/tradingview_view.py +++ b/gamestonk_terminal/technical_analysis/tradingview_view.py @@ -2,8 +2,9 @@ import argparse from typing import List import requests import pandas as pd -from gamestonk_terminal import config_terminal as cfg from tradingview_ta import TA_Handler + +from gamestonk_terminal import config_terminal as cfg from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, ) diff --git a/terminal.py b/terminal.py index 28c7d7c641c..ed0ff2cbbfe 100644 --- a/terminal.py +++ b/terminal.py @@ -33,13 +33,7 @@ from gamestonk_terminal.cryptocurrency import crypto_controller from gamestonk_terminal.screener import screener_controller from gamestonk_terminal.portfolio_optimization import po_controller -# import warnings -# warnings.simplefilter("always") - - -# pylint: disable=too-many-branches - - +# pylint: disable=too-many-statements,too-many-branches def main(): """ Gamestonk Terminal is an awesome stock market terminal that has been developed for fun, @@ -361,9 +355,9 @@ def main(): if b_quit: break - else: - if not main_cmd: - should_print_help = True + + if not main_cmd: + should_print_help = True print( "Hope you enjoyed the terminal. Remember that stonks only go up. Diamond hands.\n" From 309ba1ecce8792ade48e25e5468dd61de777b74f Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 22:30:30 -0700 Subject: [PATCH 088/114] Adding extra line --- terminal.py | 1 + 1 file changed, 1 insertion(+) diff --git a/terminal.py b/terminal.py index ed0ff2cbbfe..78e912c761d 100644 --- a/terminal.py +++ b/terminal.py @@ -33,6 +33,7 @@ from gamestonk_terminal.cryptocurrency import crypto_controller from gamestonk_terminal.screener import screener_controller from gamestonk_terminal.portfolio_optimization import po_controller + # pylint: disable=too-many-statements,too-many-branches def main(): """ From fa63412ac35d117f3a7ec102ccd2868e36a8e16f Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 21 Apr 2021 12:20:37 -0400 Subject: [PATCH 089/114] Add coinmarketcap top 100 ability + small refactor --- gamestonk_terminal/config_terminal.py | 3 + gamestonk_terminal/cryptocurrency/README.md | 16 +++ .../cryptocurrency/coinmarketcap_view.py | 100 ++++++++++++++++++ .../cryptocurrency/crypto_controller.py | 14 ++- .../{coin_api.py => pycoingecko_view.py} | 0 pyproject.toml | 1 + requirements-full.txt | 1 + requirements-old.txt | 1 + requirements-win.txt | 1 + requirements.txt | 1 + tests/test_coingecko_crypto.py | 2 +- 11 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 gamestonk_terminal/cryptocurrency/coinmarketcap_view.py rename gamestonk_terminal/cryptocurrency/{coin_api.py => pycoingecko_view.py} (100%) diff --git a/gamestonk_terminal/config_terminal.py b/gamestonk_terminal/config_terminal.py index ea2aab6b960..bed32fd3644 100644 --- a/gamestonk_terminal/config_terminal.py +++ b/gamestonk_terminal/config_terminal.py @@ -45,3 +45,6 @@ TRADIER_TOKEN = os.getenv("GT_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" diff --git a/gamestonk_terminal/cryptocurrency/README.md b/gamestonk_terminal/cryptocurrency/README.md index fd5ac92c10e..78a1167ffbf 100644 --- a/gamestonk_terminal/cryptocurrency/README.md +++ b/gamestonk_terminal/cryptocurrency/README.md @@ -9,6 +9,7 @@ Current functionality is aimed to be similar to loading a stock ticker. * [load](#load) * [view](#view) +* [top](#top) ## load Load a given coin vs a given currency: @@ -39,3 +40,18 @@ usage: view After loading the above 1 day dogecoin/eur. Running view plots the data: ![doge](https://user-images.githubusercontent.com/18151143/112690617-7832f500-8e52-11eb-84c4-253ab222a918.png) + + +## top +This command displays the top n cryptocurrencies from coinmarketcap.com. The list appears to be sorted by Mar + +```` +top [-n] [-s --sort SORTBY] [--descend] +```` +* -n: Number of coins to look at (after sort). Defaults to 10. +* -s/--sort : Column to sort by. One of {Symbol,CMC_Rank,LastPrice,DayPctChange,MarketCap}. Defaults to sorting by the CMC rank. +* --descend : Flag to change the sorting order. Sorts in ascending order (since default order is the Rank which starts at 1). + +Example usage to get the CMC top 100, then show the top 4 highest Percent Day Change + +![im](https://user-images.githubusercontent.com/18151143/115587223-6bf85700-a29b-11eb-9d96-cb4239b7c2d0.png) diff --git a/gamestonk_terminal/cryptocurrency/coinmarketcap_view.py b/gamestonk_terminal/cryptocurrency/coinmarketcap_view.py new file mode 100644 index 00000000000..a8820889d33 --- /dev/null +++ b/gamestonk_terminal/cryptocurrency/coinmarketcap_view.py @@ -0,0 +1,100 @@ +"""CoinMarketCap API""" +__docformat__ = "numpy" + +import argparse +from typing import List +import pandas as pd +from tabulate import tabulate +from coinmarketcapapi import CoinMarketCapAPI +from gamestonk_terminal.config_terminal import COINMARKETCAP_KEY +from gamestonk_terminal.helper_funcs import parse_known_args_and_warn + +sort_options = ["Symbol", "CMC_Rank", "LastPrice", "DayPctChange", "MarketCap"] + +sort_map = { + "Symbol": "Symbol", + "CMC_Rank": "CMC_Rank", + "LastPrice": "Last Price", + "DayPctChange": "1 Day Pct Change", + "MarketCap": "Market Cap ($B)", +} + + +def get_cmc_top_n(other_args: List[str]): + """ + Shows top n coins from coinmarketcap.com + Parameters + ---------- + other_args: List[str] + Arguments to pass to argparse + + """ + parser = argparse.ArgumentParser( + prog="cmc_top_n", + add_help=False, + description="This gets the top ranked coins from coinmarketcap.com", + ) + + parser.add_argument( + "-n", default=10, dest="n_to_get", type=int, help="number of coins to display" + ) + + parser.add_argument( + "-s", + "--sort", + dest="sortby", + type=str, + help="column to sort data by.", + default="CMC_Rank", + choices=sort_options, + ) + + parser.add_argument( + "--descend", + action="store_false", + help="Flag to sort in descending order (lowest first)", + dest="descend", + default=True, + ) + + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + cmc = CoinMarketCapAPI(COINMARKETCAP_KEY) + ratings = cmc.cryptocurrency_listings_latest().data + + symbol, rank, price, pchange1d, mkt_cap = [], [], [], [], [] + for coin in ratings: + symbol.append(coin["symbol"]) + rank.append(coin["cmc_rank"]) + price.append(coin["quote"]["USD"]["price"]) + pchange1d.append(coin["quote"]["USD"]["percent_change_24h"]) + mkt_cap.append(coin["quote"]["USD"]["market_cap"] / (10 ** 9)) + + df = pd.DataFrame(data=[symbol, rank, price, pchange1d, mkt_cap]).transpose() + df.columns = [ + "Symbol", + "CMC_Rank", + "Last Price", + "1 Day Pct Change", + "Market Cap ($B)", + ] + + df = df.sort_values(by=sort_map[ns_parser.sortby], ascending=ns_parser.descend) + + print( + tabulate( + df.iloc[: ns_parser.n_to_get, :], + headers=df.columns, + showindex=False, + tablefmt="fancy_grid", + floatfmt=".2f", + ) + ) + print("") + + except Exception as e: + print(e) + print("") diff --git a/gamestonk_terminal/cryptocurrency/crypto_controller.py b/gamestonk_terminal/cryptocurrency/crypto_controller.py index 4a1508e11f8..e78323b473b 100644 --- a/gamestonk_terminal/cryptocurrency/crypto_controller.py +++ b/gamestonk_terminal/cryptocurrency/crypto_controller.py @@ -7,12 +7,13 @@ 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 coin_api +from gamestonk_terminal.cryptocurrency import pycoingecko_view +from gamestonk_terminal.cryptocurrency import coinmarketcap_view as cmc_view class CryptoController: - CHOICES = ["help", "q", "quit", "load", "view"] + CHOICES = ["help", "q", "quit", "load", "view", "top"] def __init__(self): """ CONSTRUCTOR """ @@ -34,6 +35,8 @@ class CryptoController: print(" load load cryptocurrency data") print(" view load and view cryptocurrency data") print("") + print(" top view top coins from coinmarketcap") + print("") def switch(self, an_input: str): """Process and dispatch input @@ -64,16 +67,19 @@ class CryptoController: return True def call_load(self, other_args): - self.current_coin, self.current_df = coin_api.load(other_args) + self.current_coin, self.current_df = pycoingecko_view.load(other_args) def call_view(self, other_args): if self.current_coin: - coin_api.view(self.current_coin, self.current_df, other_args) + pycoingecko_view.view(self.current_coin, self.current_df, other_args) else: print("No coin selected. Use 'load' to load the coin you want to look at.") print("") + def call_top(self, other_args): + cmc_view.get_cmc_top_n(other_args) + def menu(): crypto_controller = CryptoController() diff --git a/gamestonk_terminal/cryptocurrency/coin_api.py b/gamestonk_terminal/cryptocurrency/pycoingecko_view.py similarity index 100% rename from gamestonk_terminal/cryptocurrency/coin_api.py rename to gamestonk_terminal/cryptocurrency/pycoingecko_view.py diff --git a/pyproject.toml b/pyproject.toml index 53f0f468699..a3bbf6762c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,6 +58,7 @@ statsmodels = "^0.12.2" tabulate = "^0.8.9" pyportfolioopt = "^1.4.1" selenium = "^3.141.0" +python-coinmarketcap = "^0.2" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements-full.txt b/requirements-full.txt index 39247ebb9c6..1dce549665e 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -146,6 +146,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-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" pytrends==4.7.3 diff --git a/requirements-old.txt b/requirements-old.txt index 3dd16fb2a3f..6dcb6d00577 100644 --- a/requirements-old.txt +++ b/requirements-old.txt @@ -93,6 +93,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-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" pytrends==4.7.3 diff --git a/requirements-win.txt b/requirements-win.txt index d5b413e1ca6..399b80c6f67 100644 --- a/requirements-win.txt +++ b/requirements-win.txt @@ -95,6 +95,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-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" pytrends==4.7.3 diff --git a/requirements.txt b/requirements.txt index 31e6b0412cc..bf0985ecfa5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -110,6 +110,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-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" pytrends==4.7.3 diff --git a/tests/test_coingecko_crypto.py b/tests/test_coingecko_crypto.py index 5f20e2e04d1..003b5927f8b 100644 --- a/tests/test_coingecko_crypto.py +++ b/tests/test_coingecko_crypto.py @@ -1,7 +1,7 @@ from unittest import mock, TestCase import json from pycoingecko import CoinGeckoAPI -from gamestonk_terminal.cryptocurrency.coin_api import load +from gamestonk_terminal.cryptocurrency.pycoingecko_view import load # pylint: disable=unused-import From c3838e21995bc21b2fbf3956560f6bb5e24e0805 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 21 Apr 2021 12:23:58 -0400 Subject: [PATCH 090/114] Add coinmarketcap top 100 ability + small refactor --- poetry.lock | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 582cfdfc228..1c9dc7b56d1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2046,6 +2046,14 @@ toml = "*" [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +[[package]] +name = "python-coinmarketcap" +version = "0.2" +description = "CoinMarketCap Python API Wrapper" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "python-dateutil" version = "2.8.1" @@ -2946,7 +2954,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "2f3963dac96a208dfe5157d593c45f946d9b4c829b16302f2b297250390367cb" +content-hash = "fa7c02ebec2d14a1c42f76f8e1328134975893c5f98afa879f2bc672675d6a7f" [metadata.files] absl-py = [ @@ -4275,6 +4283,11 @@ pytest = [ {file = "pytest-6.2.3-py3-none-any.whl", hash = "sha256:6ad9c7bdf517a808242b998ac20063c41532a570d088d77eec1ee12b0b5574bc"}, {file = "pytest-6.2.3.tar.gz", hash = "sha256:671238a46e4df0f3498d1c3270e5deb9b32d25134c99b7d75370a68cfbe9b634"}, ] +python-coinmarketcap = [ + {file = "python-coinmarketcap-0.2.tar.gz", hash = "sha256:b1e0e8b098fc910a5ec943a06774d5ee3b190e915123366e2f16238ef0a8a433"}, + {file = "python_coinmarketcap-0.2-py2-none-any.whl", hash = "sha256:54c278154ee11ca78837fb73eae8c322a60af93dc0ce75b515fecf895d181cf5"}, + {file = "python_coinmarketcap-0.2-py3-none-any.whl", hash = "sha256:3b69a7a92cd4f2b4726a2982d166c0b587fa4911cf366286f798e1e6f9d94933"}, +] python-dateutil = [ {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, From 2e3e9c6bb4bc3729c41bb289aac5c0c170cde9be Mon Sep 17 00:00:00 2001 From: Jamie Date: Tue, 20 Apr 2021 20:05:52 -0400 Subject: [PATCH 091/114] updated permanent discord link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a23fb298cbb..d3d2f8966fb 100644 --- a/README.md +++ b/README.md @@ -369,7 +369,7 @@ Distributed under the MIT License. See [LICENSE](https://github.com/DidierRLopes [James Maslek](https://www.linkedin.com/in/james-maslek-b6810186/) - jmaslek11@gmail.com -Feel free to share loss porn, memes or any questions at https://discord.gg/BsfJk4MQ +Feel free to share loss porn, memes or any questions at https://discord.gg/Up2QGbMKHY ## Acknowledgments From 9b6bef5b37de2005c8225a409643611574650e9e Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 13:21:49 -0700 Subject: [PATCH 092/114] Refactoring comparison analysis --- .../comparison_analysis/ca_controller.py | 91 +++++++++++----- .../{finbrain_api.py => finbrain_view.py} | 6 ++ ...rket_watch_api.py => market_watch_view.py} | 3 + ...o_finance_api.py => yahoo_finance_view.py} | 100 ++++++++++++++---- 4 files changed, 155 insertions(+), 45 deletions(-) rename gamestonk_terminal/comparison_analysis/{finbrain_api.py => finbrain_view.py} (99%) rename gamestonk_terminal/comparison_analysis/{market_watch_api.py => market_watch_view.py} (99%) rename gamestonk_terminal/comparison_analysis/{yahoo_finance_api.py => yahoo_finance_view.py} (77%) diff --git a/gamestonk_terminal/comparison_analysis/ca_controller.py b/gamestonk_terminal/comparison_analysis/ca_controller.py index 499b6c9cd39..3772807b71a 100644 --- a/gamestonk_terminal/comparison_analysis/ca_controller.py +++ b/gamestonk_terminal/comparison_analysis/ca_controller.py @@ -2,23 +2,24 @@ __docformat__ = "numpy" import argparse -import requests import random from typing import List from datetime import datetime +import requests import pandas as pd from matplotlib import pyplot as plt +from finvizfinance.screener.overview import Overview +from prompt_toolkit.completion import NestedCompleter + from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal import config_terminal as cfg -from finvizfinance.screener.overview import Overview from gamestonk_terminal.helper_funcs import get_flair, parse_known_args_and_warn -from gamestonk_terminal.comparison_analysis import yahoo_finance_api as yf_api -from gamestonk_terminal.comparison_analysis import market_watch_api as mw_api -from gamestonk_terminal.comparison_analysis import finbrain_api as f_api +from gamestonk_terminal.comparison_analysis import yahoo_finance_view +from gamestonk_terminal.comparison_analysis import market_watch_view +from gamestonk_terminal.comparison_analysis import finbrain_view from gamestonk_terminal.comparison_analysis import finviz_compare_view from gamestonk_terminal.portfolio_optimization import po_controller from gamestonk_terminal.menu import session -from prompt_toolkit.completion import NestedCompleter class ComparisonAnalysisController: @@ -54,9 +55,23 @@ class ComparisonAnalysisController: start: datetime, interval: str, similar: List[str], - user: bool, ): - """Constructor""" + """Constructor + + Parameters + ---------- + stock : pd.DataFrame + Stock data + ticker : str + Stock ticker + start : datetime + Start time + interval : str + Time interval + similar : List[str] + List of similar tickers + """ + self.similar = similar self.user = "" self.stock = stock @@ -69,7 +84,6 @@ class ComparisonAnalysisController: choices=self.CHOICES, ) - @staticmethod def print_help(self): """Print help""" @@ -108,14 +122,21 @@ class ComparisonAnalysisController: print(" performance brief performance comparison") print(" technical brief technical comparison") print("") + if self.similar: print(" > po portfolio optimization for selected tickers") print("") return - @staticmethod def get_similar_companies(self, other_args: List[str]): - """ Get similar companies. [Source: Polygon API] """ + """Get similar companies. [Source: Polygon API] + + Parameters + ---------- + other_args : List[str] + argparse other args + """ + parser = argparse.ArgumentParser( add_help=False, prog="get", @@ -189,9 +210,15 @@ class ComparisonAnalysisController: print("") return - @staticmethod def select_similar_companies(self, other_args: List[str]): - """ Select similar companies, e.g. NIO,XPEV,LI""" + """Select similar companies, e.g. NIO,XPEV,LI + + Parameters + ---------- + other_args : List[str] + argparse other args + """ + parser = argparse.ArgumentParser( add_help=False, prog="select", @@ -242,7 +269,7 @@ class ComparisonAnalysisController: def call_help(self, _): """Process Help command""" - self.print_help(self) + self.print_help() def call_q(self, _): """Process Q command - quit the menu""" @@ -254,43 +281,43 @@ class ComparisonAnalysisController: def call_get(self, other_args: List[str]): """Process get command""" - self.get_similar_companies(self, other_args) + self.get_similar_companies(other_args) def call_select(self, other_args: List[str]): """Process select command""" - self.select_similar_companies(self, other_args) + self.select_similar_companies(other_args) def call_historical(self, other_args: List[str]): """Process historical command""" - yf_api.historical( + yahoo_finance_view.historical( other_args, self.stock, self.ticker, self.start, self.interval, self.similar ) def call_hcorr(self, other_args: List[str]): """Process historical correlation command""" - yf_api.correlation( + yahoo_finance_view.correlation( other_args, self.stock, self.ticker, self.start, self.interval, self.similar ) def call_income(self, other_args: List[str]): """Process income command""" - mw_api.compare_income(other_args, self.ticker, self.similar) + market_watch_view.compare_income(other_args, self.ticker, self.similar) def call_balance(self, other_args: List[str]): """Process balance command""" - mw_api.compare_balance(other_args, self.ticker, self.similar) + market_watch_view.compare_balance(other_args, self.ticker, self.similar) def call_cashflow(self, other_args: List[str]): """Process cashflow command""" - mw_api.compare_cashflow(other_args, self.ticker, self.similar) + market_watch_view.compare_cashflow(other_args, self.ticker, self.similar) def call_sentiment(self, other_args: List[str]): """Process sentiment command""" - f_api.sentiment_compare(other_args, self.ticker, self.similar) + finbrain_view.sentiment_compare(other_args, self.ticker, self.similar) def call_scorr(self, other_args: List[str]): """Process sentiment correlation command""" - f_api.sentiment_correlation(other_args, self.ticker, self.similar) + finbrain_view.sentiment_correlation(other_args, self.ticker, self.similar) def call_overview(self, other_args: List[str]): """Process overview command""" @@ -324,11 +351,21 @@ class ComparisonAnalysisController: def menu(stock: pd.DataFrame, ticker: str, start: datetime, interval: str): - """Comparison Analysis Menu""" + """Comparison Analysis Menu - ca_controller = ComparisonAnalysisController( - stock, ticker, start, interval, [], False - ) + Parameters + ---------- + stock : pd.DataFrame + Stock data + ticker : str + Stock ticker + start : datetime + Time start + interval : str + Time interval + """ + + ca_controller = ComparisonAnalysisController(stock, ticker, start, interval, []) ca_controller.call_help(None) while True: diff --git a/gamestonk_terminal/comparison_analysis/finbrain_api.py b/gamestonk_terminal/comparison_analysis/finbrain_view.py similarity index 99% rename from gamestonk_terminal/comparison_analysis/finbrain_api.py rename to gamestonk_terminal/comparison_analysis/finbrain_view.py index c1cb629d893..cc0ee139d64 100644 --- a/gamestonk_terminal/comparison_analysis/finbrain_api.py +++ b/gamestonk_terminal/comparison_analysis/finbrain_view.py @@ -10,6 +10,7 @@ import pandas as pd from pandas.plotting import register_matplotlib_converters import numpy as np import seaborn as sns + from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, plot_autoscale, @@ -33,6 +34,7 @@ def sentiment_compare(other_args: List[str], ticker: str, similar: List[str]): similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="sentiment_compare", @@ -98,6 +100,7 @@ def sentiment_correlation(other_args: List[str], ticker: str, similar: List[str] similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="sentiment_compare", @@ -164,6 +167,7 @@ def get_sentiments(similar: List[str]) -> pd.DataFrame: DataFrame() Contains sentiment analysis from several tickers """ + df_sentiment = pd.DataFrame() for ticker in similar: result = requests.get(f"https://api.finbrain.tech/v0/sentiments/{ticker}") @@ -196,6 +200,7 @@ def plot_sentiments(df_sentiment: pd.DataFrame, similar: List[str]): similar : List[str] List of similar companies """ + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) for idx, ticker in enumerate(similar): @@ -251,6 +256,7 @@ def plot_correlation(df_sentiment: pd.DataFrame, similar: List[str]): similar : List[str] List of similar companies """ + plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) mask = np.zeros((len(similar), len(similar)), dtype=bool) diff --git a/gamestonk_terminal/comparison_analysis/market_watch_api.py b/gamestonk_terminal/comparison_analysis/market_watch_view.py similarity index 99% rename from gamestonk_terminal/comparison_analysis/market_watch_api.py rename to gamestonk_terminal/comparison_analysis/market_watch_view.py index 5067cdeae38..4cef54e2b79 100644 --- a/gamestonk_terminal/comparison_analysis/market_watch_api.py +++ b/gamestonk_terminal/comparison_analysis/market_watch_view.py @@ -27,6 +27,7 @@ def compare_income(other_args: List[str], ticker: str, similar: List[str]): similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="income", @@ -132,6 +133,7 @@ def compare_balance(other_args: List[str], ticker: str, similar: List[str]): similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="compare_balance", @@ -237,6 +239,7 @@ def compare_cashflow(other_args: List[str], ticker: str, similar: List[str]): similar : List[str] Similar companies to compare income with """ + parser = argparse.ArgumentParser( add_help=False, prog="compare_cashflow", diff --git a/gamestonk_terminal/comparison_analysis/yahoo_finance_api.py b/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py similarity index 77% rename from gamestonk_terminal/comparison_analysis/yahoo_finance_api.py rename to gamestonk_terminal/comparison_analysis/yahoo_finance_view.py index 72df9f825ad..095a506b4f6 100644 --- a/gamestonk_terminal/comparison_analysis/yahoo_finance_api.py +++ b/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py @@ -1,4 +1,9 @@ +""" Comparison Analysis Yahoo Finance View """ +__docformat__ = "numpy" + import argparse +from typing import List +from datetime import datetime import numpy as np import pandas as pd from pandas.plotting import register_matplotlib_converters @@ -21,6 +26,24 @@ d_candle_types = { def check_one_of_ohlca(type_candles: str) -> str: + """Convert a candle type + + Parameters + ---------- + type_candles : str + OHLCA candle type + + Returns + ------- + str + Converted candle type + + Raises + ------ + argparse.ArgumentTypeError + Unknown candle type + """ + if ( type_candles == "o" or type_candles == "h" @@ -32,7 +55,32 @@ def check_one_of_ohlca(type_candles: str) -> str: raise argparse.ArgumentTypeError("The type of candles specified is not recognized") -def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): +def historical( + other_args: List[str], + df_stock: pd.DataFrame, + ticker: str, + start: datetime, + interval: str, + similar: List[str], +): + """Display historical data from Yahoo Finance + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + df_stock : pd.DataFrame + Stock data + ticker : str + Ticker symbol + start : datetime + Time start + interval : str + Time interval + similar : List[str] + List of similar tickers + """ + parser = argparse.ArgumentParser( add_help=False, prog="historical", @@ -66,11 +114,11 @@ def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): ) try: - if s_interval != "1440min": + if interval != "1440min": print("Intraday historical data analysis comparison is not yet available.") # Alpha Vantage only supports 5 calls per minute, we need another API to get intraday data else: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -80,16 +128,14 @@ def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): similar += ns_parser.l_also plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) - plt.title(f"Similar companies to {s_ticker}") - df_stock = yf.download( - s_ticker, start=s_start, progress=False, threads=False - ) + plt.title(f"Similar companies to {ticker}") + df_stock = yf.download(ticker, start=start, progress=False, threads=False) plt.plot( df_stock.index, df_stock[d_candle_types[ns_parser.type_candle]].values ) # plt.plot(df_stock.index, df_stock["5. adjusted close"].values, lw=2) l_min = [df_stock.index[0]] - l_leg = [s_ticker] + l_leg = [ticker] l_stocks = similar[:] @@ -98,7 +144,7 @@ def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): for symbol in l_stocks: try: df_similar_stock = yf.download( - symbol, start=s_start, progress=False, threads=False + symbol, start=start, progress=False, threads=False ) if not df_similar_stock.empty: plt.plot( @@ -141,7 +187,25 @@ def historical(l_args, df_stock, s_ticker, s_start, s_interval, similar): print(e, "\n") -def correlation(l_args, df_stock, s_ticker, s_start, s_interval, similar): +def correlation(other_args, df_stock, ticker, start, interval, similar): + """[summary] + + Parameters + ---------- + other_args : [type] + Command line arguments to be processed with argparse + df_stock : pd.DataFrame + Stock data + ticker : str + Ticker symbol + start : datetime + Time start + interval : str + Time interval + similar : [type] + List of similar tickers + """ + parser = argparse.ArgumentParser( add_help=False, prog="corr", @@ -176,11 +240,11 @@ def correlation(l_args, df_stock, s_ticker, s_start, s_interval, similar): ) try: - if s_interval != "1440min": + if interval != "1440min": print("Intraday historical data analysis comparison is not yet available.") # Alpha Vantage only supports 5 calls per minute, we need another API to get intraday data else: - ns_parser = parse_known_args_and_warn(parser, l_args) + ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: return @@ -193,21 +257,21 @@ def correlation(l_args, df_stock, s_ticker, s_start, s_interval, similar): print("Provide at least a similar company for correlation") else: d_stock = {} - d_stock[s_ticker] = yf.download(s_ticker, start=s_start, progress=False) - l_min = [d_stock[s_ticker].index[0]] + d_stock[ticker] = yf.download(ticker, start=start, progress=False) + l_min = [d_stock[ticker].index[0]] for symbol in similar: - d_stock[symbol] = yf.download(symbol, start=s_start, progress=False) + d_stock[symbol] = yf.download(symbol, start=start, progress=False) if not d_stock[symbol].empty: l_min.append(d_stock[symbol].index[0]) min_start_date = max(l_min) - df_stock = d_stock[s_ticker][ + df_stock = d_stock[ticker][ d_candle_types[ns_parser.type_candle] - ].rename(s_ticker) + ].rename(ticker) for symbol in d_stock: - if symbol != s_ticker: + if symbol != ticker: if not d_stock[symbol].empty: df_stock = pd.concat( [ From 4355dcaaf697c62cf6b02ed76eaff76922ad78e1 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 13:25:51 -0700 Subject: [PATCH 093/114] Adding __init__.py --- gamestonk_terminal/comparison_analysis/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 gamestonk_terminal/comparison_analysis/__init__.py diff --git a/gamestonk_terminal/comparison_analysis/__init__.py b/gamestonk_terminal/comparison_analysis/__init__.py new file mode 100644 index 00000000000..e69de29bb2d From 7ecc5f2feacc494beeb3ccc826c2807cd67d4460 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 13:37:56 -0700 Subject: [PATCH 094/114] Try a different way to pylint --- .github/workflows/test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e85716d7882..a6e166da0c5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,8 @@ jobs: - run: mypy --ignore-missing-imports . - run: shopt -s globstar && pyupgrade --py36-plus **/*.py - run: safety check - - run: pylint **/*.py + - run: | + find . -name '*.py' -exec pylint {} \; test: name: ubuntu-latest - Python 3.8 needs: linting From 67c31b1b035d424c39c0813a0c653d9a2ff696d9 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 14:15:45 -0700 Subject: [PATCH 095/114] Updating pylint to actually run --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a6e166da0c5..fceaff60738 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,7 +33,7 @@ jobs: - run: shopt -s globstar && pyupgrade --py36-plus **/*.py - run: safety check - run: | - find . -name '*.py' -exec pylint {} \; + pylint terminal.py gamestonk_terminal tests test: name: ubuntu-latest - Python 3.8 needs: linting From 5718b49a843d6550ff35626401598cdc5021c1b7 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 22:25:29 -0700 Subject: [PATCH 096/114] Fixing pylint errors and warnings --- .pylintrc | 6 +- .../behavioural_analysis/ba_controller.py | 2 +- .../behavioural_analysis/finbrain_view.py | 3 +- .../behavioural_analysis/reddit_view.py | 22 ----- .../comparison_analysis/yahoo_finance_view.py | 9 +- gamestonk_terminal/discovery/finviz_view.py | 15 ++- .../discovery/marketbeat_view.py | 4 +- .../discovery/seeking_alpha_model.py | 4 +- .../discovery/seeking_alpha_view.py | 2 +- .../due_diligence/finra_view.py | 3 +- .../portfolio/port_controller.py | 7 +- .../optimizer_helper.py | 23 +++-- .../portfolio_optimization/optimizer_view.py | 99 +++++++++---------- .../portfolio_optimization/po_controller.py | 9 +- .../prediction_techniques/ets.py | 12 +-- .../prediction_techniques/neural_networks.py | 21 ---- .../prediction_techniques/pred_controller.py | 9 +- .../prediction_techniques/pred_helper.py | 3 +- .../technical_analysis/finviz_view.py | 3 +- .../technical_analysis/overlap.py | 2 +- .../technical_analysis/ta_controller.py | 10 +- .../technical_analysis/tradingview_view.py | 3 +- terminal.py | 14 +-- 23 files changed, 119 insertions(+), 166 deletions(-) diff --git a/.pylintrc b/.pylintrc index ceaa81904dc..c8806cea49c 100644 --- a/.pylintrc +++ b/.pylintrc @@ -54,7 +54,7 @@ confidence= # disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call # disable=too-many-instance-attributes,len-as-condition,too-few-public-methods,anomalous-backslash-in-string,no-else-return,simplifiable-if-statement,too-many-arguments,duplicate-code,no-name-in-module,no-member,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,missing-docstring,invalid-name,bad-whitespace,consider-using-enumerate,unexpected-keyword-arg -disable=useless-return,missing-docstring,invalid-name,import-error,bad-continuation,broad-except,unnecessary-lambda,no-self-use,duplicate-code,consider-using-generator +disable=useless-return,missing-docstring,invalid-name,import-error,bad-continuation,broad-except,unnecessary-lambda,no-self-use,duplicate-code,consider-using-generator,unbalanced-tuple-unpacking # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option @@ -397,7 +397,7 @@ valid-metaclass-classmethod-first-arg=mcs [DESIGN] # Maximum number of arguments for function / method -max-args=5 +max-args=8 # Maximum number of attributes for a class (see R0902). # max-attributes=7 @@ -416,7 +416,7 @@ max-locals=40 max-parents=7 # Maximum number of public methods for a class (see R0904). -max-public-methods=20 +max-public-methods=30 # Maximum number of return / yield for function / method body max-returns=9 diff --git a/gamestonk_terminal/behavioural_analysis/ba_controller.py b/gamestonk_terminal/behavioural_analysis/ba_controller.py index 57e9a66cbe6..e8ae8f60aee 100644 --- a/gamestonk_terminal/behavioural_analysis/ba_controller.py +++ b/gamestonk_terminal/behavioural_analysis/ba_controller.py @@ -4,6 +4,7 @@ __docformat__ = "numpy" import argparse from typing import List from datetime import datetime +from prompt_toolkit.completion import NestedCompleter from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal.helper_funcs import get_flair @@ -14,7 +15,6 @@ from gamestonk_terminal.behavioural_analysis import ( stocktwits_view, finbrain_view, ) -from prompt_toolkit.completion import NestedCompleter class BehaviouralAnalysisController: diff --git a/gamestonk_terminal/behavioural_analysis/finbrain_view.py b/gamestonk_terminal/behavioural_analysis/finbrain_view.py index 090327aff73..e5d1907e485 100644 --- a/gamestonk_terminal/behavioural_analysis/finbrain_view.py +++ b/gamestonk_terminal/behavioural_analysis/finbrain_view.py @@ -9,13 +9,14 @@ import matplotlib.dates as mdates import pandas as pd from pandas.plotting import register_matplotlib_converters import numpy as np +from colorama import Fore, Style + from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, plot_autoscale, ) from gamestonk_terminal.config_plot import PLOT_DPI from gamestonk_terminal import feature_flags as gtff -from colorama import Fore, Style register_matplotlib_converters() diff --git a/gamestonk_terminal/behavioural_analysis/reddit_view.py b/gamestonk_terminal/behavioural_analysis/reddit_view.py index fdf6b1396d1..231f1728276 100644 --- a/gamestonk_terminal/behavioural_analysis/reddit_view.py +++ b/gamestonk_terminal/behavioural_analysis/reddit_view.py @@ -189,17 +189,6 @@ def popular_tickers(l_args): wallstreetbets """, ) - """ - parser.add_argument( - "-d", - "--days", - action="store", - dest="n_days", - type=check_positive, - default=1, - help="look for the tickers from those n past days.", - ) - """ try: ns_parser = parse_known_args_and_warn(parser, l_args) @@ -502,17 +491,6 @@ def spac(l_args): default=5, help="limit of posts with SPACs retrieved.", ) - """ - parser.add_argument( - "-d", - "--days", - action="store", - dest="n_days", - type=check_positive, - default=5, - help="look for the tickers from those n past days.", - ) - """ try: ns_parser = parse_known_args_and_warn(parser, l_args) diff --git a/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py b/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py index 095a506b4f6..d2552845e61 100644 --- a/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py +++ b/gamestonk_terminal/comparison_analysis/yahoo_finance_view.py @@ -44,14 +44,9 @@ def check_one_of_ohlca(type_candles: str) -> str: Unknown candle type """ - if ( - type_candles == "o" - or type_candles == "h" - or type_candles == "l" - or type_candles == "c" - or type_candles == "a" - ): + if type_candles in ("o", "h", "l", "c", "a"): return type_candles + raise argparse.ArgumentTypeError("The type of candles specified is not recognized") diff --git a/gamestonk_terminal/discovery/finviz_view.py b/gamestonk_terminal/discovery/finviz_view.py index 3bd3e06e8f6..284779960c4 100644 --- a/gamestonk_terminal/discovery/finviz_view.py +++ b/gamestonk_terminal/discovery/finviz_view.py @@ -4,10 +4,11 @@ __docformat__ = "numpy" import argparse from typing import List import webbrowser -from gamestonk_terminal.helper_funcs import parse_known_args_and_warn from finvizfinance.group import valuation, performance, spectrum from PIL import Image +from gamestonk_terminal.helper_funcs import parse_known_args_and_warn + l_GROUPS = [ "Sector", "Industry", @@ -97,6 +98,7 @@ def get_valuation_performance_data(group: str, data_type: str): pd.DataFrame dataframe with valuation/performance data """ + if data_type == "valuation": df_group = valuation.Valuation().ScreenerView(group=group) elif data_type == "performance": @@ -117,6 +119,7 @@ def get_spectrum_data(group: str): data_type : str select data type to see data between valuation or performance """ + spectrum.Spectrum().ScreenerView(group=group) @@ -130,6 +133,7 @@ def view_group_data(other_args: List[str], data_type: str): data_type : str select data type to see data between valuation, performance and spectrum """ + parser = argparse.ArgumentParser( add_help=False, prog="group_data", @@ -156,12 +160,12 @@ def view_group_data(other_args: List[str], data_type: str): ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return + return None if isinstance(ns_parser.group, List): ns_parser.group = ns_parser.group[0] - if data_type == "valuation" or data_type == "performance": + if data_type in ("valuation", "performance"): df_group = get_valuation_performance_data(ns_parser.group, data_type) print(df_group.to_string()) @@ -172,7 +176,7 @@ def view_group_data(other_args: List[str], data_type: str): img.show() print("") - return ns_parser.group + return img else: print( @@ -180,7 +184,8 @@ def view_group_data(other_args: List[str], data_type: str): ) print("") - return "" + return None except SystemExit: print("") + return None diff --git a/gamestonk_terminal/discovery/marketbeat_view.py b/gamestonk_terminal/discovery/marketbeat_view.py index 13ec048ee5c..c2f3c58007d 100644 --- a/gamestonk_terminal/discovery/marketbeat_view.py +++ b/gamestonk_terminal/discovery/marketbeat_view.py @@ -2,14 +2,14 @@ __docformat__ = "numpy" import argparse +from typing import List import numpy as np import pandas as pd -from typing import List + from gamestonk_terminal.helper_funcs import ( check_positive, parse_known_args_and_warn, ) - from gamestonk_terminal.discovery import marketbeat_model diff --git a/gamestonk_terminal/discovery/seeking_alpha_model.py b/gamestonk_terminal/discovery/seeking_alpha_model.py index 6041eb63f67..1a2df5f03a3 100644 --- a/gamestonk_terminal/discovery/seeking_alpha_model.py +++ b/gamestonk_terminal/discovery/seeking_alpha_model.py @@ -2,11 +2,11 @@ __docformat__ = "numpy" from typing import List +from datetime import datetime import requests from bs4 import BeautifulSoup import pandas as pd from pandas.core.frame import DataFrame -from datetime import datetime from gamestonk_terminal.helper_funcs import get_user_agent @@ -180,7 +180,7 @@ def get_trending_list(num: int) -> list: } ) - return articles + return articles[:num] def get_article_data(article_id: int) -> dict: diff --git a/gamestonk_terminal/discovery/seeking_alpha_view.py b/gamestonk_terminal/discovery/seeking_alpha_view.py index 1670cc3e084..ee65fae29d5 100644 --- a/gamestonk_terminal/discovery/seeking_alpha_view.py +++ b/gamestonk_terminal/discovery/seeking_alpha_view.py @@ -3,8 +3,8 @@ __docformat__ = "numpy" import argparse from typing import List -import pandas as pd from datetime import datetime +import pandas as pd from gamestonk_terminal.helper_funcs import ( check_positive, parse_known_args_and_warn, diff --git a/gamestonk_terminal/due_diligence/finra_view.py b/gamestonk_terminal/due_diligence/finra_view.py index baa7884dcea..8182e376cb1 100644 --- a/gamestonk_terminal/due_diligence/finra_view.py +++ b/gamestonk_terminal/due_diligence/finra_view.py @@ -200,7 +200,8 @@ def plot_dark_pools(ticker: str, ats: pd.DataFrame, otc: pd.DataFrame): otc : pd.DataFrame OTC (Non-ATS) Data """ - _, axData = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + + _, _ = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) plt.subplot(3, 1, (1, 2)) if not ats.empty and not otc.empty: diff --git a/gamestonk_terminal/portfolio/port_controller.py b/gamestonk_terminal/portfolio/port_controller.py index d6d5265789e..e9d6b0c1fea 100644 --- a/gamestonk_terminal/portfolio/port_controller.py +++ b/gamestonk_terminal/portfolio/port_controller.py @@ -4,6 +4,7 @@ import argparse from typing import List import pandas as pd 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 @@ -15,6 +16,7 @@ from gamestonk_terminal.portfolio.portfolio_helpers import ( class PortfolioController: + """ Portfolio Controller """ CHOICES = [ "help", @@ -129,6 +131,7 @@ class PortfolioController: if broker in self.BROKERS: api = broker + "_api" try: + # pylint: disable=eval-used eval(api + ".login()") self.broker_list.add(broker) logged_in = True @@ -179,7 +182,9 @@ class PortfolioController: print("Login to desired brokers\n") for broker in self.broker_list: holdings = pd.concat( - [holdings, eval(broker + "_api.return_holdings()")], axis=0 + # pylint: disable=eval-used + [holdings, eval(broker + "_api.return_holdings()")], + axis=0, ) self.merged_holdings = merge_portfolios(holdings) print_portfolio(self.merged_holdings) diff --git a/gamestonk_terminal/portfolio_optimization/optimizer_helper.py b/gamestonk_terminal/portfolio_optimization/optimizer_helper.py index f88ad80463c..8236d01b789 100644 --- a/gamestonk_terminal/portfolio_optimization/optimizer_helper.py +++ b/gamestonk_terminal/portfolio_optimization/optimizer_helper.py @@ -1,4 +1,4 @@ -""" Portfolio Optimization Helper Functions""" +""" Portfolio Optimization Helper Functions """ __docformat__ = "numpy" import argparse @@ -110,12 +110,12 @@ l_valid_property_infos = [ ] -def check_valid_property_type(property: str) -> str: +def check_valid_property_type(aproperty: str) -> str: """ Check that the property selected is valid """ - if property in l_valid_property_infos: - return property - else: - raise argparse.ArgumentTypeError(f"{property} is not a valid info") + if aproperty in l_valid_property_infos: + return aproperty + + raise argparse.ArgumentTypeError(f"{aproperty} is not a valid info") def process_stocks(list_of_stocks: List[str], period: str = "3mo") -> pd.DataFrame: @@ -133,6 +133,7 @@ def process_stocks(list_of_stocks: List[str], period: str = "3mo") -> pd.DataFra stock_closes: DataFrame DataFrame containing daily (adjusted) close prices for each stock in list """ + stock_prices = yf.download( list_of_stocks, period=period, progress=False, group_by="ticker" ) @@ -155,6 +156,7 @@ def prepare_efficient_frontier(stock_prices: pd.DataFrame): ef: EfficientFrontier EfficientFrontier object """ + mu = expected_returns.mean_historical_return(stock_prices) S = risk_models.sample_cov(stock_prices) ef = EfficientFrontier(mu, S) @@ -162,13 +164,14 @@ def prepare_efficient_frontier(stock_prices: pd.DataFrame): def display_weights(weights: dict): - """ - Print weights in a nice format + """Print weights in a nice format + Parameters ---------- weights: dict weights to display. Keys are stocks. Values are either weights or values if -v specified """ + if not weights: return weight_df = pd.DataFrame.from_dict(data=weights, orient="index", columns=["value"]) @@ -185,8 +188,8 @@ def my_autopct(x): """Function for autopct of plt.pie. This results in values not being printed in the pie if they are 'too small'""" if x > 4: return f"{x:.2f} %" - else: - return "" + + return "" def pie_chart_weights(weights: dict, title_opt: str): diff --git a/gamestonk_terminal/portfolio_optimization/optimizer_view.py b/gamestonk_terminal/portfolio_optimization/optimizer_view.py index 6c61666d5bf..884bea7c578 100644 --- a/gamestonk_terminal/portfolio_optimization/optimizer_view.py +++ b/gamestonk_terminal/portfolio_optimization/optimizer_view.py @@ -122,12 +122,8 @@ def property_weighting(stocks: List[str], other_args: List[str]): List of tickers to be included in optimization other_args : List[str] Command line arguments to be processed with argparse - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers """ + parser = argparse.ArgumentParser( add_help=False, prog="property", @@ -136,7 +132,7 @@ def property_weighting(stocks: List[str], other_args: List[str]): parser.add_argument( "-p", "--property", - required=True if "-h" not in other_args else False, + required=bool("-h" not in other_args), type=check_valid_property_type, dest="property", help="""Property info to weigh. Use one of: @@ -217,19 +213,16 @@ def property_weighting(stocks: List[str], other_args: List[str]): def max_sharpe(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that maximises the Sharpe Ratio + """Return a portfolio that maximises the Sharpe Ratio Parameters ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="maxsharpe", description="Maximise the Sharpe Ratio" ) @@ -273,7 +266,7 @@ def max_sharpe(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -309,19 +302,16 @@ def max_sharpe(stocks: List[str], other_args: List[str]): def min_volatility(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that optimizes for minimum volatility + """Return a portfolio that optimizes for minimum volatility Parameters ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="min_volatility", @@ -354,7 +344,7 @@ def min_volatility(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -390,19 +380,16 @@ def min_volatility(stocks: List[str], other_args: List[str]): def max_quadratic_utility(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that maximises the quadratic utility, given some risk aversion + """Return a portfolio that maximises the quadratic utility, given some risk aversion Parameters ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="max_quadratic_utility", @@ -458,7 +445,7 @@ def max_quadratic_utility(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -499,20 +486,15 @@ def max_quadratic_utility(stocks: List[str], other_args: List[str]): def efficient_risk(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that maximises return for a target risk. The resulting portfolio will have - a volatility less than the target (but not guaranteed to be equal) + """Return a portfolio that maximises return for a target risk. The resulting portfolio will have + a volatility less than the target (but not guaranteed to be equal) - Parameters - ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="effrisk", @@ -568,7 +550,7 @@ def efficient_risk(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -609,19 +591,16 @@ def efficient_risk(stocks: List[str], other_args: List[str]): def efficient_return(stocks: List[str], other_args: List[str]): - """ - Return a portfolio that minimises volatility for a given target return ('Markowitz portfolio') + """Displays a portfolio that minimises volatility for a given target return ('Markowitz portfolio') Parameters ---------- - stocks: List[str] + stocks : List[str] List of the stocks to be included in the weights - - Returns - ------- - weights: dict - Dictionary of weights where keys are the tickers. + other_args : List[str] + argparse other args """ + parser = argparse.ArgumentParser( add_help=False, prog="effret", @@ -676,7 +655,7 @@ def efficient_return(stocks: List[str], other_args: List[str]): try: ns_parser = parse_known_args_and_warn(parser, other_args) if not ns_parser: - return None + return if len(stocks) < 2: print("Please have at least 2 loaded tickers to calculate weights.\n") @@ -717,6 +696,16 @@ def efficient_return(stocks: List[str], other_args: List[str]): def show_ef(stocks: List[str], other_args: List[str]): + """Display efficient frontier + + Parameters + ---------- + stocks : List[str] + List of the stocks to be included in the weights + other_args : List[str] + argparse other args + """ + parser = argparse.ArgumentParser( add_help=False, prog="ef", @@ -756,7 +745,7 @@ def show_ef(stocks: List[str], other_args: List[str]): mu = expected_returns.mean_historical_return(stock_prices) S = risk_models.sample_cov(stock_prices) ef = EfficientFrontier(mu, S) - fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) # Generate random portfolios n_samples = ns_parser.n_port diff --git a/gamestonk_terminal/portfolio_optimization/po_controller.py b/gamestonk_terminal/portfolio_optimization/po_controller.py index c66ca63e846..c4345e8b386 100644 --- a/gamestonk_terminal/portfolio_optimization/po_controller.py +++ b/gamestonk_terminal/portfolio_optimization/po_controller.py @@ -1,7 +1,6 @@ -"""Portfolio Optimization Controller Module""" +""" Portfolio Optimization Controller Module """ __docformat__ = "numpy" - import argparse from typing import List import matplotlib.pyplot as plt @@ -34,6 +33,7 @@ class PortfolioOptimization: "yolo", ] + # pylint: disable=dangerous-default-value def __init__(self, tickers: List[str] = []): """ Construct Portfolio Optimization @@ -113,12 +113,12 @@ class PortfolioOptimization: def call_add(self, other_args: List[str]): """Process add command""" - self.add_stocks(self, other_args) + self.add_stocks(other_args) def call_select(self, other_args: List[str]): """Process select command""" self.tickers = [] - self.add_stocks(self, other_args) + self.add_stocks(other_args) def call_equal(self, other_args: List[str]): """Process equal command""" @@ -168,7 +168,6 @@ class PortfolioOptimization: print({"GME": 200}) print("") - @staticmethod def add_stocks(self, other_args: List[str]): """ Add ticker or Select tickes for portfolio to be optimized """ parser = argparse.ArgumentParser( diff --git a/gamestonk_terminal/prediction_techniques/ets.py b/gamestonk_terminal/prediction_techniques/ets.py index 96e17306d78..c26e6f28a5a 100644 --- a/gamestonk_terminal/prediction_techniques/ets.py +++ b/gamestonk_terminal/prediction_techniques/ets.py @@ -5,6 +5,7 @@ import numpy as np import pandas as pd from pandas.plotting import register_matplotlib_converters from statsmodels.tsa.holtwinters import ExponentialSmoothing + from gamestonk_terminal.helper_funcs import ( check_positive, parse_known_args_and_warn, @@ -18,19 +19,18 @@ from gamestonk_terminal.prediction_techniques.pred_helper import ( price_prediction_backtesting_color, print_prediction_kpis, ) - from gamestonk_terminal.config_plot import PLOT_DPI from gamestonk_terminal import feature_flags as gtff register_matplotlib_converters() -trend = "Ad" # Additive damped, A Additive, N None -seasonal = "N" # None, A Additive, M Multiplicative -seasonal_periods = 5 +# trend = "Ad" # Additive damped, A Additive, N None +# seasonal = "N" # None, A Additive, M Multiplicative +# seasonal_periods = 5 def check_valid_trend(trend: str) -> str: - if trend == "N" or trend == "A" or trend == "Ad": + if trend in ("N", "A", "Ad"): return trend raise argparse.ArgumentTypeError( "Invalid trend selected. Choose between 'N', 'A', and 'Ad'" @@ -38,7 +38,7 @@ def check_valid_trend(trend: str) -> str: def check_valid_seasonal(seasonal: str) -> str: - if seasonal == "N" or seasonal == "A" or seasonal == "M": + if seasonal in ("N", "A", "M"): return seasonal raise argparse.ArgumentTypeError( "Invalid seasonal selected. Choose between 'N', 'A', and 'M'" diff --git a/gamestonk_terminal/prediction_techniques/neural_networks.py b/gamestonk_terminal/prediction_techniques/neural_networks.py index 2e7d63e5db6..d0489619576 100644 --- a/gamestonk_terminal/prediction_techniques/neural_networks.py +++ b/gamestonk_terminal/prediction_techniques/neural_networks.py @@ -408,27 +408,6 @@ def _plot_and_print_results( ) plt.plot(df_pred.index, df_pred[df_pred.columns[0]], lw=2, c="tab:green") else: - """ - # Looks too noisy to output all loops predictions - for idx_loop in range(ns_parser.n_loops): - plt.plot( - [df_stock.index[-1], df_pred.index[0]], - [ - df_stock["5. adjusted close"].values[-1], - df_pred[df_pred.columns[idx_loop]].values[0], - ], - lw=0.5, - c="tab:green", - linestyle="--", - ) - plt.plot( - df_pred.index, - df_pred[df_pred.columns[idx_loop]], - lw=1, - ls="--", - c="tab:green", - ) - """ df_quantiles = pd.DataFrame() df_quantiles["Quantile 10%"] = df_pred.quantile(0.1, axis=1) df_quantiles["Median"] = df_pred.quantile(0.5, axis=1) diff --git a/gamestonk_terminal/prediction_techniques/pred_controller.py b/gamestonk_terminal/prediction_techniques/pred_controller.py index 8d2bdb4b2be..2ca6c8e6443 100644 --- a/gamestonk_terminal/prediction_techniques/pred_controller.py +++ b/gamestonk_terminal/prediction_techniques/pred_controller.py @@ -1,8 +1,10 @@ import argparse from typing import List -import pandas as pd from datetime import datetime +import pandas as pd import matplotlib.pyplot as plt +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 @@ -14,7 +16,6 @@ from gamestonk_terminal.prediction_techniques import ( regression, sma, ) -from prompt_toolkit.completion import NestedCompleter class PredictionTechniquesController: @@ -59,7 +60,6 @@ class PredictionTechniquesController: choices=self.CHOICES, ) - @staticmethod def print_help(self): """ Print help """ @@ -110,7 +110,7 @@ class PredictionTechniquesController: def call_help(self, _): """Process Help command""" - self.print_help(self) + self.print_help() def call_q(self, _): """Process Q command - quit the menu""" @@ -170,6 +170,7 @@ class PredictionTechniquesController: def call_prophet(self, other_args: List[str]): """Process prophet command""" + # pylint: disable=import-outside-toplevel from gamestonk_terminal.prediction_techniques import fbprophet fbprophet.fbprophet(other_args, self.ticker, self.stock) diff --git a/gamestonk_terminal/prediction_techniques/pred_helper.py b/gamestonk_terminal/prediction_techniques/pred_helper.py index 43aba435f39..c69ac5f0616 100644 --- a/gamestonk_terminal/prediction_techniques/pred_helper.py +++ b/gamestonk_terminal/prediction_techniques/pred_helper.py @@ -1,13 +1,14 @@ import numpy as np import pandas as pd from colorama import Fore, Style -from gamestonk_terminal import feature_flags as gtff from sklearn.metrics import ( mean_absolute_error, r2_score, mean_squared_error, ) +from gamestonk_terminal import feature_flags as gtff + def price_prediction_color(val: float, last_val: float) -> str: if float(val) > last_val: diff --git a/gamestonk_terminal/technical_analysis/finviz_view.py b/gamestonk_terminal/technical_analysis/finviz_view.py index 0fc3f794356..1e74144ca48 100644 --- a/gamestonk_terminal/technical_analysis/finviz_view.py +++ b/gamestonk_terminal/technical_analysis/finviz_view.py @@ -3,10 +3,11 @@ __docformat__ = "numpy" import argparse from typing import List -from gamestonk_terminal.helper_funcs import parse_known_args_and_warn from finvizfinance.quote import finvizfinance from PIL import Image +from gamestonk_terminal.helper_funcs import parse_known_args_and_warn + def view(other_args: List[str], ticker: str): """View historical price with trendlines. [Source: Finviz] diff --git a/gamestonk_terminal/technical_analysis/overlap.py b/gamestonk_terminal/technical_analysis/overlap.py index 7509c0ce2f3..a6c4b5d971a 100644 --- a/gamestonk_terminal/technical_analysis/overlap.py +++ b/gamestonk_terminal/technical_analysis/overlap.py @@ -69,7 +69,7 @@ def ema(l_args, s_ticker, s_interval, df_stock): offset=ns_parser.n_offset, ).dropna() - _, axPrice = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + _, _ = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) plt.title(f"{ns_parser.n_length} EMA on {s_ticker}") if s_interval == "1440min": plt.plot( diff --git a/gamestonk_terminal/technical_analysis/ta_controller.py b/gamestonk_terminal/technical_analysis/ta_controller.py index 7362b2edb26..620e13ab55f 100644 --- a/gamestonk_terminal/technical_analysis/ta_controller.py +++ b/gamestonk_terminal/technical_analysis/ta_controller.py @@ -3,10 +3,12 @@ __docformat__ = "numpy" import argparse import os -import pandas as pd from typing import List from datetime import datetime +import pandas as pd import matplotlib.pyplot as plt +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 @@ -18,7 +20,6 @@ from gamestonk_terminal.technical_analysis import volume as ta_volume from gamestonk_terminal.technical_analysis import finbrain_view from gamestonk_terminal.technical_analysis import tradingview_view from gamestonk_terminal.technical_analysis import finviz_view -from prompt_toolkit.completion import NestedCompleter class TechnicalAnalysisController: @@ -65,7 +66,6 @@ class TechnicalAnalysisController: choices=self.CHOICES, ) - @staticmethod def print_help(self): """Print help""" @@ -106,7 +106,6 @@ class TechnicalAnalysisController: print(" ad chaikin accumulation/distribution line values") print(" obv on balance volume") print("") - return def switch(self, an_input: str): """Process and dispatch input @@ -118,6 +117,7 @@ class TechnicalAnalysisController: True - quit the program None - continue in the menu """ + (known_args, other_args) = self.ta_parser.parse_known_args(an_input.split()) # Due to Finviz implementation of Spectrum, we delete the generated spectrum figure @@ -134,7 +134,7 @@ class TechnicalAnalysisController: def call_help(self, _): """Process Help command""" - self.print_help(self) + self.print_help() def call_q(self, _): """Process Q command - quit the menu""" diff --git a/gamestonk_terminal/technical_analysis/tradingview_view.py b/gamestonk_terminal/technical_analysis/tradingview_view.py index 61d2faf0723..b2f1668dfb4 100644 --- a/gamestonk_terminal/technical_analysis/tradingview_view.py +++ b/gamestonk_terminal/technical_analysis/tradingview_view.py @@ -2,8 +2,9 @@ import argparse from typing import List import requests import pandas as pd -from gamestonk_terminal import config_terminal as cfg from tradingview_ta import TA_Handler + +from gamestonk_terminal import config_terminal as cfg from gamestonk_terminal.helper_funcs import ( parse_known_args_and_warn, ) diff --git a/terminal.py b/terminal.py index 28c7d7c641c..ed0ff2cbbfe 100644 --- a/terminal.py +++ b/terminal.py @@ -33,13 +33,7 @@ from gamestonk_terminal.cryptocurrency import crypto_controller from gamestonk_terminal.screener import screener_controller from gamestonk_terminal.portfolio_optimization import po_controller -# import warnings -# warnings.simplefilter("always") - - -# pylint: disable=too-many-branches - - +# pylint: disable=too-many-statements,too-many-branches def main(): """ Gamestonk Terminal is an awesome stock market terminal that has been developed for fun, @@ -361,9 +355,9 @@ def main(): if b_quit: break - else: - if not main_cmd: - should_print_help = True + + if not main_cmd: + should_print_help = True print( "Hope you enjoyed the terminal. Remember that stonks only go up. Diamond hands.\n" From 31076e9c4ab34a0e5802ab6f1ea0f86dfe577fbc Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 20 Apr 2021 22:30:30 -0700 Subject: [PATCH 097/114] Adding extra line --- terminal.py | 1 + 1 file changed, 1 insertion(+) diff --git a/terminal.py b/terminal.py index ed0ff2cbbfe..78e912c761d 100644 --- a/terminal.py +++ b/terminal.py @@ -33,6 +33,7 @@ from gamestonk_terminal.cryptocurrency import crypto_controller from gamestonk_terminal.screener import screener_controller from gamestonk_terminal.portfolio_optimization import po_controller + # pylint: disable=too-many-statements,too-many-branches def main(): """ From 0265a4f78c3a4b0954dac1d4cc8c0d00f90e73f3 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 21 Apr 2021 15:35:19 -0400 Subject: [PATCH 098/114] fix test --- tests/test_coingecko_crypto.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_coingecko_crypto.py b/tests/test_coingecko_crypto.py index 003b5927f8b..e0eed2eed55 100644 --- a/tests/test_coingecko_crypto.py +++ b/tests/test_coingecko_crypto.py @@ -8,7 +8,7 @@ from gamestonk_terminal.cryptocurrency.pycoingecko_view import load class TestCoinGeckoAPI(TestCase): @mock.patch( - "gamestonk_terminal.cryptocurrency.coin_api.CoinGeckoAPI.get_coin_market_chart_by_id" + "gamestonk_terminal.cryptocurrency.pycoingecko_view.CoinGeckoAPI.get_coin_market_chart_by_id" ) def test_coin_api_load(self, mock_load): """ From 4a32b3a8b418059050b696bed83652fabfd7282f Mon Sep 17 00:00:00 2001 From: DJ Date: Wed, 21 Apr 2021 15:07:54 -0600 Subject: [PATCH 099/114] run linter --- terminal.py | 1 - 1 file changed, 1 deletion(-) diff --git a/terminal.py b/terminal.py index 1ad32666dac..368f078bcc3 100644 --- a/terminal.py +++ b/terminal.py @@ -35,7 +35,6 @@ from gamestonk_terminal.portfolio_optimization import po_controller from gamestonk_terminal.forex import fx_controller - # pylint: disable=too-many-statements,too-many-branches def main(): """ From 04330f2e3cc15837c521bcf070230a4538493d42 Mon Sep 17 00:00:00 2001 From: DJ Date: Wed, 21 Apr 2021 15:23:06 -0600 Subject: [PATCH 100/114] run poetry --- poetry.lock | 50 ++++++++++++++++++++++++++----- pyproject.toml | 1 + requirements-full.txt | 68 ++++++++++--------------------------------- requirements.txt | 3 +- 4 files changed, 61 insertions(+), 61 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1c9dc7b56d1..a5b4f1f7f8e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -837,7 +837,7 @@ idna = ">=2.0" [[package]] name = "importlib-metadata" -version = "4.0.0" +version = "4.0.1" description = "Read metadata from Python packages" category = "main" optional = false @@ -1496,6 +1496,14 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "oandapyv20" +version = "0.6.3" +description = "Python wrapper for the OANDA REST-V20 API" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "oauthlib" version = "3.1.0" @@ -2099,7 +2107,7 @@ python-versions = "*" [[package]] name = "pyupgrade" -version = "2.12.0" +version = "2.13.0" description = "A tool to automatically upgrade syntax for newer versions." category = "dev" optional = false @@ -2954,7 +2962,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "fa7c02ebec2d14a1c42f76f8e1328134975893c5f98afa879f2bc672675d6a7f" +content-hash = "2b31cd4c709b83d1a6f1d516036c84dc611cc487ae5d499905658454fa8dba40" [metadata.files] absl-py = [ @@ -3287,30 +3295,51 @@ entrypoints = [ ] ephem = [ {file = "ephem-3.7.7.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:0a6d6ed003383f702695094399728052981c567d423b25aa7163b3fd40de3d5a"}, + {file = "ephem-3.7.7.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3cbc4f643329c4f64de63584e636625fa9f11b50209386ed99cbf508abe19488"}, {file = "ephem-3.7.7.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e73b9997d7b844fabff988d7f66c3bad4e76ec8975ec9c60ec988037bb5c04b1"}, {file = "ephem-3.7.7.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:7619297a1103f6b3dac0c609bfa7c31e17678fb1a02653347ec030487e412031"}, + {file = "ephem-3.7.7.1-cp27-cp27m-win32.whl", hash = "sha256:7756218a8b72ca50ee4f290b80828073412e7d7023389df5ead5d14839175bda"}, + {file = "ephem-3.7.7.1-cp27-cp27m-win_amd64.whl", hash = "sha256:b8f9fb5b4184523b98f6629c6c927aeeba80d61df21f07af2844cdae45e1a294"}, {file = "ephem-3.7.7.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:37fd1abbebb821381d2865064a6fa9484ffdcd2161cf92193da8d42da79aa7db"}, {file = "ephem-3.7.7.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ff4e1584cc232d8bc4aea405346eeb8a24b0fbe84c6331d4edb5d4456d19f1c3"}, {file = "ephem-3.7.7.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:c6081a9791e9de6511cddbeb9529bd5550fdb6f9e2a8dc9c2ec85911d67c6d11"}, + {file = "ephem-3.7.7.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d1d1ac8dc9be47dc6c7ec62800ca6557d03e8be3716c2a10ea0c8f1198c0a701"}, {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:7f781d73e49caf7989c503a948471f1c8c1f738a450d557413999fb732f4dba3"}, {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f0959882bf73c8fe1cb801f42b0989e0ecb9d84b99eb8b8f70d61d16767a1e8a"}, + {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:06029db6b26f1764ed009360de8530f6cd759411232b3001df1b69ba6afa871d"}, + {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2014_s390x.whl", hash = "sha256:562baaeb3a46cf2248f97d2ad80092d747024e5dea62ebe50386a04b8e506c10"}, {file = "ephem-3.7.7.1-cp35-cp35m-win32.whl", hash = "sha256:2bcd953cced045e4232bcb71d60f6ba237f7944c880e83e74cc959449b192dee"}, {file = "ephem-3.7.7.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fd0b922387df1ad8721f2fafd5dca51ce7105238f968e1532a177b781b8cae0e"}, {file = "ephem-3.7.7.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:e10c2c8afbb9e927d46d9bf3562441da2173ff196790a75ad0e5c5ee920d5922"}, + {file = "ephem-3.7.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:592264e512b5658402e93903343eb26502c6f327df8a71847f3dcaea73908f32"}, {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:8d586d970c42d62b1fc757a1c7c10679416a43e9e4a77391a05907159ce346f8"}, {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1a8ea6a045ff669011f8ecdeffadfc5eaa519fb56ab8dd40508910e9db5ec7b0"}, + {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c25993d6554820ff11fdd8f2ddb75bf99e70db01327f09700bf8811201e9daef"}, + {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:9180d953ff4cbe89fc9ccc78aea73f290c0166b8ddb01e9c837b4639a7492ec8"}, {file = "ephem-3.7.7.1-cp36-cp36m-win32.whl", hash = "sha256:72fdb72c813fc9780726aa732eb2193bbe1663549265ca5a746899215ecfbffd"}, {file = "ephem-3.7.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f5af029f8814aa8617e73b2ddcad2bd1c682ca13c31ee3b6f5825dd5cb43e777"}, {file = "ephem-3.7.7.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:e61c68f1c7d304a130bb6b88c1fca6600bbc1a1df6ca9a109b6eba4c6cbd3376"}, + {file = "ephem-3.7.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fdf5f3ed8bd46ce2bf1145b26aec65a2c08ea7c97cf42b6b439af6e7bc6dc94d"}, {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:31e2a17ca6f8d6bd44832574fea5461938ba034e52bf551e15e1a4c8f8c6c4fb"}, {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:1ff5abefa230d5ab40846f1cb27d4f5583d46044fecf10e17bfb559bdc766a47"}, + {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:5ef34e3cfea0683998e867d7b8de642081e8821fafbd5e1d2dcab503c119c4a2"}, + {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:e2aca9edb59ee2bb3c8c36f17177966bc762da04af994450c8ad61a20fb6acdd"}, {file = "ephem-3.7.7.1-cp37-cp37m-win32.whl", hash = "sha256:71ea3935c658ee184575fd4cc2aa3e7fd6d6bac4a1ccff9ee5549cee67ff0385"}, {file = "ephem-3.7.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:34fd228105b89fefd20608420861a75a184db1edeaf0056cf2f85d2a2f768aee"}, {file = "ephem-3.7.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:189fcaeacb44dc5a1684ad489542f126d99d4a85e87d2fe73864c902f0bc2c71"}, {file = "ephem-3.7.7.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a5ddf46ced515e4b81dfd22e6408fd06a329c31c6abb10af48d392641c490b0e"}, {file = "ephem-3.7.7.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:3530bee3eb7458d86d4c399f51f5b73ad7ea0441f0b2fb03de41d623789935af"}, + {file = "ephem-3.7.7.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:77193de077e5fff453756144dee978e5fd6978c5c03ce3f67a09bb237e78f9d4"}, + {file = "ephem-3.7.7.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:095ad42e8df6a5c91e0aeb5a68d76c0800b0283f72fc5f76e6df370ae1fb5537"}, {file = "ephem-3.7.7.1-cp38-cp38-win32.whl", hash = "sha256:33ad1a71b204aff123250b04e0ff2d5c3b8e9c6c814bf2c675d7752ce5896c02"}, {file = "ephem-3.7.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:4bc5140cc7218a53ee6d949110f6ed413b8e3165294100515cd0fb29aa8e3637"}, + {file = "ephem-3.7.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7aa88d2a6d216c2044be2a3b3cb184e9c8a5022f12464220694017ea9d75209d"}, + {file = "ephem-3.7.7.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:1a9822bde93205c67fd3399b26868204b67d9e4442af21a764307e51ea6dc672"}, + {file = "ephem-3.7.7.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:15dd3dbb3864fb853388e39ac3c915c72873507f54ee6b3ede0033b03465d8ba"}, + {file = "ephem-3.7.7.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5763919cdf38cd0488172711da504c3be003b7c104ccd2516cc496ff05f146ae"}, + {file = "ephem-3.7.7.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:cdea23a7caa1178b322e6e76484d40bd021672446ff51b512f35581e0f1b32b7"}, + {file = "ephem-3.7.7.1-cp39-cp39-win32.whl", hash = "sha256:c3cbc973b334892972445cec3deb99aafd0c57cb4e50679d5f12fc8c51b4e65f"}, + {file = "ephem-3.7.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:1af920c382980fe3566a31f36bd712973e1ca6049cbe07b4624214d5e1f144bc"}, {file = "ephem-3.7.7.1.tar.gz", hash = "sha256:36b51a8dc7cfdeb456dd6b8ab811accab8341b2d562ee3c6f4c86f6d3dbb984e"}, ] fbprophet = [ @@ -3491,8 +3520,8 @@ idna-ssl = [ {file = "idna-ssl-1.1.0.tar.gz", hash = "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.0.0-py3-none-any.whl", hash = "sha256:19192b88d959336bfa6bdaaaef99aeafec179eca19c47c804e555703ee5f07ef"}, - {file = "importlib_metadata-4.0.0.tar.gz", hash = "sha256:2e881981c9748d7282b374b68e759c87745c25427b67ecf0cc67fb6637a1bff9"}, + {file = "importlib_metadata-4.0.1-py3-none-any.whl", hash = "sha256:d7eb1dea6d6a6086f8be21784cc9e3bcfa55872b52309bc5fad53a8ea444465d"}, + {file = "importlib_metadata-4.0.1.tar.gz", hash = "sha256:8c501196e49fb9df5df43833bdb1e4328f64847763ec8a50703148b73784d581"}, ] inflection = [ {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, @@ -3955,6 +3984,9 @@ numpy = [ {file = "numpy-1.19.5-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73"}, {file = "numpy-1.19.5.zip", hash = "sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4"}, ] +oandapyv20 = [ + {file = "oandapyV20-0.6.3.tar.gz", hash = "sha256:173a56b41ab3a19315c2fbea6f9aa3f0c17f64ba84acff014d072c64c1844b28"}, +] oauthlib = [ {file = "oauthlib-3.1.0-py2.py3-none-any.whl", hash = "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea"}, {file = "oauthlib-3.1.0.tar.gz", hash = "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889"}, @@ -4305,8 +4337,8 @@ pytz = [ {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, ] pyupgrade = [ - {file = "pyupgrade-2.12.0-py2.py3-none-any.whl", hash = "sha256:024fc6be99c2ccdbc1c9354ac0ab8d5b9e5bf69a5477384677b6c9d8f2ce63bf"}, - {file = "pyupgrade-2.12.0.tar.gz", hash = "sha256:eef4d77e44e57dfbae897a9a61543be1f34701dbbe51cc18462210021bd28dcf"}, + {file = "pyupgrade-2.13.0-py2.py3-none-any.whl", hash = "sha256:1cb5a15573fc63824b952bf7dde5b96f9672a1179ec779ac2d159a845da743c8"}, + {file = "pyupgrade-2.13.0.tar.gz", hash = "sha256:dc6b580b7bc82f357acb354bbba03d8d69da51425ecd5993a2651059bca80518"}, ] pywin32 = [ {file = "pywin32-300-cp35-cp35m-win32.whl", hash = "sha256:1c204a81daed2089e55d11eefa4826c05e604d27fe2be40b6bf8db7b6a39da63"}, @@ -4563,6 +4595,7 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c658432d8a20e95398f6bb95ff9731ce9dfa343fdf21eea7ec6a7edfacd4b4d9"}, {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9dfa564ef27e8e674aa1cc74378416d580ac4ede1136c13dd555a87996e13422"}, {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:9c6097b6a9b2bafc5e0f31f659e6ab5e131383209c30c9e978c5b8abdac5ed2a"}, + {file = "scikit_learn-0.24.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:5580eba7345a4d3b097be2f067cc71a306c44bab19e8717a30361f279c929bea"}, {file = "scikit_learn-0.24.1-cp36-cp36m-win32.whl", hash = "sha256:7b04691eb2f41d2c68dbda8d1bd3cb4ef421bdc43aaa56aeb6c762224552dfb6"}, {file = "scikit_learn-0.24.1-cp36-cp36m-win_amd64.whl", hash = "sha256:1adf483e91007a87171d7ce58c34b058eb5dab01b5fee6052f15841778a8ecd8"}, {file = "scikit_learn-0.24.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:ddb52d088889f5596bc4d1de981f2eca106b58243b6679e4782f3ba5096fd645"}, @@ -4570,6 +4603,7 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0567a2d29ad08af98653300c623bd8477b448fe66ced7198bef4ed195925f082"}, {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:99349d77f54e11f962d608d94dfda08f0c9e5720d97132233ebdf35be2858b2d"}, {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:83b21ff053b1ff1c018a2d24db6dd3ea339b1acfbaa4d9c881731f43748d8b3b"}, + {file = "scikit_learn-0.24.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:abe835a851610f87201819cb315f8d554e1a3e8128912783a31e87264ba5ffb7"}, {file = "scikit_learn-0.24.1-cp37-cp37m-win32.whl", hash = "sha256:c3deb3b19dd9806acf00cf0d400e84562c227723013c33abefbbc3cf906596e9"}, {file = "scikit_learn-0.24.1-cp37-cp37m-win_amd64.whl", hash = "sha256:d54dbaadeb1425b7d6a66bf44bee2bb2b899fe3e8850b8e94cfb9c904dcb46d0"}, {file = "scikit_learn-0.24.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:3c4f07f47c04e81b134424d53c3f5e16dfd7f494e44fd7584ba9ce9de2c5e6c1"}, @@ -4577,6 +4611,7 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:4ddd2b6f7449a5d539ff754fa92d75da22de261fd8fdcfb3596799fadf255101"}, {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:826b92bf45b8ad80444814e5f4ac032156dd481e48d7da33d611f8fe96d5f08b"}, {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:259ec35201e82e2db1ae2496f229e63f46d7f1695ae68eef9350b00dc74ba52f"}, + {file = "scikit_learn-0.24.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:9599a3f3bf33f73fed0fe06d1dfa4e6081365a58c1c807acb07271be0dce9733"}, {file = "scikit_learn-0.24.1-cp38-cp38-win32.whl", hash = "sha256:8772b99d683be8f67fcc04789032f1b949022a0e6880ee7b75a7ec97dbbb5d0b"}, {file = "scikit_learn-0.24.1-cp38-cp38-win_amd64.whl", hash = "sha256:ed9d65594948678827f4ff0e7ae23344e2f2b4cabbca057ccaed3118fdc392ca"}, {file = "scikit_learn-0.24.1-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:8aa1b3ac46b80eaa552b637eeadbbce3be5931e4b5002b964698e33a1b589e1e"}, @@ -4584,6 +4619,7 @@ scikit-learn = [ {file = "scikit_learn-0.24.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:087dfede39efb06ab30618f9ab55a0397f29c38d63cd0ab88d12b500b7d65fd7"}, {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:895dbf2030aa7337649e36a83a007df3c9811396b4e2fa672a851160f36ce90c"}, {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:9a24d1ccec2a34d4cd3f2a1f86409f3f5954cc23d4d2270ba0d03cf018aa4780"}, + {file = "scikit_learn-0.24.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:54be0a60a5a35005ad69c75902e0f5c9f699db4547ead427e97ef881c3242e6f"}, {file = "scikit_learn-0.24.1-cp39-cp39-win32.whl", hash = "sha256:fab31f48282ebf54dd69f6663cd2d9800096bad1bb67bbc9c9ac84eb77b41972"}, {file = "scikit_learn-0.24.1-cp39-cp39-win_amd64.whl", hash = "sha256:4562dcf4793e61c5d0f89836d07bc37521c3a1889da8f651e2c326463c4bd697"}, ] diff --git a/pyproject.toml b/pyproject.toml index a3bbf6762c7..45e9f245261 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ tabulate = "^0.8.9" pyportfolioopt = "^1.4.1" selenium = "^3.141.0" python-coinmarketcap = "^0.2" +oandapyV20 = "^0.6.3" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements-full.txt b/requirements-full.txt index 659e713d3c7..15e7172d368 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -5,7 +5,6 @@ ansiwrap==0.8.4; python_version >= "3.6" appdirs==1.4.4; python_version >= "3.6" appnope==0.1.2; platform_system == "Darwin" and python_version >= "3.6" and sys_platform == "darwin" argon2-cffi==20.1.0; python_version >= "3.6" -astunparse==1.6.3 async-generator==1.10; python_full_version >= "3.6.1" and python_version >= "3.6" async-timeout==3.0.1; python_full_version >= "3.5.3" and python_version >= "3.6" attrs==20.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" @@ -13,7 +12,6 @@ backcall==0.2.0; python_version >= "3.6" beautifulsoup4==4.9.3; python_version >= "3.5" black==20.8b1; python_version >= "3.6" bleach==3.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -bpemb==0.3.3; python_version >= "3.6" bs4==0.0.1 certifi==2020.12.5; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" cffi==1.14.5; implementation_name == "pypy" and python_version >= "3.6" @@ -26,38 +24,23 @@ cssselect==1.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or p cvxpy==1.1.12; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" cycler==0.10.0; python_version >= "3.6" cython==0.29.17; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "darwin" or python_full_version >= "3.3.0" and python_version >= "3.6" and sys_platform == "darwin" -dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.6.2" +dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" datetime==4.3; python_version >= "3.5" decorator==4.4.2; 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.2.0" and python_version >= "3.6") defusedxml==0.7.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -deprecated==1.2.12; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" detecta==0.0.5; python_version >= "3.6" ecos==2.0.7.post1; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" entrypoints==0.3; python_version >= "3.6" -ephem==3.7.7.1; python_version >= "2.7" and python_version < "4" -fbprophet==0.6 -filelock==3.0.12; python_full_version >= "3.6.0" and python_version >= "3.6" finviz==1.4.1 finvizfinance==0.9.6; python_version >= "3.5" -flair==0.7; python_version >= "3.6" -flatbuffers==1.12 fredapi==0.4.3 -ftfy==6.0.1; python_version >= "3.6" fundamentalanalysis==0.2.7 -future==0.18.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" -gast==0.3.3; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" -gdown==3.12.2; python_version >= "3.6" -gensim==3.8.2; python_version >= "3.6" -google-auth-oauthlib==0.4.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" -google-auth==1.29.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6" -google-pasta==0.2.0 -grpcio==1.32.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" h5py==2.10.0 hijri-converter==2.1.1; python_version >= "3.6" holidays==0.10.5.2 idna-ssl==1.1.0; python_version < "3.7" and python_version >= "3.6" idna==2.10; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version < "3.7" and python_version >= "3.6" and python_full_version >= "3.5.0" -importlib-metadata==4.0.0; python_version < "3.8" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_full_version >= "3.2.0" and python_version >= "3.6" and python_version < "3.8") +importlib-metadata==4.0.1; python_version < "3.8" and python_version >= "3.6" inflection==0.5.1; python_version >= "3.5" ipykernel==5.5.3; python_version >= "3.6" ipython-genutils==0.2.0; python_full_version >= "3.6.1" and python_version >= "3.6" @@ -66,6 +49,7 @@ ipywidgets==7.6.3 iso8601==0.1.14 jedi==0.18.0; python_version >= "3.6" jinja2==2.11.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +joblib==1.0.1; python_version >= "3.6" jsonschema==3.2.0; python_version >= "3.6" jupyter-client==6.2.0; python_full_version >= "3.6.1" and python_version >= "3.6" jupyter-console==6.4.0; python_version >= "3.6" @@ -74,17 +58,12 @@ jupyter==1.0.0 jupyterlab-pygments==0.1.2; python_version >= "3.6" jupyterlab-widgets==1.0.0; python_version >= "3.6" kiwisolver==1.3.1; python_version >= "3.6" -konoha==4.6.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" korean-lunar-calendar==0.2.1 -langdetect==1.0.8; python_version >= "3.6" -lunarcalendar==0.0.9; python_version >= "2.7" and python_version < "4" -lxml==4.6.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" -markdown==3.3.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" +lxml==4.6.3; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" markupsafe==1.1.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" matplotlib==3.3.4; python_version >= "3.6" mistune==0.8.4; python_version >= "3.6" more-itertools==8.7.0; python_version >= "3.5" -mpld3==0.3; python_version >= "3.6" mplfinance==0.12.7a12 msgpack==1.0.2 multidict==5.1.0; python_version >= "3.6" @@ -94,36 +73,33 @@ nbclient==0.5.3; python_full_version >= "3.6.1" and python_version >= "3.6" nbconvert==6.0.7; python_version >= "3.6" nbformat==5.1.3; python_full_version >= "3.6.1" and python_version >= "3.6" nest-asyncio==1.5.1; python_full_version >= "3.6.1" and python_version >= "3.6" -networkx==2.5.1; python_version >= "3.6" notebook==6.3.0; python_version >= "3.6" numpy==1.19.5; python_version >= "3.6" +oandapyv20==0.6.3 oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" -opt-einsum==3.3.0; python_version >= "3.5" osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" -overrides==3.1.0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.6" -packaging==20.9; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") +packaging==20.9; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" pandas-ta==0.2.45b pandas==1.1.5; python_full_version >= "3.6.1" pandocfilters==1.4.3; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" papermill==2.3.3; python_version >= "3.6" parso==0.8.2; python_version >= "3.6" pathspec==0.8.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" +patsy==0.5.1; python_version >= "3.6" pexpect==4.8.0; sys_platform != "win32" and python_version >= "3.6" pickleshare==0.7.5; python_version >= "3.6" pillow==8.2.0; python_version >= "3.6" plotly==4.14.3 +pmdarima==1.8.0; python_version >= "3.6" praw==7.2.0; python_version >= "3.6" and python_version < "4.0" prawcore==2.0.0; python_version >= "3.6" and python_version < "4.0" prettytable==2.1.0; python_version >= "3.6" prometheus-client==0.10.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" prompt-toolkit==3.0.18; python_full_version >= "3.6.1" -protobuf==3.15.8; python_full_version >= "3.6.0" and python_version >= "3.6" psaw==0.0.12; python_version >= "3" ptyprocess==0.7.0; os_name != "nt" and python_version >= "3.6" and sys_platform != "win32" py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" and implementation_name == "pypy" or implementation_name == "pypy" and python_version >= "3.6" and python_full_version >= "3.4.0" pyally==1.1.2 -pyasn1-modules==0.2.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.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" pygments==2.8.1; python_version >= "3.6" @@ -131,13 +107,12 @@ pymeeus==0.5.11; python_version >= "3.5" pyobjc-core==7.1; python_version >= "3.6" and sys_platform == "darwin" pyobjc-framework-cocoa==7.1; python_version >= "3.6" and sys_platform == "darwin" pyotp==2.6.0; python_version >= "3" -pyparsing==2.4.7; python_full_version >= "3.6.0" 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") +pyparsing==2.4.7; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" 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" -pystan==2.19.1.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-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" pytrends==4.7.3 pytz==2021.1; python_full_version >= "3.6.1" and python_version >= "3.5" @@ -151,47 +126,35 @@ qtpy==1.9.0; python_version >= "3.6" quandl==3.6.1; python_version >= "3.5" rapidfuzz==1.4.1; python_version >= "3.5" regex==2020.11.13 -requests-oauthlib==1.3.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" +requests-oauthlib==1.3.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" requests==2.25.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") retrying==1.3.3 robin-stocks==2.0.3; python_version >= "3" -rsa==4.7.2; 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") -sacremoses==0.0.45; python_full_version >= "3.6.0" and python_version >= "3.6" scikit-learn==0.24.1; python_version >= "3.6" scipy==1.5.4; python_version >= "3.6" screeninfo==0.6.7 scs==2.1.3; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" seaborn==0.11.1; python_version >= "3.6" -segtok==1.5.10; python_version >= "3.6" selenium==3.141.0 send2trash==1.5.0; python_version >= "3.6" -sentencepiece==0.1.91; python_full_version >= "3.6.0" and python_version >= "3.6" -setuptools-git==1.2 -six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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.6.0") and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") -smart-open==5.0.0; python_version >= "3.6" +six==1.15.0; python_full_version >= "3.6.1" 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 >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0") 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 >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6") soupsieve==2.2.1; python_version >= "3.6" -sqlitedict==1.7.0; python_version >= "3.6" statsmodels==0.12.2; python_version >= "3.6" tabulate==0.8.9 tenacity==7.0.0; python_version >= "3.6" -tensorboard-data-server==0.6.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" and python_version >= "3.6" -tensorboard-plugin-wit==1.8.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" -tensorboard==2.5.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.2.0" -tensorflow-estimator==2.4.0 -tensorflow==2.4.1 termcolor==1.1.0 terminado==0.9.4; python_version >= "3.6" testpath==0.4.4; python_version >= "3.6" textwrap3==0.9.2; python_version >= "3.6" +threadpoolctl==2.1.0; python_version >= "3.6" timeseriescrossvalidation @ git+https://github.com/DidierRLopes/TimeSeriesCrossValidation.git@master toml==0.10.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" tornado==6.1; python_full_version >= "3.6.1" and python_version >= "3.6" -tqdm==4.60.0; python_full_version >= "3.6.0" and python_version >= "3.6" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6") +tqdm==4.60.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" tradingview-ta==3.2.3; python_version >= "3.5" traitlets==4.3.3; python_full_version >= "3.6.1" and python_version >= "3.6" -transformers==3.5.1; python_full_version >= "3.6.0" typed-ast==1.4.3; python_version >= "3.6" -typing-extensions==3.7.4.3; python_full_version >= "3.6.2" and python_version >= "3.6" and python_version < "3.8" +typing-extensions==3.7.4.3; python_version < "3.8" and python_version >= "3.6" update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0" urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6" user-agent==0.1.9 @@ -199,7 +162,6 @@ wcwidth==0.2.5; python_version >= "3.6" and python_full_version >= "3.6.1" webencodings==0.5.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" websocket-client==0.58.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0" websockets==8.1; python_full_version >= "3.6.1" -werkzeug==1.0.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" widgetsnbextension==3.5.1 yarl==1.6.3; python_version >= "3.6" yfinance==0.1.59 diff --git a/requirements.txt b/requirements.txt index bf0985ecfa5..15e7172d368 100644 --- a/requirements.txt +++ b/requirements.txt @@ -40,7 +40,7 @@ hijri-converter==2.1.1; python_version >= "3.6" holidays==0.10.5.2 idna-ssl==1.1.0; python_version < "3.7" and python_version >= "3.6" idna==2.10; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version < "3.7" and python_version >= "3.6" and python_full_version >= "3.5.0" -importlib-metadata==4.0.0; python_version < "3.8" and python_version >= "3.6" +importlib-metadata==4.0.1; python_version < "3.8" and python_version >= "3.6" inflection==0.5.1; python_version >= "3.5" ipykernel==5.5.3; python_version >= "3.6" ipython-genutils==0.2.0; python_full_version >= "3.6.1" and python_version >= "3.6" @@ -75,6 +75,7 @@ nbformat==5.1.3; python_full_version >= "3.6.1" and python_version >= "3.6" nest-asyncio==1.5.1; python_full_version >= "3.6.1" and python_version >= "3.6" notebook==6.3.0; python_version >= "3.6" numpy==1.19.5; python_version >= "3.6" +oandapyv20==0.6.3 oauthlib==3.1.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" osqp==0.6.2.post0; python_full_version >= "3.6.1" and python_full_version < "4.0.0" and python_version >= "3.5" packaging==20.9; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" From 30847ffd4cc29a8d049877029d037abf9c1ff3c5 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Wed, 21 Apr 2021 22:25:25 -0700 Subject: [PATCH 101/114] Updating poetry action and version --- .github/workflows/test.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fceaff60738..52d673da809 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,8 +49,9 @@ jobs: architecture: x64 - name: Install Poetry - uses: snok/install-poetry@v1.1.1 + uses: snok/install-poetry@v1.1.4 with: + version: 1.1.6 virtualenvs-create: true virtualenvs-in-project: true @@ -102,8 +103,9 @@ jobs: architecture: x64 - name: Install Poetry - uses: snok/install-poetry@v1.1.1 + uses: snok/install-poetry@v1.1.4 with: + version: 1.1.6 virtualenvs-create: true virtualenvs-in-project: true From 0ee59c8439bef4f87eda9bad8ede6059021287d2 Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 22 Apr 2021 22:21:27 +0100 Subject: [PATCH 102/114] Add fa-score --- .../fundamental_analysis/fa_controller.py | 9 +++++ .../financial_modeling_prep_view.py | 35 +++++++++++++++++++ poetry.lock | 35 +++++++------------ pyproject.toml | 1 + requirements.txt | 1 + 5 files changed, 59 insertions(+), 22 deletions(-) diff --git a/gamestonk_terminal/fundamental_analysis/fa_controller.py b/gamestonk_terminal/fundamental_analysis/fa_controller.py index 2cad209fd82..5de204ab675 100644 --- a/gamestonk_terminal/fundamental_analysis/fa_controller.py +++ b/gamestonk_terminal/fundamental_analysis/fa_controller.py @@ -9,6 +9,7 @@ from gamestonk_terminal.fundamental_analysis import alpha_vantage_controller as from gamestonk_terminal.fundamental_analysis import business_insider_view as biw from gamestonk_terminal.fundamental_analysis import ( financial_modeling_prep_controller as fmpc, + financial_modeling_prep_view as fmpv, ) from gamestonk_terminal.fundamental_analysis import finviz_view from gamestonk_terminal.fundamental_analysis import market_watch_view @@ -26,6 +27,7 @@ class FundamentalAnalysisController: "help", "q", "quit", + "score", "screener", "income", "balance", @@ -83,6 +85,9 @@ class FundamentalAnalysisController: print("") print(" screener screen info about the company [Finviz]") print(" mgmt management team of the company [Business Insider]") + print( + " score investing score from Warren Buffett, Joseph Piotroski and Benjamin Graham [FMP]" + ) print("") print("Market Watch API") print(" income income statement of the company") @@ -137,6 +142,10 @@ class FundamentalAnalysisController: """ Process screener command """ finviz_view.screener(other_args, self.ticker) + def call_score(self, other_args: List[str]): + """ Process score command """ + fmpv.valinvest_score(other_args, self.ticker) + def call_income(self, other_args: List[str]): """ Process income command """ market_watch_view.income(other_args, self.ticker) diff --git a/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py b/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py index 68e22a86281..f5bda9f8a17 100644 --- a/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py +++ b/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_view.py @@ -5,6 +5,7 @@ import argparse from typing import List from datetime import datetime import pandas as pd +import valinvest import FundamentalAnalysis as fa # Financial Modeling Prep from gamestonk_terminal import config_terminal as cfg from gamestonk_terminal.dataframe_helpers import clean_df_index @@ -15,6 +16,40 @@ from gamestonk_terminal.helper_funcs import ( ) +def valinvest_score(other_args: List[str], ticker: str): + """Value investing tool based on Warren Buffett, Joseph Piotroski and Benjamin Graham thoughts [Source: FMP] + + Parameters + ---------- + other_args : List[str] + argparse other args + ticker : str + Fundamental analysis ticker symbol + """ + + parser = argparse.ArgumentParser( + add_help=False, + prog="score", + description=""" + Value investing tool based on Warren Buffett, Joseph Piotroski and Benjamin Graham thoughts [Source: FMP] + """, + ) + + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + valstock = valinvest.Fundamental(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) + score = 100 * (valstock.fscore() / 9) + print(f"Score: {score:.2f}".rstrip("0").rstrip(".") + " %") + print("") + + except Exception as e: + print(e, "\n") + return + + def profile(other_args: List[str], ticker: str): """Financial Modeling Prep ticker profile diff --git a/poetry.lock b/poetry.lock index a5b4f1f7f8e..d232c41a1fd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2837,6 +2837,14 @@ python-versions = "*" [package.dependencies] six = "*" +[[package]] +name = "valinvest" +version = "0.0.2" +description = "A value investing tool based on Warren Buffett, Joseph Piotroski and Benjamin Graham thoughts" +category = "main" +optional = false +python-versions = ">=3.6" + [[package]] name = "wcwidth" version = "0.2.5" @@ -2962,7 +2970,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "2b31cd4c709b83d1a6f1d516036c84dc611cc487ae5d499905658454fa8dba40" +content-hash = "2088d5cb7d1789cabe8d0f0f211ec599f56e630b4997527b9838d3ecf517f04c" [metadata.files] absl-py = [ @@ -3295,51 +3303,30 @@ entrypoints = [ ] ephem = [ {file = "ephem-3.7.7.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:0a6d6ed003383f702695094399728052981c567d423b25aa7163b3fd40de3d5a"}, - {file = "ephem-3.7.7.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3cbc4f643329c4f64de63584e636625fa9f11b50209386ed99cbf508abe19488"}, {file = "ephem-3.7.7.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e73b9997d7b844fabff988d7f66c3bad4e76ec8975ec9c60ec988037bb5c04b1"}, {file = "ephem-3.7.7.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:7619297a1103f6b3dac0c609bfa7c31e17678fb1a02653347ec030487e412031"}, - {file = "ephem-3.7.7.1-cp27-cp27m-win32.whl", hash = "sha256:7756218a8b72ca50ee4f290b80828073412e7d7023389df5ead5d14839175bda"}, - {file = "ephem-3.7.7.1-cp27-cp27m-win_amd64.whl", hash = "sha256:b8f9fb5b4184523b98f6629c6c927aeeba80d61df21f07af2844cdae45e1a294"}, {file = "ephem-3.7.7.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:37fd1abbebb821381d2865064a6fa9484ffdcd2161cf92193da8d42da79aa7db"}, {file = "ephem-3.7.7.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ff4e1584cc232d8bc4aea405346eeb8a24b0fbe84c6331d4edb5d4456d19f1c3"}, {file = "ephem-3.7.7.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:c6081a9791e9de6511cddbeb9529bd5550fdb6f9e2a8dc9c2ec85911d67c6d11"}, - {file = "ephem-3.7.7.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d1d1ac8dc9be47dc6c7ec62800ca6557d03e8be3716c2a10ea0c8f1198c0a701"}, {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:7f781d73e49caf7989c503a948471f1c8c1f738a450d557413999fb732f4dba3"}, {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f0959882bf73c8fe1cb801f42b0989e0ecb9d84b99eb8b8f70d61d16767a1e8a"}, - {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:06029db6b26f1764ed009360de8530f6cd759411232b3001df1b69ba6afa871d"}, - {file = "ephem-3.7.7.1-cp35-cp35m-manylinux2014_s390x.whl", hash = "sha256:562baaeb3a46cf2248f97d2ad80092d747024e5dea62ebe50386a04b8e506c10"}, {file = "ephem-3.7.7.1-cp35-cp35m-win32.whl", hash = "sha256:2bcd953cced045e4232bcb71d60f6ba237f7944c880e83e74cc959449b192dee"}, {file = "ephem-3.7.7.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fd0b922387df1ad8721f2fafd5dca51ce7105238f968e1532a177b781b8cae0e"}, {file = "ephem-3.7.7.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:e10c2c8afbb9e927d46d9bf3562441da2173ff196790a75ad0e5c5ee920d5922"}, - {file = "ephem-3.7.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:592264e512b5658402e93903343eb26502c6f327df8a71847f3dcaea73908f32"}, {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:8d586d970c42d62b1fc757a1c7c10679416a43e9e4a77391a05907159ce346f8"}, {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1a8ea6a045ff669011f8ecdeffadfc5eaa519fb56ab8dd40508910e9db5ec7b0"}, - {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c25993d6554820ff11fdd8f2ddb75bf99e70db01327f09700bf8811201e9daef"}, - {file = "ephem-3.7.7.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:9180d953ff4cbe89fc9ccc78aea73f290c0166b8ddb01e9c837b4639a7492ec8"}, {file = "ephem-3.7.7.1-cp36-cp36m-win32.whl", hash = "sha256:72fdb72c813fc9780726aa732eb2193bbe1663549265ca5a746899215ecfbffd"}, {file = "ephem-3.7.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f5af029f8814aa8617e73b2ddcad2bd1c682ca13c31ee3b6f5825dd5cb43e777"}, {file = "ephem-3.7.7.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:e61c68f1c7d304a130bb6b88c1fca6600bbc1a1df6ca9a109b6eba4c6cbd3376"}, - {file = "ephem-3.7.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fdf5f3ed8bd46ce2bf1145b26aec65a2c08ea7c97cf42b6b439af6e7bc6dc94d"}, {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:31e2a17ca6f8d6bd44832574fea5461938ba034e52bf551e15e1a4c8f8c6c4fb"}, {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:1ff5abefa230d5ab40846f1cb27d4f5583d46044fecf10e17bfb559bdc766a47"}, - {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:5ef34e3cfea0683998e867d7b8de642081e8821fafbd5e1d2dcab503c119c4a2"}, - {file = "ephem-3.7.7.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:e2aca9edb59ee2bb3c8c36f17177966bc762da04af994450c8ad61a20fb6acdd"}, {file = "ephem-3.7.7.1-cp37-cp37m-win32.whl", hash = "sha256:71ea3935c658ee184575fd4cc2aa3e7fd6d6bac4a1ccff9ee5549cee67ff0385"}, {file = "ephem-3.7.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:34fd228105b89fefd20608420861a75a184db1edeaf0056cf2f85d2a2f768aee"}, {file = "ephem-3.7.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:189fcaeacb44dc5a1684ad489542f126d99d4a85e87d2fe73864c902f0bc2c71"}, {file = "ephem-3.7.7.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a5ddf46ced515e4b81dfd22e6408fd06a329c31c6abb10af48d392641c490b0e"}, {file = "ephem-3.7.7.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:3530bee3eb7458d86d4c399f51f5b73ad7ea0441f0b2fb03de41d623789935af"}, - {file = "ephem-3.7.7.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:77193de077e5fff453756144dee978e5fd6978c5c03ce3f67a09bb237e78f9d4"}, - {file = "ephem-3.7.7.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:095ad42e8df6a5c91e0aeb5a68d76c0800b0283f72fc5f76e6df370ae1fb5537"}, {file = "ephem-3.7.7.1-cp38-cp38-win32.whl", hash = "sha256:33ad1a71b204aff123250b04e0ff2d5c3b8e9c6c814bf2c675d7752ce5896c02"}, {file = "ephem-3.7.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:4bc5140cc7218a53ee6d949110f6ed413b8e3165294100515cd0fb29aa8e3637"}, - {file = "ephem-3.7.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7aa88d2a6d216c2044be2a3b3cb184e9c8a5022f12464220694017ea9d75209d"}, - {file = "ephem-3.7.7.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:1a9822bde93205c67fd3399b26868204b67d9e4442af21a764307e51ea6dc672"}, - {file = "ephem-3.7.7.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:15dd3dbb3864fb853388e39ac3c915c72873507f54ee6b3ede0033b03465d8ba"}, - {file = "ephem-3.7.7.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5763919cdf38cd0488172711da504c3be003b7c104ccd2516cc496ff05f146ae"}, - {file = "ephem-3.7.7.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:cdea23a7caa1178b322e6e76484d40bd021672446ff51b512f35581e0f1b32b7"}, - {file = "ephem-3.7.7.1-cp39-cp39-win32.whl", hash = "sha256:c3cbc973b334892972445cec3deb99aafd0c57cb4e50679d5f12fc8c51b4e65f"}, - {file = "ephem-3.7.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:1af920c382980fe3566a31f36bd712973e1ca6049cbe07b4624214d5e1f144bc"}, {file = "ephem-3.7.7.1.tar.gz", hash = "sha256:36b51a8dc7cfdeb456dd6b8ab811accab8341b2d562ee3c6f4c86f6d3dbb984e"}, ] fbprophet = [ @@ -4940,6 +4927,10 @@ urllib3 = [ user-agent = [ {file = "user_agent-0.1.9.tar.gz", hash = "sha256:8f1ad46cc4aef9f99515ea1c74bb8cacc43e23074c335b2ba2db7735ebe9c0d5"}, ] +valinvest = [ + {file = "valinvest-0.0.2-py3-none-any.whl", hash = "sha256:37fadaf30c69e0487fed8d9cc93bb792ca8cf36fed0839e0e755a84738166ab9"}, + {file = "valinvest-0.0.2.tar.gz", hash = "sha256:9614aaf8019e015c20ea48867ede8a6ea10e1c6410e787314066d7b2e5aeb7dc"}, +] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, diff --git a/pyproject.toml b/pyproject.toml index 45e9f245261..d0f9c731ebc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,6 +60,7 @@ pyportfolioopt = "^1.4.1" selenium = "^3.141.0" python-coinmarketcap = "^0.2" oandapyV20 = "^0.6.3" +valinvest = "^0.0.2" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements.txt b/requirements.txt index 15e7172d368..654cd4398b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -158,6 +158,7 @@ typing-extensions==3.7.4.3; python_version < "3.8" and python_version >= "3.6" update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0" urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6" user-agent==0.1.9 +valinvest==0.0.2; python_version >= "3.6" wcwidth==0.2.5; python_version >= "3.6" and python_full_version >= "3.6.1" webencodings==0.5.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" websocket-client==0.58.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0" From cdeb2122dcdac79bf4fe4fffce7a5315c6bdbd38 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 22 Apr 2021 22:24:48 +0100 Subject: [PATCH 103/114] Keep image resolution --- gamestonk_terminal/options/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gamestonk_terminal/options/README.md b/gamestonk_terminal/options/README.md index 300574e5de9..7413f9a88aa 100644 --- a/gamestonk_terminal/options/README.md +++ b/gamestonk_terminal/options/README.md @@ -100,9 +100,10 @@ In order to run, the selenium webdriver must be installed. Currently, this runs on either Chrome or Firefox. The path to the driver should be defined in [config_terminal.py](#config_terminal.py). Note this may take more time than other commands to process. + ```` usage: info [-d DRIVER] ```` * -d/--driver : One of {chrome, firefox}. This indicates which driver you have installed. -![im](https://user-images.githubusercontent.com/18151143/115454584-efa83a00-a1ee-11eb-9d0f-2558ffa31579.png) \ No newline at end of file +opinfo From 1dcbb29b762cebb3eb69d1c36a057b2e898807bb Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 22 Apr 2021 22:31:00 +0100 Subject: [PATCH 104/114] Keep README in line with others --- gamestonk_terminal/cryptocurrency/README.md | 39 +++++++++------------ 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/gamestonk_terminal/cryptocurrency/README.md b/gamestonk_terminal/cryptocurrency/README.md index 78a1167ffbf..4a1b7b48fea 100644 --- a/gamestonk_terminal/cryptocurrency/README.md +++ b/gamestonk_terminal/cryptocurrency/README.md @@ -1,57 +1,52 @@ -# Cryptocurrency +# CRYPTOCURRENCY -This page gives an overview of the ability to load cryptocurrency data. - -Current crypto data is [Powered by CoinGecko API](#https://www.coingecko.com/en). -This is an awesome service that currently requires no API Key! - -Current functionality is aimed to be similar to loading a stock ticker. +This menu aims to explore crypto world, and the usage of the following commands along with an example will be exploited below. * [load](#load) + * load a given coin vs a given currency [CoinGecko] * [view](#view) + * plot the loaded crypto data * [top](#top) + * view top coins from coinmarketcap [coinmarketcap.com] + ## load -Load a given coin vs a given currency: ```` usage: load [-c --coin] [-d --days] [--vs] ```` + +Load a given coin vs a given currency. Currently only retrieves price, not volume or MarketCap. The current crypto data is [Powered by CoinGecko API](#https://www.coingecko.com/en), which is an awesome service that currently requires no API Key! + * -c/--coin The coin you wish to load. This can either be the symbol or the name. `load -c btc` and `load -c bitcoin` will load. The -c flag is optional, the above is equivalent to `load btc`. - * -d/--days The number of days to look. Defaults to 30 days. As per the API: Minutely data will be used for duration within 1 day, Hourly data will be used for duration between 1 day and 90 days, Daily data will be used for duration above 90 days. - * --vs The currency to look against. Defaults to "usd". -Currently only retrieves price, not volume or MarketCap. - -Example doge/eur for the past day: -```` -load -c doge -d 1 --vs eur -```` ## view -Plot the loaded crypto data. + ```` usage: view ```` -After loading the above 1 day dogecoin/eur. Running view plots the data: -![doge](https://user-images.githubusercontent.com/18151143/112690617-7832f500-8e52-11eb-84c4-253ab222a918.png) +Plot the loaded crypto data. + +![crypto_view](https://user-images.githubusercontent.com/25267873/115787452-20889a80-a3ba-11eb-9216-f7fd1ffc98cf.png) ## top -This command displays the top n cryptocurrencies from coinmarketcap.com. The list appears to be sorted by Mar ```` top [-n] [-s --sort SORTBY] [--descend] ```` + +This command displays the top n cryptocurrencies from coinmarketcap.com. + * -n: Number of coins to look at (after sort). Defaults to 10. * -s/--sort : Column to sort by. One of {Symbol,CMC_Rank,LastPrice,DayPctChange,MarketCap}. Defaults to sorting by the CMC rank. * --descend : Flag to change the sorting order. Sorts in ascending order (since default order is the Rank which starts at 1). -Example usage to get the CMC top 100, then show the top 4 highest Percent Day Change +crypto -![im](https://user-images.githubusercontent.com/18151143/115587223-6bf85700-a29b-11eb-9d96-cb4239b7c2d0.png) From 3cb643dbff1009b5b2824f754376698961b3ecc0 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 22 Apr 2021 22:35:16 +0100 Subject: [PATCH 105/114] Add forex to ROADMAP --- ROADMAP.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ROADMAP.md b/ROADMAP.md index ee6fca45d7e..eed825916c6 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -20,6 +20,7 @@ * [Credit Analysis](#Credit-Analysis) * [Cryptocurrencies](#Cryptocurrencies) * [Screener](#Screener) +* [Forex](#Forex) ## Additional @@ -63,6 +64,7 @@ ## Fundamental Analysis * [x] Rearrange FA menu to have AV and FMP as submenus (@didier) - [PR #166](https://github.com/DidierRLopes/GamestonkTerminal/pull/166) +* [x] Add Fundamental Analysis score (@didier) - [PR #383](https://github.com/DidierRLopes/GamestonkTerminal/pull/383) **NEXT** * [ ] Add Treasury Yield Curve data (@aia) - [PR #281](https://github.com/DidierRLopes/GamestonkTerminal/pull/281) @@ -209,6 +211,13 @@ ___ --- +## Forex +* [x] Add entire forex menu through Oanda (@alokan) - [PR #360](https://github.com/DidierRLopes/GamestonkTerminal/pull/360) + +**NEXT** + +--- + ## Backend **NEXT** From d9abafb2cae15a26a2c02949319c7846eb3b80db Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 22 Apr 2021 22:39:03 +0100 Subject: [PATCH 106/114] add fa-score readme --- gamestonk_terminal/fundamental_analysis/README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/gamestonk_terminal/fundamental_analysis/README.md b/gamestonk_terminal/fundamental_analysis/README.md index 5c2c114b0ce..914675970e5 100644 --- a/gamestonk_terminal/fundamental_analysis/README.md +++ b/gamestonk_terminal/fundamental_analysis/README.md @@ -6,7 +6,9 @@ This menu aims to extract all fundamentals of a pre-loaded company, and the usag * screen info about the company [Finviz] * [mgmt](#mgmt) * management team of the company [Business Insider] - +* [score](#score) + * investing score from Warren Buffett, Joseph Piotroski and Benjamin Graham [FMP] + [MARKET WATCH](#MARKET_WATCH) * [income](#income) @@ -323,3 +325,12 @@ Prints the growth of several financial statement items and ratios over time. Thi * n : Number of latest years/quarters. Default 1. * q : Quarter fundamental data flag. Default False. + + +### score + +```text +usage: score +``` + +Value investing tool based on Warren Buffett, Joseph Piotroski and Benjamin Graham thoughts [Source: Financial Modeling Prep] From 4792aa698b0deb6495d2bacce2ac843fdd473d83 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 22 Apr 2021 22:41:38 +0100 Subject: [PATCH 107/114] Update features readme --- gamestonk_terminal/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index 83f8c8b9402..49ae1f6510d 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -145,6 +145,7 @@ Command|Description ----- | --------- `screener` |screen info about the company ([Finviz](https://finviz.com/)) `mgmt` |management team of the company ([Business Insider](https://markets.businessinsider.com/)) +`score` |investing score from Warren Buffett, Joseph Piotroski and Benjamin Graham ([FMP](https://financialmodelingprep.com/)) [Market Watch API](https://markets.businessinsider.com/) | `income` |income statement of the company `balance` |balance sheet of the company @@ -272,6 +273,7 @@ Command|Description ------ | ------------ `load`| load cryptocurrency data `view`| load and view cryptocurrency data +`top` | view top coins from coinmarketcap   ## Comparison Analysis [»](comparison_analysis/README.md) From d1874bdbe074e622bf78955ecce2619b8e3ee328 Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 22 Apr 2021 22:45:32 +0100 Subject: [PATCH 108/114] Add Forex to features readme --- gamestonk_terminal/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/gamestonk_terminal/README.md b/gamestonk_terminal/README.md index 49ae1f6510d..211b0a008e7 100644 --- a/gamestonk_terminal/README.md +++ b/gamestonk_terminal/README.md @@ -17,6 +17,7 @@ * [FRED](#FRED-) * [Options](#Options-) * [Screener](#Screener-) +* [Forex](#Forex-) ## Main @@ -366,5 +367,26 @@ performance |performance (e.g. Perf Week, Perf YTD, Volatility M) technical |technical (e.g. Beta, SMA50, 52W Low, RSI, Change) signals |view filter signals (e.g. -s top_gainers) +  + + +## Forex [»](forex/README.md) +Command|Description +------ | -------- +summary |display a summary of your account +calendar |get information about past or upcoming events which may impact the price +list |list your order history +pending |get information about pending orders +cancel |cancel a pending order by ID +positions |get information about your positions +trades |see a list of open trades +closetrade |close a trade by ID +load |specify an instrument to use +candles |get a candlestick chart for the forex instrument +price |show the current price for the forex instrument +order |place a limit order +orderbook |display the orderbook if Oanda provides one for the forex instrument +positionbook |display the positionbook if Oanda provides one for the forex instrument +   From d76c5437add636bfc8666383c437e7307c01681d Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 22 Apr 2021 22:52:12 +0100 Subject: [PATCH 109/114] Fix op/info command, although browser needs to pop up --- gamestonk_terminal/options/op_scrape_view.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/gamestonk_terminal/options/op_scrape_view.py b/gamestonk_terminal/options/op_scrape_view.py index 40bb5e1e0f9..7b9ee996fdf 100644 --- a/gamestonk_terminal/options/op_scrape_view.py +++ b/gamestonk_terminal/options/op_scrape_view.py @@ -63,14 +63,16 @@ def print_options_data(stock: str, other_args: List[str]): try: if browser == "chrome": - options = cOpts() - options.headless = True - driver = webdriver.Chrome(options=options, executable_path=path_to_driver) + # commenting this because it breaks when in usage + # the downside is that the browser will pop up to get the data + driver = webdriver.Chrome(executable_path=path_to_driver) elif browser == "firefox": - options = fOpts() - options.headless = True - driver = webdriver.Firefox(options=options, executable_path=path_to_driver) + # commenting this because it breaks when in usage + # the downside is that the browser will pop up to get the data + #options = fOpts() + #options.headless = True + driver = webdriver.Firefox(executable_path=path_to_driver) page = f"https://www.barchart.com/stocks/quotes/{stock}/overview" driver.get(page) From a105fc829dc23b68781d38f1595ae382a4737bce Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Thu, 22 Apr 2021 22:55:49 +0100 Subject: [PATCH 110/114] Update ROADMAP.md --- ROADMAP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ROADMAP.md b/ROADMAP.md index eed825916c6..5242e32bfb3 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -192,6 +192,7 @@ ___ ## 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) **NEXT** * [ ] Add [Coinpaprika](https://coinpaprika.com/api/) From 0c9e1a29f83cc771e9003323e848761fbe68da37 Mon Sep 17 00:00:00 2001 From: didier Date: Thu, 22 Apr 2021 22:57:22 +0100 Subject: [PATCH 111/114] Black fix --- gamestonk_terminal/options/op_scrape_view.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gamestonk_terminal/options/op_scrape_view.py b/gamestonk_terminal/options/op_scrape_view.py index 7b9ee996fdf..dbf5459181f 100644 --- a/gamestonk_terminal/options/op_scrape_view.py +++ b/gamestonk_terminal/options/op_scrape_view.py @@ -5,8 +5,9 @@ import argparse from typing import List from selenium import webdriver from bs4 import BeautifulSoup -from selenium.webdriver.chrome.options import Options as cOpts -from selenium.webdriver.firefox.options import Options as fOpts + +# from selenium.webdriver.chrome.options import Options as cOpts +# from selenium.webdriver.firefox.options import Options as fOpts import pandas as pd from tabulate import tabulate from gamestonk_terminal.config_terminal import ( @@ -65,13 +66,15 @@ def print_options_data(stock: str, other_args: List[str]): if browser == "chrome": # commenting this because it breaks when in usage # the downside is that the browser will pop up to get the data + # options = cOpts() + # options.headless = True driver = webdriver.Chrome(executable_path=path_to_driver) elif browser == "firefox": # commenting this because it breaks when in usage # the downside is that the browser will pop up to get the data - #options = fOpts() - #options.headless = True + # options = fOpts() + # options.headless = True driver = webdriver.Firefox(executable_path=path_to_driver) page = f"https://www.barchart.com/stocks/quotes/{stock}/overview" From ca2ae2c240499ce6f752563566b0511e239bd90f Mon Sep 17 00:00:00 2001 From: didier Date: Fri, 23 Apr 2021 17:29:26 +0100 Subject: [PATCH 112/114] Fix clean build --- requirements-full.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements-full.txt b/requirements-full.txt index 15e7172d368..654cd4398b4 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -158,6 +158,7 @@ typing-extensions==3.7.4.3; python_version < "3.8" and python_version >= "3.6" update-checker==0.18.0; python_version >= "3.6" and python_version < "4.0" urllib3==1.26.4; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.6" user-agent==0.1.9 +valinvest==0.0.2; python_version >= "3.6" wcwidth==0.2.5; python_version >= "3.6" and python_full_version >= "3.6.1" webencodings==0.5.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" websocket-client==0.58.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "4.0" or python_version >= "3.6" and python_version < "4.0" and python_full_version >= "3.4.0" From 23ce51b95e7c6af2dfae9ab5b227ce244d412c01 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Fri, 23 Apr 2021 10:13:59 -0700 Subject: [PATCH 113/114] Updating due_diligence.ipynb based on FA refactor --- notebooks/templates/due_diligence.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 notebooks/templates/due_diligence.ipynb diff --git a/notebooks/templates/due_diligence.ipynb b/notebooks/templates/due_diligence.ipynb old mode 100644 new mode 100755 index 09f4d95510f..8b3672abe76 --- a/notebooks/templates/due_diligence.ipynb +++ b/notebooks/templates/due_diligence.ipynb @@ -150,7 +150,7 @@ "metadata": {}, "outputs": [], "source": [ - "from gamestonk_terminal.fundamental_analysis import market_watch_api as mw" + "from gamestonk_terminal.fundamental_analysis import market_watch_model as mw" ] }, { @@ -215,4 +215,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} From 3e3e7e8aedb06d4dd770b0b4dae57445a25bc10b Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Fri, 23 Apr 2021 10:14:30 -0700 Subject: [PATCH 114/114] Yahoo renamed Crude Oil from HCL=F to CL=F --- notebooks/templates/econ_data.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 notebooks/templates/econ_data.ipynb diff --git a/notebooks/templates/econ_data.ipynb b/notebooks/templates/econ_data.ipynb old mode 100644 new mode 100755 index 4eea6cc29a7..fa4f80f2693 --- a/notebooks/templates/econ_data.ipynb +++ b/notebooks/templates/econ_data.ipynb @@ -319,7 +319,7 @@ }, "outputs": [], "source": [ - "edh.draw_graph(\"HCL=F\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=720, low_trend=False)" + "edh.draw_graph(\"CL=F\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=720, low_trend=False)" ] }, {