From ffc879accd2e586ecb19194a75cc35a220164b81 Mon Sep 17 00:00:00 2001 From: Artem Veremey Date: Tue, 16 Mar 2021 23:31:58 -0700 Subject: [PATCH] Refactor Papermill menu and add an Econ Data report --- .../financial_modeling_prep_api.py | 2 +- gamestonk_terminal/main_helper.py | 2 + gamestonk_terminal/papermill/__init__.py | 2 +- ...due_diligence.py => due_diligence_view.py} | 21 +- .../papermill/econ_data_helper.py | 97 +++++ .../papermill/econ_data_view.py | 58 +++ .../papermill/papermill_controller.py | 93 +++++ .../papermill/papermill_menu.py | 60 --- .../technical_analysis/README.md | 4 +- .../technical_analysis/trendline_api.py | 2 +- notebooks/templates/econ_data.ipynb | 355 ++++++++++++++++++ terminal.py | 2 +- 12 files changed, 627 insertions(+), 71 deletions(-) rename gamestonk_terminal/papermill/{due_diligence.py => due_diligence_view.py} (71%) create mode 100755 gamestonk_terminal/papermill/econ_data_helper.py create mode 100755 gamestonk_terminal/papermill/econ_data_view.py create mode 100644 gamestonk_terminal/papermill/papermill_controller.py delete mode 100644 gamestonk_terminal/papermill/papermill_menu.py create mode 100755 notebooks/templates/econ_data.ipynb diff --git a/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_api.py b/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_api.py index 04c144a9989..7189fce3fd5 100644 --- a/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_api.py +++ b/gamestonk_terminal/fundamental_analysis/financial_modeling_prep_api.py @@ -2,6 +2,7 @@ import argparse 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 ( @@ -11,7 +12,6 @@ from gamestonk_terminal.helper_funcs import ( get_flair, ) from gamestonk_terminal.menu import session -from prompt_toolkit.completion import NestedCompleter def print_menu(s_ticker, s_start, s_interval): diff --git a/gamestonk_terminal/main_helper.py b/gamestonk_terminal/main_helper.py index 28aa4ca6323..30e9905287c 100644 --- a/gamestonk_terminal/main_helper.py +++ b/gamestonk_terminal/main_helper.py @@ -165,6 +165,7 @@ def load(l_args, s_ticker, s_start, s_interval, df_stock): df_stock, _ = ts.get_daily_adjusted( symbol=ns_parser.s_ticker, outputsize="full" ) + # pylint: disable=no-member df_stock.sort_index(ascending=True, inplace=True) # Slice dataframe from the starting date YYYY-MM-DD selected @@ -199,6 +200,7 @@ def load(l_args, s_ticker, s_start, s_interval, df_stock): df_stock, _ = ts.get_intraday( symbol=ns_parser.s_ticker, outputsize="full", interval=s_interval ) + # pylint: disable=no-member df_stock.sort_index(ascending=True, inplace=True) # Slice dataframe from the starting date YYYY-MM-DD selected diff --git a/gamestonk_terminal/papermill/__init__.py b/gamestonk_terminal/papermill/__init__.py index 857291ab8fb..5791b68bd19 100644 --- a/gamestonk_terminal/papermill/__init__.py +++ b/gamestonk_terminal/papermill/__init__.py @@ -1 +1 @@ -from . import papermill_menu # noqa: F401 +from . import papermill_controller # noqa: F401 diff --git a/gamestonk_terminal/papermill/due_diligence.py b/gamestonk_terminal/papermill/due_diligence_view.py similarity index 71% rename from gamestonk_terminal/papermill/due_diligence.py rename to gamestonk_terminal/papermill/due_diligence_view.py index b77abd2b9d3..f4575e1d844 100644 --- a/gamestonk_terminal/papermill/due_diligence.py +++ b/gamestonk_terminal/papermill/due_diligence_view.py @@ -1,11 +1,22 @@ +"""Papermill Due Diligence View Module""" +__docformat__ = "numpy" + import argparse +from typing import List from datetime import datetime import os import webbrowser import papermill as pm -def analysis(l_args): +def due_diligence(other_args: List[str]): + """Due Diligence report + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + """ parser = argparse.ArgumentParser( add_help=False, prog="dd", @@ -24,16 +35,16 @@ def analysis(l_args): ) try: - (ns_parser, l_unknown_args) = parser.parse_known_args(l_args) + (parser, unknown_args) = parser.parse_known_args(other_args) except SystemExit: print("") return - if l_unknown_args: - print(f"The following args couldn't be interpreted: {l_unknown_args}") + if unknown_args: + print(f"The following args couldn't be interpreted: {unknown_args}") # Update values: - s_ticker = ns_parser.s_ticker + s_ticker = parser.s_ticker today = datetime.now() diff --git a/gamestonk_terminal/papermill/econ_data_helper.py b/gamestonk_terminal/papermill/econ_data_helper.py new file mode 100755 index 00000000000..25e7f24f365 --- /dev/null +++ b/gamestonk_terminal/papermill/econ_data_helper.py @@ -0,0 +1,97 @@ +"""Papermill Econ Data Helper Module""" +__docformat__ = "numpy" + +import os +import pathlib +from datetime import datetime, timedelta +import pandas as pd +import mplfinance as mpf + +from gamestonk_terminal.technical_analysis import trendline_api as trend + +# pylint: disable=too-many-arguments +def draw_graph( + ticker: str, + report_cache_dir: str, + time_delta: int = 180, + line_type: str = "candle", + draw_mas: tuple = (20, 50), + draw_volume: bool = True, + high_trend: bool = True, + low_trend: bool = True, +): + """Draw Graph is a helper that wraps mplfinance, caching and trendline + + Parameters + ---------- + ticker : str + Stock ticker to draw + report_cache_dir : str + Ticker data cache directory to use + time_delta : int, optional + Graph period in days, by default 180 + line_type : str, optional + Graph line type to pass to mplfinance, by default "candle" + draw_mas : tuple, optional + SMAs to draw, by default (20, 50) + draw_volume : bool, optional + Switch to draw trading volume by default True + high_trend : bool, optional + Switch to draw high trend line, by default True + low_trend : bool, optional + Switch to draw low trend line, by default True + """ + df_stock_cache = pathlib.Path( + report_cache_dir, f"{ticker}_stock_data_{time_delta}.pkl" + ) + if os.path.isfile(df_stock_cache): + # print(f"Found a cache file. Loading {df_stock_cache}") + df_stock = pd.read_pickle(df_stock_cache) + else: + # print("Cache file not found. Getting data") + df_stock = trend.load_ticker( + ticker, (datetime.now() - timedelta(days=time_delta)).strftime("%Y-%m-%d") + ) + df_stock = trend.find_trendline(df_stock, "OC_High", "high") + df_stock = trend.find_trendline(df_stock, "OC_Low", "how") + # print("Savind cache file") + df_stock.to_pickle(df_stock_cache) + # print(os.listdir(report_cache_dir)) + + df_stock = trend.load_ticker( + ticker, (datetime.now() - timedelta(days=time_delta)).strftime("%Y-%m-%d") + ) + df_stock = trend.find_trendline(df_stock, "OC_High", "high") + df_stock = trend.find_trendline(df_stock, "OC_Low", "how") + + mc = mpf.make_marketcolors( + up="green", down="red", edge="black", wick="black", volume="in", ohlc="i" + ) + s = mpf.make_mpf_style(marketcolors=mc, gridstyle=":", y_on_right=True) + + ap0 = [] + + if "OC_High_trend" in df_stock.columns and high_trend: + ap0.append( + mpf.make_addplot(df_stock["OC_High_trend"], color="g"), + ) + + if "OC_Low_trend" in df_stock.columns and low_trend: + ap0.append( + mpf.make_addplot(df_stock["OC_Low_trend"], color="b"), + ) + + mpf.plot( + df_stock, + type=line_type, + mav=draw_mas, + volume=draw_volume, + addplot=ap0, + xrotation=0, + style=s, + figratio=(10, 7), + figscale=2.00, + update_width_config=dict( + candle_linewidth=1.0, candle_width=0.8, volume_linewidth=1.0 + ), + ) diff --git a/gamestonk_terminal/papermill/econ_data_view.py b/gamestonk_terminal/papermill/econ_data_view.py new file mode 100755 index 00000000000..bab7757d13d --- /dev/null +++ b/gamestonk_terminal/papermill/econ_data_view.py @@ -0,0 +1,58 @@ +"""Papermill Econ Data View Module""" +__docformat__ = "numpy" + +import argparse +from typing import List +from datetime import datetime +import os +import webbrowser +import papermill as pm + + +def econ_data(other_args: List[str]): + """Creates an Economic Data report + + Parameters + ---------- + other_args : List[str] + Command line arguments to be processed with argparse + """ + parser = argparse.ArgumentParser( + add_help=False, + prog="econ", + description=""" + Run Economic Data report + """, + ) + + try: + (_, unknown_args) = parser.parse_known_args(other_args) + except SystemExit: + print("") + return + + if unknown_args: + print(f"The following args couldn't be interpreted: {unknown_args}") + + today = datetime.now() + + analysis_notebook = ( + f"notebooks/reports/econ_data_{today.strftime('%Y%m%d_%H%M%S')}.ipynb" + ) + + try: + pm.execute_notebook( + "notebooks/templates/econ_data.ipynb", + analysis_notebook, + parameters=dict( + report_name=f"econ_data_{today.strftime('%Y%m%d_%H%M%S')}", + base_path=os.path.abspath(os.path.join(".")), + ), + ) + except Exception as e: + print(e) + print("") + return + + webbrowser.open(f"http://localhost:8888/notebooks/{analysis_notebook}") + print("") diff --git a/gamestonk_terminal/papermill/papermill_controller.py b/gamestonk_terminal/papermill/papermill_controller.py new file mode 100644 index 00000000000..a2d5556e2d8 --- /dev/null +++ b/gamestonk_terminal/papermill/papermill_controller.py @@ -0,0 +1,93 @@ +"""Papermill Controller Module""" +__docformat__ = "numpy" + +import argparse +from typing import List + +from gamestonk_terminal.papermill import due_diligence_view +from gamestonk_terminal.papermill import econ_data_view + +from gamestonk_terminal.helper_funcs import get_flair + + +class PapermillController: + """ Papermill Controller class""" + + def __init__(self): + """Constructor""" + self.papermill_parser = argparse.ArgumentParser( + add_help=False, prog="papermill" + ) + self.papermill_parser.add_argument( + "cmd", + choices=["help", "q", "quit", "dd", "econ"], + ) + + def switch(self, an_input: str): + """Process and dispatch input""" + (known_args, other_args) = self.papermill_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""" + print_papermill() + + def call_q(self, _): + """Process Q command""" + return False + + def call_quit(self, _): + """Process Quit command""" + return True + + def call_dd(self, other_args: List[str]): + """Process DD command""" + due_diligence_view.due_diligence(other_args) + + def call_econ(self, other_args: List[str]): + """Process Econ command""" + econ_data_view.econ_data(other_args) + + +def print_papermill(): + """Print help""" + + print("\nDiscovery Mode:") + print(" help show this papermill menu again") + print(" q quit this menu, and shows back to main menu") + print(" quit quit to abandon program") + print("") + print(" dd run papermill to generate due diligence summary") + print(" econ run papermill to generate economic data summary") + print("") + + return + + +def papermill_menu(): + """Papermill Menu""" + + pc = PapermillController() + + print_papermill() + + while True: + # Get input command from user + an_input = input(f"{get_flair()} (mill)> ") + + try: + process_input = pc.switch(an_input) + except SystemExit: + print("The command selected doesn't exist\n") + continue + + if process_input is False: + return False + + if process_input is True: + return True diff --git a/gamestonk_terminal/papermill/papermill_menu.py b/gamestonk_terminal/papermill/papermill_menu.py deleted file mode 100644 index ae87d2aad0c..00000000000 --- a/gamestonk_terminal/papermill/papermill_menu.py +++ /dev/null @@ -1,60 +0,0 @@ -import argparse - -from gamestonk_terminal.papermill import due_diligence - -from gamestonk_terminal.helper_funcs import get_flair - - -def print_papermill(): - """ Print help """ - - print("\nDiscovery Mode:") - print(" help show this papermill menu again") - print(" q quit this menu, and shows back to main menu") - print(" quit quit to abandon program") - print("") - print(" dd run papermill to generate due diligence summary") - print("") - - return - - -def papermill_menu(): - papermill_parser = argparse.ArgumentParser(add_help=False, prog="papermill") - papermill_parser.add_argument( - "cmd", - choices=["help", "q", "quit", "dd"], - ) - - print_papermill() - - while True: - # Get input command from user - as_input = input(f"{get_flair()} (mill)> ") - - # Parse fundamental analysis command of the list of possible commands - try: - (ns_known_args, l_args) = papermill_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_papermill() - - elif ns_known_args.cmd == "q": - # Just leave the MILL menu - return False - - elif ns_known_args.cmd == "quit": - # Abandon the program - return True - - elif ns_known_args.cmd == "dd": - due_diligence.analysis(l_args) - - else: - print("Command not recognized!") diff --git a/gamestonk_terminal/technical_analysis/README.md b/gamestonk_terminal/technical_analysis/README.md index a9c96533a88..284fbc1a5c9 100644 --- a/gamestonk_terminal/technical_analysis/README.md +++ b/gamestonk_terminal/technical_analysis/README.md @@ -3,7 +3,7 @@ This menu aims to perform a technical analysis on a pre-loaded ticker chart, and the usage of the following commands along with an example will be exploited below. [OVERLAP](#OVERLAP) - * [ema](#ema) + * [ema](#ema) - exponential moving average * [sma](#sma) - simple moving average @@ -12,7 +12,7 @@ This menu aims to perform a technical analysis on a pre-loaded ticker chart, and [MOMENTUM](#MOMENTUM) * [cci](#cci) - - commodity channel index + - commodity channel index * [macd](#macd) - moving average convergence/divergence * [rsi](#rsi) diff --git a/gamestonk_terminal/technical_analysis/trendline_api.py b/gamestonk_terminal/technical_analysis/trendline_api.py index fae6276a409..68e7d7e6457 100755 --- a/gamestonk_terminal/technical_analysis/trendline_api.py +++ b/gamestonk_terminal/technical_analysis/trendline_api.py @@ -22,7 +22,7 @@ def load_ticker(ticker: str, start_date: str) -> DataFrame: DataFrame A Panda's data frame with columns Open, High, Low, Close, Adj Close, Volume, date_id, OC-High, OC-Low. """ - print(f"Start date: {start_date}") + # print(f"Start date: {start_date}") df_data = yf.download(ticker, start=start_date, progress=False) df_data["date_id"] = (df_data.index.date - df_data.index.date.min()).astype( diff --git a/notebooks/templates/econ_data.ipynb b/notebooks/templates/econ_data.ipynb new file mode 100755 index 00000000000..e55acb77ab9 --- /dev/null +++ b/notebooks/templates/econ_data.ipynb @@ -0,0 +1,355 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "blank-couple", + "metadata": {}, + "outputs": [], + "source": [ + "import importlib\n", + "import pathlib\n", + "import os\n", + "import sys\n", + "from datetime import datetime\n", + "module_path = os.path.abspath(os.path.join('../..'))\n", + "if module_path not in sys.path:\n", + " sys.path.append(module_path)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "exact-price", + "metadata": {}, + "outputs": [], + "source": [ + "datetime.now()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "naked-shower", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "report_name=f\"econ_{datetime.now().strftime('%Y%m%d_%H%M%S')}\"\n", + "base_path=os.path.abspath(os.path.join('../..'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "moderate-cheat", + "metadata": {}, + "outputs": [], + "source": [ + "cache_dir = pathlib.Path(base_path, \"notebooks\", \"reports\", report_name)\n", + "if not os.path.isdir(cache_dir):\n", + " print(f\"Reports data directory not found. Creating {cache_dir}\")\n", + " os.mkdir(cache_dir)\n", + "else:\n", + " print(f\"Found reports directory {cache_dir}\")\n", + " print(os.listdir(cache_dir))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "southern-gnome", + "metadata": {}, + "outputs": [], + "source": [ + "from gamestonk_terminal.papermill import econ_data_helper as edh" + ] + }, + { + "cell_type": "markdown", + "id": "initial-palace", + "metadata": {}, + "source": [ + "## Dow Jones - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "invalid-interstate", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"^DJI\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=720, low_trend=False)" + ] + }, + { + "cell_type": "markdown", + "id": "responsible-poker", + "metadata": {}, + "source": [ + "## Dow Jones - 1 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "departmental-sender", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"^DJI\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=360, low_trend=True)" + ] + }, + { + "cell_type": "markdown", + "id": "passing-printing", + "metadata": {}, + "source": [ + "## S&P 500 - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "related-quality", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"^GSPC\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=720, low_trend=False)" + ] + }, + { + "cell_type": "markdown", + "id": "annoying-drain", + "metadata": {}, + "source": [ + "## Yield on 5-Year US Treasury Notes - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cathedral-divide", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"^FVX\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=False, time_delta=720, low_trend=False, high_trend=False)" + ] + }, + { + "cell_type": "markdown", + "id": "selective-macintosh", + "metadata": {}, + "source": [ + "## Yield on 10-Year US Treasury Notes - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "induced-vancouver", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"^TNX\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=False, time_delta=720, low_trend=False, high_trend=False)" + ] + }, + { + "cell_type": "markdown", + "id": "imported-message", + "metadata": {}, + "source": [ + "## Yield on 10-Year US Treasury Notes - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "alleged-citizenship", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"^TYX\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=False, time_delta=720, low_trend=False, high_trend=False)" + ] + }, + { + "cell_type": "markdown", + "id": "complimentary-stomach", + "metadata": {}, + "source": [ + "## Gold - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "varying-pasta", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"GLD\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=720)" + ] + }, + { + "cell_type": "markdown", + "id": "perfect-illness", + "metadata": {}, + "source": [ + "## Silver - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "confirmed-event", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"SLV\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=720, low_trend=False)" + ] + }, + { + "cell_type": "markdown", + "id": "faced-canon", + "metadata": {}, + "source": [ + "## Energy - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "extended-earthquake", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"XLE\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=720)" + ] + }, + { + "cell_type": "markdown", + "id": "statewide-explanation", + "metadata": {}, + "source": [ + "## Crude Oil - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "classical-coast", + "metadata": { + "scrolled": false + }, + "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)" + ] + }, + { + "cell_type": "markdown", + "id": "spoken-delta", + "metadata": {}, + "source": [ + "## Real Estate - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "changing-eight", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"XLRE\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=720, low_trend=False)" + ] + }, + { + "cell_type": "markdown", + "id": "mathematical-support", + "metadata": {}, + "source": [ + "## Real Estate - 1 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "exact-jacksonville", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"VNQ\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=360, low_trend=True)" + ] + }, + { + "cell_type": "markdown", + "id": "worse-horror", + "metadata": {}, + "source": [ + "## Financials - 2 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "controlled-portuguese", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"XLF\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=720, low_trend=False)" + ] + }, + { + "cell_type": "markdown", + "id": "typical-sandwich", + "metadata": {}, + "source": [ + "## Financials - 1 year trend with 20, 50 and 200 day SMA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "headed-bundle", + "metadata": {}, + "outputs": [], + "source": [ + "edh.draw_graph(\"XLF\", cache_dir, line_type=\"line\", draw_mas=(20,50,200), draw_volume=True, time_delta=360, low_trend=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "german-ecology", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/terminal.py b/terminal.py index ff99ed5a6cc..4969ab67c9d 100644 --- a/terminal.py +++ b/terminal.py @@ -18,7 +18,7 @@ from gamestonk_terminal.fundamental_analysis import fa_menu as fam 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 -from gamestonk_terminal.papermill import papermill_menu as mill +from gamestonk_terminal.papermill import papermill_controller as mill from gamestonk_terminal.sentiment import sen_menu as sm from gamestonk_terminal.technical_analysis import ta_menu as tam from gamestonk_terminal.comparison_analysis import ca_menu as cam