¿Cómo Crear un Filtro de Kalman en Python?

0
546
Filtro de Kalman en Python

El Filtro de Kalman es un algoritmo matemático utilizado para estimar y prever las tendencias subyacentes o los valores de variables financieras basándose en los datos observados del mercado. Ayuda a filtrar el ruido y proporciona estimaciones más precisas de los precios de los activos, rendimientos, volatilidad y otras métricas financieras. Es algo que este filtro intenta lograr.

En este artículo vamos a mostrar cómo calcular y trazar el filtro de Kalman en un gráfico de precios de un activo financiero usando un código de Python.

¿Qué es el Filtro de Kalman?

Una de las aplicaciones más destacadas del Filtro de Kalman en el trading es su capacidad para suavizar los datos de precios, de manera similar a la Media Móvil (MA). Las medias móviles son herramientas de análisis técnico utilizadas por los traders para identificar tendencias y posibles oportunidades de trading. Sin embargo, las medias móviles tienen limitaciones, especialmente la necesidad de elegir una longitud de ventana adecuada, lo que puede generar preocupaciones sobre el sobreajuste.

El Filtro de Kalman ofrece una solución elegante al proporcionar un enfoque dinámico y basado en datos para filtrar y suavizar los precios de las acciones. Elimina la necesidad de una longitud de ventana fija, reduciendo las preocupaciones sobre el sobreajuste y ofreciendo una herramienta más robusta para los traders.

No entraremos en detalle sobre cómo calcularlo matemáticamente, ya que es un proceso largo que implica muchas fórmulas. En este caso, usaremos una biblioteca de Python diseñada para realizar análisis de este tipo. En un artículo posterior hablaremos en mayor detalle del filtro de Kalman y los cálculos que hay detrás.

Código para el cálculo del Filtro de Kalman en Python

Para el cálculo del Filtro de Kalman vamos a usar una herramienta de Python llamada pykalman, una librería desarrollada para el cálculo rápido del filtro y el suavizado de Kalman sin la necesidad de tener conocimientos profundos sobre las matemáticas que están detrás de este concepto. 

Por supuesto, también es posible programar el filtro de Kalman desde cero en Python y otros lenguajes, pero para esto el programador debe tener experiencia y conocimientos de las matemáticas involucradas, lo que puede alargar el proceso y hacer el código más complicado de lo necesario. Y como aquí nuestro objetivo no es convertirnos en programadores expertos, sino desarrollar herramientas de análisis lo más sencillas posibles, vamos a crear el código usando pykalman.

Sin embargo, siempre es recomendable que el usuario conozca las bases teóricas de una herramienta como el filtro de Kalman para comprender sus señales y que hace y que no hace realmente.

Ahora veamos el código.

import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt
from pykalman import KalmanFilter
from matplotlib.dates import DateFormatter

# Configuración de estilo
plt.style.use('ggplot') # Puedes cambiarlo por otro estilo si prefieres

# Descargar datos históricos de Bitcoin
btc = yf.download('BTC-USD', period='6mo', interval='1d') # Datos de los últimos 6 meses

# Preparar los datos
closing_prices = btc['Close'].values.reshape(-1, 1) # Precios de cierre
dates = btc.index # Fechas correspondientes

# Configurar el filtro de Kalman
kf = KalmanFilter(
transition_matrices=1, # Modelo de caminata aleatoria
observation_matrices=1, # Relación entre estado y medición
initial_state_mean=closing_prices[0], # Valor inicial
initial_state_covariance=1, # Incertidumbre inicial
observation_covariance=1, # Aumentamos el ruido de medición
transition_covariance=0.1 # Aumentamos el ruido del proceso
)

# Aplicar el filtro de Kalman
state_means, state_covariances = kf.filter(closing_prices)

# Calcular la desviación estándar para las bandas de confianza
std = np.sqrt(state_covariances[:, 0, 0])

# Ajustar el multiplicador de las bandas para que sean visibles
multiplier = 3 # Puedes ajustar este valor para hacer las bandas más anchas o estrechas

# Crear la figura y el gráfico
fig, ax = plt.subplots(figsize=(14, 7))

# Graficar el precio real de Bitcoin
ax.plot(dates, closing_prices, label='Precio Real', color='#2C5F8A', alpha=0.9)

# Graficar el filtro de Kalman
ax.plot(dates, state_means, label='Filtro de Kalman', color='#E14658', linewidth=2.5)

# Añadir bandas de confianza (ajustadas para que sean visibles)
ax.fill_between(dates,
state_means[:, 0] - multiplier * std,
state_means[:, 0] + multiplier * std,
color='#E14658', alpha=0.2, label=f'Banda de confianza ({multiplier}σ)')

# Personalizar el gráfico
ax.set_title('Análisis de Bitcoin con Filtro de Kalman', fontsize=16, pad=15)
ax.set_xlabel('Fecha', fontsize=12)
ax.set_ylabel('Precio (USD)', fontsize=12)
ax.legend(loc='upper left', frameon=True)

# Formatear las fechas en el eje X
ax.xaxis.set_major_formatter(DateFormatter("%d-%b")) # Formato: día-mes
plt.xticks(rotation=45) # Rotar las etiquetas para mejor legibilidad

# Ajustar el layout y mostrar el gráfico
plt.tight_layout()
plt.show()

Cuando se corre el código, se obtiene la siguiente imagen con el precio de BTC y el filtro de Kalman:

Filtro de Kalman en Python

Filtro de Kalman de Bitcoin en Python

Explicación del código

Ahora vamos a desglosar el código paso a paso:

Importación de librerías

import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt
from pykalman import KalmanFilter
from matplotlib.dates import DateFormatter
  • yfinance: Para descargar datos financieros (en este caso, de Bitcoin) de Yahoo Finance.
  • numpy: Para operaciones matemáticas y manejo de arrays.
  • matplotlib.pyplot: Una biblioteca diseñada para crear gráficos.
  • pykalman.KalmanFilter: Como ya indicamos, sirve para implementar el filtro de Kalman.
  • matplotlib.dates.DateFormatter: Para formatear las fechas en el gráfico.

Configuración del estilo del gráfico

plt.style.use('ggplot')
  • plt.style.use(‘ggplot’): Define el estilo visual del gráfico. En este caso, usamos el estilo ‘ggplot’, que es similar a los gráficos de R. Puedes cambiarlo por otros estilos como ‘seaborn’, ‘dark_background’, o ‘fivethirtyeight’.

Descarga de datos

btc = yf.download('BTC-USD', period='6mo', interval='1d')
  • yf.download: Descarga los datos históricos de Bitcoin.
    • ‘BTC-USD’: El ticker de Bitcoin en Yahoo Finance.
    • period=’6mo’: Descarga datos de los últimos 6 meses.
    • interval=’1d’: Intervalo de tiempo diario (también puede ser ‘1h’, ‘1wk’, etc.).

Podemos cambiar el activo por cualquier otro. Por ejemplo, podríamos cambiar “BTC–USD” por “APPL” para usar los datos de precios de Apple.

-Preparación de los datos

closing_prices = btc['Close'].values.reshape(-1, 1)
dates = btc.index
  • btc[‘Close’].values: Extrae los precios de cierre como un array de NumPy.
  • .reshape(-1, 1): Reformatea el array para que sea una matriz de una sola columna (necesario para el filtro de Kalman).
  • dates = btc.index: Extrae las fechas correspondientes a los precios.

Configuración del filtro de Kalman

kf = KalmanFilter(
    transition_matrices=1,
    observation_matrices=1,
    initial_state_mean=closing_prices[0],
    initial_state_covariance=1,
    observation_covariance=1,
    transition_covariance=0.1
)
  • transition_matrices=1: Define cómo evoluciona el estado (en este caso, un modelo de caminata aleatoria).
  • observation_matrices=1: Define cómo se relaciona el estado con las mediciones.
  • initial_state_mean=closing_prices[0]: Valor inicial del filtro (el primer precio de cierre).
  • initial_state_covariance=1: Incertidumbre inicial del estado.
  • observation_covariance=1: Ruido de medición (ajusta la sensibilidad del filtro a los datos).
  • transition_covariance=0.1: Ruido del proceso (controla la suavidad del filtro).

-Aplicación del filtro de Kalman

state_means, state_covariances = kf.filter(closing_prices)
  • kf.filter(closing_prices): Aplica el filtro de Kalman a los precios de cierre.
    • state_means: Los valores suavizados (estimados) del precio.
    • state_covariances: La incertidumbre asociada a cada estimación.

Cálculo de la desviación estándar

std = np.sqrt(state_covariances[:, 0, 0])

  • state_covariances[:, 0, 0]: Extrae las varianzas del estado (son matrices 1×1).
  • np.sqrt: Calcula la desviación estándar a partir de las varianzas.

Creación del gráfico

fig, ax = plt.subplots(figsize=(14, 7))
  • plt.subplots: Crea una figura y un conjunto de ejes.
    • figsize=(14, 7): Define el tamaño del gráfico (ancho, alto).

Graficar el precio real y el filtro de Kalman

ax.plot(dates, closing_prices, label='Precio Real', color='#2C5F8A', alpha=0.9)
ax.plot(dates, state_means, label='Filtro de Kalman', color='#E14658', linewidth=2.5)
  • ax.plot: Dibuja una línea en el gráfico.
    • dates: Eje X (fechas).
    • closing_prices: Eje Y (precios reales).
    • state_means: Eje Y (valores suavizados por el filtro de Kalman).
    • label: Etiqueta para la leyenda.
    • color: Color de la línea.
    • alpha: Transparencia de la línea.

Añadir bandas de confianza

ax.fill_between(dates, 
                state_means[:, 0] - multiplier * std, 
                state_means[:, 0] + multiplier * std, 
                color='#E14658', alpha=0.2, label=f'Banda de confianza ({multiplier}σ)')
  • ax.plot: Dibuja una línea en el gráfico.
    • dates: Eje X (fechas).
    • closing_prices: Eje Y (precios reales).
    • state_means: Eje Y (valores suavizados por el filtro de Kalman).
    • label: Etiqueta para la leyenda.
    • color: Color de la línea.
    • alpha: Transparencia de la línea.

Personalización del gráfico

ax.set_title('Análisis de Bitcoin con Filtro de Kalman', fontsize=16, pad=15)
ax.set_xlabel('Fecha', fontsize=12)
ax.set_ylabel('Precio (USD)', fontsize=12)
ax.legend(loc='upper left', frameon=True)
  • ax.set_title: Título del gráfico.
  • ax.set_xlabel: Etiqueta del eje X.
  • ax.set_ylabel: Etiqueta del eje Y.
  • ax.legend: Muestra la leyenda.
    • loc=’upper left’: Posición de la leyenda.
    • frameon=True: Dibuja un marco alrededor de la leyenda.

Formatear las fechas

ax.xaxis.set_major_formatter(DateFormatter("%d-%b"))
plt.xticks(rotation=45)
  • DateFormatter(“%d-%b”): Formatea las fechas como “día-mes” (por ejemplo, “15-Oct”).
  • plt.xticks(rotation=45): Rota las etiquetas del eje X para mejor legibilidad.

Mostrar el gráfico

plt.tight_layout()
plt.show()
  • plt.tight_layout(): Ajusta el layout para evitar superposiciones.
  • plt.show(): Muestra el gráfico en una ventana.

Resumen del flujo del código:

  1. Descarga los datos de Bitcoin.
  2. Prepara los datos para el filtro de Kalman.
  3. Configura y aplica el filtro de Kalman.
  4. Calcula las bandas de confianza.
  5. Crea y personaliza el gráfico.
  6. Muestra el gráfico.

 

Pueden acceder a más herramientas de trading para Python en la siguiente sección: Recursos de trading de Python


 

TagsPython
Raul Canessa

Leave a reply