diff --git a/openbb_terminal/core/session/current_system.py b/openbb_terminal/core/session/current_system.py index 77403e9842f..62ec09037cf 100644 --- a/openbb_terminal/core/session/current_system.py +++ b/openbb_terminal/core/session/current_system.py @@ -3,7 +3,8 @@ from copy import deepcopy # IMPORTS INTERNAL from openbb_terminal.core.models import SystemModel -from openbb_terminal.core.session.system_handler import handle_system, save_system +from openbb_terminal.core.session.env_handler import read_env +from openbb_terminal.core.session.utils import load_dict_to_model def get_current_system() -> SystemModel: @@ -14,8 +15,8 @@ def get_current_system() -> SystemModel: def set_current_system(system: SystemModel): """Set current system.""" global __system # pylint: disable=global-statement - save_system(system) __system = system -__system = handle_system() +__env_dict = read_env() +__system = load_dict_to_model(__env_dict, SystemModel) diff --git a/openbb_terminal/core/session/system_handler.py b/openbb_terminal/core/session/system_handler.py deleted file mode 100644 index 3c80c80e4f7..00000000000 --- a/openbb_terminal/core/session/system_handler.py +++ /dev/null @@ -1,86 +0,0 @@ -import atexit -import json -import os -from pathlib import Path - -from pydantic.json import pydantic_encoder - -from openbb_terminal.core.config.paths import ( - SETTINGS_DIRECTORY, -) -from openbb_terminal.core.models import SystemModel -from openbb_terminal.core.session.env_handler import read_env -from openbb_terminal.core.session.utils import load_dict_to_model - -SYSTEM_FILE_PATH = SETTINGS_DIRECTORY / "system.json" - - -def handle_system(file_path: Path = SYSTEM_FILE_PATH) -> SystemModel: - """ - Handle the system. - - Reads system data from file if it exists, else reads environment variable data. - Returns a system model built from the loaded data. - - Parameters - ---------- - file_path (Path): The file path. - - Returns - ------- - SystemModel: The system model. - """ - - try: - if os.path.isfile(file_path): - system_data = {} - with open(file_path) as f: - system_data = json.load(f) - if system_data: - return load_dict_to_model(system_data, SystemModel) - except Exception: - pass - - __env_dict = read_env() - system = load_dict_to_model(__env_dict, SystemModel) - save_system(system=system, file_path=file_path) - subscribe_delete_system_on_exit(file_path=file_path) - return system - - -def save_system(system: SystemModel, file_path: Path = SYSTEM_FILE_PATH): - """ - Write system to file. - - Parameters - ---------- - system (SystemModel): The system model. - file_path (Path): The file path. - - Returns - ------- - system (SystemModel): The system model. - """ - - try: - with open(file_path, "w") as f: - json_content = json.dumps(system, default=pydantic_encoder) - f.write(json_content) - except Exception: - pass - - -def subscribe_delete_system_on_exit(file_path: Path): - """ - Deletes the system file on exiting the application. - - Parameters - ---------- - file_path (Path): The file path. - """ - - def delete_file(file_path: Path): - if os.path.isfile(file_path): - os.remove(file_path) - - atexit.register(delete_file, file_path=file_path) diff --git a/openbb_terminal/dashboards/dashboards_controller.py b/openbb_terminal/dashboards/dashboards_controller.py index 760478a0512..1b282b0174c 100644 --- a/openbb_terminal/dashboards/dashboards_controller.py +++ b/openbb_terminal/dashboards/dashboards_controller.py @@ -18,7 +18,6 @@ import dotenv import numpy as np import psutil -import openbb_terminal.config_terminal as cfg from openbb_terminal.base_helpers import load_env_vars, strtobool from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY, SETTINGS_ENV_FILE from openbb_terminal.core.plots.backend import plots_backend @@ -199,7 +198,6 @@ class DashboardsController(BaseController): cmd += " --theme=dark" if ns_parser.input or response.lower() == "y" and not process_check: - cfg.change_logging_suppress(new_value=True) self.processes.append( psutil.Popen( f"{cmd} --no-browser --port {port}" @@ -211,7 +209,6 @@ class DashboardsController(BaseController): env=os.environ, ) ) - cfg.change_logging_suppress(new_value=False) atexit.register(self.kill_processes) console.print( diff --git a/openbb_terminal/dashboards/stream/Forecasting.py b/openbb_terminal/dashboards/stream/Forecasting.py index 21645d161e0..3bc792e0b8d 100644 --- a/openbb_terminal/dashboards/stream/Forecasting.py +++ b/openbb_terminal/dashboards/stream/Forecasting.py @@ -9,10 +9,17 @@ import streamlit as st import yfinance as yf from rich.table import Table +import openbb_terminal.config_terminal as cfg from openbb_terminal.core.plots.plotly_helper import OpenBBFigure from openbb_terminal.forecast import helpers from openbb_terminal.rich_config import console -from openbb_terminal.sdk import openbb + +# Suppressing sdk logs +cfg.change_logging_suppress(new_value=True) + +# Import the OpenBB SDK +# pylint: disable=wrong-import-position +from openbb_terminal.sdk import openbb # noqa: E402 st.set_page_config( layout="wide", diff --git a/openbb_terminal/dashboards/stream/pages/Indicators.py b/openbb_terminal/dashboards/stream/pages/Indicators.py index ad088fd094d..e17bcca9506 100644 --- a/openbb_terminal/dashboards/stream/pages/Indicators.py +++ b/openbb_terminal/dashboards/stream/pages/Indicators.py @@ -8,11 +8,18 @@ import pandas as pd import streamlit as st from streamlit.delta_generator import DeltaGenerator +import openbb_terminal.config_terminal as cfg from openbb_terminal.common.technical_analysis import ta_helpers from openbb_terminal.core.plots.plotly_helper import OpenBBFigure from openbb_terminal.core.plots.plotly_ta.ta_class import PlotlyTA from openbb_terminal.rich_config import console -from openbb_terminal.sdk import openbb + +# Suppressing sdk logs +cfg.change_logging_suppress(new_value=True) + +# Import the OpenBB SDK +# pylint: disable=wrong-import-position +from openbb_terminal.sdk import openbb # noqa: E402 pd.options.plotting.backend = "plotly" st.set_page_config( diff --git a/openbb_terminal/dashboards/voila/forecast.ipynb b/openbb_terminal/dashboards/voila/forecast.ipynb index ffbb5f42fee..fefbb37e62c 100644 --- a/openbb_terminal/dashboards/voila/forecast.ipynb +++ b/openbb_terminal/dashboards/voila/forecast.ipynb @@ -1,361 +1,374 @@ { - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "e9ad60bc", - "metadata": {}, - "outputs": [], - "source": [ - "from datetime import datetime, timedelta\n", - "from typing import Callable, Any\n", - "from inspect import signature\n", - "import warnings, logging\n", - "\n", - "import ipywidgets as widgets\n", - "import yfinance as yf\n", - "import pandas as pd\n", - "from IPython.display import display\n", - "\n", - "from openbb_terminal.sdk import openbb, theme\n", - "\n", - "theme.apply_style()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "beb36881", - "metadata": {}, - "outputs": [], - "source": [ - "try:\n", - " has_forecast = True\n", - " model_opts = {\n", - " \"expo\": openbb.forecast.expo_chart,\n", - " \"theta\": openbb.forecast.theta_chart,\n", - " \"linregr\": openbb.forecast.linregr_chart,\n", - " \"regr\": openbb.forecast.regr_chart,\n", - " \"rnn\": openbb.forecast.rnn_chart,\n", - " \"brnn\": openbb.forecast.brnn_chart,\n", - " \"nbeats\": openbb.forecast.nbeats_chart,\n", - " \"tcn\": openbb.forecast.tcn_chart,\n", - " \"trans\": openbb.forecast.trans_chart,\n", - " \"tft\": openbb.forecast.tft_chart,\n", - " \"nhits\": openbb.forecast.nhits_chart,\n", - " }\n", - "\n", - " feat_engs = {\n", - " \"ema\": openbb.forecast.ema,\n", - " \"sto\": openbb.forecast.sto,\n", - " \"rsi\": openbb.forecast.rsi,\n", - " \"roc\": openbb.forecast.roc,\n", - " \"mom\": openbb.forecast.mom,\n", - " \"atr\": openbb.forecast.atr,\n", - " \"delta\": openbb.forecast.delta,\n", - " \"signal\": openbb.forecast.signal,\n", - " }\n", - "except AttributeError as e:\n", - " print(e)\n", - " has_forecast = False\n", - " model_opts = {}\n", - " feat_engs = {}\n", - "\n", - "interval_opts = [\n", - " \"1m\",\n", - " \"2m\",\n", - " \"5m\",\n", - " \"15m\",\n", - " \"30m\",\n", - " \"60m\",\n", - " \"90m\",\n", - " \"1h\",\n", - " \"1d\",\n", - " \"5d\",\n", - " \"1wk\",\n", - " \"1mo\",\n", - " \"3mo\",\n", - "]\n", - "\n", - "\n", - "def format_df(df: pd.DataFrame) -> pd.DataFrame:\n", - " if len(df.columns) != 6:\n", - " df.columns = [\"_\".join(col).strip() for col in df.columns.values]\n", - " df.reset_index(inplace=True)\n", - " df.columns = [x.lower() for x in df.columns]\n", - " return df\n", - "\n", - "\n", - "def has_parameter(func: Callable[..., Any], parameter: str) -> bool:\n", - " params = signature(func).parameters\n", - " parameters = params.keys()\n", - " return parameter in parameters" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f8c2f65c", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "class Chart:\n", - " def __init__(self):\n", - " self.last_tickers = \"\"\n", - " self.last_interval = \"1d\"\n", - " self.df = pd.DataFrame()\n", - " self.result = pd.DataFrame()\n", - " self.infos = {}\n", - "\n", - " def handle_changes(\n", - " self,\n", - " past_covariates,\n", - " start,\n", - " end,\n", - " interval,\n", - " tickers,\n", - " target_column,\n", - " model,\n", - " naive,\n", - " forecast_only,\n", - " ):\n", - " ticker_list = tickers.split(\",\")\n", - " if ticker_list:\n", - " if tickers != self.last_tickers or interval != self.last_interval:\n", - " if interval in [\"1d\", \"5d\", \"1wk\", \"1mo\", \"3mo\"]:\n", - " self.df = yf.download(\n", - " tickers, period=\"max\", interval=interval, progress=False\n", - " )\n", - " else:\n", - " end_date = end + timedelta(days=1)\n", - " self.df = yf.download(\n", - " tickers,\n", - " start=start,\n", - " end=end_date,\n", - " interval=interval,\n", - " progress=False,\n", - " )\n", - " self.df = format_df(self.df)\n", - " self.last_tickers = tickers\n", - " self.last_interval = interval\n", - " forecast_model = model_opts[model]\n", - " self.forecast_model = forecast_model\n", - " contains_covariates = has_parameter(forecast_model, \"past_covariates\")\n", - "\n", - " # Update Inputs\n", - " if list(target_widget.options) != [\n", - " x for x in self.df.columns if x != \"date\"\n", - " ]:\n", - " target_widget.options = [x for x in self.df.columns if x != \"date\"]\n", - " return\n", - " if list(past_covs_widget.options) != [\n", - " x for x in self.df.columns if x != \"date\"\n", - " ]:\n", - " past_covs_widget.options = [x for x in self.df.columns if x != \"date\"]\n", - " past_covs_widget.disabled = not contains_covariates\n", - " return\n", - " if past_covs_widget.disabled == contains_covariates:\n", - " past_covs_widget.disabled = not contains_covariates\n", - " column_widget.options = [x for x in self.df.columns if x != \"date\"]\n", - "\n", - " start_n = datetime(start.year, start.month, start.day)\n", - " end_n = datetime(end.year, end.month, end.day)\n", - " calcs = self.df\n", - " if interval in [\"1d\", \"5d\", \"1wk\", \"1mo\", \"3mo\"]:\n", - " result = calcs.loc[\n", - " (calcs[\"date\"] >= start_n) & (calcs[\"date\"] <= end_n)\n", - " ]\n", - " else:\n", - " result = calcs\n", - " if not target_column:\n", - " target_column = self.df.columns[0]\n", - " kwargs = {}\n", - " if contains_covariates and past_covariates != ():\n", - " kwargs[\"past_covariates\"] = \",\".join(past_covariates)\n", - " if has_parameter(forecast_model, \"naive\"):\n", - " kwargs[\"naive\"] = naive\n", - " if has_parameter(forecast_model, \"forecast_only\"):\n", - " kwargs[\"forecast_only\"] = forecast_only\n", - " # This sets up everything to run the function on button click\n", - "\n", - " self.result = result\n", - " self.target_column = target_column\n", - " self.n_predict = 5\n", - " self.kwargs = kwargs\n", - "\n", - " def handle_click(self, to_run):\n", - " if to_run:\n", - " run_widget.value = False\n", - " else:\n", - " df = self.result.dropna()\n", - " if not df.empty:\n", - " self.forecast_model(\n", - " self.result,\n", - " target_column=self.target_column,\n", - " n_predict=5,\n", - " **self.kwargs\n", - " )\n", - "\n", - " def handle_eng(self, target, feature):\n", - " self.feature_target = target\n", - " self.feature_model = feat_engs[feature]\n", - "\n", - " def handle_click2(self, to_run):\n", - " if to_run:\n", - " add_widget.value = False\n", - " else:\n", - " kwargs = {}\n", - " if has_parameter(self.feature_model, \"target_column\"):\n", - " kwargs[\"target_column\"] = self.feature_target\n", - " self.df = self.feature_model(self.df, **kwargs)\n", - " past_covs_widget.options = self.df.columns" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e0d4de31-1b4f-4c1f-8467-ca314a578d56", - "metadata": {}, - "outputs": [], - "source": [ - "w_auto = widgets.Layout(width=\"auto\")\n", - "model_value = list(model_opts)[0] if model_opts else None\n", - "model_widget = widgets.Select(\n", - " options=list(model_opts),\n", - " value=model_value,\n", - " layout=widgets.Layout(\n", - " width=\"8%\",\n", - " ),\n", - ")\n", - "past_covs_widget = widgets.SelectMultiple(\n", - " options=[\"\"],\n", - " value=[\"\"],\n", - " layout=widgets.Layout(\n", - " width=\"8%\",\n", - " ),\n", - ")\n", - "\n", - "base_date = (datetime.today() - timedelta(days=365)).date()\n", - "start_widget = widgets.DatePicker(value=base_date, layout=w_auto, description=\"Start\")\n", - "end_widget = widgets.DatePicker(\n", - " value=datetime.today().date(), layout=w_auto, description=\"End\"\n", - ")\n", - "\n", - "target_widget = widgets.Dropdown(options=[\"\"], value=\"\", description=\"Target\")\n", - "interval_widget = widgets.Dropdown(\n", - " options=interval_opts, value=\"1d\", layout=w_auto, description=\"Interval\"\n", - ")\n", - "tickers_widget = widgets.Textarea(\n", - " value=\"TSLA,\", layout=widgets.Layout(width=\"auto\", height=\"100%\")\n", - ")\n", - "\n", - "# Output box\n", - "naive_widget = widgets.ToggleButton(value=False, description=\"Show Naive\")\n", - "forecast_only_widget = widgets.ToggleButton(value=False, description=\"Forecast Only\")\n", - "run_widget = widgets.ToggleButton(value=False, description=\"Run Model\")\n", - "\n", - "# feat_box\n", - "feat_value = list(feat_engs.keys())[0] if feat_engs else None\n", - "column_widget = widgets.Dropdown(options=[\"\"], value=\"\", description=\"Target\")\n", - "feat_widget = widgets.Dropdown(\n", - " options=list(feat_engs.keys()), value=feat_value, description=\"Feature\"\n", - ")\n", - "add_widget = widgets.ToggleButton(\n", - " value=False, description=\"Add Feature\", layout=widgets.Layout(align=\"flex_end\")\n", - ") # get this to work\n", - "\n", - "selection_box = widgets.VBox([tickers_widget, target_widget])\n", - "date_box = widgets.VBox([start_widget, end_widget, interval_widget])\n", - "output_box = widgets.VBox([naive_widget, forecast_only_widget, run_widget])\n", - "feat_box = widgets.VBox([column_widget, feat_widget, add_widget])\n", - "controls = widgets.HBox(\n", - " [selection_box, model_widget, past_covs_widget, date_box, output_box, feat_box],\n", - ")\n", - "if has_forecast:\n", - " chart = Chart()\n", - " widgets.interactive_output(\n", - " chart.handle_changes,\n", - " {\n", - " \"past_covariates\": past_covs_widget,\n", - " \"start\": start_widget,\n", - " \"end\": end_widget,\n", - " \"interval\": interval_widget,\n", - " \"tickers\": tickers_widget,\n", - " \"target_column\": target_widget,\n", - " \"model\": model_widget,\n", - " \"naive\": naive_widget,\n", - " \"forecast_only\": forecast_only_widget,\n", - " },\n", - " )\n", - "\n", - " widgets.interactive_output(\n", - " chart.handle_eng, {\"target\": column_widget, \"feature\": feat_widget}\n", - " )\n", - " widgets.interactive_output(chart.handle_click2, {\"to_run\": add_widget})\n", - "\n", - " stocks_view = widgets.interactive_output(chart.handle_click, {\"to_run\": run_widget})\n", - "\n", - " title_html = \"
Use a comma after EVERY stock typed.
'\n", - "\n", - " app_contents = [\n", - " widgets.HTML(title_html),\n", - " controls,\n", - " widgets.HTML(warning_html),\n", - " stocks_view,\n", - " ]\n", - " app = widgets.VBox(app_contents)\n", - "else:\n", - " title_html = \"The forecasting dependencies are not installed.
'\n", - " )\n", - " app = widgets.VBox([widgets.HTML(title_html), widgets.HTML(warning_html)])\n", - "display(app)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9dbf43a2-70e1-44e9-a524-be3e97008b58", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.9.6" - }, - "metadata": { - "interpreter": { - "hash": "e896a00ead8b521528d79ac9ef24990696f2b751eb283ab8e0d078c9c4971ffc" - } - }, - "vscode": { - "interpreter": { - "hash": "bd3088e2ce83c7406a082a5b650cfc74fd1480320510d276c9fa5780b96e5fae" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "e9ad60bc", + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import datetime, timedelta\n", + "from typing import Callable, Any\n", + "from inspect import signature\n", + "import warnings, logging\n", + "\n", + "import ipywidgets as widgets\n", + "import yfinance as yf\n", + "import pandas as pd\n", + "from IPython.display import display\n", + "\n", + "theme.apply_style()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "404cb982", + "metadata": {}, + "outputs": [], + "source": [ + "# Suppressing sdk logs\n", + "import openbb_terminal.config_terminal as cfg\n", + "cfg.change_logging_suppress(new_value=True)\n", + "\n", + "# Import the OpenBB SDK\n", + "from openbb_terminal.sdk import openbb, widgets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "beb36881", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " has_forecast = True\n", + " model_opts = {\n", + " \"expo\": openbb.forecast.expo_chart,\n", + " \"theta\": openbb.forecast.theta_chart,\n", + " \"linregr\": openbb.forecast.linregr_chart,\n", + " \"regr\": openbb.forecast.regr_chart,\n", + " \"rnn\": openbb.forecast.rnn_chart,\n", + " \"brnn\": openbb.forecast.brnn_chart,\n", + " \"nbeats\": openbb.forecast.nbeats_chart,\n", + " \"tcn\": openbb.forecast.tcn_chart,\n", + " \"trans\": openbb.forecast.trans_chart,\n", + " \"tft\": openbb.forecast.tft_chart,\n", + " \"nhits\": openbb.forecast.nhits_chart,\n", + " }\n", + "\n", + " feat_engs = {\n", + " \"ema\": openbb.forecast.ema,\n", + " \"sto\": openbb.forecast.sto,\n", + " \"rsi\": openbb.forecast.rsi,\n", + " \"roc\": openbb.forecast.roc,\n", + " \"mom\": openbb.forecast.mom,\n", + " \"atr\": openbb.forecast.atr,\n", + " \"delta\": openbb.forecast.delta,\n", + " \"signal\": openbb.forecast.signal,\n", + " }\n", + "except AttributeError as e:\n", + " print(e)\n", + " has_forecast = False\n", + " model_opts = {}\n", + " feat_engs = {}\n", + "\n", + "interval_opts = [\n", + " \"1m\",\n", + " \"2m\",\n", + " \"5m\",\n", + " \"15m\",\n", + " \"30m\",\n", + " \"60m\",\n", + " \"90m\",\n", + " \"1h\",\n", + " \"1d\",\n", + " \"5d\",\n", + " \"1wk\",\n", + " \"1mo\",\n", + " \"3mo\",\n", + "]\n", + "\n", + "\n", + "def format_df(df: pd.DataFrame) -> pd.DataFrame:\n", + " if len(df.columns) != 6:\n", + " df.columns = [\"_\".join(col).strip() for col in df.columns.values]\n", + " df.reset_index(inplace=True)\n", + " df.columns = [x.lower() for x in df.columns]\n", + " return df\n", + "\n", + "\n", + "def has_parameter(func: Callable[..., Any], parameter: str) -> bool:\n", + " params = signature(func).parameters\n", + " parameters = params.keys()\n", + " return parameter in parameters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f8c2f65c", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "class Chart:\n", + " def __init__(self):\n", + " self.last_tickers = \"\"\n", + " self.last_interval = \"1d\"\n", + " self.df = pd.DataFrame()\n", + " self.result = pd.DataFrame()\n", + " self.infos = {}\n", + "\n", + " def handle_changes(\n", + " self,\n", + " past_covariates,\n", + " start,\n", + " end,\n", + " interval,\n", + " tickers,\n", + " target_column,\n", + " model,\n", + " naive,\n", + " forecast_only,\n", + " ):\n", + " ticker_list = tickers.split(\",\")\n", + " if ticker_list:\n", + " if tickers != self.last_tickers or interval != self.last_interval:\n", + " if interval in [\"1d\", \"5d\", \"1wk\", \"1mo\", \"3mo\"]:\n", + " self.df = yf.download(\n", + " tickers, period=\"max\", interval=interval, progress=False\n", + " )\n", + " else:\n", + " end_date = end + timedelta(days=1)\n", + " self.df = yf.download(\n", + " tickers,\n", + " start=start,\n", + " end=end_date,\n", + " interval=interval,\n", + " progress=False,\n", + " )\n", + " self.df = format_df(self.df)\n", + " self.last_tickers = tickers\n", + " self.last_interval = interval\n", + " forecast_model = model_opts[model]\n", + " self.forecast_model = forecast_model\n", + " contains_covariates = has_parameter(forecast_model, \"past_covariates\")\n", + "\n", + " # Update Inputs\n", + " if list(target_widget.options) != [\n", + " x for x in self.df.columns if x != \"date\"\n", + " ]:\n", + " target_widget.options = [x for x in self.df.columns if x != \"date\"]\n", + " return\n", + " if list(past_covs_widget.options) != [\n", + " x for x in self.df.columns if x != \"date\"\n", + " ]:\n", + " past_covs_widget.options = [x for x in self.df.columns if x != \"date\"]\n", + " past_covs_widget.disabled = not contains_covariates\n", + " return\n", + " if past_covs_widget.disabled == contains_covariates:\n", + " past_covs_widget.disabled = not contains_covariates\n", + " column_widget.options = [x for x in self.df.columns if x != \"date\"]\n", + "\n", + " start_n = datetime(start.year, start.month, start.day)\n", + " end_n = datetime(end.year, end.month, end.day)\n", + " calcs = self.df\n", + " if interval in [\"1d\", \"5d\", \"1wk\", \"1mo\", \"3mo\"]:\n", + " result = calcs.loc[\n", + " (calcs[\"date\"] >= start_n) & (calcs[\"date\"] <= end_n)\n", + " ]\n", + " else:\n", + " result = calcs\n", + " if not target_column:\n", + " target_column = self.df.columns[0]\n", + " kwargs = {}\n", + " if contains_covariates and past_covariates != ():\n", + " kwargs[\"past_covariates\"] = \",\".join(past_covariates)\n", + " if has_parameter(forecast_model, \"naive\"):\n", + " kwargs[\"naive\"] = naive\n", + " if has_parameter(forecast_model, \"forecast_only\"):\n", + " kwargs[\"forecast_only\"] = forecast_only\n", + " # This sets up everything to run the function on button click\n", + "\n", + " self.result = result\n", + " self.target_column = target_column\n", + " self.n_predict = 5\n", + " self.kwargs = kwargs\n", + "\n", + " def handle_click(self, to_run):\n", + " if to_run:\n", + " run_widget.value = False\n", + " else:\n", + " df = self.result.dropna()\n", + " if not df.empty:\n", + " self.forecast_model(\n", + " self.result,\n", + " target_column=self.target_column,\n", + " n_predict=5,\n", + " **self.kwargs\n", + " )\n", + "\n", + " def handle_eng(self, target, feature):\n", + " self.feature_target = target\n", + " self.feature_model = feat_engs[feature]\n", + "\n", + " def handle_click2(self, to_run):\n", + " if to_run:\n", + " add_widget.value = False\n", + " else:\n", + " kwargs = {}\n", + " if has_parameter(self.feature_model, \"target_column\"):\n", + " kwargs[\"target_column\"] = self.feature_target\n", + " self.df = self.feature_model(self.df, **kwargs)\n", + " past_covs_widget.options = self.df.columns" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e0d4de31-1b4f-4c1f-8467-ca314a578d56", + "metadata": {}, + "outputs": [], + "source": [ + "w_auto = widgets.Layout(width=\"auto\")\n", + "model_value = list(model_opts)[0] if model_opts else None\n", + "model_widget = widgets.Select(\n", + " options=list(model_opts),\n", + " value=model_value,\n", + " layout=widgets.Layout(\n", + " width=\"8%\",\n", + " ),\n", + ")\n", + "past_covs_widget = widgets.SelectMultiple(\n", + " options=[\"\"],\n", + " value=[\"\"],\n", + " layout=widgets.Layout(\n", + " width=\"8%\",\n", + " ),\n", + ")\n", + "\n", + "base_date = (datetime.today() - timedelta(days=365)).date()\n", + "start_widget = widgets.DatePicker(value=base_date, layout=w_auto, description=\"Start\")\n", + "end_widget = widgets.DatePicker(\n", + " value=datetime.today().date(), layout=w_auto, description=\"End\"\n", + ")\n", + "\n", + "target_widget = widgets.Dropdown(options=[\"\"], value=\"\", description=\"Target\")\n", + "interval_widget = widgets.Dropdown(\n", + " options=interval_opts, value=\"1d\", layout=w_auto, description=\"Interval\"\n", + ")\n", + "tickers_widget = widgets.Textarea(\n", + " value=\"TSLA,\", layout=widgets.Layout(width=\"auto\", height=\"100%\")\n", + ")\n", + "\n", + "# Output box\n", + "naive_widget = widgets.ToggleButton(value=False, description=\"Show Naive\")\n", + "forecast_only_widget = widgets.ToggleButton(value=False, description=\"Forecast Only\")\n", + "run_widget = widgets.ToggleButton(value=False, description=\"Run Model\")\n", + "\n", + "# feat_box\n", + "feat_value = list(feat_engs.keys())[0] if feat_engs else None\n", + "column_widget = widgets.Dropdown(options=[\"\"], value=\"\", description=\"Target\")\n", + "feat_widget = widgets.Dropdown(\n", + " options=list(feat_engs.keys()), value=feat_value, description=\"Feature\"\n", + ")\n", + "add_widget = widgets.ToggleButton(\n", + " value=False, description=\"Add Feature\", layout=widgets.Layout(align=\"flex_end\")\n", + ") # get this to work\n", + "\n", + "selection_box = widgets.VBox([tickers_widget, target_widget])\n", + "date_box = widgets.VBox([start_widget, end_widget, interval_widget])\n", + "output_box = widgets.VBox([naive_widget, forecast_only_widget, run_widget])\n", + "feat_box = widgets.VBox([column_widget, feat_widget, add_widget])\n", + "controls = widgets.HBox(\n", + " [selection_box, model_widget, past_covs_widget, date_box, output_box, feat_box],\n", + ")\n", + "if has_forecast:\n", + " chart = Chart()\n", + " widgets.interactive_output(\n", + " chart.handle_changes,\n", + " {\n", + " \"past_covariates\": past_covs_widget,\n", + " \"start\": start_widget,\n", + " \"end\": end_widget,\n", + " \"interval\": interval_widget,\n", + " \"tickers\": tickers_widget,\n", + " \"target_column\": target_widget,\n", + " \"model\": model_widget,\n", + " \"naive\": naive_widget,\n", + " \"forecast_only\": forecast_only_widget,\n", + " },\n", + " )\n", + "\n", + " widgets.interactive_output(\n", + " chart.handle_eng, {\"target\": column_widget, \"feature\": feat_widget}\n", + " )\n", + " widgets.interactive_output(chart.handle_click2, {\"to_run\": add_widget})\n", + "\n", + " stocks_view = widgets.interactive_output(chart.handle_click, {\"to_run\": run_widget})\n", + "\n", + " title_html = \"Use a comma after EVERY stock typed.
'\n", + "\n", + " app_contents = [\n", + " widgets.HTML(title_html),\n", + " controls,\n", + " widgets.HTML(warning_html),\n", + " stocks_view,\n", + " ]\n", + " app = widgets.VBox(app_contents)\n", + "else:\n", + " title_html = \"The forecasting dependencies are not installed.
'\n", + " )\n", + " app = widgets.VBox([widgets.HTML(title_html), widgets.HTML(warning_html)])\n", + "display(app)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9dbf43a2-70e1-44e9-a524-be3e97008b58", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.9.6" + }, + "metadata": { + "interpreter": { + "hash": "e896a00ead8b521528d79ac9ef24990696f2b751eb283ab8e0d078c9c4971ffc" + } + }, + "vscode": { + "interpreter": { + "hash": "bd3088e2ce83c7406a082a5b650cfc74fd1480320510d276c9fa5780b96e5fae" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/openbb_terminal/reports/reports_controller.py b/openbb_terminal/reports/reports_controller.py index 4116e2b6060..bea8bdd83ce 100644 --- a/openbb_terminal/reports/reports_controller.py +++ b/openbb_terminal/reports/reports_controller.py @@ -8,7 +8,6 @@ import os # pylint: disable=R1732, R0912 from typing import Any, Dict, List, Optional -import openbb_terminal.config_terminal as cfg from openbb_terminal.core.session.current_user import get_current_user from openbb_terminal.custom_prompt_toolkit import NestedCompleter from openbb_terminal.decorators import log_start_end @@ -191,7 +190,6 @@ class ReportController(BaseController): ns_parser = self.parse_simple_args(parser, other_args) if ns_parser: - cfg.change_logging_suppress(new_value=True) if report_name == "equity" and "." in ns_parser.symbol: console.print( "[red]Cannot currently handle tickers with a '.' in them[/red]\n" @@ -203,7 +201,6 @@ class ReportController(BaseController): input_path=str(reports_model.REPORTS_FOLDER / report_name), args_dict=parameters, ) - cfg.change_logging_suppress(new_value=False) else: console.print("[red]Notebook not found![/red]\n") diff --git a/openbb_terminal/reports/reports_model.py b/openbb_terminal/reports/reports_model.py index f16f3782c31..2c323d12fb9 100644 --- a/openbb_terminal/reports/reports_model.py +++ b/openbb_terminal/reports/reports_model.py @@ -5,12 +5,12 @@ import logging # pylint: disable=R1732, R0912 import os -from ast import literal_eval from datetime import datetime from pathlib import Path from threading import Thread from typing import Any, Dict, List, Union +import nbformat import pandas as pd import papermill as pm from ipykernel.kernelapp import IPKernelApp @@ -85,6 +85,7 @@ REPORT_CHOICES = { "--symbol": {c: None for c in STOCKS_TICKERS + ETF_TICKERS}, }, } +TARGET_TAG = "parameters" @log_start_end(log=logger) @@ -157,43 +158,34 @@ def extract_parameters(input_path: str) -> Dict[str, str]: input_path = add_ipynb_extension(input_path) - with open(input_path, encoding="utf-8") as file: - notebook_content = file.read() + with open(input_path) as f: + nb = nbformat.read(f, as_version=nbformat.NO_CONVERT) - # Look for the metadata cell to understand if there are parameters required by the report - metadata_cell = """"metadata": {\n "tags": [\n "parameters"\n ]\n },\n "outputs":""" + target_tag = TARGET_TAG - # Locate position of the data of interest and get parameters - if notebook_content.find(metadata_cell) >= 0: - position = notebook_content.find(metadata_cell) - else: - return {} + cell_lines = [] + for cell in nb.cells: + # Filter cells by tag + if target_tag in cell.metadata.get("tags", []): + # Split cell source into separate lines + lines = cell.source.split("\n") + # Remove empty and commented lines + lines = [ + line for line in lines if line.strip() and not line.startswith("#") + ] + cell_lines.extend(lines) - metadata = notebook_content[position:] # noqa: E203 - cell_start = 'source": ' - cell_end = "]" - start_position = metadata.find(cell_start) - params = metadata[ - start_position : metadata.find(cell_end, start_position) + 1 # noqa: E203 - ] + parameters_dict = {} + for line in cell_lines: + # Extract key and value from each line + key, value = line.split("=") + key = key.strip() + value = value.strip() + # Add key-value pair to dictionary + parameters_dict[key] = value - # Make sure that the parameters provided are relevant - if "parameters" in notebook_content: - parameters_names = [ - param.split("=")[0][:-1] - for param in literal_eval(params.strip('source": ')) - if param[0] not in ["#", "\n"] - ] - parameters_values = [ - param.split("=")[1][2:-2] - for param in literal_eval(params.strip('source": ')) - if param[0] not in ["#", "\n"] - ] - - if "report_name" in parameters_names: - parameters_names.remove("report_name") - - parameters_dict = dict(zip(parameters_names, parameters_values)) + if "report_name" in parameters_dict: + parameters_dict.pop("report_name") return parameters_dict diff --git a/openbb_terminal/reports/templates/crypto.ipynb b/openbb_terminal/reports/templates/crypto.ipynb index 1746dede123..e99939b124f 100644 --- a/openbb_terminal/reports/templates/crypto.ipynb +++ b/openbb_terminal/reports/templates/crypto.ipynb @@ -1,1148 +1,1160 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "70ba2c8a", - "metadata": {}, - "source": [ - "## Notebook setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "driven-billion", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import io\n", - "import warnings\n", - "import datetime\n", - "import numpy as np\n", - "import base64\n", - "import pandas as pd\n", - "from typing import List\n", - "\n", - "from IPython.display import HTML\n", - "\n", - "import openbb_terminal.config_terminal as cfg\n", - "from openbb_terminal.reports import widget_helpers as widgets\n", - "from openbb_terminal.sdk import openbb\n", - "from openbb_terminal.helper_classes import TerminalStyle\n", - "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", - "from openbb_terminal import OpenBBFigure\n", - "\n", - "\n", - "warnings.filterwarnings(\"ignore\")\n", - "\n", - "pd.set_option(\"display.float_format\", lambda x: \"%.5f\" % x)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", - "metadata": {}, - "outputs": [], - "source": [ - "from openbb_terminal.core.session.current_user import get_current_user\n", - "\n", - "user = get_current_user()\n", - "\n", - "cfg.theme = TerminalStyle(\n", - " user.preferences.MPL_STYLE,\n", - " user.preferences.PMF_STYLE,\n", - " user.preferences.RICH_STYLE,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c52f83e1", - "metadata": {}, - "outputs": [], - "source": [ - "stylesheet = widgets.html_report_stylesheet()" - ] - }, - { - "cell_type": "markdown", - "id": "807fda4e", - "metadata": {}, - "source": [ - "## Select Ticker" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "intended-sherman", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "# Parameters that will be replaced when calling this notebook\n", - "# Do not leave parameters blank as notebook will not run otherwise\n", - "symbol = \"BTC\"\n", - "report_name = f\"Crypto Report for {symbol}\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2c46efb8", - "metadata": {}, - "outputs": [], - "source": [ - "ticker = symbol" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d4897334", - "metadata": {}, - "outputs": [], - "source": [ - "author = \"\"\n", - "report_title = f\"INVESTMENT RESEARCH REPORT ON {ticker.upper()}\"\n", - "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", - "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", - "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", - "report_title, report_date, report_time, report_timezone" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "35d9a943", - "metadata": {}, - "outputs": [], - "source": [ - "# basic info\n", - "\n", - "basic_info = openbb.crypto.dd.basic(ticker)\n", - "if not basic_info.empty:\n", - " basic_info = basic_info.set_index(\"Metric\")\n", - " basic_info" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "091d305e", - "metadata": {}, - "outputs": [], - "source": [ - "news = openbb.crypto.dd.news(symbol=ticker).head(10)\n", - "\n", - "if (isinstance(news, pd.DataFrame) and not news.empty) or (\n", - " not isinstance(news, pd.DataFrame) and news\n", - "):\n", - " news = news.set_index(\"published_at\")\n", - " news.sort_index()\n", - " news[\"link\"] = news[\"link\"].apply(lambda x: f'{x}')\n", - " news\n", - "else:\n", - " news = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bd281ab8", - "metadata": {}, - "outputs": [], - "source": [ - "links = openbb.crypto.dd.links(ticker)\n", - "\n", - "if (isinstance(links, pd.DataFrame) and not links.empty) or (\n", - " not isinstance(links, pd.DataFrame) and links\n", - "):\n", - " links[\"Link\"] = links[\"Link\"].apply(lambda x: f'{x}')\n", - " links\n", - "else:\n", - " links = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "07d09ce8", - "metadata": {}, - "outputs": [], - "source": [ - "five_year = datetime.datetime.now() - datetime.timedelta(days=1825)\n", - "three_year = datetime.datetime.now() - datetime.timedelta(days=1095)\n", - "one_year = datetime.datetime.now() - datetime.timedelta(days=365)\n", - "three_months = datetime.datetime.now() - datetime.timedelta(days=90)\n", - "\n", - "dates = {\n", - " \"three_months\": three_months,\n", - " \"one_year\": one_year,\n", - " \"three_year\": three_year,\n", - " \"five_year\": five_year,\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e6d6d43d", - "metadata": {}, - "outputs": [], - "source": [ - "from tkinter.filedialog import Open\n", - "\n", - "\n", - "def get_historical_data(ticker, dict_of_dates, is_plot=True) -> List[pd.DataFrame]:\n", - " list_of_historical_data = []\n", - "\n", - " for date in dict_of_dates:\n", - " data = openbb.crypto.load(\n", - " symbol=ticker,\n", - " to_symbol=\"usd\",\n", - " start_date=dict_of_dates[date],\n", - " source=\"YahooFinance\",\n", - " )\n", - "\n", - " if data.empty:\n", - " continue\n", - "\n", - " # we'll be using the adjusted close price as same as close price\n", - " data[\"Adj Close\"] = data[\"Close\"]\n", - "\n", - " if is_plot:\n", - " fig = OpenBBFigure(yaxis_title=\"USDT\").set_title(\n", - " f\"{date} historical data for {ticker.upper()}\"\n", - " )\n", - " fig.add_scatter(x=data.index, y=data[\"Adj Close\"], name=\"Close\")\n", - "\n", - " plot_data = fig.to_html()\n", - "\n", - " list_of_historical_data.append(plot_data)\n", - " else:\n", - " list_of_historical_data.append(data)\n", - "\n", - " return list_of_historical_data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ed19a708", - "metadata": {}, - "outputs": [], - "source": [ - "try:\n", - " historical_data = get_historical_data(ticker, dates)\n", - "except Exception as e:\n", - " raise KeyboardInterrupt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8f815dbc", - "metadata": {}, - "outputs": [], - "source": [ - "historical_data_one_year = get_historical_data(ticker, {\"one_year\": one_year}, False)[0]\n", - "historical_data_one_year" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "081a4bb3", - "metadata": {}, - "outputs": [], - "source": [ - "from openbb_terminal.cryptocurrency.cryptocurrency_helpers import show_quick_performance\n", - "\n", - "show_quick_performance(\n", - " crypto_df=historical_data_one_year,\n", - " symbol=ticker,\n", - " current_currency=\"USDT\",\n", - " source=\"YahooFinance\",\n", - " exchange=\"binance\",\n", - " interval=\"1440\",\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "88af0fbe", - "metadata": {}, - "outputs": [], - "source": [ - "headlines = openbb.crypto.dd.headlines_chart(ticker, external_axes=True)\n", - "\n", - "if headlines:\n", - " headlines = headlines.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e4509c6e", - "metadata": {}, - "outputs": [], - "source": [ - "candle_one_year = openbb.crypto.chart(\n", - " historical_data_one_year,\n", - " to_symbol=ticker,\n", - " from_symbol=\"USDT\",\n", - " source=\"YahooFinance\",\n", - " exchange=\"binance\",\n", - " interval=\"1440\",\n", - " external_axes=True,\n", - ")\n", - "\n", - "if candle_one_year:\n", - " candle_one_year = candle_one_year.to_html()" - ] - }, - { - "cell_type": "markdown", - "id": "7f83daae", - "metadata": {}, - "source": [ - "## Due Diligence" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "93d66cf1", - "metadata": {}, - "outputs": [], - "source": [ - "# market cap dominance\n", - "mcapdom_df = openbb.crypto.dd.mcapdom(symbol=ticker)\n", - "\n", - "if (isinstance(mcapdom_df, pd.DataFrame) and not mcapdom_df.empty) or (\n", - " not isinstance(mcapdom_df, pd.DataFrame) and mcapdom_df\n", - "):\n", - " mcapdom = openbb.crypto.dd.mcapdom_chart(symbol=ticker, external_axes=True)\n", - "\n", - " if mcapdom:\n", - " mcapdom = mcapdom.to_html()\n", - "else:\n", - " mcapdom_df = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "284b0586", - "metadata": {}, - "outputs": [], - "source": [ - "# roadmap\n", - "roadmap_model = openbb.crypto.dd.rm(symbol=ticker)\n", - "\n", - "if (isinstance(roadmap_model, pd.DataFrame) and not roadmap_model.empty) or (\n", - " not isinstance(roadmap_model, pd.DataFrame) and roadmap_model\n", - "):\n", - " roadmap_model = roadmap_model.set_index(\"Date\")\n", - " roadmap_model.sort_index()\n", - "\n", - " roadmap_view = openbb.crypto.dd.rm_chart(symbol=ticker, external_axes=True)\n", - " if roadmap_view:\n", - " roadmap_view = roadmap_view.to_html()\n", - "\n", - "else:\n", - " roadmap_model = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9ddbc654", - "metadata": {}, - "outputs": [], - "source": [ - "tokenomics_model = openbb.crypto.dd.rm(symbol=ticker)\n", - "\n", - "if (isinstance(tokenomics_model, pd.DataFrame) and not tokenomics_model.empty) or (\n", - " not isinstance(tokenomics_model, pd.DataFrame) and tokenomics_model\n", - "):\n", - " tokenomics_model = tokenomics_model.set_index(\"Date\")\n", - " tokenomics_model.sort_index()\n", - "\n", - " tokenomics_view = openbb.crypto.dd.tk_chart(symbol=ticker, external_axes=True)\n", - " if tokenomics_view:\n", - " tokenomics_view = tokenomics_view.to_html()\n", - "\n", - "else:\n", - " tokenomics_model = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7d02fcc4", - "metadata": {}, - "outputs": [], - "source": [ - "# fundraise\n", - "fundraise = openbb.crypto.dd.fr(symbol=ticker) # this returns a tuple\n", - "\n", - "if fundraise:\n", - " fundraise_info = fundraise[0]\n", - " fundraise_df = fundraise[1]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5e625a2e", - "metadata": {}, - "outputs": [], - "source": [ - "trading_pair_info = openbb.crypto.dd.trading_pair_info(f\"{ticker}-USDT\")\n", - "if (isinstance(trading_pair_info, pd.DataFrame) and not trading_pair_info.empty) or (\n", - " not isinstance(trading_pair_info, pd.DataFrame) and trading_pair_info\n", - "):\n", - " trading_pair_info = trading_pair_info.set_index(\"Metric\")\n", - " trading_pair_info\n", - "else:\n", - " trading_pair_info = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8f33b4d8", - "metadata": {}, - "outputs": [], - "source": [ - "import openbb_terminal.cryptocurrency.due_diligence.pycoingecko_model as gecko\n", - "from openbb_terminal.cryptocurrency.cryptocurrency_helpers import get_coingecko_id\n", - "\n", - "ath = pd.DataFrame()\n", - "try:\n", - " cg_id = get_coingecko_id(symbol=ticker)\n", - " coin = gecko.Coin(ticker)\n", - " ath = coin.get_all_time_high(currency=cg_id)\n", - "\n", - "except Exception as e:\n", - " print(\"Reached coingecko API limit\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2a82e990", - "metadata": {}, - "outputs": [], - "source": [ - "import openbb_terminal.cryptocurrency.due_diligence.pycoingecko_model as gecko\n", - "from openbb_terminal.cryptocurrency.cryptocurrency_helpers import get_coingecko_id\n", - "\n", - "atl = pd.DataFrame()\n", - "try:\n", - " cg_id = get_coingecko_id(symbol=ticker)\n", - " coin = gecko.Coin(ticker)\n", - " atl = coin.get_all_time_low(currency=cg_id)\n", - "\n", - "except Exception as e:\n", - " print(\"Reached coingecko API limit\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e9e512e9", - "metadata": {}, - "outputs": [], - "source": [ - "# market stats about loaded coin\n", - "\n", - "market = openbb.crypto.dd.mkt(ticker)\n", - "\n", - "if (isinstance(market, pd.DataFrame) and not market.empty) or (\n", - " not isinstance(market, pd.DataFrame) and market\n", - "):\n", - " market = market.set_index(\"exchange\")\n", - "\n", - " market[\"market_url\"] = market[\"market_url\"].apply(\n", - " lambda x: f'{x}'\n", - " )\n", - " market\n", - "else:\n", - " market = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1d6e76cb", - "metadata": {}, - "outputs": [], - "source": [ - "# all exchanges where loaded coin is listed\n", - "ex = openbb.crypto.dd.ex(ticker)\n", - "\n", - "if (isinstance(ex, pd.DataFrame) and not ex.empty) or (\n", - " not isinstance(ex, pd.DataFrame) and ex\n", - "):\n", - " ex = ex.set_index(\"id\")\n", - " ex\n", - "else:\n", - " ex = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1fcdbc67", - "metadata": {}, - "outputs": [], - "source": [ - "# last trades\n", - "trades = openbb.crypto.dd.trades(symbol=ticker, exchange_id=\"gemini\", to_symbol=\"USD\")\n", - "if (isinstance(trades, pd.DataFrame) and not trades.empty) or (\n", - " not isinstance(trades, pd.DataFrame) and trades\n", - "):\n", - " trades = trades.set_index(\"Date\")\n", - " trades\n", - "else:\n", - " trades = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "262d190a", - "metadata": {}, - "outputs": [], - "source": [ - "# order book\n", - "order_book_raw = openbb.crypto.dd.ob(\n", - " symbol=ticker, exchange=\"gemini\", to_symbol=\"USD\"\n", - ") # this returns a dict\n", - "\n", - "if order_book_raw:\n", - " order_book = openbb.crypto.dd.ob_chart(\n", - " symbol=ticker, exchange=\"gemini\", to_symbol=\"USD\", external_axes=True\n", - " )\n", - " if order_book:\n", - " order_book = order_book.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "679d0d79", - "metadata": {}, - "outputs": [], - "source": [ - "# price and supply related metrics for loaded coin\n", - "\n", - "ps = openbb.crypto.dd.ps(ticker)\n", - "if (isinstance(ps, pd.DataFrame) and not ps.empty) or (\n", - " not isinstance(ps, pd.DataFrame) and ps\n", - "):\n", - " ps = ps.set_index(\"Metric\")\n", - " ps\n", - "else:\n", - " ps = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "92e76d79", - "metadata": {}, - "outputs": [], - "source": [ - "# events\n", - "\n", - "events = openbb.crypto.dd.events(ticker)\n", - "\n", - "if (isinstance(events, pd.DataFrame) and not events.empty) or (\n", - " not isinstance(events, pd.DataFrame) and events\n", - "):\n", - " events = events.set_index(\"date\")\n", - " events[\"link\"] = events[\"link\"].apply(lambda x: f'{x}')\n", - "else:\n", - " events = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a14130db", - "metadata": {}, - "outputs": [], - "source": [ - "# social media\n", - "\n", - "from openbb_terminal.cryptocurrency.due_diligence.pycoingecko_view import display_social\n", - "\n", - "display_social(ticker)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8f89627f", - "metadata": {}, - "outputs": [], - "source": [ - "# tweets for loaded coin\n", - "\n", - "tweets = openbb.crypto.dd.twitter(ticker)\n", - "tweets" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9bb75443", - "metadata": {}, - "outputs": [], - "source": [ - "# github activity over time\n", - "\n", - "gh_data = openbb.crypto.dd.gh(symbol=ticker)\n", - "\n", - "if (isinstance(gh_data, pd.DataFrame) and not gh_data.empty) or (\n", - " not isinstance(gh_data, pd.DataFrame) and gh_data\n", - "):\n", - " gh = openbb.crypto.dd.gh_chart(symbol=ticker, external_axes=True)\n", - " if gh:\n", - " gh = gh.to_html()\n", - "else:\n", - " gh_data = pd.DataFrame()" - ] - }, - { - "cell_type": "markdown", - "id": "fcaa973d", - "metadata": {}, - "source": [ - "## TA\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "477317b4", - "metadata": {}, - "outputs": [], - "source": [ - "ticker_data = historical_data_one_year.copy()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7af3695c", - "metadata": {}, - "outputs": [], - "source": [ - "# simple moving average\n", - "ticker_data.index.names = [\"date\"]\n", - "\n", - "sma = openbb.ta.ma_chart(\n", - " data=ticker_data,\n", - " ma_type=\"SMA\",\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if sma:\n", - " sma = sma.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5d5089fa", - "metadata": {}, - "outputs": [], - "source": [ - "# exponential moving average\n", - "ema = openbb.ta.ma_chart(\n", - " data=ticker_data,\n", - " ma_type=\"EMA\",\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if ema:\n", - " ema = ema.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5facfbf4", - "metadata": {}, - "outputs": [], - "source": [ - "# zero lag exponential moving average\n", - "\n", - "zlma = openbb.ta.ma_chart(\n", - " data=ticker_data,\n", - " ma_type=\"ZLMA\",\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if zlma:\n", - " zlma = zlma.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "df54f7ad", - "metadata": {}, - "outputs": [], - "source": [ - "# commodity channel index\n", - "\n", - "cci = openbb.ta.cci_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if cci:\n", - " cci = cci.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f53469eb", - "metadata": {}, - "outputs": [], - "source": [ - "# moving average convergence/divergence\n", - "\n", - "macd = openbb.ta.macd_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if macd:\n", - " macd = macd.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dd79e6b6", - "metadata": {}, - "outputs": [], - "source": [ - "# fisher transform\n", - "\n", - "fisher = openbb.ta.fisher_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if fisher:\n", - " fisher = fisher.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b699e61f", - "metadata": {}, - "outputs": [], - "source": [ - "# aroon indicator\n", - "\n", - "aroon = openbb.ta.aroon_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if aroon:\n", - " aroon = aroon.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "79401027", - "metadata": {}, - "outputs": [], - "source": [ - "# bollinger bands\n", - "\n", - "bbands = openbb.ta.bbands_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if bbands:\n", - " bbands = bbands.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0b5e2949", - "metadata": {}, - "outputs": [], - "source": [ - "# fibonacci retracement\n", - "\n", - "fib = openbb.ta.fib_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if fib:\n", - " fib = fib.to_html()" - ] - }, - { - "cell_type": "markdown", - "id": "48847a7f", - "metadata": {}, - "source": [ - "## QA" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e77b373b", - "metadata": {}, - "outputs": [], - "source": [ - "# summary\n", - "\n", - "summary = openbb.qa.summary(data=ticker_data)\n", - "summary" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3ecfc93e", - "metadata": {}, - "outputs": [], - "source": [ - "# normality statistics and tests\n", - "\n", - "# openbb.qa.normality_chart(\n", - "# data=ticker_data,\n", - "# target=\"Close\",\n", - "# )\n", - "\n", - "normality = openbb.qa.normality(\n", - " data=ticker_data[\"Close\"],\n", - ")\n", - "normality" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8abe96b0", - "metadata": {}, - "outputs": [], - "source": [ - "# box and whisker plot\n", - "\n", - "bw = openbb.qa.bw(\n", - " symbol=ticker,\n", - " data=ticker_data,\n", - " target=\"Close\",\n", - " yearly=False,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if bw:\n", - " bw = bw.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "66a7dccc", - "metadata": {}, - "outputs": [], - "source": [ - "# rolling mean and std deviation of prices\n", - "\n", - "rolling = openbb.qa.rolling_chart(\n", - " symbol=ticker,\n", - " data=ticker_data,\n", - " target=\"Close\",\n", - " external_axes=True,\n", - ")\n", - "\n", - "if rolling:\n", - " rolling = rolling.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d6b43dd7", - "metadata": {}, - "outputs": [], - "source": [ - "# rolling kurtosis of distribution of prices\n", - "\n", - "kurtosis = openbb.qa.kurtosis_chart(\n", - " symbol=ticker,\n", - " data=ticker_data,\n", - " target=\"Close\",\n", - " external_axes=True,\n", - ")\n", - "\n", - "if kurtosis:\n", - " kurtosis = kurtosis.to_html()" - ] - }, - { - "cell_type": "markdown", - "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", - "metadata": {}, - "source": [ - "## Render the report template to a file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", - "metadata": {}, - "outputs": [], - "source": [ - "body = f\"\"\"\n", - "\n", - "\n", - "\"\"\"\n", - "\n", - "\n", - "img = (\n", - " str(REPOSITORY_DIRECTORY)\n", - " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", - ")\n", - "floppy_disk_img = (\n", - " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", - ")\n", - "body += widgets.header(\n", - " img,\n", - " floppy_disk_img,\n", - " author,\n", - " report_date,\n", - " report_time,\n", - " report_timezone,\n", - " f\"INVESTMENT RESEARCH REPORT: {ticker}\",\n", - ")\n", - "\n", - "body += widgets.tablinks(\n", - " [\n", - " \"SUMMARY\",\n", - " \"Due Diligence\",\n", - " \"Technical Analysis\",\n", - " \"Quantitative Analysis\",\n", - " ]\n", - ")\n", - "\n", - "comment = \"\"\n", - "\n", - "# Summary tab\n", - "htmlcode = \"\"\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Basic information about loaded coin\") + basic_info.to_html()]\n", - ")\n", - "if not links.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"Links\") + links.to_html(escape=False)])\n", - "\n", - "if not news.empty:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, \"Published news\") + news.to_html(escape=False)]\n", - " )\n", - "\n", - "htmlcode += widgets.row([widgets.h(3, \"Historical data\")])\n", - "for data in historical_data:\n", - " htmlcode += widgets.row([data])\n", - "\n", - "htmlcode += widgets.row([widgets.h(3, \"1-year historical data candlestick chart\")])\n", - "htmlcode += widgets.row([candle_one_year])\n", - "htmlcode += widgets.row([widgets.h(3, \"Sentiment analysis\")])\n", - "htmlcode += widgets.row([headlines])\n", - "# TODO: print rich table\n", - "# htmlcode += widgets.row([widgets.h(3, \"Quick performance\")])\n", - "# htmlcode += widgets.row([quick_performance])\n", - "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", - "\n", - "# # Due diligence tab\n", - "htmlcode = \"\"\n", - "if not trading_pair_info.empty:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, f\"Trading pair info {ticker}/USDT\") + trading_pair_info.to_html()]\n", - " )\n", - "if not mcapdom_df.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"Market cap dominance\")])\n", - " htmlcode += widgets.row([mcapdom])\n", - "\n", - "if not roadmap_model.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"Roadmap\") + roadmap_model.to_html()])\n", - " htmlcode += widgets.row([roadmap_view])\n", - "\n", - "if not tokenomics_model.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"Tokenomics\") + tokenomics_model.to_html()])\n", - " htmlcode += widgets.row([tokenomics_view])\n", - "\n", - "if fundraise:\n", - " htmlcode += widgets.row([widgets.h(3, \"Fundraising Details\")])\n", - " htmlcode += widgets.row([widgets.p(fundraise_info)])\n", - " htmlcode += widgets.row([fundraise_df.to_html()])\n", - "\n", - "if not ath.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"All time high\")])\n", - " htmlcode += widgets.row([ath.to_html()])\n", - "\n", - "if not atl.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"All time low\")])\n", - " htmlcode += widgets.row([atl.to_html()])\n", - "\n", - "if not market.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"All markets\")])\n", - " htmlcode += widgets.row([market.sample(n=20).sort_index().to_html(escape=False)])\n", - "\n", - "if not ex.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"Exchanges where loaded coin is listed\")])\n", - " htmlcode += widgets.row([ex.sample(n=20).sort_index().to_html()])\n", - "\n", - "if not trades.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"Last trades\")])\n", - " htmlcode += widgets.row([trades.tail(20).to_html()])\n", - "\n", - "if order_book_raw:\n", - " htmlcode += widgets.row([widgets.h(3, \"Order book\")])\n", - " htmlcode += widgets.row([order_book])\n", - "\n", - "if not ps.empty:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, \"Price and supply related metrics for loaded coin\")]\n", - " )\n", - " htmlcode += widgets.row([ps.to_html()])\n", - "\n", - "if not events.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"Events\")])\n", - " htmlcode += widgets.row([events.to_html(escape=False)])\n", - "\n", - "# TODO: print rich table\n", - "# htmlcode += widgets.row([widgets.h(3, \"Tweets for loaded coin\")])\n", - "# htmlcode += widgets.row([tweets])\n", - "# htmlcode += widgets.row([widgets.h(3, \"Social media\")])\n", - "# htmlcode += widgets.row([social.to_html()])\n", - "\n", - "if not gh_data.empty:\n", - " htmlcode += widgets.row([widgets.h(3, \"Github activity over time\")])\n", - " htmlcode += widgets.row([gh])\n", - "else:\n", - " htmlcode += widgets.row([widgets.h(3, \"Github activity over time\")])\n", - " htmlcode += widgets.row([widgets.p(\"No data available.\")])\n", - "\n", - "body += widgets.add_tab(\"Due Diligence\", htmlcode)\n", - "\n", - "# Technical Analysis tab\n", - "htmlcode = \"\"\n", - "htmlcode = widgets.row([widgets.h(3, \"Simple moving average\")])\n", - "htmlcode += widgets.row([sma])\n", - "htmlcode += widgets.row([widgets.h(3, \"Exponential moving average\")])\n", - "htmlcode += widgets.row([ema])\n", - "htmlcode += widgets.row([widgets.h(3, \"Zero lag exponential moving average\")])\n", - "htmlcode += widgets.row([zlma])\n", - "htmlcode += widgets.row([widgets.h(3, \"Commodity channel index\")])\n", - "htmlcode += widgets.row([cci])\n", - "htmlcode += widgets.row([widgets.h(3, \"Moving average convergence/divergence\")])\n", - "htmlcode += widgets.row([macd])\n", - "htmlcode += widgets.row([widgets.h(3, \"Fisher transform\")])\n", - "htmlcode += widgets.row([fisher])\n", - "htmlcode += widgets.row([widgets.h(3, \"Aroon indicator\")])\n", - "htmlcode += widgets.row([aroon])\n", - "htmlcode += widgets.row([widgets.h(3, \"Bollinger bands\")])\n", - "htmlcode += widgets.row([bbands])\n", - "htmlcode += widgets.row([widgets.h(3, \"Fibonacci retracement\")])\n", - "htmlcode += widgets.row([fib])\n", - "body += widgets.add_tab(\"Technical Analysis\", htmlcode)\n", - "\n", - "# Quantitative Analysis tab\n", - "htmlcode = \"\"\n", - "htmlcode = widgets.row([widgets.h(3, \"Summary\") + summary.to_html()])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Normality statistics and tests\") + normality.to_html()]\n", - ")\n", - "htmlcode += widgets.row([widgets.h(3, \"Box and whisker plot\")])\n", - "htmlcode += widgets.row([bw])\n", - "htmlcode += widgets.row([widgets.h(3, \"Rolling mean and std deviation of prices\")])\n", - "htmlcode += widgets.row([rolling])\n", - "htmlcode += widgets.row([widgets.h(3, \"Rolling kurtosis of distribution of prices\")])\n", - "htmlcode += widgets.row([kurtosis])\n", - "body += widgets.add_tab(\"Quantitative Analysis\", htmlcode)\n", - "\n", - "body += widgets.tab_clickable_and_save_evt()\n", - "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", - "\n", - "# # to save the results\n", - "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", - " fh.write(report)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "venv", - "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.10.8" - }, - "vscode": { - "interpreter": { - "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "70ba2c8a", + "metadata": {}, + "source": [ + "## Notebook setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "driven-billion", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import io\n", + "import warnings\n", + "import datetime\n", + "import numpy as np\n", + "import base64\n", + "import pandas as pd\n", + "from typing import List\n", + "\n", + "from IPython.display import HTML\n", + "\n", + "import openbb_terminal.config_terminal as cfg\n", + "from openbb_terminal.helper_classes import TerminalStyle\n", + "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", + "from openbb_terminal import OpenBBFigure\n", + "\n", + "\n", + "warnings.filterwarnings(\"ignore\")\n", + "\n", + "pd.set_option(\"display.float_format\", lambda x: \"%.5f\" % x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24ed42f0", + "metadata": {}, + "outputs": [], + "source": [ + "# Suppressing sdk logs\n", + "cfg.change_logging_suppress(new_value=True)\n", + "\n", + "# Import the OpenBB SDK\n", + "from openbb_terminal.sdk import openbb, widgets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", + "metadata": {}, + "outputs": [], + "source": [ + "from openbb_terminal.core.session.current_user import get_current_user\n", + "\n", + "user = get_current_user()\n", + "\n", + "cfg.theme = TerminalStyle(\n", + " user.preferences.MPL_STYLE,\n", + " user.preferences.PMF_STYLE,\n", + " user.preferences.RICH_STYLE,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c52f83e1", + "metadata": {}, + "outputs": [], + "source": [ + "stylesheet = widgets.html_report_stylesheet()" + ] + }, + { + "cell_type": "markdown", + "id": "807fda4e", + "metadata": {}, + "source": [ + "## Select Ticker" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "intended-sherman", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "# Parameters that will be replaced when calling this notebook\n", + "# Do not leave parameters blank as notebook will not run otherwise\n", + "symbol = \"BTC\"\n", + "report_name = f\"Crypto Report for {symbol}\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c46efb8", + "metadata": {}, + "outputs": [], + "source": [ + "ticker = symbol" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d4897334", + "metadata": {}, + "outputs": [], + "source": [ + "author = \"\"\n", + "report_title = f\"INVESTMENT RESEARCH REPORT ON {ticker.upper()}\"\n", + "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", + "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", + "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", + "report_title, report_date, report_time, report_timezone" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "35d9a943", + "metadata": {}, + "outputs": [], + "source": [ + "# basic info\n", + "\n", + "basic_info = openbb.crypto.dd.basic(ticker)\n", + "if not basic_info.empty:\n", + " basic_info = basic_info.set_index(\"Metric\")\n", + " basic_info" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "091d305e", + "metadata": {}, + "outputs": [], + "source": [ + "news = openbb.crypto.dd.news(symbol=ticker).head(10)\n", + "\n", + "if (isinstance(news, pd.DataFrame) and not news.empty) or (\n", + " not isinstance(news, pd.DataFrame) and news\n", + "):\n", + " news = news.set_index(\"published_at\")\n", + " news.sort_index()\n", + " news[\"link\"] = news[\"link\"].apply(lambda x: f'{x}')\n", + " news\n", + "else:\n", + " news = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd281ab8", + "metadata": {}, + "outputs": [], + "source": [ + "links = openbb.crypto.dd.links(ticker)\n", + "\n", + "if (isinstance(links, pd.DataFrame) and not links.empty) or (\n", + " not isinstance(links, pd.DataFrame) and links\n", + "):\n", + " links[\"Link\"] = links[\"Link\"].apply(lambda x: f'{x}')\n", + " links\n", + "else:\n", + " links = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07d09ce8", + "metadata": {}, + "outputs": [], + "source": [ + "five_year = datetime.datetime.now() - datetime.timedelta(days=1825)\n", + "three_year = datetime.datetime.now() - datetime.timedelta(days=1095)\n", + "one_year = datetime.datetime.now() - datetime.timedelta(days=365)\n", + "three_months = datetime.datetime.now() - datetime.timedelta(days=90)\n", + "\n", + "dates = {\n", + " \"three_months\": three_months,\n", + " \"one_year\": one_year,\n", + " \"three_year\": three_year,\n", + " \"five_year\": five_year,\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6d6d43d", + "metadata": {}, + "outputs": [], + "source": [ + "from tkinter.filedialog import Open\n", + "\n", + "\n", + "def get_historical_data(ticker, dict_of_dates, is_plot=True) -> List[pd.DataFrame]:\n", + " list_of_historical_data = []\n", + "\n", + " for date in dict_of_dates:\n", + " data = openbb.crypto.load(\n", + " symbol=ticker,\n", + " to_symbol=\"usd\",\n", + " start_date=dict_of_dates[date],\n", + " source=\"YahooFinance\",\n", + " )\n", + "\n", + " if data.empty:\n", + " continue\n", + "\n", + " # we'll be using the adjusted close price as same as close price\n", + " data[\"Adj Close\"] = data[\"Close\"]\n", + "\n", + " if is_plot:\n", + " fig = OpenBBFigure(yaxis_title=\"USDT\").set_title(\n", + " f\"{date} historical data for {ticker.upper()}\"\n", + " )\n", + " fig.add_scatter(x=data.index, y=data[\"Adj Close\"], name=\"Close\")\n", + "\n", + " plot_data = fig.to_html()\n", + "\n", + " list_of_historical_data.append(plot_data)\n", + " else:\n", + " list_of_historical_data.append(data)\n", + "\n", + " return list_of_historical_data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed19a708", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " historical_data = get_historical_data(ticker, dates)\n", + "except Exception as e:\n", + " raise KeyboardInterrupt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f815dbc", + "metadata": {}, + "outputs": [], + "source": [ + "historical_data_one_year = get_historical_data(ticker, {\"one_year\": one_year}, False)[0]\n", + "historical_data_one_year" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "081a4bb3", + "metadata": {}, + "outputs": [], + "source": [ + "from openbb_terminal.cryptocurrency.cryptocurrency_helpers import show_quick_performance\n", + "\n", + "show_quick_performance(\n", + " crypto_df=historical_data_one_year,\n", + " symbol=ticker,\n", + " current_currency=\"USDT\",\n", + " source=\"YahooFinance\",\n", + " exchange=\"binance\",\n", + " interval=\"1440\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "88af0fbe", + "metadata": {}, + "outputs": [], + "source": [ + "headlines = openbb.crypto.dd.headlines_chart(ticker, external_axes=True)\n", + "\n", + "if headlines:\n", + " headlines = headlines.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e4509c6e", + "metadata": {}, + "outputs": [], + "source": [ + "candle_one_year = openbb.crypto.chart(\n", + " historical_data_one_year,\n", + " to_symbol=ticker,\n", + " from_symbol=\"USDT\",\n", + " source=\"YahooFinance\",\n", + " exchange=\"binance\",\n", + " interval=\"1440\",\n", + " external_axes=True,\n", + ")\n", + "\n", + "if candle_one_year:\n", + " candle_one_year = candle_one_year.to_html()" + ] + }, + { + "cell_type": "markdown", + "id": "7f83daae", + "metadata": {}, + "source": [ + "## Due Diligence" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93d66cf1", + "metadata": {}, + "outputs": [], + "source": [ + "# market cap dominance\n", + "mcapdom_df = openbb.crypto.dd.mcapdom(symbol=ticker)\n", + "\n", + "if (isinstance(mcapdom_df, pd.DataFrame) and not mcapdom_df.empty) or (\n", + " not isinstance(mcapdom_df, pd.DataFrame) and mcapdom_df\n", + "):\n", + " mcapdom = openbb.crypto.dd.mcapdom_chart(symbol=ticker, external_axes=True)\n", + "\n", + " if mcapdom:\n", + " mcapdom = mcapdom.to_html()\n", + "else:\n", + " mcapdom_df = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "284b0586", + "metadata": {}, + "outputs": [], + "source": [ + "# roadmap\n", + "roadmap_model = openbb.crypto.dd.rm(symbol=ticker)\n", + "\n", + "if (isinstance(roadmap_model, pd.DataFrame) and not roadmap_model.empty) or (\n", + " not isinstance(roadmap_model, pd.DataFrame) and roadmap_model\n", + "):\n", + " roadmap_model = roadmap_model.set_index(\"Date\")\n", + " roadmap_model.sort_index()\n", + "\n", + " roadmap_view = openbb.crypto.dd.rm_chart(symbol=ticker, external_axes=True)\n", + " if roadmap_view:\n", + " roadmap_view = roadmap_view.to_html()\n", + "\n", + "else:\n", + " roadmap_model = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9ddbc654", + "metadata": {}, + "outputs": [], + "source": [ + "tokenomics_model = openbb.crypto.dd.rm(symbol=ticker)\n", + "\n", + "if (isinstance(tokenomics_model, pd.DataFrame) and not tokenomics_model.empty) or (\n", + " not isinstance(tokenomics_model, pd.DataFrame) and tokenomics_model\n", + "):\n", + " tokenomics_model = tokenomics_model.set_index(\"Date\")\n", + " tokenomics_model.sort_index()\n", + "\n", + " tokenomics_view = openbb.crypto.dd.tk_chart(symbol=ticker, external_axes=True)\n", + " if tokenomics_view:\n", + " tokenomics_view = tokenomics_view.to_html()\n", + "\n", + "else:\n", + " tokenomics_model = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d02fcc4", + "metadata": {}, + "outputs": [], + "source": [ + "# fundraise\n", + "fundraise = openbb.crypto.dd.fr(symbol=ticker) # this returns a tuple\n", + "\n", + "if fundraise:\n", + " fundraise_info = fundraise[0]\n", + " fundraise_df = fundraise[1]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5e625a2e", + "metadata": {}, + "outputs": [], + "source": [ + "trading_pair_info = openbb.crypto.dd.trading_pair_info(f\"{ticker}-USDT\")\n", + "if (isinstance(trading_pair_info, pd.DataFrame) and not trading_pair_info.empty) or (\n", + " not isinstance(trading_pair_info, pd.DataFrame) and trading_pair_info\n", + "):\n", + " trading_pair_info = trading_pair_info.set_index(\"Metric\")\n", + " trading_pair_info\n", + "else:\n", + " trading_pair_info = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f33b4d8", + "metadata": {}, + "outputs": [], + "source": [ + "import openbb_terminal.cryptocurrency.due_diligence.pycoingecko_model as gecko\n", + "from openbb_terminal.cryptocurrency.cryptocurrency_helpers import get_coingecko_id\n", + "\n", + "ath = pd.DataFrame()\n", + "try:\n", + " cg_id = get_coingecko_id(symbol=ticker)\n", + " coin = gecko.Coin(ticker)\n", + " ath = coin.get_all_time_high(currency=cg_id)\n", + "\n", + "except Exception as e:\n", + " print(\"Reached coingecko API limit\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2a82e990", + "metadata": {}, + "outputs": [], + "source": [ + "import openbb_terminal.cryptocurrency.due_diligence.pycoingecko_model as gecko\n", + "from openbb_terminal.cryptocurrency.cryptocurrency_helpers import get_coingecko_id\n", + "\n", + "atl = pd.DataFrame()\n", + "try:\n", + " cg_id = get_coingecko_id(symbol=ticker)\n", + " coin = gecko.Coin(ticker)\n", + " atl = coin.get_all_time_low(currency=cg_id)\n", + "\n", + "except Exception as e:\n", + " print(\"Reached coingecko API limit\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e9e512e9", + "metadata": {}, + "outputs": [], + "source": [ + "# market stats about loaded coin\n", + "\n", + "market = openbb.crypto.dd.mkt(ticker)\n", + "\n", + "if (isinstance(market, pd.DataFrame) and not market.empty) or (\n", + " not isinstance(market, pd.DataFrame) and market\n", + "):\n", + " market = market.set_index(\"exchange\")\n", + "\n", + " market[\"market_url\"] = market[\"market_url\"].apply(\n", + " lambda x: f'{x}'\n", + " )\n", + " market\n", + "else:\n", + " market = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d6e76cb", + "metadata": {}, + "outputs": [], + "source": [ + "# all exchanges where loaded coin is listed\n", + "ex = openbb.crypto.dd.ex(ticker)\n", + "\n", + "if (isinstance(ex, pd.DataFrame) and not ex.empty) or (\n", + " not isinstance(ex, pd.DataFrame) and ex\n", + "):\n", + " ex = ex.set_index(\"id\")\n", + " ex\n", + "else:\n", + " ex = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1fcdbc67", + "metadata": {}, + "outputs": [], + "source": [ + "# last trades\n", + "trades = openbb.crypto.dd.trades(symbol=ticker, exchange_id=\"gemini\", to_symbol=\"USD\")\n", + "if (isinstance(trades, pd.DataFrame) and not trades.empty) or (\n", + " not isinstance(trades, pd.DataFrame) and trades\n", + "):\n", + " trades = trades.set_index(\"Date\")\n", + " trades\n", + "else:\n", + " trades = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "262d190a", + "metadata": {}, + "outputs": [], + "source": [ + "# order book\n", + "order_book_raw = openbb.crypto.dd.ob(\n", + " symbol=ticker, exchange=\"gemini\", to_symbol=\"USD\"\n", + ") # this returns a dict\n", + "\n", + "if order_book_raw:\n", + " order_book = openbb.crypto.dd.ob_chart(\n", + " symbol=ticker, exchange=\"gemini\", to_symbol=\"USD\", external_axes=True\n", + " )\n", + " if order_book:\n", + " order_book = order_book.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "679d0d79", + "metadata": {}, + "outputs": [], + "source": [ + "# price and supply related metrics for loaded coin\n", + "\n", + "ps = openbb.crypto.dd.ps(ticker)\n", + "if (isinstance(ps, pd.DataFrame) and not ps.empty) or (\n", + " not isinstance(ps, pd.DataFrame) and ps\n", + "):\n", + " ps = ps.set_index(\"Metric\")\n", + " ps\n", + "else:\n", + " ps = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92e76d79", + "metadata": {}, + "outputs": [], + "source": [ + "# events\n", + "\n", + "events = openbb.crypto.dd.events(ticker)\n", + "\n", + "if (isinstance(events, pd.DataFrame) and not events.empty) or (\n", + " not isinstance(events, pd.DataFrame) and events\n", + "):\n", + " events = events.set_index(\"date\")\n", + " events[\"link\"] = events[\"link\"].apply(lambda x: f'{x}')\n", + "else:\n", + " events = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a14130db", + "metadata": {}, + "outputs": [], + "source": [ + "# social media\n", + "\n", + "from openbb_terminal.cryptocurrency.due_diligence.pycoingecko_view import display_social\n", + "\n", + "display_social(ticker)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f89627f", + "metadata": {}, + "outputs": [], + "source": [ + "# tweets for loaded coin\n", + "\n", + "tweets = openbb.crypto.dd.twitter(ticker)\n", + "tweets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9bb75443", + "metadata": {}, + "outputs": [], + "source": [ + "# github activity over time\n", + "\n", + "gh_data = openbb.crypto.dd.gh(symbol=ticker)\n", + "\n", + "if (isinstance(gh_data, pd.DataFrame) and not gh_data.empty) or (\n", + " not isinstance(gh_data, pd.DataFrame) and gh_data\n", + "):\n", + " gh = openbb.crypto.dd.gh_chart(symbol=ticker, external_axes=True)\n", + " if gh:\n", + " gh = gh.to_html()\n", + "else:\n", + " gh_data = pd.DataFrame()" + ] + }, + { + "cell_type": "markdown", + "id": "fcaa973d", + "metadata": {}, + "source": [ + "## TA\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "477317b4", + "metadata": {}, + "outputs": [], + "source": [ + "ticker_data = historical_data_one_year.copy()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7af3695c", + "metadata": {}, + "outputs": [], + "source": [ + "# simple moving average\n", + "ticker_data.index.names = [\"date\"]\n", + "\n", + "sma = openbb.ta.ma_chart(\n", + " data=ticker_data,\n", + " ma_type=\"SMA\",\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if sma:\n", + " sma = sma.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d5089fa", + "metadata": {}, + "outputs": [], + "source": [ + "# exponential moving average\n", + "ema = openbb.ta.ma_chart(\n", + " data=ticker_data,\n", + " ma_type=\"EMA\",\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if ema:\n", + " ema = ema.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5facfbf4", + "metadata": {}, + "outputs": [], + "source": [ + "# zero lag exponential moving average\n", + "\n", + "zlma = openbb.ta.ma_chart(\n", + " data=ticker_data,\n", + " ma_type=\"ZLMA\",\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if zlma:\n", + " zlma = zlma.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df54f7ad", + "metadata": {}, + "outputs": [], + "source": [ + "# commodity channel index\n", + "\n", + "cci = openbb.ta.cci_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if cci:\n", + " cci = cci.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f53469eb", + "metadata": {}, + "outputs": [], + "source": [ + "# moving average convergence/divergence\n", + "\n", + "macd = openbb.ta.macd_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if macd:\n", + " macd = macd.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd79e6b6", + "metadata": {}, + "outputs": [], + "source": [ + "# fisher transform\n", + "\n", + "fisher = openbb.ta.fisher_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if fisher:\n", + " fisher = fisher.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b699e61f", + "metadata": {}, + "outputs": [], + "source": [ + "# aroon indicator\n", + "\n", + "aroon = openbb.ta.aroon_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if aroon:\n", + " aroon = aroon.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79401027", + "metadata": {}, + "outputs": [], + "source": [ + "# bollinger bands\n", + "\n", + "bbands = openbb.ta.bbands_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if bbands:\n", + " bbands = bbands.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b5e2949", + "metadata": {}, + "outputs": [], + "source": [ + "# fibonacci retracement\n", + "\n", + "fib = openbb.ta.fib_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if fib:\n", + " fib = fib.to_html()" + ] + }, + { + "cell_type": "markdown", + "id": "48847a7f", + "metadata": {}, + "source": [ + "## QA" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e77b373b", + "metadata": {}, + "outputs": [], + "source": [ + "# summary\n", + "\n", + "summary = openbb.qa.summary(data=ticker_data)\n", + "summary" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ecfc93e", + "metadata": {}, + "outputs": [], + "source": [ + "# normality statistics and tests\n", + "\n", + "# openbb.qa.normality_chart(\n", + "# data=ticker_data,\n", + "# target=\"Close\",\n", + "# )\n", + "\n", + "normality = openbb.qa.normality(\n", + " data=ticker_data[\"Close\"],\n", + ")\n", + "normality" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8abe96b0", + "metadata": {}, + "outputs": [], + "source": [ + "# box and whisker plot\n", + "\n", + "bw = openbb.qa.bw(\n", + " symbol=ticker,\n", + " data=ticker_data,\n", + " target=\"Close\",\n", + " yearly=False,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if bw:\n", + " bw = bw.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66a7dccc", + "metadata": {}, + "outputs": [], + "source": [ + "# rolling mean and std deviation of prices\n", + "\n", + "rolling = openbb.qa.rolling_chart(\n", + " symbol=ticker,\n", + " data=ticker_data,\n", + " target=\"Close\",\n", + " external_axes=True,\n", + ")\n", + "\n", + "if rolling:\n", + " rolling = rolling.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6b43dd7", + "metadata": {}, + "outputs": [], + "source": [ + "# rolling kurtosis of distribution of prices\n", + "\n", + "kurtosis = openbb.qa.kurtosis_chart(\n", + " symbol=ticker,\n", + " data=ticker_data,\n", + " target=\"Close\",\n", + " external_axes=True,\n", + ")\n", + "\n", + "if kurtosis:\n", + " kurtosis = kurtosis.to_html()" + ] + }, + { + "cell_type": "markdown", + "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", + "metadata": {}, + "source": [ + "## Render the report template to a file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", + "metadata": {}, + "outputs": [], + "source": [ + "body = f\"\"\"\n", + "\n", + "\n", + "\"\"\"\n", + "\n", + "\n", + "img = (\n", + " str(REPOSITORY_DIRECTORY)\n", + " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", + ")\n", + "floppy_disk_img = (\n", + " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", + ")\n", + "body += widgets.header(\n", + " img,\n", + " floppy_disk_img,\n", + " author,\n", + " report_date,\n", + " report_time,\n", + " report_timezone,\n", + " f\"INVESTMENT RESEARCH REPORT: {ticker}\",\n", + ")\n", + "\n", + "body += widgets.tablinks(\n", + " [\n", + " \"SUMMARY\",\n", + " \"Due Diligence\",\n", + " \"Technical Analysis\",\n", + " \"Quantitative Analysis\",\n", + " ]\n", + ")\n", + "\n", + "comment = \"\"\n", + "\n", + "# Summary tab\n", + "htmlcode = \"\"\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Basic information about loaded coin\") + basic_info.to_html()]\n", + ")\n", + "if not links.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"Links\") + links.to_html(escape=False)])\n", + "\n", + "if not news.empty:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, \"Published news\") + news.to_html(escape=False)]\n", + " )\n", + "\n", + "htmlcode += widgets.row([widgets.h(3, \"Historical data\")])\n", + "for data in historical_data:\n", + " htmlcode += widgets.row([data])\n", + "\n", + "htmlcode += widgets.row([widgets.h(3, \"1-year historical data candlestick chart\")])\n", + "htmlcode += widgets.row([candle_one_year])\n", + "htmlcode += widgets.row([widgets.h(3, \"Sentiment analysis\")])\n", + "htmlcode += widgets.row([headlines])\n", + "# TODO: print rich table\n", + "# htmlcode += widgets.row([widgets.h(3, \"Quick performance\")])\n", + "# htmlcode += widgets.row([quick_performance])\n", + "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", + "\n", + "# # Due diligence tab\n", + "htmlcode = \"\"\n", + "if not trading_pair_info.empty:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, f\"Trading pair info {ticker}/USDT\") + trading_pair_info.to_html()]\n", + " )\n", + "if not mcapdom_df.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"Market cap dominance\")])\n", + " htmlcode += widgets.row([mcapdom])\n", + "\n", + "if not roadmap_model.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"Roadmap\") + roadmap_model.to_html()])\n", + " htmlcode += widgets.row([roadmap_view])\n", + "\n", + "if not tokenomics_model.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"Tokenomics\") + tokenomics_model.to_html()])\n", + " htmlcode += widgets.row([tokenomics_view])\n", + "\n", + "if fundraise:\n", + " htmlcode += widgets.row([widgets.h(3, \"Fundraising Details\")])\n", + " htmlcode += widgets.row([widgets.p(fundraise_info)])\n", + " htmlcode += widgets.row([fundraise_df.to_html()])\n", + "\n", + "if not ath.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"All time high\")])\n", + " htmlcode += widgets.row([ath.to_html()])\n", + "\n", + "if not atl.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"All time low\")])\n", + " htmlcode += widgets.row([atl.to_html()])\n", + "\n", + "if not market.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"All markets\")])\n", + " htmlcode += widgets.row([market.sample(n=20).sort_index().to_html(escape=False)])\n", + "\n", + "if not ex.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"Exchanges where loaded coin is listed\")])\n", + " htmlcode += widgets.row([ex.sample(n=20).sort_index().to_html()])\n", + "\n", + "if not trades.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"Last trades\")])\n", + " htmlcode += widgets.row([trades.tail(20).to_html()])\n", + "\n", + "if order_book_raw:\n", + " htmlcode += widgets.row([widgets.h(3, \"Order book\")])\n", + " htmlcode += widgets.row([order_book])\n", + "\n", + "if not ps.empty:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, \"Price and supply related metrics for loaded coin\")]\n", + " )\n", + " htmlcode += widgets.row([ps.to_html()])\n", + "\n", + "if not events.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"Events\")])\n", + " htmlcode += widgets.row([events.to_html(escape=False)])\n", + "\n", + "# TODO: print rich table\n", + "# htmlcode += widgets.row([widgets.h(3, \"Tweets for loaded coin\")])\n", + "# htmlcode += widgets.row([tweets])\n", + "# htmlcode += widgets.row([widgets.h(3, \"Social media\")])\n", + "# htmlcode += widgets.row([social.to_html()])\n", + "\n", + "if not gh_data.empty:\n", + " htmlcode += widgets.row([widgets.h(3, \"Github activity over time\")])\n", + " htmlcode += widgets.row([gh])\n", + "else:\n", + " htmlcode += widgets.row([widgets.h(3, \"Github activity over time\")])\n", + " htmlcode += widgets.row([widgets.p(\"No data available.\")])\n", + "\n", + "body += widgets.add_tab(\"Due Diligence\", htmlcode)\n", + "\n", + "# Technical Analysis tab\n", + "htmlcode = \"\"\n", + "htmlcode = widgets.row([widgets.h(3, \"Simple moving average\")])\n", + "htmlcode += widgets.row([sma])\n", + "htmlcode += widgets.row([widgets.h(3, \"Exponential moving average\")])\n", + "htmlcode += widgets.row([ema])\n", + "htmlcode += widgets.row([widgets.h(3, \"Zero lag exponential moving average\")])\n", + "htmlcode += widgets.row([zlma])\n", + "htmlcode += widgets.row([widgets.h(3, \"Commodity channel index\")])\n", + "htmlcode += widgets.row([cci])\n", + "htmlcode += widgets.row([widgets.h(3, \"Moving average convergence/divergence\")])\n", + "htmlcode += widgets.row([macd])\n", + "htmlcode += widgets.row([widgets.h(3, \"Fisher transform\")])\n", + "htmlcode += widgets.row([fisher])\n", + "htmlcode += widgets.row([widgets.h(3, \"Aroon indicator\")])\n", + "htmlcode += widgets.row([aroon])\n", + "htmlcode += widgets.row([widgets.h(3, \"Bollinger bands\")])\n", + "htmlcode += widgets.row([bbands])\n", + "htmlcode += widgets.row([widgets.h(3, \"Fibonacci retracement\")])\n", + "htmlcode += widgets.row([fib])\n", + "body += widgets.add_tab(\"Technical Analysis\", htmlcode)\n", + "\n", + "# Quantitative Analysis tab\n", + "htmlcode = \"\"\n", + "htmlcode = widgets.row([widgets.h(3, \"Summary\") + summary.to_html()])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Normality statistics and tests\") + normality.to_html()]\n", + ")\n", + "htmlcode += widgets.row([widgets.h(3, \"Box and whisker plot\")])\n", + "htmlcode += widgets.row([bw])\n", + "htmlcode += widgets.row([widgets.h(3, \"Rolling mean and std deviation of prices\")])\n", + "htmlcode += widgets.row([rolling])\n", + "htmlcode += widgets.row([widgets.h(3, \"Rolling kurtosis of distribution of prices\")])\n", + "htmlcode += widgets.row([kurtosis])\n", + "body += widgets.add_tab(\"Quantitative Analysis\", htmlcode)\n", + "\n", + "body += widgets.tab_clickable_and_save_evt()\n", + "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", + "\n", + "# # to save the results\n", + "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", + " fh.write(report)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "venv", + "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.9.6" + }, + "vscode": { + "interpreter": { + "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/openbb_terminal/reports/templates/economy.ipynb b/openbb_terminal/reports/templates/economy.ipynb index 90b1b53cfd5..f0068f8dfda 100644 --- a/openbb_terminal/reports/templates/economy.ipynb +++ b/openbb_terminal/reports/templates/economy.ipynb @@ -1,739 +1,750 @@ { - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "id": "70ba2c8a", - "metadata": {}, - "source": [ - "## Notebook setup\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "driven-billion", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import io\n", - "import warnings\n", - "import datetime\n", - "import numpy as np\n", - "import pandas as pd\n", - "import base64\n", - "import pytz\n", - "\n", - "from IPython.display import HTML\n", - "\n", - "import openbb_terminal.config_terminal as cfg\n", - "from openbb_terminal.reports import widget_helpers as widgets\n", - "from openbb_terminal.sdk import openbb\n", - "from openbb_terminal.helper_funcs import get_user_timezone\n", - "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", - "from openbb_terminal import OpenBBFigure, theme\n", - "from openbb_terminal.helper_classes import TerminalStyle\n", - "\n", - "\n", - "warnings.filterwarnings(\"ignore\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f9feebc8", - "metadata": {}, - "outputs": [], - "source": [ - "from openbb_terminal.core.session.current_user import get_current_user\n", - "\n", - "user = get_current_user()\n", - "\n", - "cfg.theme = TerminalStyle(\n", - " user.preferences.MPL_STYLE,\n", - " user.preferences.PMF_STYLE,\n", - " user.preferences.RICH_STYLE,\n", - ")\n", - "theme.apply_style(\"light\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e6e39973", - "metadata": {}, - "outputs": [], - "source": [ - "stylesheet = widgets.html_report_stylesheet()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "daef64ec", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "# Parameters that will be replaced when calling this notebook\n", - "# Do not leave parameters blank as notebook will not run otherwise\n", - "report_name = \"economy_report\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", - "metadata": {}, - "outputs": [], - "source": [ - "author = \"OpenBB\"\n", - "report_title = f\"Economy report\"\n", - "user_time_zone = pytz.timezone(get_user_timezone())\n", - "report_date = pd.Timestamp.now(tz=user_time_zone).strftime(\"%d %B, %Y\")\n", - "report_time = pd.Timestamp.now(tz=user_time_zone).strftime(\"%H:%M\")\n", - "report_timezone = pd.Timestamp.now(tz=user_time_zone).tzinfo\n", - "report_title, report_date, report_time, report_timezone" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "9363f19a", - "metadata": {}, - "source": [ - "## Data\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "0b9ec3f9", - "metadata": {}, - "source": [ - "Summary\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e3b15d6f-dc9e-4f97-aa07-37d949a4e4bb", - "metadata": {}, - "outputs": [], - "source": [ - "overview = openbb.economy.overview()\n", - "overview.set_index(list(overview.columns[0]), inplace=True)\n", - "overview = OpenBBFigure.to_table(overview, print_index=True, width=600)\n", - "\n", - "futures = openbb.economy.futures()\n", - "futures.set_index(list(futures.columns[0]), inplace=True)\n", - "futures[\"%Chg\"] = futures[\"%Chg\"].apply(lambda x: float(f\"{x:.2f}\"))\n", - "futures_fig = OpenBBFigure.to_table(futures, print_index=True)\n", - "\n", - "news = openbb.news(\"economy\")\n", - "news.columns = news.columns.str.title()\n", - "news[\"Title\"] = news.apply(lambda x: f'{x[\"Title\"]}', axis=1)\n", - "news = news[[\"Title\", \"Published\"]]\n", - "news[\"Published\"] = pd.to_datetime(news[\"Published\"]).dt.strftime(\"%Y-%m-%d %H:%M\")\n", - "news.set_index(\"Published\", inplace=True)\n", - "\n", - "news = OpenBBFigure.to_table(news, print_index=True, columnwidth=[1.3, 7], width=1100)\n", - "news.update_layout(clickmode=\"event+select\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "64729474", - "metadata": {}, - "outputs": [], - "source": [ - "rtps_data = openbb.economy.rtps()\n", - "subplots = OpenBBFigure.create_subplots(1, 2, horizontal_spacing=0.15)\n", - "openbb.economy.rtps_chart(external_axes=True).to_subplot(subplots, 1, 1)\n", - "\n", - "chg = futures[\"%Chg\"]\n", - "colors = [theme.up_color if x > 0 else theme.down_color for x in list(chg.values)]\n", - "subplots.add_bar(\n", - " y=chg.index,\n", - " x=chg.values,\n", - " orientation=\"h\",\n", - " marker_color=colors,\n", - " showlegend=False,\n", - " row=1,\n", - " col=2,\n", - ")\n", - "subplots.update_xaxes(title_text=\"Performance (%)\", row=1, col=1)\n", - "subplots.update_xaxes(title_text=\"Change %\", row=1, col=2)\n", - "subplots.update_layout(margin=dict(l=0, r=0, t=0, b=0), yaxis=dict(side=\"left\"))\n", - "chart_0 = subplots.to_html()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "7315ac99", - "metadata": {}, - "source": [ - "Events\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a02c6166", - "metadata": {}, - "outputs": [], - "source": [ - "events_1 = openbb.economy.events(\n", - " countries=\"United States\",\n", - " start_date=datetime.datetime.now().strftime(\"%Y-%m-%d\"),\n", - ")\n", - "if not events_1.empty:\n", - " events_1 = OpenBBFigure.to_table(\n", - " events_1.set_index(\"Date\"), print_index=True, height=200\n", - " )\n", - "\n", - "events_2 = openbb.economy.events(\n", - " countries=[\n", - " \"Germany\",\n", - " \"Spain\",\n", - " \"Italy\",\n", - " \"United Kingdom\",\n", - " \"France\",\n", - " \"Portugal\",\n", - " \"Greece\",\n", - " ],\n", - " start_date=datetime.datetime.now().strftime(\"%Y-%m-%d\"),\n", - ")\n", - "if not events_2.empty:\n", - " events_2 = OpenBBFigure.to_table(events_2.set_index(\"Date\"), print_index=True)\n", - "\n", - "events_3 = openbb.economy.events(\n", - " countries=\"China\",\n", - " start_date=datetime.datetime.now().strftime(\"%Y-%m-%d\"),\n", - ")\n", - "if not events_3.empty:\n", - " events_3 = OpenBBFigure.to_table(events_3.set_index(\"Date\"), print_index=True)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "f1863bd0", - "metadata": {}, - "source": [ - "Yields\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8e332ca6", - "metadata": {}, - "outputs": [], - "source": [ - "ycrv = openbb.fixedincome.ycrv(return_date=True)\n", - "\n", - "if (isinstance(ycrv, pd.DataFrame) and not ycrv.empty) or (\n", - " not isinstance(ycrv, pd.DataFrame) and ycrv\n", - "):\n", - " ycrv_data_1, _ = ycrv\n", - " ycrv_country_1 = \"United states\"\n", - "\n", - " ycrv_chart_1 = openbb.fixedincome.ycrv_chart(external_axes=True)\n", - "\n", - " if ycrv_chart_1:\n", - " ycrv_chart_1 = ycrv_chart_1.to_html()\n", - "\n", - " if not ycrv_data_1.empty:\n", - " ycrv_data_1.drop([\"Maturity\"], axis=1, inplace=True)\n", - " ycrv_data_1.index = [\n", - " \"1M\",\n", - " \"3M\",\n", - " \"6M\",\n", - " \"1Y\",\n", - " \"2Y\",\n", - " \"3Y\",\n", - " \"5Y\",\n", - " \"7Y\",\n", - " \"10Y\",\n", - " \"20Y\",\n", - " \"30Y\",\n", - " ]\n", - "else:\n", - " ycrv = None" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "31fb0f86", - "metadata": {}, - "outputs": [], - "source": [ - "openbb.economy.treasury_maturities()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c4f987af", - "metadata": {}, - "outputs": [], - "source": [ - "subplots = OpenBBFigure.create_subplots(\n", - " 2,\n", - " 2,\n", - " vertical_spacing=0.15,\n", - " subplot_titles=(\"UST 2y-10y\", \"UST 10y-30y\", \"Nominal vs TIPS\"),\n", - " specs=[[{}, {}], [{\"colspan\": 2}, None]],\n", - ")\n", - "openbb.economy.treasury_chart(\n", - " instruments=[\"nominal\"],\n", - " maturities=[\"2y\", \"10y\"],\n", - " frequency=\"daily\",\n", - " start_date=\"2020-01-01\",\n", - " external_axes=True,\n", - ").to_subplot(subplots, 1, 1)\n", - "\n", - "openbb.economy.treasury_chart(\n", - " instruments=[\"nominal\"],\n", - " maturities=[\"10y\", \"30y\"],\n", - " frequency=\"daily\",\n", - " start_date=\"2020-01-01\",\n", - " external_axes=True,\n", - ").to_subplot(subplots, 1, 2)\n", - "\n", - "openbb.economy.treasury_chart(\n", - " instruments=[\"nominal\", \"inflation\"],\n", - " maturities=[\"10y\"],\n", - " frequency=\"daily\",\n", - " start_date=\"2020-01-01\",\n", - " external_axes=True,\n", - ").to_subplot(subplots, 2, 1)\n", - "\n", - "ust = subplots.to_html()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "7a3c421f", - "metadata": {}, - "source": [ - "Equity Market\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "12c98e06", - "metadata": {}, - "outputs": [], - "source": [ - "valuation = OpenBBFigure.to_table(openbb.economy.valuation(), print_index=False)\n", - "performance = OpenBBFigure.to_table(openbb.economy.performance(), print_index=False)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "42f5570d", - "metadata": {}, - "outputs": [], - "source": [ - "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", - "data = openbb.economy.index(\n", - " indices=[\"sp500\", \"dow_djus\", \"nasdaq100\", \"russell3000\", \"cboe_vix\"],\n", - " start_date=\"2000-03-09\",\n", - ")\n", - "\n", - "data = data.pct_change().dropna()\n", - "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", - "for col in data.columns:\n", - " fig.add_scatter(\n", - " x=data.index,\n", - " y=data[col] * 100,\n", - " name=col,\n", - " )\n", - "\n", - "eqty_0 = fig.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "286a82d7", - "metadata": {}, - "outputs": [], - "source": [ - "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", - "data = openbb.economy.index(\n", - " indices=[\"ftse100\", \"de_dax40\", \"fr_cac40\", \"it_mib40\", \"es_ibex35\"],\n", - " start_date=\"2000-01-01\",\n", - ")\n", - "\n", - "data = data.pct_change().dropna()\n", - "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", - "for col in data.columns:\n", - " fig.add_scatter(\n", - " x=data.index,\n", - " y=data[col] * 100,\n", - " name=col,\n", - " )\n", - "\n", - "eqty_1 = fig.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e825e8ed", - "metadata": {}, - "outputs": [], - "source": [ - "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", - "data = openbb.economy.index(\n", - " indices=[\"jp_n225\", \"cn_csi300\", \"hk_china\", \"au_asx50\"], start_date=\"2014-01-01\"\n", - ")\n", - "\n", - "data = data.pct_change().dropna()\n", - "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", - "for col in data.columns:\n", - " fig.add_scatter(\n", - " x=data.index,\n", - " y=data[col] * 100,\n", - " name=col,\n", - " )\n", - "\n", - "eqty_2 = fig.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8eb1327b", - "metadata": {}, - "outputs": [], - "source": [ - "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", - "data = openbb.economy.index(\n", - " indices=[\"in_nse50\", \"br_bvsp\", \"za_jo\", \"mx_ipc\", \"ru_moex\"],\n", - " start_date=\"2013-01-01\",\n", - ")\n", - "\n", - "data = data.pct_change().dropna()\n", - "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", - "for col in data.columns:\n", - " fig.add_scatter(\n", - " x=data.index,\n", - " y=data[col] * 100,\n", - " name=col,\n", - " )\n", - "\n", - "eqty_3 = fig.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "02630bd6", - "metadata": {}, - "outputs": [], - "source": [ - "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", - "data = openbb.economy.index(indices=[\"arca_xoi\", \"arca_pse\"], start_date=\"2000-01-01\")\n", - "\n", - "data = data.pct_change().dropna()\n", - "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", - "for col in data.columns:\n", - " fig.add_scatter(\n", - " x=data.index,\n", - " y=data[col] * 100,\n", - " name=col,\n", - " )\n", - "\n", - "eqty_4 = fig.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5a4c8963", - "metadata": {}, - "outputs": [], - "source": [ - "bigmac_res = openbb.economy.bigmac()\n", - "\n", - "if (isinstance(bigmac_res, pd.DataFrame) and not bigmac_res.empty) or (\n", - " not isinstance(bigmac_res, pd.DataFrame) and bigmac_res\n", - "):\n", - " bigmac = openbb.economy.bigmac_chart(\n", - " country_codes=[\n", - " \"USA\",\n", - " \"CAN\",\n", - " \"ARG\",\n", - " \"PRT\",\n", - " \"NLD\",\n", - " \"FRA\",\n", - " \"UAE\",\n", - " \"LKA\",\n", - " \"VNM\",\n", - " \"RUS\",\n", - " \"SWE\",\n", - " \"GBR\",\n", - " ],\n", - " external_axes=True,\n", - " )\n", - " if bigmac:\n", - " bigmac.set_title(\"\")\n", - " bigmac = bigmac.to_html()\n", - "\n", - "else:\n", - " bigmac_res = pd.DataFrame()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1947a06c", - "metadata": {}, - "outputs": [], - "source": [ - "subplots = OpenBBFigure.create_subplots(1, 1, specs=[[{\"secondary_y\": True}]])\n", - "\n", - "openbb.economy.macro_chart(\n", - " parameters=[\"CONF\", \"IP\"], start_date=\"2010-01-01\", external_axes=True\n", - ").to_subplot(subplots, 1, 1, secondary_y=False)\n", - "subplots.update_yaxes(title_text=\"Confidence and IP\", secondary_y=False)\n", - "\n", - "\n", - "df, df_dict, _ = openbb.economy.macro(parameters=[\"CPI\"], start_date=\"2010-01-01\")\n", - "cpi_chg = df.pct_change(1) * 100\n", - "subplots.add_scatter(\n", - " x=cpi_chg.index,\n", - " y=cpi_chg.T.values[0],\n", - " name=\"CPI (% change)\",\n", - " mode=\"lines\",\n", - " line=dict(color=\"red\", dash=\"dash\"),\n", - " secondary_y=True,\n", - " yaxis=\"y2\",\n", - ")\n", - "subplots.update_yaxes(\n", - " title_text=\"CPI (% change)\",\n", - " secondary_y=True,\n", - " range=[-2, 2],\n", - " side=\"left\",\n", - " overlaying=\"y\",\n", - ")\n", - "subplots.horizontal_legend()\n", - "\n", - "macro_0 = subplots.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "971e4c51", - "metadata": {}, - "outputs": [], - "source": [ - "fred = openbb.economy.fred(series_ids=[\"T10Y3M\"], start_date=\"1980-01-01\")\n", - "\n", - "if (isinstance(fred, pd.DataFrame) and not fred.empty) or (\n", - " not isinstance(fred, pd.DataFrame) and fred\n", - "):\n", - " df, df_dict = fred\n", - "\n", - " fig = OpenBBFigure.create_subplots(1, 1, specs=[[{\"secondary_y\": True}]])\n", - " fig.add_scatter(\n", - " x=df.index,\n", - " y=df[\"T10Y3M\"],\n", - " name=df_dict[\"T10Y3M\"][\"title\"],\n", - " line=dict(color=\"red\", dash=\"dash\"),\n", - " secondary_y=False,\n", - " )\n", - " openbb.economy.fred_chart(\n", - " series_ids=[\"A191RP1A027NBEA\"],\n", - " start_date=\"1980-01-01\",\n", - " external_axes=True,\n", - " ).to_subplot(fig, 1, 1, secondary_y=True)\n", - " fig.update_yaxes(secondary_y=True, side=\"left\", overlaying=\"y\")\n", - " fig.set_title(\"\")\n", - " fig.horizontal_legend()\n", - "\n", - " fred_0 = fig.to_html()\n", - "else:\n", - " fred = None" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", - "metadata": {}, - "source": [ - "## Render the report template to a file\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", - "metadata": {}, - "outputs": [], - "source": [ - "body = f\"\"\"\n", - "\n", - "\n", - "\"\"\"\n", - "\n", - "\n", - "img = (\n", - " str(REPOSITORY_DIRECTORY)\n", - " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", - ")\n", - "floppy_disk_img = (\n", - " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", - ")\n", - "body += widgets.header(\n", - " img,\n", - " floppy_disk_img,\n", - " author,\n", - " report_date,\n", - " report_time,\n", - " report_timezone,\n", - " f\"ECONOMY REPORT: Leverage multiple sources to create custom reports.\",\n", - ")\n", - "\n", - "body += widgets.tablinks(\n", - " [\n", - " \"SUMMARY\",\n", - " \"Events\",\n", - " \"Yields\",\n", - " \"Equity Market\",\n", - " \"Macro Data\",\n", - " ]\n", - ")\n", - "\n", - "# Summary\n", - "htmlcode = widgets.row(\n", - " [widgets.h(3, \"Global markets (source: WSJ)\") + overview.to_html()]\n", - ")\n", - "\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Commodities (source: WSJ)\") + futures_fig.to_html()]\n", - " + [\n", - " widgets.h(3, \"Real-time sector performance (source: Alphavantage)\")\n", - " + rtps_data.to_html().replace(\"table\", 'table style=\"display:inline\"')\n", - " ]\n", - ")\n", - "htmlcode += widgets.row([chart_0])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Top news on 'economy' keyword (source: Newsapi)\") + news.to_html()]\n", - ")\n", - "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", - "\n", - "# Events\n", - "htmlcode = widgets.row([widgets.h(3, \"Economic calendars (source: investing.com)\")])\n", - "htmlcode += widgets.row([widgets.h(3, \"United States\") + events_1.to_html()])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Select European Countries\") + events_2.to_html()]\n", - ")\n", - "htmlcode += widgets.row([widgets.h(3, \"China\") + events_3.to_html()])\n", - "body += widgets.add_tab(\"Events\", htmlcode)\n", - "\n", - "# Yields\n", - "htmlcode = widgets.row([widgets.h(3, \"US treasuries (source: EconDB)\") + ust])\n", - "\n", - "if ycrv:\n", - " htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, f\"{ycrv_country_1} yield curve (source: FRED)\")\n", - " + (ycrv_chart_1 or \"\")\n", - " ]\n", - " )\n", - " htmlcode += widgets.row([widgets.h(3, \"\") + ycrv_data_1.to_html()])\n", - "\n", - "body += widgets.add_tab(\"Yields\", htmlcode)\n", - "\n", - "# Equity market\n", - "htmlcode = widgets.row(\n", - " [widgets.h(3, \"Valuation (source: Finviz)\") + valuation.to_html()]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Performance (source: Finviz)\") + valuation.to_html()]\n", - ")\n", - "htmlcode += widgets.row([widgets.h(3, \"US markets (source: YahooFinance)\") + eqty_0])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"European markets (source: YahooFinance)\") + eqty_1]\n", - ")\n", - "htmlcode += widgets.row([widgets.h(3, \"APAC markets (source: YahooFinance)\") + eqty_2])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Emerging markets (source: YahooFinance)\") + eqty_3]\n", - ")\n", - "htmlcode += widgets.row([widgets.h(3, \"ARCA (source: YahooFinance)\") + eqty_4])\n", - "body += widgets.add_tab(\"Equity Market\", htmlcode)\n", - "\n", - "# Macro\n", - "htmlcode = \"\"\n", - "if not bigmac_res.empty:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, \"Bigmac index (source: Nasdaq)\") + (bigmac or \"\")]\n", - " )\n", - "htmlcode += widgets.row([widgets.h(3, \"Leading indicators (source: EconDB)\") + macro_0])\n", - "if fred:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, \"Recession indicator (source: FRED)\") + fred_0]\n", - " )\n", - "body += widgets.add_tab(\"Macro Data\", htmlcode)\n", - "\n", - "body += widgets.tab_clickable_and_save_evt()\n", - "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", - "\n", - "# to save the results\n", - "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", - " fh.write(report)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "venv", - "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.10.8" - }, - "vscode": { - "interpreter": { - "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "70ba2c8a", + "metadata": {}, + "source": [ + "## Notebook setup\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "driven-billion", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import io\n", + "import warnings\n", + "import datetime\n", + "import numpy as np\n", + "import pandas as pd\n", + "import base64\n", + "import pytz\n", + "\n", + "from IPython.display import HTML\n", + "\n", + "import openbb_terminal.config_terminal as cfg\n", + "from openbb_terminal.helper_funcs import get_user_timezone\n", + "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", + "from openbb_terminal import OpenBBFigure, theme\n", + "from openbb_terminal.helper_classes import TerminalStyle\n", + "\n", + "\n", + "warnings.filterwarnings(\"ignore\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4494cd3e", + "metadata": {}, + "outputs": [], + "source": [ + "# Suppressing sdk logs\n", + "cfg.change_logging_suppress(new_value=True)\n", + "\n", + "# Import the OpenBB SDK\n", + "from openbb_terminal.sdk import openbb, widgets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f9feebc8", + "metadata": {}, + "outputs": [], + "source": [ + "from openbb_terminal.core.session.current_user import get_current_user\n", + "\n", + "user = get_current_user()\n", + "\n", + "cfg.theme = TerminalStyle(\n", + " user.preferences.MPL_STYLE,\n", + " user.preferences.PMF_STYLE,\n", + " user.preferences.RICH_STYLE,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6e39973", + "metadata": {}, + "outputs": [], + "source": [ + "stylesheet = widgets.html_report_stylesheet()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "daef64ec", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "# Parameters that will be replaced when calling this notebook\n", + "# Do not leave parameters blank as notebook will not run otherwise\n", + "report_name = \"economy_report\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", + "metadata": {}, + "outputs": [], + "source": [ + "author = \"OpenBB\"\n", + "report_title = f\"Economy report\"\n", + "user_time_zone = pytz.timezone(get_user_timezone())\n", + "report_date = pd.Timestamp.now(tz=user_time_zone).strftime(\"%d %B, %Y\")\n", + "report_time = pd.Timestamp.now(tz=user_time_zone).strftime(\"%H:%M\")\n", + "report_timezone = pd.Timestamp.now(tz=user_time_zone).tzinfo\n", + "report_title, report_date, report_time, report_timezone" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "9363f19a", + "metadata": {}, + "source": [ + "## Data\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "0b9ec3f9", + "metadata": {}, + "source": [ + "Summary\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3b15d6f-dc9e-4f97-aa07-37d949a4e4bb", + "metadata": {}, + "outputs": [], + "source": [ + "overview = openbb.economy.overview()\n", + "overview.set_index(list(overview.columns[0]), inplace=True)\n", + "overview = OpenBBFigure.to_table(overview, print_index=True, width=600)\n", + "\n", + "futures = openbb.economy.futures()\n", + "futures.set_index(list(futures.columns[0]), inplace=True)\n", + "futures[\"%Chg\"] = futures[\"%Chg\"].apply(lambda x: float(f\"{x:.2f}\"))\n", + "futures_fig = OpenBBFigure.to_table(futures, print_index=True)\n", + "\n", + "news = openbb.news(\"economy\")\n", + "news.columns = news.columns.str.title()\n", + "news[\"Title\"] = news.apply(lambda x: f'{x[\"Title\"]}', axis=1)\n", + "news = news[[\"Title\", \"Published\"]]\n", + "news[\"Published\"] = pd.to_datetime(news[\"Published\"]).dt.strftime(\"%Y-%m-%d %H:%M\")\n", + "news.set_index(\"Published\", inplace=True)\n", + "\n", + "news = OpenBBFigure.to_table(news, print_index=True, columnwidth=[1.3, 7], width=1100)\n", + "news.update_layout(clickmode=\"event+select\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "64729474", + "metadata": {}, + "outputs": [], + "source": [ + "rtps_data = openbb.economy.rtps()\n", + "subplots = OpenBBFigure.create_subplots(1, 2, horizontal_spacing=0.15)\n", + "openbb.economy.rtps_chart(external_axes=True).to_subplot(subplots, 1, 1)\n", + "\n", + "chg = futures[\"%Chg\"]\n", + "colors = [theme.up_color if x > 0 else theme.down_color for x in list(chg.values)]\n", + "subplots.add_bar(\n", + " y=chg.index,\n", + " x=chg.values,\n", + " orientation=\"h\",\n", + " marker_color=colors,\n", + " showlegend=False,\n", + " row=1,\n", + " col=2,\n", + ")\n", + "subplots.update_xaxes(title_text=\"Performance (%)\", row=1, col=1)\n", + "subplots.update_xaxes(title_text=\"Change %\", row=1, col=2)\n", + "subplots.update_layout(margin=dict(l=0, r=0, t=0, b=0), yaxis=dict(side=\"left\"))\n", + "chart_0 = subplots.to_html()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "7315ac99", + "metadata": {}, + "source": [ + "Events\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a02c6166", + "metadata": {}, + "outputs": [], + "source": [ + "events_1 = openbb.economy.events(\n", + " countries=\"United States\",\n", + " start_date=datetime.datetime.now().strftime(\"%Y-%m-%d\"),\n", + ")\n", + "if not events_1.empty:\n", + " events_1 = OpenBBFigure.to_table(\n", + " events_1.set_index(\"Date\"), print_index=True, height=200\n", + " )\n", + "\n", + "events_2 = openbb.economy.events(\n", + " countries=[\n", + " \"Germany\",\n", + " \"Spain\",\n", + " \"Italy\",\n", + " \"United Kingdom\",\n", + " \"France\",\n", + " \"Portugal\",\n", + " \"Greece\",\n", + " ],\n", + " start_date=datetime.datetime.now().strftime(\"%Y-%m-%d\"),\n", + ")\n", + "if not events_2.empty:\n", + " events_2 = OpenBBFigure.to_table(events_2.set_index(\"Date\"), print_index=True)\n", + "\n", + "events_3 = openbb.economy.events(\n", + " countries=\"China\",\n", + " start_date=datetime.datetime.now().strftime(\"%Y-%m-%d\"),\n", + ")\n", + "if not events_3.empty:\n", + " events_3 = OpenBBFigure.to_table(events_3.set_index(\"Date\"), print_index=True)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "f1863bd0", + "metadata": {}, + "source": [ + "Yields\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8e332ca6", + "metadata": {}, + "outputs": [], + "source": [ + "ycrv = openbb.fixedincome.ycrv(return_date=True)\n", + "\n", + "if (isinstance(ycrv, pd.DataFrame) and not ycrv.empty) or (\n", + " not isinstance(ycrv, pd.DataFrame) and ycrv\n", + "):\n", + " ycrv_data_1, _ = ycrv\n", + " ycrv_country_1 = \"United states\"\n", + "\n", + " ycrv_chart_1 = openbb.fixedincome.ycrv_chart(external_axes=True)\n", + "\n", + " if ycrv_chart_1:\n", + " ycrv_chart_1 = ycrv_chart_1.to_html()\n", + "\n", + " if not ycrv_data_1.empty:\n", + " ycrv_data_1.drop([\"Maturity\"], axis=1, inplace=True)\n", + " ycrv_data_1.index = [\n", + " \"1M\",\n", + " \"3M\",\n", + " \"6M\",\n", + " \"1Y\",\n", + " \"2Y\",\n", + " \"3Y\",\n", + " \"5Y\",\n", + " \"7Y\",\n", + " \"10Y\",\n", + " \"20Y\",\n", + " \"30Y\",\n", + " ]\n", + "else:\n", + " ycrv = None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31fb0f86", + "metadata": {}, + "outputs": [], + "source": [ + "openbb.economy.treasury_maturities()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4f987af", + "metadata": {}, + "outputs": [], + "source": [ + "subplots = OpenBBFigure.create_subplots(\n", + " 2,\n", + " 2,\n", + " vertical_spacing=0.15,\n", + " subplot_titles=(\"UST 2y-10y\", \"UST 10y-30y\", \"Nominal vs TIPS\"),\n", + " specs=[[{}, {}], [{\"colspan\": 2}, None]],\n", + ")\n", + "openbb.economy.treasury_chart(\n", + " instruments=[\"nominal\"],\n", + " maturities=[\"2y\", \"10y\"],\n", + " frequency=\"daily\",\n", + " start_date=\"2020-01-01\",\n", + " external_axes=True,\n", + ").to_subplot(subplots, 1, 1)\n", + "\n", + "openbb.economy.treasury_chart(\n", + " instruments=[\"nominal\"],\n", + " maturities=[\"10y\", \"30y\"],\n", + " frequency=\"daily\",\n", + " start_date=\"2020-01-01\",\n", + " external_axes=True,\n", + ").to_subplot(subplots, 1, 2)\n", + "\n", + "openbb.economy.treasury_chart(\n", + " instruments=[\"nominal\", \"inflation\"],\n", + " maturities=[\"10y\"],\n", + " frequency=\"daily\",\n", + " start_date=\"2020-01-01\",\n", + " external_axes=True,\n", + ").to_subplot(subplots, 2, 1)\n", + "\n", + "ust = subplots.to_html()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "7a3c421f", + "metadata": {}, + "source": [ + "Equity Market\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12c98e06", + "metadata": {}, + "outputs": [], + "source": [ + "valuation = OpenBBFigure.to_table(openbb.economy.valuation(), print_index=False)\n", + "performance = OpenBBFigure.to_table(openbb.economy.performance(), print_index=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42f5570d", + "metadata": {}, + "outputs": [], + "source": [ + "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", + "data = openbb.economy.index(\n", + " indices=[\"sp500\", \"dow_djus\", \"nasdaq100\", \"russell3000\", \"cboe_vix\"],\n", + " start_date=\"2000-03-09\",\n", + ")\n", + "\n", + "data = data.pct_change().dropna()\n", + "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", + "for col in data.columns:\n", + " fig.add_scatter(\n", + " x=data.index,\n", + " y=data[col] * 100,\n", + " name=col,\n", + " )\n", + "\n", + "eqty_0 = fig.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "286a82d7", + "metadata": {}, + "outputs": [], + "source": [ + "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", + "data = openbb.economy.index(\n", + " indices=[\"ftse100\", \"de_dax40\", \"fr_cac40\", \"it_mib40\", \"es_ibex35\"],\n", + " start_date=\"2000-01-01\",\n", + ")\n", + "\n", + "data = data.pct_change().dropna()\n", + "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", + "for col in data.columns:\n", + " fig.add_scatter(\n", + " x=data.index,\n", + " y=data[col] * 100,\n", + " name=col,\n", + " )\n", + "\n", + "eqty_1 = fig.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e825e8ed", + "metadata": {}, + "outputs": [], + "source": [ + "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", + "data = openbb.economy.index(\n", + " indices=[\"jp_n225\", \"cn_csi300\", \"hk_china\", \"au_asx50\"], start_date=\"2014-01-01\"\n", + ")\n", + "\n", + "data = data.pct_change().dropna()\n", + "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", + "for col in data.columns:\n", + " fig.add_scatter(\n", + " x=data.index,\n", + " y=data[col] * 100,\n", + " name=col,\n", + " )\n", + "\n", + "eqty_2 = fig.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8eb1327b", + "metadata": {}, + "outputs": [], + "source": [ + "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", + "data = openbb.economy.index(\n", + " indices=[\"in_nse50\", \"br_bvsp\", \"za_jo\", \"mx_ipc\", \"ru_moex\"],\n", + " start_date=\"2013-01-01\",\n", + ")\n", + "\n", + "data = data.pct_change().dropna()\n", + "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", + "for col in data.columns:\n", + " fig.add_scatter(\n", + " x=data.index,\n", + " y=data[col] * 100,\n", + " name=col,\n", + " )\n", + "\n", + "eqty_3 = fig.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "02630bd6", + "metadata": {}, + "outputs": [], + "source": [ + "fig = OpenBBFigure(yaxis_title=\"Cumulative returns (%)\")\n", + "data = openbb.economy.index(indices=[\"arca_xoi\", \"arca_pse\"], start_date=\"2000-01-01\")\n", + "\n", + "data = data.pct_change().dropna()\n", + "data = (1 + data.shift(periods=1, fill_value=0)).cumprod() - 1\n", + "for col in data.columns:\n", + " fig.add_scatter(\n", + " x=data.index,\n", + " y=data[col] * 100,\n", + " name=col,\n", + " )\n", + "\n", + "eqty_4 = fig.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a4c8963", + "metadata": {}, + "outputs": [], + "source": [ + "bigmac_res = openbb.economy.bigmac()\n", + "\n", + "if (isinstance(bigmac_res, pd.DataFrame) and not bigmac_res.empty) or (\n", + " not isinstance(bigmac_res, pd.DataFrame) and bigmac_res\n", + "):\n", + " bigmac = openbb.economy.bigmac_chart(\n", + " country_codes=[\n", + " \"USA\",\n", + " \"CAN\",\n", + " \"ARG\",\n", + " \"PRT\",\n", + " \"NLD\",\n", + " \"FRA\",\n", + " \"UAE\",\n", + " \"LKA\",\n", + " \"VNM\",\n", + " \"RUS\",\n", + " \"SWE\",\n", + " \"GBR\",\n", + " ],\n", + " external_axes=True,\n", + " )\n", + " if bigmac:\n", + " bigmac.set_title(\"\")\n", + " bigmac = bigmac.to_html()\n", + "\n", + "else:\n", + " bigmac_res = pd.DataFrame()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1947a06c", + "metadata": {}, + "outputs": [], + "source": [ + "subplots = OpenBBFigure.create_subplots(1, 1, specs=[[{\"secondary_y\": True}]])\n", + "\n", + "openbb.economy.macro_chart(\n", + " parameters=[\"CONF\", \"IP\"], start_date=\"2010-01-01\", external_axes=True\n", + ").to_subplot(subplots, 1, 1, secondary_y=False)\n", + "subplots.update_yaxes(title_text=\"Confidence and IP\", secondary_y=False)\n", + "\n", + "\n", + "df, df_dict, _ = openbb.economy.macro(parameters=[\"CPI\"], start_date=\"2010-01-01\")\n", + "cpi_chg = df.pct_change(1) * 100\n", + "subplots.add_scatter(\n", + " x=cpi_chg.index,\n", + " y=cpi_chg.T.values[0],\n", + " name=\"CPI (% change)\",\n", + " mode=\"lines\",\n", + " line=dict(color=\"red\", dash=\"dash\"),\n", + " secondary_y=True,\n", + " yaxis=\"y2\",\n", + ")\n", + "subplots.update_yaxes(\n", + " title_text=\"CPI (% change)\",\n", + " secondary_y=True,\n", + " range=[-2, 2],\n", + " side=\"left\",\n", + " overlaying=\"y\",\n", + ")\n", + "subplots.horizontal_legend()\n", + "\n", + "macro_0 = subplots.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "971e4c51", + "metadata": {}, + "outputs": [], + "source": [ + "fred = openbb.economy.fred(series_ids=[\"T10Y3M\"], start_date=\"1980-01-01\")\n", + "\n", + "if (isinstance(fred, pd.DataFrame) and not fred.empty) or (\n", + " not isinstance(fred, pd.DataFrame) and fred\n", + "):\n", + " df, df_dict = fred\n", + "\n", + " fig = OpenBBFigure.create_subplots(1, 1, specs=[[{\"secondary_y\": True}]])\n", + " fig.add_scatter(\n", + " x=df.index,\n", + " y=df[\"T10Y3M\"],\n", + " name=df_dict[\"T10Y3M\"][\"title\"],\n", + " line=dict(color=\"red\", dash=\"dash\"),\n", + " secondary_y=False,\n", + " )\n", + " openbb.economy.fred_chart(\n", + " series_ids=[\"A191RP1A027NBEA\"],\n", + " start_date=\"1980-01-01\",\n", + " external_axes=True,\n", + " ).to_subplot(fig, 1, 1, secondary_y=True)\n", + " fig.update_yaxes(secondary_y=True, side=\"left\", overlaying=\"y\")\n", + " fig.set_title(\"\")\n", + " fig.horizontal_legend()\n", + "\n", + " fred_0 = fig.to_html()\n", + "else:\n", + " fred = None" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", + "metadata": {}, + "source": [ + "## Render the report template to a file\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", + "metadata": {}, + "outputs": [], + "source": [ + "body = f\"\"\"\n", + "\n", + "\n", + "\"\"\"\n", + "\n", + "\n", + "img = (\n", + " str(REPOSITORY_DIRECTORY)\n", + " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", + ")\n", + "floppy_disk_img = (\n", + " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", + ")\n", + "body += widgets.header(\n", + " img,\n", + " floppy_disk_img,\n", + " author,\n", + " report_date,\n", + " report_time,\n", + " report_timezone,\n", + " f\"ECONOMY REPORT: Leverage multiple sources to create custom reports.\",\n", + ")\n", + "\n", + "body += widgets.tablinks(\n", + " [\n", + " \"SUMMARY\",\n", + " \"Events\",\n", + " \"Yields\",\n", + " \"Equity Market\",\n", + " \"Macro Data\",\n", + " ]\n", + ")\n", + "\n", + "# Summary\n", + "htmlcode = widgets.row(\n", + " [widgets.h(3, \"Global markets (source: WSJ)\") + overview.to_html()]\n", + ")\n", + "\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Commodities (source: WSJ)\") + futures_fig.to_html()]\n", + " + [\n", + " widgets.h(3, \"Real-time sector performance (source: Alphavantage)\")\n", + " + rtps_data.to_html().replace(\"table\", 'table style=\"display:inline\"')\n", + " ]\n", + ")\n", + "htmlcode += widgets.row([chart_0])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Top news on 'economy' keyword (source: Newsapi)\") + news.to_html()]\n", + ")\n", + "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", + "\n", + "# Events\n", + "htmlcode = widgets.row([widgets.h(3, \"Economic calendars (source: investing.com)\")])\n", + "htmlcode += widgets.row([widgets.h(3, \"United States\") + events_1.to_html()])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Select European Countries\") + events_2.to_html()]\n", + ")\n", + "htmlcode += widgets.row([widgets.h(3, \"China\") + events_3.to_html()])\n", + "body += widgets.add_tab(\"Events\", htmlcode)\n", + "\n", + "# Yields\n", + "htmlcode = widgets.row([widgets.h(3, \"US treasuries (source: EconDB)\") + ust])\n", + "\n", + "if ycrv:\n", + " htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, f\"{ycrv_country_1} yield curve (source: FRED)\")\n", + " + (ycrv_chart_1 or \"\")\n", + " ]\n", + " )\n", + " htmlcode += widgets.row([widgets.h(3, \"\") + ycrv_data_1.to_html()])\n", + "\n", + "body += widgets.add_tab(\"Yields\", htmlcode)\n", + "\n", + "# Equity market\n", + "htmlcode = widgets.row(\n", + " [widgets.h(3, \"Valuation (source: Finviz)\") + valuation.to_html()]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Performance (source: Finviz)\") + valuation.to_html()]\n", + ")\n", + "htmlcode += widgets.row([widgets.h(3, \"US markets (source: YahooFinance)\") + eqty_0])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"European markets (source: YahooFinance)\") + eqty_1]\n", + ")\n", + "htmlcode += widgets.row([widgets.h(3, \"APAC markets (source: YahooFinance)\") + eqty_2])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Emerging markets (source: YahooFinance)\") + eqty_3]\n", + ")\n", + "htmlcode += widgets.row([widgets.h(3, \"ARCA (source: YahooFinance)\") + eqty_4])\n", + "body += widgets.add_tab(\"Equity Market\", htmlcode)\n", + "\n", + "# Macro\n", + "htmlcode = \"\"\n", + "if not bigmac_res.empty:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, \"Bigmac index (source: Nasdaq)\") + (bigmac or \"\")]\n", + " )\n", + "htmlcode += widgets.row([widgets.h(3, \"Leading indicators (source: EconDB)\") + macro_0])\n", + "if fred:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, \"Recession indicator (source: FRED)\") + fred_0]\n", + " )\n", + "body += widgets.add_tab(\"Macro Data\", htmlcode)\n", + "\n", + "body += widgets.tab_clickable_and_save_evt()\n", + "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", + "\n", + "# to save the results\n", + "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", + " fh.write(report)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "venv", + "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.9.13" + }, + "vscode": { + "interpreter": { + "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/openbb_terminal/reports/templates/equity.ipynb b/openbb_terminal/reports/templates/equity.ipynb index 2090444ccdd..8fe2d932bcf 100644 --- a/openbb_terminal/reports/templates/equity.ipynb +++ b/openbb_terminal/reports/templates/equity.ipynb @@ -1,1376 +1,1397 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "70ba2c8a", - "metadata": {}, - "source": [ - "## Notebook setup\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "driven-billion", - "metadata": {}, - "outputs": [], - "source": [ - "import warnings\n", - "import datetime\n", - "import numpy as np\n", - "import pandas as pd\n", - "\n", - "from IPython.display import HTML\n", - "\n", - "# import sys\n", - "# sys.path.append('../../')\n", - "\n", - "from openbb_terminal.reports import widget_helpers as widgets\n", - "from openbb_terminal.sdk import openbb\n", - "from openbb_terminal import config_terminal as cfg\n", - "from openbb_terminal.helper_classes import TerminalStyle\n", - "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", - "from openbb_terminal import OpenBBFigure\n", - "from openbb_terminal.core.plots.plotly_ta.ta_class import PlotlyTA\n", - "\n", - "warnings.filterwarnings(\"ignore\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cf31bcc7", - "metadata": {}, - "outputs": [], - "source": [ - "from openbb_terminal.core.session.current_user import get_current_user\n", - "\n", - "user = get_current_user()\n", - "\n", - "cfg.theme = TerminalStyle(\n", - " user.preferences.MPL_STYLE,\n", - " user.preferences.PMF_STYLE,\n", - " user.preferences.RICH_STYLE,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", - "metadata": {}, - "outputs": [], - "source": [ - "stylesheet = widgets.html_report_stylesheet()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "807fda4e", - "metadata": {}, - "source": [ - "## Select symbol\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "intended-sherman", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "# Parameters that will be replaced when calling this notebook\n", - "# Do not leave parameters blank as notebook will not run otherwise\n", - "symbol = \"msft\"\n", - "report_name = f\"Equity report for {symbol}\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a441ddbc-d75b-4a18-84d4-e01b677674d3", - "metadata": {}, - "outputs": [], - "source": [ - "if \".\" in symbol:\n", - " import sys\n", - "\n", - " sys.exit(0)\n", - "symbol = symbol.upper()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", - "metadata": {}, - "outputs": [], - "source": [ - "ticker_data = openbb.stocks.load(\n", - " symbol=symbol, start_date=datetime.datetime.now() - datetime.timedelta(days=18 * 30)\n", - ")\n", - "ticker_data = openbb.stocks.process_candle(data=ticker_data)\n", - "\n", - "author = \"\"\n", - "report_title = f\"Investment Research Report on {symbol.upper()}\"\n", - "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", - "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", - "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", - "report_title, report_date, report_time, report_timezone" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e3b15d6f-dc9e-4f97-aa07-37d949a4e4bb", - "metadata": {}, - "outputs": [], - "source": [ - "info = openbb.stocks.fa.info(symbol=symbol).transpose()\n", - "\n", - "long_summary = \"Long business summary\"\n", - "long_name = \"Long name\"\n", - "\n", - "if long_summary in info and info[long_summary][0] != \"NA\":\n", - " overview = info[long_summary][0]\n", - "elif long_name in info:\n", - " overview = info[long_name][0]\n", - "else:\n", - " overview = \"\"" - ] - }, - { - "cell_type": "markdown", - "id": "f8a0d747", - "metadata": {}, - "source": [ - "## Data\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aca4b6ef", - "metadata": {}, - "outputs": [], - "source": [ - "(\n", - " df_year_estimates,\n", - " df_quarter_earnings,\n", - " df_quarter_revenues,\n", - ") = openbb.stocks.fa.est(symbol=symbol)\n", - "df_quarter_revenues" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c0f0a1ca", - "metadata": {}, - "outputs": [], - "source": [ - "display_year = sorted(df_year_estimates.columns.tolist())[:3]\n", - "df_year_estimates = df_year_estimates[display_year].head(5)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6976c1d5", - "metadata": {}, - "outputs": [], - "source": [ - "tables = openbb.etf.news(info[\"Short name\"][0], 5) if \"Short name\" in info else symbol\n", - "\n", - "for table in tables:\n", - " if not isinstance(table, pd.DataFrame):\n", - " continue\n", - "\n", - " table[0].loc[\"link\"] = (\n", - " table[0].loc[\"link\"].apply(lambda x: f'{x}')\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "38e38d7c", - "metadata": {}, - "outputs": [], - "source": [ - "quote_data = openbb.stocks.quote(symbol)\n", - "quote_data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fde46353", - "metadata": {}, - "outputs": [], - "source": [ - "df_institutional_shareholders = openbb.stocks.fa.shrs(symbol, holder=\"institutional\")\n", - "df_institutional_shareholders.index += 1\n", - "df_institutional_shareholders" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e101e24e", - "metadata": {}, - "outputs": [], - "source": [ - "openbb.stocks.fa.shrs(symbol)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "51dfd9d2", - "metadata": {}, - "outputs": [], - "source": [ - "df_institutional_shareholders = openbb.stocks.fa.shrs(symbol)\n", - "df_institutional_shareholders.index += 1\n", - "df_institutional_shareholders" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3022130e", - "metadata": {}, - "outputs": [], - "source": [ - "df_sec_filings = openbb.stocks.fa.sec(symbol)[[\"Type\", \"Category\", \"Link\"]].head(5)\n", - "df_sec_filings[\"Link\"] = df_sec_filings[\"Link\"].apply(\n", - " lambda x: f'{x}'\n", - ")\n", - "df_sec_filings" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4662b1ac", - "metadata": {}, - "outputs": [], - "source": [ - "df_analyst = openbb.stocks.fa.analyst(symbol=symbol)\n", - "\n", - "if not df_analyst.empty:\n", - " if \"target\" in df_analyst.columns:\n", - " if \"target_to\" in df_analyst.columns:\n", - " df_analyst[\"target\"] = df_analyst[\"target_to\"].combine_first(\n", - " df_analyst[\"target\"]\n", - " )\n", - " else:\n", - " df_analyst[\"target\"] = df_analyst[\"target_to\"]\n", - " df_analyst = df_analyst[[\"category\", \"analyst\", \"rating\", \"target\"]].rename(\n", - " columns={\n", - " \"category\": \"Category\",\n", - " \"analyst\": \"Analyst\",\n", - " \"rating\": \"Rating\",\n", - " \"target\": \"Price Target\",\n", - " }\n", - " )\n", - "df_analyst" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "df8bdb7d", - "metadata": {}, - "outputs": [], - "source": [ - "df_rating = openbb.stocks.fa.rating(symbol)\n", - "df_rating" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d0df953b", - "metadata": {}, - "outputs": [], - "source": [ - "pcr_chart = openbb.stocks.options.pcr_chart(symbol, window=30, external_axes=True)\n", - "\n", - "if pcr_chart:\n", - " pcr_chart = pcr_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bd79195c", - "metadata": {}, - "outputs": [], - "source": [ - "expiry_dates = openbb.stocks.options.expirations(symbol)\n", - "exp = expiry_dates[0]\n", - "option_chain = openbb.stocks.options.chains(symbol, expiration=exp)\n", - "current_price = float(ticker_data[\"Adj Close\"][-1])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ad6d0c24", - "metadata": {}, - "outputs": [], - "source": [ - "vol_chart = openbb.stocks.options.vol(\n", - " option_chain, current_price, symbol, exp, external_axes=True\n", - ")\n", - "\n", - "if vol_chart:\n", - " vol_chart = vol_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "be2d1e3a", - "metadata": {}, - "outputs": [], - "source": [ - "voi_chart = openbb.stocks.options.voi(\n", - " option_chain, current_price, symbol, exp, external_axes=True\n", - ")\n", - "\n", - "if voi_chart:\n", - " voi_chart = voi_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "324e2d4b-b2f6-4da3-bac4-ef785ad4e436", - "metadata": {}, - "outputs": [], - "source": [ - "net_short_position = openbb.stocks.dps.spos_chart(\n", - " symbol=symbol,\n", - " limit=84,\n", - " raw=False,\n", - " export=\"\",\n", - " external_axes=True,\n", - ")\n", - "\n", - "if net_short_position:\n", - " net_short_position = net_short_position.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ac0bfbda-e4b8-4b3b-b8e7-c02639fdb971", - "metadata": {}, - "outputs": [], - "source": [ - "dark_pools = openbb.stocks.dps.dpotc_chart(symbol=symbol, external_axes=True)\n", - "\n", - "if dark_pools:\n", - " dark_pools = dark_pools.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "22a7266f", - "metadata": {}, - "outputs": [], - "source": [ - "gtrades_chart = openbb.stocks.gov.gtrades_chart(\n", - " symbol,\n", - " past_transactions_months=12,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if gtrades_chart:\n", - " gtrades_chart = gtrades_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4c670ba3", - "metadata": {}, - "outputs": [], - "source": [ - "gov_contracts_chart = openbb.stocks.gov.contracts_chart(\n", - " symbol,\n", - " past_transaction_days=365,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if gov_contracts_chart:\n", - " gov_contracts_chart = gov_contracts_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "caa3dae2", - "metadata": {}, - "outputs": [], - "source": [ - "google_mentions_chart = openbb.stocks.ba.mentions_chart(\n", - " symbol,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if google_mentions_chart:\n", - " google_mentions_chart = google_mentions_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b77e60d8", - "metadata": {}, - "outputs": [], - "source": [ - "google_regions_chart = openbb.stocks.ba.regions_chart(\n", - " symbol,\n", - " limit=10,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if google_regions_chart:\n", - " google_regions_chart = google_regions_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "78593369", - "metadata": {}, - "outputs": [], - "source": [ - "similar_companies = openbb.stocks.ca.similar(symbol, source=\"Polygon\")\n", - "similar_companies.append(symbol)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4639665b", - "metadata": {}, - "outputs": [], - "source": [ - "historical_similar = openbb.stocks.ca.hist_chart(\n", - " similar_companies,\n", - " external_axes=True,\n", - " normalize=False,\n", - ")\n", - "\n", - "if historical_similar:\n", - " historical_similar = historical_similar.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "74565e53", - "metadata": {}, - "outputs": [], - "source": [ - "hcorr_similar = openbb.stocks.ca.hcorr_chart(\n", - " similar_companies,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if hcorr_similar:\n", - " hcorr_similar = hcorr_similar.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "936babfd", - "metadata": {}, - "outputs": [], - "source": [ - "vol_similar = openbb.stocks.ca.volume_chart(\n", - " similar_companies,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if vol_similar:\n", - " vol_similar = vol_similar.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "99388d4e", - "metadata": {}, - "outputs": [], - "source": [ - "scorr_similar = openbb.stocks.ca.scorr_chart(\n", - " similar_companies,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if scorr_similar:\n", - " scorr_similar = scorr_similar.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "eaa67343", - "metadata": {}, - "outputs": [], - "source": [ - "income_comparison = openbb.stocks.ca.income(similar_companies)\n", - "income_comparison" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "13ad71cf", - "metadata": {}, - "outputs": [], - "source": [ - "try:\n", - " df_related_queries = openbb.stocks.ba.queries(symbol)\n", - " df_related_queries.index += 1\n", - " df_related_queries.index\n", - "except:\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "58c06129", - "metadata": {}, - "outputs": [], - "source": [ - "try:\n", - " df_rising_queries = openbb.stocks.ba.rise(symbol)\n", - " df_rising_queries.index += 1\n", - " df_rising_queries\n", - "except:\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0a467f1a", - "metadata": {}, - "outputs": [], - "source": [ - "gov_histcont_chart = openbb.stocks.gov.histcont_chart(\n", - " symbol,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if gov_histcont_chart:\n", - " gov_histcont_chart = gov_histcont_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "730cae26", - "metadata": {}, - "outputs": [], - "source": [ - "df_lobbying = openbb.stocks.gov.lobbying(symbol, limit=5)\n", - "df_lobbying" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d8bb53c1-147e-4342-af61-0d0a9cc56e59", - "metadata": {}, - "outputs": [], - "source": [ - "price_vs_short_interest = openbb.stocks.dps.psi_sg_chart(\n", - " symbol=symbol, external_axes=True\n", - ")\n", - "\n", - "if price_vs_short_interest:\n", - " price_vs_short_interest = price_vs_short_interest.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "394668e1-1158-4a2b-8a38-04c72a6abdd6", - "metadata": {}, - "outputs": [], - "source": [ - "price_chart = openbb.stocks.candle(\n", - " symbol=symbol,\n", - " data=ticker_data,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if price_chart:\n", - " price_chart = price_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "900686a3", - "metadata": {}, - "outputs": [], - "source": [ - "price_target_chart = openbb.stocks.fa.pt_chart(\n", - " symbol=symbol,\n", - " start_date=\"2022-01-01\",\n", - " data=ticker_data,\n", - " limit=10,\n", - " raw=False,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if price_target_chart:\n", - " price_target_chart = price_target_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "61d62e1a-199e-481d-b57d-38ab486951be", - "metadata": {}, - "outputs": [], - "source": [ - "df = openbb.stocks.fa.pt(symbol=symbol)\n", - "avg_ratings_last_30_days = 0\n", - "days = 0\n", - "if not df.empty:\n", - " df_ratings = df[datetime.datetime.now() - datetime.timedelta(days=days) :]\n", - " while df_ratings.empty:\n", - " days += 30\n", - " df_ratings = df[datetime.datetime.now() - datetime.timedelta(days=days) :]\n", - "\n", - " if days > 100:\n", - " break\n", - "\n", - " if not df_ratings.empty:\n", - " avg_ratings_last_30_days = round(np.mean(df_ratings[\"Price Target\"].values), 2)\n", - " else:\n", - " avg_ratings = 0\n", - "\n", - "last_price = round(ticker_data[\"Close\"][-1], 2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f3733ff2", - "metadata": {}, - "outputs": [], - "source": [ - "ratings_over_time_chart = openbb.stocks.fa.rot_chart(\n", - " symbol=symbol,\n", - " limit=10,\n", - " raw=False,\n", - " export=\"\",\n", - " external_axes=True,\n", - ")\n", - "\n", - "if ratings_over_time_chart:\n", - " ratings_over_time_chart = ratings_over_time_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "924f8042-e58a-449c-91a3-7923158ff714", - "metadata": {}, - "outputs": [], - "source": [ - "ta_rsi = openbb.ta.rsi_chart(ticker_data[\"Close\"], external_axes=True)\n", - "\n", - "if ta_rsi:\n", - " ta_rsi = ta_rsi.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "953a340e-7ea1-4aa3-ae1d-872683dced41", - "metadata": {}, - "outputs": [], - "source": [ - "df = openbb.ta.rsi(ticker_data[\"Close\"])\n", - "rsi_value = round(df.values[-1][0], 2)\n", - "rsi_value" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dce71711-20b3-4c69-af52-e0f9a69991f8", - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.linear_model import LinearRegression\n", - "\n", - "model = LinearRegression().fit(\n", - " np.array(range(len(ticker_data[\"Close\"][-30:].index))).reshape(-1, 1),\n", - " ticker_data[\"Close\"][-30:].values,\n", - ")\n", - "regression_slope = round(model.coef_[0], 2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6272e34b-9511-4b48-9eea-ea882ce9846a", - "metadata": {}, - "outputs": [], - "source": [ - "df_insider = pd.DataFrame.from_dict(openbb.stocks.ins.lins(symbol=symbol)).head(10)\n", - "if not df_insider.empty:\n", - " df_insider[\"Val ($)\"] = df_insider[\"Value ($)\"].replace({\",\": \"\"}, regex=True)\n", - " df_insider[\"Trade\"] = df_insider.apply(\n", - " lambda row: (-1 * float(row[\"Val ($)\"]))\n", - " if row[\"Transaction\"] == \"Sale\"\n", - " else (float(row[\"Val ($)\"]) if row[\"Transaction\"] == \"Buy\" else 0),\n", - " axis=1,\n", - " )\n", - " last_10_insider_trading = round(sum(df_insider[\"Trade\"]) / 1_000_000, 2)\n", - " df_insider = df_insider.drop(columns=[\"Val ($)\", \"Trade\"])\n", - " df_insider" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "29254666-58c6-4686-87e6-2635ad8387e2", - "metadata": {}, - "outputs": [], - "source": [ - "finbrain_sentiment = openbb.stocks.ba.headlines_chart(symbol=symbol, external_axes=True)\n", - "\n", - "if finbrain_sentiment:\n", - " finbrain_sentiment = finbrain_sentiment.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b8251b47-8ecc-47be-83f3-d9f108596898", - "metadata": {}, - "outputs": [], - "source": [ - "df_sentiment_finbrain = openbb.stocks.ca.sentiment(symbols=[symbol])\n", - "finbrain_sentiment_val = float(df_sentiment_finbrain.values[-1][0])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6fe6e513-d568-41b4-8aa0-37cc578c9dc3", - "metadata": {}, - "outputs": [], - "source": [ - "(\n", - " watchlist_count,\n", - " n_cases,\n", - " n_bull,\n", - " n_bear,\n", - ") = openbb.stocks.ba.bullbear(symbol=symbol)\n", - "stocktwits_sentiment = f\"Watchlist count: {watchlist_count}\"\n", - "if n_cases > 0:\n", - " stocktwits_sentiment += f\"\\nLast {n_cases} sentiment messages:\"\n", - " stocktwits_sentiment += f\"Bullish {round(100*n_bull/n_cases, 2)}%\"\n", - " stocktwits_sentiment += f\"Bearish {round(100*n_bear/n_cases, 2)}%\"\n", - "else:\n", - " stocktwits_sentiment += \"No messages found\"\n", - "stocktwits_sentiment" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bfb75909-b877-4b3a-82a7-21ce174a7bb4", - "metadata": {}, - "outputs": [], - "source": [ - "snews = openbb.stocks.ba.snews_chart(symbol, external_axes=True)\n", - "\n", - "if snews:\n", - " snews = snews.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "329c9e1b-e1de-4836-91fd-656cc87f7111", - "metadata": {}, - "outputs": [], - "source": [ - "ticker_data_all = openbb.stocks.load(\n", - " symbol=symbol,\n", - " start_date=datetime.datetime.now() - datetime.timedelta(days=5 * 12 * 21),\n", - ")\n", - "ticker_data_all[\"Returns\"] = ticker_data_all[\"Adj Close\"].pct_change()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "37743ef3-2f16-4166-bfcc-a0fe3eb959bc", - "metadata": {}, - "outputs": [], - "source": [ - "bw_month = openbb.qa.bw(\n", - " ticker_data_all,\n", - " \"Returns\",\n", - " symbol,\n", - " yearly=False,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if bw_month:\n", - " bw_month = bw_month.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "16b33868-23dc-4c77-ac00-acb452da386c", - "metadata": {}, - "outputs": [], - "source": [ - "bw_year = openbb.qa.bw(\n", - " ticker_data_all,\n", - " \"Returns\",\n", - " symbol,\n", - " yearly=True,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if bw_year:\n", - " bw_year = bw_year.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "28ce0827", - "metadata": {}, - "outputs": [], - "source": [ - "income_df = openbb.stocks.fa.income(symbol, source=\"FinancialModelingPrep\")\n", - "data_df = openbb.stocks.fa.data(symbol)\n", - "mgmt_df = openbb.stocks.fa.mgmt(symbol)\n", - "if not mgmt_df.empty:\n", - " mgmt_df[\"Info\"] = mgmt_df[\"Info\"].apply(lambda x: f'{x}')\n", - " mgmt_df[\"Insider Activity\"] = mgmt_df[\"Insider Activity\"].apply(\n", - " lambda x: f'{x}' if x != \"-\" else x\n", - " )\n", - "try:\n", - " hist_dcf = openbb.stocks.fa.dcfc(symbol)\n", - "except:\n", - " pass\n", - "enterprise_df = openbb.stocks.fa.enterprise(symbol)\n", - "score = openbb.stocks.fa.score(symbol, years=10)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "42e289ab", - "metadata": {}, - "outputs": [], - "source": [ - "indicators = dict(\n", - " ema=dict(length=[50]),\n", - " sma=dict(length=[50]),\n", - " wma=dict(length=[50]),\n", - ")\n", - "\n", - "ma_chart = PlotlyTA.plot(ticker_data, indicators, symbol, candles=False, volume=False)\n", - "\n", - "if ma_chart:\n", - " ma_chart = ma_chart.show(external=True)\n", - " ma_chart = ma_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e8846a6f", - "metadata": {}, - "outputs": [], - "source": [ - "macd_chart = openbb.ta.macd_chart(\n", - " ticker_data[\"Close\"], symbol=symbol, external_axes=True\n", - ")\n", - "\n", - "if macd_chart:\n", - " macd_chart = macd_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "48a7a427", - "metadata": {}, - "outputs": [], - "source": [ - "cci_chart = openbb.ta.cci_chart(ticker_data, symbol=symbol, external_axes=True)\n", - "\n", - "if cci_chart:\n", - " cci_chart = cci_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6a1bd2c6", - "metadata": {}, - "outputs": [], - "source": [ - "stoch_chart = openbb.ta.stoch_chart(ticker_data, symbol=symbol, external_axes=True)\n", - "\n", - "if stoch_chart:\n", - " stoch_chart = stoch_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2611d3c6", - "metadata": {}, - "outputs": [], - "source": [ - "adx_chart = openbb.ta.adx_chart(ticker_data, symbol=symbol, external_axes=True)\n", - "\n", - "if adx_chart:\n", - " adx_chart = adx_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6ecb6e17", - "metadata": {}, - "outputs": [], - "source": [ - "bbands_chart = openbb.ta.bbands_chart(ticker_data, symbol=symbol, external_axes=True)\n", - "\n", - "if bbands_chart:\n", - " bbands_chart = bbands_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "07e42fdb", - "metadata": {}, - "outputs": [], - "source": [ - "ad_chart = openbb.ta.ad_chart(ticker_data, symbol=symbol, external_axes=True)\n", - "\n", - "if ad_chart:\n", - " ad_chart = ad_chart.to_html()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", - "metadata": {}, - "source": [ - "## Render the report template to a file\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", - "metadata": {}, - "outputs": [], - "source": [ - "body = f\"\"\"\n", - "\n", - "\n", - "\"\"\"\n", - "\n", - "\n", - "img = (\n", - " str(REPOSITORY_DIRECTORY)\n", - " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", - ")\n", - "floppy_disk_img = (\n", - " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", - ")\n", - "body += widgets.header(\n", - " img,\n", - " floppy_disk_img,\n", - " author,\n", - " report_date,\n", - " report_time,\n", - " report_timezone,\n", - " report_title,\n", - ")\n", - "\n", - "body += widgets.tablinks(\n", - " [\n", - " \"SUMMARY\",\n", - " \"Overview\",\n", - " \"Fundamental Analysis\",\n", - " \"Technical Analysis\",\n", - " \"Behavioural Analysis\",\n", - " \"Government Menu\",\n", - " \"Comparison Menu\",\n", - " \"Options\",\n", - " \"Dark Pool and Shorts\",\n", - " \"Quantitative Analysis\",\n", - " \"Analyst Opinions\",\n", - " \"Insider Trading\",\n", - " # \"Prediction Techniques\",\n", - " ]\n", - ")\n", - "\n", - "htmlcode = widgets.h(3, \"KPIs\")\n", - "htmlcode += widgets.kpi(\n", - " [last_price],\n", - " [\n", - " \"Last closing price is above the average price ratings of last 30 days\",\n", - " \"Average price ratings of last 30 day is above last closing price\",\n", - " ],\n", - " avg_ratings_last_30_days,\n", - ")\n", - "htmlcode += widgets.kpi(\n", - " [30, 70],\n", - " [\"RSI level is oversold\", \"RSI level is normal\", \"RSI level is overbought\"],\n", - " rsi_value,\n", - ")\n", - "try:\n", - " htmlcode += widgets.kpi(\n", - " [0],\n", - " [\n", - " \"The sum of last 10 insider trading (in millions) was negative\",\n", - " \"The sum of last 10 insider trading (in millions) was positive\",\n", - " ],\n", - " last_10_insider_trading,\n", - " )\n", - "except:\n", - " pass\n", - "htmlcode += widgets.kpi(\n", - " [-0.1, 0.1],\n", - " [\n", - " \"Last FinBrain sentiment is bearish\",\n", - " \" Last FinBrain sentiment is neutral\",\n", - " \"Last FinBrain sentiment is bullish\",\n", - " ],\n", - " finbrain_sentiment_val,\n", - ")\n", - "if score and score[\"Total Score\"]:\n", - " htmlcode += widgets.kpi(\n", - " [25, 75],\n", - " [\n", - " \"Buffet Score is not favourable\",\n", - " \"Buffet Score is neutral\",\n", - " \"Buffet Score is favourable\",\n", - " ],\n", - " float(score[\"Total Score\"]),\n", - " )\n", - "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", - "\n", - "htmlcode = \"\"\n", - "if overview:\n", - " htmlcode += widgets.row([widgets.h(3, \"Description\") + widgets.p(overview)])\n", - "htmlcode += widgets.row([widgets.h(3, \"Price Chart\") + (price_chart or \"\")])\n", - "htmlcode += widgets.row([widgets.h(3, \"Quote\") + quote_data.to_html()])\n", - "htmlcode += widgets.row([widgets.h(3, \"Latest News for \" + symbol)])\n", - "try:\n", - " for table in tables:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(4, table[1][\"title\"]) + table[0].to_html(escape=False)]\n", - " )\n", - "except:\n", - " pass\n", - "\n", - "if not mgmt_df.empty:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, f\"Management team of {symbol}\") + mgmt_df.to_html(escape=False)]\n", - " )\n", - "body += widgets.add_tab(\"Overview\", htmlcode)\n", - "\n", - "htmlcode = widgets.row(\n", - " [widgets.h(3, \"Price Target Chart\") + (price_target_chart or \"\")]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Analyst Ratings over time\") + (ratings_over_time_chart or \"\")]\n", - ")\n", - "try:\n", - " htmlcode += widgets.row([widgets.h(3, \"Analyst Ratings\") + df_analyst.to_html()])\n", - "except:\n", - " pass\n", - "try:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, \"Analyst Recommendations\") + df_rating.to_html()]\n", - " )\n", - "except:\n", - " pass\n", - "\n", - "body += widgets.add_tab(\"Analyst Opinions\", htmlcode)\n", - "\n", - "try:\n", - " htmlcode = widgets.row(\n", - " [widgets.h(3, \"Estimates\") + df_year_estimates.head().to_html()]\n", - " )\n", - "except:\n", - " pass\n", - "\n", - "if not df_quarter_earnings.empty:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, \"Earnings\") + df_quarter_earnings.head().to_html()]\n", - " )\n", - "if not df_quarter_revenues.empty:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, \"Revenues\") + df_quarter_revenues.head().to_html()]\n", - " )\n", - "try:\n", - " htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, \"Major Institutional Shareholders\")\n", - " + df_institutional_shareholders.head().to_html()\n", - " ]\n", - " )\n", - "except:\n", - " pass\n", - "try:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, f\"Historical DCF for {symbol}\") + hist_dcf.to_html()]\n", - " )\n", - "except:\n", - " pass\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, f\"Enterprise data for {symbol}\") + enterprise_df.to_html()]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, f\"Income Statement for {symbol}\") + income_df.to_html()]\n", - ")\n", - "try:\n", - " htmlcode += widgets.row([widgets.h(3, f\"Data for {symbol}\") + data_df.to_html()])\n", - "except:\n", - " pass\n", - "try:\n", - " htmlcode += widgets.row(\n", - " [widgets.h(3, \"SEC filings\") + df_sec_filings.to_html(escape=False)]\n", - " )\n", - "except:\n", - " pass\n", - "\n", - "body += widgets.add_tab(\"Fundamental Analysis\", htmlcode)\n", - "\n", - "htmlcode = widgets.row([widgets.h(3, \"Put to call ratio\") + (pcr_chart or \"\")])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Option Volume for closest expiry date\") + (vol_chart or \"\")]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, \"Volume and Open Interest for closest expiry date\")\n", - " + (voi_chart or \"\")\n", - " ]\n", - ")\n", - "\n", - "body += widgets.add_tab(\"Options\", htmlcode)\n", - "\n", - "htmlcode = widgets.row([net_short_position or \"\"])\n", - "htmlcode += widgets.row([price_vs_short_interest or \"\"])\n", - "# htmlcode += widgets.row([dark_pools])\n", - "body += widgets.add_tab(\"Dark Pool and Shorts\", htmlcode)\n", - "\n", - "htmlcode = widgets.row(\n", - " [\n", - " widgets.h(3, \"Congress trading in the past 12 months for \" + symbol)\n", - " + (gtrades_chart or \"\")\n", - " ]\n", - ")\n", - "htmlcode += widgets.row([gov_histcont_chart or \"\"])\n", - "htmlcode += widgets.row([gov_contracts_chart or \"\"])\n", - "htmlcode += widgets.row([widgets.h(3, \"Recent Corporate Lobbying by \" + symbol)])\n", - "try:\n", - " for _, row in df_lobbying.iterrows():\n", - " amount = (\n", - " \"$\" + str(int(float(row[\"Amount\"]))) if row[\"Amount\"] is not None else \"N/A\"\n", - " )\n", - " htmlcode += widgets.row([widgets.p(f\"{row['Date']}: {row['Client']} {amount}\")])\n", - " if (row[\"Amount\"] is not None) and (row[\"Specific_Issue\"] is not None):\n", - " htmlcode += widgets.row(\n", - " [\n", - " widgets.p(\n", - " \"\\t\"\n", - " + row[\"Specific_Issue\"].replace(\"\\n\", \" \").replace(\"\\r\", \"\")\n", - " )\n", - " ]\n", - " )\n", - "except:\n", - " pass\n", - "\n", - "body += widgets.add_tab(\"Government Menu\", htmlcode)\n", - "\n", - "htmlcode = widgets.row(\n", - " [\n", - " widgets.h(3, f\"Price over the past year for companies similar to {symbol}\")\n", - " + (historical_similar or \"\")\n", - " ]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, f\"Price correlation with similar companies for {symbol}\")\n", - " + (hcorr_similar or \"\")\n", - " ]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, f\"Volume over the past year for companies similar to {symbol}\")\n", - " + (vol_similar or \"\")\n", - " ]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, f\"Sentiment correlation with similar companies for {symbol}\")\n", - " + (scorr_similar or \"\")\n", - " ]\n", - ")\n", - "if isinstance(income_comparison, pd.DataFrame):\n", - " htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, f\"Income data for similar companies to {symbol}\")\n", - " + income_comparison.to_html()\n", - " ]\n", - " )\n", - "htmlcode += widgets.row(\n", - " [\n", - " widgets.p(\n", - " \"Note that similar companies have been found using openbb.stocks.ca.similar\"\n", - " )\n", - " ]\n", - ")\n", - "body += widgets.add_tab(\"Comparison Menu\", htmlcode)\n", - "\n", - "htmlcode = widgets.row([widgets.h(3, f\"Moving Averages for {symbol}\") + ma_chart])\n", - "htmlcode += widgets.row([macd_chart or \"\"])\n", - "htmlcode += widgets.row([ta_rsi or \"\"])\n", - "htmlcode += widgets.row([stoch_chart or \"\"])\n", - "htmlcode += widgets.row([cci_chart or \"\"])\n", - "htmlcode += widgets.row([ad_chart or \"\"])\n", - "htmlcode += widgets.row([bbands_chart or \"\"])\n", - "htmlcode += widgets.row([adx_chart or \"\"])\n", - "body += widgets.add_tab(\"Technical Analysis\", htmlcode)\n", - "\n", - "if not df_insider.empty:\n", - " htmlcode = widgets.row(\n", - " [widgets.h(3, \"Last Activity\") + df_insider.head(10).to_html(col_space=\"75px\")]\n", - " )\n", - "else:\n", - " htmlcode = widgets.row(\n", - " [widgets.h(3, \"Last Activity\") + widgets.p(\"No insider trading data found.\")]\n", - " )\n", - "\n", - "body += widgets.add_tab(\"Insider Trading\", htmlcode)\n", - "\n", - "\n", - "htmlcode = widgets.row([bw_year or \"\"])\n", - "htmlcode += widgets.row([bw_month or \"\"])\n", - "body += widgets.add_tab(\"Quantitative Analysis\", htmlcode)\n", - "\n", - "\n", - "htmlcode = widgets.row([finbrain_sentiment or \"\"])\n", - "htmlcode += widgets.row([snews or \"\"])\n", - "htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, \"Interest in \" + symbol + \" based on google analytics\")\n", - " + (google_mentions_chart or \"\")\n", - " ]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, f\"Regions with highest interest in {symbol}\")\n", - " + (google_regions_chart or \"\")\n", - " ]\n", - ")\n", - "try:\n", - " htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, f\"Top queries related to {symbol}\")\n", - " + df_related_queries.to_html()\n", - " ]\n", - " )\n", - " htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, f\"Top rising queries related to {symbol}\")\n", - " + df_rising_queries.to_html()\n", - " ]\n", - " )\n", - "except:\n", - " pass\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, f\"Stocktwits sentiment for {symbol}\") + stocktwits_sentiment]\n", - ")\n", - "body += widgets.add_tab(\"Behavioural Analysis\", htmlcode)\n", - "\n", - "body += widgets.tab_clickable_and_save_evt()\n", - "\n", - "report = widgets.html_report(\n", - " title=report_name, stylesheet=widgets.html_report_stylesheet(), body=body\n", - ")\n", - "\n", - "# to save the results\n", - "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", - " fh.write(report)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "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.10.9" - }, - "vscode": { - "interpreter": { - "hash": "af870c0f9615f5bb08692efcc9bf540319fe60e6793056508a4dab09c9fa8dda" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "70ba2c8a", + "metadata": {}, + "source": [ + "## Notebook setup\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "driven-billion", + "metadata": {}, + "outputs": [], + "source": [ + "import warnings\n", + "import datetime\n", + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "from IPython.display import HTML\n", + "\n", + "from openbb_terminal import config_terminal as cfg\n", + "from openbb_terminal.helper_classes import TerminalStyle\n", + "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", + "from openbb_terminal import OpenBBFigure\n", + "from openbb_terminal.core.plots.plotly_ta.ta_class import PlotlyTA\n", + "\n", + "warnings.filterwarnings(\"ignore\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "150e5103", + "metadata": {}, + "outputs": [], + "source": [ + "# Suppressing sdk logs\n", + "cfg.change_logging_suppress(new_value=True)\n", + "\n", + "# Import the OpenBB SDK\n", + "from openbb_terminal.sdk import openbb, widgets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf31bcc7", + "metadata": {}, + "outputs": [], + "source": [ + "from openbb_terminal.core.session.current_user import get_current_user\n", + "\n", + "user = get_current_user()\n", + "\n", + "cfg.theme = TerminalStyle(\n", + " user.preferences.MPL_STYLE,\n", + " user.preferences.PMF_STYLE,\n", + " user.preferences.RICH_STYLE,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", + "metadata": {}, + "outputs": [], + "source": [ + "stylesheet = widgets.html_report_stylesheet()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "807fda4e", + "metadata": {}, + "source": [ + "## Select symbol\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "intended-sherman", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "# Parameters that will be replaced when calling this notebook\n", + "# Do not leave parameters blank as notebook will not run otherwise\n", + "symbol = \"msft\"\n", + "report_name = f\"Equity report for {symbol}\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a441ddbc-d75b-4a18-84d4-e01b677674d3", + "metadata": {}, + "outputs": [], + "source": [ + "if \".\" in symbol:\n", + " import sys\n", + "\n", + " sys.exit(0)\n", + "symbol = symbol.upper()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", + "metadata": {}, + "outputs": [], + "source": [ + "ticker_data = openbb.stocks.load(\n", + " symbol=symbol, start_date=datetime.datetime.now() - datetime.timedelta(days=18 * 30)\n", + ")\n", + "ticker_data = openbb.stocks.process_candle(data=ticker_data)\n", + "\n", + "author = \"\"\n", + "report_title = f\"Investment Research Report on {symbol.upper()}\"\n", + "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", + "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", + "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", + "report_title, report_date, report_time, report_timezone" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3b15d6f-dc9e-4f97-aa07-37d949a4e4bb", + "metadata": {}, + "outputs": [], + "source": [ + "info = openbb.stocks.fa.info(symbol=symbol).transpose()\n", + "\n", + "long_summary = \"Long business summary\"\n", + "long_name = \"Long name\"\n", + "\n", + "if long_summary in info and info[long_summary][0] != \"NA\":\n", + " overview = info[long_summary][0]\n", + "elif long_name in info:\n", + " overview = info[long_name][0]\n", + "else:\n", + " overview = \"\"" + ] + }, + { + "cell_type": "markdown", + "id": "f8a0d747", + "metadata": {}, + "source": [ + "## Data\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aca4b6ef", + "metadata": {}, + "outputs": [], + "source": [ + "(\n", + " df_year_estimates,\n", + " df_quarter_earnings,\n", + " df_quarter_revenues,\n", + ") = openbb.stocks.fa.est(symbol=symbol)\n", + "df_quarter_revenues" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0f0a1ca", + "metadata": {}, + "outputs": [], + "source": [ + "display_year = sorted(df_year_estimates.columns.tolist())[:3]\n", + "df_year_estimates = df_year_estimates[display_year].head(5)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6976c1d5", + "metadata": {}, + "outputs": [], + "source": [ + "tables = openbb.etf.news(info[\"Short name\"][0], 5) if \"Short name\" in info else symbol\n", + "\n", + "for table in tables:\n", + " if not isinstance(table, pd.DataFrame):\n", + " continue\n", + "\n", + " table[0].loc[\"link\"] = (\n", + " table[0].loc[\"link\"].apply(lambda x: f'{x}')\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38e38d7c", + "metadata": {}, + "outputs": [], + "source": [ + "quote_data = openbb.stocks.quote(symbol)\n", + "quote_data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fde46353", + "metadata": {}, + "outputs": [], + "source": [ + "df_institutional_shareholders = openbb.stocks.fa.shrs(symbol, holder=\"institutional\")\n", + "df_institutional_shareholders.index += 1\n", + "df_institutional_shareholders" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e101e24e", + "metadata": {}, + "outputs": [], + "source": [ + "openbb.stocks.fa.shrs(symbol)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51dfd9d2", + "metadata": {}, + "outputs": [], + "source": [ + "df_institutional_shareholders = openbb.stocks.fa.shrs(symbol)\n", + "df_institutional_shareholders.index += 1\n", + "df_institutional_shareholders" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3022130e", + "metadata": {}, + "outputs": [], + "source": [ + "df_sec_filings = openbb.stocks.fa.sec(symbol)[[\"Type\", \"Category\", \"Link\"]].head(5)\n", + "df_sec_filings[\"Link\"] = df_sec_filings[\"Link\"].apply(\n", + " lambda x: f'{x}'\n", + ")\n", + "df_sec_filings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4662b1ac", + "metadata": {}, + "outputs": [], + "source": [ + "df_analyst = openbb.stocks.fa.analyst(symbol=symbol)\n", + "\n", + "if not df_analyst.empty:\n", + " if \"target\" in df_analyst.columns:\n", + " if \"target_to\" in df_analyst.columns:\n", + " df_analyst[\"target\"] = df_analyst[\"target_to\"].combine_first(\n", + " df_analyst[\"target\"]\n", + " )\n", + " else:\n", + " df_analyst[\"target\"] = df_analyst[\"target_to\"]\n", + " df_analyst = df_analyst[[\"category\", \"analyst\", \"rating\", \"target\"]].rename(\n", + " columns={\n", + " \"category\": \"Category\",\n", + " \"analyst\": \"Analyst\",\n", + " \"rating\": \"Rating\",\n", + " \"target\": \"Price Target\",\n", + " }\n", + " )\n", + "df_analyst" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df8bdb7d", + "metadata": {}, + "outputs": [], + "source": [ + "df_rating = openbb.stocks.fa.rating(symbol)\n", + "df_rating" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0df953b", + "metadata": {}, + "outputs": [], + "source": [ + "pcr_chart = openbb.stocks.options.pcr_chart(symbol, window=30, external_axes=True)\n", + "\n", + "if pcr_chart:\n", + " pcr_chart = pcr_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd79195c", + "metadata": {}, + "outputs": [], + "source": [ + "expiry_dates = openbb.stocks.options.expirations(symbol)\n", + "exp = expiry_dates[0]\n", + "option_chain = openbb.stocks.options.chains(symbol, expiration=exp)\n", + "current_price = float(ticker_data[\"Adj Close\"][-1])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad6d0c24", + "metadata": {}, + "outputs": [], + "source": [ + "vol_chart = openbb.stocks.options.vol(\n", + " option_chain, current_price, symbol, exp, external_axes=True\n", + ")\n", + "\n", + "if vol_chart:\n", + " vol_chart = vol_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "be2d1e3a", + "metadata": {}, + "outputs": [], + "source": [ + "voi_chart = openbb.stocks.options.voi(\n", + " option_chain, current_price, symbol, exp, external_axes=True\n", + ")\n", + "\n", + "if voi_chart:\n", + " voi_chart = voi_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "324e2d4b-b2f6-4da3-bac4-ef785ad4e436", + "metadata": {}, + "outputs": [], + "source": [ + "net_short_position = openbb.stocks.dps.spos_chart(\n", + " symbol=symbol,\n", + " limit=84,\n", + " raw=False,\n", + " export=\"\",\n", + " external_axes=True,\n", + ")\n", + "\n", + "if net_short_position:\n", + " net_short_position = net_short_position.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac0bfbda-e4b8-4b3b-b8e7-c02639fdb971", + "metadata": {}, + "outputs": [], + "source": [ + "dark_pools = openbb.stocks.dps.dpotc_chart(symbol=symbol, external_axes=True)\n", + "\n", + "if dark_pools:\n", + " dark_pools = dark_pools.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22a7266f", + "metadata": {}, + "outputs": [], + "source": [ + "gtrades_chart = openbb.stocks.gov.gtrades_chart(\n", + " symbol,\n", + " past_transactions_months=12,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if gtrades_chart:\n", + " gtrades_chart = gtrades_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c670ba3", + "metadata": {}, + "outputs": [], + "source": [ + "gov_contracts_chart = openbb.stocks.gov.contracts_chart(\n", + " symbol,\n", + " past_transaction_days=365,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if gov_contracts_chart:\n", + " gov_contracts_chart = gov_contracts_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "caa3dae2", + "metadata": {}, + "outputs": [], + "source": [ + "google_mentions_chart = openbb.stocks.ba.mentions_chart(\n", + " symbol,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if google_mentions_chart:\n", + " google_mentions_chart = google_mentions_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b77e60d8", + "metadata": {}, + "outputs": [], + "source": [ + "google_regions_chart = openbb.stocks.ba.regions_chart(\n", + " symbol,\n", + " limit=10,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if google_regions_chart:\n", + " google_regions_chart = google_regions_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "78593369", + "metadata": {}, + "outputs": [], + "source": [ + "similar_companies = openbb.stocks.ca.similar(symbol, source=\"Polygon\")\n", + "if similar_companies:\n", + " similar_companies.append(symbol)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4639665b", + "metadata": {}, + "outputs": [], + "source": [ + "historical_similar = openbb.stocks.ca.hist_chart(\n", + " similar_companies,\n", + " external_axes=True,\n", + " normalize=False,\n", + ")\n", + "\n", + "if historical_similar:\n", + " historical_similar = historical_similar.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "74565e53", + "metadata": {}, + "outputs": [], + "source": [ + "hcorr_similar = openbb.stocks.ca.hcorr_chart(\n", + " similar_companies,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if hcorr_similar:\n", + " hcorr_similar = hcorr_similar.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "936babfd", + "metadata": {}, + "outputs": [], + "source": [ + "vol_similar = openbb.stocks.ca.volume_chart(\n", + " similar_companies,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if vol_similar:\n", + " vol_similar = vol_similar.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "99388d4e", + "metadata": {}, + "outputs": [], + "source": [ + "scorr_similar = openbb.stocks.ca.scorr_chart(\n", + " similar_companies,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if scorr_similar:\n", + " scorr_similar = scorr_similar.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eaa67343", + "metadata": {}, + "outputs": [], + "source": [ + "income_comparison = openbb.stocks.ca.income(similar_companies)\n", + "income_comparison" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13ad71cf", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " df_related_queries = openbb.stocks.ba.queries(symbol)\n", + " df_related_queries.index += 1\n", + " df_related_queries.index\n", + "except:\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58c06129", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " df_rising_queries = openbb.stocks.ba.rise(symbol)\n", + " df_rising_queries.index += 1\n", + " df_rising_queries\n", + "except:\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a467f1a", + "metadata": {}, + "outputs": [], + "source": [ + "gov_histcont_chart = openbb.stocks.gov.histcont_chart(\n", + " symbol,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if gov_histcont_chart:\n", + " gov_histcont_chart = gov_histcont_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "730cae26", + "metadata": {}, + "outputs": [], + "source": [ + "df_lobbying = openbb.stocks.gov.lobbying(symbol, limit=5)\n", + "df_lobbying" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8bb53c1-147e-4342-af61-0d0a9cc56e59", + "metadata": {}, + "outputs": [], + "source": [ + "price_vs_short_interest = openbb.stocks.dps.psi_sg_chart(\n", + " symbol=symbol, external_axes=True\n", + ")\n", + "\n", + "if price_vs_short_interest:\n", + " price_vs_short_interest = price_vs_short_interest.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "394668e1-1158-4a2b-8a38-04c72a6abdd6", + "metadata": {}, + "outputs": [], + "source": [ + "price_chart = openbb.stocks.candle(\n", + " symbol=symbol,\n", + " data=ticker_data,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if price_chart:\n", + " price_chart = price_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "900686a3", + "metadata": {}, + "outputs": [], + "source": [ + "price_target_chart = openbb.stocks.fa.pt_chart(\n", + " symbol=symbol,\n", + " start_date=\"2022-01-01\",\n", + " data=ticker_data,\n", + " limit=10,\n", + " raw=False,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if price_target_chart:\n", + " price_target_chart = price_target_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "61d62e1a-199e-481d-b57d-38ab486951be", + "metadata": {}, + "outputs": [], + "source": [ + "df = openbb.stocks.fa.pt(symbol=symbol)\n", + "avg_ratings_last_30_days = 0\n", + "days = 0\n", + "if not df.empty:\n", + " df_ratings = df[datetime.datetime.now() - datetime.timedelta(days=days) :]\n", + " while df_ratings.empty:\n", + " days += 30\n", + " df_ratings = df[datetime.datetime.now() - datetime.timedelta(days=days) :]\n", + "\n", + " if days > 100:\n", + " break\n", + "\n", + " if not df_ratings.empty:\n", + " avg_ratings_last_30_days = round(np.mean(df_ratings[\"Price Target\"].values), 2)\n", + " else:\n", + " avg_ratings = 0\n", + "\n", + "last_price = round(ticker_data[\"Close\"][-1], 2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f3733ff2", + "metadata": {}, + "outputs": [], + "source": [ + "ratings_over_time_chart = openbb.stocks.fa.rot_chart(\n", + " symbol=symbol,\n", + " limit=10,\n", + " raw=False,\n", + " export=\"\",\n", + " external_axes=True,\n", + ")\n", + "\n", + "if ratings_over_time_chart:\n", + " ratings_over_time_chart = ratings_over_time_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "924f8042-e58a-449c-91a3-7923158ff714", + "metadata": {}, + "outputs": [], + "source": [ + "ta_rsi = openbb.ta.rsi_chart(ticker_data[\"Close\"], external_axes=True)\n", + "\n", + "if ta_rsi:\n", + " ta_rsi = ta_rsi.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "953a340e-7ea1-4aa3-ae1d-872683dced41", + "metadata": {}, + "outputs": [], + "source": [ + "df = openbb.ta.rsi(ticker_data[\"Close\"])\n", + "rsi_value = round(df.values[-1][0], 2)\n", + "rsi_value" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dce71711-20b3-4c69-af52-e0f9a69991f8", + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.linear_model import LinearRegression\n", + "\n", + "model = LinearRegression().fit(\n", + " np.array(range(len(ticker_data[\"Close\"][-30:].index))).reshape(-1, 1),\n", + " ticker_data[\"Close\"][-30:].values,\n", + ")\n", + "regression_slope = round(model.coef_[0], 2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6272e34b-9511-4b48-9eea-ea882ce9846a", + "metadata": {}, + "outputs": [], + "source": [ + "df_insider = pd.DataFrame.from_dict(openbb.stocks.ins.lins(symbol=symbol)).head(10)\n", + "if not df_insider.empty:\n", + " df_insider[\"Val ($)\"] = df_insider[\"Value ($)\"].replace({\",\": \"\"}, regex=True)\n", + " df_insider[\"Trade\"] = df_insider.apply(\n", + " lambda row: (-1 * float(row[\"Val ($)\"]))\n", + " if row[\"Transaction\"] == \"Sale\"\n", + " else (float(row[\"Val ($)\"]) if row[\"Transaction\"] == \"Buy\" else 0),\n", + " axis=1,\n", + " )\n", + " last_10_insider_trading = round(sum(df_insider[\"Trade\"]) / 1_000_000, 2)\n", + " df_insider = df_insider.drop(columns=[\"Val ($)\", \"Trade\"])\n", + " df_insider" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29254666-58c6-4686-87e6-2635ad8387e2", + "metadata": {}, + "outputs": [], + "source": [ + "finbrain_sentiment = openbb.stocks.ba.headlines_chart(symbol=symbol, external_axes=True)\n", + "\n", + "if finbrain_sentiment:\n", + " finbrain_sentiment = finbrain_sentiment.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8251b47-8ecc-47be-83f3-d9f108596898", + "metadata": {}, + "outputs": [], + "source": [ + "df_sentiment_finbrain = openbb.stocks.ca.sentiment(symbols=[symbol])\n", + "finbrain_sentiment_val = float(df_sentiment_finbrain.values[-1][0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fe6e513-d568-41b4-8aa0-37cc578c9dc3", + "metadata": {}, + "outputs": [], + "source": [ + "(\n", + " watchlist_count,\n", + " n_cases,\n", + " n_bull,\n", + " n_bear,\n", + ") = openbb.stocks.ba.bullbear(symbol=symbol)\n", + "stocktwits_sentiment = f\"Watchlist count: {watchlist_count}\"\n", + "if n_cases > 0:\n", + " stocktwits_sentiment += f\"\\nLast {n_cases} sentiment messages:\"\n", + " stocktwits_sentiment += f\"Bullish {round(100*n_bull/n_cases, 2)}%\"\n", + " stocktwits_sentiment += f\"Bearish {round(100*n_bear/n_cases, 2)}%\"\n", + "else:\n", + " stocktwits_sentiment += \"No messages found\"\n", + "stocktwits_sentiment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bfb75909-b877-4b3a-82a7-21ce174a7bb4", + "metadata": {}, + "outputs": [], + "source": [ + "snews = openbb.stocks.ba.snews_chart(symbol, external_axes=True)\n", + "\n", + "if snews:\n", + " snews = snews.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "329c9e1b-e1de-4836-91fd-656cc87f7111", + "metadata": {}, + "outputs": [], + "source": [ + "ticker_data_all = openbb.stocks.load(\n", + " symbol=symbol,\n", + " start_date=datetime.datetime.now() - datetime.timedelta(days=5 * 12 * 21),\n", + ")\n", + "ticker_data_all[\"Returns\"] = ticker_data_all[\"Adj Close\"].pct_change()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37743ef3-2f16-4166-bfcc-a0fe3eb959bc", + "metadata": {}, + "outputs": [], + "source": [ + "bw_month = openbb.qa.bw(\n", + " ticker_data_all,\n", + " \"Returns\",\n", + " symbol,\n", + " yearly=False,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if bw_month:\n", + " bw_month = bw_month.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16b33868-23dc-4c77-ac00-acb452da386c", + "metadata": {}, + "outputs": [], + "source": [ + "bw_year = openbb.qa.bw(\n", + " ticker_data_all,\n", + " \"Returns\",\n", + " symbol,\n", + " yearly=True,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if bw_year:\n", + " bw_year = bw_year.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28ce0827", + "metadata": {}, + "outputs": [], + "source": [ + "income_df = openbb.stocks.fa.income(symbol, source=\"FinancialModelingPrep\")\n", + "data_df = openbb.stocks.fa.data(symbol)\n", + "mgmt_df = openbb.stocks.fa.mgmt(symbol)\n", + "if not mgmt_df.empty:\n", + " mgmt_df[\"Info\"] = mgmt_df[\"Info\"].apply(lambda x: f'{x}')\n", + " mgmt_df[\"Insider Activity\"] = mgmt_df[\"Insider Activity\"].apply(\n", + " lambda x: f'{x}' if x != \"-\" else x\n", + " )\n", + "try:\n", + " hist_dcf = openbb.stocks.fa.dcfc(symbol)\n", + "except:\n", + " pass\n", + "enterprise_df = openbb.stocks.fa.enterprise(symbol)\n", + "score = openbb.stocks.fa.score(symbol, years=10)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42e289ab", + "metadata": {}, + "outputs": [], + "source": [ + "indicators = dict(\n", + " ema=dict(length=[50]),\n", + " sma=dict(length=[50]),\n", + " wma=dict(length=[50]),\n", + ")\n", + "\n", + "ma_chart = PlotlyTA.plot(ticker_data, indicators, symbol, candles=False, volume=False)\n", + "\n", + "if ma_chart:\n", + " ma_chart = ma_chart.show(external=True)\n", + " ma_chart = ma_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8846a6f", + "metadata": {}, + "outputs": [], + "source": [ + "macd_chart = openbb.ta.macd_chart(\n", + " ticker_data[\"Close\"], symbol=symbol, external_axes=True\n", + ")\n", + "\n", + "if macd_chart:\n", + " macd_chart = macd_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "48a7a427", + "metadata": {}, + "outputs": [], + "source": [ + "cci_chart = openbb.ta.cci_chart(ticker_data, symbol=symbol, external_axes=True)\n", + "\n", + "if cci_chart:\n", + " cci_chart = cci_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a1bd2c6", + "metadata": {}, + "outputs": [], + "source": [ + "stoch_chart = openbb.ta.stoch_chart(ticker_data, symbol=symbol, external_axes=True)\n", + "\n", + "if stoch_chart:\n", + " stoch_chart = stoch_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2611d3c6", + "metadata": {}, + "outputs": [], + "source": [ + "adx_chart = openbb.ta.adx_chart(ticker_data, symbol=symbol, external_axes=True)\n", + "\n", + "if adx_chart:\n", + " adx_chart = adx_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6ecb6e17", + "metadata": {}, + "outputs": [], + "source": [ + "bbands_chart = openbb.ta.bbands_chart(ticker_data, symbol=symbol, external_axes=True)\n", + "\n", + "if bbands_chart:\n", + " bbands_chart = bbands_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07e42fdb", + "metadata": {}, + "outputs": [], + "source": [ + "ad_chart = openbb.ta.ad_chart(ticker_data, symbol=symbol, external_axes=True)\n", + "\n", + "if ad_chart:\n", + " ad_chart = ad_chart.to_html()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", + "metadata": {}, + "source": [ + "## Render the report template to a file\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", + "metadata": {}, + "outputs": [], + "source": [ + "body = f\"\"\"\n", + "\n", + "\n", + "\"\"\"\n", + "\n", + "\n", + "img = (\n", + " str(REPOSITORY_DIRECTORY)\n", + " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", + ")\n", + "floppy_disk_img = (\n", + " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", + ")\n", + "body += widgets.header(\n", + " img,\n", + " floppy_disk_img,\n", + " author,\n", + " report_date,\n", + " report_time,\n", + " report_timezone,\n", + " report_title,\n", + ")\n", + "\n", + "body += widgets.tablinks(\n", + " [\n", + " \"SUMMARY\",\n", + " \"Overview\",\n", + " \"Fundamental Analysis\",\n", + " \"Technical Analysis\",\n", + " \"Behavioural Analysis\",\n", + " \"Government Menu\",\n", + " \"Comparison Menu\",\n", + " \"Options\",\n", + " \"Dark Pool and Shorts\",\n", + " \"Quantitative Analysis\",\n", + " \"Analyst Opinions\",\n", + " \"Insider Trading\",\n", + " # \"Prediction Techniques\",\n", + " ]\n", + ")\n", + "\n", + "htmlcode = widgets.h(3, \"KPIs\")\n", + "htmlcode += widgets.kpi(\n", + " [last_price],\n", + " [\n", + " \"Last closing price is above the average price ratings of last 30 days\",\n", + " \"Average price ratings of last 30 day is above last closing price\",\n", + " ],\n", + " avg_ratings_last_30_days,\n", + ")\n", + "htmlcode += widgets.kpi(\n", + " [30, 70],\n", + " [\"RSI level is oversold\", \"RSI level is normal\", \"RSI level is overbought\"],\n", + " rsi_value,\n", + ")\n", + "try:\n", + " htmlcode += widgets.kpi(\n", + " [0],\n", + " [\n", + " \"The sum of last 10 insider trading (in millions) was negative\",\n", + " \"The sum of last 10 insider trading (in millions) was positive\",\n", + " ],\n", + " last_10_insider_trading,\n", + " )\n", + "except:\n", + " pass\n", + "htmlcode += widgets.kpi(\n", + " [-0.1, 0.1],\n", + " [\n", + " \"Last FinBrain sentiment is bearish\",\n", + " \" Last FinBrain sentiment is neutral\",\n", + " \"Last FinBrain sentiment is bullish\",\n", + " ],\n", + " finbrain_sentiment_val,\n", + ")\n", + "if score and score[\"Total Score\"]:\n", + " htmlcode += widgets.kpi(\n", + " [25, 75],\n", + " [\n", + " \"Buffet Score is not favourable\",\n", + " \"Buffet Score is neutral\",\n", + " \"Buffet Score is favourable\",\n", + " ],\n", + " float(score[\"Total Score\"]),\n", + " )\n", + "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", + "\n", + "htmlcode = \"\"\n", + "if overview:\n", + " htmlcode += widgets.row([widgets.h(3, \"Description\") + widgets.p(overview)])\n", + "htmlcode += widgets.row([widgets.h(3, \"Price Chart\") + (price_chart or \"\")])\n", + "\n", + "try:\n", + " htmlcode += widgets.row([widgets.h(3, \"Quote\") + quote_data.to_html()])\n", + "except:\n", + " pass\n", + "\n", + "htmlcode += widgets.row([widgets.h(3, \"Latest News for \" + symbol)])\n", + "try:\n", + " for table in tables:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(4, table[1][\"title\"]) + table[0].to_html(escape=False)]\n", + " )\n", + "except:\n", + " pass\n", + "\n", + "if not mgmt_df.empty:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, f\"Management team of {symbol}\") + mgmt_df.to_html(escape=False)]\n", + " )\n", + "body += widgets.add_tab(\"Overview\", htmlcode)\n", + "\n", + "htmlcode = widgets.row(\n", + " [widgets.h(3, \"Price Target Chart\") + (price_target_chart or \"\")]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Analyst Ratings over time\") + (ratings_over_time_chart or \"\")]\n", + ")\n", + "try:\n", + " htmlcode += widgets.row([widgets.h(3, \"Analyst Ratings\") + df_analyst.to_html()])\n", + "except:\n", + " pass\n", + "try:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, \"Analyst Recommendations\") + df_rating.to_html()]\n", + " )\n", + "except:\n", + " pass\n", + "\n", + "body += widgets.add_tab(\"Analyst Opinions\", htmlcode)\n", + "\n", + "try:\n", + " htmlcode = widgets.row(\n", + " [widgets.h(3, \"Estimates\") + df_year_estimates.head().to_html()]\n", + " )\n", + "except:\n", + " pass\n", + "\n", + "if not df_quarter_earnings.empty:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, \"Earnings\") + df_quarter_earnings.head().to_html()]\n", + " )\n", + "if not df_quarter_revenues.empty:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, \"Revenues\") + df_quarter_revenues.head().to_html()]\n", + " )\n", + "try:\n", + " htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, \"Major Institutional Shareholders\")\n", + " + df_institutional_shareholders.head().to_html()\n", + " ]\n", + " )\n", + "except:\n", + " pass\n", + "try:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, f\"Historical DCF for {symbol}\") + hist_dcf.to_html()]\n", + " )\n", + "except:\n", + " pass\n", + "try:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, f\"Enterprise data for {symbol}\") + enterprise_df.to_html()]\n", + " )\n", + "except:\n", + " pass\n", + "try:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, f\"Income Statement for {symbol}\") + income_df.to_html()]\n", + " )\n", + "except:\n", + " pass\n", + "try:\n", + " htmlcode += widgets.row([widgets.h(3, f\"Data for {symbol}\") + data_df.to_html()])\n", + "except:\n", + " pass\n", + "try:\n", + " htmlcode += widgets.row(\n", + " [widgets.h(3, \"SEC filings\") + df_sec_filings.to_html(escape=False)]\n", + " )\n", + "except:\n", + " pass\n", + "\n", + "body += widgets.add_tab(\"Fundamental Analysis\", htmlcode)\n", + "\n", + "htmlcode = widgets.row([widgets.h(3, \"Put to call ratio\") + (pcr_chart or \"\")])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Option Volume for closest expiry date\") + (vol_chart or \"\")]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, \"Volume and Open Interest for closest expiry date\")\n", + " + (voi_chart or \"\")\n", + " ]\n", + ")\n", + "\n", + "body += widgets.add_tab(\"Options\", htmlcode)\n", + "\n", + "htmlcode = widgets.row([net_short_position or \"\"])\n", + "htmlcode += widgets.row([price_vs_short_interest or \"\"])\n", + "# htmlcode += widgets.row([dark_pools])\n", + "body += widgets.add_tab(\"Dark Pool and Shorts\", htmlcode)\n", + "\n", + "htmlcode = widgets.row(\n", + " [\n", + " widgets.h(3, \"Congress trading in the past 12 months for \" + symbol)\n", + " + (gtrades_chart or \"\")\n", + " ]\n", + ")\n", + "htmlcode += widgets.row([gov_histcont_chart or \"\"])\n", + "htmlcode += widgets.row([gov_contracts_chart or \"\"])\n", + "htmlcode += widgets.row([widgets.h(3, \"Recent Corporate Lobbying by \" + symbol)])\n", + "try:\n", + " for _, row in df_lobbying.iterrows():\n", + " amount = (\n", + " \"$\" + str(int(float(row[\"Amount\"]))) if row[\"Amount\"] is not None else \"N/A\"\n", + " )\n", + " htmlcode += widgets.row([widgets.p(f\"{row['Date']}: {row['Client']} {amount}\")])\n", + " if (row[\"Amount\"] is not None) and (row[\"Specific_Issue\"] is not None):\n", + " htmlcode += widgets.row(\n", + " [\n", + " widgets.p(\n", + " \"\\t\"\n", + " + row[\"Specific_Issue\"].replace(\"\\n\", \" \").replace(\"\\r\", \"\")\n", + " )\n", + " ]\n", + " )\n", + "except:\n", + " pass\n", + "\n", + "body += widgets.add_tab(\"Government Menu\", htmlcode)\n", + "\n", + "htmlcode = widgets.row(\n", + " [\n", + " widgets.h(3, f\"Price over the past year for companies similar to {symbol}\")\n", + " + (historical_similar or \"\")\n", + " ]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, f\"Price correlation with similar companies for {symbol}\")\n", + " + (hcorr_similar or \"\")\n", + " ]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, f\"Volume over the past year for companies similar to {symbol}\")\n", + " + (vol_similar or \"\")\n", + " ]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, f\"Sentiment correlation with similar companies for {symbol}\")\n", + " + (scorr_similar or \"\")\n", + " ]\n", + ")\n", + "if isinstance(income_comparison, pd.DataFrame):\n", + " htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, f\"Income data for similar companies to {symbol}\")\n", + " + income_comparison.to_html()\n", + " ]\n", + " )\n", + "htmlcode += widgets.row(\n", + " [\n", + " widgets.p(\n", + " \"Note that similar companies have been found using openbb.stocks.ca.similar\"\n", + " )\n", + " ]\n", + ")\n", + "body += widgets.add_tab(\"Comparison Menu\", htmlcode)\n", + "\n", + "htmlcode = widgets.row([widgets.h(3, f\"Moving Averages for {symbol}\") + ma_chart])\n", + "htmlcode += widgets.row([macd_chart or \"\"])\n", + "htmlcode += widgets.row([ta_rsi or \"\"])\n", + "htmlcode += widgets.row([stoch_chart or \"\"])\n", + "htmlcode += widgets.row([cci_chart or \"\"])\n", + "htmlcode += widgets.row([ad_chart or \"\"])\n", + "htmlcode += widgets.row([bbands_chart or \"\"])\n", + "htmlcode += widgets.row([adx_chart or \"\"])\n", + "body += widgets.add_tab(\"Technical Analysis\", htmlcode)\n", + "\n", + "if not df_insider.empty:\n", + " htmlcode = widgets.row(\n", + " [widgets.h(3, \"Last Activity\") + df_insider.head(10).to_html(col_space=\"75px\")]\n", + " )\n", + "else:\n", + " htmlcode = widgets.row(\n", + " [widgets.h(3, \"Last Activity\") + widgets.p(\"No insider trading data found.\")]\n", + " )\n", + "\n", + "body += widgets.add_tab(\"Insider Trading\", htmlcode)\n", + "\n", + "\n", + "htmlcode = widgets.row([bw_year or \"\"])\n", + "htmlcode += widgets.row([bw_month or \"\"])\n", + "body += widgets.add_tab(\"Quantitative Analysis\", htmlcode)\n", + "\n", + "\n", + "htmlcode = widgets.row([finbrain_sentiment or \"\"])\n", + "htmlcode += widgets.row([snews or \"\"])\n", + "htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, \"Interest in \" + symbol + \" based on google analytics\")\n", + " + (google_mentions_chart or \"\")\n", + " ]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, f\"Regions with highest interest in {symbol}\")\n", + " + (google_regions_chart or \"\")\n", + " ]\n", + ")\n", + "try:\n", + " htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, f\"Top queries related to {symbol}\")\n", + " + df_related_queries.to_html()\n", + " ]\n", + " )\n", + " htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, f\"Top rising queries related to {symbol}\")\n", + " + df_rising_queries.to_html()\n", + " ]\n", + " )\n", + "except:\n", + " pass\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, f\"Stocktwits sentiment for {symbol}\") + stocktwits_sentiment]\n", + ")\n", + "body += widgets.add_tab(\"Behavioural Analysis\", htmlcode)\n", + "\n", + "body += widgets.tab_clickable_and_save_evt()\n", + "\n", + "report = widgets.html_report(\n", + " title=report_name, stylesheet=widgets.html_report_stylesheet(), body=body\n", + ")\n", + "\n", + "# to save the results\n", + "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", + " fh.write(report)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "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.10.9" + }, + "vscode": { + "interpreter": { + "hash": "af870c0f9615f5bb08692efcc9bf540319fe60e6793056508a4dab09c9fa8dda" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/openbb_terminal/reports/templates/etf.ipynb b/openbb_terminal/reports/templates/etf.ipynb index 470ce9b2a17..715e48c8039 100644 --- a/openbb_terminal/reports/templates/etf.ipynb +++ b/openbb_terminal/reports/templates/etf.ipynb @@ -1,350 +1,364 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "70ba2c8a", - "metadata": {}, - "source": [ - "## Notebook setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "driven-billion", - "metadata": {}, - "outputs": [], - "source": [ - "import warnings\n", - "import numpy as np\n", - "import datetime\n", - "\n", - "from IPython.display import HTML\n", - "\n", - "import openbb_terminal.config_terminal as cfg\n", - "from openbb_terminal.reports import widget_helpers as widgets\n", - "from openbb_terminal.sdk import openbb\n", - "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", - "from openbb_terminal import OpenBBFigure, theme\n", - "from openbb_terminal.helper_classes import TerminalStyle\n", - "\n", - "warnings.filterwarnings(\"ignore\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", - "metadata": {}, - "outputs": [], - "source": [ - "from openbb_terminal.core.session.current_user import get_current_user\n", - "\n", - "user = get_current_user()\n", - "\n", - "cfg.theme = TerminalStyle(\n", - " user.preferences.MPL_STYLE,\n", - " user.preferences.PMF_STYLE,\n", - " user.preferences.RICH_STYLE,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "36091f30", - "metadata": {}, - "outputs": [], - "source": [ - "stylesheet = widgets.html_report_stylesheet()" - ] - }, - { - "cell_type": "markdown", - "id": "807fda4e", - "metadata": {}, - "source": [ - "## Select Ticker" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "intended-sherman", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "# Parameters that will be replaced when calling this notebook\n", - "# Do not leave parameters blank as notebook will not run otherwise\n", - "symbol = \"VTI\"\n", - "report_name = \"Equity Report for VTI\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e1f87190", - "metadata": {}, - "outputs": [], - "source": [ - "ticker = symbol" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a441ddbc-d75b-4a18-84d4-e01b677674d3", - "metadata": {}, - "outputs": [], - "source": [ - "if \".\" in ticker:\n", - " import sys\n", - "\n", - " sys.exit(0)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", - "metadata": {}, - "outputs": [], - "source": [ - "ticker_data = openbb.stocks.load(\n", - " symbol=ticker, start_date=datetime.datetime.now() - datetime.timedelta(days=4 * 30)\n", - ")\n", - "ticker_data = openbb.stocks.process_candle(data=ticker_data)\n", - "\n", - "author = \"OpenBB\"\n", - "report_title = f\"ETF RESEARCH REPORT ON {ticker.upper()}\"\n", - "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", - "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", - "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", - "report_title, report_date, report_time, report_timezone" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2ecfcf81", - "metadata": {}, - "outputs": [], - "source": [ - "# info = openbb.etf.summary(name=ticker)\n", - "# info" - ] - }, - { - "cell_type": "markdown", - "id": "f8a0d747", - "metadata": {}, - "source": [ - "## Data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "39b8e77d", - "metadata": {}, - "outputs": [], - "source": [ - "data = openbb.stocks.load(ticker)\n", - "\n", - "candle_chart = openbb.etf.candle(\n", - " symbol=ticker,\n", - " data=data,\n", - " external_axes=True,\n", - ")\n", - "\n", - "if candle_chart:\n", - " candle_chart = candle_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f751f57c", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd\n", - "\n", - "sectors = openbb.etf.weights(ticker)\n", - "sector_weights_formatted = {}\n", - "for sector_weight in sectors:\n", - " sector_weights_formatted[sector_weight[\"sector\"]] = (\n", - " float(sector_weight[\"weightPercentage\"].strip(\"%\")) / 100\n", - " )\n", - "sector_weights_formatted = dict(sorted(sector_weights_formatted.items()))\n", - "weights_df = pd.DataFrame.from_dict(sector_weights_formatted, orient=\"index\")\n", - "weights_df.columns = [\"Percentage\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "324e2d4b-b2f6-4da3-bac4-ef785ad4e436", - "metadata": {}, - "outputs": [], - "source": [ - "weights_chart = \"\"\n", - "\n", - "if len(weights_df[weights_df[\"Percentage\"] > 10].index) > 1:\n", - " colors = theme.get_colors()\n", - " fig = OpenBBFigure.create_subplots(\n", - " 1,\n", - " 3,\n", - " specs=[[{\"type\": \"domain\"}, {\"type\": \"pie\", \"colspan\": 2}, None]],\n", - " row_heights=[1],\n", - " column_widths=[0.1, 0.8, 0.1],\n", - " )\n", - "\n", - " fig.add_pie(\n", - " labels=weights_df[weights_df[\"Percentage\"] > 10].index,\n", - " values=weights_df[weights_df[\"Percentage\"] > 10][\"Percentage\"],\n", - " textinfo=\"label+percent\",\n", - " hoverinfo=\"label+percent\",\n", - " automargin=True,\n", - " rotation=45,\n", - " row=1,\n", - " col=2,\n", - " )\n", - " fig.update_traces(\n", - " textposition=\"outside\",\n", - " textfont_size=15,\n", - " marker=dict(\n", - " colors=colors,\n", - " line=dict(color=\"#F5EFF3\", width=0.8),\n", - " ),\n", - " )\n", - "\n", - " fig.update_layout(\n", - " margin=dict(t=40, b=20),\n", - " title=dict(\n", - " text=f\"Sector holdings of {ticker}\",\n", - " y=0.98,\n", - " x=0.5,\n", - " xanchor=\"center\",\n", - " yanchor=\"top\",\n", - " ),\n", - " colorway=colors,\n", - " showlegend=False,\n", - " )\n", - "\n", - " weights_chart = fig.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d8bb53c1-147e-4342-af61-0d0a9cc56e59", - "metadata": {}, - "outputs": [], - "source": [ - "holdings = openbb.etf.holdings(ticker)\n", - "holdings" - ] - }, - { - "cell_type": "markdown", - "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", - "metadata": {}, - "source": [ - "## Render the report template to a file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", - "metadata": {}, - "outputs": [], - "source": [ - "body = f\"\"\"\n", - "\n", - "\n", - "\"\"\"\n", - "\n", - "img = (\n", - " str(REPOSITORY_DIRECTORY)\n", - " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", - ")\n", - "floppy_disk_img = (\n", - " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", - ")\n", - "body += widgets.header(\n", - " img,\n", - " floppy_disk_img,\n", - " author,\n", - " report_date,\n", - " report_time,\n", - " report_timezone,\n", - " f\"ETF RESEARCH REPORT: {ticker.upper()}\",\n", - ")\n", - "\n", - "body += widgets.tablinks([\"SUMMARY\"])\n", - "\n", - "htmlcode = widgets.h(3, \"Summary\")\n", - "# htmlcode += widgets.p(info)\n", - "htmlcode += widgets.row([candle_chart])\n", - "\n", - "htmlcode += widgets.p(\"The ETF has the following weights distribution:\")\n", - "\n", - "htmlcode += widgets.row([weights_df.to_html()])\n", - "htmlcode += widgets.row([weights_chart])\n", - "\n", - "htmlcode += widgets.p(\"And has funds in the following assets:\")\n", - "htmlcode += widgets.row([holdings.to_html()])\n", - "\n", - "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", - "\n", - "body += widgets.tab_clickable_and_save_evt()\n", - "\n", - "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", - "\n", - "# to save the results\n", - "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", - " fh.write(report)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "venv", - "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.10.9" - }, - "vscode": { - "interpreter": { - "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "70ba2c8a", + "metadata": {}, + "source": [ + "## Notebook setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "driven-billion", + "metadata": {}, + "outputs": [], + "source": [ + "import warnings\n", + "import numpy as np\n", + "import datetime\n", + "\n", + "from IPython.display import HTML\n", + "\n", + "import openbb_terminal.config_terminal as cfg\n", + "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", + "from openbb_terminal import OpenBBFigure, theme\n", + "from openbb_terminal.helper_classes import TerminalStyle\n", + "\n", + "warnings.filterwarnings(\"ignore\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "473e83c7", + "metadata": {}, + "outputs": [], + "source": [ + "# Suppressing sdk logs\n", + "cfg.change_logging_suppress(new_value=True)\n", + "\n", + "# Import the OpenBB SDK\n", + "from openbb_terminal.sdk import openbb, widgets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", + "metadata": {}, + "outputs": [], + "source": [ + "from openbb_terminal.core.session.current_user import get_current_user\n", + "\n", + "user = get_current_user()\n", + "\n", + "cfg.theme = TerminalStyle(\n", + " user.preferences.MPL_STYLE,\n", + " user.preferences.PMF_STYLE,\n", + " user.preferences.RICH_STYLE,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36091f30", + "metadata": {}, + "outputs": [], + "source": [ + "stylesheet = widgets.html_report_stylesheet()" + ] + }, + { + "cell_type": "markdown", + "id": "807fda4e", + "metadata": {}, + "source": [ + "## Select Ticker" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "intended-sherman", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "# Parameters that will be replaced when calling this notebook\n", + "# Do not leave parameters blank as notebook will not run otherwise\n", + "symbol = \"VTI\"\n", + "report_name = \"Equity Report for VTI\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1f87190", + "metadata": {}, + "outputs": [], + "source": [ + "ticker = symbol" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a441ddbc-d75b-4a18-84d4-e01b677674d3", + "metadata": {}, + "outputs": [], + "source": [ + "if \".\" in ticker:\n", + " import sys\n", + "\n", + " sys.exit(0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", + "metadata": {}, + "outputs": [], + "source": [ + "ticker_data = openbb.stocks.load(\n", + " symbol=ticker, start_date=datetime.datetime.now() - datetime.timedelta(days=4 * 30)\n", + ")\n", + "ticker_data = openbb.stocks.process_candle(data=ticker_data)\n", + "\n", + "author = \"OpenBB\"\n", + "report_title = f\"ETF RESEARCH REPORT ON {ticker.upper()}\"\n", + "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", + "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", + "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", + "report_title, report_date, report_time, report_timezone" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ecfcf81", + "metadata": {}, + "outputs": [], + "source": [ + "# info = openbb.etf.summary(name=ticker)\n", + "# info" + ] + }, + { + "cell_type": "markdown", + "id": "f8a0d747", + "metadata": {}, + "source": [ + "## Data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39b8e77d", + "metadata": {}, + "outputs": [], + "source": [ + "data = openbb.stocks.load(ticker)\n", + "\n", + "candle_chart = openbb.etf.candle(\n", + " symbol=ticker,\n", + " data=data,\n", + " external_axes=True,\n", + ")\n", + "\n", + "if candle_chart:\n", + " candle_chart = candle_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f751f57c", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "sectors = openbb.etf.weights(ticker)\n", + "sector_weights_formatted = {}\n", + "for sector_weight in sectors:\n", + " sector_weights_formatted[sector_weight[\"sector\"]] = (\n", + " float(sector_weight[\"weightPercentage\"].strip(\"%\")) / 100\n", + " )\n", + "sector_weights_formatted = dict(sorted(sector_weights_formatted.items()))\n", + "weights_df = pd.DataFrame.from_dict(sector_weights_formatted, orient=\"index\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "324e2d4b-b2f6-4da3-bac4-ef785ad4e436", + "metadata": {}, + "outputs": [], + "source": [ + "weights_chart = \"\"\n", + "\n", + "if \"Percentage\" in weights_df.columns:\n", + " weights_df.columns = [\"Percentage\"]\n", + "\n", + "if \"Percentage\" in weights_df.columns and len(weights_df[weights_df[\"Percentage\"] > 10].index) > 1:\n", + " colors = theme.get_colors()\n", + " fig = OpenBBFigure.create_subplots(\n", + " 1,\n", + " 3,\n", + " specs=[[{\"type\": \"domain\"}, {\"type\": \"pie\", \"colspan\": 2}, None]],\n", + " row_heights=[1],\n", + " column_widths=[0.1, 0.8, 0.1],\n", + " )\n", + "\n", + " fig.add_pie(\n", + " labels=weights_df[weights_df[\"Percentage\"] > 10].index,\n", + " values=weights_df[weights_df[\"Percentage\"] > 10][\"Percentage\"],\n", + " textinfo=\"label+percent\",\n", + " hoverinfo=\"label+percent\",\n", + " automargin=True,\n", + " rotation=45,\n", + " row=1,\n", + " col=2,\n", + " )\n", + " fig.update_traces(\n", + " textposition=\"outside\",\n", + " textfont_size=15,\n", + " marker=dict(\n", + " colors=colors,\n", + " line=dict(color=\"#F5EFF3\", width=0.8),\n", + " ),\n", + " )\n", + "\n", + " fig.update_layout(\n", + " margin=dict(t=40, b=20),\n", + " title=dict(\n", + " text=f\"Sector holdings of {ticker}\",\n", + " y=0.98,\n", + " x=0.5,\n", + " xanchor=\"center\",\n", + " yanchor=\"top\",\n", + " ),\n", + " colorway=colors,\n", + " showlegend=False,\n", + " )\n", + "\n", + " weights_chart = fig.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8bb53c1-147e-4342-af61-0d0a9cc56e59", + "metadata": {}, + "outputs": [], + "source": [ + "holdings = openbb.etf.holdings(ticker)\n", + "holdings" + ] + }, + { + "cell_type": "markdown", + "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", + "metadata": {}, + "source": [ + "## Render the report template to a file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", + "metadata": {}, + "outputs": [], + "source": [ + "body = f\"\"\"\n", + "\n", + "\n", + "\"\"\"\n", + "\n", + "img = (\n", + " str(REPOSITORY_DIRECTORY)\n", + " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", + ")\n", + "floppy_disk_img = (\n", + " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", + ")\n", + "body += widgets.header(\n", + " img,\n", + " floppy_disk_img,\n", + " author,\n", + " report_date,\n", + " report_time,\n", + " report_timezone,\n", + " f\"ETF RESEARCH REPORT: {ticker.upper()}\",\n", + ")\n", + "\n", + "body += widgets.tablinks([\"SUMMARY\"])\n", + "\n", + "htmlcode = widgets.h(3, \"Summary\")\n", + "# htmlcode += widgets.p(info)\n", + "htmlcode += widgets.row([candle_chart])\n", + "\n", + "htmlcode += widgets.p(\"The ETF has the following weights distribution:\")\n", + "\n", + "htmlcode += widgets.row([weights_df.to_html()])\n", + "htmlcode += widgets.row([weights_chart])\n", + "\n", + "htmlcode += widgets.p(\"And has funds in the following assets:\")\n", + "htmlcode += widgets.row([holdings.to_html()])\n", + "\n", + "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", + "\n", + "body += widgets.tab_clickable_and_save_evt()\n", + "\n", + "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", + "\n", + "# to save the results\n", + "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", + " fh.write(report)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "venv", + "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.9.13" + }, + "vscode": { + "interpreter": { + "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/openbb_terminal/reports/templates/forecast.ipynb b/openbb_terminal/reports/templates/forecast.ipynb index e9846c1b68a..23aa6f20278 100644 --- a/openbb_terminal/reports/templates/forecast.ipynb +++ b/openbb_terminal/reports/templates/forecast.ipynb @@ -1,311 +1,321 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "70ba2c8a", - "metadata": {}, - "source": [ - "## Notebook setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "driven-billion", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import io\n", - "import warnings\n", - "import datetime\n", - "import numpy as np\n", - "import base64\n", - "\n", - "from IPython.display import HTML\n", - "\n", - "import openbb_terminal.config_terminal as cfg\n", - "from openbb_terminal.reports import widget_helpers as widgets\n", - "from openbb_terminal.sdk import openbb\n", - "from openbb_terminal.helper_classes import TerminalStyle\n", - "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", - "\n", - "from openbb_terminal import OpenBBFigure\n", - "\n", - "\n", - "warnings.filterwarnings(\"ignore\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", - "metadata": {}, - "outputs": [], - "source": [ - "from openbb_terminal.core.session.current_user import get_current_user\n", - "\n", - "user = get_current_user()\n", - "\n", - "cfg.theme = TerminalStyle(\n", - " user.preferences.MPL_STYLE,\n", - " user.preferences.PMF_STYLE,\n", - " user.preferences.RICH_STYLE,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f6d22d4f", - "metadata": {}, - "outputs": [], - "source": [ - "stylesheet = widgets.html_report_stylesheet()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "9c3ae3e3-2b91-43a6-aa44-7b10986fd369", - "metadata": {}, - "outputs": [], - "source": [ - "def get_html(func, title, *args, **kwargs):\n", - " kwargs[\"external_axes\"] = True\n", - " local_fig = func(*args, **kwargs)\n", - " # kwargs[\"chart\"] = True\n", - " if title:\n", - " local_fig.set_title(title)\n", - " local_fig.set_xaxis_title(\"Lag\")\n", - " local_fig.set_yaxis_title(\"Autocorrelation\")\n", - "\n", - " return local_fig.to_html()" - ] - }, - { - "cell_type": "markdown", - "id": "807fda4e", - "metadata": {}, - "source": [ - "## Select Ticker" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "intended-sherman", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "# Parameters that will be replaced when calling this notebook\n", - "# Do not leave parameters blank as notebook will not run otherwise\n", - "symbol = \"VTI\"\n", - "report_name = \"Forecast Report for VTI\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e1f87190", - "metadata": {}, - "outputs": [], - "source": [ - "ticker = symbol" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a441ddbc-d75b-4a18-84d4-e01b677674d3", - "metadata": {}, - "outputs": [], - "source": [ - "if \".\" in ticker:\n", - " import sys\n", - "\n", - " sys.exit(0)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", - "metadata": {}, - "outputs": [], - "source": [ - "ticker_data = openbb.stocks.load(\n", - " symbol=ticker, start_date=datetime.datetime.now() - datetime.timedelta(days=400)\n", - ")\n", - "\n", - "author = \"OpenBB\"\n", - "report_title = f\"FORECAST RESEARCH REPORT ON {ticker.upper()}\"\n", - "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", - "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", - "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", - "report_title, report_date, report_time, report_timezone" - ] - }, - { - "cell_type": "markdown", - "id": "f8a0d747", - "metadata": {}, - "source": [ - "## Data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cb31e9ee-e7ae-4e1b-89b4-bb6f571cfdfa", - "metadata": {}, - "outputs": [], - "source": [ - "local_fig = openbb.stocks.candle(ticker, ticker_data, external_axes=True)\n", - "plot_chart = local_fig.to_html()\n", - "\n", - "# Prepare date for forecast\n", - "ticker_data = ticker_data.reset_index()\n", - "ticker_data.columns = [x.lower() for x in ticker_data.columns]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d8bb53c1-147e-4342-af61-0d0a9cc56e59", - "metadata": {}, - "outputs": [], - "source": [ - "corr_chart = get_html(openbb.forecast.corr_chart, None, ticker_data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "74b914a1-ed32-4a17-a943-7879bc8f00df", - "metadata": {}, - "outputs": [], - "source": [ - "season_chart = get_html(openbb.forecast.season_chart, \"Seasonality Data\", ticker_data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "53568c9b-aa06-4ba0-ad86-ede6732e3187", - "metadata": {}, - "outputs": [], - "source": [ - "expo_chart = get_html(openbb.forecast.expo_chart, None, ticker_data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0a919f67-ac9f-4b75-a3b3-102e0fbe5862", - "metadata": {}, - "outputs": [], - "source": [ - "rnn_chart = get_html(openbb.forecast.rnn_chart, None, ticker_data)" - ] - }, - { - "cell_type": "markdown", - "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", - "metadata": {}, - "source": [ - "## Render the report template to a file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", - "metadata": {}, - "outputs": [], - "source": [ - "body = f\"\"\"\n", - "\n", - "\n", - "\"\"\"\n", - "\n", - "\n", - "img = (\n", - " str(REPOSITORY_DIRECTORY)\n", - " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", - ")\n", - "floppy_disk_img = (\n", - " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", - ")\n", - "body += widgets.header(\n", - " img,\n", - " floppy_disk_img,\n", - " author,\n", - " report_date,\n", - " report_time,\n", - " report_timezone,\n", - " f\"FORECAST REPORT ON: {ticker.upper()}\",\n", - ")\n", - "\n", - "body += widgets.tablinks([\"SUMMARY\"])\n", - "\n", - "htmlcode = widgets.h(3, \"Summary\")\n", - "htmlcode += widgets.row([widgets.h(3, \"Understand the data\")])\n", - "htmlcode += widgets.row([ticker_data.head(10).to_html()])\n", - "htmlcode += widgets.row([plot_chart])\n", - "htmlcode += widgets.row([widgets.h(3, \"Analyzing the data\")])\n", - "htmlcode += widgets.row([corr_chart])\n", - "htmlcode += widgets.row([season_chart])\n", - "htmlcode += widgets.row([widgets.h(3, \"Creating predictions\")])\n", - "htmlcode += widgets.row([expo_chart])\n", - "htmlcode += widgets.row([rnn_chart])\n", - "\n", - "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", - "body += widgets.tab_clickable_and_save_evt()\n", - "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", - "\n", - "# to save the results\n", - "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", - " fh.write(report)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "venv", - "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.10.8" - }, - "vscode": { - "interpreter": { - "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "70ba2c8a", + "metadata": {}, + "source": [ + "## Notebook setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "driven-billion", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import io\n", + "import warnings\n", + "import datetime\n", + "import numpy as np\n", + "import base64\n", + "\n", + "from IPython.display import HTML\n", + "\n", + "import openbb_terminal.config_terminal as cfg\n", + "from openbb_terminal.helper_classes import TerminalStyle\n", + "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", + "from openbb_terminal import OpenBBFigure\n", + "\n", + "warnings.filterwarnings(\"ignore\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "632bdfbc", + "metadata": {}, + "outputs": [], + "source": [ + "# Suppressing sdk logs\n", + "cfg.change_logging_suppress(new_value=True)\n", + "\n", + "# Import the OpenBB SDK\n", + "from openbb_terminal.sdk import openbb, widgets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", + "metadata": {}, + "outputs": [], + "source": [ + "from openbb_terminal.core.session.current_user import get_current_user\n", + "\n", + "user = get_current_user()\n", + "\n", + "cfg.theme = TerminalStyle(\n", + " user.preferences.MPL_STYLE,\n", + " user.preferences.PMF_STYLE,\n", + " user.preferences.RICH_STYLE,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6d22d4f", + "metadata": {}, + "outputs": [], + "source": [ + "stylesheet = widgets.html_report_stylesheet()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9c3ae3e3-2b91-43a6-aa44-7b10986fd369", + "metadata": {}, + "outputs": [], + "source": [ + "def get_html(func, title, *args, **kwargs):\n", + " kwargs[\"external_axes\"] = True\n", + " local_fig = func(*args, **kwargs)\n", + " # kwargs[\"chart\"] = True\n", + " if title:\n", + " local_fig.set_title(title)\n", + " local_fig.set_xaxis_title(\"Lag\")\n", + " local_fig.set_yaxis_title(\"Autocorrelation\")\n", + "\n", + " return local_fig.to_html()" + ] + }, + { + "cell_type": "markdown", + "id": "807fda4e", + "metadata": {}, + "source": [ + "## Select Ticker" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "intended-sherman", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "# Parameters that will be replaced when calling this notebook\n", + "# Do not leave parameters blank as notebook will not run otherwise\n", + "symbol = \"VTI\"\n", + "report_name = \"Forecast Report for VTI\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1f87190", + "metadata": {}, + "outputs": [], + "source": [ + "ticker = symbol" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a441ddbc-d75b-4a18-84d4-e01b677674d3", + "metadata": {}, + "outputs": [], + "source": [ + "if \".\" in ticker:\n", + " import sys\n", + "\n", + " sys.exit(0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", + "metadata": {}, + "outputs": [], + "source": [ + "ticker_data = openbb.stocks.load(\n", + " symbol=ticker, start_date=datetime.datetime.now() - datetime.timedelta(days=400)\n", + ")\n", + "\n", + "author = \"OpenBB\"\n", + "report_title = f\"FORECAST RESEARCH REPORT ON {ticker.upper()}\"\n", + "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", + "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", + "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", + "report_title, report_date, report_time, report_timezone" + ] + }, + { + "cell_type": "markdown", + "id": "f8a0d747", + "metadata": {}, + "source": [ + "## Data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb31e9ee-e7ae-4e1b-89b4-bb6f571cfdfa", + "metadata": {}, + "outputs": [], + "source": [ + "local_fig = openbb.stocks.candle(ticker, ticker_data, external_axes=True)\n", + "plot_chart = local_fig.to_html()\n", + "\n", + "# Prepare date for forecast\n", + "ticker_data = ticker_data.reset_index()\n", + "ticker_data.columns = [x.lower() for x in ticker_data.columns]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8bb53c1-147e-4342-af61-0d0a9cc56e59", + "metadata": {}, + "outputs": [], + "source": [ + "corr_chart = get_html(openbb.forecast.corr_chart, None, ticker_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "74b914a1-ed32-4a17-a943-7879bc8f00df", + "metadata": {}, + "outputs": [], + "source": [ + "season_chart = get_html(openbb.forecast.season_chart, \"Seasonality Data\", ticker_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "53568c9b-aa06-4ba0-ad86-ede6732e3187", + "metadata": {}, + "outputs": [], + "source": [ + "expo_chart = get_html(openbb.forecast.expo_chart, None, ticker_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a919f67-ac9f-4b75-a3b3-102e0fbe5862", + "metadata": {}, + "outputs": [], + "source": [ + "rnn_chart = get_html(openbb.forecast.rnn_chart, None, ticker_data)" + ] + }, + { + "cell_type": "markdown", + "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", + "metadata": {}, + "source": [ + "## Render the report template to a file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", + "metadata": {}, + "outputs": [], + "source": [ + "body = f\"\"\"\n", + "\n", + "\n", + "\"\"\"\n", + "\n", + "\n", + "img = (\n", + " str(REPOSITORY_DIRECTORY)\n", + " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", + ")\n", + "floppy_disk_img = (\n", + " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", + ")\n", + "body += widgets.header(\n", + " img,\n", + " floppy_disk_img,\n", + " author,\n", + " report_date,\n", + " report_time,\n", + " report_timezone,\n", + " f\"FORECAST REPORT ON: {ticker.upper()}\",\n", + ")\n", + "\n", + "body += widgets.tablinks([\"SUMMARY\"])\n", + "\n", + "htmlcode = widgets.h(3, \"Summary\")\n", + "htmlcode += widgets.row([widgets.h(3, \"Understand the data\")])\n", + "htmlcode += widgets.row([ticker_data.head(10).to_html()])\n", + "htmlcode += widgets.row([plot_chart])\n", + "htmlcode += widgets.row([widgets.h(3, \"Analyzing the data\")])\n", + "htmlcode += widgets.row([corr_chart])\n", + "htmlcode += widgets.row([season_chart])\n", + "htmlcode += widgets.row([widgets.h(3, \"Creating predictions\")])\n", + "htmlcode += widgets.row([expo_chart])\n", + "htmlcode += widgets.row([rnn_chart])\n", + "\n", + "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", + "body += widgets.tab_clickable_and_save_evt()\n", + "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", + "\n", + "# to save the results\n", + "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", + " fh.write(report)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "venv", + "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.10.8" + }, + "vscode": { + "interpreter": { + "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/openbb_terminal/reports/templates/forex.ipynb b/openbb_terminal/reports/templates/forex.ipynb index e8eb28a56ae..53a59328b52 100644 --- a/openbb_terminal/reports/templates/forex.ipynb +++ b/openbb_terminal/reports/templates/forex.ipynb @@ -1,652 +1,664 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "70ba2c8a", - "metadata": {}, - "source": [ - "## Notebook setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "driven-billion", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import io\n", - "import warnings\n", - "import datetime\n", - "import numpy as np\n", - "import base64\n", - "import pandas as pd\n", - "\n", - "from IPython.display import HTML\n", - "\n", - "import openbb_terminal.config_terminal as cfg\n", - "from openbb_terminal.sdk import widgets\n", - "from openbb_terminal.sdk import openbb\n", - "from openbb_terminal.helper_classes import TerminalStyle\n", - "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", - "from openbb_terminal import OpenBBFigure\n", - "\n", - "warnings.filterwarnings(\"ignore\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", - "metadata": {}, - "outputs": [], - "source": [ - "from openbb_terminal.core.session.current_user import get_current_user\n", - "\n", - "user = get_current_user()\n", - "\n", - "cfg.theme = TerminalStyle(\n", - " user.preferences.MPL_STYLE,\n", - " user.preferences.PMF_STYLE,\n", - " user.preferences.RICH_STYLE,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4b002bfd", - "metadata": {}, - "outputs": [], - "source": [ - "stylesheet = widgets.html_report_stylesheet()" - ] - }, - { - "cell_type": "markdown", - "id": "807fda4e", - "metadata": {}, - "source": [ - "## Select Ticker" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "intended-sherman", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "# Parameters that will be replaced when calling this notebook\n", - "# Do not leave parameters blank as notebook will not run otherwise\n", - "symbol = \"EURUSD\"\n", - "report_name = \"Forex Report for EURUSD\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "613cea1d", - "metadata": {}, - "outputs": [], - "source": [ - "ticker = symbol" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d4897334", - "metadata": {}, - "outputs": [], - "source": [ - "author = \"\"\n", - "report_title = f\"INVESTMENT RESEARCH REPORT ON {ticker.upper()}\"\n", - "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", - "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", - "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", - "report_title, report_date, report_time, report_timezone" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "07d09ce8", - "metadata": {}, - "outputs": [], - "source": [ - "from_symbol = ticker[:3]\n", - "to_symbol = ticker[3:]\n", - "last_year = datetime.datetime.now() - datetime.timedelta(days=365)\n", - "\n", - "ticker_data = openbb.forex.load(\n", - " from_symbol=from_symbol,\n", - " to_symbol=to_symbol,\n", - " start_date=last_year.strftime(\"%Y-%m-%d\"),\n", - " interval=\"1day\",\n", - " resolution=\"d\",\n", - ")\n", - "\n", - "# 1 year historical data\n", - "ticker_data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "88af0fbe", - "metadata": {}, - "outputs": [], - "source": [ - "last_year = datetime.datetime.now() - datetime.timedelta(days=365)\n", - "\n", - "ticker_data_interval_1month = openbb.forex.load(\n", - " from_symbol=from_symbol,\n", - " to_symbol=to_symbol,\n", - " start_date=last_year.strftime(\"%Y-%m-%d\"),\n", - " interval=\"1month\",\n", - " resolution=\"d\",\n", - ")\n", - "ticker_data_interval_1month = ticker_data_interval_1month.drop(columns=\"Volume\")\n", - "ticker_data_interval_1month" - ] - }, - { - "cell_type": "markdown", - "id": "f8a0d747", - "metadata": {}, - "source": [ - "## Data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "709a2a7e", - "metadata": {}, - "outputs": [], - "source": [ - "# candle\n", - "\n", - "candle = openbb.forex.candle(\n", - " data=ticker_data,\n", - " to_symbol=to_symbol,\n", - " from_symbol=from_symbol,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "05f54519", - "metadata": {}, - "outputs": [], - "source": [ - "# candle graph with moving averages 7/14 and 30/60\n", - "candle_ma_7_14 = openbb.forex.candle(\n", - " data=ticker_data,\n", - " to_symbol=to_symbol,\n", - " from_symbol=from_symbol,\n", - " ma=[7, 14],\n", - " external_axes=True,\n", - ").to_html()\n", - "\n", - "candle_ma_30_60 = openbb.forex.candle(\n", - " data=ticker_data,\n", - " to_symbol=to_symbol,\n", - " from_symbol=from_symbol,\n", - " ma=[30, 60],\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fc17a601", - "metadata": {}, - "outputs": [], - "source": [ - "fwd = openbb.forex.fwd(\n", - " to_symbol=to_symbol,\n", - " from_symbol=from_symbol,\n", - ")\n", - "\n", - "# forward rates\n", - "fwd" - ] - }, - { - "cell_type": "markdown", - "id": "6c852082", - "metadata": {}, - "source": [ - "# Technical analysis" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4ff6345d", - "metadata": {}, - "outputs": [], - "source": [ - "# simple moving average\n", - "ticker_data.index.names = [\"date\"]\n", - "\n", - "sma = openbb.ta.ma_chart(\n", - " data=ticker_data[\"Close\"],\n", - " ma_type=\"SMA\",\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5d5089fa", - "metadata": {}, - "outputs": [], - "source": [ - "# exponential moving average\n", - "ema = openbb.ta.ma_chart(\n", - " data=ticker_data[\"Close\"],\n", - " ma_type=\"EMA\",\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5facfbf4", - "metadata": {}, - "outputs": [], - "source": [ - "# zero lag exponential moving average\n", - "\n", - "zlma = openbb.ta.ma_chart(\n", - " data=ticker_data[\"Close\"],\n", - " ma_type=\"ZLMA\",\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "df54f7ad", - "metadata": {}, - "outputs": [], - "source": [ - "# commodity channel index\n", - "\n", - "cci = openbb.ta.cci_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f53469eb", - "metadata": {}, - "outputs": [], - "source": [ - "# moving average convergence/divergence\n", - "\n", - "macd = openbb.ta.macd_chart(\n", - " data=ticker_data[\"Adj Close\"],\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dd79e6b6", - "metadata": {}, - "outputs": [], - "source": [ - "# fisher transform\n", - "\n", - "fisher = openbb.ta.fisher_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b699e61f", - "metadata": {}, - "outputs": [], - "source": [ - "# aroon indicator\n", - "\n", - "aroon = openbb.ta.aroon_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "79401027", - "metadata": {}, - "outputs": [], - "source": [ - "# bollinger bands\n", - "\n", - "bbands = openbb.ta.bbands_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0b5e2949", - "metadata": {}, - "outputs": [], - "source": [ - "# fibonacci retracement\n", - "\n", - "fib = openbb.ta.fib_chart(\n", - " data=ticker_data,\n", - " symbol=ticker,\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "markdown", - "id": "e6f6ce8a", - "metadata": {}, - "source": [ - "# Quantitative Analysis" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e77b373b", - "metadata": {}, - "outputs": [], - "source": [ - "# summary\n", - "\n", - "summary = openbb.qa.summary(data=ticker_data)\n", - "summary" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3ecfc93e", - "metadata": {}, - "outputs": [], - "source": [ - "# normality statistics and tests\n", - "\n", - "normality = openbb.qa.normality(\n", - " data=ticker_data[\"Close\"],\n", - ")\n", - "normality" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "66a7dccc", - "metadata": {}, - "outputs": [], - "source": [ - "# rolling mean and std deviation of prices\n", - "\n", - "rolling = openbb.qa.rolling_chart(\n", - " symbol=ticker,\n", - " data=ticker_data,\n", - " target=\"Close\",\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d6b43dd7", - "metadata": {}, - "outputs": [], - "source": [ - "# rolling kurtosis of distribution of prices\n", - "\n", - "kurtosis = openbb.qa.kurtosis_chart(\n", - " symbol=ticker,\n", - " data=ticker_data,\n", - " target=\"Close\",\n", - " external_axes=True,\n", - ").to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fc31624a", - "metadata": {}, - "outputs": [], - "source": [ - "# latest news\n", - "\n", - "news = openbb.news(term=ticker).head(10)\n", - "\n", - "news[\"published\"] = pd.to_datetime(news[\"published\"])\n", - "news[\"published\"] = pd.to_datetime(\n", - " news[\"published\"], format=\"%d/%m/%y %H:%M:%S\"\n", - ").dt.strftime(\"%Y-%m-%d\")\n", - "news = news[[\"published\", \"title\", \"link\"]]\n", - "\n", - "news[\"link\"] = news[\"link\"].apply(lambda x: f'{x}')\n", - "news = news.set_index(\"published\")\n", - "news.sort_index()\n", - "news" - ] - }, - { - "cell_type": "markdown", - "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", - "metadata": {}, - "source": [ - "## Render the report template to a file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", - "metadata": {}, - "outputs": [], - "source": [ - "body = f\"\"\"\n", - "\n", - "\n", - "\"\"\"\n", - "\n", - "\n", - "img = (\n", - " str(REPOSITORY_DIRECTORY)\n", - " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", - ")\n", - "floppy_disk_img = (\n", - " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", - ")\n", - "body += widgets.header(\n", - " img,\n", - " floppy_disk_img,\n", - " author,\n", - " report_date,\n", - " report_time,\n", - " report_timezone,\n", - " f\"INVESTMENT RESEARCH REPORT: {ticker}\",\n", - ")\n", - "\n", - "body += widgets.tablinks(\n", - " [\n", - " \"SUMMARY\",\n", - " \"Overview\",\n", - " \"Technical Analysis\",\n", - " \"Quantitative Analysis\",\n", - " ]\n", - ")\n", - "\n", - "comment = \"Every analysis displayed considered every day data YTD\"\n", - "\n", - "\n", - "# TODO: add KPIs\n", - "\n", - "htmlcode = \"\"\n", - "\n", - "# htmlcode += widgets.h(3, \"KPIs\")\n", - "# htmlcode += widgets.kpi(\n", - "# [30, 70],\n", - "# [\"RSI level is oversold\", \"RSI level is normal\", \"RSI level is overbought\"],\n", - "# 999,\n", - "# )\n", - "# htmlcode += widgets.kpi(\n", - "# [0],\n", - "# [\n", - "# \"The sum of last 10 insider trading (in millions) was negative\",\n", - "# \"The sum of last 10 insider trading (in millions) was positive\",\n", - "# ],\n", - "# 999,\n", - "# )\n", - "# htmlcode += widgets.kpi(\n", - "# [-0.1, 0.1],\n", - "# [\n", - "# \"Last FinBrain sentiment is bearish\",\n", - "# \"Last FinBrain sentiment is neutral\",\n", - "# \"Last FinBrain sentiment is bullish\",\n", - "# ],\n", - "# 999,\n", - "# )\n", - "\n", - "# Summary tab\n", - "htmlcode += widgets.row([widgets.h(3, \"Latest news\") + news.to_html(escape=False)])\n", - "htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, \"One year historical data for 1st day each month\")\n", - " + ticker_data_interval_1month.to_html()\n", - " ]\n", - ")\n", - "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", - "\n", - "# Overview tab\n", - "htmlcode = \"\"\n", - "htmlcode = widgets.row([widgets.h(3, \"Candlestick chart\")])\n", - "htmlcode += widgets.row([candle])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Candlestick chart with moving averages 7 and 14\")]\n", - ")\n", - "htmlcode += widgets.row([candle_ma_7_14])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Candlestick chart with moving averages 30 and 60\")]\n", - ")\n", - "htmlcode += widgets.row([candle_ma_30_60])\n", - "htmlcode += widgets.row([widgets.h(3, \"Forward rates\")])\n", - "htmlcode += widgets.row([fwd.to_html()])\n", - "body += widgets.add_tab(\"Overview\", htmlcode, True, comment)\n", - "\n", - "# Technical Analysis tab\n", - "htmlcode = widgets.row([widgets.h(3, \"Simple moving average\")])\n", - "htmlcode += widgets.row([sma])\n", - "htmlcode += widgets.row([widgets.h(3, \"Exponential moving average\")])\n", - "htmlcode += widgets.row([ema])\n", - "htmlcode += widgets.row([widgets.h(3, \"Zero lag exponential moving average\")])\n", - "htmlcode += widgets.row([zlma])\n", - "htmlcode += widgets.row([widgets.h(3, \"Commodity channel index\")])\n", - "htmlcode += widgets.row([cci])\n", - "htmlcode += widgets.row([widgets.h(3, \"Moving average convergence/divergence\")])\n", - "htmlcode += widgets.row([macd])\n", - "htmlcode += widgets.row([widgets.h(3, \"Fisher transform\")])\n", - "htmlcode += widgets.row([fisher])\n", - "htmlcode += widgets.row([widgets.h(3, \"Aroon indicator\")])\n", - "htmlcode += widgets.row([aroon])\n", - "htmlcode += widgets.row([widgets.h(3, \"Bollinger bands\")])\n", - "htmlcode += widgets.row([bbands])\n", - "htmlcode += widgets.row([widgets.h(3, \"Fibonacci retracement\")])\n", - "htmlcode += widgets.row([fib])\n", - "body += widgets.add_tab(\"Technical Analysis\", htmlcode, True, comment)\n", - "\n", - "# Quantitative Analysis tab\n", - "htmlcode = widgets.row([widgets.h(3, \"Summary\") + summary.to_html()])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Normality statistics and tests\") + normality.to_html()]\n", - ")\n", - "htmlcode += widgets.row([widgets.h(3, \"Rolling mean and std deviation of prices\")])\n", - "htmlcode += widgets.row([rolling])\n", - "htmlcode += widgets.row([widgets.h(3, \"Rolling kurtosis of distribution of prices\")])\n", - "htmlcode += widgets.row([kurtosis])\n", - "body += widgets.add_tab(\"Quantitative Analysis\", htmlcode, True, comment)\n", - "\n", - "body += widgets.tab_clickable_and_save_evt()\n", - "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", - "\n", - "# # to save the results\n", - "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", - " fh.write(report)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "venv", - "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.10.8" - }, - "vscode": { - "interpreter": { - "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "70ba2c8a", + "metadata": {}, + "source": [ + "## Notebook setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "driven-billion", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import io\n", + "import warnings\n", + "import datetime\n", + "import numpy as np\n", + "import base64\n", + "import pandas as pd\n", + "\n", + "from IPython.display import HTML\n", + "\n", + "import openbb_terminal.config_terminal as cfg\n", + "from openbb_terminal.helper_classes import TerminalStyle\n", + "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", + "from openbb_terminal import OpenBBFigure\n", + "\n", + "warnings.filterwarnings(\"ignore\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03a286e7", + "metadata": {}, + "outputs": [], + "source": [ + "# Suppressing sdk logs\n", + "cfg.change_logging_suppress(new_value=True)\n", + "\n", + "# Import the OpenBB SDK\n", + "from openbb_terminal.sdk import openbb, widgets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", + "metadata": {}, + "outputs": [], + "source": [ + "from openbb_terminal.core.session.current_user import get_current_user\n", + "\n", + "user = get_current_user()\n", + "\n", + "cfg.theme = TerminalStyle(\n", + " user.preferences.MPL_STYLE,\n", + " user.preferences.PMF_STYLE,\n", + " user.preferences.RICH_STYLE,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b002bfd", + "metadata": {}, + "outputs": [], + "source": [ + "stylesheet = widgets.html_report_stylesheet()" + ] + }, + { + "cell_type": "markdown", + "id": "807fda4e", + "metadata": {}, + "source": [ + "## Select Ticker" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "intended-sherman", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "# Parameters that will be replaced when calling this notebook\n", + "# Do not leave parameters blank as notebook will not run otherwise\n", + "symbol = \"EURUSD\"\n", + "report_name = \"Forex Report for EURUSD\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "613cea1d", + "metadata": {}, + "outputs": [], + "source": [ + "ticker = symbol" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d4897334", + "metadata": {}, + "outputs": [], + "source": [ + "author = \"\"\n", + "report_title = f\"INVESTMENT RESEARCH REPORT ON {ticker.upper()}\"\n", + "report_date = datetime.datetime.now().strftime(\"%d %B, %Y\")\n", + "report_time = datetime.datetime.now().strftime(\"%H:%M\")\n", + "report_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo\n", + "report_title, report_date, report_time, report_timezone" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "07d09ce8", + "metadata": {}, + "outputs": [], + "source": [ + "from_symbol = ticker[:3]\n", + "to_symbol = ticker[3:]\n", + "last_year = datetime.datetime.now() - datetime.timedelta(days=365)\n", + "\n", + "ticker_data = openbb.forex.load(\n", + " from_symbol=from_symbol,\n", + " to_symbol=to_symbol,\n", + " start_date=last_year.strftime(\"%Y-%m-%d\"),\n", + " interval=\"1day\",\n", + " resolution=\"d\",\n", + ")\n", + "\n", + "# 1 year historical data\n", + "ticker_data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "88af0fbe", + "metadata": {}, + "outputs": [], + "source": [ + "last_year = datetime.datetime.now() - datetime.timedelta(days=365)\n", + "\n", + "ticker_data_interval_1month = openbb.forex.load(\n", + " from_symbol=from_symbol,\n", + " to_symbol=to_symbol,\n", + " start_date=last_year.strftime(\"%Y-%m-%d\"),\n", + " interval=\"1month\",\n", + " resolution=\"d\",\n", + ")\n", + "ticker_data_interval_1month = ticker_data_interval_1month.drop(columns=\"Volume\")\n", + "ticker_data_interval_1month" + ] + }, + { + "cell_type": "markdown", + "id": "f8a0d747", + "metadata": {}, + "source": [ + "## Data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "709a2a7e", + "metadata": {}, + "outputs": [], + "source": [ + "# candle\n", + "\n", + "candle = openbb.forex.candle(\n", + " data=ticker_data,\n", + " to_symbol=to_symbol,\n", + " from_symbol=from_symbol,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05f54519", + "metadata": {}, + "outputs": [], + "source": [ + "# candle graph with moving averages 7/14 and 30/60\n", + "candle_ma_7_14 = openbb.forex.candle(\n", + " data=ticker_data,\n", + " to_symbol=to_symbol,\n", + " from_symbol=from_symbol,\n", + " ma=[7, 14],\n", + " external_axes=True,\n", + ").to_html()\n", + "\n", + "candle_ma_30_60 = openbb.forex.candle(\n", + " data=ticker_data,\n", + " to_symbol=to_symbol,\n", + " from_symbol=from_symbol,\n", + " ma=[30, 60],\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fc17a601", + "metadata": {}, + "outputs": [], + "source": [ + "fwd = openbb.forex.fwd(\n", + " to_symbol=to_symbol,\n", + " from_symbol=from_symbol,\n", + ")\n", + "\n", + "# forward rates\n", + "fwd" + ] + }, + { + "cell_type": "markdown", + "id": "6c852082", + "metadata": {}, + "source": [ + "# Technical analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ff6345d", + "metadata": {}, + "outputs": [], + "source": [ + "# simple moving average\n", + "ticker_data.index.names = [\"date\"]\n", + "\n", + "sma = openbb.ta.ma_chart(\n", + " data=ticker_data[\"Close\"],\n", + " ma_type=\"SMA\",\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d5089fa", + "metadata": {}, + "outputs": [], + "source": [ + "# exponential moving average\n", + "ema = openbb.ta.ma_chart(\n", + " data=ticker_data[\"Close\"],\n", + " ma_type=\"EMA\",\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5facfbf4", + "metadata": {}, + "outputs": [], + "source": [ + "# zero lag exponential moving average\n", + "\n", + "zlma = openbb.ta.ma_chart(\n", + " data=ticker_data[\"Close\"],\n", + " ma_type=\"ZLMA\",\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df54f7ad", + "metadata": {}, + "outputs": [], + "source": [ + "# commodity channel index\n", + "\n", + "cci = openbb.ta.cci_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f53469eb", + "metadata": {}, + "outputs": [], + "source": [ + "# moving average convergence/divergence\n", + "\n", + "macd = openbb.ta.macd_chart(\n", + " data=ticker_data[\"Adj Close\"],\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd79e6b6", + "metadata": {}, + "outputs": [], + "source": [ + "# fisher transform\n", + "\n", + "fisher = openbb.ta.fisher_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b699e61f", + "metadata": {}, + "outputs": [], + "source": [ + "# aroon indicator\n", + "\n", + "aroon = openbb.ta.aroon_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79401027", + "metadata": {}, + "outputs": [], + "source": [ + "# bollinger bands\n", + "\n", + "bbands = openbb.ta.bbands_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0b5e2949", + "metadata": {}, + "outputs": [], + "source": [ + "# fibonacci retracement\n", + "\n", + "fib = openbb.ta.fib_chart(\n", + " data=ticker_data,\n", + " symbol=ticker,\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "markdown", + "id": "e6f6ce8a", + "metadata": {}, + "source": [ + "# Quantitative Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e77b373b", + "metadata": {}, + "outputs": [], + "source": [ + "# summary\n", + "\n", + "summary = openbb.qa.summary(data=ticker_data)\n", + "summary" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ecfc93e", + "metadata": {}, + "outputs": [], + "source": [ + "# normality statistics and tests\n", + "\n", + "normality = openbb.qa.normality(\n", + " data=ticker_data[\"Close\"],\n", + ")\n", + "normality" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66a7dccc", + "metadata": {}, + "outputs": [], + "source": [ + "# rolling mean and std deviation of prices\n", + "\n", + "rolling = openbb.qa.rolling_chart(\n", + " symbol=ticker,\n", + " data=ticker_data,\n", + " target=\"Close\",\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6b43dd7", + "metadata": {}, + "outputs": [], + "source": [ + "# rolling kurtosis of distribution of prices\n", + "\n", + "kurtosis = openbb.qa.kurtosis_chart(\n", + " symbol=ticker,\n", + " data=ticker_data,\n", + " target=\"Close\",\n", + " external_axes=True,\n", + ").to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fc31624a", + "metadata": {}, + "outputs": [], + "source": [ + "# latest news\n", + "\n", + "news = openbb.news(term=ticker).head(10)\n", + "\n", + "news[\"published\"] = pd.to_datetime(news[\"published\"])\n", + "news[\"published\"] = pd.to_datetime(\n", + " news[\"published\"], format=\"%d/%m/%y %H:%M:%S\"\n", + ").dt.strftime(\"%Y-%m-%d\")\n", + "news = news[[\"published\", \"title\", \"link\"]]\n", + "\n", + "news[\"link\"] = news[\"link\"].apply(lambda x: f'{x}')\n", + "news = news.set_index(\"published\")\n", + "news.sort_index()\n", + "news" + ] + }, + { + "cell_type": "markdown", + "id": "ac501a32-124d-4d21-aae1-a8d147bb1071", + "metadata": {}, + "source": [ + "## Render the report template to a file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12", + "metadata": {}, + "outputs": [], + "source": [ + "body = f\"\"\"\n", + "\n", + "\n", + "\"\"\"\n", + "\n", + "\n", + "img = (\n", + " str(REPOSITORY_DIRECTORY)\n", + " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", + ")\n", + "floppy_disk_img = (\n", + " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", + ")\n", + "body += widgets.header(\n", + " img,\n", + " floppy_disk_img,\n", + " author,\n", + " report_date,\n", + " report_time,\n", + " report_timezone,\n", + " f\"INVESTMENT RESEARCH REPORT: {ticker}\",\n", + ")\n", + "\n", + "body += widgets.tablinks(\n", + " [\n", + " \"SUMMARY\",\n", + " \"Overview\",\n", + " \"Technical Analysis\",\n", + " \"Quantitative Analysis\",\n", + " ]\n", + ")\n", + "\n", + "comment = \"Every analysis displayed considered every day data YTD\"\n", + "\n", + "\n", + "# TODO: add KPIs\n", + "\n", + "htmlcode = \"\"\n", + "\n", + "# htmlcode += widgets.h(3, \"KPIs\")\n", + "# htmlcode += widgets.kpi(\n", + "# [30, 70],\n", + "# [\"RSI level is oversold\", \"RSI level is normal\", \"RSI level is overbought\"],\n", + "# 999,\n", + "# )\n", + "# htmlcode += widgets.kpi(\n", + "# [0],\n", + "# [\n", + "# \"The sum of last 10 insider trading (in millions) was negative\",\n", + "# \"The sum of last 10 insider trading (in millions) was positive\",\n", + "# ],\n", + "# 999,\n", + "# )\n", + "# htmlcode += widgets.kpi(\n", + "# [-0.1, 0.1],\n", + "# [\n", + "# \"Last FinBrain sentiment is bearish\",\n", + "# \"Last FinBrain sentiment is neutral\",\n", + "# \"Last FinBrain sentiment is bullish\",\n", + "# ],\n", + "# 999,\n", + "# )\n", + "\n", + "# Summary tab\n", + "htmlcode += widgets.row([widgets.h(3, \"Latest news\") + news.to_html(escape=False)])\n", + "htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, \"One year historical data for 1st day each month\")\n", + " + ticker_data_interval_1month.to_html()\n", + " ]\n", + ")\n", + "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", + "\n", + "# Overview tab\n", + "htmlcode = \"\"\n", + "htmlcode = widgets.row([widgets.h(3, \"Candlestick chart\")])\n", + "htmlcode += widgets.row([candle])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Candlestick chart with moving averages 7 and 14\")]\n", + ")\n", + "htmlcode += widgets.row([candle_ma_7_14])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Candlestick chart with moving averages 30 and 60\")]\n", + ")\n", + "htmlcode += widgets.row([candle_ma_30_60])\n", + "htmlcode += widgets.row([widgets.h(3, \"Forward rates\")])\n", + "htmlcode += widgets.row([fwd.to_html()])\n", + "body += widgets.add_tab(\"Overview\", htmlcode, True, comment)\n", + "\n", + "# Technical Analysis tab\n", + "htmlcode = widgets.row([widgets.h(3, \"Simple moving average\")])\n", + "htmlcode += widgets.row([sma])\n", + "htmlcode += widgets.row([widgets.h(3, \"Exponential moving average\")])\n", + "htmlcode += widgets.row([ema])\n", + "htmlcode += widgets.row([widgets.h(3, \"Zero lag exponential moving average\")])\n", + "htmlcode += widgets.row([zlma])\n", + "htmlcode += widgets.row([widgets.h(3, \"Commodity channel index\")])\n", + "htmlcode += widgets.row([cci])\n", + "htmlcode += widgets.row([widgets.h(3, \"Moving average convergence/divergence\")])\n", + "htmlcode += widgets.row([macd])\n", + "htmlcode += widgets.row([widgets.h(3, \"Fisher transform\")])\n", + "htmlcode += widgets.row([fisher])\n", + "htmlcode += widgets.row([widgets.h(3, \"Aroon indicator\")])\n", + "htmlcode += widgets.row([aroon])\n", + "htmlcode += widgets.row([widgets.h(3, \"Bollinger bands\")])\n", + "htmlcode += widgets.row([bbands])\n", + "htmlcode += widgets.row([widgets.h(3, \"Fibonacci retracement\")])\n", + "htmlcode += widgets.row([fib])\n", + "body += widgets.add_tab(\"Technical Analysis\", htmlcode, True, comment)\n", + "\n", + "# Quantitative Analysis tab\n", + "htmlcode = widgets.row([widgets.h(3, \"Summary\") + summary.to_html()])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Normality statistics and tests\") + normality.to_html()]\n", + ")\n", + "htmlcode += widgets.row([widgets.h(3, \"Rolling mean and std deviation of prices\")])\n", + "htmlcode += widgets.row([rolling])\n", + "htmlcode += widgets.row([widgets.h(3, \"Rolling kurtosis of distribution of prices\")])\n", + "htmlcode += widgets.row([kurtosis])\n", + "body += widgets.add_tab(\"Quantitative Analysis\", htmlcode, True, comment)\n", + "\n", + "body += widgets.tab_clickable_and_save_evt()\n", + "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", + "\n", + "# # to save the results\n", + "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", + " fh.write(report)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "venv", + "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.10.8" + }, + "vscode": { + "interpreter": { + "hash": "381a209f752e9104bff95ec5e80679ea2e476866b80e4326f1ee6b7658af6049" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/openbb_terminal/reports/templates/portfolio.ipynb b/openbb_terminal/reports/templates/portfolio.ipynb index 9ea982e03c5..9d16c8b95d4 100644 --- a/openbb_terminal/reports/templates/portfolio.ipynb +++ b/openbb_terminal/reports/templates/portfolio.ipynb @@ -1,511 +1,522 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "70ba2c8a", - "metadata": {}, - "source": [ - "## Notebook setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "driven-billion", - "metadata": {}, - "outputs": [], - "source": [ - "import os\n", - "import io\n", - "import warnings\n", - "import datetime\n", - "import numpy as np\n", - "import base64\n", - "import pytz\n", - "import pandas as pd\n", - "\n", - "from IPython.display import HTML\n", - "\n", - "import openbb_terminal.config_terminal as cfg\n", - "from openbb_terminal.reports import widget_helpers as widgets\n", - "from openbb_terminal.sdk import openbb\n", - "from openbb_terminal.sdk import helper\n", - "from openbb_terminal.helper_classes import TerminalStyle\n", - "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", - "from openbb_terminal import OpenBBFigure\n", - "\n", - "warnings.filterwarnings(\"ignore\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "62d3ea0e", - "metadata": {}, - "outputs": [], - "source": [ - "from openbb_terminal.core.session.current_user import get_current_user\n", - "\n", - "user = get_current_user()\n", - "\n", - "cfg.theme = TerminalStyle(\n", - " user.preferences.MPL_STYLE,\n", - " user.preferences.PMF_STYLE,\n", - " user.preferences.RICH_STYLE,\n", - ")\n", - "\n", - "USER_PORTFOLIO_DATA_DIRECTORY = user.preferences.USER_PORTFOLIO_DATA_DIRECTORY" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4391e874", - "metadata": {}, - "outputs": [], - "source": [ - "stylesheet = widgets.html_report_stylesheet()" - ] - }, - { - "cell_type": "markdown", - "id": "8136bf90", - "metadata": {}, - "source": [ - "### Header" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", - "metadata": {}, - "outputs": [], - "source": [ - "theme = TerminalStyle(\"light\", \"light\", \"light\")\n", - "stylesheet = widgets.html_report_stylesheet()\n", - "user_time_zone = pytz.timezone(helper.get_user_timezone())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "daef64ec", - "metadata": { - "tags": [ - "parameters" - ] - }, - "outputs": [], - "source": [ - "# Parameters that will be replaced when calling this notebook\n", - "# Do not leave parameters blank as notebook will not run otherwise\n", - "transactions = \"holdings_example.xlsx\"\n", - "report_name = \"Portfolio Report\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dd441a31", - "metadata": {}, - "outputs": [], - "source": [ - "file_0 = (\n", - " str(REPOSITORY_DIRECTORY)\n", - " + \"/openbb_terminal/miscellaneous/portfolio/\"\n", - " + transactions\n", - ")\n", - "file_1 = str(USER_PORTFOLIO_DATA_DIRECTORY) + \"/holdings/\" + transactions\n", - "\n", - "if os.path.isfile(file_0):\n", - " transactions_path = file_0\n", - "elif os.path.isfile(file_1):\n", - " transactions_path = file_1\n", - "else:\n", - " raise FileNotFoundError(\"File not found: \" + transactions)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", - "metadata": {}, - "outputs": [], - "source": [ - "_, transactions_file = os.path.split(transactions_path)\n", - "report_title = f\"Portfolio report for {transactions_file}\"\n", - "report_date = pd.Timestamp.now(tz=user_time_zone).strftime(\"%d %B, %Y\")\n", - "report_time = pd.Timestamp.now(tz=user_time_zone).strftime(\"%H:%M\")\n", - "report_timezone = pd.Timestamp.now(tz=user_time_zone).tzinfo\n", - "report_title, report_date, report_time, report_timezone" - ] - }, - { - "cell_type": "markdown", - "id": "9363f19a", - "metadata": {}, - "source": [ - "## Data" - ] - }, - { - "cell_type": "markdown", - "id": "eb3dbd48", - "metadata": {}, - "source": [ - "Loading" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b139556d", - "metadata": {}, - "outputs": [], - "source": [ - "try:\n", - " P = openbb.portfolio.load(transactions_path)\n", - " openbb.portfolio.show(P)\n", - "except Exception as e:\n", - " raise Exception(\"Failed to load the transactions.\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "af24ed22", - "metadata": {}, - "outputs": [], - "source": [ - "beta_chart = openbb.portfolio.rbeta_chart(P, external_axes=True)\n", - "\n", - "if beta_chart:\n", - " beta_chart = beta_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "636c743d", - "metadata": {}, - "outputs": [], - "source": [ - "sharpe_chart = openbb.portfolio.rsharpe_chart(P, external_axes=True)\n", - "\n", - "if sharpe_chart:\n", - " sharpe_chart = sharpe_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ae0d9381", - "metadata": {}, - "outputs": [], - "source": [ - "volatility_chart = openbb.portfolio.rvol_chart(P, external_axes=True)\n", - "\n", - "if volatility_chart:\n", - " volatility_chart = volatility_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7e5e6fff", - "metadata": {}, - "outputs": [], - "source": [ - "sortino_chart = openbb.portfolio.rsort_chart(P, external_axes=True)\n", - "\n", - "if sortino_chart:\n", - " sortino_chart = sortino_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3567b0ca", - "metadata": {}, - "outputs": [], - "source": [ - "maxdd_chart = openbb.portfolio.maxdd_chart(P, external_axes=True)\n", - "\n", - "if maxdd_chart:\n", - " maxdd_chart = maxdd_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5dbcc1eb", - "metadata": {}, - "outputs": [], - "source": [ - "country_allocation = openbb.portfolio.alloc.countries(P)\n", - "\n", - "country_allocation[\"Portfolio\"] = (country_allocation[\"Portfolio\"] * 100).map(\n", - " \"{:.3}%\".format\n", - ")\n", - "country_allocation[\"Benchmark\"] = (country_allocation[\"Benchmark\"] * 100).map(\n", - " \"{:.3}%\".format\n", - ")\n", - "country_allocation[\"Difference\"] = (country_allocation[\"Difference\"] * 100).map(\n", - " \"{:.3}pp\".format\n", - ")\n", - "\n", - "country_allocation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8e1a67a6", - "metadata": {}, - "outputs": [], - "source": [ - "sector_allocation = openbb.portfolio.alloc.sectors(P)\n", - "\n", - "sector_allocation[\"Portfolio\"] = (sector_allocation[\"Portfolio\"] * 100).map(\n", - " \"{:.3}%\".format\n", - ")\n", - "sector_allocation[\"Benchmark\"] = (sector_allocation[\"Benchmark\"] * 100).map(\n", - " \"{:.3}%\".format\n", - ")\n", - "sector_allocation[\"Difference\"] = (sector_allocation[\"Difference\"] * 100).map(\n", - " \"{:.3}pp\".format\n", - ")\n", - "\n", - "sector_allocation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6e1260b4", - "metadata": {}, - "outputs": [], - "source": [ - "distr_chart = openbb.portfolio.distr_chart(P, external_axes=True)\n", - "\n", - "if distr_chart:\n", - " distr_chart = distr_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a668a58b", - "metadata": {}, - "outputs": [], - "source": [ - "dret_chart = openbb.portfolio.dret_chart(P, external_axes=True)\n", - "\n", - "if dret_chart:\n", - " dret_chart = dret_chart.to_html()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1ea71ca6", - "metadata": {}, - "outputs": [], - "source": [ - "yret_chart = openbb.portfolio.yret_chart(P, external_axes=True)\n", - "\n", - "if yret_chart:\n", - " yret_chart = yret_chart.to_html()" - ] - }, - { - "cell_type": "markdown", - "id": "ac795b8e", - "metadata": {}, - "source": [ - "## Render the report template to a file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ebe0799e", - "metadata": {}, - "outputs": [], - "source": [ - "body = f\"\"\"\n", - "\n", - "\n", - "\"\"\"\n", - "\n", - "\n", - "img = (\n", - " str(REPOSITORY_DIRECTORY)\n", - " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", - ")\n", - "floppy_disk_img = (\n", - " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", - ")\n", - "body += widgets.header(\n", - " img,\n", - " floppy_disk_img,\n", - " \"OpenBB\",\n", - " report_date,\n", - " report_time,\n", - " report_timezone,\n", - " report_title,\n", - ")\n", - "\n", - "body += widgets.tablinks([\"SUMMARY\", \"In-Depth Analysis\", \"Statistics\"])\n", - "\n", - "# Summary\n", - "htmlcode = widgets.p(\n", - " \"The total performance of the portfolio versus the benchmark is as follows. \"\n", - " \"Please note this calculation assumes partially shares exist for the benchmark.\"\n", - ")\n", - "\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Performance\") + openbb.portfolio.perf(P).to_html()]\n", - ")\n", - "\n", - "htmlcode += widgets.p(\"In which the following yearly returns are achieved:\")\n", - "\n", - "htmlcode += widgets.row([widgets.h(3, \"Yearly Performance\") + yret_chart])\n", - "\n", - "htmlcode += widgets.p(\n", - " \"The portfolio and benchmark consists of the following allocations to countries and sectors.\"\n", - ")\n", - "\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Country Allocation\") + country_allocation.to_html()]\n", - ")\n", - "\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Sector Allocation\") + sector_allocation.to_html()]\n", - ")\n", - "\n", - "htmlcode += widgets.p(\n", - " \"The portfolio consists of the following trades including returns.\"\n", - ")\n", - "\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Portfolio Trades\") + P.portfolio_trades.to_html()]\n", - ")\n", - "\n", - "htmlcode += widgets.p(\n", - " \"The benchmark consists of the following trades including returns.\"\n", - ")\n", - "\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Benchmark Trades\") + P.benchmark_trades.to_html()]\n", - ")\n", - "\n", - "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", - "\n", - "# In Depth Analysis\n", - "htmlcode = widgets.p(\n", - " \"The following metrics, Tracking Error and Information Ratio, measure whether you are \"\n", - " \"closely aligned with the benchmark. If the Tracking Error is not close to 1, a different benchmark \"\n", - " \"might be a better fit.\"\n", - ")\n", - "\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Tracking Error\") + openbb.portfolio.metric.trackerr(P)[0].to_html()]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [\n", - " widgets.h(3, \"Information Ratio\")\n", - " + openbb.portfolio.metric.information(P).to_html()\n", - " ]\n", - ")\n", - "\n", - "htmlcode += widgets.row([widgets.h(3, \"Beta Chart\") + beta_chart])\n", - "\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Sharpe Ratio\") + openbb.portfolio.metric.sharpe(P).to_html()]\n", - ")\n", - "htmlcode += widgets.row([widgets.h(3, \"Sharpe Ratio Chart\") + sharpe_chart])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Volatility\") + openbb.portfolio.metric.volatility(P).to_html()]\n", - ")\n", - "htmlcode += widgets.row([widgets.h(3, \"Volatility Chart\") + volatility_chart])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Sortino Ratio\") + openbb.portfolio.metric.sortino(P).to_html()]\n", - ")\n", - "htmlcode += widgets.row([widgets.h(3, \"Sortino Chart\") + sortino_chart])\n", - "\n", - "htmlcode += widgets.row([widgets.h(3, \"Maximum Drawdown\") + maxdd_chart])\n", - "\n", - "\n", - "body += widgets.add_tab(\"In-Depth Analysis\", htmlcode)\n", - "\n", - "# Statistics\n", - "htmlcode = widgets.row([widgets.h(3, \"Distribution\") + distr_chart])\n", - "htmlcode += widgets.row([widgets.h(3, \"Daily Returns\") + dret_chart])\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Volatility\") + openbb.portfolio.metric.volatility(P).to_html()]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Kurtosis\") + openbb.portfolio.metric.kurtosis(P).to_html()]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Skew\") + openbb.portfolio.metric.skew(P).to_html()]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Value at Risk (VaR)\") + openbb.portfolio.var(P).to_html()]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Expected Shortfall (cVaR)\") + openbb.portfolio.es(P).to_html()]\n", - ")\n", - "htmlcode += widgets.row(\n", - " [widgets.h(3, \"Omega Ratio\") + openbb.portfolio.om(P).to_html()]\n", - ")\n", - "\n", - "body += widgets.add_tab(\"Statistics\", htmlcode)\n", - "\n", - "body += widgets.tab_clickable_and_save_evt()\n", - "\n", - "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", - "\n", - "# to save the results\n", - "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", - " fh.write(report)" - ] - } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "obb", - "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.10.9" - }, - "vscode": { - "interpreter": { - "hash": "100174a9203096c0c10fb537684ff280825ee9e252451beb8786068677204f06" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "cells": [ + { + "cell_type": "markdown", + "id": "70ba2c8a", + "metadata": {}, + "source": [ + "## Notebook setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "driven-billion", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import io\n", + "import warnings\n", + "import datetime\n", + "import numpy as np\n", + "import base64\n", + "import pytz\n", + "import pandas as pd\n", + "\n", + "from IPython.display import HTML\n", + "\n", + "import openbb_terminal.config_terminal as cfg\n", + "from openbb_terminal.helper_classes import TerminalStyle\n", + "from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY\n", + "from openbb_terminal import OpenBBFigure\n", + "\n", + "warnings.filterwarnings(\"ignore\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49032d55", + "metadata": {}, + "outputs": [], + "source": [ + "# Suppressing sdk logs\n", + "cfg.change_logging_suppress(new_value=True)\n", + "\n", + "# Import the OpenBB SDK\n", + "from openbb_terminal.sdk import openbb, widgets, helper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62d3ea0e", + "metadata": {}, + "outputs": [], + "source": [ + "from openbb_terminal.core.session.current_user import get_current_user\n", + "\n", + "user = get_current_user()\n", + "\n", + "cfg.theme = TerminalStyle(\n", + " user.preferences.MPL_STYLE,\n", + " user.preferences.PMF_STYLE,\n", + " user.preferences.RICH_STYLE,\n", + ")\n", + "\n", + "USER_PORTFOLIO_DATA_DIRECTORY = user.preferences.USER_PORTFOLIO_DATA_DIRECTORY" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4391e874", + "metadata": {}, + "outputs": [], + "source": [ + "stylesheet = widgets.html_report_stylesheet()" + ] + }, + { + "cell_type": "markdown", + "id": "8136bf90", + "metadata": {}, + "source": [ + "### Header" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370", + "metadata": {}, + "outputs": [], + "source": [ + "theme = TerminalStyle(\"light\", \"light\", \"light\")\n", + "stylesheet = widgets.html_report_stylesheet()\n", + "user_time_zone = pytz.timezone(helper.get_user_timezone())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "daef64ec", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "# Parameters that will be replaced when calling this notebook\n", + "# Do not leave parameters blank as notebook will not run otherwise\n", + "transactions = \"holdings_example.xlsx\"\n", + "report_name = \"Portfolio Report\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd441a31", + "metadata": {}, + "outputs": [], + "source": [ + "file_0 = (\n", + " str(REPOSITORY_DIRECTORY)\n", + " + \"/openbb_terminal/miscellaneous/portfolio/\"\n", + " + transactions\n", + ")\n", + "file_1 = str(USER_PORTFOLIO_DATA_DIRECTORY) + \"/holdings/\" + transactions\n", + "\n", + "if os.path.isfile(file_0):\n", + " transactions_path = file_0\n", + "elif os.path.isfile(file_1):\n", + " transactions_path = file_1\n", + "else:\n", + " raise FileNotFoundError(\"File not found: \" + transactions)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b", + "metadata": {}, + "outputs": [], + "source": [ + "_, transactions_file = os.path.split(transactions_path)\n", + "report_title = f\"Portfolio report for {transactions_file}\"\n", + "report_date = pd.Timestamp.now(tz=user_time_zone).strftime(\"%d %B, %Y\")\n", + "report_time = pd.Timestamp.now(tz=user_time_zone).strftime(\"%H:%M\")\n", + "report_timezone = pd.Timestamp.now(tz=user_time_zone).tzinfo\n", + "report_title, report_date, report_time, report_timezone" + ] + }, + { + "cell_type": "markdown", + "id": "9363f19a", + "metadata": {}, + "source": [ + "## Data" + ] + }, + { + "cell_type": "markdown", + "id": "eb3dbd48", + "metadata": {}, + "source": [ + "Loading" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b139556d", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " P = openbb.portfolio.load(transactions_path)\n", + " openbb.portfolio.show(P)\n", + "except Exception as e:\n", + " raise Exception(\"Failed to load the transactions.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af24ed22", + "metadata": {}, + "outputs": [], + "source": [ + "beta_chart = openbb.portfolio.rbeta_chart(P, external_axes=True)\n", + "\n", + "if beta_chart:\n", + " beta_chart = beta_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "636c743d", + "metadata": {}, + "outputs": [], + "source": [ + "sharpe_chart = openbb.portfolio.rsharpe_chart(P, external_axes=True)\n", + "\n", + "if sharpe_chart:\n", + " sharpe_chart = sharpe_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae0d9381", + "metadata": {}, + "outputs": [], + "source": [ + "volatility_chart = openbb.portfolio.rvol_chart(P, external_axes=True)\n", + "\n", + "if volatility_chart:\n", + " volatility_chart = volatility_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e5e6fff", + "metadata": {}, + "outputs": [], + "source": [ + "sortino_chart = openbb.portfolio.rsort_chart(P, external_axes=True)\n", + "\n", + "if sortino_chart:\n", + " sortino_chart = sortino_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3567b0ca", + "metadata": {}, + "outputs": [], + "source": [ + "maxdd_chart = openbb.portfolio.maxdd_chart(P, external_axes=True)\n", + "\n", + "if maxdd_chart:\n", + " maxdd_chart = maxdd_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5dbcc1eb", + "metadata": {}, + "outputs": [], + "source": [ + "country_allocation = openbb.portfolio.alloc.countries(P)\n", + "\n", + "country_allocation[\"Portfolio\"] = (country_allocation[\"Portfolio\"] * 100).map(\n", + " \"{:.3}%\".format\n", + ")\n", + "country_allocation[\"Benchmark\"] = (country_allocation[\"Benchmark\"] * 100).map(\n", + " \"{:.3}%\".format\n", + ")\n", + "country_allocation[\"Difference\"] = (country_allocation[\"Difference\"] * 100).map(\n", + " \"{:.3}pp\".format\n", + ")\n", + "\n", + "country_allocation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8e1a67a6", + "metadata": {}, + "outputs": [], + "source": [ + "sector_allocation = openbb.portfolio.alloc.sectors(P)\n", + "\n", + "sector_allocation[\"Portfolio\"] = (sector_allocation[\"Portfolio\"] * 100).map(\n", + " \"{:.3}%\".format\n", + ")\n", + "sector_allocation[\"Benchmark\"] = (sector_allocation[\"Benchmark\"] * 100).map(\n", + " \"{:.3}%\".format\n", + ")\n", + "sector_allocation[\"Difference\"] = (sector_allocation[\"Difference\"] * 100).map(\n", + " \"{:.3}pp\".format\n", + ")\n", + "\n", + "sector_allocation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e1260b4", + "metadata": {}, + "outputs": [], + "source": [ + "distr_chart = openbb.portfolio.distr_chart(P, external_axes=True)\n", + "\n", + "if distr_chart:\n", + " distr_chart = distr_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a668a58b", + "metadata": {}, + "outputs": [], + "source": [ + "dret_chart = openbb.portfolio.dret_chart(P, external_axes=True)\n", + "\n", + "if dret_chart:\n", + " dret_chart = dret_chart.to_html()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1ea71ca6", + "metadata": {}, + "outputs": [], + "source": [ + "yret_chart = openbb.portfolio.yret_chart(P, external_axes=True)\n", + "\n", + "if yret_chart:\n", + " yret_chart = yret_chart.to_html()" + ] + }, + { + "cell_type": "markdown", + "id": "ac795b8e", + "metadata": {}, + "source": [ + "## Render the report template to a file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ebe0799e", + "metadata": {}, + "outputs": [], + "source": [ + "body = f\"\"\"\n", + "\n", + "\n", + "\"\"\"\n", + "\n", + "\n", + "img = (\n", + " str(REPOSITORY_DIRECTORY)\n", + " + \"/openbb_terminal/reports/templates/OpenBB_reports_logo.png\"\n", + ")\n", + "floppy_disk_img = (\n", + " str(REPOSITORY_DIRECTORY) + \"/openbb_terminal/reports/templates/floppy-disc.png\"\n", + ")\n", + "body += widgets.header(\n", + " img,\n", + " floppy_disk_img,\n", + " \"OpenBB\",\n", + " report_date,\n", + " report_time,\n", + " report_timezone,\n", + " report_title,\n", + ")\n", + "\n", + "body += widgets.tablinks([\"SUMMARY\", \"In-Depth Analysis\", \"Statistics\"])\n", + "\n", + "# Summary\n", + "htmlcode = widgets.p(\n", + " \"The total performance of the portfolio versus the benchmark is as follows. \"\n", + " \"Please note this calculation assumes partially shares exist for the benchmark.\"\n", + ")\n", + "\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Performance\") + openbb.portfolio.perf(P).to_html()]\n", + ")\n", + "\n", + "htmlcode += widgets.p(\"In which the following yearly returns are achieved:\")\n", + "\n", + "htmlcode += widgets.row([widgets.h(3, \"Yearly Performance\") + yret_chart])\n", + "\n", + "htmlcode += widgets.p(\n", + " \"The portfolio and benchmark consists of the following allocations to countries and sectors.\"\n", + ")\n", + "\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Country Allocation\") + country_allocation.to_html()]\n", + ")\n", + "\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Sector Allocation\") + sector_allocation.to_html()]\n", + ")\n", + "\n", + "htmlcode += widgets.p(\n", + " \"The portfolio consists of the following trades including returns.\"\n", + ")\n", + "\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Portfolio Trades\") + P.portfolio_trades.to_html()]\n", + ")\n", + "\n", + "htmlcode += widgets.p(\n", + " \"The benchmark consists of the following trades including returns.\"\n", + ")\n", + "\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Benchmark Trades\") + P.benchmark_trades.to_html()]\n", + ")\n", + "\n", + "body += widgets.add_tab(\"SUMMARY\", htmlcode)\n", + "\n", + "# In Depth Analysis\n", + "htmlcode = widgets.p(\n", + " \"The following metrics, Tracking Error and Information Ratio, measure whether you are \"\n", + " \"closely aligned with the benchmark. If the Tracking Error is not close to 1, a different benchmark \"\n", + " \"might be a better fit.\"\n", + ")\n", + "\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Tracking Error\") + openbb.portfolio.metric.trackerr(P)[0].to_html()]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [\n", + " widgets.h(3, \"Information Ratio\")\n", + " + openbb.portfolio.metric.information(P).to_html()\n", + " ]\n", + ")\n", + "\n", + "htmlcode += widgets.row([widgets.h(3, \"Beta Chart\") + beta_chart])\n", + "\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Sharpe Ratio\") + openbb.portfolio.metric.sharpe(P).to_html()]\n", + ")\n", + "htmlcode += widgets.row([widgets.h(3, \"Sharpe Ratio Chart\") + sharpe_chart])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Volatility\") + openbb.portfolio.metric.volatility(P).to_html()]\n", + ")\n", + "htmlcode += widgets.row([widgets.h(3, \"Volatility Chart\") + volatility_chart])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Sortino Ratio\") + openbb.portfolio.metric.sortino(P).to_html()]\n", + ")\n", + "htmlcode += widgets.row([widgets.h(3, \"Sortino Chart\") + sortino_chart])\n", + "\n", + "htmlcode += widgets.row([widgets.h(3, \"Maximum Drawdown\") + maxdd_chart])\n", + "\n", + "\n", + "body += widgets.add_tab(\"In-Depth Analysis\", htmlcode)\n", + "\n", + "# Statistics\n", + "htmlcode = widgets.row([widgets.h(3, \"Distribution\") + distr_chart])\n", + "htmlcode += widgets.row([widgets.h(3, \"Daily Returns\") + dret_chart])\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Volatility\") + openbb.portfolio.metric.volatility(P).to_html()]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Kurtosis\") + openbb.portfolio.metric.kurtosis(P).to_html()]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Skew\") + openbb.portfolio.metric.skew(P).to_html()]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Value at Risk (VaR)\") + openbb.portfolio.var(P).to_html()]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Expected Shortfall (cVaR)\") + openbb.portfolio.es(P).to_html()]\n", + ")\n", + "htmlcode += widgets.row(\n", + " [widgets.h(3, \"Omega Ratio\") + openbb.portfolio.om(P).to_html()]\n", + ")\n", + "\n", + "body += widgets.add_tab(\"Statistics\", htmlcode)\n", + "\n", + "body += widgets.tab_clickable_and_save_evt()\n", + "\n", + "report = widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n", + "\n", + "# to save the results\n", + "with open(report_name + \".html\", \"w\", encoding=\"utf-8\") as fh:\n", + " fh.write(report)" + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "obb", + "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.10.9" + }, + "vscode": { + "interpreter": { + "hash": "100174a9203096c0c10fb537684ff280825ee9e252451beb8786068677204f06" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file