Domina el Trazado de Bandas de Bollinger con Python: Guía Completa
Desde la fórmula matemática hasta un dashboard interactivo, sin atajos.
Por Jose Luis Rueda · 14 min lectura · 2026-07-31
Un trader técnico no sobrevive sin herramientas visuales. Las Bandas de Bollinger son esa línea en la arena que separa la volatilidad aceptable del ruido. Si estás aquí, probablemente ya sabes qué son. Pero necesitas llevarlas a código, generar gráficos limpios y automatizar el análisis.
Olvida las explicaciones teóricas de manual. Este artículo te da un recorrido quirúrgico por el cálculo, el trazado con Python y las variantes que usan los profesionales. HolaGPT puede generar el esqueleto del código, pero los detalles finos requieren entender cada paso. Aquí los vas a dominar.
Qué son realmente las Bandas de Bollinger
John Bollinger desarrolló este indicador en los años 80. Combina una media móvil simple (SMA) con dos bandas externas que se ensanchan o estrechan según la volatilidad del precio. La banda superior equivale a SMA más K desviaciones estándar, la inferior a SMA menos K. El valor típico de K es 2, capturando aproximadamente el 95% de las fluctuaciones del precio si los retornos se distribuyen normalmente.
La genialidad no está en la fórmula, sino en su interpretación: el precio tiende a revertir a la media dentro de las bandas. Un cierre fuera de la banda sugiere condiciones de sobrecompra o sobreventa, pero no una señal automática. El verdadero poder llega al combinarlas con patrones de velas, volumen o RSI.
La matemática sin adornos
Para un periodo n (comúnmente 20) y un multiplicador k (2):
- SMA = media de los últimos n precios de cierre
- Desviación estándar poblacional (ddof=0 o 1 según implementación)
- Banda superior = SMA + (k × desviación)
- Banda inferior = SMA - (k × desviación)
Muchos tutoriales usan pandas.DataFrame.rolling().std(ddof=0). Para análisis financiero, la diferencia es mínima. Lo que importa es ser consistente.
Preparación del entorno de trabajo
Vas a usar Python 3.10 o superior. Las bibliotecas esenciales: pandas, numpy, matplotlib y yfinance para datos en tiempo real. Si quieres gráficos interactivos, plotly. Instálalas con:
pip install pandas numpy matplotlib yfinance plotlyUn entorno virtual limpio evita conflictos. Crea uno con python -m venv bollinger_env y actívalo.
Obtención de datos financieros reales
Trabajar con datos fake es como entrenar con pesas de plástico. Conéctate a Yahoo Finance mediante yfinance:
import yfinance as yf
ticker = 'AAPL'
data = yf.download(ticker, start='2023-01-01', end='2024-12-31')
data = data[['Close']].copy()Este código descarga precios de cierre diarios. La columna 'Close' será nuestra serie de trabajo. Siempre maneja los NaN al inicio, aunque yfinance entrega datos limpios. Para índices bursátiles, usa ^GSPC (S&P 500) o ^IXIC (Nasdaq).
Cálculo vectorizado con pandas
No uses bucles for. La belleza de pandas está en sus ventanas rodantes. Definimos periodo=20, multiplicador=2:
window = 20
k = 2
data['SMA'] = data['Close'].rolling(window=window).mean()
data['STD'] = data['Close'].rolling(window=window).std(ddof=0)
data['Upper Band'] = data['SMA'] + k * data['STD']
data['Lower Band'] = data['SMA'] - k * data['STD']ddof=0 usa la desviación estándar poblacional. Algunos traders prefieren ddof=1; la diferencia en un periodo de 20 velas es marginal. La columna 'STD' es opcional si solo quieres las bandas.
Trazado básico con matplotlib
Un gráfico profesional requiere limpieza. Así se crea desde cero:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
fig, ax = plt.subplots(figsize=(14,7))
ax.plot(data.index, data['Close'], label='Precio de cierre', color='black', linewidth=1.5)
ax.plot(data.index, data['SMA'], label='SMA 20', color='orange', linestyle='--', linewidth=1.2)
ax.plot(data.index, data['Upper Band'], label='Banda superior', color='grey', linewidth=0.8)
ax.plot(data.index, data['Lower Band'], label='Banda inferior', color='grey', linewidth=0.8)
ax.fill_between(data.index, data['Lower Band'], data['Upper Band'], alpha=0.1, color='blue')
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=2))
plt.xticks(rotation=45)
ax.legend()
ax.set_title(f'Bandas de Bollinger - {ticker}', fontsize=16)
ax.set_ylabel('Precio (USD)')
plt.tight_layout()
plt.savefig('bollinger_aapl.png', dpi=300)
plt.show()El relleno semitransparente ayuda a visualizar la contracción y expansión de las bandas. Guarda la imagen en alta resolución para informes.
Versión interactiva con Plotly
Para explorar velas y bandas dinámicamente, Plotly es la opción. Agrega un gráfico de velas con las bandas superpuestas:
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Candlestick(x=data.index, open=data['Open'], high=data['High'], low=data['Low'], close=data['Close'], name='Velas'))
fig.add_trace(go.Scatter(x=data.index, y=data['SMA'], line=dict(color='orange', width=1.5), name='SMA 20'))
fig.add_trace(go.Scatter(x=data.index, y=data['Upper Band'], line=dict(color='grey', width=0.8), name='Banda superior'))
fig.add_trace(go.Scatter(x=data.index, y=data['Lower Band'], line=dict(color='grey', width=0.8), fill='tonexty', fillcolor='rgba(0,128,255,0.1)', name='Banda inferior'))
fig.update_layout(title=f'Bandas de Bollinger interactivas - {ticker}', yaxis_title='Precio', xaxis_rangeslider_visible=False)
fig.write_html('bollinger_interactivo.html')El parámetro fill='tonexty' sombrea el área entre la banda inferior y la superior, exactamente lo que necesitas para detectar la volatilidad a simple vista. Exportar a HTML te permite compartir el dashboard sin dependencias.
Ajustes prácticos que marcan la diferencia
El dilema del multiplicador
K=2 captura el 95% de los precios si la distribución es normal, pero los retornos financieros tienen colas gruesas. Prueba con K=2.2 o 2.5 para reducir falsas rupturas. Un backtesting simple te dirá cuál funciona mejor en tu activo. HolaGPT puede generar el script de validación si le especificas los parámetros a evaluar.
El período móvil
Si operas intradía, baja el periodo a 10 o 12. Para swing trading en gráficos semanales, 20 sigue siendo el estándar. La clave está en adaptarlo a la frecuencia que observas, no copiar ciegamente el valor por defecto.
Suavizado exponencial en lugar de SMA
Algunos cuants prefieren una media exponencial (EMA) para dar más peso a los precios recientes. Implementarlo requiere solo cambiar rolling().mean() por ewm(span=20).mean(). Las bandas mantienen la misma lógica pero con una reacción más rápida.
Señales de trading booleanas
No te limites a mirar. Calcula columnas de señal para identificar rupturas y cruces:
data['Above Upper'] = data['Close'] > data['Upper Band']
data['Below Lower'] = data['Close'] < data['Lower Band']
data['Cross SMA up'] = (data['Close'] > data['SMA']) & (data['Close'].shift(1) <= data['SMA'])
data['Cross SMA down'] = (data['Close'] < data['SMA']) & (data['Close'].shift(1) >= data['SMA'])Estas variables booleanas alimentan un sistema de trading automatizado o simplemente filtran puntos en el gráfico:
breakout_up = data[data['Above Upper']]
ax.scatter(breakout_up.index, breakout_up['Close'], color='red', marker='v', s=50, label='Cierre sobre banda')Integrar volumen en esos puntos añade contexto: una ruptura con volumen alto es más relevante que una con volumen anémico.
Optimización y backtesting básico
Ningún indicador funciona de forma aislada. Crea una estrategia de reversión a la media: entra en largo cuando el precio cierra por debajo de la banda inferior y sale cuando cruza la SMA hacia arriba. Calcula retornos acumulados:
data['Signal'] = 0
data.loc[data['Below Lower'], 'Signal'] = 1
data.loc[data['Cross SMA up'], 'Signal'] = -1
data['Position'] = data['Signal'].replace(0, np.nan).ffill().fillna(0)
data['Returns'] = data['Close'].pct_change()
data['Strategy'] = data['Position'].shift(1) * data['Returns']
cumulative = (data['Strategy'] + 1).cumprod()Compara el equity curve de la estrategia con un hold-and-buy del activo. Si el rendimiento ajustado por riesgo no te convence, no es culpa de las bandas: estás usando la dinámica equivocada. El mercado lateral castiga a los seguidores de tendencia; las bandas prosperan ahí.
Integración con APIs profesionales
Si los datos de Yahoo Finance no son suficientes, migra a Alpha Vantage o Polygon.io. La lógica de cálculo es idéntica; solo cambia la fuente. Un ejemplo con Alpha Vantage requiere key gratuita:
import requests
url = f'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=IBM&apikey=TU_KEY'
r = requests.get(url)
# Parsear JSON y convertirlo a DataFrameLa estructura de datos difiere, pero una vez que tengas una columna 'Close', el resto del código se reutiliza. Ese es el poder de separar la lógica financiera de la fuente de datos.
Cuando HolaGPT acelera el proceso
Un prompt bien estructurado en HolaGPT genera todo el esqueleto del código: desde la descarga hasta el gráfico con anotaciones. Pero el copiar y pegar sin criterio es peligroso. Pídele que comente cada paso, que genere pruebas unitarias para los cálculos o que convierta el script en una clase reutilizable. Por ejemplo: "Genera una clase BollingerBands con pandas que acepte dataframe, periodo y k, que calcule bandas y devuelva figura matplotlib con velas japonesas." El resultado es un componente listo para integrar en tu librería de análisis.
La verdadera ventaja no está en lo que te da, sino en cómo refinas el output. No te conformes con el primer intento: itera con HolaGPT para añadir markers en rupturas, sombreado del canal y alertas por consola.
Errores típicos que debes evitar
- Olvidar el ajuste de splits y dividendos: yfinance ajusta automáticamente, pero otras fuentes requieren columna 'Adj Close'.
- Graficar bandas sin filtrar NaN: Las primeras 19 filas no tienen SMA; debes usar
dropna()antes de trazar. - Confundir volatilidad con dirección: Una banda que se estrecha (squeeze) precede a movimientos bruscos, no te dice hacia dónde.
- Interpretar cada toque de banda como señal: Durante tendencias fuertes, el precio puede caminar pegado a la banda superior sin revertir. Combina con ADX para evitar esas trampas.
- Ignorar el timeframe: Calcular bandas en gráficos diarios es estándar; en marcos inferiores a una hora, el ruido hace que las señales pierdan fiabilidad.
Personalización avanzada para dashboards empresariales
Si construyes un panel de trading, encapsula todo en una función que devuelva una figura de Plotly lista para embed:
def plot_bollinger_dashboard(df, ticker, window=20, k=2):
df = df.copy()
df['SMA'] = df['Close'].rolling(window).mean()
df['STD'] = df['Close'].rolling(window).std(ddof=0)
df['Upper'] = df['SMA'] + k*df['STD']
df['Lower'] = df['SMA'] - k*df['STD']
fig = go.Figure()
# agregar trazas...
return figLuego puedes incrustar esta figura en un dashboard de Streamlit o Dash con una línea de código. HolaGPT te ayuda a generar los componentes de interfaz y los callbacks.
De aquí a dónde expandir
Las Bandas de Bollinger son la base. Sobre ellas construyes indicadores compuestos como el %b (dónde está el precio respecto a las bandas) y el BandWidth (ancho relativo). Ambos se calculan en dos líneas y te dan métricas numéricas para alimentar modelos de machine learning. También puedes crear mapas de calor de correlación entre múltiples activos usando sus bandas.
El límite no está en Python ni en las matemáticas. Está en tu capacidad de iterar con herramientas como HolaGPT para convertir ideas en prototipos funcionales en minutos.