Skip to content

Commit 77ef64f

Browse files
committed
finish activity01 lesson7 bokeh widgets
1 parent e90fcf0 commit 77ef64f

File tree

2 files changed

+110
-39
lines changed

2 files changed

+110
-39
lines changed

lesson07/Activity01/activity01_solution.ipynb

Lines changed: 110 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,13 @@
662662
"cell_type": "markdown",
663663
"metadata": {},
664664
"source": [
665-
"... TODO"
665+
"There are many options when it comes to choosing which interactivity to use. \n",
666+
"Since the goal of this activity is to be able to compare two stocks with each other in terms of traded volume and the high/low and open/close prices over a time range, we will need widgets to select elements and a slider to select a given range. \n",
667+
"Considering that we have to options of display, we also need a way to select either one or the other. \n",
668+
"\n",
669+
"At the end of this task, you will have something comparable to image below implemented and ready to compare data from the dataset.\n",
670+
"\n",
671+
"<img src=\"./data/candle_plot.png\" width=500 align=\"left\"/>"
666672
]
667673
},
668674
{
@@ -680,14 +686,43 @@
680686
"cell_type": "markdown",
681687
"metadata": {},
682688
"source": [
683-
"...TODO \n",
689+
"Before we go in and implement the plotting methods, we want to set up the interactivity widgets. \n",
690+
"**Please scroll down** to the cell that says `# extracing the necessary data` before implementing the plotting. \n",
691+
"\n",
692+
"Still make sure to execute the cells below that will simply `pass` and do nothing for now."
693+
]
694+
},
695+
{
696+
"cell_type": "markdown",
697+
"metadata": {},
698+
"source": [
699+
"At the moment, our `show()` in the last cell will not render any elements into our visualization. \n",
700+
"We will start with the, so called, candle stick visualization which is often used with stock price data. \n",
701+
"\n",
702+
"The already defined method below gets our `plot` object, a `stock_name`, a `stock_range` containing the data for the, with the widgets, selected range, and a color for the line. \n",
703+
"We will use those arguments to create the candle sticks. They basically contain of a `segment` that creates the vertical line, and either a green or red `vbar` to color code whether the close price is lower than the open price. \n",
704+
"\n",
705+
"\n",
706+
"Once you have created the candles, we also want to have a continuous line running through the mean (high, low) point of each candle. So you have to calculate the mean for every high, low pair and then plot those data points with a line with the given `color`.\n",
707+
"\n",
708+
"Make sure to reference the example provided in the Bokeh library here, you can adapt the code in there to our arguments.\n",
684709
"https://bokeh.pydata.org/en/latest/docs/gallery/candlestick.html\n",
685-
"https://bokeh.pydata.org/en/latest/docs/user_guide/interaction/legends.html"
710+
"\n",
711+
"After you are done implementing the `add_candle_plot` method, scroll down and run the `@interact` cell again. \n",
712+
"You will now see the candles being displayed for the two selected stocks."
713+
]
714+
},
715+
{
716+
"cell_type": "markdown",
717+
"metadata": {},
718+
"source": [
719+
"**Note:** \n",
720+
"Since we are providing the `plot` as a reference to the method, we don't need to return anything since we are mutating our passed in plot."
686721
]
687722
},
688723
{
689724
"cell_type": "code",
690-
"execution_count": 192,
725+
"execution_count": 13,
691726
"metadata": {},
692727
"outputs": [],
693728
"source": [
@@ -713,23 +748,32 @@
713748
" stock_mean_val=stock_range[['high', 'low']].mean(axis=1)\n",
714749
" plot.line(stock_range['short_date'], stock_mean_val, \n",
715750
" legend=('Mean price of ' + stock_name), muted_alpha=0.2,\n",
716-
" line_color=color, alpha=0.5)\n",
751+
" line_color=color, alpha=0.5)"
752+
]
753+
},
754+
{
755+
"cell_type": "markdown",
756+
"metadata": {},
757+
"source": [
758+
"The last missing step is implementing the plotting of the lines if the `volume` value is selected. \n",
759+
"We've created simple lines in the previous exercise, so this should not be a problem. \n",
717760
"\n",
718-
" return plot"
761+
"One additional interaction feature is to have an interactive legend that allows us to \"mute\", meaning grey out, each stock in the visualization. \n",
762+
"To make our legend interactive please take a look at the documentation for the legend feature.\n",
763+
"https://bokeh.pydata.org/en/latest/docs/user_guide/interaction/legends.html"
719764
]
720765
},
721766
{
722-
"cell_type": "code",
723-
"execution_count": null,
767+
"cell_type": "markdown",
724768
"metadata": {},
725-
"outputs": [],
726769
"source": [
727-
"...TODO"
770+
"**Note:** \n",
771+
"Don't forget to update your `add_canlde_plot` `vbar`s and `segment` to also include the `muted_alpha` parameter. Otherwise you won't be able to mute the stocks in the \"open-close\" visualization."
728772
]
729773
},
730774
{
731775
"cell_type": "code",
732-
"execution_count": 193,
776+
"execution_count": 14,
733777
"metadata": {},
734778
"outputs": [],
735779
"source": [
@@ -754,8 +798,8 @@
754798
" plot.grid.grid_line_alpha=0.3\n",
755799
" \n",
756800
" if value == 'open-close':\n",
757-
" candle_plot_1=add_candle_plot(plot, stock_1_name, stock_1_range, 'blue')\n",
758-
" candle_plot_2=add_candle_plot(plot, stock_2_name, stock_2_range, 'orange')\n",
801+
" add_candle_plot(plot, stock_1_name, stock_1_range, 'blue')\n",
802+
" add_candle_plot(plot, stock_2_name, stock_2_range, 'orange')\n",
759803
" \n",
760804
" if value == 'volume':\n",
761805
" plot.line(stock_1_range['short_date'], stock_1_range['volume'], \n",
@@ -773,16 +817,25 @@
773817
"cell_type": "markdown",
774818
"metadata": {},
775819
"source": [
776-
"...TODO"
820+
"We want to **start implementing our visualization here**. \n",
821+
"\n",
822+
"In the following cells, we will extract the necessary data which will be provided to the widget elements. \n",
823+
"In the first cell we want to extract the following information:\n",
824+
"- a list of unique stock names that are present in the dataset\n",
825+
"- a list of all short_dates that are in 2016\n",
826+
"- a sorted list of unique dates generated from the previous list of dates from 2016\n",
827+
"- a list with the values `open-close` and `volume`\n",
828+
"\n",
829+
"Once we have this information in place, we can start building our widgets."
777830
]
778831
},
779832
{
780833
"cell_type": "code",
781-
"execution_count": 194,
834+
"execution_count": 15,
782835
"metadata": {},
783836
"outputs": [],
784837
"source": [
785-
"# extracing all the stock names\n",
838+
"# extracing the necessary data\n",
786839
"stock_names=dataset['symbol'].unique()\n",
787840
"dates_2016=dataset[dataset['short_date'] >= '2016-01-01']['short_date']\n",
788841
"unique_dates_2016=sorted(dates_2016.unique())\n",
@@ -793,20 +846,27 @@
793846
"cell_type": "markdown",
794847
"metadata": {},
795848
"source": [
796-
"...TODO"
797-
]
798-
},
799-
{
800-
"cell_type": "markdown",
801-
"metadata": {},
802-
"source": [
803-
"**Note:** \n",
804-
"As mentioned in the previous exercise, we can also make use of the widgets described here: https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20List.html"
849+
"Given the extracted information from the cell above, we can now define the widgets and provide the available options to it. \n",
850+
"\n",
851+
"As mentioned in the introduction, we want to have several interactive features including:\n",
852+
"- two `Dropdown`s with which we can select two stocks that should be compared to each other\n",
853+
" - the first dropdown by default should have the `AAPL` stock selected, named \"Compare: \"\n",
854+
" - the second dropdown by default should have the `AON` stock selected, named \"to: \"\n",
855+
" \n",
856+
" \n",
857+
"- a `SelectionRange` which will allow us to select a range of dates from the extracted list of unique 2016 dates\n",
858+
" - by default, the first 25 dates should be selected, named \"From-To\"\n",
859+
" - make sure to disable the `continuous_update` parameter here\n",
860+
" - adjust the layout width to 500px to make sure the dates are displayed correctly\n",
861+
" \n",
862+
" \n",
863+
"- a `RadioButton` group that provides the options \"open-close\" and \"volume\"\n",
864+
" - by default, \"open-close\" should be selected, named \"Metric\""
805865
]
806866
},
807867
{
808868
"cell_type": "code",
809-
"execution_count": 195,
869+
"execution_count": 16,
810870
"metadata": {},
811871
"outputs": [],
812872
"source": [
@@ -827,26 +887,41 @@
827887
"\n",
828888
"value_radio=widgets.RadioButtons(options=value_options,\n",
829889
" value='open-close',\n",
830-
" description='Metric',\n",
831-
" orientation='horizontal')"
890+
" description='Metric')"
832891
]
833892
},
834893
{
835894
"cell_type": "markdown",
836895
"metadata": {},
837896
"source": [
838-
"...TODO"
897+
"**Note:** \n",
898+
"As mentioned in the previous exercise, we can also make use of the widgets described here: https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20List.html"
899+
]
900+
},
901+
{
902+
"cell_type": "markdown",
903+
"metadata": {},
904+
"source": [
905+
"After setting up the widgets, we can the method that will be called with each update of the interaction widgets. \n",
906+
"As seen in the previous exercise, we will use the `@interact` decorator for this. \n",
907+
"\n",
908+
"Instead of value ranges or lists, we will provide the variable names of our already created widgets in the decorator. \n",
909+
"The method will get 4 arguments, `stock_1`, `stock_2`, `date`, and `value`. \n",
910+
"Since we have already set up the empty method that will return a plot above, we can call `show()` with the method call inside to show the result once it is returned from the `get_stock_for_2016` method. \n",
911+
"\n",
912+
"Once you've build the widgets, upon execution, you will see them being displayed below the cell. \n",
913+
"We are now ready to to **scroll up and implement the plotting** with Bokeh."
839914
]
840915
},
841916
{
842917
"cell_type": "code",
843-
"execution_count": 196,
918+
"execution_count": 17,
844919
"metadata": {},
845920
"outputs": [
846921
{
847922
"data": {
848923
"application/vnd.jupyter.widget-view+json": {
849-
"model_id": "907e39bdce42436dbf30d133937f7c27",
924+
"model_id": "3c69a87a11504dd28beb7f5bece89d1d",
850925
"version_major": 2,
851926
"version_minor": 0
852927
},
@@ -869,16 +944,12 @@
869944
"cell_type": "markdown",
870945
"metadata": {},
871946
"source": [
947+
"This is a nice example that shows us how much interaction we can add to a visualization with very simple techniques such as using the interact functionality. \n",
948+
"\n",
872949
"**Note:** \n",
873-
"We can already see that each date is displayed on the x-axis. If we want to display a bigger time range, we have to customize the ticks on our x-axis. This can be done using `Ticker` objects. "
950+
"Think about what else you could add/change for this visualization. Maybe we don't only want to display 2016 but be able to select the year we want to display. Maybe we want to compare different years with each other. \n",
951+
"There are endless options.\n"
874952
]
875-
},
876-
{
877-
"cell_type": "code",
878-
"execution_count": null,
879-
"metadata": {},
880-
"outputs": [],
881-
"source": []
882953
}
883954
],
884955
"metadata": {
237 KB
Loading

0 commit comments

Comments
 (0)