Hablemos de pautas estacionales y dónde encontrarlas

Oct 24, 2023 | General

Grandes estudiosos del mercado, hablan sobre el comportamiento cíclico de los mercados de valores, y por eso considero importante dar una lectura a la estacionalidad de algunos activos, hoy quiero mostrarles cómo identificar pautas estacionales con python.

Pero antes de empezar, ¿Qué es una pauta estacional? José Martínez, en un artículo para www.traders-mag.es en Diciembre 2016, titulado “Las pautas estacionales: Un comportamiento cíclico” Define la pauta estacional como “comportamiento bursátil de algunos subyacentes, dentro de un marco temporal concreto”.

Partiendo de esta definición es fácil imaginar que los Commodities como soya, trigo y maíz o gas natural y petróleo, tienen un comportamiento bursátil que responde a las condiciones climáticas que afecten los procesos productivos de los mismos.

¿El resto de activos financieros responde a pautas estacionales? Bueno, citando nuevamente a José Martínez, “La pauta estacional no hace referencia únicamente a las estaciones del año sino también a comportamientos excepcionales de la bolsa frente a un dato concreto, bien sea semanal, mensual, anual, etc.. Como por ejemplo el comportamiento de determinadas acciones, dentro de la publicación de algún dato regular como puede ser el dato de empleo, stocks, consumo, etc”. Y esto amigos míos, es lo que quiero que observemos, si aún no está convencido sobre porque ponerle un ojito a las pautas estacionales, lo invito a leer el artículo “Is Seasonality Is The Best Investment Strategy?” de Dimitri Speck (Spoiler Alert!!!), en su artículo Dimitri Speck muestra los resultados de un estudio de más de 200 años donde ¡La estacionalidad supera a todas las demás estrategias!

QM blog pautas estacionales donde encontrarlas 01

Seasonality beats all other strategies!
Sources: Guido Baltussen, Laurens Swinkels, Pim van Vliet Illustration: Seasonax.

Atención: La idea no es que abandone el resto de las estrategias, la intención es ponerle un ojito a la estacionalidad y bien lo dice Dimitri Speck “piensa por ti mismo en lugar de seguir a la manada. ¡Ten en cuenta la estacionalidad!”, existe toda una serie de documentación con respecto a la estacionalidad y si desea realizar una revisión no está de más que detalle documentación como la que aparece en el Stock Trader’s Almanac de Jeffrey A. Hirsch o paginas como https://charts.equityclock.com/

“Piensa por ti mismo en lugar de seguir a la manada ¡ten en cuenta la estacionalidad!”

DIMITRI SPECK.

Estudio con Cuartiles y Diagrama de Bigotes y Cajas

¿Qué son los Cuartiles? y ¿Que es un Diagrama de Bigotes y Cajas?

En estadística, dada una distribución de datos estadísticos, los cuartiles son aquellos valores que la dividen en cuartos. El primer cuartil o cuartil inferior es aquel valor de la variable tal que la cuarta parte (25%) de las observaciones son inferiores o iguales a él, y el resto (75%) es superior o igual. El segundo cuartil es la mediana, ya que se trata del valor localizado en la mitad de la distribución. Finalmente, el tercer cuartil o cuartil superior es un valor tal que las tres cuartas partes de las observaciones son inferiores o iguales a él. Coinciden con los percentiles 25, 50 y 75 respectivamente.

Mientras que el Diagrama de bigotes y cajas es un método estandarizado para representar gráficamente una serie de datos numéricos a través de sus cuartiles. De esta manera, el diagrama de caja muestra a simple vista la mediana y los cuartiles de los datos.

QM blog pautas estacionales donde encontrarlas 02

Componentes del diagrama de caja. Fuente: https://es.wikipedia.org/wiki/Diagrama_de_caja

Manos a la Obra

Tomaremos una serie de datos del contrato del Maíz, para determinar su estacionalidad a través del uso de cuartiles y el diagrama de bigotes y cajas. Y nos fijaremos en el comportamiento de los retornos observando el diagrama, ejecutamos el siguiente código:

#Import necesary libraries
from datetime import date
import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt 
import seaborn as sns
import yfinance as yf


%matplotlib inline
plt.rcParams["figure.figsize"] = (12, 6)
sns.set()

#Descarga de Datos y Grafico de Quartiles Mensuales (incrementos mensuales medios por años)

start_date ='2010-01-01'
today = date.today()
end_date = today.strftime("%Y-%m-%d")
data = yf.download("ZC=F", start=start_date, end=end_date)
data.drop(['Open', 'Low', 'High', 'Volume', 'Close'], axis=1)

returns = np.log(data["Adj Close"]).diff().dropna().to_frame("Returns")
Monthly_Returns = returns.groupby([returns.index.year.rename('year'), 
                                   returns.index.month.rename('month')]).mean()
Monthly_Returns.boxplot(column='Returns', by='month');
QM blog pautas estacionales donde encontrarlas 03

Bueno como podemos observar, para los meses de Junio (6), Julio (7) y Septiembre (9) tienen a tener grandes variaciones, ahora prestemos atención a lo siguiente la mediana demuestra que de haber invertido en Julio hasta Septiembre habríamos obtenidos retornos positivos, o bien de Noviembre a Diciembre, a excepción de un caso en Diciembre donde el retorno es inferior a la mediana de Noviembre, algo similar ocurre de Marzo a Abril, este es un primer vistazo.

También podemos observar la variación del Maíz por día en todos estos años bajo estudio, veamos como:

def boxplot_group_day(returns_slice):
    Daily_Returns = returns_slice.groupby([returns_slice.index.isocalendar().week.rename('week'), 
                                 returns_slice.index.dayofweek.rename('day')]).mean()
    return Daily_Returns.boxplot(column='Returns', by='day')

boxplot_group_day(returns);
QM blog pautas estacionales donde encontrarlas 04

No se observan grandes variaciones para este caso, los retornos tienden a mantenerse cercanos a 0 salvo algunos puntos atípicos. Y ¿qué tal si ahora observamos la variación de los retornos para un mes en específico?

Vamos:

returns_of_june = returns.loc[returns.index.month.isin([6])]
boxplot_group_day(returns_of_june);
QM blog pautas estacionales donde encontrarlas 05

Qué curioso pareciera que para el mes de Junio (6), si invertimos un lunes (0) y cerramos la operación un Martes (1) o Miércoles (2), obtendríamos retornos positivos. Ahora veamos el comportamiento para otro mes, que tal Diciembre (12).

returns_of_december = returns.loc[returns.index.month.isin([12])]
boxplot_group_day(returns_of_december);
QM blog pautas estacionales donde encontrarlas 06

Interesante, para diciembre no se obtienen mayores variaciones, aunque quizás exista una ventaja estadística operando de Miércoles a Viernes.

Pareciera que se podrían extraer algunas estrategias interesantes luego de estos estudios, antes de continuar veremos otro tipo de estudios, basado en los Mapas de Calor.

¿Qué es un mapa de calor? Un Mapa de Calor, es una técnica de visualización de datos que muestra la magnitud de un fenómeno como color en dos dimensiones. La variación de color puede deberse al tono o la intensidad, lo que proporciona al lector pistas visuales obvias sobre cómo el fenómeno se agrupa o varía en el espacio. Hay dos categorías fundamentalmente diferentes de mapas de calor: el mapa de calor del clúster y el mapa de calor espacial. En un mapa de calor de conglomerados, las magnitudes se presentan en una matriz de tamaño de celda fijo cuyas filas y columnas son fenómenos y categorías discretos, y la clasificación de filas y columnas es intencionada y algo arbitraria, con el objetivo de sugerir conglomerados o representarlos como descubierto mediante análisis estadístico. El tamaño de la celda es arbitrario pero lo suficientemente grande para ser claramente visible. Por el contrario, la posición de una magnitud en un mapa de calor espacial está forzada por la ubicación de la magnitud en ese espacio, y no hay noción de células; se considera que el fenómeno varía continuamente.

md_returns = returns.squeeze().groupby([returns.index.month.rename('month'), 
                                 returns.index.dayofweek.rename('day')]).mean().unstack(0)

fig, ax = plt.subplots(figsize=(16,6))
sns.heatmap(md_returns, ax=ax, cmap="Spectral");
QM blog pautas estacionales donde encontrarlas 07

Pareciera buena estrategia comprar los lunes y vender los jueves del mes de Julio.

A continuación veremos otro tipo de estudio, eliminaremos la componente tendencial de nuestros datos para evitar tener datos con sesgos, muy bien hagámoslo:

window = 253
# detrend tome series by MA
ratesM = data['Adj Close'].rolling(window).mean().dropna()
ratesD = data['Adj Close'].reindex(ratesM.index).sub(ratesM)

fig, axs = plt.subplots(2, figsize=(16, 8), sharex=True)
data['Adj Close'].plot(ax=axs[0], title="Trend")
ratesM.plot(ax=axs[0])
ratesD.plot(ax=axs[1], c="g", title="Residuals");
QM blog pautas estacionales donde encontrarlas 08

Ahora bien, actualicemos el estudio, vamos otra vez con los meses:

Monthly_Returns = ratesD.groupby([ratesD.index.year.rename('year'), 
                                  ratesD.index.month.rename('month')]
                                ).median().to_frame("Returns")
Monthly_Returns.boxplot(by='month', figsize=(16, 8));
QM blog pautas estacionales donde encontrarlas 09

Como podemos observar, ya no queda tan claro que de Julio a Septiembre obtendremos retornos positivos, de hecho ya no están muchas cosas claras, se mantiene que obtengamos posibles incrementos de Noviembre a Diciembre pero no se ve tan claro.

Que podemos hacer en estos casos, bueno busquemos una confirmación más visual, incorporaremos otra librería a nuestro estudio.

Descomposición

Utilizaremos la librería statsmodels para hacer una descomposición estacional y lo graficaremos, de la siguiente manera:

import statsmodels.api as sm
decomposition = sm.tsa.seasonal_decompose(data['Adj Close'], model="additive", period = 253)

trend = decomposition.trend
seasonal = decomposition.seasonal
residual = decomposition.resid

fig, axs = plt.subplots(4, figsize=(14, 10), sharex=True)
data['Adj Close'].plot(title='Original', color="blue", ax=axs[0])
trend.plot(title='Trend', color="red", ax=axs[1])
seasonal.plot(title='Seasonality', color="orange", ax=axs[2])
residual.plot(title='Residuals', color="green", ax=axs[3])
plt.tight_layout();seasonal["2019"].plot(label='Seasonality', color="blue", figsize=(20,8));
QM blog pautas estacionales donde encontrarlas 10

¿Que observamos acá? Bueno los precios de cierre de la serie da datos, la componente tendencia, la componente estacional y el residuo de residual que no es más que lo que le falta a la suma de la componente tendencial + la componente estacional para ser igual a la gráfica original, es importante destacar que en este caso es así porque se ha dicho que las componentes son “aditivas”.

Observemos la estacionalidad del año 2019.

seasonal["2019"].plot(label='Seasonality', color="blue", figsize=(20,8));

Queríamos comprobar si de verdad de noviembre a diciembre ha incrementado el precio, bueno pareciera ser que sí.

QM blog pautas estacionales donde encontrarlas 11

Hagamos un Zoom a este periodo:

seasonal["2019-11":"2019-12"].plot(label='Seasonality', color="blue", figsize=(20,8));
QM blog pautas estacionales donde encontrarlas 12

Pues pareciera que a partir del 15 de Noviembre hasta finales de Diciembre el precio recupera 15 puntos de su precio.

Bueno solo para verificar lo que hemos realizado, podemos compararlo con las gráficas que presenta https://charts.equityclock.com actualizada a Diciembre 2019.

QM blog pautas estacionales donde encontrarlas 13

Conclusión

Como podrá observar se encuentran cosas interesantes al realizar búsqueda de pautas estacionales, invito al lector aplicar el estudio a diversos activos y se sorprenderá gratamente, al identificar pautas estacionales podemos contar con una ventaja estadística a nuestro favor al momento de abrir operaciones. Invito al lector a que replique el estudio en otros activos.

Para ampliar la información:

https://www.mql5.com/es/articles/7038

https://machinelearningmastery.com/decompose-time-series-data-trend-seasonality/

https://en.wikipedia.org/wiki/Heat_map

Un agradecimiento especial para Antonio Rodríguez (@paduel_py) por el feedback en cuando al desarrollo del código que se presenta en este artículo.

Article written by Alexander Rios

Quantified Models YouTube Channel

We have several videos available on our YouTube channel that you may find very useful in developing trading systems.

We hope this information has been useful to you.

Subscribe to our Newsletter

Join our mailing list to receive the latest news and updates from Quantified Models team.

Subscribe to our Newsletter

You have Successfully Subscribed!

Skip to content