Reports and Dashboards to be one level above (#1805)

This commit is contained in:
didierlopes.eth
2022-05-12 12:35:36 +01:00
committed by GitHub
parent 24cf4a4b4d
commit 37ea3fd6a3
41 changed files with 74925 additions and 4889 deletions

View File

@@ -6,6 +6,6 @@ from . import (
etf,
forex,
portfolio,
jupyter,
reports,
stocks,
)

View File

@@ -10,6 +10,6 @@ from .etf import etf_api as etf
from .forex import forex_api as forex
from .mutual_funds import mutual_fund_api as funds
from .portfolio import portfolio_api as portfolio
from .jupyter import widget_helpers as widgets
from .reports import widget_helpers as widgets
from .config_terminal import theme

View File

@@ -33,7 +33,7 @@ class DashboardsController(BaseController):
"shortdata",
"crypto",
]
PATH = "/jupyter/dashboards/"
PATH = "/dashboards/"
def __init__(self, queue: List[str] = None):
"""Constructor"""
@@ -56,7 +56,7 @@ class DashboardsController(BaseController):
shortdata finra shortdata analysis
crypto cryptocurrency exchange rates against USD[/cmds]
"""
console.print(text=help_text, menu="Jupyter - Dashboards")
console.print(text=help_text, menu="Dashboards")
@log_start_end(log=logger)
def call_stocks(self, other_args: List[str]):

View File

@@ -1,177 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "e9ad60bc",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import ipywidgets as widgets\n",
"import plotly.graph_objs as go\n",
"import yfinance as yf\n",
"from IPython.display import display"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "beb36881",
"metadata": {},
"outputs": [],
"source": [
"opts = [\n",
" \"lastTradeDate\",\n",
" \"strike\",\n",
" \"lastPrice\",\n",
" \"bid\",\n",
" \"ask\",\n",
" \"change\",\n",
" \"percentChange\",\n",
" \"volume\",\n",
" \"openInterest\",\n",
" \"impliedVolatility\",\n",
"]\n",
"\n",
"\n",
"def clean_str(string):\n",
" new_str = \"\"\n",
" for letter in string:\n",
" if letter.isupper():\n",
" new_str += \" \"\n",
" new_str += letter\n",
" return new_str.title()\n",
"\n",
"\n",
"def format_plotly(fig, x, y, ticker, expiry, inst):\n",
" fig.update_yaxes(title=clean_str(y))\n",
" fig.update_xaxes(title=clean_str(x))\n",
" expires = \", \".join(expiry)\n",
" title = (\n",
" f\"{clean_str(y)} vs. {clean_str(x)} for {ticker.upper()} {inst}s on {expires}\"\n",
" )\n",
" fig.update_layout(\n",
" autosize=False,\n",
" width=1000,\n",
" height=500,\n",
" title={\n",
" \"text\": title,\n",
" \"y\": 0.95,\n",
" \"x\": 0.5,\n",
" \"xanchor\": \"center\",\n",
" \"yanchor\": \"top\",\n",
" },\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f8c2f65c",
"metadata": {
"tags": [
"parameters"
]
},
"outputs": [],
"source": [
"class Chart:\n",
" def __init__(self):\n",
" self.last_ticker = \"\"\n",
" self.dfs = {}\n",
"\n",
" def update(self, ticker, expiry, inst, x, y):\n",
" if ticker:\n",
" stock = yf.Ticker(ticker)\n",
" if ticker != self.last_ticker:\n",
" exp_w.options = stock.options\n",
" self.last_ticker = ticker\n",
"\n",
" if expiry:\n",
" fig = go.Figure()\n",
" for expire in expiry:\n",
" if expire not in self.dfs:\n",
" self.dfs[expire] = stock.option_chain(expire)\n",
" group = self.dfs[expire]\n",
" df = group.calls if inst == \"Call\" else group.puts\n",
"\n",
" plot = go.Scatter(\n",
" x=df[x],\n",
" y=df[y],\n",
" mode=\"lines\",\n",
" connectgaps=True,\n",
" name=expire,\n",
" )\n",
" fig.add_trace(plot)\n",
"\n",
" format_plotly(fig, x, y, ticker, expiry, inst)\n",
"\n",
" if os.environ.get(\"SERVER_SOFTWARE\", \"jupyter\").startswith(\"voila\"):\n",
" fig.show(config={\"showTips\": False}, renderer=\"notebook\")\n",
" else:\n",
" fig.show(config={\"showTips\": False})\n",
"\n",
"\n",
"x_w = widgets.Dropdown(options=opts, value=\"strike\", description=\"X\")\n",
"y_w = widgets.Dropdown(options=opts, value=\"lastPrice\", description=\"Y\")\n",
"tickers_w = widgets.Text(description=\"Ticker\")\n",
"exp_w = widgets.SelectMultiple(description=\"Expiry\")\n",
"inst_w = widgets.Dropdown(options=[\"Put\", \"Call\"], value=\"Call\", description=\"Type\")\n",
"\n",
"select_opt = widgets.VBox([tickers_w, exp_w])\n",
"select_plot = widgets.VBox([inst_w, x_w, y_w])\n",
"controls = widgets.HBox([select_opt, select_plot])\n",
"\n",
"chart = Chart()\n",
"stocks_view = widgets.interactive_output(\n",
" chart.update,\n",
" {\"ticker\": tickers_w, \"expiry\": exp_w, \"inst\": inst_w, \"x\": x_w, \"y\": y_w},\n",
")\n",
"\n",
"title_html = \"<h1>Option Chain Dashboard</h1>\"\n",
"app_contents = [\n",
" widgets.HTML(title_html),\n",
" controls,\n",
" stocks_view,\n",
"]\n",
"app = widgets.VBox(app_contents)\n",
"display(app)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a84c7390-6b43-4a25-8aa2-31aa84f52605",
"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.8.12"
},
"metadata": {
"interpreter": {
"hash": "e896a00ead8b521528d79ac9ef24990696f2b751eb283ab8e0d078c9c4971ffc"
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,222 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 10,
"id": "e9ad60bc",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from datetime import datetime, timedelta\n",
"import ipywidgets as widgets\n",
"import plotly.graph_objs as go\n",
"import yfinance as yf\n",
"import pandas as pd\n",
"from IPython.display import display"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "6c554cd2-462c-4832-b73c-c214aae11ce4",
"metadata": {},
"outputs": [],
"source": [
"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",
"]"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "f8c2f65c",
"metadata": {
"tags": [
"parameters"
]
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b462032b043b47a8899f8366f43ab28e",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(HTML(value='<h1>Correlation Analysis Dashboard</h1>'), HBox(children=(VBox(children=(Textarea(v…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"class Chart:\n",
" def __init__(self):\n",
" self.last_tickers = \"\"\n",
" self.last_interval = \"1d\"\n",
" self.df = pd.DataFrame()\n",
"\n",
" def create(self, data, start, end, interval, tickers):\n",
" global last_tickers, df, last_interval\n",
" if tickers and tickers[-1] == \",\":\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",
" self.df = yf.download(\n",
" tickers, start=start, end=end, interval=interval, progress=False\n",
" )\n",
" self.last_tickers = tickers\n",
" self.last_interval = interval\n",
"\n",
" start_n = datetime(start.year, start.month, start.day)\n",
" end_n = datetime(end.year, end.month, end.day)\n",
"\n",
" df = self.df[data]\n",
"\n",
" if not isinstance(df, pd.Series):\n",
" if interval in [\"1d\", \"5d\", \"1wk\", \"1mo\", \"3mo\"]:\n",
" result = df.loc[(df.index >= start_n) & (df.index <= end_n)].corr()\n",
" else:\n",
" result = df.corr()\n",
"\n",
" base = [\n",
" [\n",
" \"black\" if x == 1 else \"lightgreen\" if x > 0 else \"lightpink\"\n",
" for x in result[y].tolist()\n",
" ]\n",
" for y in result.columns\n",
" ]\n",
" base = [[\"lightgray\" for _ in range(result.shape[0])]] + base\n",
" result = result.reset_index()\n",
" result.rename(columns={\"index\": \"\"}, inplace=True)\n",
"\n",
" fig = go.Figure(\n",
" data=[\n",
" go.Table(\n",
" header=dict(\n",
" values=list(result.columns),\n",
" fill_color=\"lightgray\",\n",
" font=dict(color=\"black\"),\n",
" align=\"left\",\n",
" ),\n",
" cells=dict(\n",
" values=[result[x] for x in result.columns],\n",
" fill_color=base,\n",
" format=[\"\"]\n",
" + [\".2f\" for _ in range(len(df.columns) - 1)],\n",
" font=dict(color=\"black\"),\n",
" align=\"left\",\n",
" ),\n",
" )\n",
" ],\n",
" )\n",
" fig.update_layout(\n",
" autosize=True,\n",
" height=600,\n",
" showlegend=False,\n",
" )\n",
" if os.environ.get(\"SERVER_SOFTWARE\", \"jupyter\").startswith(\"voila\"):\n",
" fig.show(config={\"showTips\": False}, renderer=\"notebook\")\n",
" else:\n",
" fig.show(config={\"showTips\": False})\n",
"\n",
"\n",
"w_auto = widgets.Layout(width=\"auto\")\n",
"data_opts = [\"Open\", \"Close\", \"High\", \"Low\", \"Volume\"]\n",
"data_widget = widgets.Dropdown(\n",
" options=data_opts, value=\"Close\", layout=w_auto, description=\"Data\"\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",
"interval_widget = widgets.Dropdown(\n",
" options=interval_opts, value=\"1d\", layout=w_auto, description=\"Interval\"\n",
")\n",
"tickers_widget = widgets.Textarea(value=\"TSLA,AAPL,\", layout=w_auto)\n",
"\n",
"data_box = widgets.VBox([tickers_widget, data_widget])\n",
"date_box = widgets.VBox([start_widget, end_widget, interval_widget])\n",
"controls = widgets.HBox([data_box, date_box], layout=widgets.Layout(width=\"60%\"))\n",
"\n",
"chart = Chart()\n",
"stocks_view = widgets.interactive_output(\n",
" chart.create,\n",
" {\n",
" \"data\": data_widget,\n",
" \"start\": start_widget,\n",
" \"end\": end_widget,\n",
" \"interval\": interval_widget,\n",
" \"tickers\": tickers_widget,\n",
" },\n",
")\n",
"\n",
"title_html = \"<h1>Correlation Analysis Dashboard</h1>\"\n",
"warning_html = '<p style=\"color:red\">Use a comma after EVERY stock typed.</p>'\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",
"display(app)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "37f46146-a206-4c25-b969-81c5abec4b1d",
"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.8.12"
},
"metadata": {
"interpreter": {
"hash": "e896a00ead8b521528d79ac9ef24990696f2b751eb283ab8e0d078c9c4971ffc"
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,160 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "6e198e40-0c33-45b3-a79b-2d9ee9eff7b9",
"metadata": {
"tags": []
},
"source": [
"# Cryptocurrency exchange rates to USD ($)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "da655985-c9b7-492e-aefa-fbe3bc1865d5",
"metadata": {},
"outputs": [],
"source": [
"import json\n",
"import os\n",
"\n",
"import ipywidgets as ipw\n",
"from IPython.display import display\n",
"import pandas as pd\n",
"\n",
"from openbb_terminal import api as openbb\n",
"\n",
"ipw.HTML(f\"<style>{openbb.widgets.price_card_stylesheet()}</style>\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dcbbf867-af50-4d06-ae5c-7c09647aa55d",
"metadata": {},
"outputs": [],
"source": [
"COIN_LIST = (\n",
" \"BTC,ETH,USDT,BNB,USDC,XRP,LUNA,ADA,\"\n",
" + \"SOL,AVAX,DOT,BUSD,DOGE,UST,SHIB,WBTC,\"\n",
" + \"MATIC,CRO,DAI,LTC,ATOM,NEAR,LINK,BCH,\"\n",
" + \"UNI,TRX,FTT,ETC,LEO,ALGO,XLM,MANA,\"\n",
" + \"BTCB,HBAR,EGLD,ICP,SAND,XMR,WAVES,VET,\"\n",
" + \"APE,FIL,FTM,AXS,THETA,KLAY,XTZ,RUNE\"\n",
").split(\",\")\n",
"exchange_rates = {}"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "deeeb80a-3675-44fb-9a1b-2325d8da4e7d",
"metadata": {},
"outputs": [],
"source": [
"def get_exchange_rate(coin: str, days: int = 2):\n",
" \"\"\"Get exchange rate for a cryptocurrency agains USD.\"\"\"\n",
" (_, _, _, _, current_df, _,) = openbb.crypto.load(\n",
" coin=coin,\n",
" source=\"cp\",\n",
" days=days,\n",
" vs=\"usd\",\n",
" interval=\"1day\",\n",
" should_load_ta_data=True,\n",
" )\n",
" price_color = \"neutral_color\"\n",
" if current_df[\"Close\"].iloc[-1] > current_df[\"Close\"].iloc[-2]:\n",
" price_color = \"up_color\"\n",
" elif current_df[\"Close\"].iloc[-1] < current_df[\"Close\"].iloc[-2]:\n",
" price_color = \"down_color\"\n",
" price = str(current_df[\"Close\"].iloc[-1])[:7]\n",
"\n",
" return price, price_color"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "18acf5cb-6cbf-484d-8042-107c030098de",
"metadata": {},
"outputs": [],
"source": [
"def show_rates(btn):\n",
" \"\"\"Show exchange rates in grid box widget.\"\"\"\n",
" grid.children = ()\n",
" for coin in COIN_LIST:\n",
" if coin not in exchange_rates.keys():\n",
" exchange_rates[coin] = {\"price\": None, \"color\": None}\n",
" try:\n",
" price, price_color = get_exchange_rate(coin=coin)\n",
" except:\n",
" price, price_color = \"-------\", \"neutral_color\"\n",
" widgets = list(grid.children)\n",
" widgets.append(\n",
" ipw.HTML(\n",
" openbb.widgets.price_card(\n",
" ticker=coin,\n",
" price=price,\n",
" price_color=price_color,\n",
" )\n",
" )\n",
" )\n",
" grid.children = tuple(widgets)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cf2021e9-de8a-466e-b341-fcd6abda64b5",
"metadata": {},
"outputs": [],
"source": [
"update_rates = ipw.Button(description=\"Update rates\")\n",
"update_rates.on_click(show_rates)\n",
"header = ipw.HBox([update_rates])\n",
"\n",
"layout = ipw.Layout(grid_template_columns=\"1fr \" * 8)\n",
"grid = ipw.GridBox(\n",
" [],\n",
" layout=layout,\n",
")\n",
"\n",
"display(header, grid)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "19dfcbfe-eaec-406e-bb3c-72d1b3538a6e",
"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.8.12"
},
"voila": {
"theme": "dark"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,284 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "da655985-c9b7-492e-aefa-fbe3bc1865d5",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import sys\n",
"import time\n",
"from datetime import datetime, timedelta\n",
"from typing import Optional\n",
"\n",
"import ipywidgets as ipw\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib_inline.backend_inline\n",
"from ipyflex import FlexLayout\n",
"from widget_helpers import price_card, stylesheet\n",
"\n",
"from openbb_terminal import api as openbb\n",
"\n",
"%matplotlib widget\n",
"openbb.theme.applyMPLstyle()\n",
"ipw.HTML(f\"<style>{stylesheet()}</style>\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f5905453-4de6-4f5f-8012-9acdfca50987",
"metadata": {},
"outputs": [],
"source": [
"def get_exchange_rate(currency_pair: str) -> str:\n",
" \"\"\"Get exchange rate for a currency pair.\"\"\"\n",
" from_symbol, to_symbol = currency_pair.split(\"/\")\n",
" exchange_data = openbb.forex.models.av.get_quote(\n",
" to_symbol=to_symbol, from_symbol=from_symbol\n",
" )\n",
" return exchange_data[\"Realtime Currency Exchange Rate\"][\"5. Exchange Rate\"][:6]\n",
"\n",
"\n",
"def get_candle_widget(\n",
" output: Optional[ipw.Output],\n",
" to_symbol: str,\n",
" from_symbol: str,\n",
") -> ipw.Output:\n",
" \"\"\"Plot a candle chart for a currency pair.\"\"\"\n",
" start_date = datetime.now() - timedelta(days=1)\n",
" start_date = start_date.strftime(\"%Y-%m-%d\")\n",
"\n",
" exchange_rate_data = openbb.forex.models.av.get_historical(\n",
" to_symbol=to_symbol,\n",
" from_symbol=from_symbol,\n",
" start_date=start_date,\n",
" resolution=\"i\",\n",
" interval=\"15\",\n",
" )\n",
" fig, ax = plt.subplots(1, 1, figsize=(11, 4))\n",
" openbb.forex.candle(\n",
" data=exchange_rate_data,\n",
" to_symbol=to_symbol,\n",
" from_symbol=from_symbol,\n",
" external_axes=[ax],\n",
" )\n",
"\n",
" ax.set_xlim(0, len(exchange_rate_data.index))\n",
" fig.canvas.header_visible = False\n",
" fig.canvas.footer_visible = False\n",
" with output:\n",
" output.clear_output(True)\n",
" fig.canvas.show()\n",
" return output\n",
"\n",
"\n",
"def on_dropdown_change(change):\n",
" \"\"\"Update charts on change of dropdown selection.\"\"\"\n",
" if change[\"type\"] == \"change\" and change[\"name\"] == \"value\":\n",
" output = ipw.Output()\n",
" get_candle_widget(\n",
" to_symbol=to_widget.value,\n",
" from_symbol=from_widget.value,\n",
" )\n",
" dashboard.children[\"Candle\"] = output"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5c768d15-37ad-441b-b069-506c4bdbb9a7",
"metadata": {},
"outputs": [],
"source": [
"exchange_rates = {\n",
" \"EUR/USD\": {\"latest\": None, \"previous\": None},\n",
" \"USD/JPY\": {\"latest\": None, \"previous\": None},\n",
" \"GBP/USD\": {\"latest\": None, \"previous\": None},\n",
" \"AUD/USD\": {\"latest\": None, \"previous\": None},\n",
" \"USD/CAD\": {\"latest\": None, \"previous\": None},\n",
" # \"USD/CNY\": {\"latest\": None, \"previous\": None},\n",
" # \"USD/CHF\": {\"latest\": None, \"previous\": None},\n",
" # \"USD/HKD\": {\"latest\": None, \"previous\": None},\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4968ab89-aafe-4234-933c-963bd672715d",
"metadata": {},
"outputs": [],
"source": [
"def compose_widgets():\n",
" widgets = {}\n",
" for currency_pair in exchange_rates:\n",
" price = exchange_rates[currency_pair][\"latest\"]\n",
" price_color = \"neutral_color\"\n",
" if exchange_rates[currency_pair][\"previous\"] is not None:\n",
" if (\n",
" exchange_rates[currency_pair][\"latest\"]\n",
" > exchange_rates[currency_pair][\"previous\"]\n",
" ):\n",
" price_color = \"up_color\"\n",
" elif (\n",
" exchange_rates[currency_pair][\"latest\"]\n",
" < exchange_rates[currency_pair][\"previous\"]\n",
" ):\n",
" price_color = \"down_color\"\n",
" widgets[currency_pair] = ipw.HTML(\n",
" price_card(ticker=currency_pair, price=price, price_color=price_color)\n",
" )\n",
" return widgets"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f35d1500-a411-4cff-94ee-d65d4d1810f9",
"metadata": {},
"outputs": [],
"source": [
"# for currency_code in rates_to_usd:\n",
"# rates_to_usd[currency_code][\"previous\"] = rates_to_usd[currency_code][\"latest\"]\n",
"# rates_to_usd[currency_code][\"latest\"] = get_rate_against_usd(currency_code)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8a72837b-4ddd-4c01-a493-ebb430202cbc",
"metadata": {},
"outputs": [],
"source": [
"widgets = compose_widgets()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c636543c-42fe-4dd6-a900-1552a3c28c7e",
"metadata": {},
"outputs": [],
"source": [
"currency_list = openbb.forex.models.av.get_currency_list()\n",
"from_widget = ipw.Dropdown(\n",
" options=currency_list,\n",
" value=\"EUR\",\n",
" description=\"From:\",\n",
" disabled=False,\n",
" layout=ipw.Layout(margin=\"130\"),\n",
")\n",
"to_widget = ipw.Dropdown(\n",
" options=currency_list,\n",
" value=\"USD\",\n",
" description=\"To:\",\n",
" disabled=False,\n",
")\n",
"exchange_selection = ipw.VBox([from_widget, to_widget])\n",
"\n",
"widgets[\"Select\"] = exchange_selection"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9d069845-d622-4878-8b18-b385c6cb7a7f",
"metadata": {},
"outputs": [],
"source": [
"output = ipw.Output()\n",
"output = get_candle_widget(\n",
" output=output,\n",
" to_symbol=to_widget.value,\n",
" from_symbol=from_widget.value,\n",
")\n",
"widgets[\"Candle\"] = output"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "81c7e5c7-2e52-45ba-bf7d-aa240f95be2d",
"metadata": {},
"outputs": [],
"source": [
"from_widget.observe(on_dropdown_change)\n",
"to_widget.observe(on_dropdown_change)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a0c7d921-e5dc-4ce8-97f1-a59b414a676a",
"metadata": {},
"outputs": [],
"source": [
"dashboard = FlexLayout(\n",
" layout_config={\"borderLeft\": False, \"borderRight\": False, \"enableSection\": False},\n",
" style={\n",
" \"height\": \"calc(100vh - 80px)\",\n",
" \"backgroundColor\": \"rgb(0 0 0)\",\n",
" \"fontFamily\": \"Consolas\",\n",
" \"fontWeight\": 800,\n",
" },\n",
" header={\n",
" \"title\": \"Currencies\",\n",
" \"style\": {\n",
" \"backgroundColor\": \"rgb(0 0 0)\",\n",
" \"fontWeight\": 400,\n",
" \"fontSize\": \"28px\",\n",
" },\n",
" \"buttons\": [],\n",
" },\n",
" widgets=widgets,\n",
" template=os.path.join(\"widgets\", \"currencies.json\"),\n",
" editable=False,\n",
")\n",
"dashboard"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5fedac44-5e09-44f0-bbbe-fbad7c8716cd",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "3c850ba2-408b-4061-947e-5a1b8a284d22",
"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.8.12"
},
"voila": {
"theme": "dark"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,255 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true,
"jupyter": {
"outputs_hidden": true
}
},
"outputs": [],
"source": [
"import io\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"import requests\n",
"from datetime import datetime, timedelta\n",
"import ipywidgets as widgets\n",
"from IPython.display import display\n",
"\n",
"%matplotlib widget"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"class ShortDataDash:\n",
" def __init__(self):\n",
" self.df = pd.DataFrame()\n",
" self.days_slider = widgets.IntSlider(\n",
" value=5,\n",
" min=5,\n",
" max=252,\n",
" step=1,\n",
" description=\"Days Back\",\n",
" style={\"description_width\": \"initial\"},\n",
" )\n",
" self.count_slider = widgets.IntSlider(\n",
" value=10,\n",
" min=1,\n",
" max=25,\n",
" step=1,\n",
" description=\"Number to show.\",\n",
" style={\"description_width\": \"initial\"},\n",
" )\n",
" self.output1 = widgets.Output()\n",
" self.output2 = widgets.Output()\n",
" self.load_button = widgets.Button(\n",
" description=\"Load Data\", layout=widgets.Layout(width=\"200px\", height=\"40px\")\n",
" )\n",
" self.load_button.on_click(self.load_button_click)\n",
" self.show_button = widgets.Button(\n",
" description=\"Change Number Shown\", layout=self.load_button.layout\n",
" )\n",
" self.show_button.on_click(self.show_button_click)\n",
"\n",
" self.slider_box = widgets.HBox([self.days_slider, self.count_slider])\n",
" self.button_box = widgets.VBox([self.load_button, self.show_button])\n",
"\n",
" self.stock_input = widgets.Text(\n",
" value=\"GME\",\n",
" placeholder=\"GME\",\n",
" description=\"Ticker:\",\n",
" )\n",
" self.ticker_button = widgets.Button(description=\"Plot Ticker\")\n",
" self.ticker_button.on_click(self.ticker_button_click)\n",
"\n",
" def show_button_click(self, b):\n",
" self.output1.clear_output()\n",
" with self.output1:\n",
" self.update()\n",
"\n",
" def load_button_click(self, b):\n",
" self.output1.clear_output()\n",
" self.output2.clear_output()\n",
" with self.output1:\n",
" print(f\"Data Loading for {self.days_slider.value} days\")\n",
" self.fetch_new_data()\n",
" self.update()\n",
"\n",
" def ticker_button_click(self, b):\n",
" self.output2.clear_output()\n",
" with self.output2:\n",
" self.ticker_plot()\n",
"\n",
" def fetch_new_data(self):\n",
" self.df = pd.DataFrame()\n",
" today = datetime.now().date()\n",
" idx = 0\n",
" len_df = 0\n",
" while len_df < self.days_slider.value:\n",
" date = today - timedelta(days=idx)\n",
" r = requests.get(\n",
" f\"https://cdn.finra.org/equity/regsho/daily/CNMSshvol{date.strftime('%Y%m%d')}.txt\"\n",
" )\n",
" if r.status_code == 200:\n",
" self.df = pd.concat(\n",
" [self.df, pd.read_csv(io.StringIO(r.text), sep=\"|\")], axis=0\n",
" )\n",
" len_df += 1\n",
" idx += 1\n",
" self.df = self.df[self.df.Date > 20100101]\n",
" self.df.Date = self.df[\"Date\"].apply(\n",
" lambda x: datetime.strptime(str(x), \"%Y%m%d\")\n",
" )\n",
"\n",
" def update(self):\n",
" if not self.df.empty:\n",
" temp = (\n",
" self.df.groupby(\"Symbol\")[[\"ShortVolume\", \"TotalVolume\"]]\n",
" .agg(\"sum\")\n",
" .sort_values(by=\"ShortVolume\", ascending=False)\n",
" .head(self.count_slider.value)[::-1]\n",
" )\n",
" self.fig, self.ax = plt.subplots(figsize=(6, 6))\n",
" self.ax.barh(temp.index, temp.TotalVolume, alpha=0.4, label=\"Total Volume\")\n",
" self.ax.barh(temp.index, temp.ShortVolume, label=\"Short Volume\")\n",
" self.ax.set_title(\n",
" f\"Top {self.count_slider.value} Short Volume in Last {self.days_slider.value} Days\"\n",
" )\n",
" self.ax.legend()\n",
" self.fig.tight_layout()\n",
" plt.show()\n",
"\n",
" def ticker_plot(self):\n",
" stock_data = self.df.copy().loc[\n",
" self.df.Symbol == self.stock_input.value,\n",
" [\"Date\", \"ShortVolume\", \"TotalVolume\"],\n",
" ]\n",
" self.fig2, self.ax2 = plt.subplots(figsize=(6, 6))\n",
" self.ax2.plot(\n",
" stock_data.Date, stock_data.TotalVolume, alpha=0.4, label=\"Total Volume\"\n",
" )\n",
" self.ax2.plot(stock_data.Date, stock_data.ShortVolume, label=\"Short Volume\")\n",
" self.ax2.set_title(\n",
" f\"Stock Volume and Short Volume for {self.stock_input.value.upper()}\"\n",
" )\n",
" self.ax2.legend()\n",
" self.fig2.autofmt_xdate()\n",
" self.fig2.tight_layout()\n",
" plt.show()\n",
"\n",
" def build_app(self):\n",
" title_html = \"\"\"\n",
"<h2>Finra Short Data</h2>\n",
"<p>This widget downloads the consolidated NMS short data from FINRA and aggregates the data by summing over the entire time period.</p>\n",
"<p>Note that clicking the 'Load Data' button will reload all data. This can get time consuming, so if you pick a few hundred days, expect a few minutes for loading time.</p>\n",
"\"\"\"\n",
" middle_html = \"\"\"\n",
"Here we allow the user to query for a single stock. This will work with the loaded data. Note that if you want to reload the data, this will once again take some time.\n",
" \"\"\"\n",
" return [\n",
" widgets.HTML(\n",
" title_html, layout=widgets.Layout(margin=\"0 0 3em 0\", max_width=\"800px\")\n",
" ),\n",
" self.slider_box,\n",
" self.button_box,\n",
" self.output1,\n",
" widgets.HTML(\n",
" middle_html,\n",
" layout=widgets.Layout(margin=\"0 0 3em 0\", max_width=\"800px\"),\n",
" ),\n",
" self.stock_input,\n",
" self.ticker_button,\n",
" self.output2,\n",
" ]"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"dash = ShortDataDash()\n",
"app = widgets.VBox(\n",
" dash.build_app(), layout=widgets.Layout(max_width=\"1024px\", margin=\"0 auto 0 auto\")\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
},
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "dcda08c8d643465fb862d01341d71370",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(HTML(value=\"\\n<h2>Finra Short Data</h2>\\n<p>This widget downloads the consolidated NMS short da…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"display(app)"
]
}
],
"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.8.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

View File

@@ -1,404 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "e9ad60bc",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from datetime import datetime, timedelta\n",
"import ipywidgets as widgets\n",
"import plotly.graph_objs as go\n",
"import yfinance as yf\n",
"import pandas as pd\n",
"from IPython.display import display"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "beb36881",
"metadata": {},
"outputs": [],
"source": [
"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",
"rows = [\n",
" \"sector\",\n",
" \"marketCap\",\n",
" \"beta\",\n",
" \"fiftyTwoWeekHigh\",\n",
" \"fiftyTwoWeekLow\",\n",
" \"floatShares\",\n",
" \"sharesShort\",\n",
" \"exDividendDate\",\n",
"]\n",
"\n",
"views = {\n",
" \"Raw Data\": lambda x, y: x,\n",
" \"Percent Change\": lambda x, y: x.pct_change(),\n",
" \"Rolling Average\": lambda x, y: x.rolling(y).mean(),\n",
" \"Rolling Variance\": lambda x, y: x.rolling(y).var(),\n",
" \"Rolling Standard Deviation\": lambda x, y: x.rolling(y).var() ** 0.5,\n",
" \"Rolling Coefficient of Variation\": lambda x, y: (x.rolling(y).var() ** 0.5)\n",
" / (x.rolling(y).mean()),\n",
"}\n",
"\n",
"clean_row = {\n",
" \"sector\": \"Sector\",\n",
" \"marketCap\": \"M Cap\",\n",
" \"beta\": \"Beta\",\n",
" \"fiftyTwoWeekHigh\": \"52W High\",\n",
" \"fiftyTwoWeekLow\": \"52W Low\",\n",
" \"floatShares\": \"Floats\",\n",
" \"sharesShort\": \"Shorts\",\n",
" \"exDividendDate\": \"Ex-Div\",\n",
"}\n",
"\n",
"clean_data = {\n",
" \"sector\": lambda x: \"N/A\" if x is None else x,\n",
" \"marketCap\": lambda x: \"N/A\" if x is None else big_num(x),\n",
" \"beta\": lambda x: \"N/A\" if x is None else f\"{round(x,2)}\",\n",
" \"fiftyTwoWeekHigh\": lambda x: \"N/A\" if x is None else f\"${round(x,2)}\",\n",
" \"fiftyTwoWeekLow\": lambda x: \"N/A\" if x is None else f\"${round(x,2)}\",\n",
" \"floatShares\": lambda x: \"N/A\" if x is None else big_num(x),\n",
" \"sharesShort\": lambda x: \"N/A\" if x is None else big_num(x),\n",
" \"exDividendDate\": lambda x: \"N/A\"\n",
" if x is None\n",
" else datetime.fromtimestamp(x).strftime(\"%Y/%m/%d\"),\n",
"}\n",
"\n",
"\n",
"def big_num(num):\n",
" if num > 1_000_000_000_000:\n",
" return f\"{round(num/1_000_000_000_000,2)}T\"\n",
" if num > 1_000_000_000:\n",
" return f\"{round(num/1_000_000_000,2)}B\"\n",
" if num > 1_000_000:\n",
" return f\"{round(num/1_000_000,2)}M\"\n",
" if num > 1_000:\n",
" return f\"{num/round(1_000,2)}K\"\n",
" return f\"{round(num,2)}\"\n",
"\n",
"\n",
"def clean_str(string):\n",
" new_str = \"\"\n",
" for letter in string:\n",
" if letter.isupper():\n",
" new_str += \" \"\n",
" new_str += letter\n",
" return new_str.title()\n",
"\n",
"\n",
"def format_plotly(fig, data, start, end, chart, calc=None):\n",
" fig.update_yaxes(title=None)\n",
" fig.update_xaxes(title=None)\n",
" start_t = start.strftime(\"%Y/%m/%d\")\n",
" end_t = end.strftime(\"%Y/%m/%d\")\n",
" if calc:\n",
" if len(calc) == 1:\n",
" fig_title = f\"{calc[0]} of {data} from {start_t} to {end_t}\"\n",
" else:\n",
" fig_title = f\"{', '.join(calc)} of {data} from {start_t} to {end_t}\"\n",
" else:\n",
" fig_title = \"Volume\"\n",
" height = 500 if chart == \"main\" else 300\n",
" fig.update_layout(\n",
" margin=dict(l=0, r=10, t=10, b=10),\n",
" autosize=False,\n",
" width=900,\n",
" height=height,\n",
" legend=dict(orientation=\"h\"),\n",
" title={\n",
" \"text\": fig_title,\n",
" \"y\": 0.95,\n",
" \"x\": 0.5,\n",
" \"xanchor\": \"center\",\n",
" \"yanchor\": \"top\",\n",
" },\n",
" )\n",
"\n",
"\n",
"def create_line(visual, x, y, name, data, fig):\n",
" if visual == \"line\":\n",
" plot = go.Scatter(x=x, y=y[data], mode=\"lines\", name=name, connectgaps=True)\n",
" if visual == \"scatter\":\n",
" plot = go.Scatter(x=x, y=y[data], mode=\"markers\", name=name)\n",
" if visual == \"candle\":\n",
" plot = go.Candlestick(\n",
" x=x,\n",
" open=y[\"Open\"],\n",
" close=y[\"Close\"],\n",
" high=y[\"High\"],\n",
" low=y[\"Low\"],\n",
" name=name,\n",
" )\n",
" fig.add_trace(plot)\n",
"\n",
"\n",
"def show_fig(fig):\n",
" config = {\"showTips\": False, \"scrollZoom\": True}\n",
" if os.environ.get(\"SERVER_SOFTWARE\", \"jupyter\").startswith(\"voila\"):\n",
" fig.show(config=config, renderer=\"notebook\")\n",
" else:\n",
" fig.show(config=config)\n",
"\n",
"\n",
"def table_data(infos):\n",
" cols = [\"Ticker\"] + list(infos)\n",
" data = pd.DataFrame(columns=cols)\n",
" data[\"Ticker\"] = [clean_row[x] for x in rows]\n",
" for ticker in list(infos):\n",
" data[ticker] = [clean_data[x](infos[ticker].get(x, None)) for x in rows]\n",
" new_cols = {k: clean_str(k) for k in rows}\n",
" return data"
]
},
{
"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.infos = {}\n",
"\n",
" def create_stock(\n",
" self, calculation, data, rolling, start, end, interval, tickers, chart\n",
" ):\n",
" if tickers and tickers[-1] == \",\":\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.last_tickers = tickers\n",
" self.last_interval = interval\n",
"\n",
" start_n = datetime(start.year, start.month, start.day)\n",
" end_n = datetime(end.year, end.month, end.day)\n",
" fig = go.Figure()\n",
" for item in calculation:\n",
" calcs = views[item](self.df, rolling)\n",
" if interval in [\"1d\", \"5d\", \"1wk\", \"1mo\", \"3mo\"]:\n",
" result = calcs.loc[\n",
" (calcs.index >= start_n) & (calcs.index <= end_n)\n",
" ]\n",
" else:\n",
" result = calcs\n",
"\n",
" if len(result.columns) == 6:\n",
" name = f\"{tickers.split(',')[0]} {item}\"\n",
" create_line(chart, result.index, result, name, data, fig)\n",
"\n",
" else:\n",
" for val in result.columns.levels[1]:\n",
" vals = result.xs(val, axis=1, level=1, drop_level=True)\n",
" name = f\"{val.upper()} {item}\"\n",
" create_line(chart, result.index, vals, name, data, fig)\n",
"\n",
" format_plotly(fig, data, start, end, \"main\", calculation)\n",
" show_fig(fig)\n",
"\n",
" def create_volume(self, start, end, interval, tickers):\n",
" start_n = datetime(start.year, start.month, start.day)\n",
" end_n = datetime(end.year, end.month, end.day)\n",
" result = self.df.loc[(self.df.index >= start_n) & (self.df.index <= end_n)]\n",
" fig = go.Figure()\n",
" if len(result.columns) == 6:\n",
" name = f\"{tickers.split(',')[0]}\"\n",
" create_line(\"line\", result.index, result, name, \"Volume\", fig)\n",
" else:\n",
" for val in result.columns.levels[1]:\n",
" vals = result.xs(val, axis=1, level=1, drop_level=True)\n",
" name = f\"{val.upper()}\"\n",
" create_line(\"line\", result.index, vals, name, \"Volume\", fig)\n",
" format_plotly(fig, \"Volume\", start, end, \"volume\")\n",
" show_fig(fig)\n",
"\n",
" def create_table(self, tickers):\n",
" if tickers and tickers[-1] == \",\":\n",
" clean_tickers = [x for x in tickers.split(\",\") if x]\n",
" for ticker in clean_tickers:\n",
" if ticker not in self.infos:\n",
" self.infos[ticker] = yf.Ticker(ticker).info\n",
" for ticker in self.infos:\n",
" if ticker not in tickers:\n",
" self.infos.pop(ticker)\n",
" result = table_data(self.infos)\n",
" fig = go.Figure(\n",
" data=[\n",
" go.Table(\n",
" header=dict(\n",
" values=result.columns,\n",
" fill_color=\"lightgray\",\n",
" font=dict(color=\"black\"),\n",
" align=\"left\",\n",
" ),\n",
" cells=dict(\n",
" values=[result[x] for x in result.columns],\n",
" font=dict(color=\"black\"),\n",
" align=\"left\",\n",
" ),\n",
" )\n",
" ],\n",
" )\n",
" fig.update_layout(margin=dict(l=0, r=20, t=0, b=0), width=350)\n",
" show_fig(fig)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e0d4de31-1b4f-4c1f-8467-ca314a578d56",
"metadata": {},
"outputs": [],
"source": [
"w_auto = widgets.Layout(width=\"auto\")\n",
"calc_widget = widgets.SelectMultiple(\n",
" options=list(views.keys()), value=[\"Raw Data\"], layout=w_auto\n",
")\n",
"\n",
"data_opts = [\"Open\", \"Close\", \"High\", \"Low\"]\n",
"data_widget = widgets.Dropdown(\n",
" options=data_opts, value=\"Close\", layout=w_auto, description=\"Data\"\n",
")\n",
"rolling_widget = widgets.Dropdown(\n",
" options=list(range(2, 101)), value=60, layout=w_auto, description=\"Rolling\"\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",
"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",
"chart_opts = [\"line\", \"scatter\", \"candle\"]\n",
"chart_widget = widgets.Dropdown(\n",
" options=chart_opts, value=\"line\", layout=w_auto, description=\"Chart\"\n",
")\n",
"data_box = widgets.VBox([data_widget, rolling_widget, chart_widget])\n",
"date_box = widgets.VBox([start_widget, end_widget, interval_widget])\n",
"controls = widgets.HBox(\n",
" [tickers_widget, calc_widget, date_box, data_box],\n",
" layout=widgets.Layout(width=\"90%\"),\n",
")\n",
"chart = Chart()\n",
"stocks_view = widgets.interactive_output(\n",
" chart.create_stock,\n",
" {\n",
" \"calculation\": calc_widget,\n",
" \"data\": data_widget,\n",
" \"rolling\": rolling_widget,\n",
" \"start\": start_widget,\n",
" \"end\": end_widget,\n",
" \"interval\": interval_widget,\n",
" \"tickers\": tickers_widget,\n",
" \"chart\": chart_widget,\n",
" },\n",
")\n",
"\n",
"volume_view = widgets.interactive_output(\n",
" chart.create_volume,\n",
" {\n",
" \"start\": start_widget,\n",
" \"end\": end_widget,\n",
" \"interval\": interval_widget,\n",
" \"tickers\": tickers_widget,\n",
" },\n",
")\n",
"\n",
"table_view = widgets.interactive_output(chart.create_table, {\"tickers\": tickers_widget})\n",
"\n",
"charts = widgets.VBox(\n",
" [stocks_view, volume_view],\n",
" layout=widgets.Layout(width=\"100%\", padding=\"0\", margin=\"0\"),\n",
")\n",
"figures = widgets.HBox(\n",
" [charts, table_view], layout=widgets.Layout(padding=\"0\", margin=\"0\")\n",
")\n",
"\n",
"title_html = \"<h1>Stock Analysis Dashboard</h1>\"\n",
"warning_html = '<p style=\"color:red\"=>Use a comma after EVERY stock typed.</p>'\n",
"\n",
"app_contents = [widgets.HTML(title_html), controls, widgets.HTML(warning_html), figures]\n",
"app = widgets.VBox(app_contents)\n",
"display(app)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8f33793c-adc9-4bc1-8fd4-aeff5a00ccba",
"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.8.12"
},
"metadata": {
"interpreter": {
"hash": "e896a00ead8b521528d79ac9ef24990696f2b751eb283ab8e0d078c9c4971ffc"
}
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,162 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "68b664c7-c52d-42c1-b170-575370323d22",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import warnings\n",
"import sys\n",
"import ipywidgets as widgets\n",
"import plotly.graph_objects as go\n",
"import numpy as np\n",
"import pandas as pd\n",
"from IPython.display import display\n",
"\n",
"warnings.filterwarnings(\"ignore\")\n",
"module_path = os.path.abspath(os.path.join(\"../../..\"))\n",
"\n",
"if module_path not in sys.path:\n",
" sys.path.append(module_path)\n",
"\n",
"from openbb_terminal import api as openbb"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6c98dc75-6325-43da-93a2-1b8ec96bd368",
"metadata": {},
"outputs": [],
"source": [
"z_dict = {\n",
" \"IV\": \"Implied Volatility\",\n",
" \"OI\": \"Open Interest\",\n",
" \"LP\": \"Last Price\",\n",
"}\n",
"strings = {\n",
" \"IV\": \"DTE: %{x} <br>Strike: %{y} <br>IV: %{z}<extra></extra>\",\n",
" \"OI\": \"DTE: %{x} <br>Strike: %{y} <br>OI: %{z}<extra></extra>\",\n",
" \"LP\": \"DTE: %{x} <br>Strike: %{y} <br>LP: %{z}<extra></extra>\",\n",
"}\n",
"\n",
"\n",
"def create_layout(fig, width, height, z, ticker):\n",
" fig.update_layout(\n",
" title=f\"{z.upper()} Surface for {ticker.upper()}\",\n",
" autosize=False,\n",
" width=width,\n",
" height=height,\n",
" scene=dict(\n",
" xaxis_title=\"Days to Expiration\",\n",
" yaxis_title=\"Strike\",\n",
" zaxis_title=z_dict[z],\n",
" ),\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c1bc5c6a-ccb2-4ef5-9c79-1f619fbf95a6",
"metadata": {},
"outputs": [],
"source": [
"class Chart:\n",
" def __init__(self):\n",
" self.last_ticker = \"\"\n",
" self.df = pd.DataFrame()\n",
"\n",
" def create(self, z, ticker, height, width):\n",
" if ticker:\n",
" if ticker != self.last_ticker:\n",
" self.df = openbb.stocks.options.models.yfinance.get_iv_surface(ticker)\n",
" self.last_ticker = ticker\n",
"\n",
" if not self.df.empty:\n",
" z_dict = {\n",
" \"IV\": self.df.impliedVolatility,\n",
" \"OI\": self.df.openInterest,\n",
" \"LP\": self.df.lastPrice,\n",
" }\n",
" fig = go.Figure(\n",
" data=[\n",
" go.Mesh3d(\n",
" z=z_dict[z],\n",
" x=self.df.dte,\n",
" y=self.df.strike,\n",
" intensity=np.sqrt(z_dict[z]),\n",
" colorscale=\"Jet\",\n",
" hovertemplate=strings[z],\n",
" showscale=False,\n",
" )\n",
" ]\n",
" )\n",
"\n",
" create_layout(fig, height, width, z, ticker)\n",
" if os.environ.get(\"SERVER_SOFTWARE\", \"jupyter\").startswith(\"voila\"):\n",
" fig.show(config={\"showTips\": False}, renderer=\"notebook\")\n",
" else:\n",
" fig.show(config={\"showTips\": False})\n",
"\n",
"\n",
"opts = [\"IV\", \"OI\", \"LP\"]\n",
"z_widget = widgets.Dropdown(options=opts, value=\"IV\", description=\"Data\")\n",
"tickers_widget = widgets.Text(description=\"Ticker\", value=\"TSLA\")\n",
"h_widget = widgets.IntText(value=1000, description=\"Height\")\n",
"w_widget = widgets.IntText(value=1000, description=\"Width\")\n",
"\n",
"controls = widgets.VBox([tickers_widget, z_widget])\n",
"size = widgets.VBox([h_widget, w_widget])\n",
"controls = widgets.HBox([controls, size])\n",
"\n",
"chart = Chart()\n",
"stocks_view = widgets.interactive_output(\n",
" chart.create,\n",
" {\"z\": z_widget, \"ticker\": tickers_widget, \"height\": h_widget, \"width\": w_widget},\n",
")\n",
"\n",
"title_html = \"<h1>Option Surface Dashboard</h1>\"\n",
"app_contents = [\n",
" widgets.HTML(title_html),\n",
" controls,\n",
" stocks_view,\n",
"]\n",
"app = widgets.VBox(app_contents)\n",
"display(app)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "014f267a-92ba-4f23-afb1-9720d8a68cbb",
"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.8.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,62 +0,0 @@
"""Jupyter Controller Module"""
__docformat__ = "numpy"
import logging
from typing import List
from prompt_toolkit.completion import NestedCompleter
from openbb_terminal import feature_flags as obbff
from openbb_terminal.decorators import log_start_end
from openbb_terminal.menu import session
from openbb_terminal.parent_classes import BaseController
from openbb_terminal.rich_config import console
# pylint: disable=import-outside-toplevel
logger = logging.getLogger(__name__)
class JupyterController(BaseController):
"""Resources Controller class"""
CHOICES_COMMANDS = [
"reports",
"dashboards",
]
PATH = "/jupyter/"
def __init__(self, queue: List[str] = None):
"""Constructor"""
super().__init__(queue)
if session and obbff.USE_PROMPT_TOOLKIT:
choices: dict = {c: {} for c in self.controller_choices}
self.completer = NestedCompleter.from_nested_dict(choices)
def print_help(self):
"""Print help"""
help_text = """[menu]
> reports creates jupyter reports
> dashboards shows interactive jupyter dashboards[/menu]
"""
console.print(text=help_text, menu="Jupyter")
@log_start_end(log=logger)
def call_reports(self, _):
"""Process reports command"""
from openbb_terminal.jupyter.reports.reports_controller import (
ReportController,
)
self.queue = self.load_class(ReportController, self.queue)
@log_start_end(log=logger)
def call_dashboards(self, _):
"""Process dashboards command"""
from openbb_terminal.jupyter.dashboards.dashboards_controller import (
DashboardsController,
)
self.queue = self.load_class(DashboardsController, self.queue)

View File

@@ -1,281 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "elect-highway",
"metadata": {},
"outputs": [],
"source": [
"# Import most generic modules\n",
"import os\n",
"import sys\n",
"from datetime import datetime\n",
"from IPython.display import display, Markdown\n",
"import warnings\n",
"\n",
"warnings.filterwarnings(\"ignore\")\n",
"module_path = os.path.abspath(os.path.join(\"../../..\"))\n",
"\n",
"if module_path not in sys.path:\n",
" sys.path.append(module_path)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fatty-colony",
"metadata": {
"tags": [
"parameters"
]
},
"outputs": [],
"source": [
"report_name = f\"{datetime.now().strftime('%Y%m%d_%H%M%S')}_crypto_market\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "medieval-majority",
"metadata": {},
"outputs": [],
"source": [
"display(Markdown(f\"# Crypto Market - {datetime.now().strftime('%Y/%m/%d %H:%M:%S')}\"))"
]
},
{
"cell_type": "markdown",
"id": "basic-sucking",
"metadata": {},
"source": [
"## Bitcoin Chart"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "318022a0",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.cryptocurrency import cryptocurrency_helpers\n",
"import pandas as pd\n",
"\n",
"coin_map_df = (\n",
" cryptocurrency_helpers.prepare_all_coins_df().set_index(\"Symbol\").loc[\"btc\"]\n",
")\n",
"\n",
"coin_map_df = (\n",
" coin_map_df.dropna().iloc[0]\n",
" if isinstance(coin_map_df, pd.DataFrame)\n",
" else coin_map_df\n",
")\n",
"\n",
"cryptocurrency_helpers.plot_chart(\n",
" coin=\"btc-bitcoin\", source=\"cp\", currency=\"USD\", days=60, coin_map_df=coin_map_df\n",
")"
]
},
{
"cell_type": "markdown",
"id": "animal-titanium",
"metadata": {},
"source": [
"## Global Market Information"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "artistic-stewart",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.cryptocurrency.overview import coinpaprika_view\n",
"\n",
"coinpaprika_view.display_global_market(export=\"\")"
]
},
{
"cell_type": "markdown",
"id": "twelve-visiting",
"metadata": {},
"source": [
"## Top coins market information"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "photographic-payday",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.cryptocurrency.overview import coinpaprika_view\n",
"\n",
"coinpaprika_view.display_all_coins_market_info(\n",
" currency=\"USD\", sortby=\"volume_24h\", descend=True, top=10, export=\"\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "median-spirituality",
"metadata": {},
"source": [
"## Top gainers in last 24h"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "threaded-archives",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.cryptocurrency.discovery import pycoingecko_view\n",
"\n",
"pycoingecko_view.display_gainers(period=\"24h\", top=10, export=\"\")"
]
},
{
"cell_type": "markdown",
"id": "recognized-intent",
"metadata": {},
"source": [
"## Top losers in last 24h"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "exceptional-objective",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.cryptocurrency.discovery import pycoingecko_view\n",
"\n",
"pycoingecko_view.display_losers(period=\"24h\", top=10, export=\"\")"
]
},
{
"cell_type": "markdown",
"id": "rough-routine",
"metadata": {},
"source": [
"## Coins trending on coingecko"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "matched-syria",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.cryptocurrency.discovery import pycoingecko_view\n",
"\n",
"pycoingecko_view.display_trending(\n",
" export=\"\",\n",
")"
]
},
{
"cell_type": "markdown",
"id": "established-order",
"metadata": {},
"source": [
"## Decentralized Finance Global Market Info"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "artistic-grocery",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.cryptocurrency.overview import pycoingecko_view\n",
"\n",
"pycoingecko_view.display_global_defi_info(export=\"\")"
]
},
{
"cell_type": "markdown",
"id": "elect-universe",
"metadata": {},
"source": [
"## Top DeFi Coins"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "configured-macedonia",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.cryptocurrency.discovery import pycoingecko_view\n",
"\n",
"pycoingecko_view.display_coins(\"decentralized-finance-defi\", top=10, export=\"\")"
]
},
{
"cell_type": "markdown",
"id": "comparative-congo",
"metadata": {},
"source": [
"## Top Decentralized Exchanges"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "scientific-healthcare",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.cryptocurrency.discovery import dappradar_view\n",
"\n",
"dappradar_view.display_top_dexes(top=10, export=\"\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "knowing-imagination",
"metadata": {},
"outputs": [],
"source": [
"!jupyter nbconvert {report_name + '.ipynb'} --to html --no-input"
]
}
],
"metadata": {
"celltoolbar": "Tags",
"interpreter": {
"hash": "158b8ab50e95ded652d8f2b468df64cac8eaa223c5e60f12cdaaeaccc6039b6d"
},
"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.8.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,253 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "driven-billion",
"metadata": {},
"outputs": [],
"source": [
"# Import most generic modules\n",
"import importlib\n",
"import pathlib\n",
"import os\n",
"import sys\n",
"from datetime import datetime, timedelta\n",
"import pandas as pd\n",
"from IPython.display import display, Markdown\n",
"import warnings\n",
"\n",
"warnings.filterwarnings(\"ignore\")\n",
"module_path = os.path.abspath(os.path.join(\"../..\"))\n",
"\n",
"if module_path not in sys.path:\n",
" sys.path.append(module_path)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "intended-sherman",
"metadata": {
"tags": [
"parameters"
]
},
"outputs": [],
"source": [
"# Parameters that will be replaced when calling this notebook\n",
"ticker = \"AMC\"\n",
"\n",
"report_name = f\"{datetime.now().strftime('%Y%m%d_%H%M%S')}_dark_pool_{ticker.upper()}\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "mounted-phase",
"metadata": {},
"outputs": [],
"source": [
"display(\n",
" Markdown(\n",
" f\"# {ticker.upper()} - Dark Pool - {datetime.now().strftime('%Y/%m/%d %H:%M:%S')}\"\n",
" )\n",
")"
]
},
{
"cell_type": "markdown",
"id": "capable-allergy",
"metadata": {},
"source": [
"## Top 10 Negative Dark Pool Positions"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "statewide-debate",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.stocks.dark_pool_shorts import stockgrid_view\n",
"\n",
"stockgrid_view.dark_pool_short_positions(\n",
" num=10, sort_field=\"dpp_dollar\", ascending=True, export=\"\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "artificial-tampa",
"metadata": {},
"source": [
"## Top 10 Most Highly Shorted Stocks"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "smaller-association",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.stocks.dark_pool_shorts import shortinterest_view\n",
"\n",
"shortinterest_view.high_short_interest(num=10, export=\"\")"
]
},
{
"cell_type": "markdown",
"id": "cleared-contemporary",
"metadata": {},
"source": [
"## Dark Pool Activity"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "medical-tomato",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.stocks.dark_pool_shorts import stockgrid_view\n",
"\n",
"stockgrid_view.net_short_position(ticker=ticker.upper(), num=60, raw=False, export=\"\")\n",
"\n",
"stockgrid_view.net_short_position(ticker=ticker.upper(), num=10, raw=True, export=\"\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "comprehensive-nashville",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.stocks.dark_pool_shorts import stockgrid_view\n",
"\n",
"stockgrid_view.short_interest_volume(\n",
" ticker=ticker.upper(), num=60, raw=False, export=\"\"\n",
")\n",
"\n",
"stockgrid_view.short_interest_volume(ticker=ticker.upper(), num=10, raw=True, export=\"\")"
]
},
{
"cell_type": "markdown",
"id": "decreased-mills",
"metadata": {},
"source": [
"## Options info"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "medical-shaft",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.stocks.options import barchart_view\n",
"\n",
"barchart_view.print_options_data(ticker=ticker.upper(), export=\"\")"
]
},
{
"cell_type": "markdown",
"id": "understood-houston",
"metadata": {},
"source": [
"## Put and Call Open Interest Expiring next"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "acute-burning",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.stocks.options import yfinance_model, yfinance_view\n",
"\n",
"selected_date = yfinance_model.option_expirations(ticker)[0]\n",
"options = yfinance_model.get_option_chain(ticker, selected_date)\n",
"\n",
"yfinance_view.plot_oi(\n",
" ticker=ticker,\n",
" expiry=selected_date,\n",
" min_sp=-1,\n",
" max_sp=-1,\n",
" calls_only=False,\n",
" puts_only=False,\n",
" export=\"\",\n",
")"
]
},
{
"cell_type": "markdown",
"id": "convinced-orleans",
"metadata": {},
"source": [
"## Failure-to-deliver (30 days lag)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "capital-narrow",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.stocks import stocks_helper\n",
"from openbb_terminal.stocks.dark_pool_shorts import sec_view\n",
"\n",
"stock = stocks_helper.load(ticker)\n",
"\n",
"sec_view.fails_to_deliver(\n",
" ticker=ticker.upper(),\n",
" stock=stock,\n",
" start=datetime.now() - timedelta(days=60),\n",
" end=datetime.now(),\n",
" num=0,\n",
" raw=False,\n",
" export=\"\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "above-prior",
"metadata": {},
"outputs": [],
"source": [
"!jupyter nbconvert {report_name + \".ipynb\"} --to html --no-input"
]
}
],
"metadata": {
"celltoolbar": "Tags",
"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.8.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,453 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "70ba2c8a",
"metadata": {},
"source": [
"## Notebook setup"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "driven-billion",
"metadata": {},
"outputs": [],
"source": [
"import io\n",
"import warnings\n",
"from datetime import datetime, timedelta\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib_inline.backend_inline\n",
"\n",
"from openbb_terminal import api as openbb\n",
"from openbb_terminal.helper_classes import TerminalStyle\n",
"\n",
"%matplotlib inline\n",
"matplotlib_inline.backend_inline.set_matplotlib_formats(\"svg\")\n",
"warnings.filterwarnings(\"ignore\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370",
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" theme = TerminalStyle(\"light\", \"light\", \"light\")\n",
"except:\n",
" pass\n",
"stylesheet = openbb.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",
"ticker = \"AMC\"\n",
"report_name = \"\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b",
"metadata": {},
"outputs": [],
"source": [
"ticker_data = openbb.stocks.load(ticker, start=datetime.now() - timedelta(days=365))\n",
"ticker_data = openbb.stocks.process_candle(ticker_data)\n",
"\n",
"report_title = f\"{ticker.upper()} Due Diligence report ({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})\"\n",
"report_title"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e3b15d6f-dc9e-4f97-aa07-37d949a4e4bb",
"metadata": {},
"outputs": [],
"source": [
"overview = openbb.stocks.fa.models.yahoo_finance.get_info(ticker=ticker).transpose()[\n",
" \"Long business summary\"\n",
"][0]\n",
"overview"
]
},
{
"cell_type": "markdown",
"id": "f8a0d747",
"metadata": {},
"source": [
"## Data"
]
},
{
"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.dd.models.business_insider.get_estimates(ticker)"
]
},
{
"cell_type": "markdown",
"id": "b9c8feff",
"metadata": {
"tags": []
},
"source": [
"### 1. Yearly Estimates"
]
},
{
"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)\n",
"df_year_estimates"
]
},
{
"cell_type": "markdown",
"id": "64d3d490",
"metadata": {
"tags": []
},
"source": [
"### 2. Quarterly Earnings"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fde46353",
"metadata": {},
"outputs": [],
"source": [
"df_quarter_earnings"
]
},
{
"cell_type": "markdown",
"id": "d13a1e5e",
"metadata": {
"tags": []
},
"source": [
"### 3. Quarterly Revenues"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "51dfd9d2",
"metadata": {},
"outputs": [],
"source": [
"df_quarter_revenues"
]
},
{
"cell_type": "markdown",
"id": "6303e520",
"metadata": {
"tags": []
},
"source": [
"### 4. SEC Filings"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3022130e",
"metadata": {},
"outputs": [],
"source": [
"df_sec_filings = openbb.stocks.dd.models.marketwatch.get_sec_filings(ticker)[\n",
" [\"Type\", \"Category\", \"Link\"]\n",
"].head(5)\n",
"df_sec_filings"
]
},
{
"cell_type": "markdown",
"id": "1e201003",
"metadata": {
"tags": []
},
"source": [
"### 5. Analyst Ratings"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4662b1ac",
"metadata": {},
"outputs": [],
"source": [
"df_analyst = openbb.stocks.dd.models.finviz.get_analyst_data(ticker)\n",
"df_analyst[\"target_to\"] = df_analyst[\"target_to\"].combine_first(df_analyst[\"target\"])\n",
"df_analyst = df_analyst[[\"category\", \"analyst\", \"rating\", \"target_to\"]].rename(\n",
" columns={\n",
" \"category\": \"Category\",\n",
" \"analyst\": \"Analyst\",\n",
" \"rating\": \"Rating\",\n",
" \"target_to\": \"Price Target\",\n",
" }\n",
")\n",
"df_analyst"
]
},
{
"cell_type": "markdown",
"id": "680b2b57",
"metadata": {},
"source": [
"# Testing - Invesment Thesis"
]
},
{
"cell_type": "markdown",
"id": "ade589d6-d80f-4651-acb7-929943114ef0",
"metadata": {},
"source": [
"## Plots"
]
},
{
"cell_type": "markdown",
"id": "621ed931-57e9-4ca6-afe8-8ef278122c77",
"metadata": {},
"source": [
"### 1. Price history"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "394668e1-1158-4a2b-8a38-04c72a6abdd6",
"metadata": {},
"outputs": [],
"source": [
"fig, (candles, volume) = plt.subplots(nrows=2, ncols=1, figsize=(5, 3), dpi=150)\n",
"openbb.stocks.candle(\n",
" s_ticker=ticker,\n",
" df_stock=ticker_data,\n",
" use_matplotlib=True,\n",
" external_axes=[candles, volume],\n",
")\n",
"candles.set_xticklabels(\"\")\n",
"fig.tight_layout()\n",
"\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"price_chart = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "markdown",
"id": "bf07a909",
"metadata": {},
"source": [
"### 2. Price Target"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "900686a3",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(8, 3), dpi=150)\n",
"openbb.stocks.dd.pt(\n",
" ticker=ticker,\n",
" start=\"2021-10-25\",\n",
" interval=\"1440min\",\n",
" stock=ticker_data,\n",
" num=10,\n",
" raw=False,\n",
" external_axes=[ax],\n",
")\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"price_target_chart = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "markdown",
"id": "63c0538c",
"metadata": {},
"source": [
"### 3. Ratings over time"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3733ff2",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(8, 3), dpi=150)\n",
"openbb.stocks.dd.rot(\n",
" ticker=ticker,\n",
" num=10,\n",
" raw=False,\n",
" export=\"\",\n",
" external_axes=[ax],\n",
")\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"ratings_over_time_chart = f.getvalue().decode(\"utf-8\")"
]
},
{
"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": "mounted-phase",
"metadata": {},
"outputs": [],
"source": [
"body = \"\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "abfe37e4-ea38-42c3-8fb5-7cceb233fb12",
"metadata": {},
"outputs": [],
"source": [
"# Title\n",
"body += openbb.widgets.h(1, report_title)\n",
"\n",
"body += openbb.widgets.h(2, \"Overview\")\n",
"body += openbb.widgets.row([openbb.widgets.p(overview)])\n",
"\n",
"\n",
"# Analysts ratings\n",
"body += openbb.widgets.h(2, \"Analyst assessments\")\n",
"body += openbb.widgets.row([price_target_chart])\n",
"body += openbb.widgets.row([df_analyst.to_html()])\n",
"body += openbb.widgets.row([ratings_over_time_chart])\n",
"\n",
"# Price history and yearly estimates\n",
"body += openbb.widgets.row(\n",
" [\n",
" openbb.widgets.h(3, \"Price history\") + price_chart,\n",
" openbb.widgets.h(3, \"Estimates\") + df_year_estimates.head().to_html(),\n",
" ]\n",
")\n",
"\n",
"# Earnings and revenues\n",
"body += openbb.widgets.h(2, \"Earnings and revenues\")\n",
"body += openbb.widgets.row([df_quarter_earnings.head().to_html()])\n",
"body += openbb.widgets.row([df_quarter_revenues.head().to_html()])\n",
"\n",
"# Sec filings and insider trading\n",
"body += openbb.widgets.h(2, \"SEC filings\")\n",
"body += openbb.widgets.row([df_sec_filings.to_html()])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eb26492f-d13f-4302-b36d-ea8ee0020f82",
"metadata": {},
"outputs": [],
"source": [
"report = openbb.widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ee07c30c-9b38-4035-b128-20b7c9989951",
"metadata": {},
"outputs": [],
"source": [
"# to save the results\n",
"with open(report_name + \".html\", \"w\") as fh:\n",
" fh.write(report)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "34991096-bc3a-4134-b519-aa3a490abe98",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"celltoolbar": "Tags",
"interpreter": {
"hash": "31090e8428bc3cbe850895ffb75aca3a30f914a21038b56ab61f04d2ddd7301b"
},
"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.8.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,648 +0,0 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "another-behalf",
"metadata": {},
"outputs": [],
"source": [
"# Import most generic modules\n",
"import importlib\n",
"import pathlib\n",
"import os\n",
"import sys\n",
"from datetime import datetime\n",
"from IPython.display import display, Markdown\n",
"import warnings\n",
"\n",
"warnings.filterwarnings(\"ignore\")\n",
"module_path = os.path.abspath(os.path.join(\"../..\"))\n",
"\n",
"if module_path not in sys.path:\n",
" sys.path.append(module_path)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "racial-graduation",
"metadata": {
"tags": [
"parameters"
]
},
"outputs": [],
"source": [
"report_name = f\"{datetime.now().strftime('%Y%m%d_%H%M%S')}_econ_data\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "commercial-cargo",
"metadata": {},
"outputs": [],
"source": [
"display(Markdown(f\"# Economy Data - {datetime.now().strftime('%Y/%m/%d %H:%M:%S')}\"))"
]
},
{
"cell_type": "markdown",
"id": "informative-behavior",
"metadata": {},
"source": [
"## Dow Jones - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "stylish-elite",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"^DJI\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
" low_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "fifty-happiness",
"metadata": {},
"source": [
"## Dow Jones - 1 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "identical-classification",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"^DJI\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=360,\n",
" low_trend=True,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "boxed-turning",
"metadata": {},
"source": [
"## S&P 500 - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "threaded-language",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"^GSPC\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
" low_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "fleet-transparency",
"metadata": {},
"source": [
"## Market Volatility (VIX) - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "disturbed-workstation",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"^VIX\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=False,\n",
" time_delta=720,\n",
" high_trend=False,\n",
" low_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "civilian-november",
"metadata": {},
"source": [
"## Market Volatility (VIX) - 1 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "several-inventory",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"^VIX\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=False,\n",
" time_delta=360,\n",
" high_trend=False,\n",
" low_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "bizarre-record",
"metadata": {},
"source": [
"## Yield on 5-Year US Treasury Notes - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "military-temperature",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"^FVX\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=False,\n",
" time_delta=720,\n",
" low_trend=False,\n",
" high_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "greater-party",
"metadata": {},
"source": [
"## Yield on 10-Year US Treasury Notes - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "aboriginal-violin",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"^TNX\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=False,\n",
" time_delta=720,\n",
" low_trend=False,\n",
" high_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "continent-sally",
"metadata": {},
"source": [
"## Yield on 30-Year US Treasury Notes - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "formed-heating",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"^TYX\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=False,\n",
" time_delta=720,\n",
" low_trend=False,\n",
" high_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "handled-insurance",
"metadata": {},
"source": [
"## Gold - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "advisory-johnston",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"GLD\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "played-writer",
"metadata": {},
"source": [
"## Silver - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "light-harvest",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"SLV\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
" low_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "floral-giant",
"metadata": {},
"source": [
"## Euro vs US Dollar - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "corrected-estimate",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"FXE\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
" low_trend=True,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "neither-montana",
"metadata": {},
"source": [
"## Yen vs US Dollar - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "middle-geneva",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"FXY\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
" low_trend=True,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "theoretical-grammar",
"metadata": {},
"source": [
"## Energy - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "swedish-thickness",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"XLE\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "gentle-humor",
"metadata": {},
"source": [
"## Crude Oil - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "instructional-serve",
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"CL=F\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
" low_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "classical-listening",
"metadata": {},
"source": [
"## Real Estate - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "enclosed-administration",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"XLRE\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
" low_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "turned-percentage",
"metadata": {},
"source": [
"## Real Estate - 1 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "sharing-removal",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"VNQ\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=360,\n",
" low_trend=True,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "swedish-happiness",
"metadata": {},
"source": [
"## Financials - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "beginning-aspect",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"XLF\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
" low_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "restricted-glucose",
"metadata": {},
"source": [
"## Financials - 1 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "personal-whole",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"XLF\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=360,\n",
" low_trend=True,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "detailed-strike",
"metadata": {},
"source": [
"## Materials - 2 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "negative-mitchell",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"XLB\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=720,\n",
" low_trend=False,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "boolean-rotation",
"metadata": {},
"source": [
"## Materials - 1 year trend with 20, 50 and 200 day SMA"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "settled-orange",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.economy import econ_data_helper\n",
"\n",
"econ_data_helper.draw_graph(\n",
" \"XLB\",\n",
" \"\",\n",
" line_type=\"line\",\n",
" draw_mas=(20, 50, 200),\n",
" draw_volume=True,\n",
" time_delta=360,\n",
" low_trend=True,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "premium-transportation",
"metadata": {},
"outputs": [],
"source": [
"!jupyter nbconvert {report_name + \".ipynb\"} --to html --no-input"
]
}
],
"metadata": {
"celltoolbar": "Tags",
"kernelspec": {
"display_name": "",
"language": "python",
"name": ""
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,682 +0,0 @@
{
"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",
"import matplotlib.pyplot as plt\n",
"import matplotlib_inline.backend_inline\n",
"\n",
"# import sys\n",
"# sys.path.append('../../../')\n",
"\n",
"from openbb_terminal import api as openbb\n",
"from openbb_terminal.helper_classes import TerminalStyle\n",
"\n",
"%matplotlib inline\n",
"matplotlib_inline.backend_inline.set_matplotlib_formats(\"svg\")\n",
"warnings.filterwarnings(\"ignore\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c3fe7db5-ec6a-42cf-9e66-52dc1de22370",
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" theme = TerminalStyle(\"light\", \"light\", \"light\")\n",
"except:\n",
" pass\n",
"stylesheet = openbb.widgets.html_report_stylesheet()\n",
"with open(\"./openbb_terminal/jupyter/reports/OpenBB_reports_logo.png\", \"rb\") as image_file:\n",
" openbb_image_encoded = base64.b64encode(image_file.read())"
]
},
{
"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",
"ticker = \"TSLA\"\n",
"report_name = \"\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1be26dae-cafe-4a22-80aa-eff296fc1a9b",
"metadata": {},
"outputs": [],
"source": [
"ticker_data = openbb.stocks.load(ticker, start=datetime.datetime.now() - datetime.timedelta(days=4*30))\n",
"ticker_data = openbb.stocks.process_candle(ticker_data)\n",
"\n",
"author = \"Didier Rodrigues Lopes\"\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": "e3b15d6f-dc9e-4f97-aa07-37d949a4e4bb",
"metadata": {},
"outputs": [],
"source": [
"overview = openbb.stocks.fa.models.yahoo_finance.get_info(ticker=ticker).transpose()[\n",
" \"Long business summary\"\n",
"][0]\n",
"overview"
]
},
{
"cell_type": "markdown",
"id": "f8a0d747",
"metadata": {},
"source": [
"## Data"
]
},
{
"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.dd.models.business_insider.get_estimates(ticker)"
]
},
{
"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)\n",
"df_year_estimates"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fde46353",
"metadata": {},
"outputs": [],
"source": [
"df_quarter_earnings"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "51dfd9d2",
"metadata": {},
"outputs": [],
"source": [
"df_quarter_revenues"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3022130e",
"metadata": {},
"outputs": [],
"source": [
"df_sec_filings = openbb.stocks.dd.models.marketwatch.get_sec_filings(ticker)[\n",
" [\"Type\", \"Category\", \"Link\"]\n",
"].head(5)\n",
"df_sec_filings"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4662b1ac",
"metadata": {},
"outputs": [],
"source": [
"df_analyst = openbb.stocks.dd.models.finviz.get_analyst_data(ticker)\n",
"df_analyst[\"target_to\"] = df_analyst[\"target_to\"].combine_first(df_analyst[\"target\"])\n",
"df_analyst = df_analyst[[\"category\", \"analyst\", \"rating\", \"target_to\"]].rename(\n",
" columns={\n",
" \"category\": \"Category\",\n",
" \"analyst\": \"Analyst\",\n",
" \"rating\": \"Rating\",\n",
" \"target_to\": \"Price Target\",\n",
" }\n",
")\n",
"df_analyst"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "324e2d4b-b2f6-4da3-bac4-ef785ad4e436",
"metadata": {},
"outputs": [],
"source": [
"fig, ax1 = plt.subplots(figsize=(11, 5), dpi=150)\n",
"ax2 = ax1.twinx()\n",
"openbb.stocks.dps.spos(\n",
" ticker,\n",
" num=84,\n",
" raw=False,\n",
" export=\"\",\n",
" external_axes=[ax1, ax2],\n",
")\n",
"fig.tight_layout()\n",
"\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"net_short_position = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ac0bfbda-e4b8-4b3b-b8e7-c02639fdb971",
"metadata": {},
"outputs": [],
"source": [
"fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(11, 5), dpi=150)\n",
"openbb.stocks.dps.dpotc(\n",
" ticker,\n",
" external_axes=[ax1, ax2],\n",
")\n",
"fig.tight_layout()\n",
"\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"dark_pools = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e40a2b8f-8076-4220-89ad-388def38971c",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(11, 5), dpi=150)\n",
"openbb.stocks.dps.volexch(\n",
" ticker,\n",
" external_axes=[ax],\n",
")\n",
"fig.tight_layout()\n",
"\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"volexch = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d8bb53c1-147e-4342-af61-0d0a9cc56e59",
"metadata": {},
"outputs": [],
"source": [
"fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(11, 5), dpi=150)\n",
"ax3 = ax1.twinx()\n",
"openbb.stocks.dps.psi_sg(\n",
" ticker,\n",
" external_axes=[ax1, ax2, ax3],\n",
")\n",
"fig.tight_layout()\n",
"\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"price_vs_short_interest = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "394668e1-1158-4a2b-8a38-04c72a6abdd6",
"metadata": {},
"outputs": [],
"source": [
"fig, (candles, volume) = plt.subplots(nrows=2, ncols=1, figsize=(11, 5), dpi=150)\n",
"openbb.stocks.candle(\n",
" s_ticker=ticker,\n",
" df_stock=ticker_data,\n",
" use_matplotlib=True,\n",
" external_axes=[candles, volume],\n",
")\n",
"candles.set_xticklabels(\"\")\n",
"fig.tight_layout()\n",
"\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"price_chart = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "900686a3",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(11, 3), dpi=150)\n",
"openbb.stocks.dd.pt(\n",
" ticker=ticker,\n",
" start=\"2022-01-01\",\n",
" interval=\"1440min\",\n",
" stock=ticker_data,\n",
" num=10,\n",
" raw=False,\n",
" external_axes=[ax],\n",
")\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"price_target_chart = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "61d62e1a-199e-481d-b57d-38ab486951be",
"metadata": {},
"outputs": [],
"source": [
"df = openbb.stocks.dd.models.business_insider.get_price_target_from_analysts(ticker)\n",
"avg_ratings_last_30_days = round(np.mean(df[datetime.datetime.now() - datetime.timedelta(days=30):][\"Price Target\"].values), 2)\n",
"last_price = round(ticker_data[\"Close\"][-1], 2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3733ff2",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(11, 3), dpi=150)\n",
"openbb.stocks.dd.rot(\n",
" ticker=ticker,\n",
" num=10,\n",
" raw=False,\n",
" export=\"\",\n",
" external_axes=[ax],\n",
")\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"ratings_over_time_chart = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "924f8042-e58a-449c-91a3-7923158ff714",
"metadata": {},
"outputs": [],
"source": [
"fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(11, 3), dpi=150)\n",
"openbb.stocks.ta.rsi(ticker_data[\"Close\"], external_axes=[ax1, ax2])\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"ta_rsi = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "953a340e-7ea1-4aa3-ae1d-872683dced41",
"metadata": {},
"outputs": [],
"source": [
"df = openbb.stocks.ta.models.momentum.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",
"model = LinearRegression().fit(np.array(range(len(ticker_data[\"Close\"][-30:].index))).reshape(-1,1), ticker_data[\"Close\"][-30:].values)\n",
"regression_slope = round(model.coef_[0], 2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6272e34b-9511-4b48-9eea-ea882ce9846a",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"df_insider = pd.DataFrame.from_dict(openbb.stocks.ins.models.finviz.get_last_insider_activity(ticker)).head(10)\n",
"df_insider[\"Val ($)\"] = df_insider[\"Value ($)\"].replace({',': ''}, regex=True)\n",
"df_insider[\"Trade\"] = df_insider.apply(\n",
" lambda row: (-1*float(row[\"Val ($)\"])) if row[\"Transaction\"] == \"Sale\" 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": [
"fig, ax = plt.subplots(figsize=(11, 3), dpi=150)\n",
"openbb.stocks.ba.headlines(ticker, external_axes=[ax])\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"finbrain_sentiment = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b8251b47-8ecc-47be-83f3-d9f108596898",
"metadata": {},
"outputs": [],
"source": [
"df_sentiment_finbrain = openbb.stocks.ba.models.finbrain.get_sentiment(ticker)\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": [
"watchlist_count, n_cases, n_bull, n_bear = openbb.stocks.ba.models.stocktwits.get_bullbear(ticker)\n",
"stocktwits_sentiment = f\"Watchlist count: {watchlist_count}</br>\"\n",
"if n_cases > 0:\n",
" stocktwits_sentiment += f\"\\nLast {n_cases} sentiment messages:</br>\"\n",
" stocktwits_sentiment += f\"Bullish {round(100*n_bull/n_cases, 2)}%</br>\"\n",
" stocktwits_sentiment += f\"Bearish {round(100*n_bear/n_cases, 2)}%\"\n",
"else:\n",
" stocktwits_sentiment += \"No messages found\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bfb75909-b877-4b3a-82a7-21ce174a7bb4",
"metadata": {},
"outputs": [],
"source": [
"fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(11, 5), dpi=150)\n",
"openbb.stocks.ba.snews(ticker, external_axes=[ax1, ax2])\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"snews = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "329c9e1b-e1de-4836-91fd-656cc87f7111",
"metadata": {},
"outputs": [],
"source": [
"ticker_data_all = openbb.stocks.load(ticker, start=datetime.datetime.now() - datetime.timedelta(days=5*12*21))\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": [
"fig, ax = plt.subplots(figsize=(11, 3), dpi=150)\n",
"openbb.stocks.qa.bw(ticker, ticker_data_all, \"Returns\", False, external_axes=[ax])\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"bw_month = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "16b33868-23dc-4c77-ac00-acb452da386c",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(11, 3), dpi=150)\n",
"openbb.stocks.qa.bw(ticker, ticker_data_all, \"Returns\", True, external_axes=[ax])\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"bw_year = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c688fa89-3773-41fe-8ab8-bb6a610f2287",
"metadata": {},
"outputs": [],
"source": [
"regression_val = round(openbb.stocks.pred.models.regression.get_regression_model(ticker_data_all[\"Close\"], 1, 80, 20, 1)[0][-1], 2)\n",
"regression_val"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "66e51d40-3dca-46c0-abd6-4c1f04f59732",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(11, 3), dpi=150)\n",
"openbb.stocks.pred.regression(ticker, ticker_data_all[\"Close\"], 1, 80, 20, 1, external_axes=[ax])\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"regression = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "90e77854-0652-4f62-9c0b-89d3fda456c6",
"metadata": {},
"outputs": [],
"source": [
"fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(11, 3), dpi=150)\n",
"openbb.stocks.pred.mc(ticker_data[\"Close\"], 30, 100, external_axes=[ax1, ax2])\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"mc = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bb97c78c-4c4e-4e24-a2a1-29cdf47839c5",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(11, 3), dpi=150)\n",
"openbb.stocks.pred.regression(ticker, ticker_data_all[\"Close\"], 1, 80, 20, 1, external_axes=[ax])\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"regression = f.getvalue().decode(\"utf-8\")"
]
},
{
"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 = \"\"\n",
"\n",
"img = f'<img src=\"data:image/png;base64,{openbb_image_encoded.decode()}\" alt=\"OpenBB\" style=\"width:144px;\">'\n",
"body += openbb.widgets.header(img, author, report_date, report_time, report_timezone, f'<b>INVESTMENT RESEARCH REPORT:</b> {ticker}')\n",
"\n",
"body += openbb.widgets.tablinks([\"SUMMARY\", \"Overview\", \"Analyst Opinions\", \"Fundamental Analysis\", \"Dark Pool and Shorts\", \"Technical Analysis\", \"Insider Trading\", \"Behavioural Analysis\", \"Quantitative Analysis\", \"Prediction Techniques\"])\n",
"\n",
"htmlcode = openbb.widgets.h(3, \"KPIs\")\n",
"htmlcode += openbb.widgets.kpi([last_price], [\"Last closing price is above the average price ratings of last 30 days\", \"Average price ratings of last 30 day is above last closing price\"], avg_ratings_last_30_days)\n",
"htmlcode += openbb.widgets.kpi([0], [\"Regression (dollars per market day) on last 30 market days is negative\", \"Regression (dollars per market day) on last 30 market days is positive\"], regression_slope)\n",
"htmlcode += openbb.widgets.kpi([30, 70], [\"RSI level is oversold\", \"RSI level is normal\", \"RSI level is overbought\"], rsi_value) \n",
"htmlcode += openbb.widgets.kpi([0], [\"The sum of last 10 insider trading (in millions) was negative\", \"The sum of last 10 insider trading (in millions) was positive\"], last_10_insider_trading)\n",
"htmlcode += openbb.widgets.kpi([-.1, .1], [\"Last FinBrain sentiment is bearish\", \" Last FinBrain sentiment is neutral\", \"Last FinBrain sentiment is bullish\"], finbrain_sentiment_val) \n",
"htmlcode += openbb.widgets.kpi([0], [\"The regression for the next 20th market price is below closing price\", \"The regression for the next 20th market price is above closing price\"], round(regression_val - last_price, 2)) \n",
"body += openbb.widgets.add_tab(\"SUMMARY\", htmlcode)\n",
"\n",
"htmlcode = openbb.widgets.row([price_chart])\n",
"htmlcode += openbb.widgets.row([openbb.widgets.h(3, \"Description\") + openbb.widgets.p(overview)])\n",
"body += openbb.widgets.add_tab(\"Overview\", htmlcode)\n",
"\n",
"htmlcode = openbb.widgets.row([price_target_chart])\n",
"htmlcode += openbb.widgets.row([ratings_over_time_chart])\n",
"htmlcode += openbb.widgets.row([df_analyst.to_html()])\n",
"body += openbb.widgets.add_tab(\"Analyst Opinions\", htmlcode)\n",
"\n",
"htmlcode = openbb.widgets.row([openbb.widgets.h(3, \"Estimates\") + df_year_estimates.head().to_html()])\n",
"htmlcode += openbb.widgets.row([openbb.widgets.h(3, \"Earnings\") + df_quarter_earnings.head().to_html()])\n",
"htmlcode += openbb.widgets.row([openbb.widgets.h(3, \"Revenues\") + df_quarter_revenues.head().to_html()])\n",
"htmlcode += openbb.widgets.row([openbb.widgets.h(3, \"SEC filings\") + df_sec_filings.head().to_html()])\n",
"body += openbb.widgets.add_tab(\"Fundamental Analysis\", htmlcode)\n",
" \n",
"htmlcode = openbb.widgets.row([net_short_position])\n",
"htmlcode += openbb.widgets.row([price_vs_short_interest])\n",
"htmlcode += openbb.widgets.row([dark_pools])\n",
"htmlcode += openbb.widgets.row([volexch])\n",
"body += openbb.widgets.add_tab(\"Dark Pool and Shorts\", htmlcode)\n",
"\n",
"body += openbb.widgets.add_tab(\"Technical Analysis\", openbb.widgets.row([ta_rsi]))\n",
"\n",
"htmlcode = openbb.widgets.row([openbb.widgets.h(3, \"Last Activity\") + df_insider.head(10).to_html(col_space='75px')])\n",
"body += openbb.widgets.add_tab(\"Insider Trading\", htmlcode)\n",
"\n",
"htmlcode = openbb.widgets.row([finbrain_sentiment])\n",
"htmlcode += openbb.widgets.row([snews])\n",
"htmlcode += openbb.widgets.row([openbb.widgets.h(3, \"Stocktwits\") + stocktwits_sentiment])\n",
"body += openbb.widgets.add_tab(\"Behavioural Analysis\", htmlcode)\n",
"\n",
"htmlcode = openbb.widgets.row([bw_month])\n",
"htmlcode += openbb.widgets.row([bw_year])\n",
"body += openbb.widgets.add_tab(\"Quantitative Analysis\", htmlcode)\n",
"\n",
"htmlcode = openbb.widgets.row([regression])\n",
"htmlcode += openbb.widgets.row([mc])\n",
"body += openbb.widgets.add_tab(\"Prediction Techniques\", htmlcode)\n",
"\n",
"body += openbb.widgets.tab_clickable_evt()\n",
"\n",
"report = openbb.widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)\n",
"\n",
"# to save the results\n",
"with open(report_name + \".html\", \"w\") as fh:\n",
" fh.write(report)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e15cef06-0d10-4153-b6d3-9762be0ed1dd",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"celltoolbar": "Tags",
"interpreter": {
"hash": "aa1c4d436101635411b2afa2ce061827695b6e3d0efa7f05338cbf11ad26165e"
},
"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.8.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,528 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "7e02d340-956a-496d-b4e5-fd74cc85f13a",
"metadata": {},
"source": [
"## Notebook setup"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "phantom-facility",
"metadata": {},
"outputs": [],
"source": [
"import io\n",
"import math\n",
"import warnings\n",
"from datetime import datetime, timedelta\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib_inline.backend_inline\n",
"import pandas as pd\n",
"from tqdm.notebook import tqdm\n",
"\n",
"from openbb_terminal import api as openbb\n",
"from openbb_terminal.helper_classes import TerminalStyle\n",
"\n",
"%matplotlib inline\n",
"matplotlib_inline.backend_inline.set_matplotlib_formats(\"svg\")\n",
"warnings.filterwarnings(\"ignore\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d318a555-d1db-444e-ba8c-8427850dec59",
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" theme = TerminalStyle(\"light\", \"light\", \"light\")\n",
"except:\n",
" pass\n",
"stylesheet = openbb.widgets.html_report_stylesheet()"
]
},
{
"cell_type": "markdown",
"id": "fa5bd393-2f66-4ba3-98f8-66230636ce0e",
"metadata": {},
"source": [
"## Select Ticker"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "compact-count",
"metadata": {
"tags": [
"parameters"
]
},
"outputs": [],
"source": [
"# Parameters that will be replaced when calling this notebook\n",
"ticker = \"clx\"\n",
"report_name = f\"{datetime.now().strftime('%Y%m%d_%H%M%S')}_comparison_{ticker.upper()}\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "possible-constraint",
"metadata": {},
"outputs": [],
"source": [
"ticker = ticker.upper()\n",
"report_title = (\n",
" f\"{ticker.upper()} Comparison ({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})\"\n",
")\n",
"report_title"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b9eaca4a-a46d-45a3-9306-e80e74234f12",
"metadata": {},
"outputs": [],
"source": [
"finviz_similar = openbb.stocks.ca.models.finviz_compare.get_similar_companies(\n",
" ticker, [\"Sector\", \"Industry\", \"Country\"]\n",
")[0]\n",
"finviz_similar.pop(finviz_similar.index(ticker))\n",
"print(f\"Similar companies:\\n{' '.join([i for i in finviz_similar])}\")"
]
},
{
"cell_type": "markdown",
"id": "135b09f6-c22b-4cc5-b68e-d77f9e3b3a60",
"metadata": {
"tags": []
},
"source": [
"### Overview"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9907d7ea-3ad0-4123-ab2e-f03defa4eea2",
"metadata": {},
"outputs": [],
"source": [
"overview = openbb.stocks.ca.models.finviz_compare.get_comparison_data(\n",
" similar=finviz_similar,\n",
" data_type=\"overview\",\n",
")\n",
"overview = overview.sort_values(\"Volume\", ascending=False)\n",
"overview.head(4)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bc7d52a4-fbe6-4b39-a3d5-bfae841dacac",
"metadata": {},
"outputs": [],
"source": [
"# Update the list of similar companies to take up only up to 12 with top volume\n",
"finviz_similar = overview[\"Ticker\"].to_list()[:12]\n",
"print(f\"Similar companies:\\n{' '.join([i for i in finviz_similar])}\")"
]
},
{
"cell_type": "markdown",
"id": "ffea4266-e801-4a4e-8cac-3d60e735aa4e",
"metadata": {},
"source": [
"### Similar companies and descriptions"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "21122245-457b-4347-b89f-d4aabb5bdc9a",
"metadata": {},
"outputs": [],
"source": [
"def get_info_as_dict(ticker):\n",
" df_info = openbb.stocks.fa.models.yahoo_finance.get_info(ticker)\n",
" if \"Long business summary\" in df_info.index:\n",
" summary = df_info.loc[\"Long business summary\"].values[0]\n",
" elif \"Long name\" in df_info.index:\n",
" summary = df_info.loc[\"Long name\"].values[0]\n",
" else:\n",
" summary = \"\"\n",
" if \"Website\" in df_info.index:\n",
" website = df_info.loc[\"Website\"].values[0]\n",
" else:\n",
" website = \"\"\n",
" return {\"summary\": summary, \"website\": website}\n",
"\n",
"\n",
"similar_companies = dict()\n",
"similar_companies[ticker] = get_info_as_dict(ticker)\n",
"\n",
"if finviz_similar:\n",
" for symbol in tqdm(finviz_similar):\n",
" similar_companies[symbol] = get_info_as_dict(symbol)"
]
},
{
"cell_type": "markdown",
"id": "temporal-clerk",
"metadata": {
"tags": []
},
"source": [
"### Historical prices"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5e7509a7-961a-4fb8-bd87-0df4b8c98d04",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"for c in tqdm(finviz_similar):\n",
" fig, ax = plt.subplots(figsize=(4.2, 3), dpi=150)\n",
" openbb.stocks.ca.hist(\n",
" normalize=True,\n",
" similar_tickers=[ticker, c],\n",
" external_axes=[ax],\n",
" )\n",
" ax.set_title(\"\")\n",
" fig.tight_layout()\n",
" f = io.BytesIO()\n",
" fig.savefig(f, format=\"svg\")\n",
" similar_companies[c][\"historical_price\"] = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "markdown",
"id": "2a07f866-7939-4fb7-8b14-c0701087a8ae",
"metadata": {},
"source": [
"### Historical correlation"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2df60c41-4f87-483c-abe7-7063fa7648cf",
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(9.5, 6), dpi=150)\n",
"\n",
"openbb.stocks.ca.hcorr(\n",
" similar_tickers=finviz_similar,\n",
" external_axes=[ax],\n",
")\n",
"\n",
"fig.tight_layout()\n",
"f = io.BytesIO()\n",
"fig.savefig(f, format=\"svg\")\n",
"historical_correlation = f.getvalue().decode(\"utf-8\")"
]
},
{
"cell_type": "markdown",
"id": "21005668-7f21-4884-a231-846130695602",
"metadata": {
"tags": []
},
"source": [
"### Historical volumes"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f84b055f-ec6d-4b61-89f3-17f06a1ca12d",
"metadata": {},
"outputs": [],
"source": [
"volume_groups = []\n",
"for i in range(math.ceil(len(finviz_similar) / 3)):\n",
" volume_groups.append(finviz_similar[3 * (i) : 3 * (i + 1)])\n",
"volume_groups"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8812a2f6-f912-4161-a938-5e2a343d782a",
"metadata": {},
"outputs": [],
"source": [
"historical_volumes = []\n",
"for vgroup in volume_groups:\n",
" fig, ax = plt.subplots(figsize=(4, 3), dpi=150)\n",
" openbb.stocks.ca.volume(\n",
" similar_tickers=vgroup,\n",
" external_axes=[ax],\n",
" )\n",
" ax.set_title(\" \".join([i for i in vgroup]))\n",
" f = io.BytesIO()\n",
" fig.savefig(f, format=\"svg\")\n",
" historical_volumes.append(f.getvalue().decode(\"utf-8\"))"
]
},
{
"cell_type": "markdown",
"id": "5277ae24-b7d7-48e6-b46c-fcffdf84631f",
"metadata": {
"tags": []
},
"source": [
"### Valuation"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ef50e7ba-70bf-4ffc-b01c-8e28266c13b4",
"metadata": {},
"outputs": [],
"source": [
"valuation = openbb.stocks.ca.models.finviz_compare.get_comparison_data(\n",
" similar=finviz_similar,\n",
" data_type=\"valuation\",\n",
")\n",
"valuation.head(4)"
]
},
{
"cell_type": "markdown",
"id": "98030d12-9a77-4f08-b4ad-2c558d9ad225",
"metadata": {
"tags": []
},
"source": [
"### Financial"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1fdfac4c-62cd-4bd3-b7df-41ba67263798",
"metadata": {},
"outputs": [],
"source": [
"financial = openbb.stocks.ca.models.finviz_compare.get_comparison_data(\n",
" similar=finviz_similar,\n",
" data_type=\"financial\",\n",
")\n",
"financial.head(4)"
]
},
{
"cell_type": "markdown",
"id": "f7cf8774-5162-47ea-8bfe-5005ed2fb9d9",
"metadata": {
"tags": []
},
"source": [
"### Ownership"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d3f90d1f-7a40-403f-bf3e-17703e151f4b",
"metadata": {},
"outputs": [],
"source": [
"ownership = openbb.stocks.ca.models.finviz_compare.get_comparison_data(\n",
" similar=finviz_similar,\n",
" data_type=\"ownership\",\n",
")\n",
"ownership.head(4)"
]
},
{
"cell_type": "markdown",
"id": "c1833238-5ea8-486b-a6e7-6043e7c0aa0e",
"metadata": {
"tags": []
},
"source": [
"### Performance"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "62057b47-2364-49ed-80e7-7d6938f2819d",
"metadata": {},
"outputs": [],
"source": [
"performance = openbb.stocks.ca.models.finviz_compare.get_comparison_data(\n",
" similar=finviz_similar,\n",
" data_type=\"performance\",\n",
")\n",
"performance.head(4)"
]
},
{
"cell_type": "markdown",
"id": "6d0494c0-e66a-414a-ba2d-89e4072e1a8f",
"metadata": {
"tags": []
},
"source": [
"### Technical"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1178a080-83ce-4170-a355-9faa8cf9abe6",
"metadata": {},
"outputs": [],
"source": [
"technical = openbb.stocks.ca.models.finviz_compare.get_comparison_data(\n",
" similar=finviz_similar,\n",
" data_type=\"technical\",\n",
")\n",
"technical.head(4)"
]
},
{
"cell_type": "markdown",
"id": "16a5fc9a-0d9b-4589-b680-f954e4e6f78a",
"metadata": {},
"source": [
"## Render the report template to a file"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eebac826-906b-482d-a387-55cb78eb5e18",
"metadata": {},
"outputs": [],
"source": [
"body = \"\""
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "26727f90-0950-4434-97f9-6b52180e4473",
"metadata": {},
"outputs": [],
"source": [
"body += openbb.widgets.h(1, report_title)\n",
"\n",
"body += openbb.widgets.h(2, \"Overview\")\n",
"\n",
"for company in similar_companies:\n",
" if company == ticker:\n",
" continue\n",
" # widgets.append()\n",
" body += openbb.widgets.row(\n",
" [\n",
" openbb.widgets.h(3, company)\n",
" + \"<br>\"\n",
" + similar_companies[company][\"website\"]\n",
" + \"<br>\"\n",
" + \"<br>\"\n",
" + similar_companies[company][\"summary\"],\n",
" openbb.widgets.h(3, f\"{ticker} vs {company}\")\n",
" + similar_companies[company][\"historical_price\"],\n",
" ]\n",
" )\n",
"\n",
"body += openbb.widgets.h(2, \"Historical correlation\")\n",
"body += openbb.widgets.row([historical_correlation])\n",
"\n",
"body += openbb.widgets.h(2, \"Historical volumes\")\n",
"for chart in range(0, len(historical_volumes), 2):\n",
" body += openbb.widgets.row(\n",
" [historical_volumes[chart], historical_volumes[chart + 1]]\n",
" )\n",
"\n",
"\n",
"body += openbb.widgets.h(2, \"Screeners\")\n",
"\n",
"body += openbb.widgets.h(3, \"overview\")\n",
"body += openbb.widgets.row([overview.to_html()])\n",
"\n",
"body += openbb.widgets.h(3, \"valuation\")\n",
"body += openbb.widgets.row([valuation.to_html()])\n",
"\n",
"body += openbb.widgets.h(3, \"financial\")\n",
"body += openbb.widgets.row([financial.to_html()])\n",
"\n",
"body += openbb.widgets.h(3, \"ownership\")\n",
"body += openbb.widgets.row([ownership.to_html()])\n",
"\n",
"body += openbb.widgets.h(3, \"performance\")\n",
"body += openbb.widgets.row([performance.to_html()])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f7697fa8-cc27-4bf8-b5e6-ea6ab4ec6a21",
"metadata": {},
"outputs": [],
"source": [
"report = openbb.widgets.html_report(title=report_name, stylesheet=stylesheet, body=body)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "42e6a584-b7c9-435f-98cb-ea93ac6b8812",
"metadata": {},
"outputs": [],
"source": [
"# to save the results\n",
"with open(report_name + \".html\", \"w\") as fh:\n",
" fh.write(report)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6de79d28-fc26-4bf0-bece-f823a424b4fc",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"celltoolbar": "Tags",
"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.8.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -79,7 +79,7 @@ class ReportController(BaseController):
+ f"{args if args != '<>' else ''}\n"
)
CHOICES_MENUS = report_names + ids_reports
PATH = "/jupyter/reports/"
PATH = "/reports/"
def __init__(self, queue: List[str] = None):
"""Constructor"""
@@ -97,7 +97,7 @@ class ReportController(BaseController):
help_text = f"""[info]
Select one of the following reports:[/info][cmds]
{self.reports_opts}[/cmds]"""
console.print(text=help_text, menu="Jupyter - Reports")
console.print(text=help_text, menu="Reports - WORK IN PROGRESS")
@log_start_end(log=logger)
def switch(self, an_input: str):
@@ -182,7 +182,7 @@ Select one of the following reports:[/info][cmds]
console.print("")
notebook_template = os.path.join(
"openbb_terminal", "jupyter", "reports", report_to_run
"openbb_terminal", "reports", report_to_run
)
args_to_output = f"_{'_'.join(other_args)}" if "_".join(other_args) else ""
report_output_name = (
@@ -192,7 +192,6 @@ Select one of the following reports:[/info][cmds]
)
notebook_output = os.path.join(
"openbb_terminal",
"jupyter",
"reports",
"stored",
report_output_name,
@@ -215,6 +214,7 @@ Select one of the following reports:[/info][cmds]
report_output_path = os.path.join(
os.path.abspath(os.path.join(".")), notebook_output + ".html"
)
print(report_output_path)
webbrowser.open(f"file://{report_output_path}")
console.print("")

File diff suppressed because one or more lines are too long

View File

@@ -66,7 +66,8 @@ class TerminalController(BaseController):
"portfolio",
"forex",
"etf",
"jupyter",
"reports",
"dashboards",
"funds",
"alternative",
"econometrics",
@@ -145,8 +146,10 @@ class TerminalController(BaseController):
> funds
> alternative
> econometrics
> portfolio
> jupyter[/menu]
> dashboards
> reports[/menu]
""",
menu="Home",
)
@@ -209,12 +212,28 @@ class TerminalController(BaseController):
self.queue = self.load_class(ForexController, self.queue)
def call_jupyter(self, _):
"""Process jupyter command"""
def call_reports(self, _):
"""Process reports command"""
if not obbff.PACKAGED_APPLICATION:
from openbb_terminal.jupyter.jupyter_controller import JupyterController
from openbb_terminal.reports.reports_controller import (
ReportController,
)
self.queue = self.load_class(JupyterController, self.queue)
self.queue = self.load_class(ReportController, self.queue)
else:
console.print("This feature is coming soon.")
console.print(
"Use the source code and an Anaconda environment if you are familiar with Python."
)
def call_dashboards(self, _):
"""Process dashboards command"""
if not obbff.PACKAGED_APPLICATION:
from openbb_terminal.dashboards.dashboards_controller import (
DashboardsController,
)
self.queue = self.load_class(DashboardsController, self.queue)
else:
console.print("This feature is coming soon.")
console.print(

View File

@@ -1,143 +0,0 @@
import os
import pytest
from openbb_terminal.jupyter.dashboards import dashboards_controller
@pytest.mark.vcr(record_mode="none")
@pytest.mark.parametrize(
"queue, expected",
[
(["load", "help"], []),
(["quit", "help"], ["help"]),
],
)
def test_menu_with_queue(expected, mocker, queue):
path_controller = "openbb_terminal.jupyter.dashboards.dashboards_controller"
# MOCK SWITCH
mocker.patch(
target=f"{path_controller}.DashboardsController.switch",
return_value=["quit"],
)
result_menu = dashboards_controller.DashboardsController(queue=queue).menu()
assert result_menu == expected
@pytest.mark.vcr(record_mode="none")
def test_menu_without_queue_completion(mocker):
path_controller = "openbb_terminal.jupyter.dashboards.dashboards_controller"
# ENABLE AUTO-COMPLETION : HELPER_FUNCS.MENU
mocker.patch(
target="openbb_terminal.feature_flags.USE_PROMPT_TOOLKIT",
new=True,
)
mocker.patch(
target="openbb_terminal.parent_classes.session",
)
mocker.patch(
target="openbb_terminal.parent_classes.session.prompt",
return_value="quit",
)
# DISABLE AUTO-COMPLETION : CONTROLLER.COMPLETER
mocker.patch.object(
target=dashboards_controller.obbff,
attribute="USE_PROMPT_TOOLKIT",
new=True,
)
mocker.patch(
target=f"{path_controller}.session",
)
mocker.patch(
target=f"{path_controller}.session.prompt",
return_value="quit",
)
result_menu = dashboards_controller.DashboardsController(queue=None).menu()
assert result_menu == []
@pytest.mark.vcr(record_mode="none")
@pytest.mark.record_stdout
def test_print_help():
controller = dashboards_controller.DashboardsController(queue=None)
controller.print_help()
@pytest.mark.vcr(record_mode="none")
@pytest.mark.parametrize(
"an_input, expected_queue",
[
("", []),
("/help", ["home", "help"]),
("help/help", ["help", "help"]),
("q", ["quit"]),
("h", []),
(
"r",
["quit", "quit", "reset", "jupyter", "dashboards"],
),
],
)
def test_switch(an_input, expected_queue):
controller = dashboards_controller.DashboardsController(queue=None)
queue = controller.switch(an_input=an_input)
assert queue == expected_queue
@pytest.mark.vcr(record_mode="none")
def test_call_cls(mocker):
mocker.patch("os.system")
controller = dashboards_controller.DashboardsController(queue=None)
controller.call_cls([])
assert controller.queue == []
os.system.assert_called_once_with("cls||clear")
@pytest.mark.vcr(record_mode="none")
@pytest.mark.parametrize(
"func, queue, expected_queue",
[
(
"call_exit",
[],
["quit", "quit", "quit"],
),
("call_exit", ["help"], ["quit", "quit", "quit", "help"]),
("call_home", [], ["quit", "quit"]),
("call_help", [], []),
("call_quit", [], ["quit"]),
("call_quit", ["help"], ["quit", "help"]),
(
"call_reset",
[],
["quit", "quit", "reset", "jupyter", "dashboards"],
),
(
"call_reset",
["help"],
[
"quit",
"quit",
"reset",
"jupyter",
"dashboards",
"help",
],
),
],
)
def test_call_func_expect_queue(expected_queue, func, queue):
controller = dashboards_controller.DashboardsController(queue=queue)
result = getattr(controller, func)([])
assert result is None
assert controller.queue == expected_queue

View File

@@ -1,8 +0,0 @@
stocks historic stock information
correlation stock correlations
vsurf options volatility surface
chains options chain analysis
shortdata finra shortdata analysis
crypto cryptocurrency exchange rates against USD

View File

@@ -1,149 +0,0 @@
import os
import pytest
from openbb_terminal.jupyter import jupyter_controller
@pytest.mark.vcr(record_mode="none")
@pytest.mark.parametrize(
"queue, expected",
[
(["load", "help"], []),
(["quit", "help"], ["help"]),
],
)
def test_menu_with_queue(expected, mocker, queue):
path_controller = "openbb_terminal.jupyter.jupyter_controller"
# MOCK SWITCH
mocker.patch(
target=f"{path_controller}.JupyterController.switch",
return_value=["quit"],
)
result_menu = jupyter_controller.JupyterController(queue=queue).menu()
assert result_menu == expected
@pytest.mark.vcr(record_mode="none")
def test_menu_without_queue_completion(mocker):
path_controller = "openbb_terminal.jupyter.jupyter_controller"
# ENABLE AUTO-COMPLETION : HELPER_FUNCS.MENU
mocker.patch(
target="openbb_terminal.feature_flags.USE_PROMPT_TOOLKIT",
new=True,
)
mocker.patch(
target="openbb_terminal.parent_classes.session",
)
mocker.patch(
target="openbb_terminal.parent_classes.session.prompt",
return_value="quit",
)
# DISABLE AUTO-COMPLETION : CONTROLLER.COMPLETER
mocker.patch.object(
target=jupyter_controller.obbff,
attribute="USE_PROMPT_TOOLKIT",
new=True,
)
mocker.patch(
target=f"{path_controller}.session",
)
mocker.patch(
target=f"{path_controller}.session.prompt",
return_value="quit",
)
result_menu = jupyter_controller.JupyterController(queue=None).menu()
assert result_menu == []
@pytest.mark.vcr(record_mode="none")
@pytest.mark.record_stdout
def test_print_help():
controller = jupyter_controller.JupyterController(queue=None)
controller.print_help()
@pytest.mark.vcr(record_mode="none")
@pytest.mark.parametrize(
"an_input, expected_queue",
[
("", []),
("/help", ["home", "help"]),
("help/help", ["help", "help"]),
("q", ["quit"]),
("h", []),
(
"r",
[
"quit",
"reset",
"jupyter",
],
),
],
)
def test_switch(an_input, expected_queue):
controller = jupyter_controller.JupyterController(queue=None)
queue = controller.switch(an_input=an_input)
assert queue == expected_queue
@pytest.mark.vcr(record_mode="none")
def test_call_cls(mocker):
mocker.patch("os.system")
controller = jupyter_controller.JupyterController(queue=None)
controller.call_cls([])
assert controller.queue == []
os.system.assert_called_once_with("cls||clear")
@pytest.mark.vcr(record_mode="none")
@pytest.mark.parametrize(
"func, queue, expected_queue",
[
(
"call_exit",
[],
["quit", "quit"],
),
("call_exit", ["help"], ["quit", "quit", "help"]),
("call_home", [], ["quit"]),
("call_help", [], []),
("call_quit", [], ["quit"]),
("call_quit", ["help"], ["quit", "help"]),
(
"call_reset",
[],
[
"quit",
"reset",
"jupyter",
],
),
(
"call_reset",
["help"],
[
"quit",
"reset",
"jupyter",
"help",
],
),
],
)
def test_call_func_expect_queue(expected_queue, func, queue):
controller = jupyter_controller.JupyterController(queue=queue)
result = getattr(controller, func)([])
assert result is None
assert controller.queue == expected_queue

View File

@@ -1,4 +0,0 @@
> reports creates jupyter reports
> dashboards shows interactive jupyter dashboards