Implementación de un modelo de pares de trading en Python
En este ejemplo vamos a utilizar las bibliotecas pandas y numpy para crear un modelo de pares de trading y analizar su rentabilidad y riesgo. Primero, cargamos los datos de dos activos que queremos considerar para la estrategia de pares de trading. Por ejemplo, supongamos que queremos usar las acciones de Apple (AAPL) y Intel (INTC).
import pandas as pd
import numpy as np
import pandas_datareader as pdr
start_date = '2010-01-01'
end_date = '2021-01-01'
AAPL = pdr.get_data_yahoo('AAPL', start_date, end_date)['Adj Close']
INTC = pdr.get_data_yahoo('INTC', start_date, end_date)['Adj Close']
df = pd.concat([AAPL, INTC], axis=1)
df.columns = ['AAPL', 'INTC']
print(df.head())
Ahora, podemos llevar a cabo el análisis de pares de trading. Primero, calculamos la relación entre los precios de ambas acciones:
# Calculamos la relación entre los precios de AAPL e INTC
spread = df['AAPL'] - df['INTC']
zscore = (spread - np.mean(spread))/np.std(spread)
print(zscore.head())
Ahora, podemos determinar nuestros puntos de entrada y salida utilizando un umbral de z-score. Supongamos que queremos entrar en la operación cuando el z-score llega a 2, es decir, cuando la diferencia entre los precios es 2 desviaciones estándar por encima de la media, y salir cuando vuelve a la media (z-score = 0).
# Definimos los puntos de entrada y salida de acuerdo al umbral de z-score
entry = 2
exit = 0
df['zscore'] = zscore
df['long_entry'] = (df['zscore'] < -entry) # Apertura de posición larga
df['long_exit'] = (df['zscore'] > -exit) # Cierre de posición larga
df['short_entry'] = (df['zscore'] > entry) # Apertura de posición corta
df['short_exit'] = (df['zscore'] < exit) # Cierre de posición corta
En este punto, podemos simular nuestra estrategia como si estuviéramos negociando con dinero real. Supongamos que vamos a invertir $10,000 en cada operación y vamos a asumir que no hay costos asociados a las transacciones. Podemos calcular nuestros rendimientos diarios multiplicando nuestro retorno por el cambio porcentual diario en los precios de las acciones.
# Simulación de la estrategia de pares de trading
startcash = 10000
df['AAPL_position'] = np.where(df['long_entry'], startcash/df['AAPL'], np.nan)
df['AAPL_position'] = np.where(df['long_exit'], 0, df['AAPL_position'])
df['INTC_position'] = np.where(df['long_entry'], -startcash/df['INTC'], np.nan)
df['INTC_position'] = np.where(df['long_exit'], 0, df['INTC_position'])
df['position'] = df['AAPL_position'] + df['INTC_position']
df['position'] = df['position'].fillna(method='ffill')
df['AAPL_holdings'] = df['AAPL'] * df['AAPL_position']
df['INTC_holdings'] = df['INTC'] * df['INTC_position']
df['cash'] = startcash - (df['AAPL_holdings'] + df['INTC_holdings']).cumsum()
df['value'] = df['cash'] + df['AAPL_holdings'] + df['INTC_holdings']
df['returns'] = df['value'].pct_change()
Finalmente, podemos analizar los rendimientos y los riesgos de nuestra estrategia. Podríamos calcular la rentabilidad acumulada, la tasa de rendimiento anualizada, el factor de ganancia, la relación de Sharpe y otros ratios.
# Análisis del rendimiento y riesgo de la estrategia
cumulative_return = df['returns'].cumsum()[-1]
annual_return = df['returns'].mean() * 252
gain_to_pain_ratio = df['returns'][df['returns']>0].sum() / abs(df['returns'][df['returns']<0].sum())
sharpe_ratio = annual_return / df['returns'].std() * np.sqrt(252)
print(f'Cumulative Return: {cumulative_return:.2%}')
print(f'Annual Return: {annual_return:.2%}')
print(f'Gain to Pain Ratio: {gain_to_pain_ratio:.2f}')
print(f'Sharpe Ratio: {sharpe_ratio:.2f}')