Make interactive charts with bokeh
Bokeh is a Python library for interactive data visualization, which allow users to create dynamic and engaging charts that go beyond static pictures. Bokeh's toolkit offers a range of interactive features, from hover tooltips, zoomable plots, to dropdown selection . Here is a demonstration of how to use Bokeh to create an interactive chart to compare historical stock price performance between 7 stocks
Download and prepare historical stock data
Using yfinance library to scrape data from Yahoo Finance and prepare it the usual way
# import libraries import yfinance as yf import pandas as pd import datetime # Download all stock price historical data from yahoo finance spy_data = yf.download("SPY") aapl_data = yf.download("AAPL") goog_data = yf.download("GOOG") tsla_data = yf.download("TSLA") amzn_data = yf.download("AMZN") meta_data = yf.download("META") nvda_data = yf.download("NVDA") # Reset index to turn date to a separate column spy_data.reset_index(inplace=True) aapl_data.reset_index(inplace=True) goog_data.reset_index(inplace=True) tsla_data.reset_index(inplace=True) amzn_data.reset_index(inplace=True) meta_data.reset_index(inplace=True) nvda_data.reset_index(inplace=True) # Add a column for ticker symbol spy_data['Ticker'] = 'SPY' aapl_data['Ticker'] = 'AAPL' goog_data['Ticker'] = 'GOOG' tsla_data['Ticker'] = 'TSLA' amzn_data['Ticker'] = 'AMZN' meta_data['Ticker'] = 'META' nvda_data['Ticker'] = 'NVDA' # Preview dataframe spy_data.head()
Printing out the first 5 rows of a dataframe to examine if data shows up as expected
# Put all stocks into a consolidated data frame stock_all = pd.concat([spy_data, aapl_data, goog_data, tsla_data, amzn_data, meta_data, nvda_data]) # Restrict data to work with to only dates after specific year stock_all['Date'] = pd.to_datetime(stock_all['Date']) df = stock_all[stock_all['Date'] >= '2010-01-01'] # preview data frame structure df.info()
2. Create an interactive chart to compare historical price performance
First, import related modules
# import libraries from bokeh.layouts import layout, column, row from bokeh.models import ColumnDataSource, RangeSlider, DateRangeSlider, HoverTool, CDSView, BooleanFilter, CustomJS, Dropdown, Select, Div from bokeh.plotting import figure, output_notebook, show output_notebook()
And create a chart, add in Timeline Slider, Legend and Hover Tools
# Define date range for graph start_date = pd.to_datetime('2010-01-01') end_date = datetime.datetime.now() date_rangeX = pd.date_range(start = start_date, end = end_date) # Create lists for ticker & color ticker_list = ['SPY', 'AAPL', 'AMZN', 'GOOG', 'META', 'NVDA', 'TSLA'] color_list = ['lightblue', 'red', 'orange', 'darkblue', 'olive', 'darkgreen', 'pink'] # Instantiating the figure object graph = figure(title = f"Stock Closing Prices {start_date.year}-{end_date.year}", x_axis_type = "datetime", x_axis_label = 'Date', y_axis_label = 'Price (USD)', sizing_mode = "stretch_width", height = 500) # Make font size of title bigger graph.title.text_font_size = '20pt' graph.title.align = "center" # Draw graphs for all ticker on the list for data, name, color in zip([df[df['Ticker']== 'SPY'], df[df['Ticker']== 'AAPL'], df[df['Ticker']== 'AMZN'], df[df['Ticker']== 'GOOG'], df[df['Ticker']== 'META'], df[df['Ticker']== 'NVDA'], df[df['Ticker']== 'TSLA']], ticker_list, color_list ): graph.line(data['Date'], data['Adj Close'], line_width=1.5, color=color, alpha=0.8, legend_label=name) # Put legend to top left corner & define click_policy graph.legend.location = "top_left" graph.legend.click_policy = "hide" # Set up RangeSlider for timeline timeline_slider = DateRangeSlider( title = "Adjust timeline (x-axis) range", start = date_rangeX.min(), end = date_rangeX.max(), step = 1, value = (date_rangeX.min(), date_rangeX.max()), sizing_mode = "stretch_width") # Add callback code timeline_slider.js_link("value", graph.x_range, "start", attr_selector=0) timeline_slider.js_link("value", graph.x_range, "end", attr_selector=1) # Define the tooltip hover_tool = HoverTool( tooltips = [ ('Date', '@x{%F}'), ('Adj Price', '@y{$0.00}' ) ], formatters = {'@x': 'datetime'} ) # Add hover_tool to graph graph.add_tools(hover_tool) # create layout layout = column(graph, timeline_slider, sizing_mode = 'stretch_both') # show result show(layout)
And the result is a beautiful interactive chart that allows users to read details when they want to utilizing different tools and to narrow comparison to a subset of stocks
Moving the timeline range at the bottom of the chart to start in 2021, we can zoom into the last 2+ years of stock performance. If we hover the mouse over each line, details about date and adjusted closing price are shown
To narrow down the selection of stock to compare, we can click on the ticker symbols in the legend box to the left. In the example below, I want to focus on GOOG, META, and TSLA
You can download the Jupiter Notebook from my Github repository here:
https://github.com/ExcellentBee/Learning-Everyday/blob/main/Stock%20Price%20Comparison%20Interactive%20Charting%20with%20Bokeh.ipynb