From ec07686aedce6f952dde45818580bafb31992ecf Mon Sep 17 00:00:00 2001 From: DidierRLopes Date: Sun, 8 Aug 2021 21:36:24 +0100 Subject: [PATCH] Refactor Economy menu (#652) * Allow to quit when DEFAULT_CONTEXT selected * terminal imports inside context selection * rework economy/events command * Refactor fear greed CNN command * refactor WSJ in economy * import fred * refactor fred commands in economy * refactor disc commands into economy * refactor disc commands into economy 2 * fix fred test * fix fred test * av pylint * update quit from direct context * fix av lint * Add industry simply wallst to economy * improve events display * improv after review * add mypy types * tabulate raw series * remove simply wallst --- exports/economy/.gitkeep | 0 .../economy/alphavantage_model.py | 22 + .../economy/alphavantage_view.py | 44 ++ gamestonk_terminal/economy/cnn_model.py | 54 ++ gamestonk_terminal/economy/cnn_view.py | 98 +-- .../economy/economy_controller.py | 747 +++++++++++++++--- gamestonk_terminal/economy/finnhub_model.py | 22 + gamestonk_terminal/economy/finnhub_view.py | 175 ++-- gamestonk_terminal/economy/finviz_model.py | 36 + gamestonk_terminal/economy/finviz_view.py | 73 ++ gamestonk_terminal/economy/fred_model.py | 98 +++ gamestonk_terminal/economy/fred_view.py | 277 +++---- gamestonk_terminal/economy/wsj_model.py | 24 +- gamestonk_terminal/economy/wsj_view.py | 311 ++++---- .../stocks/discovery/alpha_vantage_view.py | 54 -- .../stocks/discovery/disc_controller.py | 43 - .../stocks/discovery/finviz_view.py | 182 ----- poetry.lock | 46 +- pyproject.toml | 1 + requirements-full.txt | 1 + requirements.txt | 1 + terminal.py | 115 +-- tests/test_fred_fred_view.py | 36 +- 23 files changed, 1433 insertions(+), 1027 deletions(-) create mode 100644 exports/economy/.gitkeep create mode 100644 gamestonk_terminal/economy/alphavantage_model.py create mode 100644 gamestonk_terminal/economy/alphavantage_view.py create mode 100644 gamestonk_terminal/economy/cnn_model.py create mode 100644 gamestonk_terminal/economy/finnhub_model.py create mode 100644 gamestonk_terminal/economy/finviz_model.py create mode 100644 gamestonk_terminal/economy/finviz_view.py create mode 100644 gamestonk_terminal/economy/fred_model.py delete mode 100644 gamestonk_terminal/stocks/discovery/alpha_vantage_view.py delete mode 100644 gamestonk_terminal/stocks/discovery/finviz_view.py diff --git a/exports/economy/.gitkeep b/exports/economy/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/gamestonk_terminal/economy/alphavantage_model.py b/gamestonk_terminal/economy/alphavantage_model.py new file mode 100644 index 00000000000..d9470eda2b8 --- /dev/null +++ b/gamestonk_terminal/economy/alphavantage_model.py @@ -0,0 +1,22 @@ +""" Alpha Vantage Model """ +__docformat__ = "numpy" + +import pandas as pd +from alpha_vantage.sectorperformance import SectorPerformances +from gamestonk_terminal import config_terminal as cfg + + +def get_sector_data() -> pd.DataFrame: + """Get real-time performance sector data + + Returns + ---------- + df_sectors : pd.Dataframe + Real-time performance data + """ + sector_perf = SectorPerformances( + key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas" + ) + # pylint: disable=unbalanced-tuple-unpacking + df_sectors, _ = sector_perf.get_sector() + return df_sectors diff --git a/gamestonk_terminal/economy/alphavantage_view.py b/gamestonk_terminal/economy/alphavantage_view.py new file mode 100644 index 00000000000..22d4915be50 --- /dev/null +++ b/gamestonk_terminal/economy/alphavantage_view.py @@ -0,0 +1,44 @@ +""" Alpha Vantage View """ +__docformat__ = "numpy" + +import os +import matplotlib.pyplot as plt +from gamestonk_terminal.helper_funcs import export_data +from gamestonk_terminal.economy import alphavantage_model +from gamestonk_terminal import feature_flags as gtff + + +def realtime_performance_sector(raw: bool, export: str): + """Display Real-Time Performance sector. [Source: AlphaVantage] + + Parameters + ---------- + raw : bool + Output only raw data + export : str + Export dataframe data to csv,json,xlsx file + """ + df_sectors = alphavantage_model.get_sector_data() + + # pylint: disable=invalid-sequence-index + df_rtp = df_sectors["Rank A: Real-Time Performance"] + + if raw: + print(df_rtp.to_string()) + + else: + df_rtp.plot(kind="bar") + plt.title("Real Time Performance (%) per Sector") + plt.tight_layout() + plt.grid() + if gtff.USE_ION: + plt.ion() + plt.show() + print("") + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "rtps", + df_sectors, + ) diff --git a/gamestonk_terminal/economy/cnn_model.py b/gamestonk_terminal/economy/cnn_model.py new file mode 100644 index 00000000000..ae8e41800aa --- /dev/null +++ b/gamestonk_terminal/economy/cnn_model.py @@ -0,0 +1,54 @@ +""" CNN Model """ +__docformat__ = "numpy" + +from typing import Tuple +from fear_greed_index.CNNFearAndGreedIndex import CNNFearAndGreedIndex +from pandas.plotting import register_matplotlib_converters +import matplotlib.pyplot as plt + +register_matplotlib_converters() + + +def get_feargreed_report(indicator: str, fig: plt.figure) -> Tuple[str, plt.figure]: + """Display CNN Fear And Greed Index. + + Parameters + ---------- + indicator : str + CNN Fear And Greed indicator or index. From Junk Bond Demand, Market Volatility, + Put and Call Options, Market Momentum Stock Price Strength, Stock Price Breadth, + Safe Heaven Demand, and Index. + plt.figure + matplotlib figure initialized if indicator 'all' is selected + + Returns + ---------- + str + String output with respect to indicator chosen + plt.figure + matplotlib figure with indicator + """ + cnn_fg = CNNFearAndGreedIndex() + + if indicator: + if indicator == "index": + return cnn_fg.index_summary, cnn_fg.index_chart + + d_indicator_match = { + "jbd": "Junk Bond Demand", + "mv": "Market Volatility", + "pco": "Put and Call Options", + "mm": "Market Momentum", + "sps": "Stock Price Strength", + "spb": "Stock Price Breadth", + "shd": "Safe Heaven Demand", + } + indicator_name = d_indicator_match[indicator] + + for ind in cnn_fg.all_indicators: + if indicator_name == ind.type_indicator: + return ind.get_report(), ind.chart + + return "", plt.figure() + + return cnn_fg.get_complete_report(), cnn_fg.plot_all_charts(fig) diff --git a/gamestonk_terminal/economy/cnn_view.py b/gamestonk_terminal/economy/cnn_view.py index c0f122f2a9b..54e373a3bb7 100644 --- a/gamestonk_terminal/economy/cnn_view.py +++ b/gamestonk_terminal/economy/cnn_view.py @@ -1,105 +1,37 @@ -""" Fred View """ +""" CNN View """ __docformat__ = "numpy" -import argparse -from typing import List -from fear_greed_index.CNNFearAndGreedIndex import CNNFearAndGreedIndex from pandas.plotting import register_matplotlib_converters import matplotlib.pyplot as plt 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 gamestonk_terminal.economy import cnn_model register_matplotlib_converters() -def fear_and_greed_index(other_args: List[str]): +def fear_and_greed_index(indicator: str): """Display CNN Fear And Greed Index. Parameters ---------- - other_args : List[str] - argparse other args + indicator : str + CNN Fear And Greed indicator or index. From Junk Bond Demand, Market Volatility, + Put and Call Options, Market Momentum Stock Price Strength, Stock Price Breadth, + Safe Heaven Demand, and Index. """ + fig = plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) - parser = argparse.ArgumentParser( - add_help=False, - prog="feargreed", - description=""" - Display CNN Fear And Greed Index from https://money.cnn.com/data/fear-and-greed/. - """, - ) + report, im = cnn_model.get_feargreed_report(indicator, fig) - parser.add_argument( - "-i", - "--indicator", - dest="indicator", - required=False, - type=str, - choices=["jbd", "mv", "pco", "mm", "sps", "spb", "shd", "index"], - help=""" - CNN Fear And Greed indicator or index. From Junk Bond Demand, Market Volatility, - Put and Call Options, Market Momentum Stock Price Strength, Stock Price Breadth, - Safe Heaven Demand, and Index. - """, - ) + print(report) - try: - if other_args: - if "-" not in other_args[0]: - other_args.insert(0, "-i") + if indicator: + plt.imshow(im) - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return - - cnn_fg = CNNFearAndGreedIndex() - - fig = plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) - - if ns_parser.indicator: - if ns_parser.indicator == "index": - print(cnn_fg.index_summary) - - im = cnn_fg.index_chart - plt.imshow(im) - - else: - d_indicator_match = { - "jbd": "Junk Bond Demand", - "mv": "Market Volatility", - "pco": "Put and Call Options", - "mm": "Market Momentum", - "sps": "Stock Price Strength", - "spb": "Stock Price Breadth", - "shd": "Safe Heaven Demand", - } - indicator_name = d_indicator_match[ns_parser.indicator] - - for indicator in cnn_fg.all_indicators: - if indicator_name == indicator.type_indicator: - print(indicator.get_report()) - im = indicator.chart - plt.imshow(im) - - else: - # print Fear and Greed complete report - print(cnn_fg.get_complete_report()) - - # plot Fear and Greed charts - cnn_fg.plot_all_charts(fig) - - if gtff.USE_ION: - plt.ion() - - plt.show() - print("") - - except SystemExit: - print("") - except Exception as e: - print(e, "\n") - return + if gtff.USE_ION: + plt.ion() + plt.show() diff --git a/gamestonk_terminal/economy/economy_controller.py b/gamestonk_terminal/economy/economy_controller.py index 887284bcf54..c3159cc04a2 100644 --- a/gamestonk_terminal/economy/economy_controller.py +++ b/gamestonk_terminal/economy/economy_controller.py @@ -6,12 +6,21 @@ import os from typing import List 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.helper_funcs import ( + get_flair, + parse_known_args_and_warn, + check_positive, + valid_date, +) from gamestonk_terminal.menu import session -from gamestonk_terminal.economy import fred_view -from gamestonk_terminal.economy import finnhub_view -from gamestonk_terminal.economy import cnn_view -from gamestonk_terminal.economy import wsj_view +from gamestonk_terminal.economy import ( + fred_view, + finnhub_view, + cnn_view, + wsj_view, + finviz_view, + alphavantage_view, +) from gamestonk_terminal.economy.report import report_controller # pylint: disable=R1710 @@ -20,7 +29,24 @@ from gamestonk_terminal.economy.report import report_controller class EconomyController: """Economy Controller""" - # Command choices + d_GROUPS = { + "sector": "Sector", + "industry": "Industry", + "basic materials": "Industry (Basic Materials)", + "communication services": "Industry (Communication Services)", + "consumer cyclical": "Industry (Consumer Cyclical)", + "consumer defensive": "Industry (Consumer Defensive)", + "energy": "Industry (Energy)", + "financial": "Industry (Financial)", + "healthcare": "Industry (Healthcare)", + "industrials": "Industry (Industrials)", + "real Estate": "Industry (Real Estate)", + "technology": "Industry (Technology)", + "utilities": "Industry (Utilities)", + "country": "Country (U.S. listed stocks only)", + "capitalization": "Capitalization", + } + CHOICES = [ "cls", "?", @@ -30,20 +56,8 @@ class EconomyController: ] CHOICES_COMMANDS = [ - "events", - "fred", - "vixcls", - "gdp", - "unrate", - "dgs1", - "dgs5", - "dgs10", - "dgs30", - "mortgage30us", - "fedfunds", - "aaa", - "dexcaus", "feargreed", + "events", "overview", "indices", "futures", @@ -51,6 +65,14 @@ class EconomyController: "glbonds", "futures", "currencies", + "search", + "series", + "valuation", + "performance", + "spectrum", + "map", + "rtps", + "industry", ] CHOICES_MENUS = [ @@ -71,45 +93,41 @@ class EconomyController: @staticmethod def print_help(): """Print help""" - print( - "https://github.com/GamestonkTerminal/GamestonkTerminal/tree/main/gamestonk_terminal/economy" - ) - print("") - print(">> ECONOMY <<") - print("") - print("What do you want to do?") - print(" cls clear screen") - print(" ?/help show this menu again") - print(" q quit this menu, and shows back to main menu") - print(" quit quit to abandon program") - print(" ") - print(" feargreed CNN Fear and Greed Index") - print(" events economic impact events [Finnhub]") - print( - " fred display customized FRED data from https://fred.stlouisfed.org" - ) - print(" vixcls Volatility Index") - print(" gdp Gross Domestic Product") - print(" unrate Unemployment Rate") - print(" dgs1 1-year Treasury Constant Maturity Rate") - print(" dgs5 5-year Treasury Constant Maturity Rate") - print(" dgs10 10-year Treasury Constant Maturity Rate") - print(" dgs30 30-year Treasury Constant Maturity Rate") - print(" mortgage30us 30-year Fixed Rate Mortgage Average") - print(" fedfunds Effective Federal Funds Rate") - print(" aaa Moody's Seasoned AAA Corporate Bond Yield") - print(" dexcaus Canada / U.S. Foreign Exchange Rate (CAD per 1 USD)") - print("") - print("Wall St. Journal:") - print(" overview market data overview") - print(" indices us indices overview") - print(" futures futures overview") - print(" usbonds us bond overview") - print(" glbonds global bonds overview") - print(" currencies currency overview") - print("") - print("> report generate automatic report") - print("") + help_text = """https://github.com/GamestonkTerminal/GamestonkTerminal/tree/main/gamestonk_terminal/economy + +>> ECONOMY << + +What do you want to do? + cls clear screen + ?/help show this menu again + q quit this menu, and shows back to main menu + quit quit to abandon program + +CNN: + feargreed CNN Fear and Greed Index +Finnhub: + events economic impact events +Wall St. Journal: + overview market data overview + indices US indices overview + futures futures and commodities overview + usbonds US bonds overview + glbonds global bonds overview + currencies currencies overview +Finviz: + map S&P500 index stocks map + valuation valuation of sectors, industry, country + performance performance of sectors, industry, country + spectrum spectrum of sectors, industry, country +Alpha Vantage: + rtps real-time performance sectors +FRED: + search search FRED series notes + series plot series from https://fred.stlouisfed.org + +> report generate automatic report +""" + print(help_text) def switch(self, an_input: str): """Process and dispatch input @@ -157,83 +175,588 @@ class EconomyController: def call_events(self, other_args: List[str]): """Process events command""" - finnhub_view.economy_calendar_events(other_args) + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="events", + description=""" + Output economy impact calendar impact events. [Source: Finnhub] + """, + ) + parser.add_argument( + "-c", + "--country", + action="store", + dest="country", + type=str, + default="US", + choices=["NZ", "AU", "ERL", "CA", "EU", "US", "JP", "CN", "GB", "CH"], + help="Country from where to get economy calendar impact events", + ) + parser.add_argument( + "-n", + "--num", + action="store", + dest="num", + type=check_positive, + default=10, + help="Number economy calendar impact events to display", + ) + parser.add_argument( + "-i", + "--impact", + action="store", + dest="impact", + type=str, + default="all", + choices=["low", "medium", "high", "all"], + help="Impact of the economy event", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-c") - def call_fred(self, other_args: List[str]): - """Process fred command""" - fred_view.display_fred(other_args, "") + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return - def call_vixcls(self, other_args: List[str]): - """Process vixcls command""" - fred_view.display_fred(other_args, "VIXCLS") + finnhub_view.economy_calendar_events( + country=ns_parser.country, + num=ns_parser.num, + impact=ns_parser.impact, + export=ns_parser.export, + ) - def call_gdp(self, other_args: List[str]): - """Process gdp command""" - fred_view.display_fred(other_args, "GDP") - - def call_unrate(self, other_args: List[str]): - """Process unrate command""" - fred_view.display_fred(other_args, "UNRATE") - - def call_dgs1(self, other_args: List[str]): - """Process dgs1 command""" - fred_view.display_fred(other_args, "DGS1") - - def call_dgs5(self, other_args: List[str]): - """Process dgs5 command""" - fred_view.display_fred(other_args, "DGS5") - - def call_dgs10(self, other_args: List[str]): - """Process dgs10 command""" - fred_view.display_fred(other_args, "DGS10") - - def call_dgs30(self, other_args: List[str]): - """Process dgs30 command""" - fred_view.display_fred(other_args, "DGS30") - - def call_mortgage30us(self, other_args: List[str]): - """Process mortgage30us command""" - fred_view.display_fred(other_args, "MORTGAGE30US") - - def call_fedfunds(self, other_args: List[str]): - """Process fedfunds command""" - fred_view.display_fred(other_args, "FEDFUNDS") - - def call_aaa(self, other_args: List[str]): - """Process aaa command""" - fred_view.display_fred(other_args, "AAA") - - def call_dexcaus(self, other_args: List[str]): - """Process dexcaus command""" - fred_view.display_fred(other_args, "DEXCAUS") + except Exception as e: + print(e, "\n") def call_feargreed(self, other_args: List[str]): """Process feargreed command""" - cnn_view.fear_and_greed_index(other_args) + parser = argparse.ArgumentParser( + add_help=False, + prog="feargreed", + description=""" + Display CNN Fear And Greed Index from https://money.cnn.com/data/fear-and-greed/. + """, + ) + parser.add_argument( + "-i", + "--indicator", + dest="indicator", + required=False, + type=str, + choices=["jbd", "mv", "pco", "mm", "sps", "spb", "shd", "index"], + help=""" + CNN Fear And Greed indicator or index. From Junk Bond Demand, Market Volatility, + Put and Call Options, Market Momentum Stock Price Strength, Stock Price Breadth, + Safe Heaven Demand, and Index. + """, + ) + try: + 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 + + cnn_view.fear_and_greed_index(indicator=ns_parser.indicator) + + except Exception as e: + print(e, "\n") def call_overview(self, other_args: List[str]): """Process overview command""" - wsj_view.display_overview(other_args) + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="overview", + description="Market overview. [Source: Wall St. Journal]", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + wsj_view.display_overview( + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") def call_indices(self, other_args: List[str]): """Process indices command""" - wsj_view.display_indices(other_args) + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="indices", + description="US indices. [Source: Wall St. Journal]", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + wsj_view.display_indices( + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") def call_futures(self, other_args: List[str]): """Process futures command""" - wsj_view.display_futures(other_args) + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="futures", + description="Futures/Commodities. [Source: Wall St. Journal]", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + wsj_view.display_futures( + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") def call_usbonds(self, other_args: List[str]): """Process usbonds command""" - wsj_view.display_usbonds(other_args) + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="usbonds", + description="US Bonds. [Source: Wall St. Journal]", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + wsj_view.display_usbonds( + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") def call_glbonds(self, other_args: List[str]): """Process glbonds command""" - wsj_view.display_glbonds(other_args) + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="glbonds", + description="Global Bonds. [Source: Wall St. Journal]", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + wsj_view.display_glbonds( + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") def call_currencies(self, other_args: List[str]): - """Process curremcies command""" - wsj_view.display_currencies(other_args) + """Process currencies command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="currencies", + description="Currencies. [Source: Wall St. Journal]", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + wsj_view.display_currencies( + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") + + def call_map(self, other_args: List[str]): + """Process map command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="map", + description=""" + Performance index stocks map categorized by sectors and industries. + Size represents market cap. Opens web-browser. [Source: Finviz] + """, + ) + parser.add_argument( + "-p", + "--period", + action="store", + dest="s_period", + type=str, + default="1d", + choices=["1d", "1w", "1m", "3m", "6m", "1y"], + help="Performance period.", + ) + parser.add_argument( + "-t", + "--type", + action="store", + dest="s_type", + type=str, + default="sp500", + choices=["sp500", "world", "full", "etf"], + help="Map filter type.", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + finviz_view.map_sp500_view( + period=ns_parser.s_period, + map_type=ns_parser.s_type, + ) + + except Exception as e: + print(e, "\n") + + def call_valuation(self, other_args: List[str]): + """Process valuation command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="valuation", + description=""" + View group (sectors, industry or country) valuation data. [Source: Finviz] + """, + ) + parser.add_argument( + "-g", + "--group", + type=str, + default="Sector", + dest="group", + help="Data group (sector, industry or country)", + choices=list(self.d_GROUPS.keys()), + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-g") + other_args = [other_args[0], " ".join(other_args[1:])] + + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + finviz_view.view_group_data( + s_group=self.d_GROUPS[ns_parser.group], + data_type="valuation", + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") + + def call_performance(self, other_args: List[str]): + """Process performance command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="performance", + description=""" + View group (sectors, industry or country) performance data. [Source: Finviz] + """, + ) + parser.add_argument( + "-g", + "--group", + type=str, + default="Sector", + dest="group", + help="Data group (sector, industry or country)", + choices=list(self.d_GROUPS.keys()), + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-g") + other_args = [other_args[0], " ".join(other_args[1:])] + + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + finviz_view.view_group_data( + s_group=self.d_GROUPS[ns_parser.group], + data_type="performance", + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") + + def call_spectrum(self, other_args: List[str]): + """Process spectrum command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="spectrum", + description=""" + View group (sectors, industry or country) spectrum data. [Source: Finviz] + """, + ) + parser.add_argument( + "-g", + "--group", + type=str, + default="Sector", + dest="group", + help="Data group (sector, industry or country)", + choices=list(self.d_GROUPS.keys()), + ) + try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-g") + other_args = [other_args[0], " ".join(other_args[1:])] + + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + finviz_view.view_group_data( + s_group=self.d_GROUPS[ns_parser.group], + data_type="spectrum", + export="", + ) + # Due to Finviz implementation of Spectrum, we delete the generated spectrum figure + # after saving it and displaying it to the user + os.remove(ns_parser.group + ".jpg") + + except Exception as e: + print(e, "\n") + + def call_rtps(self, other_args: List[str]): + """Process rtps command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="rtps", + description=""" + Real-time and historical sector performances calculated from + S&P500 incumbents. Pops plot in terminal. [Source: Alpha Vantage] + """, + ) + parser.add_argument( + "--raw", + action="store_true", + dest="raw", + help="Only output raw data", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + alphavantage_view.realtime_performance_sector( + raw=ns_parser.raw, + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") + + def call_series(self, other_args: List[str]): + """Process series command""" + parser = argparse.ArgumentParser( + add_help=False, + prog="series", + description=""" + Display (multiple) series from https://fred.stlouisfed.org. [Source: FRED] + """, + ) + parser.add_argument( + "-i", + "--id", + dest="series_id", + required="-h" not in other_args, + type=str, + help="FRED Series from https://fred.stlouisfed.org. For multiple series use: series1,series2,series3", + ) + parser.add_argument( + "-s", + dest="start_date", + type=valid_date, + default="2019-01-01", + help="Starting date (YYYY-MM-DD) of data", + ) + parser.add_argument( + "--raw", + action="store_true", + dest="raw", + help="Only output raw data", + ) + parser.add_argument( + "--export", + choices=["csv", "json", "xlsx"], + default="", + type=str, + dest="export", + help="Export dataframe data to csv,json,xlsx file", + ) + try: + 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 + + fred_view.display_series( + series=ns_parser.series_id, + start_date=ns_parser.start_date, + raw=ns_parser.raw, + export=ns_parser.export, + ) + + except Exception as e: + print(e, "\n") + + def call_search(self, other_args: List[str]): + """Process search command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="search", + description="Print series notes when searching for series. [Source: FRED]", + ) + parser.add_argument( + "-s", + "--series", + action="store", + dest="series_term", + type=str, + required="-h" not in other_args, + help="Search for this series term.", + ) + parser.add_argument( + "-n", + "--num", + action="store", + dest="num", + type=check_positive, + default=5, + help="Maximum number of series notes to display.", + ) + try: + if other_args: + if "-" not in other_args[0]: + other_args.insert(0, "-s") + + ns_parser = parse_known_args_and_warn(parser, other_args) + if not ns_parser: + return + + fred_view.notes( + series_term=ns_parser.series_term, + num=ns_parser.num, + ) + + except Exception as e: + print(e, "\n") def call_report(self, _): """Process report command""" diff --git a/gamestonk_terminal/economy/finnhub_model.py b/gamestonk_terminal/economy/finnhub_model.py new file mode 100644 index 00000000000..d331af6b2ac --- /dev/null +++ b/gamestonk_terminal/economy/finnhub_model.py @@ -0,0 +1,22 @@ +import requests +import pandas as pd +from gamestonk_terminal import config_terminal as cfg + + +def get_economy_calendar_events() -> pd.DataFrame: + """Get economic calendar events + + Returns + ------- + pd.DataFrame + Get dataframe with economic calendar events + """ + response = requests.get( + f"https://finnhub.io/api/v1/calendar/economic?token={cfg.API_FINNHUB_KEY}" + ) + if response.status_code == 200: + d_data = response.json() + if "economicCalendar" in d_data: + return pd.DataFrame(d_data["economicCalendar"]) + + return pd.DataFrame() diff --git a/gamestonk_terminal/economy/finnhub_view.py b/gamestonk_terminal/economy/finnhub_view.py index b869d8c5957..decb89b0c8c 100644 --- a/gamestonk_terminal/economy/finnhub_view.py +++ b/gamestonk_terminal/economy/finnhub_view.py @@ -1,131 +1,80 @@ -import argparse -from typing import List -import requests -import pandas as pd -from gamestonk_terminal import config_terminal as cfg -from gamestonk_terminal.helper_funcs import ( - parse_known_args_and_warn, - check_positive, -) +import os +from tabulate import tabulate +from gamestonk_terminal.economy import finnhub_model +from gamestonk_terminal.helper_funcs import export_data -def get_economy_calendar_events() -> pd.DataFrame: - """Get economic calendar events - - Returns - ------- - pd.DataFrame - Get dataframe with economic calendar events - """ - response = requests.get( - f"https://finnhub.io/api/v1/calendar/economic?token={cfg.API_FINNHUB_KEY}" - ) - if response.status_code == 200: - d_data = response.json() - if "economicCalendar" in d_data: - return pd.DataFrame(d_data["economicCalendar"]) - - return pd.DataFrame() - - -def economy_calendar_events(other_args: List[str]): - """Output economy calendar impact events +def economy_calendar_events(country: str, num: int, impact: str, export: str): + """Output economy calendar impact events. [Source: Finnhub] Parameters ---------- - other_args : List[str] - Command line arguments to be processed with argparse + country : str + Country from where to get economy calendar impact events + num : int + Number economy calendar impact events to display + impact : str + Impact of the economy event + export : str + Export dataframe data to csv,json,xlsx file """ - parser = argparse.ArgumentParser( - add_help=False, - prog="events", - description=""" - Output economy impact calendar impact events. [Source: https://finnhub.io] - """, - ) - parser.add_argument( - "-c", - "--country", - action="store", - dest="country", - type=str, - default="US", - choices=["NZ", "AU", "ERL", "CA", "EU", "US", "JP", "CN", "GB", "CH"], - help="Country from where to get economy calendar impact events", - ) - parser.add_argument( - "-n", - "--num", - action="store", - dest="num", - type=check_positive, - default=10, - help="Number economy calendar impact events to display", - ) - parser.add_argument( - "-i", - "--impact", - action="store", - dest="impact", - type=str, - default="all", - choices=["low", "medium", "high", "all"], - help="Impact of the economy event", + df_events = finnhub_model.get_economy_calendar_events() + + if df_events.empty: + print("No latest economy calendar events found\n") + return + + df_econ_calendar = df_events[df_events["country"] == country].sort_values( + "time", ascending=True ) - try: - if other_args: - if "-" not in other_args[0]: - other_args.insert(0, "-c") + if df_econ_calendar.empty: + print("No latest economy calendar events found in the specified country\n") + return - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return - - df_events = get_economy_calendar_events() - - if df_events.empty: - print("No latest economy calendar events found\n") - return - - df_econ_calendar = df_events[ - df_events["country"] == ns_parser.country - ].sort_values("time", ascending=True) + if impact != "all": + df_econ_calendar = df_econ_calendar[df_econ_calendar["impact"] == impact] if df_econ_calendar.empty: - print("No latest economy calendar events found in the specified country\n") + print( + "No latet economy calendar events found in the specified country with this impact\n" + ) return - if ns_parser.impact != "all": - df_econ_calendar = df_econ_calendar[ - df_econ_calendar["impact"] == ns_parser.impact - ] + df_econ_calendar = df_econ_calendar.fillna("").head(n=num) - if df_econ_calendar.empty: - print( - "No latet economy calendar events found in the specified country with this impact\n" - ) - return + d_econ_calendar_map = { + "actual": "Actual release", + "prev": "Previous release", + "country": "Country", + "unit": "Unit", + "estimate": "Estimate", + "event": "Event", + "impact": "Impact Level", + "time": "Release time", + } - df_econ_calendar = df_econ_calendar.fillna("---").head(n=ns_parser.num) + df_econ_calendar = df_econ_calendar[ + ["time", "event", "impact", "prev", "estimate", "actual", "unit"] + ].rename(columns=d_econ_calendar_map) - d_econ_calendar_map = { - "actual": "Actual release", - "prev": "Previous release", - "country": "Country", - "unit": "Unit", - "estimate": "Estimate", - "event": "Event", - "impact": "Impact Level", - "time": "Release time", - } + df_econ_calendar.replace("", float("NaN"), inplace=True) + df_econ_calendar.dropna(how="all", axis=1, inplace=True) - df_econ_calendar = df_econ_calendar[ - ["time", "event", "impact", "prev", "estimate", "actual", "unit"] - ].rename(columns=d_econ_calendar_map) + print( + tabulate( + df_econ_calendar, + headers=df_econ_calendar.columns, + showindex=False, + floatfmt=".2f", + tablefmt="fancy_grid", + ) + ) + print("") - print(df_econ_calendar.to_string(index=False)) - print("") - - except Exception as e: - print(e, "\n") + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "events", + df_econ_calendar, + ) diff --git a/gamestonk_terminal/economy/finviz_model.py b/gamestonk_terminal/economy/finviz_model.py new file mode 100644 index 00000000000..80e151ff09f --- /dev/null +++ b/gamestonk_terminal/economy/finviz_model.py @@ -0,0 +1,36 @@ +""" Finviz Model """ +__docformat__ = "numpy" + +import pandas as pd +from finvizfinance.group import valuation, performance, spectrum + + +def get_valuation_performance_data(group: str, data_type: str) -> pd.DataFrame: + """Get group (sectors, industry or country) valuation/performance data + + Parameters + ---------- + group : str + sectors, industry or country + data_type : str + valuation or performance + + Returns + ---------- + pd.DataFrame + dataframe with valuation/performance data + """ + if data_type == "valuation": + return valuation.Valuation().ScreenerView(group=group) + return performance.Performance().ScreenerView(group=group) + + +def get_spectrum_data(group: str): + """Get group (sectors, industry or country) valuation/performance data + + Parameters + ---------- + group : str + sectors, industry or country + """ + spectrum.Spectrum().ScreenerView(group=group) diff --git a/gamestonk_terminal/economy/finviz_view.py b/gamestonk_terminal/economy/finviz_view.py new file mode 100644 index 00000000000..4863a9f66d8 --- /dev/null +++ b/gamestonk_terminal/economy/finviz_view.py @@ -0,0 +1,73 @@ +""" Finviz View """ +__docformat__ = "numpy" + +import os +import webbrowser +from tabulate import tabulate +from PIL import Image +from gamestonk_terminal.economy import finviz_model +from gamestonk_terminal.helper_funcs import export_data + + +def map_sp500_view(period: str, map_type: str): + """Opens Finviz map website in a browser. [Source: Finviz] + + Parameters + ---------- + period : str + Performance period + map_type : str + Map filter type + """ + # Conversion from period and type, to fit url requirements + d_period = {"1d": "", "1w": "w1", "1m": "w4", "3m": "w13", "6m": "w26", "1y": "w52"} + d_type = {"sp500": "sec", "world": "geo", "full": "sec_all", "etf": "etf"} + # TODO: Try to get this image and output it instead of opening browser + webbrowser.open( + f"https://finviz.com/map.ashx?t={d_type[map_type]}&st={d_period[period]}" + ) + print("") + + +def view_group_data(s_group: str, data_type: str, export: str): + """View group (sectors, industry or country) valuation/performance/spectrum data + + Parameters + ---------- + s_group : str + group between sectors, industry or country + data_type : str + select data type to see data between valuation, performance and spectrum + export : str + Export dataframe data to csv,json,xlsx file + """ + if data_type in ("valuation", "performance"): + df_group = finviz_model.get_valuation_performance_data(s_group, data_type) + print( + tabulate( + df_group.fillna(""), + showindex=False, + floatfmt=".2f", + headers=df_group.columns, + tablefmt="fancy_grid", + ), + "\n", + ) + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + data_type, + df_group, + ) + + elif data_type == "spectrum": + finviz_model.get_spectrum_data(s_group) + + img = Image.open(s_group + ".jpg") + img.show() + + else: + print( + "Invalid data type. Choose between valuation, performance and spectrum.\n" + ) diff --git a/gamestonk_terminal/economy/fred_model.py b/gamestonk_terminal/economy/fred_model.py new file mode 100644 index 00000000000..1e98e53f3b2 --- /dev/null +++ b/gamestonk_terminal/economy/fred_model.py @@ -0,0 +1,98 @@ +""" Fred View """ +__docformat__ = "numpy" + +from typing import List, Tuple +import pandas as pd +import fred +from fredapi import Fred + +from gamestonk_terminal import config_terminal as cfg + + +def get_series_notes(series_term: str, num: int) -> str: + """Get Series notes. [Source: FRED] + + Parameters + ---------- + series_term : str + Search for this series term + num : int + Maximum number of series notes to display + + Returns + ---------- + notes : str + Series notes output + """ + fred.key(cfg.API_FRED_KEY) + d_series = fred.search(series_term) + if "seriess" not in d_series: + return "No Series found using this term!\n" + + df_fred = pd.DataFrame(d_series["seriess"]) + if df_fred.empty: + return "No Series found using this term!\n" + + df_fred = df_fred.sort_values(by=["popularity"], ascending=False).head(num) + + notes = "" + for _, series in df_fred.iterrows(): + if series["notes"]: + notes += series["id"] + "\n" + notes += "-" * len(series["id"]) + "\n" + notes += series["notes"] + "\n\n" + + if not notes: + return "Series notes not found!\n" + + return notes + + +def get_series_ids(series_term: str, num: int) -> Tuple[List[str], List[str]]: + """Get Series IDs. [Source: FRED] + + Parameters + ---------- + series_term : str + Search for this series term + num : int + Maximum number of series IDs to output + + Returns + ---------- + List[str] + List of series IDs + List[str] + List of series Titles + """ + fred.key(cfg.API_FRED_KEY) + d_series = fred.search(series_term) + + if "seriess" not in d_series: + return [], [] + + if not d_series["seriess"]: + return [], [] + + df_series = pd.DataFrame(d_series["seriess"]) + df_series = df_series.sort_values(by=["popularity"], ascending=False).head(num) + return df_series["id"].values, df_series["title"].values + + +def get_series_data(series_id: str, start: str): + """Get Series data. [Source: FRED] + + Parameters + ---------- + series_id : str + Series ID to get data from + start : str + Start date to get data from, format yyyy-mm-dd + + Returns + ---------- + pd.DataFrame + Series data + """ + fredapi_client = Fred(cfg.API_FRED_KEY) + return fredapi_client.get_series(series_id, start) diff --git a/gamestonk_terminal/economy/fred_view.py b/gamestonk_terminal/economy/fred_view.py index e5dbdd142ef..aa30b738465 100644 --- a/gamestonk_terminal/economy/fred_view.py +++ b/gamestonk_terminal/economy/fred_view.py @@ -1,194 +1,145 @@ """ Fred View """ __docformat__ = "numpy" -import argparse -from typing import List -import pandas as pd +import os +from tabulate import tabulate from pandas.plotting import register_matplotlib_converters +import pandas as pd import matplotlib.pyplot as plt -from fredapi import Fred -from gamestonk_terminal.helper_funcs import ( - parse_known_args_and_warn, - valid_date, - plot_autoscale, -) +from gamestonk_terminal.economy import fred_model +from gamestonk_terminal.helper_funcs import plot_autoscale, export_data from gamestonk_terminal.config_plot import PLOT_DPI -from gamestonk_terminal import config_terminal as cfg from gamestonk_terminal import feature_flags as gtff register_matplotlib_converters() -fred_series_description = { - "VIXCLS": "Volatility Index", - "GDP": "Gross Domestic Product", - "UNRATE": "Unemployment Rate", - "DGS1": "1-Year Treasury Constant Maturity Rate", - "DGS5": "5-Year Treasury Constant Maturity Rate", - "DGS10": "10-Year Treasury Constant Maturity Rate", - "DGS30": "30-Year Treasury Constant Maturity Rate", - "MORTGAGE30US": "30-Year Mortgage Rate", - "FEDFUNDS": "Effective Federal Funds Rate", - "AAA": "Moody's Seasoned AAA Corporate Bond Yield", - "DEXCAUS": "Canada / U.S. Foreign Exchange Rate", -} - - -def display_fred(other_args: List[str], choice: str): - """Display customized Federal Reserve Economic Data (FRED) from https://fred.stlouisfed.org. - It is possible to display multiple series. +def notes(series_term: str, num: int): + """Print Series notes. [Source: FRED] Parameters ---------- - other_args : List[str] - argparse other args - choice : str - Fred data series: "VIXCLS", "GDP", "DGS1", "DGS5", "DGS10", "DGS30", "MORTGAGE30US", "FEDFUNDS", - "AAA", "DEXCAUS", "UNRATE", + series_term : str + Search for these series_term + num : int + Maximum number of series notes to display """ + print(fred_model.get_series_notes(series_term, num)) - parser = argparse.ArgumentParser( - add_help=False, - prog=choice if choice else "fred", - description=""" - Display customized Federal Reserve Economic Data (FRED) from https://fred.stlouisfed.org. - It is possible to display multiple series. - """, - ) - parser.add_argument( - "-i", - "--id", - dest="series_id", - required=not bool(choice) and "-h" not in other_args, - type=str, - default=choice.upper(), - help="FRED Series ID from https://fred.stlouisfed.org. For multiple series use: series1,series2,series3", - ) +def display_series(series: str, start_date: str, raw: bool, export: str): + """Display (multiple) series from https://fred.stlouisfed.org. [Source: FRED] - parser.add_argument( - "-s", - dest="start_date", - type=valid_date, - default="2019-01-01", - help="Starting date (YYYY-MM-DD) of data", - ) + Parameters + ---------- + series : str + FRED Series ID from https://fred.stlouisfed.org. For multiple series use: series1,series2,series3 + start_date : str + Starting date (YYYY-MM-DD) of data + raw : bool + Output only raw data + export : str + Export dataframe data to csv,json,xlsx file + """ + if export: + l_series_fred = list() - parser.add_argument( - "-t", - "--text", - action="store_true", - dest="text", - help="Only output text data", - ) + if not raw: + _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) + ax.axes.get_yaxis().set_visible(False) + plt.subplots_adjust(right=0.9 - series.count(",") * 0.1) + l_colors = [ + "tab:blue", + "tab:orange", + "tab:green", + "tab:red", + "tab:purple", + "tab:brown", + "tab:pink", + "tab:gray", + "tab:olive", + "tab:cyan", + ] - try: - if not choice: - if other_args: - if "-" not in other_args[0]: - other_args.insert(0, "-i") - ns_parser = parse_known_args_and_warn(parser, other_args) + l_ts_start = list() + l_ts_end = list() + p = {} + success = -1 + success_series = list() + success_titles = list() - if not ns_parser: - return + for serie_term in series.split(","): + if serie_term: + l_series, l_title = fred_model.get_series_ids(serie_term, 5) - fred = Fred(api_key=cfg.API_FRED_KEY) + if len(l_series) == 0: + print(f"No series found for term '{serie_term}'\n") + continue - if "," in ns_parser.series_id: - if not ns_parser.text: - l_colors = [ - "tab:blue", - "tab:orange", - "tab:green", - "tab:red", - "tab:purple", - "tab:brown", - "tab:pink", - "tab:gray", - "tab:olive", - "tab:cyan", - ] - l_ts_start = list() - l_ts_end = list() - p = {} - _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) - ax.axes.get_yaxis().set_visible(False) - plt.subplots_adjust(right=0.9 - ns_parser.series_id.count(",") * 0.1) + print(f"For '{serie_term}', series IDs found: {', '.join(l_series)}.\n") - series = ns_parser.series_id.split(",") + ser = l_series[0] + ser_title = l_title[0] + df_fred = fred_model.get_series_data(ser, start_date) - success = -1 - success_series = list() - for series_id in series: - try: - d_data = fred.get_series(series_id, ns_parser.start_date) - success += 1 - success_series.append(series_id.upper()) - except Exception: - print(f"Series '{series_id}' doesn't exist!") - continue + if export: + l_series_fred.append(df_fred) - df_fred = pd.DataFrame(d_data, columns=[f"{series_id}"]) - df_fred.index.name = "Date" - - if ns_parser.text: - print(df_fred.dropna().to_string(), "\n") - - else: - axes = ax.twinx() - axes.spines["right"].set_position(("axes", 1 + success * 0.15)) - axes.spines["right"].set_color(l_colors[success]) - (p[success],) = axes.plot( - df_fred.index, - df_fred.iloc[:, 0], - c=l_colors[success], - label=series_id.upper(), - ) - - axes.yaxis.label.set_color(l_colors[success]) - - l_ts_start.append(df_fred.index[0]) - l_ts_end.append(df_fred.index[-1]) - - if not ns_parser.text and success: - plt.title("FRED: " + ", ".join(success_series)) - plt.xlim(min(l_ts_start), max(l_ts_end)) - plt.gcf().autofmt_xdate() - plt.xlabel("Time") - plt.legend([val for _, val in p.items()], success_series) - plt.gca().spines["left"].set_visible(False) - plt.show() - print("") - - else: - d_data = fred.get_series(ns_parser.series_id, ns_parser.start_date) - - df_fred = pd.DataFrame(d_data, columns=[f"{ns_parser.series_id}"]) df_fred.index.name = "Date" - if ns_parser.text: - print(df_fred.to_string()) + if raw: + df_fred.index = df_fred.index.strftime("%d/%m/%Y") + print( + tabulate( + df_fred.dropna().to_frame(), + showindex=True, + headers=[f"{ser}: {ser_title}"], + tablefmt="fancy_grid", + floatfmt=".2f", + ), + "\n", + ) else: - plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI) - plt.plot(df_fred.index, df_fred.iloc[:, 0]) - plt.xlabel("Time") - plt.xlim(df_fred.index[0], df_fred.index[-1]) - plt.ylabel(f"{ns_parser.series_id.upper()}") - plt.grid(b=True, which="major", color="#666666", linestyle="-") - plt.minorticks_on() - plt.grid( - b=True, which="minor", color="#999999", linestyle="-", alpha=0.2 - ) - if choice: - plt.title(fred_series_description[ns_parser.series_id]) - if gtff.USE_ION: - plt.ion() - plt.show() - print("") + success += 1 + success_series.append(ser.upper()) + success_titles.append(ser_title) - except SystemExit: - print("") - except Exception as e: - print(e, "\n") - return + axes = ax.twinx() + axes.spines["right"].set_position(("axes", 1 + success * 0.15)) + axes.spines["right"].set_color(l_colors[success]) + (p[success],) = axes.plot( + df_fred.index, + df_fred.values, + c=l_colors[success], + label=ser.upper(), + ) + + axes.yaxis.label.set_color(l_colors[success]) + + l_ts_start.append(df_fred.index[0]) + l_ts_end.append(df_fred.index[-1]) + + if not raw and success > -1: + plt.title("FRED: " + ", ".join(success_series)) + plt.xlim(min(l_ts_start), max(l_ts_end)) + plt.gcf().autofmt_xdate() + plt.xlabel("Time") + plt.legend( + [val for _, val in p.items()], success_titles, loc="best", prop={"size": 6} + ) + plt.gca().spines["left"].set_visible(False) + if gtff.USE_ION: + plt.ion() + plt.show() + + if export: + df_data = pd.concat(l_series_fred, axis=1) + df_data.columns = success_series + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "series", + df_data, + ) diff --git a/gamestonk_terminal/economy/wsj_model.py b/gamestonk_terminal/economy/wsj_model.py index 977980ac043..508f43088d1 100644 --- a/gamestonk_terminal/economy/wsj_model.py +++ b/gamestonk_terminal/economy/wsj_model.py @@ -5,8 +5,8 @@ import pandas as pd def us_indices() -> pd.DataFrame: - """ - Get the top US indices + """Get the top US indices + Returns ------- indices: pd.DataFrame @@ -42,8 +42,8 @@ def us_indices() -> pd.DataFrame: def market_overview() -> pd.DataFrame: - """ - Scrape data for market overview + """Scrape data for market overview + Returns ------- overview: pd.DataFrame @@ -77,8 +77,8 @@ def market_overview() -> pd.DataFrame: def top_commodities() -> pd.DataFrame: - """ - Scrape data for top commodities + """Scrape data for top commodities + Returns ------- commodities: pd.DataFrame @@ -113,8 +113,8 @@ def top_commodities() -> pd.DataFrame: def us_bonds() -> pd.DataFrame: - """ - Scrape data for us bonds + """Scrape data for us bonds + Returns ------- bonds: pd.DataFrame @@ -150,8 +150,8 @@ def us_bonds() -> pd.DataFrame: def global_bonds() -> pd.DataFrame: - """ - Scrape data for global bonds + """Scrape data for global bonds + Returns ------- bonds: pd.DataFrame @@ -182,8 +182,8 @@ def global_bonds() -> pd.DataFrame: def global_currencies() -> pd.DataFrame: - """ - Scrape data for global currencies + """Scrape data for global currencies + Returns ------- currencies: pd.DataFrame diff --git a/gamestonk_terminal/economy/wsj_view.py b/gamestonk_terminal/economy/wsj_view.py index 196487d0fee..5d04c68a5e7 100644 --- a/gamestonk_terminal/economy/wsj_view.py +++ b/gamestonk_terminal/economy/wsj_view.py @@ -1,224 +1,199 @@ """WSJ view """ __docformat__ = "numpy" -import argparse -from typing import List +import os from tabulate import tabulate - -from gamestonk_terminal.economy.wsj_model import ( - market_overview, - us_bonds, - us_indices, - global_bonds, - global_currencies, - top_commodities, -) -from gamestonk_terminal.helper_funcs import parse_known_args_and_warn +from gamestonk_terminal.economy import wsj_model +from gamestonk_terminal.helper_funcs import export_data -def display_overview(other_args: List[str]): - """Display market overview +def display_overview(export: str): + """Market overview. [Source: Wall St. Journal] Parameters ---------- - other_args: List[str] - Argparse arguments + export : str + Export dataframe data to csv,json,xlsx file """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="overview", - description="WSJ market overview", - ) - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return - data = market_overview() - print( - tabulate( - data, - showindex=False, - headers=data.columns, - floatfmt=".2f", - tablefmt="fancy_grid", - ) + df_data = wsj_model.market_overview() + if df_data.empty: + print("No overview data available\n") + return + + print( + tabulate( + df_data, + showindex=False, + headers=df_data.columns, + floatfmt=".2f", + tablefmt="fancy_grid", ) - print("") + ) + print("") - except Exception as e: - print(e, "\n") + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "overview", + df_data, + ) -def display_indices(other_args: List[str]): - """Display us indices +def display_indices(export: str): + """US indices. [Source: Wall St. Journal] Parameters ---------- - other_args: List[str] - Argparse arguments + export : str + Export dataframe data to csv,json,xlsx file """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="indices", - description="WSJ US Indices", - ) - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return + df_data = wsj_model.us_indices() + if df_data.empty: + print("No indices data available\n") + return - data = us_indices() - print( - tabulate( - data, - showindex=False, - headers=data.columns, - floatfmt=".2f", - tablefmt="fancy_grid", - ) + print( + tabulate( + df_data, + showindex=False, + headers=df_data.columns, + floatfmt=".2f", + tablefmt="fancy_grid", ) - print("") + ) + print("") - except Exception as e: - print(e, "\n") + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "indices", + df_data, + ) -def display_futures(other_args: List[str]): - """Display futures/commodities +def display_futures(export: str): + """Futures/Commodities. [Source: Wall St. Journal] Parameters ---------- - other_args: List[str] - Argparse arguments + export : str + Export dataframe data to csv,json,xlsx file """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="futures", - description="WSJ futures/commodities", - ) - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return - data = top_commodities() - print( - tabulate( - data, - showindex=False, - headers=data.columns, - floatfmt=".2f", - tablefmt="fancy_grid", - ) + df_data = wsj_model.top_commodities() + if df_data.empty: + print("No futures/commodities data available\n") + return + + print( + tabulate( + df_data, + showindex=False, + headers=df_data.columns, + floatfmt=".2f", + tablefmt="fancy_grid", ) - print("") + ) + print("") - except Exception as e: - print(e, "\n") + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "futures", + df_data, + ) -def display_usbonds(other_args: List[str]): - """Display us bonds overview +def display_usbonds(export: str): + """US bonds. [Source: Wall St. Journal] Parameters ---------- - other_args: List[str] - Argparse arguments + export : str + Export dataframe data to csv,json,xlsx file """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="usbonds", - description="WSJ US Bonds overview", - ) - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return + df_data = wsj_model.us_bonds() + if df_data.empty: + print("No US bonds data available\n") + return - data = us_bonds() - print( - tabulate( - data, - showindex=False, - headers=data.columns, - floatfmt=".2f", - tablefmt="fancy_grid", - ) + print( + tabulate( + df_data, + showindex=False, + headers=df_data.columns, + floatfmt=".2f", + tablefmt="fancy_grid", ) - print("") + ) + print("") - except Exception as e: - print(e, "\n") + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "usbonds", + df_data, + ) -def display_glbonds(other_args: List[str]): - """Display global bond overview +def display_glbonds(export: str): + """Global bonds. [Source: Wall St. Journal] Parameters ---------- - other_args: List[str] - Argparse arguments + export : str + Export dataframe data to csv,json,xlsx file """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="glbond", - description="WSJ global bond overview", - ) - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return + df_data = wsj_model.global_bonds() + if df_data.empty: + print("No global bonds data available\n") + return - data = global_bonds() - print( - tabulate( - data, - showindex=False, - headers=data.columns, - floatfmt=".2f", - tablefmt="fancy_grid", - ) + print( + tabulate( + df_data, + showindex=False, + headers=df_data.columns, + floatfmt=".2f", + tablefmt="fancy_grid", ) - print("") + ) + print("") - except Exception as e: - print(e, "\n") + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "glbonds", + df_data, + ) -def display_currencies(other_args: List[str]): - """Display global currencies +def display_currencies(export: str): + """Display currencies. [Source: Wall St. Journal] Parameters ---------- - other_args: List[str] - Argparse arguments + export : str + Export dataframe data to csv,json,xlsx file """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="currencies", - description="WSJ currency overview", - ) - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return + df_data = wsj_model.global_currencies() + if df_data.empty: + print("No currencies data available\n") + return - data = global_currencies() - print( - tabulate( - data, - showindex=False, - headers=data.columns, - floatfmt=".2f", - tablefmt="fancy_grid", - ) + print( + tabulate( + df_data, + showindex=False, + headers=df_data.columns, + floatfmt=".2f", + tablefmt="fancy_grid", ) - print("") + ) + print("") - except Exception as e: - print(e, "\n") + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "currencies", + df_data, + ) diff --git a/gamestonk_terminal/stocks/discovery/alpha_vantage_view.py b/gamestonk_terminal/stocks/discovery/alpha_vantage_view.py deleted file mode 100644 index 496b40cc9d0..00000000000 --- a/gamestonk_terminal/stocks/discovery/alpha_vantage_view.py +++ /dev/null @@ -1,54 +0,0 @@ -""" Alpha Vantage View """ -__docformat__ = "numpy" - -import argparse -from typing import List -import matplotlib.pyplot as plt -from alpha_vantage.sectorperformance import SectorPerformances -from gamestonk_terminal import config_terminal as cfg -from gamestonk_terminal.helper_funcs import parse_known_args_and_warn -from gamestonk_terminal import feature_flags as gtff - - -def sectors_view(other_args: List[str]): - """Opens a bar chart with sector performance - - Parameters - ---------- - other_args : List[str] - argparse other args - """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="sectors", - description=""" - Real-time and historical sector performances calculated from - S&P500 incumbents. Pops plot in terminal. [Source: Alpha Vantage] - """, - ) - - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return - - sector_perf = SectorPerformances( - key=cfg.API_KEY_ALPHAVANTAGE, output_format="pandas" - ) - # pylint: disable=unbalanced-tuple-unpacking - df_sectors, _ = sector_perf.get_sector() - # pylint: disable=invalid-sequence-index - df_sectors["Rank A: Real-Time Performance"].plot(kind="bar") - plt.title("Real Time Performance (%) per Sector") - plt.tight_layout() - plt.grid() - - if gtff.USE_ION: - plt.ion() - - plt.show() - print("") - - except Exception as e: - print(e, "\n") diff --git a/gamestonk_terminal/stocks/discovery/disc_controller.py b/gamestonk_terminal/stocks/discovery/disc_controller.py index c24a3ae697d..9cd42da9f74 100644 --- a/gamestonk_terminal/stocks/discovery/disc_controller.py +++ b/gamestonk_terminal/stocks/discovery/disc_controller.py @@ -10,10 +10,8 @@ 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.stocks.discovery import ( - alpha_vantage_view, ark_view, fidelity_view, - finviz_view, seeking_alpha_view, short_interest_view, simply_wallst_view, @@ -38,8 +36,6 @@ class DiscoveryController: "q", "quit", "ipo", - "map", - "rtp_sectors", "gainers", "losers", "orders", @@ -50,9 +46,6 @@ class DiscoveryController: "simply_wallst", "spachero", "uwhales", - "valuation", - "performance", - "spectrum", "latest", "trending", "darkpool", @@ -64,7 +57,6 @@ class DiscoveryController: def __init__(self): """Constructor""" - self.spectrum_img_to_delete = "" self.disc_parser = argparse.ArgumentParser(add_help=False, prog="disc") self.disc_parser.add_argument( "cmd", @@ -84,8 +76,6 @@ class DiscoveryController: print(" quit quit to abandon program") print("") print(" ipo past and future IPOs [Finnhub]") - print(" map S&P500 index stocks map [Finviz]") - print(" rtp_sectors real-time performance sectors [Alpha Vantage]") print(" gainers show latest top gainers [Yahoo Finance]") print(" losers show latest top losers [Yahoo Finance]") print(" orders orders by Fidelity Customers [Fidelity]") @@ -102,9 +92,6 @@ class DiscoveryController: print(" simply_wallst Simply Wall St. research data [Simply Wall St.]") print(" spachero great website for SPACs research [SpacHero]") print(" uwhales good website for SPACs research [UnusualWhales]") - print(" valuation valuation of sectors, industry, country [Finviz]") - print(" performance performance of sectors, industry, country [Finviz]") - print(" spectrum spectrum of sectors, industry, country [Finviz]") print(" latest latest news [Seeking Alpha]") print(" trending trending news [Seeking Alpha]") print( @@ -137,14 +124,6 @@ class DiscoveryController: (known_args, other_args) = self.disc_parser.parse_known_args(an_input.split()) - # Due to Finviz implementation of Spectrum, we delete the generated spectrum figure - # after saving it and displaying it to the user - if self.spectrum_img_to_delete: - # Confirm that file exists - if os.path.isfile(self.spectrum_img_to_delete + ".jpg"): - os.remove(self.spectrum_img_to_delete + ".jpg") - self.spectrum_img_to_delete = "" - # Help menu again if known_args.cmd == "?": self.print_help() @@ -175,14 +154,6 @@ class DiscoveryController: """Process ipo command""" finnhub_view.ipo_calendar(other_args) - def call_map(self, other_args: List[str]): - """Process map command""" - finviz_view.map_sp500_view(other_args) - - def call_rtp_sectors(self, other_args: List[str]): - """Process rtp_sectors command""" - alpha_vantage_view.sectors_view(other_args) - def call_gainers(self, other_args: List[str]): """Process gainers command""" yahoo_finance_view.gainers_view(other_args) @@ -223,20 +194,6 @@ class DiscoveryController: """Process uwhales command""" unusual_whales_view.unusual_whales_view(other_args) - def call_valuation(self, other_args: List[str]): - """Process valuation command""" - finviz_view.view_group_data(other_args, "valuation") - - def call_performance(self, other_args: List[str]): - """Process performance command""" - finviz_view.view_group_data(other_args, "performance") - - def call_spectrum(self, other_args: List[str]): - """Process spectrum command""" - self.spectrum_img_to_delete = finviz_view.view_group_data( - other_args, "spectrum" - ) - def call_latest(self, other_args: List[str]): """Process latest command""" seeking_alpha_view.latest_news_view(other_args) diff --git a/gamestonk_terminal/stocks/discovery/finviz_view.py b/gamestonk_terminal/stocks/discovery/finviz_view.py deleted file mode 100644 index 7cfd31e3185..00000000000 --- a/gamestonk_terminal/stocks/discovery/finviz_view.py +++ /dev/null @@ -1,182 +0,0 @@ -""" Finviz View """ -__docformat__ = "numpy" - -import argparse -from typing import List -import webbrowser -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", - "Industry (Basic Materials)", - "Industry (Communication Services)", - "Industry (Consumer Cyclical)", - "Industry (Consumer Defensive)", - "Industry (Energy)", - "Industry (Financial)", - "Industry (Healthcare)", - "Industry (Industrials)", - "Industry (Real Estate)", - "Industry (Technology)", - "Industry (Utilities)", - "Country (U.S. listed stocks only)", - "Capitalization", -] - - -def map_sp500_view(other_args: List[str]): - """Opens Finviz website in a browser - - Parameters - ---------- - other_args : List[str] - argparse other args - """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="map", - description=""" - Performance index stocks map categorized by sectors and industries. - Size represents market cap. Opens web-browser. [Source: Finviz] - """, - ) - parser.add_argument( - "-p", - "--period", - action="store", - dest="s_period", - type=str, - default="1d", - choices=["1d", "1w", "1m", "3m", "6m", "1y"], - help="Performance period.", - ) - parser.add_argument( - "-t", - "--type", - action="store", - dest="s_type", - type=str, - default="sp500", - choices=["sp500", "world", "full", "etf"], - help="Map filter type.", - ) - - # Conversion from period and type, to fit url requirements - d_period = {"1d": "", "1w": "w1", "1m": "w4", "3m": "w13", "6m": "w26", "1y": "w52"} - d_type = {"sp500": "sec", "world": "geo", "full": "sec_all", "etf": "etf"} - - try: - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return - - webbrowser.open( - f"https://finviz.com/map.ashx?t={d_type[ns_parser.s_type]}&st={d_period[ns_parser.s_period]}" - ) - print("") - - except Exception as e: - print(e, "\n") - - -def get_valuation_performance_data(group: str, data_type: str): - """Get group (sectors, industry or country) valuation/performance data - - Parameters - ---------- - group : str - sectors, industry or country - data_type : str - valuation or performance - - Returns - ---------- - pd.DataFrame - dataframe with valuation/performance data - """ - if data_type == "valuation": - return valuation.Valuation().ScreenerView(group=group) - return performance.Performance().ScreenerView(group=group) - - -def get_spectrum_data(group: str): - """Get group (sectors, industry or country) valuation/performance data - - Parameters - ---------- - group : str - sectors, industry or country - """ - spectrum.Spectrum().ScreenerView(group=group) - - -def view_group_data(other_args: List[str], data_type: str): - """View group (sectors, industry or country) valuation/performance/spectrum data - - Parameters - ---------- - other_args : List[str] - argparse other args - data_type : str - select data type to see data between valuation, performance and spectrum - """ - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="group_data", - description=""" - View group (sectors, industry or country) valuation/performance/spectrum data. [Source: Finviz] - """, - ) - parser.add_argument( - "-g", - "--group", - nargs="+", - type=str, - default="Sector", - dest="group", - help="Data group (sector, industry or country)", - choices=l_GROUPS, - ) - - try: - if other_args: - if "-" not in other_args[0]: - other_args.insert(0, "-g") - other_args = [other_args[0], " ".join(other_args[1:])] - - ns_parser = parse_known_args_and_warn(parser, other_args) - if not ns_parser: - return "" - - if isinstance(ns_parser.group, List): - ns_parser.group = ns_parser.group[0] - - if data_type in ("valuation", "performance"): - df_group = get_valuation_performance_data(ns_parser.group, data_type) - print(df_group.to_string()) - print("") - - elif data_type == "spectrum": - get_spectrum_data(ns_parser.group) - - img = Image.open(ns_parser.group + ".jpg") - img.show() - - print("") - return ns_parser.group - - else: - print( - "Invalid data type. Choose between valuation, performance and spectrum.\n" - ) - return "" - - except SystemExit: - print("") - return "" diff --git a/poetry.lock b/poetry.lock index fc58664c0cb..e476fd93ce5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -651,6 +651,17 @@ category = "main" optional = true python-versions = "*" +[[package]] +name = "fred" +version = "3.1" +description = "St. Louis Federal Reserve FRED API" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +requests = "*" + [[package]] name = "fredapi" version = "0.4.3" @@ -3052,7 +3063,7 @@ prediction = ["tensorflow", "pmdarima"] [metadata] lock-version = "1.1" python-versions = "^3.6.8" -content-hash = "90b9e9207f1a4680fc23f634392afb9c45bbc0227f36c6b6c1a1afde4dcdcb12" +content-hash = "152e3c597c933d00b15ee5c1ba97452112ae228c8995e0780303a378b5906a24" [metadata.files] absl-py = [ @@ -3141,10 +3152,6 @@ argon2-cffi = [ {file = "argon2_cffi-20.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:9dfd5197852530294ecb5795c97a823839258dfd5eb9420233c7cfedec2058f2"}, {file = "argon2_cffi-20.1.0-cp39-cp39-win32.whl", hash = "sha256:e2db6e85c057c16d0bd3b4d2b04f270a7467c147381e8fd73cbbe5bc719832be"}, {file = "argon2_cffi-20.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:8a84934bd818e14a17943de8099d41160da4a336bcc699bb4c394bbb9b94bd32"}, - {file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-macosx_10_7_x86_64.whl", hash = "sha256:b94042e5dcaa5d08cf104a54bfae614be502c6f44c9c89ad1535b2ebdaacbd4c"}, - {file = "argon2_cffi-20.1.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:8282b84ceb46b5b75c3a882b28856b8cd7e647ac71995e71b6705ec06fc232c3"}, - {file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3aa804c0e52f208973845e8b10c70d8957c9e5a666f702793256242e9167c4e0"}, - {file = "argon2_cffi-20.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:36320372133a003374ef4275fbfce78b7ab581440dfca9f9471be3dd9a522428"}, ] astroid = [ {file = "astroid-2.6.5-py3-none-any.whl", hash = "sha256:7b963d1c590d490f60d2973e57437115978d3a2529843f160b5003b721e1e925"}, @@ -3307,8 +3314,6 @@ cssselect = [ {file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"}, ] cvxpy = [ - {file = "cvxpy-1.1.12-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:48e9bae36a43453659ca5d0c85e78f1eb0dfe629b8aa0f023f65aa59d0ac04d7"}, - {file = "cvxpy-1.1.12-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fe0bcb7f83b5d4deb760bf033cb72ab97c8e0770b116e08d96e9726cb1a52c01"}, {file = "cvxpy-1.1.12-cp36-cp36m-win_amd64.whl", hash = "sha256:86f8e4aa1a79482431b89aa526249d9fda04c74e04a3ec224d1175d281643d71"}, {file = "cvxpy-1.1.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:90b09a7361b9c614166fa673e1fe9321317df6939135330e1621b9a0bf10e3a8"}, {file = "cvxpy-1.1.12-cp37-cp37m-win_amd64.whl", hash = "sha256:084e5292f2a13133a1cd28d68f5af1df33a5119b0f1aec7cecf834eea3e2d11d"}, @@ -3316,8 +3321,6 @@ cvxpy = [ {file = "cvxpy-1.1.12-cp38-cp38-win_amd64.whl", hash = "sha256:76d04444cb50ad2840bbc72a625ac246b5eeeeb580ee20c71bec057822667738"}, {file = "cvxpy-1.1.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2de5e0e75316839bc71b5df2c2db0131cee7ef06dac566c6c44dc852c091502b"}, {file = "cvxpy-1.1.12-cp39-cp39-win_amd64.whl", hash = "sha256:9fa4d033ab31855aea090e4b358017b36880390a7d0e6e97ecc5226c77eab489"}, - {file = "cvxpy-1.1.12-py3.5-macosx-10.9-x86_64.egg", hash = "sha256:27ff263c80700b097d3714ba34161bd284f736f3029dfa89a95bf4c4a2801cb9"}, - {file = "cvxpy-1.1.12-py3.6-macosx-10.7-x86_64.egg", hash = "sha256:7c1c5371dda78580f0892fba6776abb6e43bdb45589311c3179a057f1a984110"}, {file = "cvxpy-1.1.12-py3.6-win-amd64.egg", hash = "sha256:d2c28e0eea1b6dc70262c9ed8b63c5c1747d85c28b3ec24cbaab07583b3ad729"}, {file = "cvxpy-1.1.12-py3.7-win-amd64.egg", hash = "sha256:44d0e3d60693831ac70bdc9b2e23faf84401347bfcdef4eb5da5ae22ac57f5ff"}, {file = "cvxpy-1.1.12-py3.8-win-amd64.egg", hash = "sha256:c86f8de9a63ccbd45844a4482df8099824688b5329060f089aad1c3beb939190"}, @@ -3427,10 +3430,6 @@ entrypoints = [ {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, ] -et-xmlfile = [ - {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"}, - {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"}, -] fear-greed-index = [ {file = "fear-greed-index-0.1.3.tar.gz", hash = "sha256:5ba5286ee29b2b35147a93da353899e30abf1715decf943183399e4f057a2d87"}, {file = "fear_greed_index-0.1.3-py3-none-any.whl", hash = "sha256:0bdccdce61a408172187254dced6e1033c6126620d4694aaccc5ce09f4001921"}, @@ -3454,6 +3453,9 @@ flatbuffers = [ {file = "flatbuffers-1.12-py2.py3-none-any.whl", hash = "sha256:9e9ef47fa92625c4721036e7c4124182668dc6021d9e7c73704edd395648deb9"}, {file = "flatbuffers-1.12.tar.gz", hash = "sha256:63bb9a722d5e373701913e226135b28a6f6ac200d5cc7b4d919fa38d73b44610"}, ] +fred = [ + {file = "fred-3.1.tar.gz", hash = "sha256:f31327d648917694b8d15d66ca4e82a082dbb88ca027bdcc9d56738cbc836a6a"}, +] fredapi = [ {file = "fredapi-0.4.3-py3-none-any.whl", hash = "sha256:e06075592eabddadfe0635f3c59e9072c9f48647430328b4582171ea10f7df2f"}, {file = "fredapi-0.4.3.tar.gz", hash = "sha256:d9b3194fb60541991bd33f019c710d4a9580ecfb5e47efbf2d2571888a2aac02"}, @@ -3734,40 +3736,30 @@ lxml = [ {file = "lxml-4.6.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4"}, {file = "lxml-4.6.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51"}, {file = "lxml-4.6.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586"}, - {file = "lxml-4.6.3-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:4c61b3a0db43a1607d6264166b230438f85bfed02e8cff20c22e564d0faff354"}, - {file = "lxml-4.6.3-cp35-cp35m-manylinux2014_x86_64.whl", hash = "sha256:5c8c163396cc0df3fd151b927e74f6e4acd67160d6c33304e805b84293351d16"}, {file = "lxml-4.6.3-cp35-cp35m-win32.whl", hash = "sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2"}, {file = "lxml-4.6.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4"}, {file = "lxml-4.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4"}, {file = "lxml-4.6.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3"}, {file = "lxml-4.6.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d"}, - {file = "lxml-4.6.3-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d916d31fd85b2f78c76400d625076d9124de3e4bda8b016d25a050cc7d603f24"}, {file = "lxml-4.6.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec"}, - {file = "lxml-4.6.3-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:c47ff7e0a36d4efac9fd692cfa33fbd0636674c102e9e8d9b26e1b93a94e7617"}, {file = "lxml-4.6.3-cp36-cp36m-win32.whl", hash = "sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04"}, {file = "lxml-4.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a"}, {file = "lxml-4.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654"}, {file = "lxml-4.6.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0"}, {file = "lxml-4.6.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3"}, - {file = "lxml-4.6.3-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:36108c73739985979bf302006527cf8a20515ce444ba916281d1c43938b8bb96"}, {file = "lxml-4.6.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2"}, - {file = "lxml-4.6.3-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:cdaf11d2bd275bf391b5308f86731e5194a21af45fbaaaf1d9e8147b9160ea92"}, {file = "lxml-4.6.3-cp37-cp37m-win32.whl", hash = "sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade"}, {file = "lxml-4.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b"}, {file = "lxml-4.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa"}, {file = "lxml-4.6.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a"}, {file = "lxml-4.6.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927"}, - {file = "lxml-4.6.3-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:e1cbd3f19a61e27e011e02f9600837b921ac661f0c40560eefb366e4e4fb275e"}, {file = "lxml-4.6.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791"}, - {file = "lxml-4.6.3-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:1b38116b6e628118dea5b2186ee6820ab138dbb1e24a13e478490c7db2f326ae"}, {file = "lxml-4.6.3-cp38-cp38-win32.whl", hash = "sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28"}, {file = "lxml-4.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7"}, {file = "lxml-4.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0"}, {file = "lxml-4.6.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1"}, {file = "lxml-4.6.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23"}, - {file = "lxml-4.6.3-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:3082c518be8e97324390614dacd041bb1358c882d77108ca1957ba47738d9d59"}, {file = "lxml-4.6.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969"}, - {file = "lxml-4.6.3-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:6f12e1427285008fd32a6025e38e977d44d6382cf28e7201ed10d6c1698d2a9a"}, {file = "lxml-4.6.3-cp39-cp39-win32.whl", hash = "sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f"}, {file = "lxml-4.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83"}, {file = "lxml-4.6.3.tar.gz", hash = "sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468"}, @@ -4030,10 +4022,6 @@ oauthlib = [ onetimepass = [ {file = "onetimepass-1.0.1.tar.gz", hash = "sha256:a569dac076d6e3761cbc55e36952144a637ca1b075c6d509de1c1dbc5e7f6a27"}, ] -openpyxl = [ - {file = "openpyxl-3.0.7-py2.py3-none-any.whl", hash = "sha256:46af4eaf201a89b610fcca177eed957635f88770a5462fb6aae4a2a52b0ff516"}, - {file = "openpyxl-3.0.7.tar.gz", hash = "sha256:6456a3b472e1ef0facb1129f3c6ef00713cebf62e736cd7a75bcc3247432f251"}, -] opt-einsum = [ {file = "opt_einsum-3.3.0-py3-none-any.whl", hash = "sha256:2455e59e3947d3c275477df7f5205b30635e266fe6dc300e3d9f9646bfcea147"}, {file = "opt_einsum-3.3.0.tar.gz", hash = "sha256:59f6475f77bbc37dcf7cd748519c0ec60722e91e63ca114e68821c0c54a46549"}, @@ -4254,13 +4242,9 @@ protobuf = [ {file = "protobuf-3.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2ae692bb6d1992afb6b74348e7bb648a75bb0d3565a3f5eea5bec8f62bd06d87"}, {file = "protobuf-3.17.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:99938f2a2d7ca6563c0ade0c5ca8982264c484fdecf418bd68e880a7ab5730b1"}, {file = "protobuf-3.17.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6902a1e4b7a319ec611a7345ff81b6b004b36b0d2196ce7a748b3493da3d226d"}, - {file = "protobuf-3.17.3-cp38-cp38-win32.whl", hash = "sha256:59e5cf6b737c3a376932fbfb869043415f7c16a0cf176ab30a5bbc419cd709c1"}, - {file = "protobuf-3.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ebcb546f10069b56dc2e3da35e003a02076aaa377caf8530fe9789570984a8d2"}, {file = "protobuf-3.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ffbd23640bb7403574f7aff8368e2aeb2ec9a5c6306580be48ac59a6bac8bde"}, {file = "protobuf-3.17.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:26010f693b675ff5a1d0e1bdb17689b8b716a18709113288fead438703d45539"}, {file = "protobuf-3.17.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e76d9686e088fece2450dbc7ee905f9be904e427341d289acbe9ad00b78ebd47"}, - {file = "protobuf-3.17.3-cp39-cp39-win32.whl", hash = "sha256:a38bac25f51c93e4be4092c88b2568b9f407c27217d3dd23c7a57fa522a17554"}, - {file = "protobuf-3.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:85d6303e4adade2827e43c2b54114d9a6ea547b671cb63fafd5011dc47d0e13d"}, {file = "protobuf-3.17.3-py2.py3-none-any.whl", hash = "sha256:2bfb815216a9cd9faec52b16fd2bfa68437a44b67c56bee59bc3926522ecb04e"}, {file = "protobuf-3.17.3.tar.gz", hash = "sha256:72804ea5eaa9c22a090d2803813e280fb273b62d5ae497aaf3553d141c4fdd7b"}, ] diff --git a/pyproject.toml b/pyproject.toml index 9cc3d63ec12..7dc4d3d888a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,6 +77,7 @@ fear-greed-index = "^0.1.3" pyEX = "^0.5.0" charset-normalizer = "2.0.1" sentiment-investor = "^2.0.0" +fred = "^3.1" [tool.poetry.dev-dependencies] pytest = "^6.2.2" diff --git a/requirements-full.txt b/requirements-full.txt index 2bca790017f..8532c47febe 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -48,6 +48,7 @@ ffn==0.3.6; python_version >= "2.7" and python_full_version < "3.0.0" or python_ finviz==1.4.2 finvizfinance==0.9.9; python_version >= "3.5" flatbuffers==1.12 +fred==3.1 fredapi==0.4.3 frozendict==2.0.3; python_version >= "3.6" fundamentalanalysis==0.2.11 diff --git a/requirements.txt b/requirements.txt index ce513b543c7..33e2da69b92 100644 --- a/requirements.txt +++ b/requirements.txt @@ -44,6 +44,7 @@ fear-greed-index==0.1.3; python_full_version >= "3.6.8" and python_full_version ffn==0.3.6; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" finviz==1.4.2 finvizfinance==0.9.9; python_version >= "3.5" +fred==3.1 fredapi==0.4.3 frozendict==2.0.3; python_version >= "3.6" fundamentalanalysis==0.2.11 diff --git a/terminal.py b/terminal.py index 96732bfc6d8..4482d3a2193 100644 --- a/terminal.py +++ b/terminal.py @@ -20,18 +20,10 @@ from gamestonk_terminal.menu import session from gamestonk_terminal import feature_flags as gtff from gamestonk_terminal import config_terminal -from gamestonk_terminal.stocks import stocks_controller -from gamestonk_terminal.cryptocurrency import crypto_controller -from gamestonk_terminal.economy import economy_controller -from gamestonk_terminal.options import options_controller - # from gamestonk_terminal.etf import etf_controller -from gamestonk_terminal.forex import forex_controller -from gamestonk_terminal.resources import resources_controller -from gamestonk_terminal.portfolio import portfolio_controller -# pylint: disable=too-many-public-methods +# pylint: disable=too-many-public-methods,import-outside-toplevel class TerminalController: @@ -166,18 +158,26 @@ What do you want to do? # MENUS def call_stocks(self, _): """Process stocks command""" + from gamestonk_terminal.stocks import stocks_controller + return stocks_controller.menu() def call_crypto(self, _): """Process crypto command""" + from gamestonk_terminal.cryptocurrency import crypto_controller + return crypto_controller.menu() def call_economy(self, _): """Process econ command""" + from gamestonk_terminal.economy import economy_controller + return economy_controller.menu() def call_options(self, _): """Process op command""" + from gamestonk_terminal.options import options_controller + return options_controller.menu() def call_etf(self, _): @@ -187,14 +187,20 @@ What do you want to do? def call_forex(self, _): """Process fx command""" + from gamestonk_terminal.forex import forex_controller + return forex_controller.menu() def call_resources(self, _): """Process resources command""" + from gamestonk_terminal.resources import resources_controller + return resources_controller.menu() def call_portfolio(self, _): """Process portfolio command""" + from gamestonk_terminal.portfolio import portfolio_controller + return portfolio_controller.menu() @@ -202,72 +208,75 @@ def terminal(): """Terminal Menu""" bootup() - + process_input = False t_controller = TerminalController() if config_terminal.DEFAULT_CONTEXT: if config_terminal.DEFAULT_CONTEXT in t_controller.CHOICES_MENUS: try: print("") - t_controller.switch(config_terminal.DEFAULT_CONTEXT.lower()) + process_input = t_controller.switch( + config_terminal.DEFAULT_CONTEXT.lower() + ) except SystemExit: print("") else: print("\nInvalid DEFAULT_CONTEXT config selected!", "\n") - t_controller.print_help() - parsed_stdin = False + if not process_input: + t_controller.print_help() + parsed_stdin = False - while True: - if gtff.ENABLE_QUICK_EXIT: - print("Quick exit enabled") - break + while True: + 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: - an_input = " ".join(sys.argv[1:]) - print(f"{get_flair()}> {an_input}") - parsed_stdin = True + # Get input command from stdin or user + if not parsed_stdin and len(sys.argv) > 1: + an_input = " ".join(sys.argv[1:]) + print(f"{get_flair()}> {an_input}") + parsed_stdin = True - elif session and gtff.USE_PROMPT_TOOLKIT: - an_input = session.prompt( - f"{get_flair()}> ", completer=t_controller.completer - ) + elif session and gtff.USE_PROMPT_TOOLKIT: + an_input = session.prompt( + f"{get_flair()}> ", completer=t_controller.completer + ) - else: - an_input = input(f"{get_flair()}> ") + else: + an_input = input(f"{get_flair()}> ") - # Is command empty - if not an_input: - print("") - continue + # Is command empty + if not an_input: + print("") + continue - # Process list of commands selected by user - try: - process_input = t_controller.switch(an_input) - # None - Keep loop - # True - Quit or Reset based on flag - # False - Keep loop and show help menu + # Process list of commands selected by user + try: + process_input = t_controller.switch(an_input) + # None - Keep loop + # True - Quit or Reset based on flag + # False - Keep loop and show help menu - if process_input is not None: - # Quit terminal - if process_input: - break + if process_input is not None: + # Quit terminal + if process_input: + break - t_controller.print_help() + t_controller.print_help() - except SystemExit: - print("The command selected doesn't exist\n") - continue + except SystemExit: + print("The command selected doesn't exist\n") + continue - if not gtff.ENABLE_QUICK_EXIT: - # Check if the user wants to reset application - if an_input == "reset" or t_controller.update_succcess: - ret_code = reset() - if ret_code != 0: + if not gtff.ENABLE_QUICK_EXIT: + # Check if the user wants to reset application + if an_input == "reset" or t_controller.update_succcess: + ret_code = reset() + if ret_code != 0: + print_goodbye() + else: print_goodbye() - else: - print_goodbye() if __name__ == "__main__": diff --git a/tests/test_fred_fred_view.py b/tests/test_fred_fred_view.py index df541bbc790..5e3038de32c 100644 --- a/tests/test_fred_fred_view.py +++ b/tests/test_fred_fred_view.py @@ -5,27 +5,37 @@ from io import StringIO import pandas as pd # pylint: disable=unused-import -from gamestonk_terminal.economy.fred_view import display_fred # noqa: F401 +from gamestonk_terminal.economy.fred_view import display_series # noqa: F401 fred_data_mock = """ -,GDP -2019-01-01,21115.309 -2019-04-01,21329.877 -2019-07-01,21540.325 -2019-10-01,21747.394 -2020-01-01,21561.139 -2020-04-01,19520.114 -2020-07-01,21170.252 -2020-10-01,21494.731 -2021-01-01,22048.894 +For 'gdp', series IDs found: GDP, GDPC1, M2V, GFDEGDQ188S, PAYEMS. + +GDP +--- +Date +2019-01-01 21001.591 +2019-04-01 21289.268 +2019-07-01 21505.012 +2019-10-01 21694.458 +2020-01-01 21481.367 +2020-04-01 19477.444 +2020-07-01 21138.574 +2020-10-01 21477.597 +2021-01-01 22038.226 +2021-04-01 22722.581 """ class TestFredFredView(unittest.TestCase): - @mock.patch("gamestonk_terminal.economy.fred_view.Fred.get_series") + @mock.patch("gamestonk_terminal.economy.fred_model.get_series_data") def test_display_fred(self, mock_get_series): fred_data = pd.read_csv(StringIO(fred_data_mock), header=0, index_col=0) mock_get_series.return_value = fred_data - display_fred(["-t"], "gdp") + display_series( + series="gdp", + start_date="2019-01-01", + raw=True, + export="", + )