Una introducción conceptual breve a la programación en R

Sintaxis

# Los comentarios y las anotaciones se incorporan utilizaneo el signo "#" al inicio de la linea

print("Hola!")  # hace llamado a ejecutar el contenido indicado entre corchetes "()"
## [1] "Hola!"
5 + 5  # las operaciones artimeticas se ejecturan de manera directa
## [1] 10
# Asignación de variables
x <- "Hola"
y <- "!"
print(x)
## [1] "Hola"
print(paste(x,y)) # el comando paste, pega contenidos/variables
## [1] "Hola !"

Tipos de data

* numeric - (10.5, 55, 787)
* integer - (1L, 55L, 100L, where the letter "L" declares this as an integer)
* complex - (9 + 3i, where "i" is the imaginary part)
* character (a.k.a. string) - ("k", "R is exciting", "FALSE", "11.5")
* logical (a.k.a. boolean) - (TRUE or FALSE)
# numeric
x <- 10.5
class(x)
## [1] "numeric"
# integer
x <- 1000L
class(x)
## [1] "integer"
# complex
x <- 9i + 3
class(x)
## [1] "complex"
# character/string
x <- "R es cool"
class(x)
## [1] "character"
# logical/boolean
x <- TRUE
class(x) 
## [1] "logical"

Estructuras de datos

* vectores
* matrices
* data frames
* arreglos
* listas
# VECTORES
# es una combinacion numerica de una dimensión
# cada elemento puede ser accedido de manera directa haciendo llamada al vector e indicando su orden númerico
serie <- c(5,10,25,30,35,40)
str(serie)
##  num [1:6] 5 10 25 30 35 40
serie[3] # muestra 25
## [1] 25
# MATRICES
# es un set bi-dimensional de data
# puede ser numerico o de caracteres, pero nunca mixto
# para acceder a un elemento, es necesario especificar su respectiva fila (primero) y columna (segundo)
# las matrices tambien pueden hacer llamada a nombres de fila y columna
mat <- matrix(c(1,2,3,4), nrow = 2, ncol = 2)
str(mat)
##  num [1:2, 1:2] 1 2 3 4
mat[1,2] # formato: matrix[#fila, #columna]. Output: fila 1, columna 2
## [1] 3
# DATA FRAME
# al igual que la matriz, es un set bi-diensional
# la diferencia: puede almacenar distintas estructuras de datos en cada columna
# es la estructura de datos mas flexible, y frecuentemente utilizada
df <- data.frame (
  Entrenamiento = c("Fuerza", "Resistencia", "Otro"),
  Presion = c(100, 150, 120),
  Duracion = c(60, 30, 45)
)
df 
##   Entrenamiento Presion Duracion
## 1        Fuerza     100       60
## 2   Resistencia     150       30
## 3          Otro     120       45
# Existen tres formas para acceder a un elemento
# 1: llamada numerica
# 2: llamada por nombre - compatible con el formato matricial
# 3: llamada por nombre - vectorizando columnas
#    en este formato, las filas se acceden como si fueran vectores. esta es incompatible con el formato de matriz!
df[,1] # presenta todos los registros de la columna 1
## [1] "Fuerza"      "Resistencia" "Otro"
df[,'Entrenamiento'] # presenta todos los registros de la columna "Entrenamiento"
## [1] "Fuerza"      "Resistencia" "Otro"
df$Entrenamiento[1] # presenta el primer registro de la columna "Entrenamiento"
## [1] "Fuerza"
# ARREGLOS
# es un set multidimensional de data
# este arreglo crea una sola dimensión con valores en el rango 1 hasta 24
arreglo.simple <- c(1:24)
arreglo.simple
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
# para un arreglo multidimensional, las dimensiones se acceden de la siguiente forma:
# arreglo[#dimension1, #dimenssion2, #dimensionN]
arreglo.multidimensional <- array(arreglo.simple, dim = c(4, 3, 2))
arreglo.multidimensional[,,1]
##      [,1] [,2] [,3]
## [1,]    1    5    9
## [2,]    2    6   10
## [3,]    3    7   11
## [4,]    4    8   12
# LISTAS
# las listas son las estructuras mas flexibles.
# puede almacenar, literalmente, cualquier cosa
lista <- list(serie,
              mat,
              arreglo.simple,
              df)
lista
## [[1]]
## [1]  5 10 25 30 35 40
## 
## [[2]]
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## 
## [[3]]
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
## 
## [[4]]
##   Entrenamiento Presion Duracion
## 1        Fuerza     100       60
## 2   Resistencia     150       30
## 3          Otro     120       45

Funciones matematicas y estadisticas

# Math
min(5,1)
## [1] 1
max(5,1)
## [1] 5
abs(-100)
## [1] 100
floor(9.5)
## [1] 9
ceiling(9.5)
## [1] 10
sqrt(252)
## [1] 15.87451
serie <- c(5,10,25,30,35,40,45,50,55,60,75,80,500)
mean(serie) # media aritmetica
## [1] 77.69231
sd(serie) # desviación estándar
## [1] 128.8348
quantile(serie,0.25) # percentile
## 25% 
##  30

Fechas y tiempo

Fechas y formatos

fecha <- as.Date('2022-10-28')
fecha
## [1] "2022-10-28"
fecha.formateada <- as.Date('10/28/2022', format='%m/%d/%Y')
fecha.formateada
## [1] "2022-10-28"

Manejo de condiciones, iteracion

  • IF, ELSE IF, ELSE
  • WHILE
  • FOR
# IF, ELSE IF
# El IF es la forma de loop mas sencilla
# controla por la condicion que se desea
a <- 33
b <- 200

# IF LOOP
if (b > a) {
  print("b es mayor que a")
} 
## [1] "b es mayor que a"
# ELSE IF, ELSE
# en la practica, es dificil cubrir todas las posibilidades y cada uno de los IFs
# por lo tanto, R permite dar una solucion que sea simplemente diferente a lo deseado
a <- 200
b <- 33

if (b > a) {
  print("b es mayor que a")
} else if (a == b) {
  print("a y b son iguales")
} else {
  print("a es mayor que b")
}
## [1] "a es mayor que b"
# WHILE
# Ejecuta el bloque de codigo de manera repetitiva mientras se cumple la condicion
i <- 1
while (i < 6) {
  print(i)
  i <- i + 1
} 
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
# FOR
# Ejecuta una asignacion de manera iterativa y de manera secuencial
# Este tipo de operativos son muy importantes!
for (x in 1:10) {
  print(x)
} 
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
## [1] 10

Secuencias y repeticiones

n <- 5
1:n # secuencia
## [1] 1 2 3 4 5
seq_len(n) # secuencia, con manejo de valores nulos
## [1] 1 2 3 4 5
rep(1,n) # repite el valor n-veces
## [1] 1 1 1 1 1

Funciones

# Las funciones se utilizan para aplicar procedimientos repetitivos de manera eficiente
# frecuentemente son combinadas con la iteracion para procesar datos
# utilizan condiciones definidas en forma de parametro para procesar respuestas
mi.funcion <- function(x) { 
    print(x)
} 

x <- "Hola!"
mi.funcion(x)
## [1] "Hola!"

Ejercicio práctico

VaR

  • VaR historico con un loop
  • VaR historico con una función
library(quantmod)
library(xts)
library(PerformanceAnalytics)

# El codigo identifica varias compañias del S&P500, descarga la data de precios, transforma las diferencias
# y computa el VaR Historico

# define los nombres de compañías que serán analizadas
symbol <- c("AAPL","AMZN","TSLA","GOOG","NFLX","META") 

# 01: VaR historico con un loop
# define la lista donde se van a guardar los datos procesados.
# en cada objeto de la lista será almacenado 1 data frame con el analisis.
lista.activos <- list()
for(i in 1:length(symbol)){
  # la iteración va corriendo el analisis para cada elemento definido en el vector "symbol"
  # termina cuanto se alcanza el último elemento (en este caso 6)
  # si se agregan nuevos elementos o se restan, el loop sigue funcionando.
  
  # descarga la data desde yahoo finance
  data <- getSymbols(symbol[i], src = 'yahoo', from = '2010-01-01', auto.assign = FALSE) 
  data$var.diaria <- CalculateReturns(Cl(data), method = "discrete") 
  
  # VAR HISTORICO
  # computa VaR al 5% de confianza, c-VaR
  VaR.historico.05 <- quantile(na.omit(data$var.diaria),0.05)
  
  # coloca el cVaR en una columna de la tabla para fines de poder hacer el plot
  data$VaR.historico.05 <- VaR.historico.05 
  
  # identifica las instancias donde el VaR fue rebasado
  excesos.VaR.historico <- which(data$var.diaria < VaR.historico.05)
  cVaR.historico.05 <- mean(data$var.diaria[excesos.VaR.historico])
  
  # coloca el cVaR en una columna de la tabla para fines de poder hacer el plot
  data$cVaR.historico.05 <- cVaR.historico.05
  
  # almacena en la lista el análisis 
  lista.activos[[i]] <- data
  
}

# muestra las 10 ultimas observaciones de AAPL, solo columnas que contienen variacion diaria, VaR, y cVaR
tail(lista.activos[[1]][,c('var.diaria','VaR.historico.05','cVaR.historico.05')],10)
##             var.diaria VaR.historico.05 cVaR.historico.05
## 2022-10-24  0.01480270      -0.02700189        -0.0409114
## 2022-10-25  0.01933756      -0.02700189        -0.0409114
## 2022-10-26 -0.01962708      -0.02700189        -0.0409114
## 2022-10-27 -0.03046537      -0.02700189        -0.0409114
## 2022-10-28  0.07555250      -0.02700189        -0.0409114
## 2022-10-31 -0.01541036      -0.02700189        -0.0409114
## 2022-11-01 -0.01754273      -0.02700189        -0.0409114
## 2022-11-02 -0.03730498      -0.02700189        -0.0409114
## 2022-11-03 -0.04240498      -0.02700189        -0.0409114
## 2022-11-04 -0.00360023      -0.02700189        -0.0409114
# 02: VaR historico con una función
# Mas fácil y elegante. La función permite mayor flexibilidad en la aplicación repetitiva
calculo.VaR <- function(symbol,x){ 
  # argumento "symbol" es un parametro de la función que determina cual compañía será analizada
  # artumento "x" determina el percentil de la medición
  
  data <- getSymbols(symbol, src = 'yahoo', from = '2010-01-01', auto.assign = FALSE) 
  data$var.diaria <- CalculateReturns(Cl(data), method = "discrete") 
  resultado <- quantile(na.omit(data$var.diaria),x)
  resultado
}

# Prueba función
calculo.VaR(symbol[i],0.05)
##          5% 
## -0.03738219
# Aplicación loop para realizar una llamada iterativa.
for(i in 1:length(symbol)){
  # as.numeric: conviere el objeto en valores numericos eliminando fecha (formato de serie de tiempo)
  var <- as.numeric(calculo.VaR(symbol[i],0.05)) 
  print(paste(symbol[i],var))
}
## [1] "AAPL -0.0270018912391192"
## [1] "AMZN -0.0302542451709598"
## [1] "TSLA -0.0502154334074043"
## [1] "GOOG -0.0258321053857869"
## [1] "NFLX -0.0425964523886101"
## [1] "META -0.0373821882219519"

Lecturas de datos

# CSV
# la funcion read.csv lee archivos .CSV que son localizados a partir del directorio principal (getwd())
# el R permite lecutra de archivos a traves de la web. La funcion url() hace exactamente eso.

# Aquí se descarga el Indice GOBIXDR que puede ser accedido en la web de la Bolsa de Valores RD 
# https://bvrd.com.do/gobixdr/

gobix <- read.csv(url("https://www.bvrd.com.do/indice/Data/GobixDataIRP.csv")) # descarga
gobix <- gobix[,1:2] # se queda con dos primeras columnas
colnames(gobix)[1] <- "fecha" # renombra la columna 1
gobix$fecha <- lubridate::mdy(gobix[,1]) # la convierte en formato fechas mes-dia-año
gobix <- xts::as.xts(gobix[,-1], order.by=gobix$fecha) # convierte el formato en XTS
colnames(gobix)[1] <- "Close.GOBIX" # renombra la serie (indice al cierre del dia)

# visualiza los ultimos 20 dias.
tail(gobix,20)
##            Close.GOBIX
## 2022-10-10      106.95
## 2022-10-11      106.96
## 2022-10-12      106.81
## 2022-10-13      106.80
## 2022-10-14      106.79
## 2022-10-17      106.78
## 2022-10-18      106.78
## 2022-10-19      106.77
## 2022-10-20      106.76
## 2022-10-21      107.96
## 2022-10-24      107.94
## 2022-10-25      107.93
## 2022-10-26      105.23
## 2022-10-27      105.23
## 2022-10-28      105.22
## 2022-10-31      107.67
## 2022-11-01      107.66
## 2022-11-02      107.41
## 2022-11-03      107.17
## 2022-11-04      106.92
# VaR. Aplica el ejercicio del VaR historico visto en clase.
gobix$var.diaria <- CalculateReturns(Cl(gobix), method = "discrete") 

# VAR HISTORICO
# computa VaR al 5% de confianza, c-VaR
VaR.historico.05 <- quantile(na.omit(gobix$var.diaria),0.05)
gobix$VaR.historico.05 <- VaR.historico.05 

# identifica las instancias donde el VaR fue rebasado
excesos.VaR.historico <- which(gobix$var.diaria < VaR.historico.05)
# estima la media de los rebases (cola izquierda)
cVaR.historico.05 <- mean(gobix$var.diaria[excesos.VaR.historico])
gobix$cVaR.historico.05 <- cVaR.historico.05

# Visualización
# hace el plot de la serie historica
plot(Cl(gobix), main="GOBIX-DR comportamiento histórico", type="l", grid.col=NA)

# Plot de la volatilidad
plot.risk <- plot(gobix$var.diaria, main="Volatilidad diaria", lwd=1, grid.col=NA)
plot.risk <- lines(gobix$VaR.historico.05, on=1, col="red", lty=2, lwd=1) # marca el nivel del VaR al 5%.
plot.risk <- lines(gobix$cVaR.historico.05, on=1, col="red", lty=1, lwd=1) # marca el nivel del c-VaR al 5%.
plot.risk <- points(gobix$var.diaria[excesos.VaR.historico], col="red", pch=16, cex=0.6) # visualiza instancias de exceso
plot.risk

# histograma / PDF
hist(gobix$var.diaria,  breaks=64, freq=FALSE, col="grey", main="Histograma Volatiliad Realizada diaria", xlab="var % diaria")
abline(v=VaR.historico.05, col="red", lty=2, lwd=2)
abline(v=cVaR.historico.05, col="red", lty=1, lwd=2)

Graficos

Recursos: * R Cookbook * Una guia