Quantitative Research : ETF Decay Factor in Python

En este articulo , vamos a explorar el Leverage Factor.
El leverage factor, es un factor que su ventaja radica, en la creacion defectuosa de productos financieros. Dentro de un instrumento que replica un indice, siempre existe el denominado tracking error, que es la diferencia entre lo que ha materializado el activo subyacente, y lo que ha materializado el etf.
Los errores estimados de los etfs, son ratios aceptables, para productos non-leverage. Pero que ocurre, en los productos leveraged?
Antes de hablar de drogas duras, me gustaria recordar que:
- Los productos leveleados, adquieren mas riesgos que los productos flat,mediante su sistema de replicacion, o cualquier otra derivada, lo que los convierte en productos de muy corto plazo, y no recomendables para el largo plazo, dado que probablemente no se se entiende que producto se esta tratando, y que riesgos ocultos podria esconder.
- Un portfolio con etfs leveleados en 2020, hubiera acabado en muerte directa. Es una exposicion a mercado que debe ser gestionada unicamente si se entiende con que se esta trabajando.
- Los ETFs leveleados suelen tener mayores tasas. Hay que valorar en que momentos existe una ventaja estadistica sobre los mismos.
Matematicamente podriamos definir que
alpha = R < -1 * R + t
siendo:
- R: Los retornos del activo
- t : todos los gastos
contexto:
- En periodos volatiles, es peor
- En periodos lowvol, acumula decay
Sentido Comun:
Los etfs leveleados son productos optimos, para situaciones de exposicion puntual, por ejemplo ante eventos y noticias, y para los mas arriesgados, podria ser una fuente de cobertura puntual, siempre hablando a corto plazo.
Lo explicado en este taller, para llevar un portfolio a largo plazo, es algo para quien entienda, que esta haciendo. La Matrix de riegos de un portfolio de este tipo, crece exponencialmente hacia limites no conodios, dado el aumento de factores exogenos al precio que condicionan la viabilidad del producto.
Este articulo, es unicamente divulgativo. Replicarlo implicaria la muerte con un evento de 1.5 sigma
df = pd.DataFrame(index=range(50))
df.loc[df.index % 2 == 1,'r'] = 0.03
df.loc[df.index % 2 == 0,'r'] = -0.02913
df.iloc[0].loc['r'] = 0
df['p'] = (df['r'] + 1).cumprod()
df['-r'] = df['r'] * -1
df['-2r'] = df['r'] * -2
df['-3r'] = df['r'] * -3
df['-p'] = (df['-r'] + 1).cumprod()
df['-2p'] = (df['-2r'] + 1).cumprod()
df['-3p'] = (df['-3r'] + 1).cumprod()
test = df[['p','-p','-2p','-3p']] * 100

Como podemos apreciar, en tan solo 6 periodos, observamos el efecto decay, en tan solo 7 dias ha sido suficiente para que:
El precio, ha recuperado el nivel inicial de 100, y los precios calculados mediante retornos levelados aun tienen mucha diferencia.
El efecto es persistente en el tiempo
si vemos el final de la muestra, en tan solo 50 dias,
- el -1x esta a 7 puntos de su precio inicial
- el -2x esta a 18 puntos de su precio inicial
- el -3x esta a 30 puntos de su precio inicial

Testeando con datos de mercado.
Matematicamente, el efecto decay, estas demostrado. El siguiente paso consite en recopilar una lista de posibles candidados, generar un grupo de control, y un grupo de prueba, y validar la hipotesis.
- H1: 33% -1 * r_-3x > 33% r
Universos
leveraged = [SDOW SMDD SPXU SQQQ SRTY TMV]
control = [ DOW,MDI,SPX,NDX,RTY,TLT]
Descargando tickers desde el data lake
def create_from_lake(tickers):
out = pd.DataFrame()
allz = ac.get_library('etfs.prices.stable').read_batch(tickers)
for i in range(0,len(allz)):
currentz = allz[i]
out[allz[i].symbol] = currentz.data.close
return out
Get data from DataLake
controlz = create_from_lake(control)
sample = create_from_lake(leveraged)
sample_pct = sample.pct_change().dropna().cumsum()
controlz_pct = controlz.pct_change().dropna().cumsum()
H1: 33% * -1 * r_-3x > r
En este primer caso, vamos a analizar si, una ponderacion del 33% de la poscion (en corto) de un activo leveleado, es mejor que el activo subyacente. Para ello, vamos a crearnos una funcion, que nos automatize el proceso.
Siendo :
- r = retono del activo subyacente (En este caso, el mismo etf, que tenga la misma composicion de cartera, y mayor market cap)
- -3x = retorno del etf leveleado x3 en una posicion corta
- alpha = diferencias entre 1 unidad de -3x y 1 unidad de r (donde se deberia apreciar el apalancamiento medio, recordemos, que el multiplicador de estos productos es el esperado, y en la realidad es muy aproximado, pero no es el efectivo, y en momentos volatiles, el nivel de apalancamiento entra en un terreno confuso)
- eq_r_alpha hace referencia a la rentabilidad de la posicion -3x ponderada al 33% de cartera
- equal_risk: la diferencia entre una posicion del 33% del -3x posicionada en corto, y una unidad de riesgo posicionada en largo
def check_level_factor(controlz_pct,sample_pct,start,end):
results = pd.DataFrame()
controlz = create_from_lake(control)[start:end]
sample = create_from_lake(leveraged)[start:end]
sample_pct = sample.pct_change().dropna().cumsum()
controlz_pct = controlz.pct_change().dropna().cumsum()
for i in range(0,len(controlz_pct.columns)):
results.loc[controlz_pct.columns[i],'r'] = controlz_pct.iloc[-1][i] * 100
results.loc[controlz_pct.columns[i],'-r3x'] = -1 * sample_pct.iloc[-1][i] * 100
results.loc[controlz_pct.columns[i],'alpha'] = results.loc[controlz_pct.columns[i],'-r3x'] - results.loc[controlz_pct.columns[i],'r']
results.loc[controlz_pct.columns[i],'eq_r_alpha'] = 0.33 * results.loc[controlz_pct.columns[i],'-r3x']
results.loc[controlz_pct.columns[i],'equal_risk'] = 0.33 * results.loc[controlz_pct.columns[i],'-r3x'] -controlz_pct.iloc[-1][i] * 100
return results
Para poder validar nuestra hipotesis
H1: 33% * -1 * r_-3x > r
Dejando de lado la estadistica, deberiamos tener un porcentaje muy alto de overpeformance, y si no es asi, deberiamos investigar las implicaciones de la volatilñidad, dado que con un analisis prelimiar, se puede estimar que cuando la volatilidad aumenta, la rentabilidad de este factor desaparece.
Analizaremos en periodos anuales el desempeño del factor, mediante la funcion que hemos definido anteriormente.
Durante el 14/15, Los apalancamientos efectios, se han ido de madre en algunos activos como TLT, IWM, SPY, si consideramos el alpha, como el valor que aporta el etf, gracias a su apalancamiento, la forma mas apropiada para para concluir sobre el factor en el periodo, lo hacemos mediante el equal risk, que comparamos las diferencias de las posiciones ponderadas por nominal ( 33% del 3x) contra el activo subyacente.
Siendo
- equal_risk > 0 -> El factor esta funcionando.
- equal_risk < 0 -> El factor no esta funcionando.

La media de equal_risk del portfolio es de 1.73. Lo cual asegura que a una expectativa identica de volatilidad, estamos obteniendo rentabilidad adicional, con la misma posicion, y la misma ponderacion, unicamente por una correcta eleccion del activo.
Si extendemos el periodo

Desde 2015 hasta 2019, el factor ha estado funciando, aportando una rentabilidad media adicional de un 7% durante el periodo, y recordemos, a mismas posiciones, y mismas expectativas de riesgo. Durante esta etapa, se produjo un contexto de mercado de baja volatilidad, y subidas constantes,favoreciendo los mecanismos del factor, llegando hasta el punto de
TLT, Un caso diferente
Como vemos, TLT, esta comercializado como un etf convencional, pero su funcionamiento interno de compras y ventas de bonos del tesoro, genera unos flujos internos, que cuando se exponen hacia el factor del ETF Decay, se vuelven impredecibles sus resultados, pues el activo subyacente ha acabado en negativo el periodo, con un 2%, y a mismo riesgo, la posicion corta en TMV esta ganando un 10%. Los tipos de interes, las expectativas de inflacion, la coyuntura macroeconomica, los factores que afectan a la renta variable esta muy correlacionados con los factores que afectan a la renta fija, pero, al tener un horizonte temporal definido de sus activos, las valoraciones de sus holdings es distinta, y por consecuencia su impacto sobre el factor.
Pero de forma general, los activos se estan comportando tal como lo esperado, y ademas aportando rentabilidad adicional.
Ampliando aun mas el horizonte temporal

Para validad la teoria de que la volatilidad afecta negativamente al factor, podemos observar que cuando ampliamos el intervalo, desde 2019 hasta 2024, los resultados son muy dispares.
TLT, tal como hemos comentado, utiliza unas valoraciones a su estilo, y se ha descorrelacionado totalmente, aportando mayor drawdow, un 10% adicional.
Tenemos el caso de etf de SDOW, que vemos que su nivel de apalancamiento durante la volatilidad, no ha sido el estimado, dado que se esperaba un apalancamiento x3, esperando una rentabilidad estimada aproximada de un 190%, y devolviendo unciamente un 161%, dejandose un gran pellizco por el camino.
El resto de candidatos, sufriendo niveles de volatilidad similares, han salido dentro de los parametros estimados.
- Al aumentar la volatilidad, disminuye la rentabilidad de equal_risk
- Los tickers menos volatiles han funcionado mejor que los mas volatilies ( SPY mejor que QQQ)
Ideas
- Se podria exprimir el caso alcista mediante cortos en TMF para las epocas donde existe la posibilidad de inflacion y cambios de politicas monetarias?
Una de las formas de implantar este factor, es mediante un portfolio, con rebalanceos temporales en funcion de algun estimador.
Siendo simplistas, cuando SPY cruce la media de 200 de forma alcista, vendemos spxu.
El estimador es la media de 200, que al preguntar precio > media, siempre va a devolver un valor booleano (True,False) .
Ademas, para no pisarnos los dedos, deberiamos utilizar un activo sin leveleado en epocas donde la volatilidad sea mayor a la media.
Proximamente
Liberare algun template, para poder modelizar este factor de una forma sencilla desde zipline. Simplemente habria que tener dos factores. El factor que genere la señal, y este factor, que genera sobre que activo realizar la entrada.