Nos vamos a enfocar en el arbitraje de pases de futuros en Rofex. En esta ocasión usaremos los contratos de futuro de dolar (DOMar19, DOAbr19) y el pase de futuro de dolar (DOP 03/04).

Pasemos a la estrategia

Primero definimos los imports que vamos a utilizar en nuestro código. En este caso serán Strategy y Order, ambas provistas por ArQuants.

[code language=”python”]
from arquants import Strategy
from arquants import Order
[/code]

En segundo lugar definimos la clase de la estrategia. La misma tiene que extender la clase Strategy. Podemos definir los parámetros que la estrategia soporta dentro de la firma del método __init__, en este caso min_diff. También podemos definir atributos.

[code language=”python”]
class ArbitrajePases(Strategy):

def __init__(self, min_diff=0.01):
self.orders = []
self.min_diff = min_diff
[/code]

Nos queda presentar lo mas importante de la estrategia, el metodo next. Este método es invocado cada vez que se recibe market data.

[code language=”python”]
def next(self):
self.log(“Market data recibidia. Chequeando arbitraje”)
if self.data1.bid_px[0] – self.data0.offer_px[0] > self.data2.offer_px[0]:
self.logs(“Arbitraje detectado, comprando pase, vendiendo combinada”)
size = min(self.data1.bid_qty[0], self.data0.offer_qty[0], self.data2.offer_qty[0])
self.sell(data=self.data1, price=self.data1.bid_px[0], size=size, exectype=Order.Limit)
self.buy(data=self.data0, price=self.data0.offer_px[0], size=size, exectype=Order.Limit)
self.buy(data=self.data2, price=self.data2.offer_px[0], size=size, exectype=Order.Limit)

elif self.data1.offer_px[0] – self.data0.bid_px[0] < self.data2.bid_px[0]:
self.logs(“Arbitraje detectado, vendiendo pase, comprando combinada”)
size = min(self.data1.offer_qty[0], self.data0.bid_qty[0], self.data2.bid_qty[0])
self.buy(data=self.data1, price=self.data1.offer_px[0], size=size, exectype=Order.Limit)
self.sell(data=self.data0, price=self.data0.bid_px[0], size=size, exectype=Order.Limit)
self.sell(data=self.data2, price=self.data2.bid_px[0], size=size, exectype=Order.Limit)
[/code]

Podemos ver que se hace referencia a atributos llamados data0, data1, y data2. Los mismos representan cada uno de los contratos que se están operando. En este caso data0 está asociado al contrato corto (por ejemplo DOMar19), data1 al contrato largo (por ejemplo DOAbr19) y data2 al pase (DOP 03/04).

Cada data contiene market data correspondiente al contrato. En particular la market data actual es accedida invocando el tipo de market data que se desea en el indice 0. Por ejemplo self.data0.offer_px[0] retorna el valor del mejor offer de DOMar19 en el momento actual.

También vemos que se utilizan los métodos sell y buy. Estos métodos pertenecen a la libreria de ArQuants y permiten comprar y vender. Sus parámetros permiten especificar que se va a operar, a que precio, que cantidad, y con que tipo de orden. Existen más parámetros que permiten
hacer una definición más precisa de la orden.

Finalmente, la estrategia comprará DOP 03/04 y hará una venta de pase vendiendo DOAbr19 y comprando DOMar19 si el precio de venta de DOAbr19 menos el precio de compra de DOMar19 es mayor al precio de compra de DOP 03/04.
En caso de que no sea posible, intentará vender DOP 03/04 y hacer una compra de pase comprando DOAbr19 y vendiendo DOMar19 si el precio de compra de DOAbr19 menos el precio de venta de DOMar19 es menor al precio de venta de DOP 03/04

Si consigue realizar alguna de las dos operaciones habrá arbitrado un pase de contratos de futuros de dólar.

El código completo de la estrategia queda de la siguiente manera

[code language=”python”]
from arquants import Strategy
from arquants import Order

class ArbitrajePases(Strategy):

def __init__(self, min_diff=0.01):
self.orders = []
self.min_diff = min_diff

def next(self):
self.log(“Market data recibidia. Chequeando arbitraje”)
if self.data1.bid_px[0] – self.data0.offer_px[0] > self.data2.offer_px[0]:
self.logs(“Arbitraje detectado, comprando pase, vendiendo combinada”)
size = min(self.data1.bid_qty[0], self.data0.offer_qty[0], self.data2.offer_qty[0])
self.sell(data=self.data1, price=self.data1.bid_px[0], size=size, exectype=Order.Limit)
self.buy(data=self.data0, price=self.data0.offer_px[0], size=size, exectype=Order.Limit)
self.buy(data=self.data2, price=self.data2.offer_px[0], size=size, exectype=Order.Limit)

elif self.data1.offer_px[0] – self.data0.bid_px[0] < self.data2.bid_px[0]:
self.logs(“Arbitraje detectado, vendiendo pase, comprando combinada”)
size = min(self.data1.offer_qty[0], self.data0.bid_qty[0], self.data2.bid_qty[0])
self.buy(data=self.data1, price=self.data1.offer_px[0], size=size, exectype=Order.Limit)
self.sell(data=self.data0, price=self.data0.bid_px[0], size=size, exectype=Order.Limit)
self.sell(data=self.data2, price=self.data2.bid_px[0], size=size, exectype=Order.Limit)
[/code]

<strong>Por</strong> Juan Bais
Por Juan Bais

Ingeniero de sistemas de la Universidad de Buenos Aires y Co founder de TradeSpark.