
En nuestros tutoriales anteriores de Bokeh, vimos cómo dar tus primeros pasos con Bokeh y crear gráficos básicos de dispersión y líneas. Además de sus amplias posibilidades de visualización de datos, Bokeh también permite alojar apps en sus servidores habilitando la conexión entre Python y el navegador.
Empezaremos creando la app y ejecutándola en los servidores de Bokeh para compartirla con tu equipo. Para saber más sobre cómo funciona el servidor de Bokeh, consulta la documentación de Bokeh.
Conceptos básicos del servidor de Bokeh
Bokeh convierte objetos (como gráficos, widgets, ejes y prácticamente todo lo que creas) a formato JSON.
El servidor de Bokeh convierte el código Python que escribes en un documento JSON. Ese documento se renderiza en JavaScript mediante la librería cliente de Bokeh (BokehJS) para que los usuarios vean la aplicación en el navegador.
La ventaja de Bokeh es que se encarga de la parte de JavaScript. ¡Así que no necesitas saber JavaScript para crear una app! La siguiente imagen resume cómo funciona el servidor de Bokeh.

Fuente: The Bokeh Server
Cómo crear y ejecutar una aplicación Bokeh
La estructura general de una aplicación Bokeh es:
- Crear gráficos y widgets: es el primer paso para construir una aplicación Bokeh. Define de antemano qué gráfico(s) quieres mostrar.
- Definir funciones de callback: una función de callback indica a la aplicación cómo responder a la interacción del usuario. Por ejemplo, si seleccionas un ticker distinto en un gráfico temporal, el gráfico debería actualizarse con los nuevos datos.
- Crear layouts: los layouts nos ayudan a presentar los gráficos de forma eficaz y atractiva.
Crear una app web de análisis bursátil con Bokeh
Descripción del proyecto
En esta sección, verás cómo crear una app web sencilla y desplegarla para que la usen analistas financieros.
Imagina que trabajas en Big Money Inc, una gestora de activos líder. Tu manager ha oído a tus compañeras y compañeros elogiar tus habilidades con Python. Ahora quiere que crees una app bursátil para que los analistas financieros de la empresa comparen dos acciones. Cree que podrán ahorrar tiempo comparando rápidamente cualquier acción con otra similar del mismo sector. Por ejemplo, pueden comparar Apple con Microsoft y elegir la mejor para construir carteras de clientes. La comparación debe incluir métricas básicas como:
- Gráficos de la evolución del precio de cierre
- Correlación
- Media (rentabilidad esperada)
- Desviación estándar (riesgo esperado)
Debe existir una forma de personalizar el periodo de análisis de forma interactiva. Por ejemplo, poder comparar el rendimiento de dos acciones en la última semana, mes, año o cualquier periodo deseado. Además, la app debe estar disponible para todo el personal de la empresa. Esto implica desplegarla en la nube.
Requisitos previos
- Conocimientos básicos de Bokeh.
- Cierto nivel de Python.
- Tener instalados los paquetes indicados en nuestro tutorial de introducción a Bokeh.
Visión general de la app web bursátil
La app web da respuesta al caso práctico anterior. Permite seleccionar dos tickers y visualizar estadísticas descriptivas (como media y desviación estándar) de precios y rendimientos, gráficos de correlación y gráficos de tendencias de precio para las acciones elegidas. La interactividad se consigue permitiendo combinar distintos tickers y distintos periodos (en los gráficos de precio). La app web tendrá este aspecto:

Crear el proyecto Bokeh de la app bursátil
1. Crea una carpeta de proyecto y llámala SelectStock.
2. Abre la carpeta del proyecto y crea un archivo llamado main.py.
3. Guarda una copia de los datos del mercado bursátil en la carpeta del proyecto como "all_stocks_5yr.csv".
Guarda una copia de los tickers. El archivo ticker.py contiene la lista de tickers. Solo incluimos 505 tickers, porque meter la lista completa en el script main.py haría el código poco manejable. Es mejor guardar la lista en un archivo separado y llamarla cuando haga falta.
Abre el archivo main.py en tu editor favorito, como Spyder, atom o Sublime Text.
Importar paquetes
Escribe el siguiente código en main.py. Importa los paquetes y los tickers necesarios para crear la app web:
# Import the required packages
import pandas as pd
from functools import lru_cache
from bokeh.io import curdoc
from bokeh.layouts import column, row
from bokeh.models import ColumnDataSource, PreText, Select, Div
from bokeh.plotting import figure
# load the list of tickers
import tickers
tickers = tickers.tickers
Leer y cargar datos
Escribe una función para evitar comparar un ticker consigo mismo:
# Create a function to ensure that a ticker is not compared to itself
def foo(val, lst):
return [x for x in lst if x != val]
Add the following code to read and load data for the webapp:
# A function to read and load data
# Note the use of @lru_cache() decorator is to cache the data and speed up reloads
@lru_cache()
def load_ticker(ticker):
data = pd.read_csv('all_stocks_5yr.csv', parse_dates=['date'])
data = data.set_index('date')
data = data[data['Name'] == ticker]
return pd.DataFrame({ticker: data.close, ticker+'_returns': data.close.diff()})
# A function to create a dataframe for the selected tickers
@lru_cache()
def get_data(t1, t2):
df1 = load_ticker(t1)
df2 = load_ticker(t2)
data = pd.concat([df1, df2], axis=1)
data = data.dropna()
data['t1'] = data[t1]
data['t2'] = data[t2]
data['t1_returns'] = data[t1+'_returns']
data['t2_returns'] = data[t2+'_returns']
return data
# Put data into a ColumnDataSource
source = ColumnDataSource(
data=dict(date=[], t1=[], t2=[], t1_returns=[], t2_returns=[]))
Crear widgets
# set up widgets
stats = PreText(text='', width=500)
ticker1 = Select(value='AAPL', options=foo('GOOG', tickers))
ticker2 = Select(value='GOOG', options=foo('AAPL', tickers))
Los widgets permiten al usuario seleccionar el primer y el segundo ticker para la comparación. Una vez seleccionados, Bokeh puede crear los gráficos.
Crear gráficos
# set up plots
tools = 'pan,wheel_zoom,xbox_select,reset'
corr = figure(width=400, height=350,
tools='pan,wheel_zoom,box_select,reset', output_backend='webgl')
corr.diamond('t1_returns', 't2_returns', size=2, source=source, color="red",
selection_color="orange", alpha=0.6, nonselection_alpha=0.1, selection_alpha=0.4)
time_series1 = figure(width=900, height=200, tools=tools,
x_axis_type='datetime', active_drag="xbox_select", output_backend='webgl')
time_series1.line('date', 't1', source=source, color='orange')
time_series2 = figure(width=900, height=200, tools=tools,
x_axis_type='datetime', active_drag="xbox_select", output_backend='webgl')
time_series2.x_range = time_series1.x_range
time_series2.line('date', 't2', source=source, color='green')
En este código, primero definimos las herramientas que acompañarán a los gráficos. El primer gráfico es el de correlación, con la función figure() especificando width = 400 y height = 350. El gráfico de correlación utiliza marcadores en forma de rombo.
Usamos el glyph line para crear las series temporales de los tickers. Igualamos el rango de ambas series para poder compararlas correctamente.
# Define callbacks
def change_ticker1(attrname, old, new):
ticker2.options = foo(new, tickers)
update()
def change_ticker2(attrname, old, new):
ticker1.options = foo(new, tickers)
update()
def update(selected=None):
t1, t2 = ticker1.value, ticker2.value
df = get_data(t1, t2)
data = df[['t1', 't2', 't1_returns', 't2_returns']]
source.data = data
update_stats(df, t1, t2)
corr.title.text = '%s returns vs. %s returns' % (t1, t2)
time_series1.title.text, time_series2.title.text = t1, t2
def update_stats(data, t1, t2):
stats.text = str(data[[t1, t2, t1+'_returns', t2+'_returns']].describe())
ticker1.on_change('value', change_ticker1)
ticker2.on_change('value', change_ticker2)
def selection_change(attrname, old, new):
t1, t2 = ticker1.value, ticker2.value
data = get_data(t1, t2)
selected = source.selected.indices
if selected:
data = data.iloc[selected, :]
update_stats(data, t1, t2)
source.selected.on_change('indices', selection_change)
En la sección de callbacks, las dos primeras funciones definen las devoluciones de llamada de los tickers 1 y 2, respectivamente.
La función update() actualiza los gráficos cuando el usuario selecciona una combinación distinta de tickers; update_stats() actualiza las estadísticas al cambiar los tickers; y selection_change() actualiza toda la app cuando el usuario selecciona datos.
Configurar el layout
Primero, añade a la app un título que indique al usuario cómo interactuar con ella. La función Div te permite introducir el texto y definir el alto y el ancho, además de otras personalizaciones.
# set up layout
# Add a title message to the app
div = Div(
text="""
<p>Select two Stocks to compare key Statistics:</p>
""",
width=900,
height=30,
)
# Create layouts
app_title = div
widgets = column(ticker1, ticker2, stats)
main_row = row(widgets, corr)
series = column(time_series1, time_series2)
layout = column(app_title, main_row, series)
El layout combina las funciones column y row.
Primero, se coloca el título arriba. Debajo va la fila principal (con las estadísticas descriptivas y el gráfico de correlación). A continuación, una columna con la primera serie temporal (para el ticker 1) y, por último, la serie temporal para el segundo ticker.
Inicializar la app
Este paso inicializa la app web cuando se ejecuta en el servidor.
# initialize the app
update()
curdoc().add_root(layout)
curdoc().title = "Compare Stocks"
Desplegar la app web
Para probar tu app web, puedes desplegarla en tu máquina local. Abre Anaconda Prompt o la terminal que prefieras. Muévete al directorio que contiene la carpeta del proyecto "SelectStock". Puedes hacerlo escribiendo:
cd "System path to where the SelectStock folder is contained"
Por ejemplo: cd "C:\\Users\\... \\SelectStock"
Escribe el siguiente comando para ejecutar la app web:
bokeh serve --show SelectStock
También puedes ir a la carpeta SelectStock y ejecutar el archivo main.py:
Bokeh serve --show main.py
Esto abrirá la app web en el navegador predeterminado en:
http://localhost:5006/SelectStock o
Estás usando Bokeh Server para ejecutar y desplegar tu app web.
También puedes desplegar la app web con servicios como Heroku.
Conclusión
En este tutorial has aprendido los fundamentos para crear y desplegar tus propias aplicaciones Bokeh en tu máquina local. Te mostramos cómo juntar todo lo aprendido para construir una app práctica, divertida e interactiva que encantará a las personas usuarias.
La forma más rápida de afianzar tus habilidades de programación es crear proyectos como este después de aprender un concepto o herramienta. Este enfoque práctico garantiza que entiendes bien la herramienta o habilidad y te permite enseñar a posibles empleadores en qué has estado trabajando.
Si quieres profundizar en Bokeh, puedes leer este libro. O, mejor aún, prueba el curso de DataCamp Interactive Visualization with Bokeh. Encontrarás más detalles sobre Bokeh y cómo crear gráficos avanzados. Incluso puedes aprender a construir tus propias apps web con Bokeh usando datos en tiempo real.
