R es un lenguaje y entorno para computación estadística y gráficos.
R se basa en el lenguaje S, desarrollado originalmente por John Chambers y sus colegas en AT&T Bell Labs a finales de la década de 1970 y principios de 1980.
R (a veces llamado “GNU S”) es un software gratuito de código abierto licenciado bajo la licencia pública general GNU (GPL 2).
El desarrollo de R fue iniciado alrededor de 1993 por Robert Gentleman y Ross Ihaka en la Universidad de Auckland, Nueva Zelanda.
R se conoce como El Proyecto R para Computación Estadística.
Visualización de datos: Tanto R como Python cuentan con numerosas bibliotecas de gráficos, pero el paquete R ggplot2 (basado en el concepto de “gramática de gráficos”) es el claro ganador (véase la galería. Python también cuenta con una biblioteca ggplot.
Bibliotecas de modelado: Tanto R como Python cuentan con numerosas bibliotecas. Parece que R tiene más potencial en ciencia de datos. En estadística, R es el claro ganador.
Facilidad de aprendizaje: Python se diseñó en 1989 para programadores con una sintaxis inspirada en C. R se desarrolló alrededor de 1993 para estadísticos y científicos, también con una sintaxis inspirada en C. Algunos piensan que Python es más fácil, mientras que otros piensan que R lo es. Quizás inicialmente R era más difícil de aprender que Python, pero con los entornos de desarrollo integrado (IDE) modernos como RStudio, esto ya no es así. Algunos podrían decir que Python es más elegante, pero eso depende de a qué esté acostumbrado cada uno.
Velocidad: Inicialmente, Python era más rápido que R. Sin embargo, con los paquetes modernos existentes, esto ya no es así. Por ejemplo, el famoso paquete de R data.table para manipular grandes cantidades de datos es el claro ganador (véase benchmark). De hecho, el paquete de R Rcpp permite combinar R con C++, lo que resulta en implementaciones muy rápidas de los paquetes. Recientemente, R también se ha beneficiado de muchos paquetes de computación paralela.
Soporte de la comunidad: Ambos lenguajes cuentan con una base de usuarios significativa, por lo que ambos cuentan con una comunidad de soporte muy activa.
Aprendizaje automático: Python es más popular para redes neuronales. Sin embargo, lo cierto es que las bibliotecas de aprendizaje profundo más populares (p. ej., TensorFlow, Keras,H2O, etc.) están codificadas en C y tienen interfaces con Python, R y otros lenguajes. Curiosamente, los bosques aleatorios (uno de los métodos de aprendizaje automático más populares) son muy superiores en R. Esto se debe a que las redes neuronales tradicionalmente provienen de la informática, mientras que los bosques aleatorios provienen de la estadística.
¿Por qué R?: R se ha utilizado para computación estadística durante más de dos décadas. Puedes empezar a escribir código útil enseguida. Ha sido ampliamente utilizado por científicos de datos y cuenta con una enorme cantidad de paquetes disponibles para diversas tareas relacionadas con la ciencia de datos.
¿Por qué Python?: Python es un lenguaje de programación de propósito general. Para aplicaciones web, Python parece ser más popular.
Finanzas: De nuevo, tanto R como Python se utilizan ampliamente en finanzas. Es fácil encontrar defensores y detractores apasionados de cada lenguaje. Según mis propias observaciones en los sectores académico e industrial, puedo afirmar que R es imbatible para pruebas rápidas y desarrollo de prototipos, y quizás Python se utilice más en etapas posteriores, cuando el producto final (probablemente web) debe desarrollarse para los clientes.
Instalación
Para instalarlo, simplemente siga estos sencillos pasos:
Ahora está listo para empezar a usar R desde RStudio (tenga en cuenta que también puede usar R directamente desde la línea de comando sin RStudio o usar otro IDE de su preferencia).
Paquetes
Para ver las versiones de R y los paquetes instalados, simplemente escriba sessionInfo():
Para ver la versión de un paquete específico, usa packageVersion("package_name").
Con el tiempo, tendrás que instalar diferentes paquetes desde CRAN con el comando install.packages("package_name") o desde GitHub con el comando devtools::install_github("package_name").
Después de instalar un paquete, es necesario cargarlo antes de poder usarlo con el comando library("package_name") o library(package_name).
# Intentemos usar la función xts() del paquete xts:x <-xts()#> Error en xts(): No se pudo encontrar la función "xts"# Intentemos cargar el paquete primero:library(xts)#> Error en library(xts): No existe el paquete "xts"# Instalamos primero:install.packages("xts")# Ahora podemos cargarlo y usarlo:library(xts)x <-xts()
Variables y tipos de datos
En R, podemos asignar fácilmente un valor a una variable u objeto con <- (si la variable no existe, se creará):
x <-"Hola"x
[1] "Hola"
Podemos combinar varios elementos con c():
y <-c("Hola", "todos")y
[1] "Hola" "todos"
Siempre podemos ver las variables en memoria con ls():
ls()
[1] "x" "y"
Mi comando favorito es str(variable). Proporciona información diversa sobre la variable, como su tipo, dimensiones, contenido, etc.
str(x)
chr "Hola"
str(y)
chr [1:2] "Hola" "todos"
Otro par de comandos útiles son head() y tail(). Son especialmente útiles para variables de gran tamaño, ya que muestran los primeros y los últimos elementos, respectivamente.
x <-c(1:1000)str(x)
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
head(x)
[1] 1 2 3 4 5 6
tail(x)
[1] 995 996 997 998 999 1000
Es importante destacar que R es un lenguaje funcional donde casi todo se hace mediante funciones de todo tipo (como str(), print(), head(), ls(), tail(), max(), etc.).
x <-c(1:1000)str(x)
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
head(x)
[1] 1 2 3 4 5 6
tail(x)
[1] 995 996 997 998 999 1000
Hay una variedad de funciones para obtener ayuda:
help(matrix) # Ayuda sobre la función matrix()?matrix # Lo mismoexample(matrix) # Mostrar un ejemplo de la función matrix()apropos("matrix") # Listar todas las funciones que contienen la cadena "matrix"# Obtener viñetas de los paquetes instaladosvignette() # Mostrar las viñetas disponiblesvignette("xts") # Mostrar una viñeta específica
Operadores en R: Los operadores aritméticos incluyen +, -, *, /, ^ y los operadores lógicos >, >=, ==, !=.
R ofrece una amplia variedad de tipos de datos, incluyendo escalares, vectores, matrices, marcos de datos y listas.
Vectores
Un vector es simplemente una colección de varias variables del mismo tipo (numéricas, de caracteres, lógicas, etc.).
Haga referencia a los elementos de un vector utilizando sub índices:
a[2] # 2do elemento del vector
[1] 2
a[c(2, 4)] # 2do y 4to elemento del vector
[1] 2 6
Tenga en cuenta que en R los vectores no son vectores columna ni vectores fila; no tienen orientación. Si se desea un vector columna, este es en realidad una matriz.
También es importante diferenciar la multiplicación elemento por elemento * del producto interno %*% y el producto externo %o%:
x <-c(1, 2)y <-c(10, 20)x * y
[1] 10 40
x %*% y
[,1]
[1,] 50
t(x) %*% y
[,1]
[1,] 50
x %o% y
[,1] [,2]
[1,] 10 20
[2,] 20 40
Los elementos de un vector se pueden nombrar así:
names(y)
NULL
names(y) <-c("convex", "optimization")y # lo mismo que imprimir (y)
convex optimization
10 20
str(y) # ver la estructura de y
Named num [1:2] 10 20
- attr(*, "names")= chr [1:2] "convex" "optimization"
length(y) # podemos obtener la longitud
[1] 2
Matrices
Una matriz es un conjunto bidimensional de varias variables del mismo tipo (numéricas, de caracteres, lógicas, etc.).
Podemos crear fácilmente una matriz con matrix():
# generar matriz numérica de 5 x 4x <-matrix(1:20, nrow =5, ncol =4)x
Un marco de datos es más general que una matriz, ya que las diferentes columnas pueden tener distintos modos (numérico, de caracteres, factorial, etc.).
d <-c(1, 2, 3, 4)e <-c("red", "white", "red", NA)f <-c(TRUE, TRUE, TRUE, FALSE)datos <-data.frame(d, e, f)names(datos) <-c("ID", "Color", "Passed") # nombres de variablesdatos
ID Color Passed
1 1 red TRUE
2 2 white TRUE
3 3 red TRUE
4 4 <NA> FALSE
str(datos)
'data.frame': 4 obs. of 3 variables:
$ ID : num 1 2 3 4
$ Color : chr "red" "white" "red" NA
$ Passed: logi TRUE TRUE TRUE FALSE
Hay varias formas de identificar los elementos de un marco de datos:
datos[c(1, 3)] # columnas 1,3 del marco de datos
ID Passed
1 1 TRUE
2 2 TRUE
3 3 TRUE
4 4 FALSE
datos[c("ID", "Color")] # columnas ID y Color del marco de datos
ID Color
1 1 red
2 2 white
3 3 red
4 4 <NA>
datos["ID"] # seleccionar ID de columna
ID
1 1
2 2
3 3
4 4
datos$ID # extrae el ID de la variable en el marco de datos (como un vector), como datos[["ID"]]
[1] 1 2 3 4
Los marcos de datos en R son muy potentes y versátiles. Se utilizan comúnmente en aprendizaje automático, donde cada fila representa una observación y cada columna una variable (cada variable puede ser de diferentes tipos).
En aplicaciones financieras, trabajamos principalmente con series temporales multivariadas, que pueden considerarse como una matriz o un marco de datos, pero con algunas particularidades: cada fila representa una observación, pero en un orden específico (indexada correctamente con fechas u horas) y cada columna corresponde al mismo tiempo (numérico). Para series temporales multivariadas, exploraremos más adelante la clase xts, que es más apropiada que las matrices o los marcos de datos.
Listas
Una lista es una colección ordenada de objetos (componentes) de (posiblemente) diferentes tipos. Una lista permite agrupar diversos objetos (posiblemente no relacionados) bajo un mismo nombre.
# Una lista con 4 componentes: una cadena, un vector numérico, una matriz y un escalarw <-list(name ="Esteban", numeros =c(1:10), matriz =matrix(NA, 3, 3), edad =30)w
$name
[1] "Esteban"
$numeros
[1] 1 2 3 4 5 6 7 8 9 10
$matriz
[,1] [,2] [,3]
[1,] NA NA NA
[2,] NA NA NA
[3,] NA NA NA
$edad
[1] 30
str(w)
List of 4
$ name : chr "Esteban"
$ numeros: int [1:10] 1 2 3 4 5 6 7 8 9 10
$ matriz : logi [1:3, 1:3] NA NA NA NA NA NA ...
$ edad : num 30
Funciones útiles
length(object) # número de elementos o componentes de un vectorstr(object) # estructura de un objetoclass(object) # clase o tipo de un objetonames(object) # nombresc(object, object, ...) # combinar objetos en un vectorcbind(object, object, ...) # combinar objetos como columnasrbind(object, object, ...) # combinar objetos como filasobject # imprimir el objetoprint(object) # imprimir el objetols() # listar los objetos actualesrm(object) # eliminar un objeto
Gráficos
Base de R
Las funciones de gráficos base/nativas en R son bastante simples y pueden no ser tan atractivas como se desea:
set.seed(1)x <-rnorm(1000) # generar números aleatorios normalesx <-cumsum(x) # paseo aleatorioplot(x, type ="l", col ="blue", main ="Paseo aleatorio", xlab ="Tiempo", ylab ="Precio logarítmico")lines(cumsum(rnorm(1000)), col ="red")
Para múltiples gráficos:
par(mfrow =c(2, 2)) # define una matriz de gráficos 2x2plot(cumsum(rnorm(1000)), type ="l", ylab ="x1")plot(cumsum(rnorm(1000)), type ="l", ylab ="x2")plot(cumsum(rnorm(1000)), type ="l", ylab ="x3")plot(cumsum(rnorm(1000)), type ="l", ylab ="x4")
par(mfrow =c(1, 1)) # establece el gráfico único predeterminado
Hay dos paquetes muy recomendados para realizar gráficos: ggplot2 y Plotly.
El paquete Plotly crea gráficos interactivos con calidad de publicación. Ejemplos de cómo crear gráficos de líneas, de dispersión, de áreas, de barras, de barras de error, de caja, histogramas, mapas de calor, subgráficos, ejes múltiples y gráficos 3D (basados en WebGL).
set.seed(123)y1 <-cumsum(rnorm(1000))y2 <-cumsum(rnorm(1000))y3 <-cumsum(rnorm(1000))x <-1:1000plot_ly() %>%add_lines(x = x, y = y1, name ="line 1", line =list(color ="blue", width =2)) %>%add_lines(x = x, y = y2, name ="line 2", line =list(color ="green", width =2)) %>%add_lines(x = x, y = y3, name ="line 3", line =list(color ="purple", width =2)) %>%layout(title ="Paseos aleatorios",xaxis =list(title ="T"),yaxis =list(title ="Precio logarítmico"),legend =list(x =1, y =1, xanchor ="right", yanchor ="top"))
Como se mencionó anteriormente, en finanzas trabajamos principalmente con series temporales multivariadas que pueden considerarse matrices donde cada fila es una observación en un orden específico (indexada correctamente con fechas u horas) y todas las columnas son del mismo tiempo (numérico) correspondiente a diferentes activos. Se podría simplemente usar un objeto de la clase matrix o data.frame. Sin embargo, existe una clase muy práctica (del paquete xts) diseñada específicamente para ese propósito: xts (de hecho, es la culminación de una larga trayectoria de desarrollo de otras clases como ts, fts, mts, irts, tseries, timeSeries y zoo).
Creación de objetos xts
Se pueden convertir fácilmente los datos de una serie temporal existente en xts con as.xts():
library(xts)data(sample_matrix) # carga algunos datos del paquete xtsclass(sample_matrix)
La diferencia más notable en el comportamiento de los objetos xts se evidencia en el uso del operador “[”. Mediante una notación especial, se pueden usar cadenas de tipo fecha para extraer datos según el índice de tiempo. Al aumentar el nivel de detalle temporal, es posible crear subconjuntos del objeto por año, semana, días o incluso segundos.
El argumento i (fila) del operador de subconjunto “[”, además de aceptar valores numéricos para la indexación, también puede ser una cadena de caracteres, un objeto basado en el tiempo o un vector de ambos. El formato debe especificarse a la izquierda con respecto al formato de tiempo estándar ISO:8601 “AAAA-MM-DD HH:MM:SS”. Esto significa que para extraer un mes en particular, también es necesario especificar el año completo.
Para identificar una hora en particular, por ejemplo, todas las observaciones en la octava hora del 1 de enero de 2007, también se necesitaría incluir el año, mes y día completos; por ejemplo, “2007-01-01 08”. También es posible solicitar explícitamente un rango de horas mediante este subconjunto basado en índices, utilizando el separador de rangos recomendado por ISO, “/”. La forma básica es “desde/hasta”, donde tanto “desde” como “hasta” son opcionales. Si falta alguno de los lados, se interpreta como una solicitud para recuperar datos desde el principio o hasta el final del objeto de datos.
Otra ventaja de este método es que las horas exactas de inicio y fin no tienen por qué coincidir con los datos subyacentes: se devolverá la observación disponible más cercana dentro del período solicitado.
El siguiente ejemplo muestra cómo extraer el mes completo de marzo de 2007:
Otras herramientas xts que permiten la creación de subconjuntos son las funciones first y last. Siguiendo el ejemplo de head y tail del paquete recomendado utils, permiten la creación de subconjuntos basados en cadenas, sin obligar al usuario a ajustarse a las especificaciones del índice de tiempo. Aquí se muestra la primera semana de los datos:
…y aquí están los primeros 3 días de la última semana de datos.
first(last(matrix_xts,"1 week"),"3 days")
Open High Low Close
2007-06-25 47.20471 47.42772 47.13405 47.42772
2007-06-26 47.44300 47.61611 47.44300 47.61611
2007-06-27 47.62323 47.71673 47.60015 47.62769
Si bien la capacidad de subconjuntos mencionada anteriormente hace que la clase temporal elegida para el índice sea menos relevante, es un factor que conviene controlar.
Para ello, xts ofrece funciones para indexar según cualquiera de las clases temporales actuales. Estas incluyen Date, POSIXct, chron, yearmon, yearqtr y timeDate. Se puede acceder al índice mediante los genéricos zoo extendidos a xts: index y la función de reemplazo index<-.
También es posible consultar y establecer directamente la clase de índice de un objeto xts mediante las funciones tclass y tclass<-, respectivamente.
La conversión temporal, que genera un nuevo objeto con la clase de índice solicitada, se puede realizar mediante la función convertIndex.
Finalmente, es sencillo combinar diferentes objetos xts en uno con múltiples columnas y alineados correctamente por el índice de tiempo con merge() o simplemente el más estándar cbind() (que llama a merge()):
An xts object on 2007-01-02 / 2007-06-30 containing:
Data: double [180, 2]
Columns: Open, Close
Index: Date [180] (TZ: "UTC")
Herramientas adicionales
Calcular periodicidad: La función periodicity proporciona un resumen rápido de la periodicidad subyacente de los objetos de series temporales:
periodicity(matrix_xts)
Daily periodicity from 2007-01-02 to 2007-06-30
Encontrar puntos finales por tiempo: Otro problema común con los datos de series temporales es la identificación de los puntos finales con respecto al tiempo. A menudo es necesario dividir los datos en intervalos horarios o mensuales para calcular alguna estadística. Una simple llamada a endpoints ofrece un vector rápido de valores adecuado para crear subconjuntos de un conjunto de datos. Tenga en cuenta que el primer elemento es cero, que se utiliza para delimitar el final.
Cambiar la periodicidad: Uno de los tipos de datos más comunes en finanzas son los datos OHLC (Apertura-Máximo-Mínimo-Cierre). A menudo es necesario cambiar la periodicidad de estos datos a algo más burdo, por ejemplo, tomar datos diarios y agregarlos a semanales o mensuales. Con to.period y las funciones contenedoras relacionadas, es una propuesta sencilla.
# cambiando el índice a algo más apropiadoto.monthly(matrix_xts)
matrix_xts.Open matrix_xts.High matrix_xts.Low matrix_xts.Close
Jan 2007 50.03978 50.77336 49.76308 50.22578
Feb 2007 50.22448 51.32342 50.19101 50.77091
Mar 2007 50.81620 50.81620 48.23648 48.97490
Apr 2007 48.94407 50.33781 48.80962 49.33974
May 2007 49.34572 49.69097 47.51796 47.73780
Jun 2007 47.74432 47.94127 47.09144 47.76719
Aplicar una función periódicamente: A menudo es deseable poder calcular una estadística específica o evaluar una función en un conjunto de períodos de tiempo no superpuestos. Con la familia de funciones period.apply es bastante sencillo. Los siguientes ejemplos ilustran una aplicación sencilla de la función max a nuestros datos de ejemplo:
# la función general, llama internamente a sapplyperiod.apply(matrix_xts[, "Close"], INDEX =endpoints(matrix_xts), FUN = max)
Además de apply.monthly, existen envoltorios para otros intervalos de tiempo comunes, como apply.daily, apply.weekly, apply.quarterly y apply.yearly. Las funciones optimizadas actuales incluyen period.max, period.min, period.sum y period.prod.
El paquete quantmod está diseñado para ayudar al operador cuantitativo en el desarrollo, prueba e implementación de modelos de trading basados en estadísticas.
Obtención de datos: La función más útil de quantmod es getSymbol(), que permite cargar fácilmente datos desde diversos sitios web como YahooFinance, GoogleFinance, FRED, etc.:
library(quantmod)getSymbols(c("AAPL", "BLK"), from ="2022-01-01", to ="2025-04-30", src ="yahoo")
[1] "AAPL" "BLK"
str(AAPL)
An xts object on 2022-01-03 / 2025-04-29 containing:
Data: double [833, 6]
Columns: AAPL.Open, AAPL.High, AAPL.Low, AAPL.Close, AAPL.Volume ... with 1 more column
Index: Date [833] (TZ: "UTC")
xts Attributes:
$ src : chr "yahoo"
$ updated: POSIXct[1:1], format: "2025-06-05 23:37:00"
Conceptos básicos OHLCV: Los datos suelen incluir los precios de apertura, máximo, mínimo, cierre, cierre ajustado y volumen. Existen numerosas funciones útiles para extraer estos datos, como Op(), Hi(), Lo(), Cl(), Ad(), Vo(), así como para realizar diversas consultas como is.OHLC(), has.Vo(), etc.
getSymbols("GS") # Goldman OHLC de Yahoo
[1] "GS"
is.OHLC(GS) # ¿Los datos contienen al menos OHL y C?
Gráficos con quantmod: La función chartSeries() es una herramienta útil para visualizar series temporales financieras de una forma familiar para muchos profesionales: gráficos de líneas, así como gráficos de barras y velas OHLC.
Existen envoltorios prácticos para estos diferentes estilos (lineChart(), barChart() y candleChart()), aunque chartSeries() contribuye significativamente a gestionar automáticamente los datos de la forma más adecuada.
chartSeries(AAPL["2024-8/2024-12"], name ="AAPL")
# Añadir multicolor y cambiar el fondo a blancocandleChart(AAPL["2024-8/2024-12"], name ="AAPL", multi.col =TRUE, theme ="white")
# Ahora semanalmente con velas de colores personalizados usando la función quantmod to.weeklychartSeries(to.weekly(AAPL), up.col ="white", dn.col ="blue", name ="AAPL")
Herramientas de gráficos de análisis técnico: Se pueden añadir estudios de análisis técnico del paquete TTR a los gráficos anteriores:
Seguidamente, podemos estimar con parámetros muy sencillos el cálculo una media móvil simple y media móvil exponencial, con las funciones SMA() y EMA(), respectivamente.
candleChart(AAPL["2024-8/2024-12"], name ="AAPL", multi.col =TRUE, theme ="white", TA="addVo();addSMA(n = 20, col = 'red'); addEMA(n = 50, col = 'blue')")
chartSeries(AAPL["2024"], name ="AAPL",TA ="addMACD(); addBBands()")
chartSeries(AAPL["2024"], name ="AAPL", TA ="addMomentum(); addEMA(); addRSI()")
chartSeries(AAPL["2024"], theme ="white", type ="candles", name ="AAPL", TA ="addMomentum(); addEMA(); addRSI()")
El paquete TTR (Reglas Técnicas de Trading) está diseñado para el análisis técnico tradicional y la creación de gráficos.
Medias Móviles: Se pueden calcular fácilmente las medias móviles (https://www.rdocumentation.org/packages/TTR/versions/0.24.4/topics/SMA)
SMA.10<-SMA(Cl(AAPL), n =5)head(SMA.10, 10)
SMA
2022-01-03 NA
2022-01-04 NA
2022-01-05 NA
2022-01-06 NA
2022-01-07 176.160
2022-01-10 174.196
2022-01-11 173.272
2022-01-12 173.394
2022-01-13 173.432
2022-01-14 173.612
EMA.30<-EMA(Cl(AAPL), n =30)plot(cbind(Cl(AAPL), EMA.30), legend.loc ="topleft", main ="Media Móvil Exponencial de 30 días")
Bandas de Bollinger: Las bandas de Bollinger son una técnica muy popular. Muchos traders creen que cuanto más se acercan los precios a la banda superior, más sobrecomprado está el mercado, y cuanto más se acercan los precios a la banda inferior, más sobrevendido es el mercado. John Bollinger tiene un conjunto de 22 reglas a seguir al usar las bandas como sistema de negociación.
plot(bb20, main ="Bandas Bollinger de 2 desviaciones estándar")
Indicador de fuerza relativa (RSI): Este indicador es un oscilador que mide la velocidad y el cambio de los movimientos del precio. Su popularidad se debe a su capacidad para identificar condiciones de sobrecompra y sobreventa en el mercado, ofreciendo señales valiosas para la toma de decisiones en trading.
RSI <-RSI(Cl(AAPL), n =14)plot(cbind(Cl(AAPL), RSI), legend.loc ="topleft", main ="RSI de 14 días")
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec AAPL.Close
2022 2.6 0.2 -1.8 -3.7 -0.5 -1.8 3.3 -1.1 -3.0 -1.5 4.9 0.2 -2.6
2023 0.9 -0.3 1.6 0.8 0.0 2.3 0.3 0.1 0.3 0.3 0.3 -0.5 6.1
2024 -1.9 -0.4 -1.1 -1.8 0.5 -1.6 1.5 -0.3 2.3 -1.8 1.0 -0.7 -4.4
2025 -0.7 1.9 1.9 0.5 NA NA NA NA NA NA NA NA 3.7
BLK.Close
2022 -10.9
2023 5.1
2024 2.2
2025 4.6
table.Stats(retornos)
AAPL.Close BLK.Close
Observations 832.0000 832.0000
NAs 0.0000 0.0000
Minimum -0.0925 -0.0771
Quartile 1 -0.0088 -0.0096
Median 0.0010 0.0003
Arithmetic Mean 0.0004 0.0002
Geometric Mean 0.0002 0.0000
Quartile 3 0.0101 0.0088
Maximum 0.1533 0.1347
SE Mean 0.0006 0.0006
LCL Mean (0.95) -0.0009 -0.0010
UCL Mean (0.95) 0.0016 0.0014
Variance 0.0003 0.0003
Stdev 0.0186 0.0177
Skewness 0.5363 0.5524
Kurtosis 7.4128 6.3950
table.DownsideRisk(retornos)
AAPL.Close BLK.Close
Semi Deviation 0.0130 0.0122
Gain Deviation 0.0135 0.0132
Loss Deviation 0.0128 0.0117
Downside Deviation (MAR=210%) 0.0176 0.0170
Downside Deviation (Rf=0%) 0.0128 0.0121
Downside Deviation (0%) 0.0128 0.0121
Maximum Drawdown 0.3343 0.4210
Historical VaR (95%) -0.0295 -0.0267
Historical ES (95%) -0.0418 -0.0381
Modified VaR (95%) -0.0245 -0.0238
Modified ES (95%) -0.0245 -0.0238
Los gráficos de rendimiento son muy útiles para evaluar el rendimiento de una estrategia de trading. El paquete PerformanceAnalytics ofrece una amplia variedad de gráficos, como gráficos de líneas, gráficos de dispersión, gráficos de barras y gráficos de caja.
charts.PerformanceSummary(retornos, wealth.index =TRUE, main ="Rendimiento de compra y retención")
chart.Boxplot(retornos, main ="Boxplot de retornos")
chart.Histogram(retornos, main ="Histograma de retornos", note.cex =0.5, methods =c("add.density", "add.normal", "add.risk"))
chart.RiskReturnScatter(retornos, main ="Riesgo vs Retorno", col ="blue")
PortfolioAnalytics es un paquete de R que proporciona soluciones numéricas para problemas de cartera con restricciones y conjuntos de objetivos complejos. El objetivo del paquete es ayudar a profesionales e investigadores a resolver problemas de optimización de cartera con restricciones y objetivos complejos que reflejen aplicaciones del mundo real.
data(edhec)class(edhec)
[1] "xts" "zoo"
ret_edhec <-tail(edhec, 60) # Extraer los últimos 5 añosrange(index(edhec)) # Fechas de inicio y fin de `edhec`
[1] "1997-01-31" "2021-05-31"
range(index(ret_edhec)) # Fechas de inicio y fin de ret_edhec
[1] "2016-06-30" "2021-05-31"
# names(edhec) # Los nombres de `edhec` son largos, por lo que se recomienda usar nombres más cortos.colnames(ret_edhec) <-c("CA", "CTAG", "DS", "EM", "EMN", "ED","FIA", "GM", "LSE", "MA", "RV", "SS", "FF")print(head(ret_edhec, 5))
Cuando un operador diseña una estrategia de cartera, lo primero que debe hacer es realizar un backtest. El backtesting es el proceso mediante el cual se pone a prueba la estrategia de cartera utilizando los datos históricos del mercado disponibles.
Un enfoque común consiste en realizar un único backtesting con los datos históricos existentes y luego trazar gráficos para extraer conclusiones.
Esto es un grave error. Realizar un único backtesting no es representativo, ya que solo representa una conclusión, y definitivamente se sobreajustará la estrategia probada si se ajustan los parámetros o se realizan comparaciones de carteras. La sección 1 de este capítulo del libro sobre backtesting ilustra los peligros del backtesting.
El paquete portfolioBacktest realiza múltiples pruebas retrospectivas de carteras de forma automatizada y en ventanas móviles, tomando datos aleatoriamente de diferentes mercados, períodos de tiempo y universos bursátiles. A continuación, se muestra un ejemplo sencillo de uso con la cartera con ponderación equitativa:
Paso 1: Cargar el paquete y los conjuntos de datos (debería descargar muchos más conjuntos de datos; consulte la viñeta)
data("dataset10")
Paso 2: – Define tu propia cartera
my_portfolio <-function(dataset, ...) { prices <- dataset$adjusted N <-ncol(prices)return(rep(1/N, N))}
Paso 3:Realizar una prueba retrospectiva (el conjunto de datos 10 solo contiene 10 conjuntos de datos con fines ilustrativos).
bt <-portfolioBacktest(my_portfolio, dataset10)
Paso 4: Verifique el rendimiento de su cartera
backtestSummary(bt)$performance
fun1
Sharpe ratio 1.476203e+00
max drawdown 8.937890e-02
annual return 1.594528e-01
annual volatility 1.218623e-01
Sortino ratio 2.057677e+00
downside deviation 8.351402e-02
Sterling ratio 2.122653e+00
Omega ratio 1.295090e+00
VaR (0.95) 1.101934e-02
CVaR (0.95) 1.789425e-02
rebalancing period 1.000000e+00
turnover 8.641594e-03
ROT (bps) 7.334458e+02
cpu time 1.538462e-03
failure rate 0.000000e+00
R Scripts
Una forma sencilla de usar R es escribir los comandos uno por uno en la ventana de comandos. Sin embargo, esto se vuelve rápidamente incómodo y es necesario escribir scripts. En RStudio, se puede simplemente crear un nuevo script de R o abrir un archivo .R, donde los comandos se escriben en el mismo orden en que se ejecutarán posteriormente (este punto es fundamental).
Con el script de R abierto, se puede ejecutar línea por línea (haciendo clic en un botón o con un atajo de teclado) o generar el archivo R completo (también haciendo clic en un botón o con un atajo de teclado).
Como alternativa, también se puede generar el archivo R desde la línea de comandos con source("filename.R"), pero primero hay que asegurarse de estar en la carpeta correcta (para ver y configurar el directorio actual, se utilizan los comandos getwd() y setwd("folder_name")).
El uso del comando source("filename.R") es muy conveniente cuando uno tiene una biblioteca de funciones o datos útiles que se necesitan antes de la ejecución de otro script principal de R.
R Markdown
Otro tipo importante de scripts es el formato R Markdown (con extensión de archivo .Rmd). Es un formato extremadamente versátil que permite la combinación de texto formateable, matemáticas basadas en códigos Latex, código R (o cualquier otro lenguaje) y la posterior inclusión automática de los resultados de la ejecución del código (gráficos, tablas o cualquier otro tipo de salida).
Este tipo de formato también existe para Python y se conoce generalmente como Jupyter Notebooks. Recientemente se ha vuelto clave en el contexto de la investigación reproducible (ya que cualquiera puede ejecutar el archivo fuente .Rmd y reproducir todos los gráficos y la salida). Este documento que está leyendo es un ejemplo de un script de R Markdown.
Los archivos de R Markdown se pueden crear o abrir directamente desde RStudio. Para compilar el archivo fuente .RMD, simplemente haga clic en el botón “Knit” y se generará automáticamente un HTML tras ejecutar todos los fragmentos de código (también se pueden generar otros formatos, como PDF).
A continuación, se muestra una plantilla sencilla de encabezado/cuerpo que puede utilizarse para preparar proyectos/informes para este curso:
---
title: "Hello R Markdown"
author: "Awesome Me"
date: "2018-09-05"
output: html_document
---
# Resumen de este documento aquí.# Primer encabezado## Primer subencabezado## Segundo subencabezado# Segundo encabezado# - Lista de viñetas 1# - Lista de viñetas 2# + más 2a# + más 2b# Este es un enlace: [Tutorial de RMarkdown](http://rmarkdown.rstudio.com)
Para obtener más información sobre el formato R Markdown: