Ariticle

Bokeh: An Interactive Data Visualization Library in CodeBook

Author:

Jirapongse Phuriphanvichai
Developer Advocate Developer Advocate

Bokeh Overview

Bokeh is a Python library for creating interactive visualizations for modern web browsers including Jupyter Notebook and Refinitiv CodeBook. It allows users to create ready-to-use appealing plots and charts nearly without much tweaking. 

Bokeh has been around since 2013. It targets modern web browsers to present interactive visualizations rather than static images. Bokeh provides libraries in multiple languages, such as Python, R, Lua, and Julia. These libraries produce JSON data for BokehJS (a Javascript library), which in turn creates interactive visualizations displayed on modern web browsers. Bokeh provides many benefits including:

  • Simple to complex visualizations: Bokeh provides different interfaces that target users of many skill levels. Users can use basic interfaces for quick and straightforward visualizations or use advanced interfaces for more complex and extremely customizable visualizations.
  • Easy to use with Pandas: Bokeh provides the ColumnDataSource class which is a fundamental data structure of Bokeh. Most plots, data tables, etc. will be driven by a ColumnDataSource. Users can also assign a Pandas data frame as a data source to plot charts.
  • Support several output mediums: The output from Bokeh can be displayed on modern web browsers including Jupyter Notebook. The output can also be exported to an HTML file. Moreover, Bokeh can be used to create interactive web applications by running them on the Bokeh server. 

Bokeh provides different levels of interfaces for users to choose from basic plots with very few customizable parameters to advanced plots with full control over their visualizations. Typically, the interfaces are divided into two levels:

  • bokeh.plotting: The intermediate-level interface that is comparable to Matplotlib. The workflow is to create a figure and then enrich this figure with different elements that render data points in the figure.
  • bokeh.models: The low-level interface that provides the maximum flexibility to application developers. This interface provides complete control over how Bokeh plots are assembled, configured, and displayed.

The examples in this article mostly rely on the bokeh.plotting interface. You can refer to the Bokeh Gallery for the list of available charts and examples. 

 

Refinitiv CodeBook

CodeBook is an application in Refinitiv Eikon or Workspace that allows users to access a cloud-hosted development environment for Python scripting, and leverage the Refinitiv APIs to rapidly build and deploy models, apps, and analytics that fit workflow needs.

CodeBook provides many pre-installed Python libraries for developers or data scientists to retrieve data from Refinitiv's platforms, process the data, plot charts, build machine learning models, and much more. 

Bokeh is one of the pre-installed visualization Python libraries in the CodeBook environment. In addition to Bokeh, there are other charting libraries available in CodeBook, such as altair, bqplot, matplotlib, plotly, and seaborn.

This article demonstrates how to use Bokeh to visualize financial data retrieved from Refinitiv APIs.

Sample Usages

The following examples below demonstrate how to use Bokeh to plot several charts to visualize the financial data retrieved from the Eikon Data API. The examples also show how to create layouts to display charts in the notebook cells. 

Please follow the steps below to run the examples.

Prerequisite

The code can be run on Refinitiv Codebook or Jupyter Notebook that has the Bokeh and Eikon Data API libraries installed. You can verify the version of Bokeh installed in Refinitiv Codebook from the Libraries&Extensions.md file. 

Import required libraries

First, the Python libraries, such as Eikon Data API, Bokeh, and utilities, are imported to retrieve the data, process the data, and plot charts.

    	
            

import refinitiv.dataplatform.eikon as ek

from bokeh.plotting import figure, show

from bokeh.io import output_notebook

from bokeh.models import ColumnDataSource, CDSView, BooleanFilter, HoverTool, FactorRange

from bokeh.transform import factor_cmap, cumsum

from bokeh.layouts import row, column, gridplot

from bokeh.models.widgets import Tabs, Panel

import pandas as pd

from math import pi

import datetime

Then, initialize the Eikon Data API with the application key and call the output_notebook() method to configure the default output state to generate output in notebook cells when the show() method is called.

    	
            

ek.set_app_key('DEFAULT_CODE_BOOK_APP_KEY')

output_notebook()

Line Chart

This example shows how to use Bokeh to plot a line chart that displays the daily historical close prices retrieved from the Eikon Data API. 

The get_timeseries method of the Eikon Data API is called to retrieve the daily historical close prices of IBM.N. 

    	
            

df1 = ek.get_timeseries('IBM.N',

                  fields=['CLOSE'],

                  start_date=datetime.timedelta(days=-365), 

                  end_date=datetime.datetime.now(), 

                  interval='daily')

df1

Then, it creates a Bokeh figure and adds a line chart to the figure. It assigns the data frame retrieved from the get_timeseires method as a data source of the line chart to plot the data from the Date and CLOSE columns. It also adds a hover tool to the figure to interactively display the data when the cursor hovers over the line chart. Next, it calls the show method to display the figure.

    	
            

figure1 = figure(title="Daily Close Price (IBM.N)",          

           x_axis_type="datetime",

           x_axis_label='Date')

figure1.line(x='Date', y='CLOSE', source=df1, legend_label="Close")

figure1.add_tools(HoverTool(

    tooltips=[

        ( "Date",  "$x{%F}"            ),

        ( "Price", "$y{"+f"0.00"+" a}" )

    ],

    formatters={

        '$x'      : 'datetime',

    },

))

figure1.legend.location = 'bottom_right'

show(figure1)

Line Chart with Multiple Lines

This example enhances the previous line chart by adding another line that shows the 15-days simple moving averages of the close prices.

It uses the rolling and mean methods to calculate the 15-days simple moving averages of the close prices and creates a new column (SMA_15) in the data frame with the calculated values.

    	
            

df1['SMA_15'] = df1.CLOSE.rolling(15).mean()

df1

Then, it creates a new figure with a line chart that is similar to the previous step and adds another dashed line that represents the data in the SMA_15 column to the figure.

figure2.line(x='Date', y='SMA_15', source=df1, legend_label="SMA 15", line_dash = 'dashed', color="red", name="SMA 15")

Next, it calls the show method to display the figure.

    	
            

figure2 = figure(title="Daily Close Price and SMA (IBM.N)",          

           x_axis_type="datetime",

           x_axis_label='Date')

 

figure2.line(x='Date', y='CLOSE', source=df1, legend_label="Close", name="CLOSE")

figure2.line(x='Date', y='SMA_15', source=df1, legend_label="SMA 15", line_dash = 'dashed', color="red", name="SMA 15")

 

figure2.add_tools(HoverTool(

    tooltips=[

        ( "", "$name"),

        ( "Date",  "$x{%F}"            ),

        ( "Price", "$y{"+f"0.00"+" a}" )

    ],

    formatters={

        '$x'      : 'datetime', 

    },

))

figure2.legend.location = 'bottom_right'

show(figure2)

Candlestick Chart

This example plots a candlestick chart that displays the daily historical open, high, low, and close prices retrieved from the Eikon Data API.

First, it calls the get_timeseries method to retrieve the daily historical OHLC prices of IBM.N.

    	
            

df2 = ek.get_timeseries('IBM.N',                  

                  start_date=datetime.timedelta(days=-90), 

                  end_date=datetime.datetime.now(), 

                  interval='daily')

df2

Then, it creates a new figure that contains segment and vertical bar glyphs. The segment glyphs are used to visualize the low and high prices and the vertical bar glyphs are used to visualize the open and close prices. If the close prices are more than or equal to the open prices, the color of the vertical bar glyphs will be green. Otherwise, the color of the vertical bar glyphs will be red.

It also adds a hover tool to the figure to interactively display the OHLC data when the cursor hovers over the chart. Next, it calls the show method to display the figure.

    	
            

source = ColumnDataSource(data=df2)

hover = HoverTool(

    tooltips=[

        ('', '@Date{%F}'),

        ('O', '@OPEN{"+f"0.00"+" a}'),

        ('H', '@HIGH{"+f"0.00"+" a}'),

        ('L', '@LOW{"+f"0.00"+" a}'),

        ('C', '@CLOSE{"+f"0.00"+" a}'),

        ('V', '@VOLUME{0}'),

    ],

 

    formatters={

        '@Date': 'datetime'

    },

    mode='mouse'

)

inc_b = source.data['CLOSE'] >= source.data['OPEN']

inc = CDSView(source=source, filters=[BooleanFilter(inc_b)])

dec_b = source.data['OPEN'] > source.data['CLOSE']

dec = CDSView(source=source, filters=[BooleanFilter(dec_b)])

w = 12*60*60*1000 

figure3 = figure(title="OHLC Candlestick Chart (IBM.N)",

                 x_axis_type="datetime",

                 sizing_mode="stretch_width",

                 height=400,

                 x_axis_label='Date')

figure3.segment(source=source, x0='Date', x1='Date', y0='HIGH', y1='LOW', color="black")

figure3.vbar(source=source, view=inc, x='Date', width=w, top='OPEN', bottom='CLOSE', fill_color="green", line_color="green")

figure3.vbar(source=source, view=dec, x='Date', width=w, top='OPEN', bottom='CLOSE', fill_color="red", line_color="red")

figure3.add_tools(hover)

 

show(figure3)

Vertical Bar Chart

This example plots a vertical bar chart that shows quarterly historical revenue back to fore years.

First, it calls the get_data method to retrieve the quarterly historical revenue of IBM.N back to four years, and then sort the data by dates in ascending order.

    	
            

quarter = pd.Timestamp(datetime.date.today()).quarter

quarter = quarter + 14

quarter = quarter*-1

df3, err = ek.get_data(

    instruments = ['IBM.N'],

    fields = ['TR.Revenue.Date','TR.Revenue'],

    parameters={'SDate':0,'EDate':quarter,'Period':'FQ0','Frq':'FQ'}

)

df3 = df3[::-1].reset_index().drop('index', axis=1)

df3

Next, it adds the following columns to the data frame.

  • Q: Quarter, e.g., Q1, Q2, Q3, or Q4.
  • Year: Year, e.g., 2021.
  • QY: Quarter and year, e.g., 2021Q1
  • Group: Tuples of 'Year' and 'Q', e.g., (2021, Q2)

These columns are used by Bokeh to plot the nested verticle bar chart.

    	
            

df3['Date'] = pd.to_datetime(df3['Date'], format='%Y-%m-%d')

df3['Q'] = ('Q' + df3['Date'].dt.quarter.astype(str))

df3['Year'] = df3['Date'].dt.to_period("Y").astype(str)

df3['QY'] = df3['Date'].dt.to_period("Q").astype(str)

df3['Group'] = df3[['Year', 'Q']].apply(lambda x: (x[0],str(x[1])), axis=1)

df3

Next, it creates a new figure and then adds the vertical chart to the figure. It uses the Group column in the data frame as the x-coordinates of the vertical bar to create the nested vertical bar chart.

It also adds a hover tool to the figure to interactively display the revenue when the cursor hovers over the chart. Next, it calls the show method to display the figure.

    	
            

palette = ['#0000ff', '#00ff00', '#ffff00', '#00ffff']

years = ['Q1','Q2','Q3','Q4']

figure4 = figure(

    x_range=FactorRange(*list(df3["Group"])),

    title="IBM.N Revenue",

    width=800

)

figure4.vbar(

    x="Group",

    top="Revenue",

    width=0.9,

    source=df3,

    fill_color=factor_cmap('Group', palette=palette, factors=years, start=1, end=3)

)

figure4.add_tools(HoverTool(

    tooltips=[

        ('', '@QY'),

        ('', '@Revenue{0.00 a}')

    ],

    mode='mouse'

))

figure4.left[0].formatter.use_scientific = False

show(figure4)

Pie Chart

This example plots a pie chart that shows the weight percentage of the constituents in the Dow Jones Industrial Average Index.

First, it calls the get_data method to retrieve the constituents and the weight percentage of the constituents in the Dow Jones Industrial Average Index. Next, it renames the column names so they can be easily referred to by Bokeh.

    	
            

df4, err = ek.get_data('0#.DJI', ['TR.IndexConstituentWeightPercent','TR.CommonName'])

df4 = df4.rename(columns={"Weight percent": "Value", "Company Common Name":"Name"})

df4

Then, it adds the following columns to the data frame.

  • angle: The angle of each sector in the pie chart. It is calculated from the weight percentages.
  • color: The color of each sector in the pie chart

These columns are used by Bokeh to plot the pie chart.

    	
            

df4['angle'] = df4['Value']/df4['Value'].sum() * 2*pi

df4['color']= ['#1f77b4', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c', '#98df8a', '#d62728', '#ff9896', '#9467bd', '#c5b0d5',

    '#8c564b', '#c49c94', '#e377c2', '#f7b6d2', '#7f7f7f', '#c7c7c7', '#bcbd22', '#dbdb8d', '#17becf', '#9edae5',

     '#0000ff', '#ff0000', '#ffff00', '#00ffff', '#ff00ff', '#F0F8FF', '#006B3C', '#00FF6F', '#392972', '#8F00FF']

df4

Next, it creates a new figure and then add the pie chart to the figure. It uses the angle and color columns in the dataframe to determine the angles and colors used in the pie chart.

    	
            

figure5 = figure(plot_height=800,plot_width=800, title="Dow Jones Industrials Constituents Weightings (.DJI)", toolbar_location=None,

           tools="hover",tooltips="@Name (@Instrument): @Value", x_range=(-0.5, 1.0))

figure5.wedge(x=0, y=1, radius=0.4,

        start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),

        line_color="white",fill_color='color', legend_field='Instrument', source=df4)

figure5.axis.axis_label=None

figure5.axis.visible=False

figure5.grid.grid_line_color = None

 

show(figure5)

Row and Column Layout

This example uses the row and column layout in Bokeh to arrange and display charts. The column() method is used to display charts vertically while the row() method is used to display charts horizontally.

It displays figure1, figure2, and figure3 in the following layout.

    	
            

row_layout = column(row(children=[figure1,figure2]), figure3)

show(row_layout)

Grid Layout

This example uses the gridplot() method to arrange Bokeh plots in a grid.

It displays figure1, figure2, figure3, and figure4 in the following layout.

    	
            

grid_layout = gridplot([[figure1, figure2], [figure3, figure4]], plot_width=500, plot_height=500)

show(grid_layout)

Panel and Tabs

This example uses the Panel() and Tabs() methods to arrange charts in a tabbed layout. It creates two tabs. The first tab contains figure1, figure2, figure3, and figure4 in the grid layout and the second tab contains figure5.

    	
            

panel1 = Panel(child=grid_layout, title='IBM.N')

panel2 = Panel(child=figure5, title='DJI')

tabs_object = Tabs(tabs = [panel1, panel2])

show(tabs_object)

Summary

Bokeh is a Python library for creating interactive visualizations for modern web browsers including Jupyter Notebook. This library is available in Refinitiv CodeBook. Therefore, developers or data scientists can use this library to visualize financial data retrieved from Refinitiv's APIs.

This article provides several examples that demonstrate how to use Bokeh in Refinitiv CodeBook to plot charts from the data frames returned from the Eikon Data API. Moreover, it also shows how to arrange charts with the Bokeh row, column, grid, and tabbed layouts.

References

  1. Cochran, S., 2019. 6 Reasons I Love Bokeh for Data Exploration with Python. [online] towardsdatascience. Available at: https://towardsdatascience.com/6-reasons-i-love-bokeh-for-data-exploration-with-python-a778a2086a95 [Accessed 18 August 2021].
  2. Dobler, M. and Großmann, T., 2020. Data Visualization Workshop. 1st ed. [S.l.]: Packt Publishing.
  3. Developers.refinitiv.com. n.d. Eikon Data API | Refinitiv Developers. [online] Available at: https://developers.refinitiv.com/en/api-catalog/eikon/eikon-data-api [Accessed 18 August 2021].
  4. Stack Overflow. 2020. How to get Bokeh hovertool working for candlesticks chart?. [online] Available at: https://stackoverflow.com/questions/61175554/how-to-get-bokeh-hovertool-working-for-candlesticks-chart [Accessed 18 August 2021].
  5. Jolly, K., 2018. Hands-on data visualization with Bokeh. 1st ed. Packt Publishing.
  6. Ray, S., 2015. Interactive Data Visualization using Bokeh (in Python). [online] Analytics Vidhya. Available at: https://www.analyticsvidhya.com/blog/2015/08/interactive-data-visualization-library-python-bokeh/ [Accessed 18 August 2021].
  7. Refinitiv.com. n.d. Refinitiv CodeBook. [online] Available at: https://www.refinitiv.com/en/products/codebook [Accessed 18 August 2021].
  8. Ven, B., 2021. Bokeh. [online] Bokeh.org. Available at: https://bokeh.org/ [Accessed 18 August 2021].
  9. Docs.bokeh.org. n.d. Gallery - Bokeh 1.4.0 documentation. [online] Available at: https://docs.bokeh.org/en/1.4.0/docs/gallery.html [Accessed 18 August 2021].