mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
Added back dashboards (sorry Didier) (#2751)
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -21,7 +21,7 @@ openbb_terminal/config_terminal.py
|
||||
openbb_terminal/feature_flags.py
|
||||
openbb_terminal/reports/stored/*
|
||||
!openbb_terminal/reports/stored/.gitkeep
|
||||
!openbb_terminal/dashboards/*.ipynb
|
||||
!openbb_terminal/dashboards/voila/*.ipynb
|
||||
!openbb_terminal/reports/*.ipynb
|
||||
openbb_terminal/portfolio/portfolios/*
|
||||
**/.ipynb_checkpoints
|
||||
|
||||
177
openbb_terminal/dashboards/voila/chains.ipynb
vendored
Normal file
177
openbb_terminal/dashboards/voila/chains.ipynb
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
207
openbb_terminal/dashboards/voila/correlation.ipynb
vendored
Normal file
207
openbb_terminal/dashboards/voila/correlation.ipynb
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
{
|
||||
"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": "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": 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",
|
||||
"\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
|
||||
}
|
||||
160
openbb_terminal/dashboards/voila/crypto.ipynb
vendored
Normal file
160
openbb_terminal/dashboards/voila/crypto.ipynb
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
284
openbb_terminal/dashboards/voila/currencies.ipynb
vendored
Normal file
284
openbb_terminal/dashboards/voila/currencies.ipynb
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
{
|
||||
"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",
|
||||
"from ipyflex import FlexLayout\n",
|
||||
"import matplotlib_inline.backend_inline\n",
|
||||
"from openbb_terminal.dashboards.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.9.6"
|
||||
},
|
||||
"voila": {
|
||||
"theme": "dark"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
320
openbb_terminal/dashboards/voila/forecast.ipynb
vendored
Normal file
320
openbb_terminal/dashboards/voila/forecast.ipynb
vendored
Normal file
@@ -0,0 +1,320 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e9ad60bc",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from datetime import datetime, timedelta\n",
|
||||
"from typing import Callable, Any\n",
|
||||
"from inspect import signature\n",
|
||||
"import warnings, logging\n",
|
||||
"\n",
|
||||
"warnings.filterwarnings(\"ignore\")\n",
|
||||
"logging.basicConfig(level=logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"pytorch_lightning\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.pl_forecasting_module\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.tcn_model\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.nbeats\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.NHiTSModel\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.nhits\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.torch_forecasting_model\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.forecasting_model\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.baselines\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"pytorch_lightning.accelerators.gpu\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.timeseries\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.utils.utils\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.utils.torch\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.tft_model\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.tft_submodels\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.utils.data.training_dataset\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.utils.data.horizon_based_dataset\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.utils.statistics\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.dataprocessing.transformers.scaler\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.RNNModel\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.BlockRNNModel\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.models.forecasting.NBEATSModel\").setLevel(logging.CRITICAL)\n",
|
||||
"logging.getLogger(\"darts.dataprocessing.transformers.fittable_data_transformer\").setLevel(logging.CRITICAL)\n",
|
||||
"\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import matplotlib_inline.backend_inline\n",
|
||||
"import ipywidgets as widgets\n",
|
||||
"import yfinance as yf\n",
|
||||
"import pandas as pd\n",
|
||||
"from IPython.display import display\n",
|
||||
"\n",
|
||||
"from openbb_terminal import api\n",
|
||||
"\n",
|
||||
"%matplotlib inline\n",
|
||||
"matplotlib_inline.backend_inline.set_matplotlib_formats(\"svg\")\n",
|
||||
"api.theme.applyMPLstyle()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "beb36881",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"try:\n",
|
||||
" has_forecast = True\n",
|
||||
" model_opts = {\n",
|
||||
" \"expo\": api.forecast.expo,\n",
|
||||
" \"theta\": api.forecast.theta,\n",
|
||||
" \"linregr\": api.forecast.linregr,\n",
|
||||
" \"regr\": api.forecast.regr,\n",
|
||||
" \"rnn\": api.forecast.rnn,\n",
|
||||
" \"brnn\": api.forecast.brnn,\n",
|
||||
" \"nbeats\": api.forecast.nbeats,\n",
|
||||
" \"tcn\": api.forecast.tcn,\n",
|
||||
" \"trans\": api.forecast.trans,\n",
|
||||
" \"tft\": api.forecast.tft,\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" feat_engs = {\n",
|
||||
" \"ema\": api.forecast.ema,\n",
|
||||
" \"sto\": api.forecast.sto,\n",
|
||||
" \"rsi\": api.forecast.rsi,\n",
|
||||
" \"roc\": api.forecast.roc,\n",
|
||||
" \"mom\": api.forecast.mom,\n",
|
||||
" \"atr\": api.forecast.atr,\n",
|
||||
" \"delta\": api.forecast.delta,\n",
|
||||
" \"signal\": api.forecast.signal,\n",
|
||||
" }\n",
|
||||
"except AttributeError:\n",
|
||||
" has_forecast = False\n",
|
||||
" model_opts = {}\n",
|
||||
" feat_engs = {}\n",
|
||||
"\n",
|
||||
"interval_opts = [\"1m\",\"2m\",\"5m\",\"15m\",\"30m\",\"60m\",\"90m\",\"1h\",\"1d\",\"5d\",\"1wk\",\"1mo\",\"3mo\"]\n",
|
||||
"\n",
|
||||
"def format_df(df: pd.DataFrame) -> pd.DataFrame:\n",
|
||||
" if len(df.columns) != 6:\n",
|
||||
" df.columns = ['_'.join(col).strip() for col in df.columns.values]\n",
|
||||
" df.reset_index(inplace=True)\n",
|
||||
" df.columns = [x.lower() for x in df.columns]\n",
|
||||
" return df\n",
|
||||
"\n",
|
||||
"def has_parameter(func: Callable[..., Any], parameter: str) -> bool:\n",
|
||||
" params = signature(func).parameters\n",
|
||||
" parameters = params.keys()\n",
|
||||
" return parameter in parameters"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "f8c2f65c",
|
||||
"metadata": {
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Chart:\n",
|
||||
" def __init__(self):\n",
|
||||
" self.last_tickers = \"\"\n",
|
||||
" self.last_interval = \"1d\"\n",
|
||||
" self.df = pd.DataFrame()\n",
|
||||
" self.infos = {}\n",
|
||||
"\n",
|
||||
" def handle_changes(\n",
|
||||
" self, past_covariates, start, end, interval, tickers, target_column, model, naive, forecast_only\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.df = format_df(self.df)\n",
|
||||
" self.last_tickers = tickers\n",
|
||||
" self.last_interval = interval\n",
|
||||
" forecast_model = model_opts[model]\n",
|
||||
" contains_covariates = has_parameter(forecast_model, \"past_covariates\")\n",
|
||||
" \n",
|
||||
" #Update Inputs\n",
|
||||
" if list(target_widget.options) != [x for x in self.df.columns if x != \"date\"]:\n",
|
||||
" target_widget.options = [x for x in self.df.columns if x != \"date\"]\n",
|
||||
" return\n",
|
||||
" if list(past_covs_widget.options) != [x for x in self.df.columns if x != \"date\"]:\n",
|
||||
" past_covs_widget.options = [x for x in self.df.columns if x != \"date\"]\n",
|
||||
" past_covs_widget.disabled = not contains_covariates\n",
|
||||
" return\n",
|
||||
" if past_covs_widget.disabled == contains_covariates:\n",
|
||||
" past_covs_widget.disabled = not contains_covariates\n",
|
||||
" column_widget.options = [x for x in self.df.columns if x != \"date\"]\n",
|
||||
" \n",
|
||||
"\n",
|
||||
" start_n = datetime(start.year, start.month, start.day)\n",
|
||||
" end_n = datetime(end.year, end.month, end.day)\n",
|
||||
" calcs = self.df\n",
|
||||
" if interval in [\"1d\", \"5d\", \"1wk\", \"1mo\", \"3mo\"]:\n",
|
||||
" result = calcs.loc[\n",
|
||||
" (calcs[\"date\"] >= start_n) & (calcs[\"date\"] <= end_n)\n",
|
||||
" ]\n",
|
||||
" else:\n",
|
||||
" result = calcs\n",
|
||||
" if not target_column:\n",
|
||||
" target_column = self.df.columns[0]\n",
|
||||
" kwargs = {}\n",
|
||||
" if contains_covariates and past_covariates != ():\n",
|
||||
" kwargs[\"past_covariates\"] = \",\".join(past_covariates)\n",
|
||||
" if has_parameter(forecast_model, \"naive\"):\n",
|
||||
" kwargs[\"naive\"] = naive\n",
|
||||
" if has_parameter(forecast_model, \"forecast_only\"):\n",
|
||||
" kwargs[\"forecast_only\"] = forecast_only\n",
|
||||
" # This sets up everything to run the function on button click\n",
|
||||
" self.forecast_model = forecast_model\n",
|
||||
" self.result = result\n",
|
||||
" self.target_column = target_column\n",
|
||||
" self.n_predict = 5\n",
|
||||
" self.kwargs = kwargs\n",
|
||||
" \n",
|
||||
" def handle_click(self, to_run):\n",
|
||||
" if to_run:\n",
|
||||
" run_widget.value = False\n",
|
||||
" else:\n",
|
||||
" df = self.result.dropna()\n",
|
||||
" self.forecast_model(self.result, target_column=self.target_column, n_predict=5, **self.kwargs)\n",
|
||||
" \n",
|
||||
" def handle_eng(self, target, feature):\n",
|
||||
" self.feature_target = target\n",
|
||||
" self.feature_model = feat_engs[feature]\n",
|
||||
"\n",
|
||||
" \n",
|
||||
" def handle_click2(self, to_run):\n",
|
||||
" if to_run:\n",
|
||||
" add_widget.value = False\n",
|
||||
" else:\n",
|
||||
" kwargs = {}\n",
|
||||
" if has_parameter(self.feature_model, \"target_column\"):\n",
|
||||
" kwargs[\"target_column\"] = self.feature_target\n",
|
||||
" self.df = self.feature_model(self.df, **kwargs)\n",
|
||||
" past_covs_widget.options = self.df.columns"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e0d4de31-1b4f-4c1f-8467-ca314a578d56",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"w_auto = widgets.Layout(width=\"auto\")\n",
|
||||
"model_value = list(model_opts)[0] if model_opts else None\n",
|
||||
"model_widget = widgets.Select(options=list(model_opts), value=model_value, layout=widgets.Layout(width=\"8%\",))\n",
|
||||
"past_covs_widget = widgets.SelectMultiple(options=[\"\"], value=[\"\"], layout=widgets.Layout(width=\"8%\",))\n",
|
||||
"\n",
|
||||
"base_date = (datetime.today() - timedelta(days=365)).date()\n",
|
||||
"start_widget = widgets.DatePicker(value=base_date, layout=w_auto, description=\"Start\")\n",
|
||||
"end_widget = widgets.DatePicker(\n",
|
||||
" value=datetime.today().date(), layout=w_auto, description=\"End\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"target_widget = widgets.Dropdown(options=[\"\"], value=\"\", description=\"Target\")\n",
|
||||
"interval_widget = widgets.Dropdown(options=interval_opts, value=\"1d\", layout=w_auto, description=\"Interval\")\n",
|
||||
"tickers_widget = widgets.Textarea(value=\"TSLA,\", layout=widgets.Layout(width=\"auto\", height=\"100%\"))\n",
|
||||
"\n",
|
||||
"# Output box\n",
|
||||
"naive_widget = widgets.ToggleButton(value=False, description=\"Show Naive\")\n",
|
||||
"forecast_only_widget = widgets.ToggleButton(value=False, description=\"Forecast Only\")\n",
|
||||
"run_widget = widgets.ToggleButton(value=False, description=\"Run Model\")\n",
|
||||
"\n",
|
||||
"#feat_box\n",
|
||||
"feat_value = list(feat_engs.keys())[0] if feat_engs else None\n",
|
||||
"column_widget = widgets.Dropdown(options=[\"\"], value=\"\", description=\"Target\")\n",
|
||||
"feat_widget = widgets.Dropdown(options=list(feat_engs.keys()), value=feat_value, description=\"Feature\")\n",
|
||||
"add_widget = widgets.ToggleButton(value=False, description=\"Add Feature\", layout=widgets.Layout(align=\"flex_end\")) # get this to work\n",
|
||||
"\n",
|
||||
"selection_box = widgets.VBox([tickers_widget, target_widget])\n",
|
||||
"date_box = widgets.VBox([start_widget, end_widget, interval_widget])\n",
|
||||
"output_box = widgets.VBox([naive_widget, forecast_only_widget, run_widget])\n",
|
||||
"feat_box = widgets.VBox([column_widget, feat_widget, add_widget])\n",
|
||||
"controls = widgets.HBox(\n",
|
||||
" [selection_box, model_widget, past_covs_widget, date_box, output_box, feat_box],\n",
|
||||
")\n",
|
||||
"if has_forecast:\n",
|
||||
" chart = Chart()\n",
|
||||
" widgets.interactive_output(\n",
|
||||
" chart.handle_changes,\n",
|
||||
" {\n",
|
||||
" \"past_covariates\": past_covs_widget,\n",
|
||||
" \"start\": start_widget,\n",
|
||||
" \"end\": end_widget,\n",
|
||||
" \"interval\": interval_widget,\n",
|
||||
" \"tickers\": tickers_widget,\n",
|
||||
" \"target_column\": target_widget,\n",
|
||||
" \"model\": model_widget,\n",
|
||||
" \"naive\": naive_widget,\n",
|
||||
" \"forecast_only\": forecast_only_widget,\n",
|
||||
" },\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" widgets.interactive_output(chart.handle_eng, {\"target\": column_widget,\"feature\": feat_widget})\n",
|
||||
" widgets.interactive_output(chart.handle_click2, {\"to_run\": add_widget})\n",
|
||||
"\n",
|
||||
" stocks_view = widgets.interactive_output(chart.handle_click, {\"to_run\": run_widget})\n",
|
||||
"\n",
|
||||
" title_html = \"<h1>Timeseries Forecasting 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), stocks_view]\n",
|
||||
" app = widgets.VBox(app_contents)\n",
|
||||
"else:\n",
|
||||
" title_html = \"<h1>Timeseries Forecasting Dashboard</h1>\"\n",
|
||||
" warning_html = '<p style=\"color:red\"=>The forecasting dependencies are not installed.</p>'\n",
|
||||
" app = widgets.VBox([widgets.HTML(title_html), widgets.HTML(warning_html)])\n",
|
||||
"display(app)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "9dbf43a2-70e1-44e9-a524-be3e97008b58",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.6"
|
||||
},
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "e896a00ead8b521528d79ac9ef24990696f2b751eb283ab8e0d078c9c4971ffc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
321
openbb_terminal/dashboards/voila/futures.ipynb
vendored
Normal file
321
openbb_terminal/dashboards/voila/futures.ipynb
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e9ad60bc",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os, sys\n",
|
||||
"import calendar\n",
|
||||
"from datetime import datetime, timedelta\n",
|
||||
"import pandas as pd\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\n",
|
||||
"from pathlib import Path\n",
|
||||
"\n",
|
||||
"from openbb_terminal.core.config.paths import REPOSITORY_DIRECTORY"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "01e1841a-ab16-4111-9b45-8ac66b85ab9f",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"full_path = REPOSITORY_DIRECTORY / \"custom_imports\" / \"dashboards\" / \"futures.csv\"\n",
|
||||
"df = pd.read_csv(full_path)\n",
|
||||
"months = [\"F\", \"G\", \"H\", \"J\", \"K\", \"M\", \"N\", \"Q\", \"U\", \"V\", \"X\", \"Z\"]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "beb36881",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os, sys\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class HiddenPrints:\n",
|
||||
" def __enter__(self):\n",
|
||||
" self._original_stdout = sys.stdout\n",
|
||||
" sys.stdout = open(os.devnull, \"w\")\n",
|
||||
"\n",
|
||||
" def __exit__(self, exc_type, exc_val, exc_tb):\n",
|
||||
" sys.stdout.close()\n",
|
||||
" sys.stdout = self._original_stdout\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def format_plotly(fig, data, chart, calc=None):\n",
|
||||
" fig.update_yaxes(title=None)\n",
|
||||
" fig.update_xaxes(title=None)\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, fig):\n",
|
||||
" if visual == \"line\":\n",
|
||||
" plot = go.Scatter(x=x, y=y, mode=\"lines\", name=name) # , connectgaps=True\n",
|
||||
" if visual == \"scatter\":\n",
|
||||
" plot = go.Scatter(x=x, y=y, 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 build_ticker(ticker: str, month: int, year: int) -> str:\n",
|
||||
" if ticker:\n",
|
||||
" row = df[df[\"Ticker\"] == f\"{ticker.split(':')[0]}=F\"].iloc[0]\n",
|
||||
" row = row.to_dict()\n",
|
||||
" the_tick = row[\"Ticker\"].replace(\"=F\", \"\")\n",
|
||||
" return f\"{the_tick}{months[month-1]}{str(year)[-2:]}.{row['Exchange']}\"\n",
|
||||
" return \"\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def next_ticker(ticker: str) -> str:\n",
|
||||
" symbol, exchange = ticker.split(\".\")\n",
|
||||
" month = symbol[-3]\n",
|
||||
" if month == \"Z\":\n",
|
||||
" new_month = \"F\"\n",
|
||||
" new_year = int(symbol[-2:]) + 1\n",
|
||||
" else:\n",
|
||||
" index = months.index(month)\n",
|
||||
" new_month = months[index + 1]\n",
|
||||
" new_year = int(symbol[-2:])\n",
|
||||
" return f\"{symbol[:-3]}{new_month}{new_year}.{exchange}\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_column(df: pd.DataFrame, column: str):\n",
|
||||
" sub_df = df.xs(column, level=1, axis=1, drop_level=False)\n",
|
||||
" sub_df.columns = sub_df.columns.to_flat_index().map(lambda x: x[0])\n",
|
||||
" sub_df = sub_df.dropna(how=\"all\")\n",
|
||||
" sub_df = sub_df.sort_index()\n",
|
||||
" if sub_df.empty:\n",
|
||||
" return None\n",
|
||||
" return sub_df\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def get_date(x: str) -> datetime:\n",
|
||||
" ticker, _ = x.split(\".\")\n",
|
||||
" month_str = ticker[-3]\n",
|
||||
" month = months.index(month_str) + 1\n",
|
||||
" year = int(ticker[-2:]) + 2000\n",
|
||||
" day = calendar.monthrange(year, month)\n",
|
||||
" return datetime(year, month, day[1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "f8c2f65c",
|
||||
"metadata": {
|
||||
"tags": [
|
||||
"parameters"
|
||||
]
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Chart:\n",
|
||||
" def __init__(self):\n",
|
||||
" self.tickers = {}\n",
|
||||
" self.last_ticker = \"\"\n",
|
||||
"\n",
|
||||
" def create_stock(self, chart_type, contracts, ticker):\n",
|
||||
" if not ticker:\n",
|
||||
" return\n",
|
||||
"\n",
|
||||
" if self.last_ticker != ticker:\n",
|
||||
" now = datetime.now()\n",
|
||||
" clean_ticker = build_ticker(ticker, now.month, now.year)\n",
|
||||
" if clean_ticker:\n",
|
||||
" raw_tickers = [clean_ticker]\n",
|
||||
" for _ in range(36):\n",
|
||||
" new_ticker = next_ticker(raw_tickers[-1])\n",
|
||||
" raw_tickers.append(new_ticker)\n",
|
||||
" raw_ticker = \",\".join(raw_tickers)\n",
|
||||
" with HiddenPrints():\n",
|
||||
" dfs = yf.download(raw_ticker, progress=False) # ,period=\"max\"\n",
|
||||
" self.tickers = {\n",
|
||||
" x: {\"data\": get_column(dfs, x), \"date\": get_date(x)}\n",
|
||||
" for x in raw_tickers\n",
|
||||
" }\n",
|
||||
" self.last_ticker = ticker\n",
|
||||
"\n",
|
||||
" fig = go.Figure()\n",
|
||||
" i = 0\n",
|
||||
" if chart_type[0][:4] == \"Hist\":\n",
|
||||
" for key, item in self.tickers.items():\n",
|
||||
" if i == contracts:\n",
|
||||
" break\n",
|
||||
" result = item[\"data\"]\n",
|
||||
" if result is not None:\n",
|
||||
" create_line(\n",
|
||||
" visual=\"line\",\n",
|
||||
" x=result.index,\n",
|
||||
" y=result[\"Adj Close\"],\n",
|
||||
" name=key,\n",
|
||||
" fig=fig,\n",
|
||||
" )\n",
|
||||
" i += 1\n",
|
||||
" else:\n",
|
||||
" x = []\n",
|
||||
" y = []\n",
|
||||
" for _, value in self.tickers.items():\n",
|
||||
" if len(x) > contracts:\n",
|
||||
" break\n",
|
||||
" if value[\"data\"] is None:\n",
|
||||
" continue\n",
|
||||
" x.append(value[\"date\"])\n",
|
||||
" y.append(value[\"data\"][\"Adj Close\"].iloc[-1])\n",
|
||||
" create_line(visual=\"line\", x=x, y=y, name=\"Future Curve\", fig=fig)\n",
|
||||
"\n",
|
||||
" format_plotly(fig, \"Close\", \"main\", \"raw\")\n",
|
||||
" show_fig(fig)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "e0d4de31-1b4f-4c1f-8467-ca314a578d56",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"category = df[\"Category\"].unique().tolist()\n",
|
||||
"exchange = df[df[\"Category\"].isin([category[0]])][\"Exchange\"].unique().tolist()\n",
|
||||
"filt_df = df[df[\"Category\"].isin([category[0]]) & df[\"Exchange\"].isin([exchange[0]])]\n",
|
||||
"tickers_raw = filt_df[[\"Ticker\", \"Description\"]].values.tolist()\n",
|
||||
"tickers = [f\"{x.replace('=F', '')}: {y}\" for x, y in tickers_raw]\n",
|
||||
"\n",
|
||||
"category.sort()\n",
|
||||
"exchange.sort()\n",
|
||||
"tickers.sort()\n",
|
||||
"\n",
|
||||
"chart_type = [\"Historical Time Series\", \"Future Curve\"]\n",
|
||||
"cat_widget = widgets.SelectMultiple(options=category, value=[category[0]])\n",
|
||||
"exch_widget = widgets.SelectMultiple(options=exchange, value=[exchange[0]])\n",
|
||||
"tickers_widget = widgets.Select(options=tickers, value=tickers[0])\n",
|
||||
"chart_widget = widgets.SelectMultiple(options=chart_type, value=[chart_type[0]])\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def on_change(change):\n",
|
||||
" cat_value = cat_widget.value\n",
|
||||
" exch_value = exch_widget.value\n",
|
||||
"\n",
|
||||
" # Filter exchange widget\n",
|
||||
" exch_filtered = df[df[\"Category\"].isin(cat_value)][\"Exchange\"].unique().tolist()\n",
|
||||
" exch_filtered.sort()\n",
|
||||
" exch_widget.options = exch_filtered\n",
|
||||
"\n",
|
||||
" # Filter ticker widget\n",
|
||||
" filtered = df[df[\"Category\"].isin(cat_value) & df[\"Exchange\"].isin(exch_value)]\n",
|
||||
" tick_raw = filtered[[\"Ticker\", \"Description\"]].values.tolist()\n",
|
||||
" tick = [f\"{x.replace('=F', '')}: {y}\" for x, y in tick_raw]\n",
|
||||
" tick.sort()\n",
|
||||
" tickers_widget.options = tick\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"cat_widget.observe(on_change)\n",
|
||||
"exch_widget.observe(on_change)\n",
|
||||
"\n",
|
||||
"contracts_widget = widgets.Dropdown(\n",
|
||||
" options=list(range(1, 25)), value=6, description=\"Contracts\"\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"controls = widgets.HBox(\n",
|
||||
" [cat_widget, exch_widget, tickers_widget, chart_widget, contracts_widget],\n",
|
||||
" layout=widgets.Layout(width=\"90%\"),\n",
|
||||
")\n",
|
||||
"chart = Chart()\n",
|
||||
"stocks_view = widgets.interactive_output(\n",
|
||||
" chart.create_stock,\n",
|
||||
" {\n",
|
||||
" \"chart_type\": chart_widget,\n",
|
||||
" \"contracts\": contracts_widget,\n",
|
||||
" \"ticker\": tickers_widget,\n",
|
||||
" },\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"title_html = \"<h1>Futures Analysis Dashboard</h1>\"\n",
|
||||
"\n",
|
||||
"app_contents = [widgets.HTML(title_html), controls, stocks_view]\n",
|
||||
"app = widgets.VBox(app_contents)\n",
|
||||
"display(app)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "6e4c3424-91c9-47c5-b336-fe8e40944905",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.6"
|
||||
},
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "e896a00ead8b521528d79ac9ef24990696f2b751eb283ab8e0d078c9c4971ffc"
|
||||
}
|
||||
},
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "ab0e87f2bc73919b75956d1b3e303320699d53da895be1bb46287d7dc67c6497"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
236
openbb_terminal/dashboards/voila/shortdata.ipynb
vendored
Normal file
236
openbb_terminal/dashboards/voila/shortdata.ipynb
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"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": null,
|
||||
"metadata": {
|
||||
"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": null,
|
||||
"metadata": {
|
||||
"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": null,
|
||||
"metadata": {
|
||||
"jupyter": {
|
||||
"outputs_hidden": false
|
||||
},
|
||||
"pycharm": {
|
||||
"name": "#%%\n"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"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
|
||||
}
|
||||
404
openbb_terminal/dashboards/voila/stocks.ipynb
vendored
Normal file
404
openbb_terminal/dashboards/voila/stocks.ipynb
vendored
Normal file
@@ -0,0 +1,404 @@
|
||||
{
|
||||
"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.9.13"
|
||||
},
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "e896a00ead8b521528d79ac9ef24990696f2b751eb283ab8e0d078c9c4971ffc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
162
openbb_terminal/dashboards/voila/vsurf.ipynb
vendored
Normal file
162
openbb_terminal/dashboards/voila/vsurf.ipynb
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
Reference in New Issue
Block a user