Markets4Sheets

Como traders, sin importar cuál sea nuestro nivel de conocimientos y experiencia, es una excelente práctica llevar una bitácora de nuestas operaciones. La gran mayoría de los brokers del mundo nos brindan en cierta medida el estado de nuestra cuenta comitente y la posibilidad de operar desde alguna plataforma online. Sin embargo, dada la facilidad y la potencia a la que nos tienen acostumbrados desde hace mucho años las planillas de cálculo, la gran mayoria de los traders solemos llevar un registro de nuestras operaciones en ellas. En nuestro mercado local, hay maneras de obtener datos de las cotizaciones en tiempo real, pero estas tecnologias suelen ser complejas y poco amigables y ni hablar de la imposibilidad de la automatización del ingreso de ordenes al mercado.

Desde hace varios años soy un admirador de la potencia del conjunto de aplicaciones de oficina provisto por Google. He trabajado con Sheets por lo menos desde 2010 y me parece un gran paso adelente vs una opción desktop como el Excel de Microsoft. Ofrece la posibilidad de colaborar entre varias personas, disponibilidad en la nube, es multplataforma, es escalable, etc, etc, etc. Es por eso que mi necesidad personal de contar con datos en tiempo real en mis planillas me llevó, hace ya mas de un año, a bucear en el mundo de los Addons para GoogleSheets. Ese mundo inexplorado y desconocido guardaba tras sus bamblinas, una serie de servicios que usados y orquestados de manera correcta, me permitieron construir una serie de funciones “custom” para que, la problematica de contar con datos en tiempo real y operar desde una planilla de cálculos, sea una realidad.

No puedo llevarme este crédito sólo. La realidad es que el verdadero potencial del addon se encuentra en la api (application programming interface) de Primary. Esta libreria se encuentra disponible de manera gratuita para todos aquellos desarrolladores que deseen realizar distintas interacciones con el mercado, desde sus propias lineas de código.

Habiendo hecho esta breve (o quizas no tanto) introducción, voy a intentar dejarles este documento que intentará ser una documentación sobre la funcionalidad provista por el addon llamado “Markets4Sheets”.


El addon está construído sobre la api de Primary que ya comentamos mas arriba. Dicha api está acoplada completamente con una cuenta comitente. Es por esto que el acceso a estas cuentas debe ser provisto por los ALyC que permiten operar productos del mercado de Rofex. La api cuenta con distintos módulos para realizar varias tareas que pueden revisar con mas detalle en la muy clara documentación.

El uso de cualquiera de las funciones del addon, requiere la autenticación por parte del usuario contra la api de Primary, y por lo tanto, de nuestra cuenta comitente. Para realizar dicha acción, debemos ir al menu de Complementos — Markets4Sheets — Login

Una vez que estemos correctamente autenticados, podremos acceder al Dashboard del addon el cuál nos ofrece información sobre nuestra cuenta, al igual que la posibilidad de controlar nuestras órdenes activas y operadas

El dashboard nos permite tomar decisiones sobre nuestas órdenes vigentes. Podremos cancelar todas las órdenes que se ingresen desde cualquiera de los servicios de Rofex (Matriz, Talaris, Markets4Sheets, etc). Y como paso adicional, podremos ingresar ordenes al mercado. Las ordenes ingresadas a través de esta funcionalidad tienen la siguiente particularidad:

  • TimeInForce: DAY
  • Tipo: Limit

Desde las celdas de nuestra planilla de cálculo, tendrémos disponible las siguientes funciones para desarrollar nuestros propios indicadores


A continuación se enumeran las funciones existentes y que solo funcionan cuando las planillas NO POSEEN COLABORADORES

MARKETDATA(ticker,atributo)

@param {string} ticker. 
@param {“BI”,”OF”,”LA”,”OP”,”CL”,”SE”,”HI”,”LO”,”TV”,”OI”,”IV”,”EV”,”NV”} atributo. Parametro opcional, si no se incluye se devuelve LA o IV según si el ticker es Renta Fija, Renta Variable o Futuro.
@param {object} REFRESH. Si se incluye este atributo la celda se refrescará automáticamente durante la rueda durante cada 30 segundos
@return {number} El atributo solicitado

Devuelve el atributo solicitado del ticker. Los ticker soportados por el momento son aquelos relacionados con los siguientes instrumentos
 * Acciones
 * Renta Fija
 * Cedear
 * Futuros
 * Indices
 * Opciones sobre futuros
 * Opciones sobre Acciones 
 * Cauciones
 * Letras
 * Obligaciones Negociables

 * Los atributos validos son aquellos soportados por la api de primary.
* BI BIDS Mejor oferta de compra en el Book
 * OF OFFERS Mejor oferta de venta en el Book
 * LA LAST Último precio operado en el mercado
 * OP OPENING PRICE Precio de apertura
 * CL CLOSING PRICE Precio de cierre
 * SE SETTLEMENT PRICE Precio de ajuste (solo para futuros)
 * HI TRADING SESSION HIGH PRICE Precio máximo de la rueda
 * LO TRADING SESSION LOW PRICE Precio mínimo de la rueda
 * TV TRADE VOLUME Volumen operado en contratos/nominales para ese security
 * OI OPEN INTEREST Interés abierto (solo para futuros)
 * IV INDEX VALUE Valor del índice (solo para índices)
 * EV TRADE EFFECTIVE VOLUME Volumen efectivo de negociación para ese security
 * NV NOMINAL VOLUME Volumen nominal de negociación para ese security

Ejemplos:

a) Obtener el último precio de APBR

=MARKETDATA(“APBR”)

b) Obtener el último bid de APBR

=MARKETDATA(“APBR”,”BI”)

c) Obtener el último precio de APBR y refrescarlo cada 30 segndos

=MARKETDATA(“APBR”,Refresh)

d) Obtener el último bid de APBR y refrescarlo cada 30 segundos

=MARKETDATA(“APBR”,”BI”,Refresh)

e) La función MARKETDATA se puede utilizar con rangos. Entonces si por ejemplo tenemos toda la columna “A” con tickers, entonces podemos realizar la siguente llamada

=MARKETDATA(A1:A10) y nos va a devolver las 10 filas correspondientes a cada una de las celdas de la columna A si contienen ticker válidos.


BOOK(ticker,depth)

@param {string} ticker. 
@param {string} profundidad. Opcional, si no se solicita se traen todos.
@param {object} REFRESH. Si se incluye este atributo la celda se refrescará automáticamente durante la rueda durante cada 30 segundos.
@return {number} Un array de 5x5

Devuelve el book del ticker solicitado en el siguiente formato
BID SIZE, BID PRICE, OFFER PRICE, OFFER SIZE,LAST

Ejemplos:

a) Obtener el primer nivel de profundidad de TS y refrescar cada 30 segundos

=BOOK(“TS”,”1",Refresh)

b) Obtener los 5 niveles de profundidad de Galicia provistos por la API

=BOOK(“GGAL”,Refresh)

Ejemplo de llamada para traer el BOOK completo de PAMP

TRADE(ticker,price,quantity,side,cancel)

Ingresa una orden al mercado del tipo LIMIT y timeInForce DAY. En caso que se ingrese correctamente guarda los parametros de la misma. Si la celda se vuelve a ejecutar con los mismos parametros, la función detecta que es una orden duplicada y devuelve un mensaje de error. La intención de esta funcionalidad es evitar que al refrescar una planilla o volverla a abrir se vuelvan a ingresar al mercado ordenes viejas. Si se usa el último parametro “cancel” con TRUE, entonces la orden se ingresará con tipo de orden IOC (immediate or cancel) o FOK (fill or kill) según si el mercado acepte un tipo o el otro.
* @param {string} ticker.
 * @param {number} price: El precio al que se quiere ingresar la orden
 * @param {number} quantity: La cantidad que se quiere operar
 * @param {string} side: “BUY” si se quiere comprar, “SELL” si se quiere vender
 * @param {boolean} cancel: Si el parametro es TRUE la orden se ingresará FOK o IOC según el mercado y se cancelará si no se puede operar completa o quedara como limit
 * @return {boolean} true si la orden se ingresó con éxito

CANCEL(ticker)

Cancela todas las órdenes activas (pendientes o parcialmente operadas) del ticker solicitado
@param {string} ticker.
@return {boolean} true si la orden se canceló con éxito


A continuación se listan las funciones que están disponibles aunque la planilla posea colaboradores

CLOSE(ticker,price)

Cierra la posición del ticker. Si no se pasa precio, cierra con orden de tipo MARKET o MARKET_TO_LIMIT según el mercado. Si se pasa un precio, pone orden tipo LIMIT a ese precio
@param {string} ticker: El instrumento para el que se quiera cerrar posición
@param {number} opcional price: El precio al que se quiera cerrar la posición
@return {boolean} Devuelve TRUE si la orden se ingresa correctamente. FALSE en caso contrario.

EJEMPLO

=CLOSE(“I.MERVDIC17”) cierra la posición independientemente de que lado este posicionado a precio de mercado.

POSITION(ticker)

@param {string} Opcional: ticker. También se pueden pasar CASH, CASH1, CASH2 y COLLATERAL para obtener los disponibles en t=0, t+1, t+2 y el disponible para garantías
@return {number} la posición del instrumento si se indicó uno, o todas las posiciones abiertas

Devuelve todas las posiciones abiertas de la cuenta
Si se pasa un ticker devuelve solo la posicion de dicho instrumento

EJEMPLO

Obtener la posición actual de toda la cuenta

=POSITION()

OPTION_VALUE(ticker,subyacente,volatilidad)

@param {string} ticker. 
@param {string} subyacente
@param {float} volatilidad_historica. Este valor se puede obtener de los informes diarios del iamc
@param {object} REFRESH. Si se incluye este atributo la celda se refrescará
automáticamente durante la rueda durante cada 30 segundos.
@return {number} el valor teórico

Devuelve la valuación BS de la base solicitada. Toma como tasa libre de riesgo la última cotización de la caución en PESOS a 7 dias.

EJEMPLO

a) Obtener el valor teórico de la base 80.4 de APBR de Diciembre

=OPTION_VALUE(“PBRC80.4DI”,”APBR”,0.3312)


IV(ticker)

Devuelve la volatilidad implicita de la base solicitada. Toma como tasa libre de riesgo la última cotización de la caución en PESOS a 7 dias.

@param {string} ticker. 
@param {string} subyacente
@param {object} REFRESH. Si se incluye este atributo la celda se refrescará
automáticamente durante la rueda durante cada 30 segundos.
@return {number} la volatilidad implicita

EJEMPLO

=IV(“PBRC90.4DI”,”APBR”) Devuelve la volatilidad implicita del momento de ejcución de la base PBRC90.4DI


BOND_YIELD(ticker)

Devuelve la TIR del bono calculada a partir del dia de ejecución de la función y según el cashflow de amortización y renta públicado en la calculadora de bonos del IAMC. Se utiliza la especie en ARS y se converite a USD con el MEP del AY24, cuyo valor de referencia se actualiza cada 10 minutos.
Probado en los siguientes instrumentos: A2E2,A2E7,AA19,AA21,AA22,AA25,AA26,AA37,AA46,AC17,AM18,AM20,AMX8,AMX9,AN18,AO20,AY24,BD2C9,BDC18,BDC19,BDC20,BP18,BP21,BP28,BPLD,,BPMD,CUAP,DIA0,DICA,DICP,DICY,DIP0,DIY0,FORM3,NDG21,NF18,NO20,PAA0,PAP0,PARA,PARP,PARY,PAY0,PBJ21,PBM24,PMD18,PMG18,PMO18,PR13,PR15,PUM21,PUO19,TC20,TC21,TJ20,TM18,TO21,TO23,TO26,TS18,TUCS1

* @param {string} ticker. 
 * @param {object} REFRESH. Si se incluye este atributo la celda se refrescará
 * automáticamente durante la rueda durante cada 1 hora.
 * @return {number} El atributo solicitado

Ejemplo

=BOND_YIELD(“AY24”) Devuelve la TIR con el último valor cotizado al momento de ejecución


Consideraciones importantes:

  • El login es válido durante 24hs una vez superado ese lapso se solicitará nuevamente la autenticación
  • El refresh funciona cada 30 segundos unicamente mientras el dashboard se encuentra abierto. Caso contrario corre cada 60 minutos.
  • Existe una limitación por parte de Google sobre la cantidad de llamadas que se pueden realizar a un servicio externo (como la api) durante 24hs. Ese limite son 20.000 llamadas. Eso significa que realizando un refresh cada 30 segundos durante las 6 hs de la rueda, cada celda que se refresque consume 720 llamadas. Eso nos da una cantidad aproximada de 27 celdas para actualizar continuamente durante la rueda. A continuación pueden encontrar un detalle estas limitaciones por parte de Google (POR FAVOR LEER EN DETALLE) https://developers.google.com/apps-script/guides/services/quotas

Por último, si alguien desea colaborar con alguna donación, se deja un código QR para enviar el monto que deseen o a través del siguiente link paypal.me/rofex4sheets