Quantstrat (abreviatura de (Quantitative Strategy Model Framework) es un paquete para R desarrollado por Peter Carl (Univ. Chicago, William Blair & Co.), Brian Peterson (Univ. Wisconsin-Madison, DV Trading) y Jeffrey Ryan (Univ. Illinois, Citadel LLC y creador de QuantMod). Con este paquete es posible crear estrategias de trading y hacer backtests, convirtiendo así R en una completa plataforma de análisis de sistemas. Si bien veremos algunas de sus funciones, podéis encontrar la referencia completa del paquete en https://rdrr.io/rforge/quantstrat/

El esquema de funcionamiento de Quanstrat es relativamente sencillo: se descargan los datos de mercado (Instruments) que deseemos analizar y calculamos una serie de valores sobre ellos (Indicators). De la interacción entre indicadores e instrumentos (relaciones de desigualdad, cruces, superación de niveles, etc.) obtenemos señales (Signals) que nos permitirán construir reglas de trading (Rules) que generarán órdenes (Orders) que se convertirán en operaciones  (Transactions).



Instalación
Quantstrat no es un paquete incluido en el repositorio habitual de R por lo que es necesario llevar a cabo una serie de pasos previos para poder instalarlo.

En primer lugar deberemos instalar Rtools (disponible en https://cran.r-project.org/bin/windows/Rtools/), herramienta que nos permitirá compilar paquetes dentro de R en Windows.

Es importante que, cuando instalemos Rtools aceptemos que nos modifique el path del sistema cuando no los solicite marcando la casilla como en la siguiente imagen, de lo contrario no nos funcionará nada de lo que hagamos después:

Seguidamente comprobamos la correcta instalación de Rtools en R con los siguientes comandos:


Si todo ha ido bien hasta aquí, usando los siguientes comandos podremos instalar los paquetes FinancialInstrument y Blotter disponibles en R-Forge y que son necesarios para instalar Quanstrat seguidamente. Aquí tenéis los comandos para hacerlo (en cada uno de ellos nos solicitará permiso para compilarlos):

   install.packages("FinancialInstrument", repos="http://R-Forge.R-project.org")
   install.packages("blotter", repos="http://R-Forge.R-project.org")
   install.packages("quantstrat", repos="http://R-Forge.R-project.org")

Para estar al tanto de las últimas versiones de estos paquetes podéis visitar https://r-forge.r-project.org/R/?group_id=316

Adicionalmente necesitaremos instalar los siguientes paquetes para que todo funcione correctamente:

   install.packages("zoo")
   install.packages("TTR", repos="http://R-Forge.R-project.org")
   install.packages("devtools")
   require(quantstrat)
   require(devtools)
   install.packages("commonmark")
   install.packages("roxygen2")

También es recomendable instalar estos dos paquetes disponibles en GitHub con los que ampliaremos muchas funciones:

  install_github("IlyaKipnis/IKTrading")
  install_github("IlyaKipnis/DSTrading")

Estos dos paquetes han sido desarrollados por Ilya Kipnis, creador del blog QuantStrat TradeR. En particular, IKTrading permite ampliar las funciones de Quantstrat, incluyendo Ichimoku, Heiken Ashi, Value Charts, varios indicadores de David Varadi y otros, así como algoritmos de asignación de capital y funciones para medir duración de una operación, MAE y MFE de una cartera, etc. Asimismo contiene quandClean, una excelente herramienta para construir históricos de futuros continuos usando los datos disponibles en Quandl. Por su parte DSTrading (Digital Signal Trading) permite incorporar todos los indicadores de John Ehlers (MESA Software).

Finalmente, si queremos tener una buena colección de métricas aplicables a los sistemas es recomendable instalarse el paquete PerformanceAnalytics (este sí que está disponible en el repositorio de R). Con este paquete podéis calcular el VaR usando diferentes medidas de riesgo, obtener ratios como Sharpe, Omega, Sortino o Calmar, o realizar análisis de rendimientos relativos y comparativas con benchmarks. Podéis encontrar más información sobre este paquete en https://cran.r-project.org/web/packages/PerformanceAnalytics/index.html


Mi Primer Sistema con Quanstrat
Bien, si habéis seguido todos los pasos correctamente ya tenéis todo listo para empezar a hacer vuestro primer sistema de trading con Quanstrat. Para ello vamos a crear un sistema sencillo basado en bandas de Bollinger que testearemos sobre los 5 principales valores del Ibex 35 en gráfico diario.

El primer paso será cargar los paquetes que necesitaremos, configurar el entorno y descargar los históricos de Inditex, Banco Santander, Telefónica, BBVA e Iberdrola:

require(quantstrat)
require(PerformanceAnalytics)
require(lattice)
startDate <- '2010-01-01'
endDate <-  '2016-12-31'
Sys.setenv(TZ="Europe/Madrid")
symbols <- c("ITX.MC", "SAN.MC", "TEF.MC", "BBVA.MC", "IBE.MC")
getSymbols(symbols, from=startDate, to=endDate, index.class="POSIXct")


Seguidamente declaramos capital inicial y divisa de la cuenta y los símbolos:

initDate <- '2010-01-01'
initEq <- 100000
currency("EUR")
stock(symbols, currency="EUR", multiplier=1)


Inicializamos estrategia, portfolio y cuenta:

rm.strat("multiAsset.bb1")
initPortf(name="multiAsset.bb1", symbols, initDate=initDate, currency = "EUR")
initAcct(name="multiAsset.bb1", portfolios="multiAsset.bb1", initDate=initDate, initEq=initEq,  currency = "EUR")
initOrders(portfolio="multiAsset.bb1", initDate=initDate)

A continuación declaramos estrategia e inicializamos las bandas de Bollinger y sus parámetros:

strategy("bbands", store=TRUE)
add.indicator("bbands", name = "BBands", arguments = list(HLC = quote(HLC(mktdata)), maType='SMA'), label='bbInd')
nSD = 2
nMA = 20

Pasamos a crear las señales sobre las que se basa la estrategia:  la primera de ellas nos indica que se produce un máximo (High) mayor que (gt) la banda superior de Bollinger (up), mientras que la segunda nos indica que se produce un cierre (Close) por debajo de (lt) la banda superior de Bollinger, tal que:

add.signal("bbands", name="sigCrossover", arguments=list(columns=c("High","up"),relationship="gt"), label="H.gt.UpperBand")
add.signal("bbands", name="sigCrossover", arguments=list(columns=c("Close","up"),relationship="lt"), label="C.lt.UpperBand")

Ahora definimos las reglas de compra y venta: la idea de la estrategia es aprovechar impulsos alcistas fuera de la banda superior de Bollinger, por lo que la primera regla abrirá una posición de compra de 100 títulos a mercado cada vez que se produzca un máximo por encima de la banda superior de Bollinger. Por su parte, la segunda regla nos indica que si se produce un cierre por debajo de la banda superior, se cerrarán todas las posiciones:

add.rule("bbands", name='ruleSignal', arguments=list(sigcol="H.gt.UpperBand",sigval=TRUE, orderqty=+100, ordertype='market', orderside='short'), type='enter', label='LongEntry')
add.rule("bbands", name='ruleSignal', arguments=list(sigcol="C.lt.UpperBand",sigval=TRUE, orderqty= 'all', ordertype='market', orderside='long'), type='exit', label='LongExit')

Una vez definidas estrategia, señales y reglas podemos proceder a ejecutar la estrategia:

t1 <- Sys.time()
out <- applyStrategy("bbands", portfolios="multiAsset.bb1", parameters=list(sd=nSD,n=nMA))
t2 <- Sys.time()
print(t2-t1)

Si todo ha ido bien nos habrá salido una lista con todas las transacciones realizadas. La diferencia entre t2 y t1 nos da el tiempo que se tarda en realizar todos los cálculos y operaciones de la estrategia.

Ahora podemos por ejemplo ver las operaciones de la estrategia en cada activo con getTxns usando las siguientes líneas:

getTxns(Portfolio="multiAsset.bb1", Symbol="ITX.MC")
getTxns(Portfolio="multiAsset.bb1", Symbol="SAN.MC")
getTxns(Portfolio="multiAsset.bb1", Symbol="TEF.MC")
getTxns(Portfolio="multiAsset.bb1", Symbol="BBVA.MC")
getTxns(Portfolio="multiAsset.bb1", Symbol="IBE.MC")

Sacar los principales datos estadísticos de la estrategia en cada activo con tradeStats:

updatePortf("multiAsset.bb1")
updateAcct("multiAsset.bb1")
updateEndEq("multiAsset.bb1")
textplot(t(tradeStats("multiAsset.bb1")))

Obteniéndose el siguiente resultado:

También podemos ver el gráfico con la estrategia, los volúmenes ejecutados, la equity y la evolución del drawdown a lo largo del tiempo. Si queremos verlo por ejemplo para Telefónica tenemos que ejecutar lo siguiente:

myTheme<-chart_theme()
myTheme$col$dn.col<-'lightblue'
myTheme$col$dn.border <- 'lightgray'
myTheme$col$up.border <- 'lightgray'
chart.Posn(Portfolio="multiAsset.bb1",Symbol="TEF.MC",theme=myTheme,TA="add_BBands(n=20,sd=2)")

Deberemos obtener un gráfico como el siguiente:


También podemos sacar estadísticas de duración de los trades con las siguientes líneas de código:

durStats <- durationStatistics (Portfolio="multiAsset.bb1", Symbols=sort(symbols))
print(t(durStats))

Con ello obtenemos la distribución de la duración de todas las operaciones, así como de las operaciones ganadoras (W) y perdedoras (L):


Por último, también podemos obtener los rendimientos acumulados para cada activo y compararlos:

rets.multi <- PortfReturns("multiAsset.bb1")
colnames(rets.multi) <- sort(symbols)
round(tail(rets.multi,5),6)
chart.CumReturns(rets.multi, colorset= rich10equal, legend.loc = "topleft",
main="CumReturns Portfolio",minor.ticks=FALSE)

El resultado que obtendríamos sería el siguiente:


Como podéis ver las posibilidades de análisis de sistemas de trading usando quantstrat se multiplican exponencialmente. En las próximas entregas veremos cómo incorporar un sencillo algoritmo de gestión monetaria a una estrategia y cómo optimizar los parámetros de una estrategia.


Saludos,
X-Trader