Alpha Factors y Alpha Trading en Python en Castellano

Alpha Factors y Alpha Trading en Python

Table of contents

Alpha Factor en Python: Modelado para Estrategias de Trading Avanzadas

El Alpha Trading es la forma de modelar Alpha Factors en escenarios de exposición a la rentabilidad. Estos modelos están ganando popularidad entre inversores de todos los niveles gracias a la mayor accesibilidad tecnológica.

¿Qué es un Alpha Factor?

Es un concepto relativamente nuevo donde las explicaciones tradicionales no reflejan la realidad dinámica de esta modalidad de inversión. El mundo de los criptoactivos ha atraído a investigadores brillantes que han generado nuevos modelos de backtesting con criterios distintos a los clásicos. Estos procesos de obtención de rentabilidad operan en un paradigma que los inversores tradicionales o analistas técnicos encontrarían difícil de comprender.

![Alpha Factor Overview](https://pythonparatrading.com/content/imagesilo de inversión que asume:

  • Los mercados son procesos estocásticos que no siguen una distribución normal, y los retornos pasados no garantizan retornos futuros. Por tanto, los métodos de selección de universos de activos son aleatorios en muchas fases del proceso de investigación, utilizando solo un 20% de datos reales y un 80% de series temporales generadas mediante técnicas de replicación estocástica.
  • Se implementan procesos avanzados de overfit y position sizing para asegurar la robustez del modelo. La evaluación se realiza con ratios que estandarizan niveles de rentabilidad y rangos de invariabilidad ante eventos estocásticos.
  • La matematización total del proceso de generación de señales permite realizar estudios de estado actual (nowcasting) y evaluar la continuidad de la robustez del modelo.

El Alpha Factor mantiene una fuerte asociación con el método científico, realizando modelos de inferencia con rigor científico aceptable.

![Métodos de investigación](https://pythonparatrading.comdecuadamente, primero debemos entender qué es el alpha. La rentabilidad de un modelo alpha puede representarse como:

$$R_t = R_t * \alpha - R_t * \beta + e$$

Dividiendo la rentabilidad en factor beta (rentabilidad de mercado) y factor alpha (rentabilidad adicional al mercado). Definimos alpha como la rentabilidad proveniente de la exposición que no corresponde en tiempo con el comportamiento del activo subyacente.

Una estrategia 100% beta sería comprar y olvidar, mientras que una estrategia 100% Alpha sería oportunista, operando solo bajo ciertas condiciones específicas.

Un Alpha Factor es un conjunto de reglas y procedimientos que, partiendo de una formulación matemática, genera exposiciones a retornos utilizando metodologías alternativas para la extracción de ventajas.

Alpha Encodings

Los alpha encoders estandarizan y matematizan las señales dentro de la filosofía de sistemas de trading. Por ejemplo, podríamos generar señales de un sistema trend following básico con un cruce de medias:

$$sign(minus(ma_{30}(close),ma_{200}(close)))$$

Esto genera una respuesta binaria basada en la resta entre dos medias móviles (30,200). Sin embargo, la entropía de estas señales es demasiado alta, similar a usar entradas y salidas aleatorias. Para mejorar, podemos utilizar más fórmulas análogas:

$$plus( \ sign(minus(ma_{20}(close),ma_{50}(close))), \ sign(minus(ma_{50}(close),ma_{100}(close))), \ sign(minus(ma_{100}(close),ma_{200}(close))) \ )$$

Esto proporciona robustez mediante la validación de señales anteriores, creando un "comité" que exige mayores umbrales para realizar cambios de estado.

Las posibilidades para codificar alpha son infinitas. Los grandes bancos suelen utilizar estos encodings en estrategias de momentum y arbitrajes long/short. Incluso podríamos testear el efecto de anuncios post-beneficios de forma sencilla:

$$div(epsDifference,std_{12}(epsDifference))$$

Universos de Activos

![Universos](https://pythonparatrading.comsos son subgrupos de activos candidatos a la exposición de alpha. Las condiciones para su generación no tienen límites: desde universos 100% aleatorios hasta criterios de capitalización bursátil, sectores, fundamentales, macroeconómicos o características estadísticas.

Los universos dinámicos reevalúan periódicamente los activos incluidos. Por ejemplo, el S&P 500 selecciona compañías bajo criterios específicos:

S&P 500. El índice mide el desempeño de gran capitalización de mercado (Large Cap). Considerado como el indicador más descriptivo del mercado de capitales de los EE.UU. El índice se compone por 500 compañías.

Para calcular el peso de cada activo se usa la fórmula:

$$p_a = MktCap / GlobalMktCap$$

Esto permite replicar exactamente la misma ponderación del índice sin ambigüedades.

Selección de Universos en Python

Vamos a crear universos de activos candidatos. Comenzaremos con una selección 100% aleatoria para evitar sesgos:

import pandas as pd
def random_tickers(x):
    tables=pd.read_html("https://en.wikipedia.org/wiki/List_of_S%26P_500_companies")
    tickers = tables[0]['Symbol'].tolist()
    return random.choices(tickers,k=x)

También podemos refinar el proceso utilizando ETFs establecidos como referencia:

import pandas as pd

urls = ['https://www.blackrock.com/es/profesionales/productos/253743/ishares-sp-500-b-ucits-etf-acc-fund/1497267045693.ajax?fileType=csv&fileName=CSPX_holdings&dataType=fund',
       'https://www.blackrock.com/es/profesionales/productos/253741/ishares-nasdaq-100-ucits-etf/1497267045693.ajax?fileType=csv&fileName=CSNDX_holdings&dataType=fund',
       'https://www.blackrock.com/es/profesionales/productos/251382/ishares-msci-world-minimum-volatility-ucits-etf/1497267045693.ajax?fileType=csv&fileName=MVOL_holdings&dataType=fund',
       'https://www.blackrock.com/es/profesionales/productos/280507/ishares-sp-500-health-care-sector-ucits-etf/1497267045693.ajax?fileType=csv&fileName=IUHC_holdings&dataType=fund']

allz = pd.DataFrame()
for x in range(len(urls)):
    tempz = pd.read_csv(urls[x],skiprows=2)
    allz = pd.concat([tempz,allz])
allz = allz[allz['Asset Class'] == 'Equity']
print('Cargados',len(allz['Ticker'].unique()),'tickers en un total de ',len(allz['Sector'].unique()),'Sectores')
allz = allz.set_index('Ticker')
allz['Market Value'] = allz['Market Value'].str.replace('.', '').str.replace(',', '.')
allz['Market Value'] = allz['Market Value'].astype(float)

Para transformar los candidatos a formato lista:

tickers_candidatos = allz.index.tolist()

O para acceder a tickers de un sector específico:

allz[allz['Sector'] == 'Cuidado de la Salud'].index.tolist()

Es importante destacar que no estamos seleccionando acciones donde nuestro sistema funciona mejor (lo que introduciría overfit), sino creando modelos que impacten contra todos los activos y seleccionen los más oportunos.

Introducción a los Alpha Factors en Python: Implementación Práctica

Vamos a explorar diferentes lógicas para investigar Alpha Factors. Este artículo presenta herramientas básicas para transformar una fórmula matemática en un modelo funcional.

Plan de Ataque

  • Cargar las librerías y herramientas necesarias
  • Programar las funciones auxiliares
  • Programar el motor principal de optimización
  • Integrar todas las piezas a la cadena

Herramientas Utilizadas

Utilizaremos librerías estándar de Python y yfinance para agilizar la descarga de datos.

import pandas as pd
import numpy as np
import scipy as sc
import matplotlib.pyplot as plt
import yfinance as yf
import itertools
from IPython.display import clear_output
plt.style.use("quantarmy")

Programación de Funciones Auxiliares

Creamos funciones para tareas repetitivas:

def calc_skew(data,y):
    skew = data.rolling(y).skew()
    return skew

def calc_rets(data,y):
    rets = data.pct_change(y)
    return rets
    
def calc_delta(d1,d2):
    delta = d1 - d1.shift(d2)
    return delta

Programación del Primer Alpha con Enfoque Multiactivo

Probaremos el alpha en diferentes activos para estimar su rendimiento:

def backtest_alpha_01(data,ret_x=10,days_delta=10,rolling_skew=10,p=1.0):
    for d in ['SPY','QQQ','IWM','TLT','GLD']:
        data = yf.download(d,progress=False)[['Adj Close']].round(2)
        df = data[['Adj Close']].round(2)
        df['c_ret'] = df['Adj Close'].pct_change(ret_x)
        df['skew'] = df['c_ret'].rolling(rolling_skew).skew()
        df['abs'] = np.abs(df['skew'])
        df['alpha'] = calc_delta(df['abs'],days_delta)
        df['signal'] = np.where(df['alpha'] > p,1,0)
        df['pct'] = df['Adj Close'].pct_change()
        df['ret'] = df['pct'] * df['signal'].shift(1)
        df['ret'].cumsum().plot()
    plt.title('Basic Backtest over assets main assets')
    plt.legend(labels=['SPY','QQQ','IWM','TLT','GLD'])
    plt.show()
    return

![Alpha Factor sobre ETFs](https://pythonparatrading.com/content/ valores (10, 10, 10, 1.0) son arbitrarios. Los resultados variarán según los parámetros utilizados para calcular el estimador y sus puntos de corte.*

Programación del Motor del Optimizador

Creamos una función que recorra todo el espectro de parámetros posibles:

def explore_alpha_01(df,ret_x=10,ret_y=16,days_delta_x=10,days_delta_y=16,rolling_skew_x=10,rolling_skew_y=16,p_x=1,p_y=2.1):
    eqs = pd.DataFrame()
    res = []
    i = 1
    
    retz = range(ret_x,ret_y,1)
    delt

Jesús Cuesta

Odesa (Ucrania)
Inversor desde 2014. Research desde 2017. He trabjado en diferentes gestoras de capital, y Hedgefunds Crypto. Apasasionado en el codigo, los datos y las finanzas. Acualmente localizado en Ucrania.