Refactor Papermill menu and add an Econ Data report

This commit is contained in:
Artem Veremey
2021-03-16 23:31:58 -07:00
parent d87a99dc1d
commit ffc879accd
12 changed files with 627 additions and 71 deletions

View File

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

View File

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

View File

@@ -1 +1 @@
from . import papermill_menu # noqa: F401
from . import papermill_controller # noqa: F401

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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