mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-29 05:21:48 +00:00
* bring dashboards and reports menus one step above * remove checkpoints * add notebooks again
256 lines
8.6 KiB
Plaintext
Vendored
256 lines
8.6 KiB
Plaintext
Vendored
{
|
|
"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
|
|
}
|