Los futuros son una forma de contrato redactado entre dos partes para la compra o venta de una cantidad de un activo subyacente en una fecha específica en el futuro.
En la práctica, los futuros se negocian en los intercambios (a diferencia de la negociación OTC) por cantidades y cualidades estandarizadas del subyacente. Los precios se marcan para el mercado todos los días. Los futuros son increíblemente líquidos y se utilizan en gran medida para fines especulativos.
Una lista detallada de todos los códigos de símbolos utilizados para los contratos de futuros en varias bolsas se puede encontrar en el sitio de datos de CSI: Futures Factsheet.
La principal diferencia entre un contrato de futuros y la propiedad de acciones es el hecho de que un contrato de futuros tiene una ventana limitada de disponibilidad en virtud de la fecha de vencimiento. En cualquier instante habrá una variedad de contratos de futuros en el mismo subyacente todos con fechas de vencimiento variables. El contrato con la fecha de vencimiento más cercana se conoce como el contrato cercano. El problema que enfrentamos como operadores cuantitativos es que en cualquier momento tenemos una opción de múltiples contratos con los que operar. Por lo tanto, estamos tratando con un conjunto de series de tiempo superpuestas en lugar de una corriente continua como en el caso de las acciones o el divisas.
El objetivo de este artículo es describir varios enfoques para construir un flujo continuo de contratos a partir de este conjunto de series múltiples y resaltar las compensaciones asociadas con cada técnica.
La principal dificultad al tratar de generar un contrato continuo a partir de los contratos subyacentes con entregas variables es que los contratos a menudo no se negocian a los mismos precios. Por lo tanto, surgen situaciones en las que no proporcionan un empalme suave de uno a otro. Esto se debe a los efectos de contango y backwardation.
Por desgracia, no existe un único método estándar para unir contratos de futuros en la industria financiera. En última instancia, el método elegido dependerá en gran medida de la estrategia que emplee los contratos y el método de ejecución.
Este método reduce la brecha entre múltiples contratos al desplazar cada contrato de modo que las entregas individuales se unan de manera fluida a los contratos adyacentes.
El problema clave con el método de Panamá incluye la introducción de un sesgo de tendencia, que introducirá una gran deriva en los precios. Esto puede conducir a datos negativos para contratos suficientemente históricos. Además, hay una pérdida de las diferencias de precios relativos debido a un cambio absoluto en los valores. Esto significa que los retornos son complicados de calcular (o simplemente incorrectos).
El enfoque de ajuste de proporcionalidad es similar a la metodología de ajuste para manejar las divisiones de existencias en acciones. En lugar de tomar un cambio absoluto en los contratos sucesivos, se utiliza la relación entre el precio de liquidación (cerramiento) más antiguo y el precio de apertura más reciente para ajustar proporcionalmente los precios de los contratos históricos. Esto permite un flujo continuo sin una interrupción del cálculo de los rendimientos porcentuales.
El principal problema con el ajuste proporcional es que cualquier estrategia comercial que dependa de un nivel de precio absoluto también tendrá que ajustarse de manera similar para ejecutar la señal correcta. Este es un proceso problemático y propenso a errores.
La esencia de este enfoque es crear un contrato continuo de contratos sucesivos tomando una proporción ponderada linealmente de cada contrato durante un número de días para garantizar una transición más fluida entre cada uno.
Por ejemplo, considere cinco días de suavizado. El precio del día 1, P1, es igual al 80% del precio del contrato lejano (F1) y al 20% del precio del contrato cercano (N1). Del mismo modo, el día 2, el precio es P2=0.6×F2+0.4×N2. Para el día 5, tenemos P5=0.0×F5+1.0×N5=N5 y el contrato se convierte en una continuación del precio cercano.
El problema con el método de rollover es que requiere que se negocie en los cinco días, lo que puede aumentar los costos de transacción.
Hay otros enfoques menos comunes para el problema, pero los evitaremos aquí.
El resto del artículo se centrará en la implementación del método de serie perpetua, ya que es el más adecuado para backtesting.
Vamos a unir el contrato de futuros de petróleo crudo WTI
Para realizar la descarga de datos de futuros he hecho uso del complemento Quandl. Asegúrese de configurar el entorno virtual Python correcto en su sistema e instale el paquete Quandl escribiendo lo siguiente en la terminal:
import datetime
import numpy as np
import pandas as pd
import Quandl
El trabajo principal se realiza en la función futures_rollover_weights. Requiere una fecha de inicio (la primera fecha del contrato cercano), un diccionario de fechas de liquidación del contrato (fechas de vencimiento), los símbolos de los contratos y el número de días para revertir el contrato (por defecto a cinco).
def futures_rollover_weights(start_date, expiry_dates, contracts, rollover_days=5):
"""This constructs a pandas DataFrame that contains weights (between 0.0 and 1.0)
of contract positions to hold in order to carry out a rollover of rollover_days
prior to the expiration of the earliest contract. The matrix can then be
'multiplied' with another DataFrame containing the settle prices of each
contract in order to produce a continuous time series futures contract."""
# Construct a sequence of dates beginning from the earliest contract start
# date to the end date of the final contract
dates = pd.date_range(start_date, expiry_dates[-1], freq='B')
# Create the 'roll weights' DataFrame that will store the multipliers for
# each contract (between 0.0 and 1.0)
roll_weights = pd.DataFrame(np.zeros((len(dates), len(contracts))),
index=dates, columns=contracts)
prev_date = roll_weights.index[0]
# Loop through each contract and create the specific weightings for
# each contract depending upon the settlement date and rollover_days
for i, (item, ex_date) in enumerate(expiry_dates.iteritems()):
if i < len(expiry_dates) - 1:
roll_weights.ix[prev_date:ex_date - pd.offsets.BDay(), item] = 1
roll_rng = pd.date_range(end=ex_date - pd.offsets.BDay(),
periods=rollover_days + 1, freq='B')
# Create a sequence of roll weights (i.e. [0.0,0.2,...,0.8,1.0]
# and use these to adjust the weightings of each future
decay_weights = np.linspace(0, 1, rollover_days + 1)
roll_weights.ix[roll_rng, item] = 1 - decay_weights
roll_weights.ix[roll_rng, expiry_dates.index[i+1]] = decay_weights
else:
roll_weights.ix[prev_date:, item] = 1
prev_date = ex_date
return roll_weights
Ahora que se ha producido la matriz de ponderación, es posible aplicar esto a las series temporales individuales. La función principal descarga los contratos cercanos y lejanos, crea un DataFrame único para ambos, construye la matriz de ponderación de rotación y, finalmente, produce una serie continua de ambos precios, ponderados adecuadamente:
if __name__ == "__main__":
# Download the current Front and Back (near and far) futures contracts
# for WTI Crude, traded on NYMEX, from Quandl.com. You will need to
# adjust the contracts to reflect your current near/far contracts
# depending upon the point at which you read this!
wti_near = Quandl.get("OFDP/FUTURE_CLF2014")
wti_far = Quandl.get("OFDP/FUTURE_CLG2014")
wti = pd.DataFrame({'CLF2014': wti_near['Settle'],
'CLG2014': wti_far['Settle']}, index=wti_far.index)
# Create the dictionary of expiry dates for each contract
expiry_dates = pd.Series({'CLF2014': datetime.datetime(2013, 12, 19),
'CLG2014': datetime.datetime(2014, 2, 21)}).order()
# Obtain the rollover weighting matrix/DataFrame
weights = futures_rollover_weights(wti_near.index[0], expiry_dates, wti.columns)
# Construct the continuous future of the WTI CL contracts
wti_cts = (wti * weights).sum(1).dropna()
# Output the merged series of contract settle prices
wti_cts.tail(60)
El resultado es el siguiente:
2013-10-14 102.230 2013-10-15 101.240 2013-10-16 102.330 2013-10-17 100.620 2013-10-18 100.990 2013-10-21 99,760 2013-10-22 98.470 2013-10-23 97.000 2013-10-24 97.240 2013-10-25 97.950 - ¿ Qué? - ¿ Qué? 2013-12-24 99,220 2013-12-26 99,550 2013-12-27 100.320 2013-12-30 99,290 2013-12-31 98.420 2014-01-02 95.440 2014-01-03 93.960 2014-01-06 93.430 2014-01-07 93.670 2014-01-08 92.330 Duración: 60, tipo: float64
Se puede ver que la serie es ahora continua a través de los dos contratos. El siguiente paso es llevar a cabo esto para múltiples entregas en una variedad de años, dependiendo de sus necesidades de backtesting.