Análisis de Retornos Financieros

Author

Julián Mauricio Fajardo, MsC en Actuaría y Finanzas

Published

December 19, 2024

LOS RETORNOS: MEDIDA DE RIESGO PARA ACTIVOS RIESGOSOS

Los retornos son una medida de riesgo neutral que es no dimensionada, es decir no es afectada ni por la magnitud, ni por la divisa en la que se presentan. Piense en dos activos: el SPY 500 (valor que ronda los 5000 USD) y la acción colombiana de ETB que pertenece al indice ICOLCAP que en los últimos dias ha tenido un valor que ronda los 100 COP. La diferencia entre ellas no solo está en la divisa representativa, sino en la magnitud de los valores. ¿Como obtenemos una medida que solo capture los rendimientos reales del activo riesgoso, independiente de estos valores?. La respuesta está en los retornos o rendimientos.

TIPOS DE RETORNOS

RETORNOS DISCRETOS

Los retornos discretos miden la variación en el precio de un activo durante un período específico. La fórmula para el retorno discreto, está dada por: \[ R_t = \frac{P_t - P_{t-1}}{P_{t-1}} \] Donde: - \(R_t\) es el retorno discreto. - \(P_t\) es el precio al final del período. - \(P_{t-1}\) es el precio al inicio del período.

RETORNOS CONTINUOS O LOGARITMICOS

El retorno logarítmico se calcula utilizando logaritmos naturales: \[ R_t = \ln\left(\frac{P_t}{P_{t-1}}\right) \] Donde: - \(R_t\) es el retorno logarítmico. - \(P_t\) es el precio al final del período. - \(P_{t-1}\) es el precio al inicio del período.

Si consideramos \(t \geq 1\), podemos afirmar que \(P_t\) es un proceso estocástico real, al igual que resulta siendo \(R_t\). Cada uno de ellos, tiene sus ventajas y desventajas a la hora de hacer análisis de rendimientos. Eso si, los retornos logaritmos tiene ventajas significativas, respecto a los retornos discretos. Por ejemplo:

  • Log-normalidad: Si asumimos que los precios se distribuyen log-normalmente, los retornos logarítmicos también se distribuyen normalmente.

  • Sumabilidad en el tiempo: Los retornos logarítmicos son aditivos en el tiempo, lo que facilita su uso en análisis y modelización.

  • Estabilidad numérica: La adición de pequeñas cantidades es más robusta numéricamente que la multiplicación de números pequeños.

En resumen, los retornos logarítmicos son preferibles en muchos casos debido a sus propiedades matemáticas y su aplicabilidad en análisis financiero.

EJEMPLO 1.

Considere dos activos riesgosos, cuyo precios historicos están dados a continuación en las listas del código que sigue, el primeros en USD (dólar americano) y el segundo en JPY (yen japonés). Haga un análisis gráfico comparativo de los retornos.

Listamos los precios y calculamos manualmente los retornos discretos:

Code
act1 <- c(120,134,139,124,130,112,128,138,132,148) ## en USD
act2 <- c(2340,2450,2400,2310,2390,2390,2480,2560,2500,2460) ## en JPY
r1 <- diff(act1)/act1 ## diff se usa para calcular las di¿frencias de los terminos de la lista
Warning in diff(act1)/act1: longer object length is not a multiple of shorter
object length
Code
r1 <- r1[1:9] # y aqui tomo los primeros 9 terminos de la lista anterior
r2 <- diff(act2)/act2
Warning in diff(act2)/act2: longer object length is not a multiple of shorter
object length
Code
r2 <- r2[1:9]

Y ahora calculamos los retornos continuos:

Code
rc1 <- NULL
for (i in 1:9){
  rc1[i] <- log(act1[i+1]/act1[i])
}
rc2 <- NULL
for (i in 1:9){
  rc2[i] <- log(act2[i+1]/act2[i])
}

A continuación veremos el comparativo entre los retornos discretos y los retornos continuos. Primero, los retornos promedio (\(\mu\))

Code
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Code
tabla1 <- data.frame(r1,r2,rc1,rc2)
media <- apply(tabla1, 2, mean)
media
         r1          r2         rc1         rc2 
0.028300888 0.006023321 0.023302281 0.005556713 

Y sus volatilidades (\(\sigma\)):

Code
volat <- apply(tabla1, 2, sd)
volat
        r1         r2        rc1        rc2 
0.10249855 0.03195572 0.10287797 0.03176967 
Code
### comparacion grafica
ggplot(tabla1, aes(x = 1:9, y = r1))+
  geom_line(color = "blue")+
  geom_line(y = rc1, color = "red")+
  labs(x = "Lista de retornos", y = "Retornos", title = "Comparación entre retornos discretos y continuos (activo 1)")+
  theme_minimal()

Aca se ve con claridad que si hay diferencia entre los dos tipos de retornos, pero estas son irrisorias, de manera tal que, podemos usar ambas para el mismo objetivo de analizar la rentabilidad de los activos. Eso si, teoricamente hablando, hay muchas mas ventajas en los retornos continuos, como ya se habia mencionado anteriormente.

Ahora veamos la comparación de los retornos logaritimicos de los dos activos:

Code
### comparacion grafica
ggplot(tabla1, aes(x = 1:9, y = rc1))+
  geom_line(color = "blue")+
  geom_line(y = rc2, color = "red")+
  labs(x = "Lista de retornos", y = "Retornos", title = "Comparación entre retornos continuos (activo 1 y activo 2)")+
  theme_minimal()

En la gráfica podemos ver con claridad la diferencia de los comportamientos en volatilidad. El activo 2 (en yen japonés) tiene cambios menos bruscos y mas moderados.

USO DE LOS PAQUETES PARA DETERMINACIÓN DE RETORNOS

Usaremos algunos de los paquetes de R para calcular los retornos logaritmicos de manera directa y no como se hizo al principio, programando con código. En el caso del paquete “tseries” usaremos la función “returns0”

Code
library(tseries)
Registered S3 method overwritten by 'quantmod':
  method            from
  as.zoo.data.frame zoo 
Code
library(timeSeries)
Loading required package: timeDate

Attaching package: 'timeSeries'
The following object is masked from 'package:dplyr':

    lag
The following objects are masked from 'package:graphics':

    lines, points
Code
library(quantmod)
Loading required package: xts
Loading required package: zoo

Attaching package: 'zoo'
The following object is masked from 'package:timeSeries':

    time<-
The following objects are masked from 'package:base':

    as.Date, as.Date.numeric

######################### Warning from 'xts' package ##########################
#                                                                             #
# The dplyr lag() function breaks how base R's lag() function is supposed to  #
# work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or       #
# source() into this session won't work correctly.                            #
#                                                                             #
# Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
# conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop           #
# dplyr from breaking base R's lag() function.                                #
#                                                                             #
# Code in packages is not affected. It's protected by R's namespace mechanism #
# Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning.  #
#                                                                             #
###############################################################################

Attaching package: 'xts'
The following objects are masked from 'package:dplyr':

    first, last
Loading required package: TTR
Code
rr1 <- returns0(act1) # aqui calculamos los retornos log del act 1
rr1 <- as.timeSeries(rr1) # aqui lo trasnformamos en una serie de tiempo

plot(rr1, col = "darkgreen", xlab = "Lista de retornos", ylab = "Retornos")

EJEMPLO 2.

Use la función get.hist.quote y la función de calculo de retornos para calcular la serie de tiempo de los retornos de la acción de Facebook y la de Netflix en las fechas desde el 1 de enero de 2023 hasta el 5 de julio de 2024.

Solución: Veamos el paso a paso de la solución para este ejemplo:

Code
### Usaremos los paquetes de R para DESCARGA DE INFO FINANCIERA DE 
# YAHOO FINANCE
ACT1 <- get.hist.quote(instrument = "META",# aqui colocas el token del instrumento
                       quote = 'AdjClose', # establece que informacion de la base requieres
                       start = "2023-01-01", # fecha de inicio de la descarga
                       end = "2024-07-05", #fecha final de la descarga
                       compression = "d")
time series starts 2023-01-03
time series ends   2024-07-03
Code
ACT1 <- as.timeSeries(ACT1) # lo colocamos en formato de serie de tiempo convencional
ACT2 <- get.hist.quote(instrument = "NFLX",# aqui colocas el token del instrumento
                       quote = 'AdjClose', # establece que informacion de la base requieres
                       start = "2023-01-01", # fecha de inicio de la descarga
                       end = "2024-07-05", #fecha final de la descarga
                       compression = "d")
time series starts 2023-01-03
time series ends   2024-07-03
Code
ACT2 <- as.timeSeries(ACT2) # aqui lo transformamos en una serie de tiempo

plot.ts(ACT1, col = "navy", main = "Precios Facebook")

Code
plot.ts(ACT2, col = "darkgreen", main = "Precios Netflix")

Code
rACT1 <- returns0(ACT1) # calculamos la serie de tiempo de los retornos
rACT2 <- returns0(ACT2)
plot.ts(rACT1, col = "navy", main = "Rentabilidad Diaria Facebook")

Code
plot.ts(rACT2, col = "darkgreen", main = "Rentabilidad Diaria Netflix")

USO DEL PAQUETE QUANTMOD PARA DETERMINACIÓN DE RETORNOS

El paquete “quantmod” es una alternativa muy buena para hacer análisis de los retornos de los precios de un activo riesgoso. Estas opciones tiene la ventaja de ser mas versatiles que los otros paquetes y de generar las series de tiempo en el fomato “xts” que viene de la frase “eXtended Time Series format”. Este formato es mucho mas conveniente para hacer analisis profesionales, ya que contiene dentro de cada series de tiempo, univariada o multivariada, mas detalles referentes al indicde de tiempo en la serie, como las horas, minutos segundos y hasta el huso horario del registro del precio financiero o de la transacción. Veamos como hacerlo de manera básica:

EJEMPLO 3

Use “quantmod” para analizar los retornos semanales de los años 2020 hasta lo que va corrido del 2024 del activo riesgoso Facebook.

Code
getSymbols("META", # colocamos el ticket del activo riesgoso en Yahoo!
           from='2020-01-01', # colocamos la fecha de inicio
           to='2024-12-18', # colocamos la fecha final (este argumento es opcional)
           periodicity = "weekly" # colocamos la periodicidad
           )
[1] "META"
Code
META <- Ad(META) # sacamos los precios de CIERRE AJUSTADO
rMETA <- returns0(META, method = "continuous") # calculamos retornos logaritmicos
ggplot(rMETA, aes(x = index(rMETA), y = META.Adjusted)) +
  geom_line(color = "blue") +
  labs(x = "Fecha", y = "Retornos", title = "Serie de Tiempo de los retornos semanales de Facebook") +
  theme_minimal()

Allí vemos el comportamiento de la serie de tiempo de rentabilidad, y podemos evidencia caracteristicas propias de este tipo de series financieras, tales como su comportamiento estacionario, y la heterocedasticidad de los retornos.

PORTAFOLIOS

Los portafolios de inversión (o carteras de inversión) es un conjunto de al menos dos activos riesgosos o libres de riesgo, en los cuales invertimos una determinada cantidad de capital, repartiéndolo estratégicamente entre los activos que componen dicho portafolio. El objetivo de estos instrumentos de inversión es aumentar la rentabilidad y diversificar el riesgo subyacente en la inversión.

  1. Diversificación: Uno de los principales objetivos de un portafolio es diversificar el riesgo. Al invertir en diferentes tipos de activos, sectores o regiones, se reduce la exposición a eventos adversos que puedan afectar a un solo activo. La diversificación puede ayudar a mitigar las pérdidas y suavizar la volatilidad del portafolio.

  2. Asignación de activos: La asignación de activos se refiere a cómo se distribuyen los recursos entre diferentes clases de activos. Por ejemplo, cuánto se invierte en acciones, cuánto en bonos y cuánto en efectivo. La asignación de activos debe basarse en los objetivos del inversionista, su horizonte temporal y su tolerancia al riesgo.

  3. Rendimiento y riesgo: Los inversionistas buscan maximizar el rendimiento de su portafolio mientras minimizan el riesgo. El rendimiento esperado está relacionado con la rentabilidad histórica y las expectativas futuras de los activos. El riesgo se mide en términos de volatilidad y la posibilidad de pérdidas.

  4. Horizonte temporal: El horizonte temporal del inversionista influye en la elección de activos. Por ejemplo, un inversionista con un horizonte a largo plazo puede asumir más riesgo y tener una mayor exposición a acciones.

  5. Rebalanceo: Con el tiempo, la composición del portafolio puede cambiar debido a las fluctuaciones del mercado. El rebalanceo periódico es importante para mantener la asignación de activos deseada.

  6. Estrategias de inversión: Hay diferentes estrategias de inversión, como el enfoque pasivo (por ejemplo, replicar un índice) o el enfoque activo (seleccionar activos específicos). Algunas personas también consideran factores como la sostenibilidad y la responsabilidad social al construir su portafolio.

Dicho esto, podemos dar la definición formal y matemática de lo que es un portafolio:

PORTAFOLIO. DEFINICIÓN FORMALIZADA

Un portafolio es un n-vector \(P=(x_1,x_2,...,x_n)\) que cumple una unica condición: \[\displaystyle \sum_{k=1}^{n} x_k=1\] Generalmente los \(x_k\) representan los pesos (o los porcentajes) del total de la inversión invertidos en el k-ésimo activo. Este portafolio se le llama “full investment” o de inversión total. Notese que los \(x_k\) pueden ser, eventualmente negativos.

EL PORTAFOLIO MINIMAL:

El portafolio minimal es el portafolio más pequeño posible, que es el que se compone exactamente de dos activos riesgosos. Analizaremos este portafolio para entender, más adelante, el portafolio general, que se compone de n activos. Veremos como calcular las medidas de riesgo básicas como lo son la rentabilidad media y la volatilidad del portafolio.

Code
### función de riesgo y rentabilidad para portafolio de dos activos riesgosos
ACT1 <- get.hist.quote('MMM', ## colcamos aqui el nombre del ticket de activo
                      quote = 'AdjClose', ## descarga precios de cierre ajustado
                      start = "2023-10-01", 
                      compression = "d")## promedios diarios de los precios
time series starts 2023-10-02
time series ends   2024-12-17
Code
ACT1 <- as.timeSeries(ACT1)  
ACT2 <- get.hist.quote("AMZN", 
                      quote = "AdjClose", 
                      start = "2023-10-01", # si se ignora "end" se toma la ultima fecha
                      compression = "d")
time series starts 2023-10-02
time series ends   2024-12-17
Code
ACT2 <- as.timeSeries(ACT2)

Programaremos una función de R para determinar el retorno promedio y la volatilidad, según lo que ya se ha visto con anterioridad.

Code
## esta funcion es para cuando descargamos los precios
port<-function(act1, # ponga aqui la primera serie de precios
               act2, # ponga aqui la segunda serie de precios
               w # ponga aqui el porcentaje invertidi en el primer activo
               ){
  ra1<-returns0(act1)*100
  ra2<-returns0(act2)*100
  mu1<-mean(ra1)
  mu2<-mean(ra2)
  mup<-w*mu1+(1-w)*mu2
  s1<-sd(ra1)
  s2<-sd(ra2)
  sp<-sqrt(w^2*var(ra1)+(1-w)^2*var(ra2)+2*w*(1-w)*s1*s2*cor(ra1,ra2))
  return(c(mup,sp))
}

Y programaremos una función en el caso de que solo se den los parámetros (rentabilidad, riesgo y correlación de los dos activos), como se verá a continuación:

Code
port2<-function(mu1,# retorno medio del primer activo
                mu2,# retorno medio del segundo activo
                sd1,# volatilidad del primer activo
                sd2,# volatilidad del segundo activo
                w, # porcentaje invertido en el primer activo
                cor # correlación entre los retornos
                ){
  mup<-w*mu1+(1-w)*mu2
  sp<-sqrt(w^2*sd1^2+(1-w)^2*sd2^2+2*w*(1-w)*sd1*sd2*cor)
  return(c(mup,sp))
}

EJEMPLO 3.

Use las descargas de precios hecha para las acciones de 3M y Amazon para determinar la rentabilidad media diaria y la volatilidad diaria de los retornos del portafolio \(\pi=(0.1,0.9)\) y del portafolio uniforme.

Primero hagamos los cálculos para el portafolio \(\pi\).

Code
port(act1 = ACT1, # precios MMM
     act2 = ACT2, # precios AMZN
     w = 0.1) #10% INVERTIDO EN EL PRIMER ACTIVO
[1] 0.1892415 1.6308312

Tenemos una rentabilidad positiva para el portafolio de 0.22% diario y una volatilidad, también diaria de 1.5% aproximadamente.

Luego hagamoslo para el portafolio uniforme, es decir \(\pi_2=(0.5,0.5)\).

Code
port(act1 = ACT1, # precios MMM
     act2 = ACT2, # precios AMZN
     w = 0.5) #50% INVERTIDO EN EL PRIMER ACTIVO
[1] 0.1884366 1.3902994

Vemos una leve variación en los resultados obtenidos. En promedio, este portafolio será un poco menos rentable que el anterior y así mismo, será menos volátil.

EJEMPLO 4

Use el portafolio anterior para hacer un análisis de rentabilidades y riesgo, confrontando los resultados mediante una gráfica bidimensional.

Code
p <- seq(-0.3,1,by=0.1)
r <- port(act1 = ACT1, act2 = ACT2, w = p)
Warning in w^2 * var(ra1): Recycling array of length 1 in vector-array arithmetic is deprecated.
  Use c() or as.vector() instead.
Warning in (1 - w)^2 * var(ra2): Recycling array of length 1 in vector-array arithmetic is deprecated.
  Use c() or as.vector() instead.
Warning in 2 * w * (1 - w) * s1 * s2 * cor(ra1, ra2): Recycling array of length 1 in vector-array arithmetic is deprecated.
  Use c() or as.vector() instead.
Code
n <- length(r)
mup <- r[1:(n/2)]
sp <- r[((n/2)+1):n]
plot(sp,mup, col = "navy", main = "Grafico Riesgo-Retorno", xlab = "Riesgo", ylab = "Retorno")
lines(sp,mup, col = "blue")

EJEMPLO 5.

Considere un portafolio de dos activos riesgosos. Para éste tenemos la siguiente información: \(\mu_1=0.098, \mu_2=0.057\) en sus rentabilidades. \(\sigma_1=0.15, \sigma_2=0.082\) en sus volatilidades. La correlación entre los activos del portafolio es \(\rho=0.2\). Suponga que se decide invertir 70% en el primer activo. Determine la rentabilidad y la volatilidad de este portafolio.

Usaremos la función ya programada port2. Lo único que hay que hacer es incluir los parámetros del problema de manera ordenada en el entorno:

Code
port2(mu1=0.098, mu2 = 0.057, sd1= 0.15, sd2 = 0.082, w = 0.7, cor = 0.2)
[1] 0.0857000 0.1125316

En donde verificamos lo hecho con proceso analítico.