Este documento sirve como guía para el ejercicio práctico del desarrollo semestral de aprendizaje, el cual será realizado por grupos de máximo 3 estudiantes preestablecidas. Cada grupo deberá llevar a cabo un proceso único e inédito; cualquier coincidencia de desarrollo que supere el 40% será sancionada con una calificación de 0.0 para los grupos involucrados. La evaluación del trabajo se realizará por partes, cada una con un valor diferenciado que contribuirá a alcanzar el 100% de la calificación final. Para analizar el proceso requerido use las diapositivas proporcionadas en clase y cualquier información de red relevante. Tenga en cuenta que se dará mayor importancia a los análisis desarrollados que a los cálculos desarrollados.
Presente los resultados en RPUBS con el nombre de los integrantes mostrando los puntos desarrollados en orden y debe enviarse en plataforma virtual. Fecha límite de entrega: 31 de octubre de 2025. Para los ejercicios use año comercial de 252 días.
1.1 Solución parte 1: Aplicación de cobertura con futuros de índice bursátil
Definición del problema
En el año 2025 se desea realizar inversiones en bolsa con objeto de inversión a 4 años. El objetivo es establecer un portafolio de inversión utilizando 3 acciones de preferencia del mismo índice bursátil. Se dispone de un capital de 10.000.000 para realizar inversiones en acciones desde el 31 de julio de 2025. Para construir un portafolio óptimo de media varianza, se considerarán entre 5 y 10 años de información histórica hasta la fecha de inicio de las inversiones (31 de julio).
Los futuros del índice bursátil serán pagaderos de forma mensual. Los criterios relacionados con los futuros del índice, como la garantía y el tamaño del contrato, se obtendrán a través de la plataforma bursátil, siendo recomendable el uso de Bloomberg o cualquier plataforma que entregue información de acciones para este fin.
Para el desarrollo del trabajo se seleccionan tres acciones del índice NASDAQ 100: Apple (AAPL), Microsoft (MSFT) y Alphabet (GOOG). El análisis abarca el periodo del 31 de julio de 2015 al 31 de julio de 2025, con el objetivo de construir un portafolio óptimo de media-varianza a partir de información histórica de retornos y riesgos.
Se dispone de un capital de $10.000.000, que se invertirá a partir del 31 de julio de 2025 con un horizonte de cuatro años. Posteriormente, se evaluará la cobertura del portafolio mediante futuros del NASDAQ 100, calculando el número óptimo de contratos para mitigar el riesgo sistemático. El estudio utiliza datos diarios, un año comercial de 252 días y métodos de optimización de Markowitz (1952).
1.1.1 Portafolio Optimo de inversión
Realice un análisis fundamental de las acciones elegidas y cuál es la expectativa de los precios hasta el 31/07/2025
3. Apple Inc. (AAPL)
Contexto y fundamentos
Apple es un gigante tecnológico con ecosistema integrado de hardware (iPhone, Mac, iPad, Watch y accesorios) y servicios (App Store, iCloud, Apple Music/TV+, etc.).
Según su reporte Q2 fiscal 2025, registró ingresos de US$ 95.4 mil millones, +5 % a/a, y EPS diluido de US$ 1.65, +8 % a/a. Apple
Desde ChartMill: Margen bruto ~46.68 %, margen operativo ~31.87 %, ROE ~150.8 %. Esto sitúa a Apple entre los mejores de su industria. ChartMill
Su negocio de servicios está registrando hitos: los servicios aportan cada vez más a los ingresos, lo cual mejora el perfil de margen y reduce dependencia del ciclo de iPhone. Por ejemplo, en Q3 del año informaron récord de servicios. Investopedia
Apple está invirtiendo en manufactura avanzada, IA y cadenas de suministro en EE.UU. (según Wikipedia resumen 2025). en.wikipedia.org
Expectativas de crecimiento
Dado su tamaño (capitalización de varios billones de USD) y su base instalada, Apple ya no crece al ritmo de startups; el crecimiento será moderado pero sólido. Por ejemplo, analistas estimaron un target de ~US$ 235-261 para 1 año. www.alphaspread.com +1
Otras fuentes más conservadoras lo ubican ~US$ 180 para 2025 si la economía decae o el ciclo de renovación se frena. cleverence.com
Considerando el horizonte hasta 31/07/2025 (~4 años desde la fecha de inversión), y suponiendo un crecimiento anual moderado quizá del 6-8 % compuesto (por ejemplo, +5 % ingresos y +8 % EPS, asumiendo reinversión), se podría proyectar un precio de ~US$ 280-300 si todo va bien; pero también escenarios de ~US$ 230-250 si moderado.
Riesgos clave
Ciclo del iPhone: si el lanzamiento de nuevos modelos fracasa o hay menor demanda, los ingresos pueden estancarse. (Ver artículo sobre WWDC 2025: Apple “está en riesgo de fallar su tendencia de largo plazo”). Seeking Alpha
Macro/Aranceles: Apple depende de manufactura global, especialmente Asia. Los aranceles o interrupciones en cadena afectan los costos y márgenes. Kiplinger
Saturación del mercado de smartphones: En mercados maduros puede haber menor crecimiento.
Expectativa de precio para 31/07/2025
Tomando un punto intermedio entre optimismo moderado y prudencia, proyectaría ≈ US$ 280 por acción hacia el 31 de julio de 2025.
Si el portafolio está valorado en dólares o convertido a tu moneda, este valor lo integrarás como expectativa de retorno
2. Microsoft Corporation (MSFT)
Resumen y fundamentos:
Microsoft mantiene una posición dominante en el mercado global de software y servicios en la nube. Su ecosistema incluye Azure, Microsoft 365, LinkedIn, Xbox y, más recientemente, la integración de IA generativa en todos sus productos tras su alianza con OpenAI. Según ChartMill (2025), se espera que las utilidades por acción (EPS) crezcan 15,2 % anual y los ingresos un 12,7 % anual. En su último reporte trimestral (FY 2025 Q4), Microsoft registró US$ 76,4 mil millones en ingresos y una utilidad neta de US$ 27,3 mil millones, lo que representa un crecimiento interanual del 24 % (RoboForex, 2025).
Perspectiva: El motor principal sigue siendo Azure, que se expande a tasas de doble dígito. Además, la adopción de herramientas de IA como Copilot en Office y Windows podría elevar los márgenes de rentabilidad en 2025-2026. Barron’s (2025) y AlphaSpread (2025) ubican el precio objetivo entre US$ 600 y US$ 750, lo que implicaría una valorización cercana al 15-20 % en el próximo año.
Riesgos:
Competencia intensa en IA y nube (Amazon, Google, Nvidia).
Riesgo de sobrevaloración por múltiplos altos.
Retrasos en monetización de productos IA.
3. Alphabet Inc. (GOOG)
Resumen y fundamentos: Alphabet Inc. —matriz de Google— domina la publicidad digital global, con negocios diversificados en Google Search, YouTube, Android, Google Cloud y DeepMind. En su reporte del segundo trimestre de 2025, Alphabet reportó US$ 96,4 mil millones en ingresos y una utilidad por acción (EPS) de US$ 2,31, un aumento del 14 % interanual (RoboForex, 2025). Su segmento Google Cloud creció más del 30 % en ingresos, mientras que YouTube Ads mostró recuperación significativa tras la desaceleración publicitaria de 2023-2024.
Perspectiva: Alphabet está invirtiendo fuertemente en infraestructura de IA y data centers. Simply Wall St (2025) estima un crecimiento promedio del EPS de 14-15 % anual. Aun con riesgos regulatorios (antitrust en EE.UU. y UE), se proyecta un precio objetivo entre US$ 300 y US$ 400 a 12 meses.
Riesgos:
Demandas y restricciones antimonopolio.
Alta dependencia de ingresos publicitarios (~70 %).
Gastos de capital crecientes en IA y centros de datos.
1.1.2Calcule los retornos anuales, la desviación estándar anual y la matriz de varianzas y covarianzas para cada acción.
Mostrar código
# --- Parámetros del problema ---SYMS <-c("AAPL","MSFT","GOOG")DATE_FROM <-"2015-07-31"DATE_TO <-"2025-07-31"TRADING_DAYS <-252# año comercial# --- 1) Descargar precios ajustados desde Yahoo Finance ---getSymbols(SYMS, src ="yahoo", from = DATE_FROM, to = DATE_TO, auto.assign =TRUE)
Podemos observar la matriz de los precio de cierre de las acciones elegidas.
Mostrar código
library(gt)library(zoo) # <-- agrega esto antes de usar coredata/indexprices_df <-data.frame(Date =index(prices),coredata(prices),row.names =NULL)gt(tail(prices_df, 30)) |>fmt_currency(columns =2:ncol(prices_df), currency ="USD", decimals =2) |>tab_options(table.font.size =px(14)) |>tab_header(title =md("**Precios ajustados (últimos 30 registros)**")) |>opt_table_outline()
Precios ajustados (últimos 30 registros)
Date
AAPL
MSFT
GOOG
2025-06-17
$195.42
$477.26
$177.07
2025-06-18
$196.36
$479.45
$173.82
2025-06-20
$200.77
$476.62
$167.58
2025-06-23
$201.27
$485.20
$165.86
2025-06-24
$200.07
$489.31
$167.59
2025-06-25
$201.33
$491.46
$171.34
2025-06-26
$200.77
$496.63
$174.27
2025-06-27
$200.85
$495.13
$178.11
2025-06-30
$204.94
$496.59
$177.23
2025-07-01
$207.58
$491.24
$176.75
2025-07-02
$212.20
$490.28
$179.60
2025-07-03
$213.31
$498.02
$180.39
2025-07-07
$209.71
$496.90
$177.40
2025-07-08
$209.77
$495.80
$175.00
2025-07-09
$210.90
$502.68
$177.50
2025-07-10
$212.17
$500.66
$178.54
2025-07-11
$210.92
$502.49
$181.15
2025-07-14
$208.38
$502.19
$182.65
2025-07-15
$208.87
$504.99
$182.94
2025-07-16
$209.92
$504.79
$183.61
2025-07-17
$209.78
$510.86
$184.54
2025-07-18
$210.94
$509.21
$185.77
2025-07-21
$212.24
$509.22
$190.98
2025-07-22
$214.16
$504.44
$191.94
2025-07-23
$213.91
$505.04
$191.34
2025-07-24
$213.52
$510.04
$193.03
2025-07-25
$213.64
$512.87
$193.91
2025-07-28
$213.81
$511.66
$193.25
2025-07-29
$211.03
$511.73
$196.25
2025-07-30
$208.81
$512.40
$197.26
Calculo de retornos
1.1.3 Definición teórica de los retornos
En el análisis financiero, el retorno de un activo mide la ganancia o pérdida relativa respecto a su precio inicial. Es una medida esencial para evaluar el rendimiento y comparar activos en el tiempo.
donde (P_t) es el precio en el periodo (t) y (P_{t-1}) el del periodo anterior. Representa el cambio porcentual directo entre dos precios consecutivos.
Ventajas prácticas: (i) es aditivo en el tiempo, (ii) suele aproximar mejor la normalidad, (iii) facilita el cálculo e interpretación de métricas del portafolio.
Estas transformaciones permiten expresar rendimiento y riesgo en base anual, compararlos entre activos y utilizarlos en la construcción de portafolios eficientes (media–varianza de Markowitz).
1) Rendimiento y riesgo por acción
MSFT: mayor media anual (25,47%) y menor volatilidad (27,14%). Es el perfil más atractivo del trío: más retorno con menos riesgo.
AAPL: media 20,46% con volatilidad 29,34%. Buen retorno, pero más riesgosa que MSFT.
GOOG: media 18,54% y volatilidad 28,75%. Es la de menor retorno con riesgo similar a AAPL.
Lectura de eficiencia (aprox. “riesgo por unidad de retorno”, σ/μ):
MSFT ≈ 1,07 (mejor), AAPL ≈ 1,43, GOOG ≈ 1,55. → MSFT domina en términos de calidad de retorno.
Mostrar código
library(PerformanceAnalytics)library(xts)library(dplyr)library(knitr)# 1. Retornos simples y logarítmicos diariosreturns_simple <-na.omit(Return.calculate(prices, method ="discrete"))returns_log <-na.omit(Return.calculate(prices, method ="log"))# 2. Estadísticos anuales desde retornos diariosTRADING_DAYS <-252ret_mean_ann <-colMeans(returns_log) * TRADING_DAYSret_sd_ann <-apply(returns_log, 2, sd) *sqrt(TRADING_DAYS)# 3. Matriz de covarianzas y correlaciones anualizadascov_matrix_ann <-cov(returns_log) * TRADING_DAYScor_matrix <-cor(returns_log)# 4. Mostrar resultadostabla_retornos <-tibble(Activo =colnames(returns_log),`Media anual (%)`= ret_mean_ann *100,`Desv.est. anual (%)`= ret_sd_ann *100)kable(tabla_retornos, digits =2, caption ="Media y desviación estándar anualizadas de los retornos logarítmicos")
Media y desviación estándar anualizadas de los retornos logarítmicos
La más baja es AAPL–GOOG (0,616) → es el par que más diversifica dentro del trío.
Implicación: habrá beneficio de diversificación, pero limitado; el riesgo sistemático del sector sigue siendo relevante.
Mostrar código
kable(cor_matrix, digits =4, caption ="Matriz de correlaciones entre las acciones")
Matriz de correlaciones entre las acciones
AAPL
MSFT
GOOG
AAPL
1.0000
0.6890
0.6157
MSFT
0.6890
1.0000
0.7287
GOOG
0.6157
0.7287
1.0000
Varianzas y covarianzas (anualizadas)
Las varianzas (diagonal) concuerdan con las σ reportadas:
Var(AAPL) 0,0861 (σ≈29,3%), Var(MSFT) 0,0737 (σ≈27,1%), Var(GOOG) 0,0827 (σ≈28,7%). → MSFT confirma ser la menos volátil.
Las covarianzas positivas (p. ej., AAPL–MSFT 0,0549) reflejan las correlaciones altas: los activos tienden a moverse juntos.
Mostrar código
kable(cov_matrix_ann, digits =6, caption ="Matriz de varianzas y covarianzas anualizada")
Matriz de varianzas y covarianzas anualizada
AAPL
MSFT
GOOG
AAPL
0.086103
0.054873
0.051938
MSFT
0.054873
0.073656
0.056856
GOOG
0.051938
0.056856
0.082656
1.1.4Calcule el retorno esperado, la desviación estándar y el Sharpe Ratio del portafolio
1.1.4.1 Definición teórica del retorno esperado, desviación estándar y Sharpe Ratio del portafolio
En el contexto de la teoría de portafolios de Markowitz, los tres indicadores fundamentales para evaluar una cartera de inversión son el retorno esperado, la desviación estándar (o volatilidad) y el Sharpe Ratio.
Retorno esperado del portafolio El retorno esperado ((E[R_p])) mide el rendimiento promedio ponderado de los activos que componen el portafolio:
\[
E[R_p] = \sum_{i=1}^{n} w_i \, E[R_i]
\]
donde: - (w_i) = proporción de capital invertida en el activo (i), - (E[R_i]) = retorno esperado del activo (i), - (n) = número de activos en el portafolio.
Este indicador representa la ganancia media esperada de la cartera, considerando las ponderaciones de cada activo.
Desviación estándar del portafolio La desviación estándar ((_p)) cuantifica el riesgo total o la variabilidad de los retornos del portafolio:
\[
\sigma_p = \sqrt{w^{\top} \Sigma w}
\]
donde: - (w) = vector de pesos del portafolio, - () = matriz de varianzas y covarianzas de los retornos de los activos.
La matriz () incluye tanto las varianzas individuales ((_i^2)) como las covarianzas entre pares de activos, que capturan los efectos de diversificación.
Sharpe Ratio El Sharpe Ratio mide la eficiencia del portafolio en términos de retorno ajustado al riesgo:
\[
SR = \frac{E[R_p] - R_f}{\sigma_p}
\]
donde: - (R_f) = tasa libre de riesgo (por ejemplo, bono del Tesoro a 3 o 12 meses), - (E[R_p] - R_f) = prima de riesgo del portafolio.
Un Sharpe Ratio más alto indica un mejor desempeño, ya que implica que el portafolio obtiene mayor retorno por cada unidad de riesgo asumida.
kable(res_pesos, align ="lrr", caption ="Pesos del portafolio: equi-ponderado vs. tangencia")
Pesos del portafolio: equi-ponderado vs. tangencia
Activo
w_eq
w_tangencia
AAPL
0.3333
0.0912
MSFT
0.3333
1.0868
GOOG
0.3333
-0.1780
Al comparar los resultados obtenidos para el portafolio equi-ponderado y el portafolio de tangencia, se observa que el segundo presenta un mejor desempeño general. El portafolio equi-ponderado, que distribuye el capital de manera uniforme entre las tres acciones (AAPL, MSFT y GOOG), alcanza un retorno esperado anual del 21,49% con una desviación estándar del 25,16%, lo que se traduce en un Sharpe Ratio de 0,735.
Por su parte, el portafolio de tangencia —que busca maximizar el Sharpe Ratio— obtiene un retorno esperado anual del 26,24% y una desviación estándar del 27,84%, alcanzando un Sharpe Ratio superior de 0,835. Esto indica que, aunque el riesgo del portafolio aumenta ligeramente, la rentabilidad adicional compensa dicho incremento, generando una mejor relación riesgo-retorno.
En cuanto a la composición del portafolio óptimo, el modelo asigna un peso mayoritario a Microsoft (MSFT) con 108,68%, una participación reducida de Apple (AAPL) con 9,12%, y una posición corta en Google (GOOG) de -17,8%. Este resultado refleja que, dentro del conjunto analizado, Microsoft es la acción con el mejor equilibrio entre rendimiento esperado y volatilidad, mientras que Google contribuye negativamente a la eficiencia del portafolio, razón por la cual el modelo sugiere reducir su exposición.
En síntesis, el portafolio de tangencia resulta ser el más eficiente en términos de la teoría media-varianza, ya que logra un mayor retorno esperado por cada unidad de riesgo asumido. En la práctica, si se aplicaran restricciones que impidan posiciones cortas, el peso negativo de Google se eliminaría, y los recursos se redistribuirían principalmente entre Microsoft y Apple, manteniendo una composición de portafolio conservadora pero eficiente.
Mostrar código
kable(res_metricas, align ="lrrr", caption ="Métricas del portafolio (anualizadas)")
Métricas del portafolio (anualizadas)
Portafolio
Retorno esperado (anual)
Desv.est. (anual)
Sharpe Ratio
Equi-ponderado
0.2149
0.2516
0.735
Tangencia (máx Sharpe)
0.2624
0.2784
0.835
1.1.5Establezca los pesos óptimos para la inversión total del capital destinado
1.1.5.1 Definición teórica de los pesos óptimos del portafolio
El objetivo del modelo de media–varianza propuesto por Harry Markowitz (1952) es determinar la combinación de activos que maximiza el rendimiento esperado para un nivel dado de riesgo, o equivalentemente, minimiza el riesgo para un nivel dado de retorno esperado.
Para un conjunto de ( n ) activos, se busca encontrar el vector de pesos ( w = (w_1, w_2, …, w_n)^) que cumpla con:
donde: - ( ) es la matriz de varianzas y covarianzas de los retornos de los activos,
- ( ) es el vector de retornos esperados,
- ( R_p ) es el retorno objetivo del portafolio,
- ( w_i ) representa la proporción de capital invertida en el activo ( i ).
La solución general de este problema se obtiene aplicando multiplicadores de Lagrange, y los pesos óptimos vienen dados por:
donde ( _1 ) y ( _2 ) son parámetros que dependen del nivel de retorno objetivo ( R_p ) y de los coeficientes:
\[
A = \mathbf{1}^{\top} \Sigma^{-1} \mathbf{1},
\quad
B = \mathbf{1}^{\top} \Sigma^{-1} \mu,
\quad
C = \mu^{\top} \Sigma^{-1} \mu,
\quad
D = AC - B^2.
\]
A partir de estos, se obtiene la frontera eficiente:
Caso especial: Portafolio de tangencia (máximo Sharpe) Cuando existe una tasa libre de riesgo ( R_f ), el portafolio óptimo es aquel que maximiza el Sharpe Ratio, cuya solución cerrada es:
Este portafolio se conoce como portafolio de mercado o de tangencia, y define la línea del mercado de capitales (CML).
Una vez determinados los pesos relativos ( w^*_{} ), la inversión total ( K ) se distribuye proporcionalmente como:
\[
I_i = K \cdot w_i^*,
\quad \text{para } i = 1, 2, ..., n.
\]
Así, el valor monetario invertido en cada activo depende tanto de su peso óptimo como del capital total disponible.
kable(res_metricas, caption ="Métricas del portafolio (anualizadas)")
Métricas del portafolio (anualizadas)
Portafolio
Retorno esperado (anual)
Desv.est. (anual)
Sharpe Ratio
Tangencia (sin restr.)
0.2624
0.2784
0.835
Máx Sharpe (long-only)
0.2513
0.2672
0.828
Mostrar código
# === Asignación de capital y n° de acciones (31-07-2025 o último disponible) ===# obtener último precio <= 2025-07-31 (si ese día no hay dato, usa el último previo)xts_cut <- prices[paste0("/", "2025-07-31")]if (NROW(xts_cut) ==0) xts_cut <- pricespx_last <-as.numeric(tail(xts_cut[, assets], 1))stopifnot(length(px_last) ==length(assets))names(px_last) <- assetsalloc_table <-function(w, label){ monto <- K * w shares <-floor(monto / px_last) invertido <- shares * px_last residuo <- monto - invertidotibble(Activo = assets,Precio =round(px_last, 2),Peso =round(w, 4),Monto =round(monto, 2),Acciones = shares,Invertido =round(invertido, 2),Efectivo_residual =round(residuo, 2),Metodo = label )}tbl_tan <-alloc_table(w_tan, "Tangencia")tbl_long <-alloc_table(w_long, "Máx Sharpe (long-only)")kable(tbl_tan, caption ="Asignación de capital y acciones — Tangencia (sin restricciones)")
Asignación de capital y acciones — Tangencia (sin restricciones)
Activo
Precio
Peso
Monto
Acciones
Invertido
Efectivo_residual
Metodo
AAPL
208.81
0.0912
911744.7
4366
911677.6
67.06
Tangencia
MSFT
512.40
1.0868
10868475.4
21211
10868466.4
8.98
Tangencia
GOOG
197.26
-0.1780
-1780220.1
-9025
-1780304.8
84.67
Tangencia
Mostrar código
kable(tbl_long, caption ="Asignación de capital y acciones — Máx Sharpe (long-only)")
Asignación de capital y acciones — Máx Sharpe (long-only)
Activo
Precio
Peso
Monto
Acciones
Invertido
Efectivo_residual
Metodo
AAPL
208.81
0.0668
668029.4
3199
667992.85
36.60
Máx Sharpe (long-only)
MSFT
512.40
0.9332
9331970.6
18212
9331785.89
184.66
Máx Sharpe (long-only)
GOOG
197.26
0.0000
0.0
-1
-197.26
197.26
Máx Sharpe (long-only)
Vizualización de la curva
El gráfico presentado muestra de forma visual la relación entre riesgo y retorno de las combinaciones posibles de inversión entre las tres acciones seleccionadas (AAPL, MSFT y GOOG). La curva negra representa la frontera eficiente, es decir, el conjunto de portafolios que ofrecen el mayor rendimiento esperado para cada nivel de riesgo. Sobre esta frontera se identifica el portafolio de tangencia, que corresponde al punto en el cual la línea del mercado de capitales (CML) —trazada en línea discontinua— es tangente a la frontera eficiente. Este punto marca la combinación óptima entre el activo libre de riesgo y el portafolio riesgoso, maximizando el rendimiento ajustado al riesgo (Sharpe Ratio).
Los activos individuales se ubican por debajo de la CML, lo que evidencia que ningún activo aislado ofrece una relación riesgo–retorno superior a la del portafolio diversificado. En particular, el portafolio de tangencia logra un retorno esperado anual de 26,24% con una desviación estándar de 27,84%, alcanzando un Sharpe Ratio de 0,835, el más alto de todos los portafolios analizados.
En cuanto a la composición, el modelo sin restricciones asigna un peso dominante a Microsoft (108,68%), un peso reducido a Apple (9,12%) y una posición corta en Google (-17,80%), lo que refleja que MSFT ofrece el mejor equilibrio entre rentabilidad y volatilidad, mientras que GOOG contribuye negativamente a la eficiencia del portafolio. Al imponer restricciones long-only, los pesos se ajustan a 93,32% para MSFT, 6,68% para AAPL y 0% para GOOG, eliminando la posición corta y manteniendo prácticamente el mismo nivel de eficiencia (Sharpe Ratio = 0,828).
La asignación monetaria de un capital total de 10.000.000 muestra que, bajo el esquema sin restricciones, se comprarían aproximadamente 21.210 acciones de MSFT, 4.366 de AAPL y se venderían en corto 9.025 de GOOG, mientras que bajo el esquema long-only se adquirirían 18.212 acciones de MSFT y 3.199 de AAPL, con una pequeña porción de efectivo residual.
En conjunto, los resultados confirman que el portafolio de tangencia es el más eficiente teóricamente, aunque el portafolio long-only es más adecuado para la implementación práctica, pues mantiene casi el mismo rendimiento esperado sin necesidad de apalancamiento ni ventas en corto. Esto demuestra que, incluso con correlaciones relativamente altas entre las acciones tecnológicas, la diversificación sigue siendo beneficiosa, y una estrategia concentrada en Microsoft con apoyo marginal de Apple permite obtener una excelente relación riesgo–retorno.
Mostrar código
library(ggplot2)library(dplyr)library(tidyr)library(scales)TRADING_DAYS <-252# --- Asegurar insumos (reconstruye si no existen) ---if (!exists("prices")) stop("Falta 'prices' en sesión.")if (!exists("returns_log")) returns_log <-na.omit(PerformanceAnalytics::Return.calculate(prices, method ="log"))if (!exists("mu")) mu <-colMeans(returns_log) * TRADING_DAYSif (!exists("Sigma")) Sigma <-cov(returns_log) * TRADING_DAYSif (!exists("rf")) rf <-0.03# 3% anual, ajusta si tienes otra tasaassets <-names(mu)# --- Portafolio de tangencia (cerrado) ---ones <-rep(1, length(mu))Sinv <-solve(Sigma)z <- Sinv %*% (mu - rf * ones)w_tan <-as.numeric(z /as.numeric(t(ones) %*% Sinv %*% (mu - rf * ones)))names(w_tan) <- assetsRp_tan <-as.numeric(sum(w_tan * mu))Sd_tan <-as.numeric(sqrt(t(w_tan) %*% Sigma %*% w_tan))# --- Parámetros A,B,C,D para frontera eficiente (no restringida) ---A <-as.numeric(t(ones) %*% Sinv %*% ones)B <-as.numeric(t(ones) %*% Sinv %*% mu)C <-as.numeric(t(mu) %*% Sinv %*% mu)D <- A*C - B^2# --- Curva de frontera eficiente a partir de R_target ---R_seq <-seq(min(mu)*0.8, max(mu)*1.2, length.out =200)frontier <-tibble(Rp = R_seq,Var = (A*R_seq^2-2*B*R_seq + C) / D) |>mutate(Sd =sqrt(pmax(Var, 0)))# --- Pesos de la frontera (opcional, por si quieres inspeccionar) ---# w(R) = Σ^{-1}[ ((C - B R)/D) * 1 + ((A R - B)/D) * μ ]# (No lo imprimimos; solo por referencia.)# w_frontier <- sapply(R_seq, function(Rt){# vec <- Sinv %*% ( ((C - B*Rt)/D) * ones + ((A*Rt - B)/D) * mu )# as.numeric(vec)# })# --- Puntos de activos individuales (σ, μ) ---sd_assets <-sqrt(diag(Sigma))pts_assets <-tibble(Activo = assets, Rp =as.numeric(mu), Sd =as.numeric(sd_assets))# --- Línea del mercado de capitales (CML): desde (0, rf) hasta tangencia ---# Recta: R = rf + slope * Sd, con slope = (Rp_tan - rf)/Sd_tanslope <- (Rp_tan - rf) / Sd_tancml_x <-seq(0, max(frontier$Sd)*1.05, length.out =100)cml <-tibble(Sd = cml_x, Rp = rf + slope * cml_x)# --- Graficar ---ggplot() +# Frontera eficiente (parte superior)geom_path(data = frontier, aes(x = Sd, y = Rp), linewidth =1.1, alpha =0.9) +# CMLgeom_line(data = cml, aes(x = Sd, y = Rp), linetype ="dashed", linewidth =1) +# Punto de tangenciageom_point(aes(x = Sd_tan, y = Rp_tan), size =3) +geom_text(aes(x = Sd_tan, y = Rp_tan),label ="Tangencia", nudge_y =0.005, nudge_x =0.002, size =3.5) +# Activos individualesgeom_point(data = pts_assets, aes(x = Sd, y = Rp), size =2.8) +geom_text(data = pts_assets, aes(x = Sd, y = Rp, label = Activo),nudge_y =0.005, size =3.3) +# Formatosscale_x_continuous(labels =percent_format(accuracy =1)) +scale_y_continuous(labels =percent_format(accuracy =1)) +labs(x ="Desviación estándar (anual)", y ="Retorno esperado (anual)",subtitle ="Frontera eficiente (no restringida), activos, portafolio de tangencia y CML",caption ="Notas: cálculos anualizados con 252 días. CML asume tasa libre de riesgo fija (rf).") +theme_minimal(base_size =12)
Frontera eficiente, portafolio de tangencia y Línea del Mercado de Capitales (CML)
1.2Optimo de contratos del futuro del índice
1.2.1Calcule el VaR al 1% y 5% del portafolio total diario, explique cómo se debe interpretar los escenarios, tenga en cuenta que estos serán los valores de cubrimiento
1.2.1.1 Definición teórica del VaR diario
El Valor en Riesgo (VaR) a nivel de significancia \(\alpha\) y horizonte de 1 día es la pérdida máxima esperada que no se excederá con probabilidad \(1-\alpha\):
Si trabajamos con retornos del portafolio \(R_{p,d}\) (positivos = ganancias, negativos = pérdidas), el VaR se reporta como número positivo:
VaR histórico (no paramétrico): usa la distribución empírica de \(R_{p,d}\) \[
VaR_{\\alpha}^{\\text{hist}} = -\\,Q_{\\alpha}\\big(R_{p,d}\\big),
\] donde \(Q_{\alpha}(\cdot)\) es el cuantil \(\alpha\).
VaR paramétrico (Normal): si \(R_{p,d} \sim \mathcal{N}(\mu_d,\sigma_d)\) \[
VaR_{\\alpha}^{\\text{norm}} = -\\big(\\mu_d + \\sigma_d\\,z_{\\alpha}\\big),
\\quad z_{\\alpha}=\\Phi^{-1}(\\alpha).
\]
Para cubrimiento, el VaR porcentual se convierte a monto monetario multiplicando por el valor del portafolio \(V\): \[
VaR\\;[\\text{monto}] = V \\times VaR\\;[\\%].
\]
Interpretación: - VaR 1% (diario): con 99% de confianza, la pérdida de un día no excederá ese valor. - VaR 5% (diario): con 95% de confianza, la pérdida de un día no excederá ese valor.
Mostrar código
library(PerformanceAnalytics)library(dplyr)library(knitr)K <-1e7# capital de referencia (10,000,000)# --- Insumos base ---stopifnot(exists("prices"))returns_log <-if (exists("returns_log")) returns_log elsena.omit(Return.calculate(prices, method ="log"))# Pesos del portafolio (prioridad: long-only -> tangencia -> equi)if (exists("w_long")) { w <- w_long} elseif (exists("w_tan")) { w <- w_tan} else { w <-rep(1/ncol(returns_log), ncol(returns_log))names(w) <-colnames(returns_log)}# Asegurar nombres y orden consistentesw <- w[colnames(returns_log)]# --- Retorno diario del portafolio (serie) ---rp_d <-as.numeric(returns_log %*% w)# rp_d es retorno LOG diario del portafolio; VaR se calcula sobre esta serie# --- VaR histórico (no paramétrico) ---alphas <-c(0.01, 0.05)VaR_hist_pct <--as.numeric(quantile(rp_d, probs = alphas, na.rm =TRUE, type =7))# --- VaR paramétrico (Normal) ---mu_d <-mean(rp_d, na.rm =TRUE)sd_d <-sd(rp_d, na.rm =TRUE)VaR_norm_pct <--(mu_d + sd_d *qnorm(alphas))# --- Pasar a montos monetarios (cubrimiento) ---VaR_hist_amt <- K * VaR_hist_pctVaR_norm_amt <- K * VaR_norm_pct# --- Tablas resumen ---tab_var_pct <-tibble(Nivel =paste0(alphas*100, "%"),`VaR Histórico (diario)`= scales::percent(VaR_hist_pct, accuracy =0.01),`VaR Normal (diario)`= scales::percent(VaR_norm_pct, accuracy =0.01))tab_var_amt <-tibble(Nivel =paste0(alphas*100, "%"),`VaR Histórico (COP/USD)`=round(VaR_hist_amt, 2),`VaR Normal (COP/USD)`=round(VaR_norm_amt, 2))kable(tab_var_pct, caption ="VaR diario del portafolio (porcentaje)")
VaR diario del portafolio (porcentaje)
Nivel
VaR Histórico (diario)
VaR Normal (diario)
1%
4.42%
3.82%
5%
2.65%
2.67%
Mostrar código
kable(tab_var_amt, caption ="VaR diario del portafolio (monto monetario sobre 10,000,000)")
VaR diario del portafolio (monto monetario sobre 10,000,000)
Nivel
VaR Histórico (COP/USD)
VaR Normal (COP/USD)
1%
442200.6
381526.2
5%
264954.5
266838.0
El portafolio presenta un VaR diario al 1% de 4,42% y un VaR al 5% de 2,65% según el método histórico, lo que significa que con una confianza del 99% y 95% respectivamente, la pérdida diaria no debería superar esos valores. En términos monetarios, esto equivale a pérdidas máximas estimadas de $442.197 y $264.957 sobre un capital de 10 millones. El método paramétrico arroja resultados similares (3,82% y 2,67%), lo que confirma una distribución de retornos relativamente estable sin colas excesivas. En general, el portafolio muestra un riesgo moderado: en escenarios extremos, las pérdidas diarias no deberían superar aproximadamente entre $260.000 y $440.000, montos que sirven como niveles de cubrimiento mínimos para definir estrategias de protección con futuros del índice.
1.2.2Calcule los valores (β) de las acciones por medio del CAPM (use el índice de las acciones elegidas para asumir los precios de mercado). Además, calcule y obtenga la beta del portafolio (use los pesos del punto d de la parte 1)
1.2.2.1 Definición teórica de las betas (CAPM) y beta del portafolio
En el marco del CAPM, la beta de un activo (i) mide su sensibilidad sistemática respecto al mercado:
library(quantmod)library(PerformanceAnalytics)library(dplyr)library(tidyr)library(knitr)library(zoo)library(xts)stopifnot(exists("prices"))SYMS <-colnames(prices)# ---- Descargar mercado intentando varias alternativas ----options(download.file.method ="libcurl")market_candidates <-c("QQQ", "^NDX", "^IXIC", "SPY", "^GSPC")fetch_market <-function(cands, from, to) {for (sym in cands) { x <-try(getSymbols(sym, src ="yahoo", from = from, to = to, auto.assign =FALSE), silent =TRUE)if (!inherits(x, "try-error")) { px <-Ad(x)colnames(px) <-"MKT"attr(px, "symbol_used") <- symreturn(px) } }stop("No se pudo descargar ningún proxy de mercado (QQQ, ^NDX, ^IXIC, SPY, ^GSPC).")}# Rango crudo (de tus activos)from_assets <-as.Date(first(index(prices)))to_assets <-as.Date(last(index(prices)))mkt_px_raw <-fetch_market(market_candidates, from = from_assets, to = to_assets)mkt_sym <-attr(mkt_px_raw, "symbol_used")# ---- Intersección de rangos (máximo inicio y mínimo fin) ----from_mkt <-as.Date(first(index(mkt_px_raw)))to_mkt <-as.Date(last(index(mkt_px_raw)))from_common <-max(from_assets, from_mkt, na.rm =TRUE)to_common <-min(to_assets, to_mkt, na.rm =TRUE)prices_cut <- prices[paste0(from_common, "/", to_common)]mkt_cut <- mkt_px_raw[paste0(from_common, "/", to_common)]# Quitar NA y asegurar que haya datos suficientesprices_cut <-na.omit(prices_cut)mkt_cut <-na.omit(mkt_cut)# Chequeos de robustezif (NROW(prices_cut) <2||NROW(mkt_cut) <2) {stop(glue::glue("Muy poca intersección de fechas entre activos y mercado.Activos: {from_assets} a {to_assets} (n={NROW(prices)})Mercado ({mkt_sym}): {from_mkt} a {to_mkt} (n={NROW(mkt_px_raw)})Intersección: {from_common} a {to_common}Filas activos en intersección: {NROW(prices_cut)}, filas mercado en intersección: {NROW(mkt_cut)}"))}# (Opcional) exigir al menos 252 observaciones para betas más estables:# if (NROW(prices_cut) < 252) warning("Menos de 252 observaciones en intersección; beta puede ser inestable.")# ---- Retornos diarios (log) y cálculo de betas ----px_all <-merge(prices_cut, mkt_cut, join ="inner")colnames(px_all) <-c(SYMS, "MKT")ret_all <-na.omit(Return.calculate(px_all, method ="log"))ret_assets <- ret_all[, SYMS]ret_mkt <- ret_all[, "MKT", drop =FALSE]var_m <-as.numeric(var(ret_mkt))betas_capm <-sapply(SYMS, function(s) cov(ret_assets[, s], ret_mkt)[1,1] / var_m)betas_reg <-sapply(SYMS, function(s) unname(coef(lm(coredata(ret_assets[, s]) ~coredata(ret_mkt)))[2]))# Pesos del punto (d): prioridad long-only -> tangencia -> equiif (exists("w_long")) { w <- w_long} elseif (exists("w_tan")) { w <- w_tan} else { w <-rep(1/length(SYMS), length(SYMS)); names(w) <- SYMS}w <- w[SYMS] # asegurar orden# Beta del portafolio (dos formas)beta_p_sum <-sum(w * betas_capm)rp <-as.numeric(as.matrix(ret_assets) %*%matrix(w, ncol =1))beta_p_dir <-as.numeric(cov(rp, coredata(ret_mkt)) / var_m)tab_betas <-tibble(Activo = SYMS,`Beta (CAPM cov/var)`=round(betas_capm, 4),`Beta (Regresión)`=round(betas_reg, 4),`Peso (w)`=round(as.numeric(w), 4))tab_beta_port <-tibble(`Proxy de mercado`= mkt_sym,`Beta portafolio (w·beta)`=round(beta_p_sum, 4),`Beta portafolio (directa)`=round(beta_p_dir, 4),`Obs. en intersección`=nrow(ret_all))kable(tab_betas, caption ="Betas por activo (CAPM y regresión) y pesos usados (rango de intersección)")
Betas por activo (CAPM y regresión) y pesos usados (rango de intersección)
Activo
Beta (CAPM cov/var)
Beta (Regresión)
Peso (w)
AAPL
1.0555
1.0555
0.0668
MSFT
1.0403
1.0403
0.9332
GOOG
1.0118
1.0118
0.0000
Mostrar código
kable(tab_beta_port, caption ="Beta del portafolio y verificación de consistencia")
Beta del portafolio y verificación de consistencia
Proxy de mercado
Beta portafolio (w·beta)
Beta portafolio (directa)
Obs. en intersección
QQQ
1.0413
1.0413
2512
Los resultados obtenidos muestran que las tres acciones seleccionadas —Apple, Microsoft y Google— presentan betas muy cercanas a 1, lo que indica que su comportamiento está altamente correlacionado con el del mercado. En particular, Apple (β = 1.056) y Microsoft (β = 1.040) exhiben una sensibilidad ligeramente superior a la del índice, mientras que Google (β = 1.012) mantiene una exposición prácticamente igual al mercado. Esto implica que ante un aumento del 1% en el índice, se espera que estas acciones incrementen su valor en aproximadamente el mismo porcentaje o un poco más. La beta del portafolio, calculada tanto de forma ponderada como directa (βₚ = 1.041), confirma que la cartera se mueve prácticamente al unísono con el mercado, reflejando un riesgo sistemático apenas superior al promedio. En consecuencia, el portafolio es levemente agresivo, con una exposición al riesgo de mercado que podría ser mitigada, si así se desea, mediante coberturas con futuros sobre el índice de referencia.
1.3Calcule el número de contratos óptimos basado para acciones
1.3.1 Definición teórica del número óptimo de contratos de futuros
El número óptimo de contratos de futuros que debe emplearse para cubrir una posición en acciones se obtiene a partir del modelo de mínima varianza, cuyo objetivo es reducir el riesgo del portafolio ante movimientos del mercado.
El ratio de cobertura óptimo (h^*) se define como:
[ h^* = = _{SF} ]
donde:
- (R_S) son los retornos del portafolio o activo,
- (R_F) los retornos del futuro,
- (_{SF}) la correlación entre ambos,
- (_S) la desviación estándar del portafolio, y
- (_F) la desviación estándar del futuro.
Una vez hallado (h^*), el número óptimo de contratos de futuros se determina mediante:
[ N^* = h^* ]
donde:
- (V_S) es el valor del portafolio a cubrir, y
- (V_F = F_0 Q) representa el valor nocional de un contrato de futuros, siendo (F_0) el precio del futuro y (Q) el tamaño del contrato.
Si (N^* > 0), se toma una posición corta en futuros (para proteger una posición larga en acciones).
Si (N^* < 0), se toma una posición larga en futuros (para cubrir una posición corta).
Mostrar código
library(quantmod)library(PerformanceAnalytics)library(dplyr)library(knitr)# --- 1. Definir pesos disponibles (usa el más adecuado) ---if (exists("w_long")) { w <- w_long} elseif (exists("w_tan")) { w <- w_tan} else {# equi-ponderado por defecto SYMS <-colnames(prices) w <-rep(1/length(SYMS), length(SYMS))names(w) <- SYMS}# --- 2. Calcular retorno del portafolio ---rp <-Return.portfolio(R = ret_assets, weights = w)# --- 3. Calcular ratio de cobertura óptimo (h*) ---cov_sf <-cov(rp, ret_mkt)var_f <-var(ret_mkt)rho_sf <-cor(rp, ret_mkt)sigma_s <-sd(rp)sigma_f <-sd(ret_mkt)h_star <-as.numeric(cov_sf / var_f) # forma clásicah_alt <-as.numeric(rho_sf * sigma_s / sigma_f) # verificación equivalente# --- 4. Valores del portafolio y del contrato ---V_s <-10000000# valor total del portafolioF0 <-as.numeric(last(Ad(getSymbols("QQQ", auto.assign =FALSE)))) # precio proxy del índiceQ <-100# tamaño típico del contratoV_f <- F0 * Q # valor nocional del contrato# --- 5. Número óptimo de contratos ---N_star <- h_star * (V_s / V_f)# --- 6. Resultados finales ---tab_contratos <-tibble(`Cov(Rp,Rf)`=round(cov_sf, 6),`Var(Rf)`=round(var_f, 6),`ρ(S,F)`=round(rho_sf, 4),`σ(S)`=round(sigma_s, 4),`σ(F)`=round(sigma_f, 4),`h* (óptimo)`=round(h_star, 4),`Precio futuro (F0)`=round(F0, 2),`Tamaño contrato (Q)`= Q,`Valor portafolio (V_S)`= V_s,`Valor contrato (V_F)`=round(V_f, 2),`N* contratos óptimos`=round(N_star, 2))kable(tab_contratos, caption ="Cálculo del número óptimo de contratos de futuros para cobertura del portafolio")
Cálculo del número óptimo de contratos de futuros para cobertura del portafolio
Cov(Rp,Rf)
Var(Rf)
ρ(S,F)
σ(S)
σ(F)
h* (óptimo)
Precio futuro (F0)
Tamaño contrato (Q)
Valor portafolio (V_S)
Valor contrato (V_F)
N* contratos óptimos
0.000211
0.000203
0.8781
0.0169
0.0142
1.0411
626.05
100
1e+07
62605
166.29
El resultado muestra que el ratio de cobertura óptimo () es 1.0411, lo cual indica que los retornos del portafolio se mueven prácticamente uno a uno con los del índice de referencia, pero con una ligera sensibilidad superior al 4 %. En otras palabras, por cada 1 % de variación en el índice, el portafolio tiende a cambiar aproximadamente 1.04 %.
Dado que el valor total de la cartera es de 10 millones y el valor nocional de un contrato de futuros del índice (QQQ) es de aproximadamente 62 605 dólares, el número óptimo de contratos necesarios para neutralizar el riesgo sistemático del portafolio es de 166 contratos. Esto implica que el inversionista debería vender 166 contratos de futuros del índice para proteger completamente la exposición al riesgo de mercado de su cartera de acciones.
1.3.2 Definición teórica del Margin Call y análisis de rentabilidad con roll-over
Calcule el Margin Call trimestral, ¿cuánto gana y se pierde en el futuro del índice? Realice un análisis de rentabilidad usando la estructura de roll-over cada trimestre. ¿Qué pasaría si deja todo en corto o en largo?
En el mercado de futuros, las posiciones están sujetas a un proceso de ajuste diario conocido como mark-to-market, donde las ganancias o pérdidas se acreditan o debitan en la cuenta de margen del inversionista al cierre de cada jornada.
Este proceso asegura que las pérdidas no superen el capital comprometido.
El Margin Call ocurre cuando el saldo de la cuenta cae por debajo del margen de mantenimiento ((M_m)), obligando al inversionista a depositar fondos adicionales hasta restablecer el margen inicial ((M_i)):
[ _t < M_m = M_i - _t ]
El valor de una posición en futuros varía según los cambios en el precio del contrato:
[ V_t = N Q (F_t - F_{t-1}) ]
donde: - (N): número de contratos,
- (Q): tamaño del contrato,
- (F_t): precio del futuro al tiempo (t),
- (F_{t-1}): precio del futuro en el periodo anterior.
El resultado diario puede ser positivo (ganancia) o negativo (pérdida), generando flujos que ajustan el margen.
Cuando se realiza una estrategia de cobertura o especulación a largo plazo, se implementa una estructura de roll-over trimestral, que consiste en: 1. Mantener la posición hasta el vencimiento del contrato del trimestre.
2. Cerrar la posición actual y abrir una nueva en el siguiente vencimiento.
El rendimiento total acumulado de la estrategia de futuros con roll-over puede expresarse como:
[ R_{} = ^{T}* F_t + ^{T} C_t ]
donde (C_t) representa los costos de transacción o ajuste al renovar los contratos.
Interpretación de las posiciones: - Posición larga (long): gana cuando el precio del futuro sube.
- Posición corta (short): gana cuando el precio del futuro baja.
En consecuencia, la rentabilidad dependerá del sentido del mercado durante los trimestres y de la correcta administración del margen de garantía.
Mostrar código
library(quantmod)library(PerformanceAnalytics)library(dplyr)library(lubridate)library(knitr)# --- 1. Descargar precios del índice (QQQ como proxy del futuro del NASDAQ) ---getSymbols("QQQ", from ="2020-01-01", to =Sys.Date(), auto.assign =TRUE)
[1] "QQQ"
Mostrar código
fut <-Ad(QQQ)colnames(fut) <-"Futuro"# --- 2. Crear estructura trimestral ---fut_quarterly <- fut[endpoints(fut, on ="quarters"), , drop =FALSE]ret_fut <-diff(log(fut_quarterly)) # retornos trimestrales aproximados# --- 3. Supuestos base ---N <-166# número óptimo de contratos (de tu cálculo previo)Q <-100# tamaño del contratoF0 <-as.numeric(first(fut)) # precio inicialMi <-0.10* N * Q * F0 # margen inicial (10% del valor nocional)Mm <-0.75* Mi # margen de mantenimiento (75%)posiciones <-c("Long", "Short")# --- 4. Simulación del margin call y resultados trimestrales ---resultados <-lapply(posiciones, function(pos) { saldo <- Mi calls <-0 ganancias <-c() precios <-coredata(fut_quarterly)for (i in2:length(precios)) { delta <- (precios[i] - precios[i-1]) * Q * Nif (pos =="Short") delta <--delta saldo <- saldo + deltaif (saldo < Mm) { calls <- calls +1 recarga <- Mi - saldo saldo <- Mi } ganancias <-c(ganancias, delta) }data.frame(Posicion = pos,Trimestres =length(ganancias),Ganancia_total =sum(ganancias),Promedio_trimestral =mean(ganancias),Margin_Calls = calls,Ultimo_saldo = saldo )})resultados_df <-bind_rows(resultados)kable(resultados_df, caption ="Simulación de Margin Calls y rentabilidad trimestral (estructura roll-over)")
Simulación de Margin Calls y rentabilidad trimestral (estructura roll-over)
Posicion
Trimestres
Ganancia_total
Promedio_trimestral
Margin_Calls
Ultimo_saldo
Long
23
7332182
318790.5
0
7678871.7
Short
23
-7332182
-318790.5
14
346689.2
Los resultados muestran que una posición larga en los futuros del índice genera una ganancia total de 7.33 millones, con un saldo final de 7.68 millones y sin llamadas de margen durante el periodo de 23 trimestres. Esto refleja un mercado predominantemente alcista, en el que mantener una posición larga fue altamente rentable.
En contraste, la posición corta arroja una pérdida equivalente de -7.33 millones y presenta 14 margin calls, lo que evidencia la presión constante de reponer garantías debido a la tendencia ascendente del índice.
1.3.3 Definición teórica del valor esperado de la cobertura trimestral del portafolio
¿Cuál sería el valor esperado de la cobertura trimestral del portafolio? Use una tasa libre de riesgo de la fecha inicial (^TNX (CBOE Interest Rate 3 a 5 Year) para estados Unidos. Realice un análisis al respecto
El objetivo de la cobertura mediante contratos de futuros es neutralizar las variaciones del valor del portafolio ante cambios en el mercado.
En un horizonte trimestral, el valor esperado de la cobertura está determinado por la evolución esperada del precio del futuro y la tasa libre de riesgo vigente en la fecha inicial.
Sea un portafolio con valor ( V_S ), cubierto con ( N^* ) contratos de futuros sobre un índice, cada uno con precio inicial ( F_0 ) y tamaño ( Q ).
El número óptimo de contratos está dado por:
\[
N^* = h^* \cdot \frac{V_S}{V_F}
\]
donde ( h^* ) es el ratio de cobertura óptimo y ( V_F = F_0 Q ) representa el valor nocional de un contrato.
En un contexto de equilibrio riesgo–neutro, el precio esperado del futuro al final del trimestre se aproxima por:
donde ( r_S ) representa el retorno esperado del portafolio de acciones.
De este modo, la cobertura permite compensar las variaciones del portafolio de renta variable con las ganancias o pérdidas de la posición en futuros, estabilizando el rendimiento trimestral neto.
Mostrar código
library(quantmod)library(PerformanceAnalytics)library(dplyr)library(lubridate)library(knitr)# --- Parámetros base ---fecha_ini <-as.Date("2025-07-31")Delta_t <-0.25# trimestre ~ 1/4 añoV_S <-10000000# valor del portafolioQ <-100# multiplicador del futuro de índice (estándar en muchos ETFs/índices)# F0: precio del "futuro" proxy. Usaremos QQQ (último precio antes o igual a fecha_ini)getSymbols("QQQ", from = fecha_ini -3650, to = fecha_ini, auto.assign =TRUE)
[1] "QQQ"
Mostrar código
F0 <-as.numeric(last(Ad(QQQ)[paste0("/", fecha_ini)]))if (is.na(F0)) F0 <-as.numeric(last(Ad(QQQ))) # fallback# --- Tasa libre de riesgo al inicio: intentamos ^FVX (5Y) y luego ^TNX (10Y) ---rf_fetch <-function(symbol, fecha) { x <-try(getSymbols(symbol, from = fecha -365, to = fecha, auto.assign =FALSE), silent =TRUE)if (inherits(x, "try-error")) return(NA_real_) y <-Ad(x)as.numeric(last(y[paste0("/", fecha)])) /100# vienen en %}r_f <-rf_fetch("^FVX", fecha_ini)if (is.na(r_f)) r_f <-rf_fetch("^TNX", fecha_ini)if (is.na(r_f)) stop("No se pudo obtener ^FVX ni ^TNX para la fecha inicial.")# --- Ratio de cobertura y N* ---# Usamos tus objetos si existen; si no, los calculamosif (!exists("ret_assets") ||!exists("ret_mkt")) {# reconstruir rápidamente desde tus preciosstopifnot(exists("prices"))# Proxy de mercado para ret_mkt acorde a QQQ mkt <-Ad(QQQ) px_all <-na.omit(merge(prices, mkt))colnames(px_all)[ncol(px_all)] <-"MKT" ret_all <-na.omit(Return.calculate(px_all, method ="log")) ret_assets <- ret_all[, colnames(prices)] ret_mkt <- ret_all[, "MKT", drop =FALSE]}# Pesos: usa w_long -> w_tan -> equiif (exists("w_long")) { w <- w_long} elseif (exists("w_tan")) { w <- w_tan} else { w <-rep(1/ncol(ret_assets), ncol(ret_assets)); names(w) <-colnames(ret_assets)}rp <-Return.portfolio(R = ret_assets, weights = w)cov_sf <-as.numeric(cov(rp, ret_mkt))var_f <-as.numeric(var(ret_mkt))h_star <- cov_sf / var_fV_F <- F0 * QN_star <-if (exists("N_star")) as.numeric(N_star) else h_star * (V_S / V_F)# --- Valor esperado trimestral de la cobertura (riesgo-neutro, sin dividendos) ---E_dF <- F0 * (r_f * Delta_t) # E[ΔF]E_PnL_short <-- N_star * Q * E_dFE_PnL_long <-+ N_star * Q * E_dF# --- Retorno esperado del portafolio en el trimestre (desde retorno anual esperado) ---# Usa tu retorno anual esperado del portafolio long-only si existe; si no, estimamos de la serie.if (exists("Rp_long")) { mu_ann <-as.numeric(Rp_long)} else { mu_ann <-mean(rp) *252# media diaria * 252}E_port_trimestral <- V_S * (mu_ann * Delta_t)# --- Agregar neto cubierto (portafolio + cobertura) ---res <-tibble(Escenario =c("Short futuros (cobertura)","Long futuros"),`r_f anual`= scales::percent(r_f, accuracy =0.01),`F0 (proxy)`=round(F0, 2),`N*`=round(N_star, 2),`E[P&L cobertura trimestral]`=c(round(E_PnL_short, 2), round(E_PnL_long, 2)),`E[retorno portafolio trim]`=round(E_port_trimestral, 2),`E[total trimestral]`=round(E_port_trimestral +c(E_PnL_short, E_PnL_long), 2))kable(res, caption ="Valor esperado trimestral: cobertura del portafolio con futuros (usando tasa libre de riesgo inicial)")
Valor esperado trimestral: cobertura del portafolio con futuros (usando tasa libre de riesgo inicial)
Escenario
r_f anual
F0 (proxy)
N*
E[P&L cobertura trimestral]
E[retorno portafolio trim]
E[total trimestral]
Short futuros (cobertura)
3.96%
567.36
166.29
-93520.46
628313.7
534793.2
Long futuros
3.96%
567.36
166.29
93520.46
628313.7
721834.1
1.4 Parte 2. Desarrollo de un Futuro de divisas.
Ustedes son inversores y el día de hoy requieren 300 millones de pesos para una compra de maquinaria amarilla, encuentran que pueden ejercer un crédito en Estados Unidos (Elijan ustedes un crédito de una entidad financiera estadounidense, con la tasa, a un plazo a 10 años, el sistema de pago será francés). Para proteger los pagos en cuotas, ustedes también deciden apalancarse con un futuro de divisas con el 70% del valor de inversión de maquinaria amarilla, desde el sexto año de la inversión (use la información de un futuro de la BVC como datos históricos) y como propone la fórmula de cálculo del futuro de TRM, use una tasa de interés comercial que emule las condiciones de la tasa americana. De lo anterior:
Proceso del crédito
1.4.1 Introducción
En esta sección se plantea un escenario práctico de cobertura cambiaria mediante el uso de contratos de futuros sobre la Tasa Representativa del Mercado (TRM). Como inversionistas colombianos que adquieren maquinaria financiada en dólares a través de un crédito en Estados Unidos, el objetivo es mitigar el riesgo de tipo de cambio asociado a las cuotas futuras. Para ello, se diseña una estrategia de cobertura con futuros de divisas listados en la Bolsa de Valores de Colombia (BVC), equivalente al 70 % del valor de la inversión, aplicada a partir del sexto año del crédito. Este ejercicio permite evaluar la efectividad del instrumento derivado frente a la exposición cambiaria y su impacto en la estabilidad de los flujos financieros del proyecto.
1.4.2Realice un análisis fundamental de la TRM y cuál es la expectativa de los precios hasta dentro de un año (busque informes de proyección de la divisa)
Factores que inciden en la TRM (USD/COP):
Tasas de interés relativas: Si la tasa doméstica en Colombia se mantiene alta (por ejemplo, la tasa de política monetaria del Banco de la República de Colombia se encuentra en torno al 9 %-10 %) frente a una tasa de EE.UU. más baja o estable, esto tiende a atraer capitales al peso, lo que puede favorecer su apreciación o al menos mitigar su depreciación. Reuters +2 bbvaresearch.com +2
Inflación y riesgo país: Una inflación persistentemente por encima de la meta reduce la confianza en el peso y eleva la depreciación esperada. Se estima que la inflación en Colombia para 2025 será superior al 4 %. Reuters +1
Precio de commodities y balanza comercial: Colombia es exportador de petróleo y otras materias primas; precios más altos favorecen ingresos de dólares y fortalecen el peso. Si el petróleo cae, esto presiona al alza de la TRM.
Entorno internacional y dólar global: Si el dólar estadounidense se fortalece (por una subida de tasas por parte de la Federal Reserve o por mayor aversión al riesgo global), monedas emergentes como el peso tienden a depreciarse. Además, algunos informes proyectan que el peso podría ser “la peor moneda de Latinoamérica” para 2026.
1.4.3 Cálculo de los retornos y la desviación estándar de la TRM
En el análisis de series financieras, los retornos representan la variación proporcional del precio o tasa de un activo entre dos periodos consecutivos. En el caso de la Tasa Representativa del Mercado (TRM), los retornos mensuales reflejan la apreciación o depreciación del peso colombiano frente al dólar estadounidense.
El retorno logarítmico mensual se define como:
\[
r_t = \ln\left(\frac{P_t}{P_{t-1}}\right)
\]
donde (P_t) y (P_{t-1}) representan el valor de la TRM en los meses (t) y (t-1), respectivamente.
Este tipo de retorno es preferido en el análisis financiero porque:
Es aditivo en el tiempo, lo que facilita el cálculo de retornos acumulados.
Se aproxima mejor a una distribución normal.
Permite un análisis estadístico más estable en series largas.
Una vez obtenidos los retornos, se calcula la media y la desviación estándar mensual, que miden el rendimiento promedio y el riesgo (volatilidad) del tipo de cambio:
donde ({r}) es el retorno promedio mensual, () es la volatilidad mensual y (n) el número total de observaciones.
Una () alta indica que la TRM es más volátil —mayor incertidumbre cambiaria—, mientras que una () baja refleja mayor estabilidad en el mercado de divisas.
Mostrar código
# --- Paquetes ---suppressPackageStartupMessages({library(quantmod)library(PerformanceAnalytics)library(dplyr)library(lubridate)library(knitr)library(xts)library(zoo)})# --- Parámetros (ajusta si quieres) ---fecha_ini <-as.Date("2015-01-01")fecha_fin <-Sys.Date()# --- Descarga TRM (USD/COP) desde Yahoo Finance ---# Símbolo: USDCOP=XgetSymbols("USDCOP=X", from = fecha_ini, to = fecha_fin, auto.assign =TRUE)
[1] "USDCOP=X"
Mostrar código
trm_daily <-na.omit(Cl(`USDCOP=X`)) # Precio de cierre diariocolnames(trm_daily) <-"TRM"# Verificación de datos suficientesif (NROW(trm_daily) <10) {stop("No se obtuvieron suficientes datos de TRM. Revisa conexión o rango de fechas.")}# --- Agregación a frecuencia mensual (último día hábil de cada mes) ---trm_monthly <-to.monthly(trm_daily, indexAt ="lastof", OHLC =FALSE)colnames(trm_monthly) <-"TRM"# --- Retornos logarítmicos mensuales ---ret_mensuales <-na.omit(diff(log(trm_monthly)))colnames(ret_mensuales) <-"ret_mensual"# --- Estadísticas: media y desviación estándar mensuales ---media_mensual <-mean(ret_mensuales)[[1]]desv_mensual <-sd(ret_mensuales)[[1]]# (Opcional) equivalentes anualizados con base 12media_anualizada <- media_mensual *12vol_anualizada <- desv_mensual *sqrt(12)# --- Resumen tabular ---periodo_txt <-paste(format(start(trm_monthly), "%Y-%m"),"→",format(end(trm_monthly), "%Y-%m"))tabla_resumen <- tibble::tibble(`Periodo (mensual)`= periodo_txt,`Observaciones (n)`=nrow(ret_mensuales),`Retorno promedio mensual (%)`=round(100* media_mensual, 3),`Desv.est. mensual (%)`=round(100* desv_mensual, 3),`Retorno promedio anual (%)`=round(100* media_anualizada, 2),`Volatilidad anual (%)`=round(100* vol_anualizada, 2))kable( tabla_resumen,caption ="TRM (USD/COP): retornos logarítmicos mensuales y volatilidad",align ="lrrrrr")
TRM (USD/COP): retornos logarítmicos mensuales y volatilidad
Periodo (mensual)
Observaciones (n)
Retorno promedio mensual (%)
Desv.est. mensual (%)
Retorno promedio anual (%)
Volatilidad anual (%)
2015-01 → 2025-11
130
0.372
3.971
4.46
13.76
Mostrar código
# --- (Opcional) Vista rápida de los últimos 12 retornos mensuales ---ultimos12 <-tail(100* ret_mensuales, 12)kable(data.frame(Mes =format(index(ultimos12), "%Y-%m"),`Retorno mensual (%)`=round(coredata(ultimos12[,1]), 3) ),caption ="Últimos 12 retornos mensuales de la TRM (en %)",align ="lr")
Últimos 12 retornos mensuales de la TRM (en %)
Mes
ret_mensual
2024-12
-0.301
2025-01
-5.680
2025-02
-0.713
2025-03
1.257
2025-04
1.391
2025-05
-2.691
2025-06
-0.998
2025-07
2.350
2025-08
-4.171
2025-09
-2.248
2025-10
-1.704
2025-11
-0.064
La TRM exhibe un retorno promedio mensual de 0.38% (≈ 4.5% anual), lo que sugiere una depreciación leve del COP frente al USD en el largo plazo. La volatilidad mensual de 4.0% (≈ 13.8% anual) indica oscilaciones relevantes: movimientos típicos mensuales de ±4% en el tipo de cambio. En los últimos 12 meses predominan variaciones negativas (p. ej., ene-2025: −5.68%, ago-2025: −4.17%, sep-2025: −2.25%, oct-2025: −1.73%), lo que apunta a una apreciación reciente del COP tras episodios puntuales de depreciación (jul-2025: +2.35%). Para cobertura, esto implica riesgo cambiario no menor: conviene dimensionar contratos con base en la volatilidad observada y revisar periódicamente el hedge por los cambios de tendencia.
1.4.4 Simulación con Browniano Geométrico (BMG) para la TRM
La dinámica de precios bajo BMG se modela como: \[
dS_t = \mu\,S_t\,dt + \sigma\,S_t\,dW_t,
\] cuyo solucionario discreto (paso mensual) es: \[
S_{t+\Delta} = S_t \exp\!\Big[\Big(\mu - \tfrac{1}{2}\sigma^2\Big)\Delta + \sigma \sqrt{\Delta}\,Z_t\Big],\quad Z_t\sim \mathcal{N}(0,1).
\]
Con retornos logarítmicos mensuales históricos (r_t=(S_t/S_{t-1})), se estiman: \[
\hat{\mu}=\overline{r},\qquad \hat{\sigma}=\text{sd}(r).
\]
Para horizonte de (H) meses y () mes, una trayectoria parte de (S_0) (última TRM observada) y repite la recursión (H) veces. Con (N) trayectorias, se resume el pronóstico por cuantiles (p5, mediana, p95) al horizonte.
Mostrar código
suppressPackageStartupMessages({library(quantmod)library(PerformanceAnalytics)library(dplyr)library(tidyr)library(ggplot2)library(knitr)library(xts)library(zoo)})# --- 1) Usar la TRM mensual y retornos ya calculados si existen; si no, descargarlos ---if (!exists("trm_monthly") ||!exists("ret_mensuales")) {getSymbols("USDCOP=X", from ="2015-01-01", to =Sys.Date(), auto.assign =TRUE) trm_daily <-na.omit(Cl(`USDCOP=X`)) trm_monthly <-to.monthly(trm_daily, indexAt ="lastof", OHLC =FALSE)colnames(trm_monthly) <-"TRM" ret_mensuales <-na.omit(diff(log(trm_monthly)))colnames(ret_mensuales) <-"ret_mensual"}# --- 2) Estimar parámetros mensuales ---mu_hat <-as.numeric(mean(ret_mensuales))sg_hat <-as.numeric(sd(ret_mensuales))# --- 3) Configuración de simulación ---set.seed(123) # reproducibilidadH <-12# horizonte en mesesN_paths <-5000# número de trayectoriasDelta <-1.0# paso mensualS0 <-as.numeric(last(trm_monthly)) # última TRM observada# --- 4) Simulación BMG (vectorizada) ---Z <-matrix(rnorm(H * N_paths), nrow = H, ncol = N_paths)drift <- (mu_hat -0.5* sg_hat^2) * Deltashock <- sg_hat *sqrt(Delta) * Zlog_increments <-sweep(shock, 1, drift, `+`) # drift + shock por meslog_levels <-apply(log_increments, 2, cumsum)S_paths <-exp( log(S0) +rbind(rep(0, N_paths), log_levels) ) # (H+1) x N# --- 5) Resumen estadístico por mes ---dates_sim <-seq.Date(from =as.Date(end(trm_monthly)), by ="month", length.out = H +1)sum_tab <-apply(S_paths, 1, quantile, probs =c(0.05, 0.5, 0.95))sum_df <-tibble(Mes = dates_sim,p05 = sum_tab[1,],p50 = sum_tab[2,],p95 = sum_tab[3,])kable( sum_df %>%mutate(across(c(p05, p50, p95), ~round(.x, 2))),caption ="TRM simulada (BMG): cuantiles 5%, 50% y 95% por mes")
TRM simulada (BMG): cuantiles 5%, 50% y 95% por mes
Mes
p05
p50
p95
2025-11-30
3856.00
3856.00
3856.00
2025-12-30
3623.71
3864.63
4131.34
2026-01-30
3536.10
3878.21
4268.79
2026-03-02
3472.69
3885.58
4364.34
2026-03-30
3419.30
3892.60
4448.96
2026-04-30
3371.92
3906.32
4515.33
2026-05-30
3347.67
3919.25
4602.03
2026-06-30
3306.02
3929.76
4677.75
2026-07-30
3288.35
3947.41
4739.41
2026-08-30
3266.23
3956.59
4787.88
2026-09-30
3236.00
3970.28
4849.10
2026-10-30
3216.61
3982.22
4915.33
2026-11-30
3181.52
3997.86
4977.95
Mostrar código
# --- 6) Gráfico de abanico (mediana y banda 5–95%) ---# ggplot(sum_df, aes(x = Mes)) +# geom_ribbon(aes(ymin = p05, ymax = p95), alpha = 0.2) +# geom_line(aes(y = p50), linewidth = 1) +# labs(# title = "Simulación BMG de la TRM (mensual)",# subtitle = paste0("S0 = ", round(S0,2),# " | μ̂ = ", round(mu_hat*100,2), "% mensual, σ̂ = ", round(sg_hat*100,2), "% mensual",# " | H = ", H, " meses, N = ", N_paths),# y = "TRM (COP por USD)", x = "Mes"# ) +# theme_minimal()
Mostrar código
# --- 7) Resumen al horizonte (H meses) ---horizon_vals <- S_paths[H +1, ]resumen_h <-tibble(`TRM (p05)`=round(quantile(horizon_vals, 0.05), 2),`TRM (mediana)`=round(median(horizon_vals), 2),`TRM (p95)`=round(quantile(horizon_vals, 0.95), 2))kable(resumen_h, caption =paste0("Distribución simulada de la TRM al horizonte de ", H, " meses"))
Distribución simulada de la TRM al horizonte de 12 meses
TRM (p05)
TRM (mediana)
TRM (p95)
3181.52
3997.86
4977.95
Mostrar código
library(dplyr)library(tidyr)library(ggplot2)library(scales)# --- Construir un data.frame largo con unas pocas trayectorias representativas ---# S_paths: matriz (H+1) x N_paths creada antes# dates_sim: vector de fechas (H+1)set.seed(123)n_mostrar <-30# nº de trayectorias a dibujaridx_mostrar <-sample(ncol(S_paths), n_mostrar) # columnas aleatoriasdf_paths <-as.data.frame(S_paths[, idx_mostrar])colnames(df_paths) <-paste0("path_", seq_len(n_mostrar))df_paths$Mes <- dates_simdf_long <- df_paths |> tidyr::pivot_longer(-Mes, names_to ="Trayectoria", values_to ="TRM")# --- Data frame del abanico y mediana (ya lo tenías como sum_df con p05, p50, p95) ---# sum_df: tibble con columnas Mes, p05, p50, p95# --- Gráfico: banda 5–95%, mediana y trayectorias seleccionadas ---ggplot() +geom_ribbon(data = sum_df, aes(x = Mes, ymin = p05, ymax = p95), alpha =0.18) +geom_line(data = df_long, aes(x = Mes, y = TRM, group = Trayectoria), linewidth =0.25, alpha =0.35) +geom_line(data = sum_df, aes(x = Mes, y = p50), linewidth =1.0) +scale_y_continuous(labels =label_number(big.mark =".", decimal.mark =",")) +labs(title ="Simulación BMG de la TRM (mensual): abanico 5–95%, mediana y 30 trayectorias",subtitle =paste0("S0 = ", round(S0,2)," | μ̂ = ", round(mu_hat*100,2), "% mensual, σ̂ = ", round(sg_hat*100,2), "% mensual"," | H = ", H, " meses, N = ", N_paths),x ="Mes", y ="TRM (COP por USD)" ) +theme_minimal(base_size =12)
1.4.5 Crédito en dólares con sistema francés (cuota fija)
Sea un precio de maquinaria (P_{}) y una TRM inicial (S_0). El precio en USD es (P_{} = ). Si el pago inicial es ( = 10% ), el crédito cubre el (1-): \[
\text{Down payment} = \alpha\, P_{\text{USD}},
\qquad
\text{Principal} = L_0 = (1-\alpha)\, P_{\text{USD}} .
\]
Con tasa anual en dólares (r_{}) y pagos mensuales por (T=10) años ((n = 12T) cuotas), la tasa mensual es \[
i =
\begin{cases}
\dfrac{r_{\text{ann}}}{12} & \text{(APR)}\\[6pt]
(1+r_{\text{ann}})^{1/12}-1 & \text{(EAR)}
\end{cases}
\]
La cuota fija (sistema francés) es \[
C = L_0 \cdot \frac{i(1+i)^n}{(1+i)^n-1}.
\]
La descomposición en el periodo (t) es: \[
\text{Interés}_t = i \, \text{Saldo}_{t-1},
\qquad
\text{Amortización}_t = C - \text{Interés}_t,
\qquad
\text{Saldo}_t = \text{Saldo}_{t-1} - \text{Amortización}_t.
\]
Mostrar código
suppressPackageStartupMessages({library(dplyr); library(lubridate); library(knitr); library(quantmod)})# --- 1) Parámetros base ---P_COP <-300e6# precio maquinaria en COP# Usa tu S0 (última TRM) si ya existe; si no, lo obtenemos de USDCOP=Xif (!exists("S0")) {getSymbols("USDCOP=X", from =Sys.Date()-60, to =Sys.Date(), auto.assign =TRUE) S0 <-as.numeric(last(Cl(`USDCOP=X`)))}P_USD <- P_COP / S0 # precio en dólaresalpha <-0.10# 10% de inicialyears <-10n <-12* years # cuotas# Tasa anual en USD (ajústala a la que elijas para el banco)r_ann <-0.055# 5.5% anual (ejemplo)use_EAR <-FALSE# FALSE = APR simple; TRUE = EAR (efectiva)# --- 2) Derivados y principal ---i <-if (use_EAR) (1+ r_ann)^(1/12) -1else r_ann/12down_payment_usd <- alpha * P_USDL0 <- (1- alpha) * P_USD # principal a financiar (90%)# Cuota fija (sistema francés)C <- L0 * (i * (1+ i)^n) / ((1+ i)^n -1)# --- 3) Cronograma de amortización mensual ---schedule <-tibble(t =1:n,Fecha =seq(from =floor_date(Sys.Date(), unit ="month") +months(1),by ="month", length.out = n)) |>mutate(Interes = i *ifelse(t ==1, L0, NA_real_),Amortizacion =NA_real_,Cuota = C,Saldo =NA_real_ )# Relleno iterativo del saldosaldo <- L0for (k in1:n) { interes_k <- i * saldo amort_k <- C - interes_k saldo <- saldo - amort_k schedule$Interes[k] <- interes_k schedule$Amortizacion[k] <- amort_k schedule$Saldo[k] <-max(saldo, 0)}# --- 4) Resumen del crédito ---resumen_credito <-tibble(`TRM inicial (S0)`=round(S0, 2),`Precio maquinaria (USD)`=round(P_USD, 2),`Inicial 10% (USD)`=round(down_payment_usd, 2),`Principal financiado (USD)`=round(L0, 2),`Tasa anual (USD)`=paste0(round(100*r_ann, 2), "%", ifelse(use_EAR," (EAR)"," (APR)")),`Cuota mensual (USD)`=round(C, 2),`N° cuotas`= n,`Interés total (USD)`=round(sum(schedule$Interes), 2),`Pago total (USD)`=round(sum(schedule$Cuota) + down_payment_usd, 2),`Flujo inicial total (USD)`=round(down_payment_usd, 2))# --- 5) Salidas ordenadas ---kable(resumen_credito, caption ="Resumen del crédito en USD (sistema francés, 10% de inicial)")
Resumen del crédito en USD (sistema francés, 10% de inicial)
TRM inicial (S0)
Precio maquinaria (USD)
Inicial 10% (USD)
Principal financiado (USD)
Tasa anual (USD)
Cuota mensual (USD)
N° cuotas
Interés total (USD)
Pago total (USD)
Flujo inicial total (USD)
3856
77800.83
7780.08
70020.75
5.5% (APR)
759.91
120
21168.35
98969.18
7780.08
Mostrar código
kable( schedule |>mutate(across(c(Interes, Amortizacion, Cuota, Saldo), ~round(.x, 2))) |>select(Fecha, Cuota, Interes, Amortizacion, Saldo) |>head(12),caption ="Cronograma mensual: primeros 12 meses (USD)")
Cronograma mensual: primeros 12 meses (USD)
Fecha
Cuota
Interes
Amortizacion
Saldo
2025-11-01
759.91
320.93
438.98
69581.77
2025-12-01
759.91
318.92
440.99
69140.77
2026-01-01
759.91
316.90
443.01
68697.76
2026-02-01
759.91
314.86
445.04
68252.72
2026-03-01
759.91
312.82
447.08
67805.63
2026-04-01
759.91
310.78
449.13
67356.50
2026-05-01
759.91
308.72
451.19
66905.31
2026-06-01
759.91
306.65
453.26
66452.05
2026-07-01
759.91
304.57
455.34
65996.71
2026-08-01
759.91
302.48
457.42
65539.28
2026-09-01
759.91
300.39
459.52
65079.76
2026-10-01
759.91
298.28
461.63
64618.14
Mostrar código
# Si quieres guardar el cronograma completo para usarlo luego:credito_schedule_usd <- schedule
El crédito en USD financiado al 90% de la compra (≈ USD 70,020.75) con tasa 5.5% APR a 10 años genera una cuota fija de ~USD 759.91. El costo financiero total (intereses) asciende a ~USD 21,168, para un pago total de ~USD 98,969 más la inicial (USD 7,780). El cronograma muestra el patrón típico del sistema francés: al inicio la cuota se compone mayoritariamente de intereses (p. ej., nov-2025: USD 320.93) y, mes a mes, la amortización aumenta (USD 438.98 → 461.63) mientras el saldo disminuye (USD 70,020 → 64,618 en 12 meses). En términos de riesgo, el flujo en USD es estable; la exposición relevante para el proyecto será la TRM al convertir a COP y, en menor medida, cambios en la tasa si el crédito no fuera estrictamente a tasa fija.
1.4.6Proceso de futuro.
Use la información de la BVC de un futuro de su preferencia, use toda la información histórica presentada del producto para calcular los retornos y la desviación estándar mensual.
1.4.7 Retornos y volatilidad mensual de un futuro BVC
Sea (P_t) el precio de liquidación del futuro en el cierre del mes (t). El retorno logarítmico mensual se define como: \[
r_t = \ln\!\left(\frac{P_t}{P_{t-1}}\right).
\]
Con la serie ({r_t}_{t=1}^n), el retorno promedio mensual y la desviación estándar mensual (volatilidad) son: \[
\bar r = \frac{1}{n}\sum_{t=1}^n r_t,
\qquad
\sigma_m = \sqrt{\frac{1}{n-1}\sum_{t=1}^n (r_t-\bar r)^2}.
\]
Para comparación anual, se suele usar: \[
\mu_{\text{anual}} \approx 12\,\bar r,
\qquad
\sigma_{\text{anual}} \approx \sqrt{12}\,\sigma_m.
\]
Dado que el histórico en CSV/XLSX de futuros listados en la BVC no está disponible públicamente sin acceso de bróker/plataforma, y para no frenar el desarrollo, trabajamos con un futuro continuo ampliamente seguido en Yahoo Finance. Elegimos WTI Crude Oil (CL=F) por su profundidad y cobertura histórica suficiente para estimar retornos mensuales y volatilidad de forma robusta.
Mostrar código
suppressPackageStartupMessages({library(quantmod); library(dplyr); library(xts); library(zoo); library(knitr); library(ggplot2)})# Lista de futuros continuos confiables en Yahoosymbols_try <-c("CL=F", # WTI Crude Oil"GC=F", # Gold"ES=F", # E-mini S&P 500"SI=F", # Silver"HG=F", # Copper"ZC=F", # Corn"ZW=F", # Wheat"ZS=F") # Soybeanspx_daily <-NULLsym_used <-NA_character_for (sym in symbols_try) { xts_try <-tryCatch(getSymbols(sym, from ="2010-01-01", to =Sys.Date(),auto.assign =FALSE), # <--- clave: devuelve xts directamenteerror =function(e) NULL,warning =function(w) suppressWarnings(tryCatch(getSymbols(sym, from ="2010-01-01", to =Sys.Date(),auto.assign =FALSE), error =function(e) NULL)) )if (!is.null(xts_try) &&NROW(xts_try) >20) { px_daily <-Cl(xts_try) sym_used <- symbreak }}if (is.null(px_daily)) stop("No se pudo descargar ningún futuro de la lista. Revisa conexión o firewall.")# Agregación mensualpx_month <-to.monthly(px_daily, indexAt ="lastof", OHLC =FALSE)colnames(px_month) <-"Precio"# Retornos log mensualesret_m <-na.omit(diff(log(px_month)))mu_m <-mean(ret_m)[[1]]sd_m <-sd(ret_m)[[1]]resumen <- tibble::tibble(`Futuro (Yahoo)`= sym_used,`Periodo`=paste(format(start(px_month), "%Y-%m"), "→", format(end(px_month), "%Y-%m")),`Obs (mensuales)`=nrow(ret_m),`Retorno medio mensual (%)`=round(100*mu_m, 3),`Desv.est. mensual (%)`=round(100*sd_m, 3),`Retorno medio anual (%)`=round(100*mu_m*12, 2),`Volatilidad anual (%)`=round(100*sd_m*sqrt(12), 2))knitr::kable(resumen, caption ="Futuro (Yahoo): retornos logarítmicos mensuales y volatilidad")
Futuro (Yahoo): retornos logarítmicos mensuales y volatilidad
El WTI muestra un retorno medio mensual de −0,095 % (≈ −1,14 % anual), lo que sugiere una tendencia plana/ligeramente negativa en el largo plazo. La volatilidad mensual de 11,36 % (≈ 39,36 % anual) es elevada, coherente con un activo cíclico y sensible a shocks de oferta/demanda. En los últimos 12 meses aparecen oscilaciones marcadas, destacando abr-2025: −20,54 % y tramos de recuperación (jun–jul 2025 con >6 % mensual), seguidos de nuevas caídas (ago–oct). En términos de cobertura, este perfil implica requisitos de margen exigentes, mark-to-market volátil y la necesidad de dimensionar el hedge con cautela (p. ej., escalonando entradas o ajustando el tamaño en función de la volatilidad reciente).
1.4.8 Simule por medio de BMG mensual el comportamiento del futuro
Mostrar código
suppressPackageStartupMessages({library(quantmod); library(dplyr); library(tidyr); library(xts); library(zoo)library(ggplot2); library(knitr)})# -------------------------------# 1) Parámetros y descarga# -------------------------------symbol <-"CL=F"# futuro continuo a usar (cámbialo si deseas)fecha_ini <-"2010-01-01"# Descarga robusta (sin auto-assign para evitar nombres raros)px_daily <-tryCatch( { xts_obj <-getSymbols(symbol, from = fecha_ini, to =Sys.Date(),auto.assign =FALSE)Cl(xts_obj) },error =function(e) stop("No se pudo descargar el símbolo de Yahoo. Revisa conexión o cambia 'symbol'."))# A mensualpx_m <-to.monthly(px_daily, indexAt ="lastof", OHLC =FALSE)colnames(px_m) <-"Precio"# Retornos log mensuales y parámetros históricosret_m <-na.omit(diff(log(px_m)))mu_hat <-as.numeric(mean(ret_m)) # media mensualsg_hat <-as.numeric(sd(ret_m)) # desviación mensual# -------------------------------# 2) Configuración de simulación# -------------------------------set.seed(123)H <-12# horizonte en meses (ajusta si quieres)N_paths <-5000# nº trayectoriasDelta <-1.0# paso mensualS0 <-as.numeric(last(px_m)) # último precio mensual observado# (Opcional) Escenarios: multiplicador de volatilidadvol_mult <-1.0# 1.0 = histórico; >1 estrés; <1 relajadomu_sim <- mu_hatsg_sim <- sg_hat * vol_mult# -------------------------------# 3) Simulación BMG# -------------------------------Z <-matrix(rnorm(H * N_paths), nrow = H, ncol = N_paths)drift <- (mu_sim -0.5* sg_sim^2) * Deltashock <- sg_sim *sqrt(Delta) * Zlog_increments <-sweep(shock, 1, drift, `+`) # H x Nlog_levels <-apply(log_increments, 2, cumsum)S_paths <-exp( log(S0) +rbind(rep(0, N_paths), log_levels) ) # (H+1) x N# Fechas simuladas (mensuales)dates_sim <-seq.Date(from =as.Date(end(px_m)), by ="month", length.out = H +1)# -------------------------------# 4) Resumen por mes (cuantiles)# -------------------------------sum_tab <-apply(S_paths, 1, quantile, probs =c(0.05, 0.5, 0.95))sum_df <-tibble(Mes = dates_sim,p05 = sum_tab[1,],p50 = sum_tab[2,],p95 = sum_tab[3,])knitr::kable( sum_df %>%mutate(across(c(p05, p50, p95), ~round(.x, 2))),caption =paste0(symbol, " – Simulación BMG mensual: cuantiles 5%, 50% y 95%"))
CL=F – Simulación BMG mensual: cuantiles 5%, 50% y 95%
La simulación BMG mensual del futuro del petróleo WTI (CL=F) muestra que, partiendo de un precio actual de USD 60,88 y bajo un retorno promedio histórico de −0,1 % mensual, el comportamiento esperado tiende a ser estable o ligeramente descendente en el horizonte de un año.
El intervalo de confianza (zona gris) evidencia una alta dispersión, producto de la volatilidad mensual estimada en 11,36 %, lo que implica que los precios podrían fluctuar entre valores cercanos a USD 45 y USD 110 hacia finales del periodo. En términos prácticos, el futuro del WTI conserva un riesgo elevado, característico de los commodities energéticos, donde shocks de oferta o geopolíticos pueden generar desviaciones fuertes respecto al valor esperado, lo que resalta la importancia de estrategias de cobertura o ajuste dinámico del portafolio.
Source Code
---title: "Trabajo final"format: html: toc: true toc-depth: 3 number-sections: true html-math-method: mathjax # render de fórmulas en HTML code-fold: true # pliega el código por sección code-summary: "Mostrar código" code-tools: true # menú flotante: Toggle All Code / Copy / Download df-print: paged # tablas largas amigablesexecute: echo: true # mostrar código por defecto (puedes ocultarlo por chunk) warning: false message: falseeditor: visual---# Solución**Información importante**Este documento sirve como guía para el ejercicio práctico del desarrollo semestral de aprendizaje, el cual será realizado por grupos de máximo 3 estudiantes preestablecidas. Cada grupo deberá llevar a cabo un proceso único e inédito; cualquier coincidencia de desarrollo que supere el 40% será sancionada con una calificación de 0.0 para los grupos involucrados. La evaluación del trabajo se realizará por partes, cada una con un valor diferenciado que contribuirá a alcanzar el 100% de la calificación final. Para analizar el proceso requerido use las diapositivas proporcionadas en clase y cualquier información de red relevante. Tenga en cuenta que se dará mayor importancia a los análisis desarrollados que a los cálculos desarrollados.Presente los resultados en RPUBS con el nombre de los integrantes mostrando los puntos desarrollados en orden y debe enviarse en plataforma virtual. Fecha límite de entrega: 31 de octubre de 2025. Para los ejercicios use año comercial de 252 días.## Solución parte 1: Aplicación de cobertura con futuros de índice bursátil**Definición del problema**En el año 2025 se desea realizar inversiones en bolsa con objeto de inversión a 4 años. El objetivo es establecer un portafolio de inversión utilizando 3 acciones de preferencia del mismo índice bursátil. Se dispone de un capital de **10.000.000** para realizar inversiones en acciones desde el 31 de julio de 2025. Para construir un portafolio óptimo de media varianza, se considerarán entre 5 y 10 años de información histórica hasta la fecha de inicio de las inversiones **(31 de julio).**Los futuros del índice bursátil serán pagaderos de forma mensual. Los criterios relacionados con los futuros del índice, como la garantía y el tamaño del contrato, se obtendrán a través de la plataforma bursátil, siendo recomendable el uso de Bloomberg o cualquier plataforma que entregue información de acciones para este fin.```{r, warning=FALSE, message=FALSE}## Paquetes importantes# --- 2. Paquetes base ---pkgs <-c("tidyverse","lubridate","readxl","janitor","here","glue","quantmod","PerformanceAnalytics","xts","zoo","quadprog","PortfolioAnalytics","tseries","RcppRoll", "DT")to_install <- pkgs[!pkgs %in%installed.packages()[, "Package"]]if(length(to_install)) install.packages(to_install, Ncpus =2L)invisible(lapply(pkgs, library, character.only =TRUE))```**Introducción**Para el desarrollo del trabajo se seleccionan tres acciones del índice NASDAQ 100: Apple (AAPL), Microsoft (MSFT) y Alphabet (GOOG). El análisis abarca el periodo del **31 de julio de 2015 al 31 de julio de 2025**, con el objetivo de construir un portafolio óptimo de media-varianza a partir de información histórica de retornos y riesgos.Se dispone de un capital de \$10.000.000, que se invertirá a partir del 31 de julio de 2025 con un horizonte de cuatro años. Posteriormente, se evaluará la cobertura del portafolio mediante futuros del NASDAQ 100, calculando el número óptimo de contratos para mitigar el riesgo sistemático. El estudio utiliza datos diarios, un año comercial de 252 días y métodos de optimización de Markowitz (1952).### Portafolio Optimo de inversión1) **Realice un análisis fundamental de las acciones elegidas y cuál es la expectativa de los precios hasta el 31/07/2025****3. Apple Inc. (AAPL)**Contexto y fundamentosApple es un gigante tecnológico con ecosistema integrado de hardware (iPhone, Mac, iPad, Watch y accesorios) y servicios (App Store, iCloud, Apple Music/TV+, etc.).Según su reporte Q2 fiscal 2025, registró ingresos de US\$ 95.4 mil millones, +5 % a/a, y EPS diluido de US\$ 1.65, +8 % a/a. AppleDesde ChartMill: Margen bruto \~46.68 %, margen operativo \~31.87 %, ROE \~150.8 %. Esto sitúa a Apple entre los mejores de su industria. ChartMillSu negocio de servicios está registrando hitos: los servicios aportan cada vez más a los ingresos, lo cual mejora el perfil de margen y reduce dependencia del ciclo de iPhone. Por ejemplo, en Q3 del año informaron récord de servicios. InvestopediaApple está invirtiendo en manufactura avanzada, IA y cadenas de suministro en EE.UU. (según Wikipedia resumen 2025). en.wikipedia.orgExpectativas de crecimientoDado su tamaño (capitalización de varios billones de USD) y su base instalada, Apple ya no crece al ritmo de startups; el crecimiento será moderado pero sólido. Por ejemplo, analistas estimaron un target de \~US\$ 235-261 para 1 año. www.alphaspread.com +1Otras fuentes más conservadoras lo ubican \~US\$ 180 para 2025 si la economía decae o el ciclo de renovación se frena. cleverence.comConsiderando el horizonte hasta 31/07/2025 (\~4 años desde la fecha de inversión), y suponiendo un crecimiento anual moderado quizá del 6-8 % compuesto (por ejemplo, +5 % ingresos y +8 % EPS, asumiendo reinversión), se podría proyectar un precio de \~US\$ 280-300 si todo va bien; pero también escenarios de \~US\$ 230-250 si moderado.Riesgos claveCiclo del iPhone: si el lanzamiento de nuevos modelos fracasa o hay menor demanda, los ingresos pueden estancarse. (Ver artículo sobre WWDC 2025: Apple “está en riesgo de fallar su tendencia de largo plazo”). Seeking Alpha**Macro/Aranceles:** Apple depende de manufactura global, especialmente Asia. Los aranceles o interrupciones en cadena afectan los costos y márgenes. KiplingerSaturación del mercado de smartphones: En mercados maduros puede haber menor crecimiento.**Expectativa de precio para 31/07/2025**Tomando un punto intermedio entre optimismo moderado y prudencia, proyectaría ≈ US\$ 280 por acción hacia el 31 de julio de 2025.Si el portafolio está valorado en dólares o convertido a tu moneda, este valor lo integrarás como expectativa de retorno**2. Microsoft Corporation (MSFT)**Resumen y fundamentos:Microsoft mantiene una posición dominante en el mercado global de software y servicios en la nube. Su ecosistema incluye Azure, Microsoft 365, LinkedIn, Xbox y, más recientemente, la integración de IA generativa en todos sus productos tras su alianza con OpenAI. Según ChartMill (2025), se espera que las utilidades por acción (EPS) crezcan 15,2 % anual y los ingresos un 12,7 % anual. En su último reporte trimestral (FY 2025 Q4), Microsoft registró US\$ 76,4 mil millones en ingresos y una utilidad neta de US\$ 27,3 mil millones, lo que representa un crecimiento interanual del 24 % (RoboForex, 2025).Perspectiva: El motor principal sigue siendo Azure, que se expande a tasas de doble dígito. Además, la adopción de herramientas de IA como Copilot en Office y Windows podría elevar los márgenes de rentabilidad en 2025-2026. Barron’s (2025) y AlphaSpread (2025) ubican el precio objetivo entre US\$ 600 y US\$ 750, lo que implicaría una valorización cercana al 15-20 % en el próximo año.Riesgos:- Competencia intensa en IA y nube (Amazon, Google, Nvidia).- Riesgo de sobrevaloración por múltiplos altos.- Retrasos en monetización de productos IA.**3. Alphabet Inc. (GOOG)**Resumen y fundamentos: Alphabet Inc. —matriz de Google— domina la publicidad digital global, con negocios diversificados en Google Search, YouTube, Android, Google Cloud y DeepMind. En su reporte del segundo trimestre de 2025, Alphabet reportó US\$ 96,4 mil millones en ingresos y una utilidad por acción (EPS) de US\$ 2,31, un aumento del 14 % interanual (RoboForex, 2025). Su segmento Google Cloud creció más del 30 % en ingresos, mientras que YouTube Ads mostró recuperación significativa tras la desaceleración publicitaria de 2023-2024.Perspectiva: Alphabet está invirtiendo fuertemente en infraestructura de IA y data centers. Simply Wall St (2025) estima un crecimiento promedio del EPS de 14-15 % anual. Aun con riesgos regulatorios (antitrust en EE.UU. y UE), se proyecta un precio objetivo entre US\$ 300 y US\$ 400 a 12 meses.Riesgos:Demandas y restricciones antimonopolio.Alta dependencia de ingresos publicitarios (\~70 %).Gastos de capital crecientes en IA y centros de datos.### **Calcule los retornos anuales, la desviación estándar anual y la matriz de varianzas y covarianzas para cada acción.**```{r}# --- Parámetros del problema ---SYMS <-c("AAPL","MSFT","GOOG")DATE_FROM <-"2015-07-31"DATE_TO <-"2025-07-31"TRADING_DAYS <-252# año comercial# --- 1) Descargar precios ajustados desde Yahoo Finance ---getSymbols(SYMS, src ="yahoo", from = DATE_FROM, to = DATE_TO, auto.assign =TRUE)prices <-na.omit(merge(Ad(AAPL), Ad(MSFT), Ad(GOOG)))colnames(prices) <- SYMS```Podemos observar la matriz de los precio de cierre de las acciones elegidas.```{r}#| label: tabla-precios-gt#| message: false#| warning: falselibrary(gt)library(zoo) # <-- agrega esto antes de usar coredata/indexprices_df <-data.frame(Date =index(prices),coredata(prices),row.names =NULL)gt(tail(prices_df, 30)) |>fmt_currency(columns =2:ncol(prices_df), currency ="USD", decimals =2) |>tab_options(table.font.size =px(14)) |>tab_header(title =md("**Precios ajustados (últimos 30 registros)**")) |>opt_table_outline()```**Calculo de retornos**### Definición teórica de los retornosEn el análisis financiero, el **retorno** de un activo mide la ganancia o pérdida relativa respecto a su precio inicial. Es una medida esencial para evaluar el rendimiento y comparar activos en el tiempo.1. **Retorno simple (aritmético)** $$ R_t \;=\; \frac{P_t - P_{t-1}}{P_{t-1}} \;=\; \frac{P_t}{P_{t-1}} - 1 $$ donde (P_t) es el precio en el periodo (t) y (P\_{t-1}) el del periodo anterior. Representa el cambio porcentual directo entre dos precios consecutivos.2. **Retorno logarítmico (continuamente compuesto)** $$ r_t \;=\; \ln\!\left(\frac{P_t}{P_{t-1}}\right) $$ Ventajas prácticas: (i) es aditivo en el tiempo, (ii) suele aproximar mejor la normalidad, (iii) facilita el cálculo e interpretación de métricas del portafolio.**Anualización** (año comercial de 252 días hábiles):$$\mu_{\text{anual}} = \bar r_{\text{diario}} \cdot 252\qquad\text{y}\qquad\sigma_{\text{anual}} = s_{\text{diario}} \cdot \sqrt{252}.$$Estas transformaciones permiten expresar **rendimiento** y **riesgo** en base anual, compararlos entre activos y utilizarlos en la construcción de portafolios eficientes (media–varianza de Markowitz).**1) Rendimiento y riesgo por acción**MSFT: mayor media anual (25,47%) y menor volatilidad (27,14%). Es el perfil más atractivo del trío: más retorno con menos riesgo.AAPL: media 20,46% con volatilidad 29,34%. Buen retorno, pero más riesgosa que MSFT.GOOG: media 18,54% y volatilidad 28,75%. Es la de menor retorno con riesgo similar a AAPL.Lectura de eficiencia (aprox. “riesgo por unidad de retorno”, σ/μ):MSFT ≈ 1,07 (mejor), AAPL ≈ 1,43, GOOG ≈ 1,55. → MSFT domina en términos de calidad de retorno.```{r}#| label: calculo-retornos#| message: false#| warning: falselibrary(PerformanceAnalytics)library(xts)library(dplyr)library(knitr)# 1. Retornos simples y logarítmicos diariosreturns_simple <-na.omit(Return.calculate(prices, method ="discrete"))returns_log <-na.omit(Return.calculate(prices, method ="log"))# 2. Estadísticos anuales desde retornos diariosTRADING_DAYS <-252ret_mean_ann <-colMeans(returns_log) * TRADING_DAYSret_sd_ann <-apply(returns_log, 2, sd) *sqrt(TRADING_DAYS)# 3. Matriz de covarianzas y correlaciones anualizadascov_matrix_ann <-cov(returns_log) * TRADING_DAYScor_matrix <-cor(returns_log)# 4. Mostrar resultadostabla_retornos <-tibble(Activo =colnames(returns_log),`Media anual (%)`= ret_mean_ann *100,`Desv.est. anual (%)`= ret_sd_ann *100)kable(tabla_retornos, digits =2, caption ="Media y desviación estándar anualizadas de los retornos logarítmicos")```**Correlaciones (diversificación)**Altas y positivas dentro del mismo sector tech:AAPL–MSFT = 0,689, MSFT–GOOG = 0,729, AAPL–GOOG = 0,616.La más baja es AAPL–GOOG (0,616) → es el par que más diversifica dentro del trío.Implicación: habrá beneficio de diversificación, pero limitado; el riesgo sistemático del sector sigue siendo relevante.```{r}kable(cor_matrix, digits =4, caption ="Matriz de correlaciones entre las acciones")```**Varianzas y covarianzas (anualizadas)**Las varianzas (diagonal) concuerdan con las σ reportadas:Var(AAPL) 0,0861 (σ≈29,3%), Var(MSFT) 0,0737 (σ≈27,1%), Var(GOOG) 0,0827 (σ≈28,7%). → MSFT confirma ser la menos volátil.Las covarianzas positivas (p. ej., AAPL–MSFT 0,0549) reflejan las correlaciones altas: los activos tienden a moverse juntos.```{r}kable(cov_matrix_ann, digits =6, caption ="Matriz de varianzas y covarianzas anualizada")```### **Calcule el retorno esperado, la desviación estándar y el Sharpe Ratio del portafolio**#### Definición teórica del retorno esperado, desviación estándar y Sharpe Ratio del portafolioEn el contexto de la **teoría de portafolios de Markowitz**, los tres indicadores fundamentales para evaluar una cartera de inversión son el **retorno esperado**, la **desviación estándar** (o volatilidad) y el **Sharpe Ratio**.**Retorno esperado del portafolio** El retorno esperado ((E\[R_p\])) mide el rendimiento promedio ponderado de los activos que componen el portafolio:$$E[R_p] = \sum_{i=1}^{n} w_i \, E[R_i]$$donde: - (w_i) = proporción de capital invertida en el activo (i), - (E\[R_i\]) = retorno esperado del activo (i), - (n) = número de activos en el portafolio.Este indicador representa la ganancia media esperada de la cartera, considerando las ponderaciones de cada activo.**Desviación estándar del portafolio** La desviación estándar ((\sigma\_p)) cuantifica el **riesgo total** o la variabilidad de los retornos del portafolio:$$\sigma_p = \sqrt{w^{\top} \Sigma w}$$donde: - (w) = vector de pesos del portafolio, - (\Sigma) = matriz de varianzas y covarianzas de los retornos de los activos.La matriz (\Sigma) incluye tanto las varianzas individuales ((\sigma\_i\^2)) como las covarianzas entre pares de activos, que capturan los efectos de **diversificación**.**Sharpe Ratio** El **Sharpe Ratio** mide la **eficiencia del portafolio** en términos de retorno ajustado al riesgo:$$SR = \frac{E[R_p] - R_f}{\sigma_p}$$donde: - (R_f) = tasa libre de riesgo (por ejemplo, bono del Tesoro a 3 o 12 meses), - (E\[R_p\] - R_f) = prima de riesgo del portafolio.Un **Sharpe Ratio más alto** indica un **mejor desempeño**, ya que implica que el portafolio obtiene mayor retorno por cada unidad de riesgo asumida.```{r}#| label: portafolio-metricas#| message: false#| warning: falselibrary(knitr)TRADING_DAYS <-252# --- (A) Si ya tienes 'returns_log', 'ann_mean_from_daily' y 'cov_ann_from_daily', omite este bloque ---if (!exists("returns_log") ||!exists("ann_mean_from_daily") ||!exists("cov_ann_from_daily")) {# Recalcular desde 'prices' returns_log <-na.omit(PerformanceAnalytics::Return.calculate(prices, method ="log")) ann_mean_from_daily <-colMeans(returns_log) * TRADING_DAYS # μ anual cov_ann_from_daily <-cov(returns_log) * TRADING_DAYS # Σ anual}mu <-as.numeric(ann_mean_from_daily) # vector de medias anualizadasnames(mu) <-colnames(returns_log)Sigma <-as.matrix(cov_ann_from_daily) # matriz de var-cov anualizadaones <-rep(1, length(mu))# --- Define la tasa libre de riesgo anual (ajústala según tu caso) ---rf <-0.03# 3% anual (ejemplo). Cambia por tu referencia (ej. UST 3M/1Y o IBR)# --- Funciones auxiliares ---ret_port <-function(w, mu) as.numeric(sum(w * mu))sd_port <-function(w, Sigma) as.numeric(sqrt(t(w) %*% Sigma %*% w))sharpe <-function(w, mu, Sigma, rf) (ret_port(w, mu) - rf) /sd_port(w, Sigma)# === 1) Portafolio EQUIPONDERADO ===w_eq <-rep(1/length(mu), length(mu))Rp_eq <-ret_port(w_eq, mu)Sd_eq <-sd_port(w_eq, Sigma)SR_eq <- (Rp_eq - rf) / Sd_eq# === 2) Portafolio de TANGENCIA (máximo Sharpe) ===# Fórmula cerrada: w* ∝ Σ^{-1} (μ - rf * 1), normalizado para que sum(w*) = 1Sigma_inv <-solve(Sigma)z <- Sigma_inv %*% (mu - rf * ones)w_tan <-as.numeric(z /sum(z)) # normaliza a suma 1Rp_tan <-ret_port(w_tan, mu)Sd_tan <-sd_port(w_tan, Sigma)SR_tan <- (Rp_tan - rf) / Sd_tan# --- Resultados tabulares ---res_pesos <-tibble(Activo =names(mu),`w_eq`=round(w_eq, 4),`w_tangencia`=round(w_tan, 4))res_metricas <-tibble(Portafolio =c("Equi-ponderado", "Tangencia (máx Sharpe)"),`Retorno esperado (anual)`=c(Rp_eq, Rp_tan),`Desv.est. (anual)`=c(Sd_eq, Sd_tan),`Sharpe Ratio`=c(SR_eq, SR_tan)) |>mutate(across(`Retorno esperado (anual)`:`Desv.est. (anual)`, ~round(.x, 4)),`Sharpe Ratio`=round(`Sharpe Ratio`, 3))``````{r}kable(res_pesos, align ="lrr", caption ="Pesos del portafolio: equi-ponderado vs. tangencia")```Al comparar los resultados obtenidos para el portafolio equi-ponderado y el portafolio de tangencia, se observa que el segundo presenta un mejor desempeño general. El portafolio equi-ponderado, que distribuye el capital de manera uniforme entre las tres acciones (AAPL, MSFT y GOOG), alcanza un retorno esperado anual del 21,49% con una desviación estándar del 25,16%, lo que se traduce en un Sharpe Ratio de 0,735.Por su parte, el portafolio de tangencia —que busca maximizar el Sharpe Ratio— obtiene un retorno esperado anual del 26,24% y una desviación estándar del 27,84%, alcanzando un Sharpe Ratio superior de 0,835. Esto indica que, aunque el riesgo del portafolio aumenta ligeramente, la rentabilidad adicional compensa dicho incremento, generando una mejor relación riesgo-retorno.En cuanto a la composición del portafolio óptimo, el modelo asigna un peso mayoritario a Microsoft (MSFT) con 108,68%, una participación reducida de Apple (AAPL) con 9,12%, y una posición corta en Google (GOOG) de -17,8%. Este resultado refleja que, dentro del conjunto analizado, Microsoft es la acción con el mejor equilibrio entre rendimiento esperado y volatilidad, mientras que Google contribuye negativamente a la eficiencia del portafolio, razón por la cual el modelo sugiere reducir su exposición.En síntesis, el portafolio de tangencia resulta ser el más eficiente en términos de la teoría media-varianza, ya que logra un mayor retorno esperado por cada unidad de riesgo asumido. En la práctica, si se aplicaran restricciones que impidan posiciones cortas, el peso negativo de Google se eliminaría, y los recursos se redistribuirían principalmente entre Microsoft y Apple, manteniendo una composición de portafolio conservadora pero eficiente.```{r}kable(res_metricas, align ="lrrr", caption ="Métricas del portafolio (anualizadas)")```### **Establezca los pesos óptimos para la inversión total del capital destinado**#### Definición teórica de los pesos óptimos del portafolioEl objetivo del modelo de **media–varianza** propuesto por *Harry Markowitz (1952)* es determinar la combinación de activos que **maximiza el rendimiento esperado** para un **nivel dado de riesgo**, o equivalentemente, **minimiza el riesgo** para un **nivel dado de retorno esperado**.Para un conjunto de ( n ) activos, se busca encontrar el vector de pesos ( w = (w_1, w_2, ..., w_n)\^\top ) que cumpla con:$$\min_w \; \frac{1}{2} w^{\top} \Sigma w\quad \text{sujeto a} \quad \begin{cases}w^{\top} \mu = R_p \\\sum_{i=1}^{n} w_i = 1\end{cases}$$donde: - ( \Sigma ) es la matriz de varianzas y covarianzas de los retornos de los activos,\- ( \mu ) es el vector de retornos esperados,\- ( R_p ) es el retorno objetivo del portafolio,\- ( w_i ) representa la proporción de capital invertida en el activo ( i ).La solución general de este problema se obtiene aplicando multiplicadores de Lagrange, y los pesos óptimos vienen dados por:$$w^* = \lambda_1 \Sigma^{-1} \mu + \lambda_2 \Sigma^{-1} \mathbf{1}$$donde ( \lambda\_1 ) y ( \lambda\_2 ) son parámetros que dependen del nivel de retorno objetivo ( R_p ) y de los coeficientes:$$A = \mathbf{1}^{\top} \Sigma^{-1} \mathbf{1}, \quadB = \mathbf{1}^{\top} \Sigma^{-1} \mu, \quadC = \mu^{\top} \Sigma^{-1} \mu, \quadD = AC - B^2.$$A partir de estos, se obtiene la frontera eficiente:$$\sigma_p^2 = \frac{A R_p^2 - 2 B R_p + C}{D}.$$------------------------------------------------------------------------**Caso especial: Portafolio de tangencia (máximo Sharpe)** Cuando existe una tasa libre de riesgo ( R_f ), el portafolio óptimo es aquel que **maximiza el Sharpe Ratio**, cuya solución cerrada es:$$w^*_{\text{tangencia}} = \frac{\Sigma^{-1} (\mu - R_f \mathbf{1})}{\mathbf{1}^{\top} \Sigma^{-1} (\mu - R_f \mathbf{1})}.$$Este portafolio se conoce como **portafolio de mercado** o **de tangencia**, y define la **línea del mercado de capitales (CML)**.\Una vez determinados los pesos relativos ( w\^\*\_{\text{tangencia}} ), la inversión total ( K ) se distribuye proporcionalmente como:$$I_i = K \cdot w_i^*,\quad \text{para } i = 1, 2, ..., n.$$Así, el valor monetario invertido en cada activo depende tanto de su peso óptimo como del capital total disponible.**Implementación**```{r}#| label: pesos-optimos-inversion-fix#| message: false#| warning: falselibrary(PerformanceAnalytics)library(quadprog)library(dplyr)library(tidyr)library(knitr)TRADING_DAYS <-252K <-1e7rf <-0.03stopifnot(exists("prices"))returns_log <-if (exists("returns_log")) returns_log elsena.omit(Return.calculate(prices, method ="log"))mu <-if (exists("mu")) mu elsecolMeans(returns_log) * TRADING_DAYSSigma <-if (exists("Sigma")) Sigma elsecov(returns_log) * TRADING_DAYSassets <-colnames(prices)ones <-rep(1, length(assets))ret_port <-function(w, mu) as.numeric(sum(w * mu))sd_port <-function(w, Sigma) as.numeric(sqrt(t(w) %*% Sigma %*% w))sharpe <-function(w, mu, Sigma, rf) (ret_port(w, mu) - rf) /sd_port(w, Sigma)# === Tangencia (sin restricciones) ===Sigma_inv <-solve(Sigma)z <- Sigma_inv %*% (mu - rf * ones)w_tan <-as.numeric(z /sum(z))names(w_tan) <- assetsRp_tan <-ret_port(w_tan, mu)Sd_tan <-sd_port(w_tan, Sigma)SR_tan <-sharpe(w_tan, mu, Sigma, rf)# === Long-only (resolver por grilla) ===solve_longonly_for_R <-function(R_target, mu, Sigma){ n <-length(mu) Dmat <-2* Sigma dvec <-rep(0, n) Amat <-cbind(ones, mu, diag(n)) # n x (2+n) bvec <-c(1, R_target, rep(0, n)) meq <-2tryCatch({ sol <-solve.QP(Dmat, dvec, Amat, bvec, meq = meq) w <-as.numeric(sol$solution)list(ok=TRUE, w=w) }, error=function(e) list(ok=FALSE, w=rep(NA, n)))}mu_min <-min(mu)*0.9mu_max <-max(mu)*1.1grid_R <-seq(mu_min, mu_max, length.out =60)cand <-lapply(grid_R, function(Rt){ ans <-solve_longonly_for_R(Rt, mu, Sigma)if(!ans$ok ||any(is.na(ans$w))) return(NULL) w <- ans$w# construir fila con nombres de columnas explícitos para los pesos df_w <-as.data.frame(t(w))colnames(df_w) <- assetsdata.frame(Rt = Rt,Rp =ret_port(w, mu),Sd =sd_port(w, Sigma),SR =sharpe(w, mu, Sigma, rf) ) |>bind_cols(df_w)})cand <-bind_rows(cand)stopifnot(ncol(cand) ==4+length(assets)) # Rt, Rp, Sd, SR + pesosbest_idx <-which.max(cand$SR)w_long <-as.numeric(cand[best_idx, (ncol(cand)-length(assets)+1):ncol(cand)])names(w_long) <- assetsRp_long <-ret_port(w_long, mu)Sd_long <-sd_port(w_long, Sigma)SR_long <-sharpe(w_long, mu, Sigma, rf)# === Tablas ===res_pesos <-tibble(Activo = assets,`w_tangencia`=round(w_tan, 4),`w_long_only`=round(w_long, 4))res_metricas <-tibble(Portafolio =c("Tangencia (sin restr.)","Máx Sharpe (long-only)"),`Retorno esperado (anual)`=c(Rp_tan, Rp_long),`Desv.est. (anual)`=c(Sd_tan, Sd_long),`Sharpe Ratio`=c(SR_tan, SR_long)) |>mutate(across(`Retorno esperado (anual)`:`Desv.est. (anual)`, ~round(.x, 4)),`Sharpe Ratio`=round(`Sharpe Ratio`, 3))kable(res_pesos, caption ="Pesos óptimos por método")kable(res_metricas, caption ="Métricas del portafolio (anualizadas)")# === Asignación de capital y n° de acciones (31-07-2025 o último disponible) ===# obtener último precio <= 2025-07-31 (si ese día no hay dato, usa el último previo)xts_cut <- prices[paste0("/", "2025-07-31")]if (NROW(xts_cut) ==0) xts_cut <- pricespx_last <-as.numeric(tail(xts_cut[, assets], 1))stopifnot(length(px_last) ==length(assets))names(px_last) <- assetsalloc_table <-function(w, label){ monto <- K * w shares <-floor(monto / px_last) invertido <- shares * px_last residuo <- monto - invertidotibble(Activo = assets,Precio =round(px_last, 2),Peso =round(w, 4),Monto =round(monto, 2),Acciones = shares,Invertido =round(invertido, 2),Efectivo_residual =round(residuo, 2),Metodo = label )}tbl_tan <-alloc_table(w_tan, "Tangencia")tbl_long <-alloc_table(w_long, "Máx Sharpe (long-only)")kable(tbl_tan, caption ="Asignación de capital y acciones — Tangencia (sin restricciones)")kable(tbl_long, caption ="Asignación de capital y acciones — Máx Sharpe (long-only)")```**Vizualización de la curva**El gráfico presentado muestra de forma visual la relación entre riesgo y retorno de las combinaciones posibles de inversión entre las tres acciones seleccionadas (AAPL, MSFT y GOOG). La curva negra representa la frontera eficiente, es decir, el conjunto de portafolios que ofrecen el mayor rendimiento esperado para cada nivel de riesgo. Sobre esta frontera se identifica el portafolio de tangencia, que corresponde al punto en el cual la línea del mercado de capitales (CML) —trazada en línea discontinua— es tangente a la frontera eficiente. Este punto marca la combinación óptima entre el activo libre de riesgo y el portafolio riesgoso, maximizando el rendimiento ajustado al riesgo (Sharpe Ratio).Los activos individuales se ubican por debajo de la CML, lo que evidencia que ningún activo aislado ofrece una relación riesgo–retorno superior a la del portafolio diversificado. En particular, el portafolio de tangencia logra un retorno esperado anual de 26,24% con una desviación estándar de 27,84%, alcanzando un Sharpe Ratio de 0,835, el más alto de todos los portafolios analizados.En cuanto a la composición, el modelo sin restricciones asigna un peso dominante a Microsoft (108,68%), un peso reducido a Apple (9,12%) y una posición corta en Google (-17,80%), lo que refleja que MSFT ofrece el mejor equilibrio entre rentabilidad y volatilidad, mientras que GOOG contribuye negativamente a la eficiencia del portafolio. Al imponer restricciones long-only, los pesos se ajustan a 93,32% para MSFT, 6,68% para AAPL y 0% para GOOG, eliminando la posición corta y manteniendo prácticamente el mismo nivel de eficiencia (Sharpe Ratio = 0,828).La asignación monetaria de un capital total de 10.000.000 muestra que, bajo el esquema sin restricciones, se comprarían aproximadamente 21.210 acciones de MSFT, 4.366 de AAPL y se venderían en corto 9.025 de GOOG, mientras que bajo el esquema long-only se adquirirían 18.212 acciones de MSFT y 3.199 de AAPL, con una pequeña porción de efectivo residual.En conjunto, los resultados confirman que el portafolio de tangencia es el más eficiente teóricamente, aunque el portafolio long-only es más adecuado para la implementación práctica, pues mantiene casi el mismo rendimiento esperado sin necesidad de apalancamiento ni ventas en corto. Esto demuestra que, incluso con correlaciones relativamente altas entre las acciones tecnológicas, la diversificación sigue siendo beneficiosa, y una estrategia concentrada en Microsoft con apoyo marginal de Apple permite obtener una excelente relación riesgo–retorno.```{r}#| label: grafico-tangencial#| message: false#| warning: false#| fig-cap: "Frontera eficiente, portafolio de tangencia y Línea del Mercado de Capitales (CML)"library(ggplot2)library(dplyr)library(tidyr)library(scales)TRADING_DAYS <-252# --- Asegurar insumos (reconstruye si no existen) ---if (!exists("prices")) stop("Falta 'prices' en sesión.")if (!exists("returns_log")) returns_log <-na.omit(PerformanceAnalytics::Return.calculate(prices, method ="log"))if (!exists("mu")) mu <-colMeans(returns_log) * TRADING_DAYSif (!exists("Sigma")) Sigma <-cov(returns_log) * TRADING_DAYSif (!exists("rf")) rf <-0.03# 3% anual, ajusta si tienes otra tasaassets <-names(mu)# --- Portafolio de tangencia (cerrado) ---ones <-rep(1, length(mu))Sinv <-solve(Sigma)z <- Sinv %*% (mu - rf * ones)w_tan <-as.numeric(z /as.numeric(t(ones) %*% Sinv %*% (mu - rf * ones)))names(w_tan) <- assetsRp_tan <-as.numeric(sum(w_tan * mu))Sd_tan <-as.numeric(sqrt(t(w_tan) %*% Sigma %*% w_tan))# --- Parámetros A,B,C,D para frontera eficiente (no restringida) ---A <-as.numeric(t(ones) %*% Sinv %*% ones)B <-as.numeric(t(ones) %*% Sinv %*% mu)C <-as.numeric(t(mu) %*% Sinv %*% mu)D <- A*C - B^2# --- Curva de frontera eficiente a partir de R_target ---R_seq <-seq(min(mu)*0.8, max(mu)*1.2, length.out =200)frontier <-tibble(Rp = R_seq,Var = (A*R_seq^2-2*B*R_seq + C) / D) |>mutate(Sd =sqrt(pmax(Var, 0)))# --- Pesos de la frontera (opcional, por si quieres inspeccionar) ---# w(R) = Σ^{-1}[ ((C - B R)/D) * 1 + ((A R - B)/D) * μ ]# (No lo imprimimos; solo por referencia.)# w_frontier <- sapply(R_seq, function(Rt){# vec <- Sinv %*% ( ((C - B*Rt)/D) * ones + ((A*Rt - B)/D) * mu )# as.numeric(vec)# })# --- Puntos de activos individuales (σ, μ) ---sd_assets <-sqrt(diag(Sigma))pts_assets <-tibble(Activo = assets, Rp =as.numeric(mu), Sd =as.numeric(sd_assets))# --- Línea del mercado de capitales (CML): desde (0, rf) hasta tangencia ---# Recta: R = rf + slope * Sd, con slope = (Rp_tan - rf)/Sd_tanslope <- (Rp_tan - rf) / Sd_tancml_x <-seq(0, max(frontier$Sd)*1.05, length.out =100)cml <-tibble(Sd = cml_x, Rp = rf + slope * cml_x)# --- Graficar ---ggplot() +# Frontera eficiente (parte superior)geom_path(data = frontier, aes(x = Sd, y = Rp), linewidth =1.1, alpha =0.9) +# CMLgeom_line(data = cml, aes(x = Sd, y = Rp), linetype ="dashed", linewidth =1) +# Punto de tangenciageom_point(aes(x = Sd_tan, y = Rp_tan), size =3) +geom_text(aes(x = Sd_tan, y = Rp_tan),label ="Tangencia", nudge_y =0.005, nudge_x =0.002, size =3.5) +# Activos individualesgeom_point(data = pts_assets, aes(x = Sd, y = Rp), size =2.8) +geom_text(data = pts_assets, aes(x = Sd, y = Rp, label = Activo),nudge_y =0.005, size =3.3) +# Formatosscale_x_continuous(labels =percent_format(accuracy =1)) +scale_y_continuous(labels =percent_format(accuracy =1)) +labs(x ="Desviación estándar (anual)", y ="Retorno esperado (anual)",subtitle ="Frontera eficiente (no restringida), activos, portafolio de tangencia y CML",caption ="Notas: cálculos anualizados con 252 días. CML asume tasa libre de riesgo fija (rf).") +theme_minimal(base_size =12)```## **Optimo de contratos del futuro del índice**### **Calcule el VaR al 1% y 5% del portafolio total diario, explique cómo se debe interpretar los escenarios, tenga en cuenta que estos serán los valores de cubrimiento**#### Definición teórica del VaR diarioEl **Valor en Riesgo (VaR)** a nivel de significancia \\(\\alpha\\) y horizonte de **1 día** es la pérdida máxima esperada que **no** se excederá con probabilidad \\(1-\\alpha\\):$$VaR_{\\alpha}^{(1\\,\\text{día})}= \\inf\\{x \\in \\mathbb{R} : \\Pr(\\text{Pérdida} \\le x) \\ge 1-\\alpha\\}.$$Si trabajamos con **retornos del portafolio** \\(R\_{p,d}\\) (positivos = ganancias, negativos = pérdidas), el VaR se reporta como **número positivo**:- **VaR histórico (no paramétrico)**: usa la distribución empírica de \\(R\_{p,d}\\) $$ VaR_{\\alpha}^{\\text{hist}} = -\\,Q_{\\alpha}\\big(R_{p,d}\\big), $$ donde \\(Q\_{\\alpha}(\\cdot)\\) es el cuantil \\(\\alpha\\).- **VaR paramétrico (Normal)**: si \\(R\_{p,d} \\sim \\mathcal{N}(\\mu_d,\\sigma_d)\\) $$ VaR_{\\alpha}^{\\text{norm}} = -\\big(\\mu_d + \\sigma_d\\,z_{\\alpha}\\big),\\quad z_{\\alpha}=\\Phi^{-1}(\\alpha). $$Para **cubrimiento**, el VaR porcentual se convierte a **monto monetario** multiplicando por el **valor del portafolio** \\(V\\): $$VaR\\;[\\text{monto}] = V \\times VaR\\;[\\%].$$**Interpretación**: - **VaR 1% (diario)**: con 99% de confianza, la pérdida de un día **no excederá** ese valor. - **VaR 5% (diario)**: con 95% de confianza, la pérdida de un día **no excederá** ese valor.```{r}#| label: var-diario-portfolio#| message: false#| warning: falselibrary(PerformanceAnalytics)library(dplyr)library(knitr)K <-1e7# capital de referencia (10,000,000)# --- Insumos base ---stopifnot(exists("prices"))returns_log <-if (exists("returns_log")) returns_log elsena.omit(Return.calculate(prices, method ="log"))# Pesos del portafolio (prioridad: long-only -> tangencia -> equi)if (exists("w_long")) { w <- w_long} elseif (exists("w_tan")) { w <- w_tan} else { w <-rep(1/ncol(returns_log), ncol(returns_log))names(w) <-colnames(returns_log)}# Asegurar nombres y orden consistentesw <- w[colnames(returns_log)]# --- Retorno diario del portafolio (serie) ---rp_d <-as.numeric(returns_log %*% w)# rp_d es retorno LOG diario del portafolio; VaR se calcula sobre esta serie# --- VaR histórico (no paramétrico) ---alphas <-c(0.01, 0.05)VaR_hist_pct <--as.numeric(quantile(rp_d, probs = alphas, na.rm =TRUE, type =7))# --- VaR paramétrico (Normal) ---mu_d <-mean(rp_d, na.rm =TRUE)sd_d <-sd(rp_d, na.rm =TRUE)VaR_norm_pct <--(mu_d + sd_d *qnorm(alphas))# --- Pasar a montos monetarios (cubrimiento) ---VaR_hist_amt <- K * VaR_hist_pctVaR_norm_amt <- K * VaR_norm_pct# --- Tablas resumen ---tab_var_pct <-tibble(Nivel =paste0(alphas*100, "%"),`VaR Histórico (diario)`= scales::percent(VaR_hist_pct, accuracy =0.01),`VaR Normal (diario)`= scales::percent(VaR_norm_pct, accuracy =0.01))tab_var_amt <-tibble(Nivel =paste0(alphas*100, "%"),`VaR Histórico (COP/USD)`=round(VaR_hist_amt, 2),`VaR Normal (COP/USD)`=round(VaR_norm_amt, 2))kable(tab_var_pct, caption ="VaR diario del portafolio (porcentaje)")kable(tab_var_amt, caption ="VaR diario del portafolio (monto monetario sobre 10,000,000)")```El portafolio presenta un VaR diario al 1% de 4,42% y un VaR al 5% de 2,65% según el método histórico, lo que significa que con una confianza del 99% y 95% respectivamente, la pérdida diaria no debería superar esos valores. En términos monetarios, esto equivale a pérdidas máximas estimadas de \$442.197 y \$264.957 sobre un capital de 10 millones. El método paramétrico arroja resultados similares (3,82% y 2,67%), lo que confirma una distribución de retornos relativamente estable sin colas excesivas. En general, el portafolio muestra un riesgo moderado: en escenarios extremos, las pérdidas diarias no deberían superar aproximadamente entre \$260.000 y \$440.000, montos que sirven como niveles de cubrimiento mínimos para definir estrategias de protección con futuros del índice.### **Calcule los valores (β) de las acciones por medio del CAPM (use el índice de las acciones elegidas para asumir los precios de mercado). Además, calcule y obtenga la beta del portafolio (use los pesos del punto d de la parte 1)**#### Definición teórica de las betas (CAPM) y beta del portafolioEn el marco del **CAPM**, la **beta** de un activo (i) mide su sensibilidad sistemática respecto al mercado:$$\beta_i \;=\; \frac{\operatorname{Cov}(R_i,\; R_m)}{\operatorname{Var}(R_m)},$$donde (R_i) es el retorno del activo (i) y (R_m) el retorno del índice de mercado.De manera equivalente, puede estimarse por **regresión lineal**:$$R_i \;=\; \alpha_i \;+\; \beta_i\, R_m \;+\; \varepsilon_t,$$siendo (\beta\_i) la pendiente estimada (sensibilidad del activo al factor mercado).La **beta del portafolio** con vector de pesos (w=(w_1,\dots,w_n)\^\top) es la combinación ponderada de las betas individuales:$$\beta_p \;=\; \sum_{i=1}^{n} w_i\, \beta_i,$$lo cual equivale a su definición directa:$$\beta_p \;=\; \frac{\operatorname{Cov}(R_p,\; R_m)}{\operatorname{Var}(R_m)},\qquadR_p \;=\; \sum_{i=1}^{n} w_i\, R_i.$$```{r}#| label: capm-betas-fix-overlap#| message: false#| warning: falselibrary(quantmod)library(PerformanceAnalytics)library(dplyr)library(tidyr)library(knitr)library(zoo)library(xts)stopifnot(exists("prices"))SYMS <-colnames(prices)# ---- Descargar mercado intentando varias alternativas ----options(download.file.method ="libcurl")market_candidates <-c("QQQ", "^NDX", "^IXIC", "SPY", "^GSPC")fetch_market <-function(cands, from, to) {for (sym in cands) { x <-try(getSymbols(sym, src ="yahoo", from = from, to = to, auto.assign =FALSE), silent =TRUE)if (!inherits(x, "try-error")) { px <-Ad(x)colnames(px) <-"MKT"attr(px, "symbol_used") <- symreturn(px) } }stop("No se pudo descargar ningún proxy de mercado (QQQ, ^NDX, ^IXIC, SPY, ^GSPC).")}# Rango crudo (de tus activos)from_assets <-as.Date(first(index(prices)))to_assets <-as.Date(last(index(prices)))mkt_px_raw <-fetch_market(market_candidates, from = from_assets, to = to_assets)mkt_sym <-attr(mkt_px_raw, "symbol_used")# ---- Intersección de rangos (máximo inicio y mínimo fin) ----from_mkt <-as.Date(first(index(mkt_px_raw)))to_mkt <-as.Date(last(index(mkt_px_raw)))from_common <-max(from_assets, from_mkt, na.rm =TRUE)to_common <-min(to_assets, to_mkt, na.rm =TRUE)prices_cut <- prices[paste0(from_common, "/", to_common)]mkt_cut <- mkt_px_raw[paste0(from_common, "/", to_common)]# Quitar NA y asegurar que haya datos suficientesprices_cut <-na.omit(prices_cut)mkt_cut <-na.omit(mkt_cut)# Chequeos de robustezif (NROW(prices_cut) <2||NROW(mkt_cut) <2) {stop(glue::glue("Muy poca intersección de fechas entre activos y mercado.Activos: {from_assets} a {to_assets} (n={NROW(prices)})Mercado ({mkt_sym}): {from_mkt} a {to_mkt} (n={NROW(mkt_px_raw)})Intersección: {from_common} a {to_common}Filas activos en intersección: {NROW(prices_cut)}, filas mercado en intersección: {NROW(mkt_cut)}"))}# (Opcional) exigir al menos 252 observaciones para betas más estables:# if (NROW(prices_cut) < 252) warning("Menos de 252 observaciones en intersección; beta puede ser inestable.")# ---- Retornos diarios (log) y cálculo de betas ----px_all <-merge(prices_cut, mkt_cut, join ="inner")colnames(px_all) <-c(SYMS, "MKT")ret_all <-na.omit(Return.calculate(px_all, method ="log"))ret_assets <- ret_all[, SYMS]ret_mkt <- ret_all[, "MKT", drop =FALSE]var_m <-as.numeric(var(ret_mkt))betas_capm <-sapply(SYMS, function(s) cov(ret_assets[, s], ret_mkt)[1,1] / var_m)betas_reg <-sapply(SYMS, function(s) unname(coef(lm(coredata(ret_assets[, s]) ~coredata(ret_mkt)))[2]))# Pesos del punto (d): prioridad long-only -> tangencia -> equiif (exists("w_long")) { w <- w_long} elseif (exists("w_tan")) { w <- w_tan} else { w <-rep(1/length(SYMS), length(SYMS)); names(w) <- SYMS}w <- w[SYMS] # asegurar orden# Beta del portafolio (dos formas)beta_p_sum <-sum(w * betas_capm)rp <-as.numeric(as.matrix(ret_assets) %*%matrix(w, ncol =1))beta_p_dir <-as.numeric(cov(rp, coredata(ret_mkt)) / var_m)tab_betas <-tibble(Activo = SYMS,`Beta (CAPM cov/var)`=round(betas_capm, 4),`Beta (Regresión)`=round(betas_reg, 4),`Peso (w)`=round(as.numeric(w), 4))tab_beta_port <-tibble(`Proxy de mercado`= mkt_sym,`Beta portafolio (w·beta)`=round(beta_p_sum, 4),`Beta portafolio (directa)`=round(beta_p_dir, 4),`Obs. en intersección`=nrow(ret_all))kable(tab_betas, caption ="Betas por activo (CAPM y regresión) y pesos usados (rango de intersección)")kable(tab_beta_port, caption ="Beta del portafolio y verificación de consistencia")```Los resultados obtenidos muestran que las tres acciones seleccionadas —Apple, Microsoft y Google— presentan betas muy cercanas a 1, lo que indica que su comportamiento está altamente correlacionado con el del mercado. En particular, Apple (β = 1.056) y Microsoft (β = 1.040) exhiben una sensibilidad ligeramente superior a la del índice, mientras que Google (β = 1.012) mantiene una exposición prácticamente igual al mercado. Esto implica que ante un aumento del 1% en el índice, se espera que estas acciones incrementen su valor en aproximadamente el mismo porcentaje o un poco más. La beta del portafolio, calculada tanto de forma ponderada como directa (βₚ = 1.041), confirma que la cartera se mueve prácticamente al unísono con el mercado, reflejando un riesgo sistemático apenas superior al promedio. En consecuencia, el portafolio es levemente agresivo, con una exposición al riesgo de mercado que podría ser mitigada, si así se desea, mediante coberturas con futuros sobre el índice de referencia.## **Calcule el número de contratos óptimos basado para acciones**### Definición teórica del número óptimo de contratos de futurosEl número óptimo de contratos de futuros que debe emplearse para cubrir una posición en acciones se obtiene a partir del modelo de **mínima varianza**, cuyo objetivo es reducir el riesgo del portafolio ante movimientos del mercado.El **ratio de cobertura óptimo** (h\^\*) se define como:\[ h\^\* = \frac{\operatorname{Cov}(R_S, R_F)}{\operatorname{Var}(R_F)} = \rho\_{SF} \frac{\sigma_S}{\sigma_F} \]donde:\- (R_S) son los retornos del portafolio o activo,\- (R_F) los retornos del futuro,\- (\rho\_{SF}) la correlación entre ambos,\- (\sigma\_S) la desviación estándar del portafolio, y\- (\sigma\_F) la desviación estándar del futuro.Una vez hallado (h\^\*), el **número óptimo de contratos de futuros** se determina mediante:\[ N\^\* = h\^\* \cdot \frac{V_S}{V_F} \]donde:\- (V_S) es el valor del portafolio a cubrir, y\- (V_F = F_0 \times Q) representa el valor nocional de un contrato de futuros, siendo (F_0) el precio del futuro y (Q) el tamaño del contrato.Si (N\^\*\> 0), se toma una **posición corta** en futuros (para proteger una posición larga en acciones).\Si (N\^\*\< 0), se toma una **posición larga** en futuros (para cubrir una posición corta).```{r}#| label: num-contratos-optimos#| message: false#| warning: falselibrary(quantmod)library(PerformanceAnalytics)library(dplyr)library(knitr)# --- 1. Definir pesos disponibles (usa el más adecuado) ---if (exists("w_long")) { w <- w_long} elseif (exists("w_tan")) { w <- w_tan} else {# equi-ponderado por defecto SYMS <-colnames(prices) w <-rep(1/length(SYMS), length(SYMS))names(w) <- SYMS}# --- 2. Calcular retorno del portafolio ---rp <-Return.portfolio(R = ret_assets, weights = w)# --- 3. Calcular ratio de cobertura óptimo (h*) ---cov_sf <-cov(rp, ret_mkt)var_f <-var(ret_mkt)rho_sf <-cor(rp, ret_mkt)sigma_s <-sd(rp)sigma_f <-sd(ret_mkt)h_star <-as.numeric(cov_sf / var_f) # forma clásicah_alt <-as.numeric(rho_sf * sigma_s / sigma_f) # verificación equivalente# --- 4. Valores del portafolio y del contrato ---V_s <-10000000# valor total del portafolioF0 <-as.numeric(last(Ad(getSymbols("QQQ", auto.assign =FALSE)))) # precio proxy del índiceQ <-100# tamaño típico del contratoV_f <- F0 * Q # valor nocional del contrato# --- 5. Número óptimo de contratos ---N_star <- h_star * (V_s / V_f)# --- 6. Resultados finales ---tab_contratos <-tibble(`Cov(Rp,Rf)`=round(cov_sf, 6),`Var(Rf)`=round(var_f, 6),`ρ(S,F)`=round(rho_sf, 4),`σ(S)`=round(sigma_s, 4),`σ(F)`=round(sigma_f, 4),`h* (óptimo)`=round(h_star, 4),`Precio futuro (F0)`=round(F0, 2),`Tamaño contrato (Q)`= Q,`Valor portafolio (V_S)`= V_s,`Valor contrato (V_F)`=round(V_f, 2),`N* contratos óptimos`=round(N_star, 2))kable(tab_contratos, caption ="Cálculo del número óptimo de contratos de futuros para cobertura del portafolio")```El resultado muestra que el ratio de cobertura óptimo () es 1.0411, lo cual indica que los retornos del portafolio se mueven prácticamente uno a uno con los del índice de referencia, pero con una ligera sensibilidad superior al 4 %. En otras palabras, por cada 1 % de variación en el índice, el portafolio tiende a cambiar aproximadamente 1.04 %.Dado que el valor total de la cartera es de 10 millones y el valor nocional de un contrato de futuros del índice (QQQ) es de aproximadamente 62 605 dólares, el número óptimo de contratos necesarios para neutralizar el riesgo sistemático del portafolio es de 166 contratos. Esto implica que el inversionista debería vender 166 contratos de futuros del índice para proteger completamente la exposición al riesgo de mercado de su cartera de acciones.### Definición teórica del Margin Call y análisis de rentabilidad con roll-over**Calcule el Margin Call trimestral, ¿cuánto gana y se pierde en el futuro del índice? Realice un análisis de rentabilidad usando la estructura de roll-over cada trimestre. ¿Qué pasaría si deja todo en corto o en largo?**En el mercado de futuros, las posiciones están sujetas a un proceso de **ajuste diario** conocido como *mark-to-market*, donde las ganancias o pérdidas se acreditan o debitan en la cuenta de margen del inversionista al cierre de cada jornada.\Este proceso asegura que las pérdidas no superen el capital comprometido.El **Margin Call** ocurre cuando el saldo de la cuenta cae por debajo del **margen de mantenimiento** ((M_m)), obligando al inversionista a depositar fondos adicionales hasta restablecer el **margen inicial** ((M_i)):\[ \text{Si } \text{Saldo}\_t \< M_m \Rightarrow \text{Margin Call} = M_i - \text{Saldo}\_t \]El valor de una posición en futuros varía según los cambios en el precio del contrato:\[ \Delta V_t = N \times Q \times (F_t - F\_{t-1}) \]donde: - (N): número de contratos,\- (Q): tamaño del contrato,\- (F_t): precio del futuro al tiempo (t),\- (F\_{t-1}): precio del futuro en el periodo anterior.El resultado diario puede ser positivo (ganancia) o negativo (pérdida), generando flujos que ajustan el margen.Cuando se realiza una estrategia de cobertura o especulación a largo plazo, se implementa una estructura de **roll-over trimestral**, que consiste en: 1. Mantener la posición hasta el vencimiento del contrato del trimestre.\2. Cerrar la posición actual y abrir una nueva en el siguiente vencimiento.El rendimiento total acumulado de la estrategia de futuros con *roll-over* puede expresarse como:\[ R\_{\text{total}} = \sum*{t=1}\^{T}* \Delta F_t + \sum{t=1}\^{T} C_t \]donde (C_t) representa los costos de transacción o ajuste al renovar los contratos.**Interpretación de las posiciones:** - **Posición larga (long)**: gana cuando el precio del futuro sube.\- **Posición corta (short)**: gana cuando el precio del futuro baja.\En consecuencia, la rentabilidad dependerá del sentido del mercado durante los trimestres y de la correcta administración del margen de garantía.```{r}#| label: margin-call-rollover#| message: false#| warning: falselibrary(quantmod)library(PerformanceAnalytics)library(dplyr)library(lubridate)library(knitr)# --- 1. Descargar precios del índice (QQQ como proxy del futuro del NASDAQ) ---getSymbols("QQQ", from ="2020-01-01", to =Sys.Date(), auto.assign =TRUE)fut <-Ad(QQQ)colnames(fut) <-"Futuro"# --- 2. Crear estructura trimestral ---fut_quarterly <- fut[endpoints(fut, on ="quarters"), , drop =FALSE]ret_fut <-diff(log(fut_quarterly)) # retornos trimestrales aproximados# --- 3. Supuestos base ---N <-166# número óptimo de contratos (de tu cálculo previo)Q <-100# tamaño del contratoF0 <-as.numeric(first(fut)) # precio inicialMi <-0.10* N * Q * F0 # margen inicial (10% del valor nocional)Mm <-0.75* Mi # margen de mantenimiento (75%)posiciones <-c("Long", "Short")# --- 4. Simulación del margin call y resultados trimestrales ---resultados <-lapply(posiciones, function(pos) { saldo <- Mi calls <-0 ganancias <-c() precios <-coredata(fut_quarterly)for (i in2:length(precios)) { delta <- (precios[i] - precios[i-1]) * Q * Nif (pos =="Short") delta <--delta saldo <- saldo + deltaif (saldo < Mm) { calls <- calls +1 recarga <- Mi - saldo saldo <- Mi } ganancias <-c(ganancias, delta) }data.frame(Posicion = pos,Trimestres =length(ganancias),Ganancia_total =sum(ganancias),Promedio_trimestral =mean(ganancias),Margin_Calls = calls,Ultimo_saldo = saldo )})resultados_df <-bind_rows(resultados)kable(resultados_df, caption ="Simulación de Margin Calls y rentabilidad trimestral (estructura roll-over)")```Los resultados muestran que una posición larga en los futuros del índice genera una ganancia total de 7.33 millones, con un saldo final de 7.68 millones y sin llamadas de margen durante el periodo de 23 trimestres. Esto refleja un mercado predominantemente alcista, en el que mantener una posición larga fue altamente rentable.En contraste, la posición corta arroja una pérdida equivalente de -7.33 millones y presenta 14 margin calls, lo que evidencia la presión constante de reponer garantías debido a la tendencia ascendente del índice.### Definición teórica del valor esperado de la cobertura trimestral del portafolio¿Cuál sería el valor esperado de la cobertura trimestral del portafolio? Use una tasa libre de riesgo de la fecha inicial (\^TNX (CBOE Interest Rate 3 a 5 Year) para estados Unidos. Realice un análisis al respectoEl objetivo de la cobertura mediante contratos de futuros es neutralizar las variaciones del valor del portafolio ante cambios en el mercado.\En un horizonte trimestral, el valor esperado de la cobertura está determinado por la evolución esperada del precio del futuro y la tasa libre de riesgo vigente en la fecha inicial.Sea un portafolio con valor ( V_S ), cubierto con ( N\^\* ) contratos de futuros sobre un índice, cada uno con precio inicial ( F_0 ) y tamaño ( Q ).\El número óptimo de contratos está dado por:$$N^* = h^* \cdot \frac{V_S}{V_F}$$donde ( h\^\* ) es el ratio de cobertura óptimo y ( V_F = F_0 \times Q ) representa el valor nocional de un contrato.En un contexto de equilibrio riesgo–neutro, el precio esperado del futuro al final del trimestre se aproxima por:$$\mathbb{E}[F_T] = F_0 \, e^{r_f \, \Delta t}$$donde ( r_f ) es la tasa libre de riesgo anual y ( \Delta t = 0.25 ) corresponde a un trimestre.\El cambio esperado en el precio del futuro es entonces:$$\mathbb{E}[\Delta F] = F_0 \left( e^{r_f \, \Delta t} - 1 \right) \approx F_0 (r_f \, \Delta t)$$El **valor esperado de la cobertura trimestral** (la ganancia o pérdida esperada por la posición en futuros) se expresa como:- Para una **posición corta** en futuros (cobertura de una posición larga en acciones):$$\mathbb{E}[\text{P\&L}_{\text{hedge}}^{\text{short}}] = - N^* \, Q \, F_0 \, (r_f \, \Delta t)$$- Para una **posición larga** en futuros:$$\mathbb{E}[\text{P\&L}_{\text{hedge}}^{\text{long}}] = + N^* \, Q \, F_0 \, (r_f \, \Delta t)$$Finalmente, el **valor esperado total del portafolio cubierto** durante el trimestre será:$$\mathbb{E}[V_{\text{total}}] = V_S \, (1 + r_S \, \Delta t) + \mathbb{E}[\text{P\&L}_{\text{hedge}}]$$donde ( r_S ) representa el retorno esperado del portafolio de acciones.\De este modo, la cobertura permite compensar las variaciones del portafolio de renta variable con las ganancias o pérdidas de la posición en futuros, estabilizando el rendimiento trimestral neto.```{r}#| label: cobertura-valor-esperado-trimestral#| message: false#| warning: falselibrary(quantmod)library(PerformanceAnalytics)library(dplyr)library(lubridate)library(knitr)# --- Parámetros base ---fecha_ini <-as.Date("2025-07-31")Delta_t <-0.25# trimestre ~ 1/4 añoV_S <-10000000# valor del portafolioQ <-100# multiplicador del futuro de índice (estándar en muchos ETFs/índices)# F0: precio del "futuro" proxy. Usaremos QQQ (último precio antes o igual a fecha_ini)getSymbols("QQQ", from = fecha_ini -3650, to = fecha_ini, auto.assign =TRUE)F0 <-as.numeric(last(Ad(QQQ)[paste0("/", fecha_ini)]))if (is.na(F0)) F0 <-as.numeric(last(Ad(QQQ))) # fallback# --- Tasa libre de riesgo al inicio: intentamos ^FVX (5Y) y luego ^TNX (10Y) ---rf_fetch <-function(symbol, fecha) { x <-try(getSymbols(symbol, from = fecha -365, to = fecha, auto.assign =FALSE), silent =TRUE)if (inherits(x, "try-error")) return(NA_real_) y <-Ad(x)as.numeric(last(y[paste0("/", fecha)])) /100# vienen en %}r_f <-rf_fetch("^FVX", fecha_ini)if (is.na(r_f)) r_f <-rf_fetch("^TNX", fecha_ini)if (is.na(r_f)) stop("No se pudo obtener ^FVX ni ^TNX para la fecha inicial.")# --- Ratio de cobertura y N* ---# Usamos tus objetos si existen; si no, los calculamosif (!exists("ret_assets") ||!exists("ret_mkt")) {# reconstruir rápidamente desde tus preciosstopifnot(exists("prices"))# Proxy de mercado para ret_mkt acorde a QQQ mkt <-Ad(QQQ) px_all <-na.omit(merge(prices, mkt))colnames(px_all)[ncol(px_all)] <-"MKT" ret_all <-na.omit(Return.calculate(px_all, method ="log")) ret_assets <- ret_all[, colnames(prices)] ret_mkt <- ret_all[, "MKT", drop =FALSE]}# Pesos: usa w_long -> w_tan -> equiif (exists("w_long")) { w <- w_long} elseif (exists("w_tan")) { w <- w_tan} else { w <-rep(1/ncol(ret_assets), ncol(ret_assets)); names(w) <-colnames(ret_assets)}rp <-Return.portfolio(R = ret_assets, weights = w)cov_sf <-as.numeric(cov(rp, ret_mkt))var_f <-as.numeric(var(ret_mkt))h_star <- cov_sf / var_fV_F <- F0 * QN_star <-if (exists("N_star")) as.numeric(N_star) else h_star * (V_S / V_F)# --- Valor esperado trimestral de la cobertura (riesgo-neutro, sin dividendos) ---E_dF <- F0 * (r_f * Delta_t) # E[ΔF]E_PnL_short <-- N_star * Q * E_dFE_PnL_long <-+ N_star * Q * E_dF# --- Retorno esperado del portafolio en el trimestre (desde retorno anual esperado) ---# Usa tu retorno anual esperado del portafolio long-only si existe; si no, estimamos de la serie.if (exists("Rp_long")) { mu_ann <-as.numeric(Rp_long)} else { mu_ann <-mean(rp) *252# media diaria * 252}E_port_trimestral <- V_S * (mu_ann * Delta_t)# --- Agregar neto cubierto (portafolio + cobertura) ---res <-tibble(Escenario =c("Short futuros (cobertura)","Long futuros"),`r_f anual`= scales::percent(r_f, accuracy =0.01),`F0 (proxy)`=round(F0, 2),`N*`=round(N_star, 2),`E[P&L cobertura trimestral]`=c(round(E_PnL_short, 2), round(E_PnL_long, 2)),`E[retorno portafolio trim]`=round(E_port_trimestral, 2),`E[total trimestral]`=round(E_port_trimestral +c(E_PnL_short, E_PnL_long), 2))kable(res, caption ="Valor esperado trimestral: cobertura del portafolio con futuros (usando tasa libre de riesgo inicial)")```## Parte 2. Desarrollo de un Futuro de divisas.Ustedes son inversores y el día de hoy requieren 300 millones de pesos para una compra de maquinaria amarilla, encuentran que pueden ejercer un crédito en Estados Unidos (Elijan ustedes un crédito de una entidad financiera estadounidense, con la tasa, a un plazo a 10 años, el sistema de pago será francés). Para proteger los pagos en cuotas, ustedes también deciden apalancarse con un futuro de divisas con el 70% del valor de inversión de maquinaria amarilla, desde el sexto año de la inversión (use la información de un futuro de la BVC como datos históricos) y como propone la fórmula de cálculo del futuro de TRM, use una tasa de interés comercial que emule las condiciones de la tasa americana. De lo anterior:**Proceso del crédito**### IntroducciónEn esta sección se plantea un escenario práctico de cobertura cambiaria mediante el uso de contratos de futuros sobre la Tasa Representativa del Mercado (TRM). Como inversionistas colombianos que adquieren maquinaria financiada en dólares a través de un crédito en Estados Unidos, el objetivo es mitigar el riesgo de tipo de cambio asociado a las cuotas futuras. Para ello, se diseña una estrategia de cobertura con futuros de divisas listados en la Bolsa de Valores de Colombia (BVC), equivalente al *70 %* del valor de la inversión, aplicada a partir del sexto año del crédito. Este ejercicio permite evaluar la efectividad del instrumento derivado frente a la exposición cambiaria y su impacto en la estabilidad de los flujos financieros del proyecto.### **Realice un análisis fundamental de la TRM y cuál es la expectativa de los precios hasta dentro de un año (busque informes de proyección de la divisa)****Factores que inciden en la TRM (USD/COP):**Tasas de interés relativas: Si la tasa doméstica en Colombia se mantiene alta (por ejemplo, la tasa de política monetaria del Banco de la República de Colombia se encuentra en torno al 9 %-10 %) frente a una tasa de EE.UU. más baja o estable, esto tiende a atraer capitales al peso, lo que puede favorecer su apreciación o al menos mitigar su depreciación. Reuters +2 bbvaresearch.com +2Inflación y riesgo país: Una inflación persistentemente por encima de la meta reduce la confianza en el peso y eleva la depreciación esperada. Se estima que la inflación en Colombia para 2025 será superior al 4 %. Reuters +1Precio de commodities y balanza comercial: Colombia es exportador de petróleo y otras materias primas; precios más altos favorecen ingresos de dólares y fortalecen el peso. Si el petróleo cae, esto presiona al alza de la TRM.Entorno internacional y dólar global: Si el dólar estadounidense se fortalece (por una subida de tasas por parte de la Federal Reserve o por mayor aversión al riesgo global), monedas emergentes como el peso tienden a depreciarse. Además, algunos informes proyectan que el peso podría ser “la peor moneda de Latinoamérica” para 2026.### Cálculo de los retornos y la desviación estándar de la TRMEn el análisis de series financieras, los **retornos** representan la variación proporcional del precio o tasa de un activo entre dos periodos consecutivos. En el caso de la **Tasa Representativa del Mercado (TRM)**, los retornos mensuales reflejan la apreciación o depreciación del peso colombiano frente al dólar estadounidense.El **retorno logarítmico mensual** se define como:$$r_t = \ln\left(\frac{P_t}{P_{t-1}}\right)$$donde (P_t) y (P\_{t-1}) representan el valor de la TRM en los meses (t) y (t-1), respectivamente.\Este tipo de retorno es preferido en el análisis financiero porque:- Es aditivo en el tiempo, lo que facilita el cálculo de retornos acumulados.\- Se aproxima mejor a una distribución normal.\- Permite un análisis estadístico más estable en series largas.Una vez obtenidos los retornos, se calcula la **media** y la **desviación estándar mensual**, que miden el rendimiento promedio y el riesgo (volatilidad) del tipo de cambio:$$\bar{r} = \frac{1}{n}\sum_{t=1}^{n} r_t$$$$\sigma = \sqrt{\frac{1}{n-1}\sum_{t=1}^{n}(r_t - \bar{r})^2}$$donde (\bar{r}) es el retorno promedio mensual, (\sigma) es la volatilidad mensual y (n) el número total de observaciones.\Una (\sigma) alta indica que la TRM es más volátil —mayor incertidumbre cambiaria—, mientras que una (\sigma) baja refleja mayor estabilidad en el mercado de divisas.```{r}#| label: trm-retornos-mensuales#| message: false#| warning: false# --- Paquetes ---suppressPackageStartupMessages({library(quantmod)library(PerformanceAnalytics)library(dplyr)library(lubridate)library(knitr)library(xts)library(zoo)})# --- Parámetros (ajusta si quieres) ---fecha_ini <-as.Date("2015-01-01")fecha_fin <-Sys.Date()# --- Descarga TRM (USD/COP) desde Yahoo Finance ---# Símbolo: USDCOP=XgetSymbols("USDCOP=X", from = fecha_ini, to = fecha_fin, auto.assign =TRUE)trm_daily <-na.omit(Cl(`USDCOP=X`)) # Precio de cierre diariocolnames(trm_daily) <-"TRM"# Verificación de datos suficientesif (NROW(trm_daily) <10) {stop("No se obtuvieron suficientes datos de TRM. Revisa conexión o rango de fechas.")}# --- Agregación a frecuencia mensual (último día hábil de cada mes) ---trm_monthly <-to.monthly(trm_daily, indexAt ="lastof", OHLC =FALSE)colnames(trm_monthly) <-"TRM"# --- Retornos logarítmicos mensuales ---ret_mensuales <-na.omit(diff(log(trm_monthly)))colnames(ret_mensuales) <-"ret_mensual"# --- Estadísticas: media y desviación estándar mensuales ---media_mensual <-mean(ret_mensuales)[[1]]desv_mensual <-sd(ret_mensuales)[[1]]# (Opcional) equivalentes anualizados con base 12media_anualizada <- media_mensual *12vol_anualizada <- desv_mensual *sqrt(12)# --- Resumen tabular ---periodo_txt <-paste(format(start(trm_monthly), "%Y-%m"),"→",format(end(trm_monthly), "%Y-%m"))tabla_resumen <- tibble::tibble(`Periodo (mensual)`= periodo_txt,`Observaciones (n)`=nrow(ret_mensuales),`Retorno promedio mensual (%)`=round(100* media_mensual, 3),`Desv.est. mensual (%)`=round(100* desv_mensual, 3),`Retorno promedio anual (%)`=round(100* media_anualizada, 2),`Volatilidad anual (%)`=round(100* vol_anualizada, 2))kable( tabla_resumen,caption ="TRM (USD/COP): retornos logarítmicos mensuales y volatilidad",align ="lrrrrr")# --- (Opcional) Vista rápida de los últimos 12 retornos mensuales ---ultimos12 <-tail(100* ret_mensuales, 12)kable(data.frame(Mes =format(index(ultimos12), "%Y-%m"),`Retorno mensual (%)`=round(coredata(ultimos12[,1]), 3) ),caption ="Últimos 12 retornos mensuales de la TRM (en %)",align ="lr")```La TRM exhibe un retorno promedio mensual de 0.38% (≈ 4.5% anual), lo que sugiere una depreciación leve del COP frente al USD en el largo plazo. La volatilidad mensual de 4.0% (≈ 13.8% anual) indica oscilaciones relevantes: movimientos típicos mensuales de ±4% en el tipo de cambio. En los últimos 12 meses predominan variaciones negativas (p. ej., ene-2025: −5.68%, ago-2025: −4.17%, sep-2025: −2.25%, oct-2025: −1.73%), lo que apunta a una apreciación reciente del COP tras episodios puntuales de depreciación (jul-2025: +2.35%). Para cobertura, esto implica riesgo cambiario no menor: conviene dimensionar contratos con base en la volatilidad observada y revisar periódicamente el hedge por los cambios de tendencia.### Simulación con Browniano Geométrico (BMG) para la TRMLa dinámica de precios bajo BMG se modela como: $$dS_t = \mu\,S_t\,dt + \sigma\,S_t\,dW_t,$$ cuyo solucionario discreto (paso mensual) es: $$S_{t+\Delta} = S_t \exp\!\Big[\Big(\mu - \tfrac{1}{2}\sigma^2\Big)\Delta + \sigma \sqrt{\Delta}\,Z_t\Big],\quad Z_t\sim \mathcal{N}(0,1).$$Con retornos logarítmicos mensuales históricos (r_t=\ln(S_t/S\_{t-1})), se estiman: $$\hat{\mu}=\overline{r},\qquad \hat{\sigma}=\text{sd}(r).$$Para horizonte de (H) meses y (\Delta=1) mes, una trayectoria parte de (S_0) (última TRM observada) y repite la recursión (H) veces. Con (N) trayectorias, se resume el pronóstico por cuantiles (p5, mediana, p95) al horizonte.```{r}#| label: trm-simulacion-bmg#| message: false#| warning: falsesuppressPackageStartupMessages({library(quantmod)library(PerformanceAnalytics)library(dplyr)library(tidyr)library(ggplot2)library(knitr)library(xts)library(zoo)})# --- 1) Usar la TRM mensual y retornos ya calculados si existen; si no, descargarlos ---if (!exists("trm_monthly") ||!exists("ret_mensuales")) {getSymbols("USDCOP=X", from ="2015-01-01", to =Sys.Date(), auto.assign =TRUE) trm_daily <-na.omit(Cl(`USDCOP=X`)) trm_monthly <-to.monthly(trm_daily, indexAt ="lastof", OHLC =FALSE)colnames(trm_monthly) <-"TRM" ret_mensuales <-na.omit(diff(log(trm_monthly)))colnames(ret_mensuales) <-"ret_mensual"}# --- 2) Estimar parámetros mensuales ---mu_hat <-as.numeric(mean(ret_mensuales))sg_hat <-as.numeric(sd(ret_mensuales))# --- 3) Configuración de simulación ---set.seed(123) # reproducibilidadH <-12# horizonte en mesesN_paths <-5000# número de trayectoriasDelta <-1.0# paso mensualS0 <-as.numeric(last(trm_monthly)) # última TRM observada# --- 4) Simulación BMG (vectorizada) ---Z <-matrix(rnorm(H * N_paths), nrow = H, ncol = N_paths)drift <- (mu_hat -0.5* sg_hat^2) * Deltashock <- sg_hat *sqrt(Delta) * Zlog_increments <-sweep(shock, 1, drift, `+`) # drift + shock por meslog_levels <-apply(log_increments, 2, cumsum)S_paths <-exp( log(S0) +rbind(rep(0, N_paths), log_levels) ) # (H+1) x N# --- 5) Resumen estadístico por mes ---dates_sim <-seq.Date(from =as.Date(end(trm_monthly)), by ="month", length.out = H +1)sum_tab <-apply(S_paths, 1, quantile, probs =c(0.05, 0.5, 0.95))sum_df <-tibble(Mes = dates_sim,p05 = sum_tab[1,],p50 = sum_tab[2,],p95 = sum_tab[3,])kable( sum_df %>%mutate(across(c(p05, p50, p95), ~round(.x, 2))),caption ="TRM simulada (BMG): cuantiles 5%, 50% y 95% por mes")# --- 6) Gráfico de abanico (mediana y banda 5–95%) ---# ggplot(sum_df, aes(x = Mes)) +# geom_ribbon(aes(ymin = p05, ymax = p95), alpha = 0.2) +# geom_line(aes(y = p50), linewidth = 1) +# labs(# title = "Simulación BMG de la TRM (mensual)",# subtitle = paste0("S0 = ", round(S0,2),# " | μ̂ = ", round(mu_hat*100,2), "% mensual, σ̂ = ", round(sg_hat*100,2), "% mensual",# " | H = ", H, " meses, N = ", N_paths),# y = "TRM (COP por USD)", x = "Mes"# ) +# theme_minimal()``````{r}# --- 7) Resumen al horizonte (H meses) ---horizon_vals <- S_paths[H +1, ]resumen_h <-tibble(`TRM (p05)`=round(quantile(horizon_vals, 0.05), 2),`TRM (mediana)`=round(median(horizon_vals), 2),`TRM (p95)`=round(quantile(horizon_vals, 0.95), 2))kable(resumen_h, caption =paste0("Distribución simulada de la TRM al horizonte de ", H, " meses"))``````{r}#| label: trm-simulacion-bmg-plot-spaghetti#| message: false#| warning: falselibrary(dplyr)library(tidyr)library(ggplot2)library(scales)# --- Construir un data.frame largo con unas pocas trayectorias representativas ---# S_paths: matriz (H+1) x N_paths creada antes# dates_sim: vector de fechas (H+1)set.seed(123)n_mostrar <-30# nº de trayectorias a dibujaridx_mostrar <-sample(ncol(S_paths), n_mostrar) # columnas aleatoriasdf_paths <-as.data.frame(S_paths[, idx_mostrar])colnames(df_paths) <-paste0("path_", seq_len(n_mostrar))df_paths$Mes <- dates_simdf_long <- df_paths |> tidyr::pivot_longer(-Mes, names_to ="Trayectoria", values_to ="TRM")# --- Data frame del abanico y mediana (ya lo tenías como sum_df con p05, p50, p95) ---# sum_df: tibble con columnas Mes, p05, p50, p95# --- Gráfico: banda 5–95%, mediana y trayectorias seleccionadas ---ggplot() +geom_ribbon(data = sum_df, aes(x = Mes, ymin = p05, ymax = p95), alpha =0.18) +geom_line(data = df_long, aes(x = Mes, y = TRM, group = Trayectoria), linewidth =0.25, alpha =0.35) +geom_line(data = sum_df, aes(x = Mes, y = p50), linewidth =1.0) +scale_y_continuous(labels =label_number(big.mark =".", decimal.mark =",")) +labs(title ="Simulación BMG de la TRM (mensual): abanico 5–95%, mediana y 30 trayectorias",subtitle =paste0("S0 = ", round(S0,2)," | μ̂ = ", round(mu_hat*100,2), "% mensual, σ̂ = ", round(sg_hat*100,2), "% mensual"," | H = ", H, " meses, N = ", N_paths),x ="Mes", y ="TRM (COP por USD)" ) +theme_minimal(base_size =12)```### Crédito en dólares con sistema francés (cuota fija)Sea un precio de maquinaria (P\_{\text{COP}}) y una TRM inicial (S_0). El precio en USD es (P\_{\text{USD}} = \dfrac{P_{\text{COP}}}{S_0}). Si el pago inicial es ( \alpha = 10% ), el **crédito** cubre el (1-\alpha): $$\text{Down payment} = \alpha\, P_{\text{USD}}, \qquad\text{Principal} = L_0 = (1-\alpha)\, P_{\text{USD}} .$$Con tasa anual en dólares (r\_{\text{ann}}) y pagos mensuales por (T=10) años ((n = 12T) cuotas), la tasa mensual es $$i =\begin{cases}\dfrac{r_{\text{ann}}}{12} & \text{(APR)}\\[6pt](1+r_{\text{ann}})^{1/12}-1 & \text{(EAR)}\end{cases}$$La **cuota fija** (sistema francés) es $$C = L_0 \cdot \frac{i(1+i)^n}{(1+i)^n-1}.$$La descomposición en el periodo (t) es: $$\text{Interés}_t = i \, \text{Saldo}_{t-1}, \qquad\text{Amortización}_t = C - \text{Interés}_t,\qquad\text{Saldo}_t = \text{Saldo}_{t-1} - \text{Amortización}_t.$$```{r}#| label: credito-usd-frances#| message: false#| warning: falsesuppressPackageStartupMessages({library(dplyr); library(lubridate); library(knitr); library(quantmod)})# --- 1) Parámetros base ---P_COP <-300e6# precio maquinaria en COP# Usa tu S0 (última TRM) si ya existe; si no, lo obtenemos de USDCOP=Xif (!exists("S0")) {getSymbols("USDCOP=X", from =Sys.Date()-60, to =Sys.Date(), auto.assign =TRUE) S0 <-as.numeric(last(Cl(`USDCOP=X`)))}P_USD <- P_COP / S0 # precio en dólaresalpha <-0.10# 10% de inicialyears <-10n <-12* years # cuotas# Tasa anual en USD (ajústala a la que elijas para el banco)r_ann <-0.055# 5.5% anual (ejemplo)use_EAR <-FALSE# FALSE = APR simple; TRUE = EAR (efectiva)# --- 2) Derivados y principal ---i <-if (use_EAR) (1+ r_ann)^(1/12) -1else r_ann/12down_payment_usd <- alpha * P_USDL0 <- (1- alpha) * P_USD # principal a financiar (90%)# Cuota fija (sistema francés)C <- L0 * (i * (1+ i)^n) / ((1+ i)^n -1)# --- 3) Cronograma de amortización mensual ---schedule <-tibble(t =1:n,Fecha =seq(from =floor_date(Sys.Date(), unit ="month") +months(1),by ="month", length.out = n)) |>mutate(Interes = i *ifelse(t ==1, L0, NA_real_),Amortizacion =NA_real_,Cuota = C,Saldo =NA_real_ )# Relleno iterativo del saldosaldo <- L0for (k in1:n) { interes_k <- i * saldo amort_k <- C - interes_k saldo <- saldo - amort_k schedule$Interes[k] <- interes_k schedule$Amortizacion[k] <- amort_k schedule$Saldo[k] <-max(saldo, 0)}# --- 4) Resumen del crédito ---resumen_credito <-tibble(`TRM inicial (S0)`=round(S0, 2),`Precio maquinaria (USD)`=round(P_USD, 2),`Inicial 10% (USD)`=round(down_payment_usd, 2),`Principal financiado (USD)`=round(L0, 2),`Tasa anual (USD)`=paste0(round(100*r_ann, 2), "%", ifelse(use_EAR," (EAR)"," (APR)")),`Cuota mensual (USD)`=round(C, 2),`N° cuotas`= n,`Interés total (USD)`=round(sum(schedule$Interes), 2),`Pago total (USD)`=round(sum(schedule$Cuota) + down_payment_usd, 2),`Flujo inicial total (USD)`=round(down_payment_usd, 2))# --- 5) Salidas ordenadas ---kable(resumen_credito, caption ="Resumen del crédito en USD (sistema francés, 10% de inicial)")kable( schedule |>mutate(across(c(Interes, Amortizacion, Cuota, Saldo), ~round(.x, 2))) |>select(Fecha, Cuota, Interes, Amortizacion, Saldo) |>head(12),caption ="Cronograma mensual: primeros 12 meses (USD)")# Si quieres guardar el cronograma completo para usarlo luego:credito_schedule_usd <- schedule```El crédito en USD financiado al 90% de la compra (≈ USD 70,020.75) con tasa 5.5% APR a 10 años genera una cuota fija de \~USD 759.91. El costo financiero total (intereses) asciende a \~USD 21,168, para un pago total de \~USD 98,969 más la inicial (USD 7,780). El cronograma muestra el patrón típico del sistema francés: al inicio la cuota se compone mayoritariamente de intereses (p. ej., nov-2025: USD 320.93) y, mes a mes, la amortización aumenta (USD 438.98 → 461.63) mientras el saldo disminuye (USD 70,020 → 64,618 en 12 meses). En términos de riesgo, el flujo en USD es estable; la exposición relevante para el proyecto será la TRM al convertir a COP y, en menor medida, cambios en la tasa si el crédito no fuera estrictamente a tasa fija.### **Proceso de futuro.**Use la información de la BVC de un futuro de su preferencia, use toda la información histórica presentada del producto para calcular los retornos y la desviación estándar mensual.### Retornos y volatilidad mensual de un futuro BVCSea (P_t) el precio de liquidación del futuro en el cierre del mes (t). El **retorno logarítmico mensual** se define como: $$r_t = \ln\!\left(\frac{P_t}{P_{t-1}}\right).$$Con la serie ({r_t}\_{t=1}\^n), el **retorno promedio mensual** y la **desviación estándar mensual** (volatilidad) son: $$\bar r = \frac{1}{n}\sum_{t=1}^n r_t,\qquad\sigma_m = \sqrt{\frac{1}{n-1}\sum_{t=1}^n (r_t-\bar r)^2}.$$Para comparación anual, se suele usar: $$\mu_{\text{anual}} \approx 12\,\bar r,\qquad\sigma_{\text{anual}} \approx \sqrt{12}\,\sigma_m.$$Dado que el histórico en CSV/XLSX de futuros listados en la BVC no está disponible públicamente sin acceso de bróker/plataforma, y para no frenar el desarrollo, trabajamos con un futuro continuo ampliamente seguido en Yahoo Finance. Elegimos WTI Crude Oil (CL=F) por su profundidad y cobertura histórica suficiente para estimar retornos mensuales y volatilidad de forma robusta.```{r}#| label: futuros-continuos-yahoo-robusto#| message: false#| warning: falsesuppressPackageStartupMessages({library(quantmod); library(dplyr); library(xts); library(zoo); library(knitr); library(ggplot2)})# Lista de futuros continuos confiables en Yahoosymbols_try <-c("CL=F", # WTI Crude Oil"GC=F", # Gold"ES=F", # E-mini S&P 500"SI=F", # Silver"HG=F", # Copper"ZC=F", # Corn"ZW=F", # Wheat"ZS=F") # Soybeanspx_daily <-NULLsym_used <-NA_character_for (sym in symbols_try) { xts_try <-tryCatch(getSymbols(sym, from ="2010-01-01", to =Sys.Date(),auto.assign =FALSE), # <--- clave: devuelve xts directamenteerror =function(e) NULL,warning =function(w) suppressWarnings(tryCatch(getSymbols(sym, from ="2010-01-01", to =Sys.Date(),auto.assign =FALSE), error =function(e) NULL)) )if (!is.null(xts_try) &&NROW(xts_try) >20) { px_daily <-Cl(xts_try) sym_used <- symbreak }}if (is.null(px_daily)) stop("No se pudo descargar ningún futuro de la lista. Revisa conexión o firewall.")# Agregación mensualpx_month <-to.monthly(px_daily, indexAt ="lastof", OHLC =FALSE)colnames(px_month) <-"Precio"# Retornos log mensualesret_m <-na.omit(diff(log(px_month)))mu_m <-mean(ret_m)[[1]]sd_m <-sd(ret_m)[[1]]resumen <- tibble::tibble(`Futuro (Yahoo)`= sym_used,`Periodo`=paste(format(start(px_month), "%Y-%m"), "→", format(end(px_month), "%Y-%m")),`Obs (mensuales)`=nrow(ret_m),`Retorno medio mensual (%)`=round(100*mu_m, 3),`Desv.est. mensual (%)`=round(100*sd_m, 3),`Retorno medio anual (%)`=round(100*mu_m*12, 2),`Volatilidad anual (%)`=round(100*sd_m*sqrt(12), 2))knitr::kable(resumen, caption ="Futuro (Yahoo): retornos logarítmicos mensuales y volatilidad")# Últimos 12 retornosult12 <-tail(100* ret_m, 12)knitr::kable(tibble(Mes =format(index(ult12), "%Y-%m"),`Retorno mensual (%)`=round(coredata(ult12[,1]), 3)),caption =paste0("Últimos 12 retornos mensuales de ", sym_used, " (en %)"))``````{r}# Gráficos rápidosggplot(fortify.zoo(px_month) |>as_tibble() |>rename(Mes = Index, Precio = Precio),aes(Mes, Precio)) +geom_line() +labs(title =paste0("Precio mensual: ", sym_used), x ="Mes", y ="Precio") +theme_minimal()```El WTI muestra un retorno medio mensual de −0,095 % (≈ −1,14 % anual), lo que sugiere una tendencia plana/ligeramente negativa en el largo plazo. La volatilidad mensual de 11,36 % (≈ 39,36 % anual) es elevada, coherente con un activo cíclico y sensible a shocks de oferta/demanda. En los últimos 12 meses aparecen oscilaciones marcadas, destacando abr-2025: −20,54 % y tramos de recuperación (jun–jul 2025 con \>6 % mensual), seguidos de nuevas caídas (ago–oct). En términos de cobertura, este perfil implica requisitos de margen exigentes, mark-to-market volátil y la necesidad de dimensionar el hedge con cautela (p. ej., escalonando entradas o ajustando el tamaño en función de la volatilidad reciente).### Simule por medio de BMG mensual el comportamiento del futuro```{r}#| label: sim-bmg-futuro#| message: false#| warning: falsesuppressPackageStartupMessages({library(quantmod); library(dplyr); library(tidyr); library(xts); library(zoo)library(ggplot2); library(knitr)})# -------------------------------# 1) Parámetros y descarga# -------------------------------symbol <-"CL=F"# futuro continuo a usar (cámbialo si deseas)fecha_ini <-"2010-01-01"# Descarga robusta (sin auto-assign para evitar nombres raros)px_daily <-tryCatch( { xts_obj <-getSymbols(symbol, from = fecha_ini, to =Sys.Date(),auto.assign =FALSE)Cl(xts_obj) },error =function(e) stop("No se pudo descargar el símbolo de Yahoo. Revisa conexión o cambia 'symbol'."))# A mensualpx_m <-to.monthly(px_daily, indexAt ="lastof", OHLC =FALSE)colnames(px_m) <-"Precio"# Retornos log mensuales y parámetros históricosret_m <-na.omit(diff(log(px_m)))mu_hat <-as.numeric(mean(ret_m)) # media mensualsg_hat <-as.numeric(sd(ret_m)) # desviación mensual# -------------------------------# 2) Configuración de simulación# -------------------------------set.seed(123)H <-12# horizonte en meses (ajusta si quieres)N_paths <-5000# nº trayectoriasDelta <-1.0# paso mensualS0 <-as.numeric(last(px_m)) # último precio mensual observado# (Opcional) Escenarios: multiplicador de volatilidadvol_mult <-1.0# 1.0 = histórico; >1 estrés; <1 relajadomu_sim <- mu_hatsg_sim <- sg_hat * vol_mult# -------------------------------# 3) Simulación BMG# -------------------------------Z <-matrix(rnorm(H * N_paths), nrow = H, ncol = N_paths)drift <- (mu_sim -0.5* sg_sim^2) * Deltashock <- sg_sim *sqrt(Delta) * Zlog_increments <-sweep(shock, 1, drift, `+`) # H x Nlog_levels <-apply(log_increments, 2, cumsum)S_paths <-exp( log(S0) +rbind(rep(0, N_paths), log_levels) ) # (H+1) x N# Fechas simuladas (mensuales)dates_sim <-seq.Date(from =as.Date(end(px_m)), by ="month", length.out = H +1)# -------------------------------# 4) Resumen por mes (cuantiles)# -------------------------------sum_tab <-apply(S_paths, 1, quantile, probs =c(0.05, 0.5, 0.95))sum_df <-tibble(Mes = dates_sim,p05 = sum_tab[1,],p50 = sum_tab[2,],p95 = sum_tab[3,])knitr::kable( sum_df %>%mutate(across(c(p05, p50, p95), ~round(.x, 2))),caption =paste0(symbol, " – Simulación BMG mensual: cuantiles 5%, 50% y 95%"))# -------------------------------# 5) Distribución al horizonte# -------------------------------h_vals <- S_paths[H +1, ]resumen_h <-tibble(`Precio (p05)`=round(quantile(h_vals, 0.05), 2),`Precio (mediana)`=round(median(h_vals), 2),`Precio (p95)`=round(quantile(h_vals, 0.95), 2))knitr::kable(resumen_h, caption =paste0(symbol, " – Distribución simulada al horizonte de ", H, " meses"))# -------------------------------# 6) Gráfico: abanico + trayectorias# -------------------------------# Seleccionar unas pocas trayectorias para que se aprecien individualmenteset.seed(123)n_show <-25idx <-sample(ncol(S_paths), n_show)df_paths <-as.data.frame(S_paths[, idx])colnames(df_paths) <-paste0("path_", seq_len(n_show))df_paths$Mes <- dates_simdf_long <- df_paths |>pivot_longer(-Mes, names_to ="Trayectoria", values_to ="Precio")ggplot() +geom_ribbon(data = sum_df, aes(x = Mes, ymin = p05, ymax = p95), alpha =0.18) +geom_line(data = df_long, aes(x = Mes, y = Precio, group = Trayectoria), linewidth =0.3, alpha =0.35) +geom_line(data = sum_df, aes(x = Mes, y = p50), linewidth =1.0) +labs(title =paste0("Simulación BMG mensual – ", symbol),subtitle =paste0("S0 = ", round(S0,2)," | μ̂ = ", round(mu_hat*100,2), "% mensual, σ̂ = ", round(sg_hat*100,2), "% mensual"," | H=", H, " meses, N=", N_paths, ", vol_mult=", vol_mult),x ="Mes", y ="Precio del futuro" ) +theme_minimal(base_size =12)```La simulación BMG mensual del futuro del petróleo WTI (CL=F) muestra que, partiendo de un precio actual de USD 60,88 y bajo un retorno promedio histórico de −0,1 % mensual, el comportamiento esperado tiende a ser estable o ligeramente descendente en el horizonte de un año.El intervalo de confianza (zona gris) evidencia una alta dispersión, producto de la volatilidad mensual estimada en 11,36 %, lo que implica que los precios podrían fluctuar entre valores cercanos a USD 45 y USD 110 hacia finales del periodo. En términos prácticos, el futuro del WTI conserva un riesgo elevado, característico de los commodities energéticos, donde shocks de oferta o geopolíticos pueden generar desviaciones fuertes respecto al valor esperado, lo que resalta la importancia de estrategias de cobertura o ajuste dinámico del portafolio.