1 Integrantes

Grupo 06:

2 Objetivo del taller

En este taller aprenderás a crear un reporte reproducible con R Markdown (RStudio) analizando el comportamiento de Bitcoin (BTC) usando datos reales de Yahoo Finance. install.packages(c(“lubridate”, “rlang”, “vctrs”, “timechange”)) library(lubridate) Construiremos:

Requisito: conexión a internet (Yahoo Finance).


3 Descarga de datos desde Yahoo Finance

Usaremos el ticker: BTC-USD (Bitcoin en USD) desde Yahoo Finance.

# ============================================================
# DESCARGA BTC-USD DESDE YAHOO FINANCE
# - from: fecha inicial de descarga
# - auto.assign = FALSE: devuelve el objeto en lugar de guardarlo en el environment
# ============================================================

ticker <- "BTC-USD"
fecha_inicio <- as.Date("2023-01-01")

# Descarga (puede demorar unos segundos según conexión)
btc_xts <- quantmod::getSymbols(
  Symbols = ticker,
  src = "yahoo",
  from = fecha_inicio,
  auto.assign = FALSE
)

# Validación rápida: debe tener filas
stopifnot(NROW(btc_xts) > 0)

# Convertimos a tibble limpio
btc <- btc_xts |>
  as.data.frame() |>
  rownames_to_column("date") |>
  as_tibble() |>
  rename(
    open     = paste0(ticker, ".Open"),
    high     = paste0(ticker, ".High"),
    low      = paste0(ticker, ".Low"),
    close    = paste0(ticker, ".Close"),
    volume   = paste0(ticker, ".Volume"),
    adjusted = paste0(ticker, ".Adjusted")
  ) |>
  mutate(date = as.Date(date)) |>
  arrange(date)

# Vista rápida
glimpse(btc)
## Rows: 1,086
## Columns: 7
## $ date     <date> 2023-01-01, 2023-01-02, 2023-01-03, 2023-01-04, 2023-01-05, …
## $ open     <dbl> 16547.91, 16625.51, 16688.85, 16680.21, 16863.47, 16836.47, 1…
## $ high     <dbl> 16630.44, 16759.34, 16760.45, 16964.59, 16884.02, 16991.99, 1…
## $ low      <dbl> 16521.23, 16572.23, 16622.37, 16667.76, 16790.28, 16716.42, 1…
## $ close    <dbl> 16625.08, 16688.47, 16679.86, 16863.24, 16836.74, 16951.97, 1…
## $ volume   <dbl> 9244361700, 12097775227, 13903079207, 18421743322, 1369275856…
## $ adjusted <dbl> 16625.08, 16688.47, 16679.86, 16863.24, 16836.74, 16951.97, 1…
head(btc, 5)
## # A tibble: 5 × 7
##   date         open   high    low  close      volume adjusted
##   <date>      <dbl>  <dbl>  <dbl>  <dbl>       <dbl>    <dbl>
## 1 2023-01-01 16548. 16630. 16521. 16625.  9244361700   16625.
## 2 2023-01-02 16626. 16759. 16572. 16688. 12097775227   16688.
## 3 2023-01-03 16689. 16760. 16622. 16680. 13903079207   16680.
## 4 2023-01-04 16680. 16965. 16668. 16863. 18421743322   16863.
## 5 2023-01-05 16863. 16884. 16790. 16837. 13692758566   16837.
tail(btc, 5)
## # A tibble: 5 × 7
##   date         open   high    low  close      volume adjusted
##   <date>      <dbl>  <dbl>  <dbl>  <dbl>       <dbl>    <dbl>
## 1 2025-12-17 87848. 90265. 85316. 86144. 44243392914   86144.
## 2 2025-12-18 86144. 89413. 84436. 85463. 52667115348   85463.
## 3 2025-12-19 85476. 89339. 85108. 88103. 46733310561   88103.
## 4 2025-12-20 88102. 88497. 87925. 88344  14688196659   88344 
## 5 2025-12-21 88340. 89011. 87666. 88297. 18405640192   88297.

4 Preparación y validaciones básicas

# ============================================================
# VALIDACIONES
# ============================================================

# 1) Tipos
stopifnot(inherits(btc$date, "Date"))

# 2) Orden cronológico
stopifnot(isTRUE(all(diff(btc$date) >= 0)))

# 3) Duplicados de fecha (por si acaso)
btc <- btc |> distinct(date, .keep_all = TRUE)

# Rango de fechas y tamaño
min(btc$date)
## [1] "2023-01-01"
max(btc$date)
## [1] "2025-12-21"
nrow(btc)
## [1] 1086

5 Métricas del comportamiento

5.1 Retornos diarios

Retorno simple:

\[ r_t = \frac{P_t}{P_{t-1}} - 1 \]

btc <- btc |>
  mutate(return = close / lag(close) - 1)

summary(btc$return)
##       Min.    1st Qu.     Median       Mean    3rd Qu.       Max.       NA's 
## -0.0868204 -0.0103730  0.0002861  0.0018389  0.0130973  0.1214426          1

KPIs rápidos (inline R):

  • Observaciones: 1086
  • Fecha inicial: 2023-01-01
  • Fecha final: 2025-12-21
  • Precio último día (close): 8.829714^{4}
  • Retorno medio diario: 0.001839
  • Volatilidad diaria (sd): 0.024564

5.2 Promedios móviles (MA 7, MA 30 Y MA 90)

btc <- btc |>
  mutate(
    ma_7  = zoo::rollmean(close, k = 7,  fill = NA, align = "right"),
    ma_30 = zoo::rollmean(close, k = 30, fill = NA, align = "right"),
    ma_90 = zoo::rollmean(close, k = 90, fill = NA, align = "right")
  )

5.3 Volatilidad rolling (30 días)

btc <- btc |>
  mutate(
    vol_30 = zoo::rollapply(
      return, width = 30, FUN = sd,
      fill = NA, align = "right", na.rm = TRUE
    )
  )

summary(btc$vol_30)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max.     NA's 
## 0.008887 0.018840 0.023206 0.023705 0.027381 0.044290       29

6 Visualizaciones

6.1 Precio de cierre + promedios móviles

ggplot(btc, aes(x = date)) +
  geom_line(aes(y = close)) +
  geom_line(aes(y = ma_7), linetype = "dashed") +
  geom_line(aes(y = ma_30),  linetype = "dotted") +
  geom_line(aes(y = ma_90), linetype = "dotted") +
  scale_y_continuous(labels = scales::comma) +
  labs(
    title = "Bitcoin (BTC-USD): Precio de cierre y promedios móviles",
    subtitle = "MA 7 días (dashed), MA 30 días (dotted) y MA 90 días (dotted) - Fuente: Yahoo Finance",
    x = "Fecha",
    y = "Precio (USD)"
  )

6.2 Retornos diarios

ggplot(btc, aes(x = date, y = return)) +
  geom_line() +
  scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)) +
  labs(
    title = "Bitcoin (BTC-USD): Retornos diarios",
    subtitle = "Los picos reflejan días de movimientos bruscos",
    x = "Fecha",
    y = "Retorno diario"
  )

6.3 Volatilidad rolling 30 días

ggplot(btc, aes(x = date, y = vol_30)) +
  geom_line() +
  scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)) +
  labs(
    title = "Bitcoin (BTC-USD): Volatilidad rolling 30 días",
    subtitle = "Desv. estándar de retornos diarios (ventana móvil de 30 días)",
    x = "Fecha",
    y = "Volatilidad (sd)"
  )


7 Tabla de resumen mensual

Resumimos por mes:

btc_mensual <- btc |>
  mutate(year_month = floor_date(date, unit = "month")) |>
  group_by(year_month) |>
  summarise(
    n_dias = sum(!is.na(return)),
    close_fin = last(close),
    ret_prom = mean(return, na.rm = TRUE),
    vol = sd(return, na.rm = TRUE),
    .groups = "drop"
  ) |>
  mutate(
    close_fin = round(close_fin, 2),
    ret_prom = round(ret_prom, 6),
    vol = round(vol, 6)
  )

kable(btc_mensual, caption = "Resumen mensual de BTC (Fuente: Yahoo Finance)")
Resumen mensual de BTC (Fuente: Yahoo Finance)
year_month n_dias close_fin ret_prom vol
2023-01-01 30 23139.28 0.011348 0.023726
2023-02-01 28 23147.35 0.000334 0.026163
2023-03-01 31 28478.48 0.007327 0.036150
2023-04-01 30 29268.81 0.001116 0.020467
2023-05-01 31 27219.66 -0.002184 0.017867
2023-06-01 30 30477.25 0.004076 0.025073
2023-07-01 31 29230.11 -0.001264 0.013072
2023-08-01 31 25931.47 -0.003634 0.021277
2023-09-01 30 26967.92 0.001373 0.011710
2023-10-01 31 34667.78 0.008395 0.023681
2023-11-01 30 37712.75 0.003048 0.022270
2023-12-01 31 42265.19 0.003947 0.023371
2024-01-01 31 42582.61 0.000643 0.028747
2024-02-01 29 61198.38 0.012872 0.024830
2024-03-01 31 71333.65 0.005697 0.039216
2024-04-01 30 60636.86 -0.005020 0.027916
2024-05-01 31 67491.41 0.003850 0.028702
2024-06-01 30 62678.29 -0.002321 0.017098
2024-07-01 31 64619.25 0.001281 0.024803
2024-08-01 31 58969.90 -0.002305 0.036792
2024-09-01 30 63329.50 0.002624 0.022475
2024-10-01 31 70215.19 0.003539 0.020570
2024-11-01 30 96449.05 0.011132 0.032485
2024-12-01 31 93429.20 -0.000760 0.023394
2025-01-01 31 102405.02 0.003217 0.022896
2025-02-01 28 84373.01 -0.006695 0.020156
2025-03-01 31 82548.91 -0.000102 0.035319
2025-04-01 30 94207.31 0.004815 0.029011
2025-05-01 31 104638.09 0.003563 0.018852
2025-06-01 30 107135.34 0.000921 0.016752
2025-07-01 31 115758.20 0.002593 0.013885
2025-08-01 31 108236.71 -0.001995 0.018706
2025-09-01 30 114056.09 0.001826 0.012734
2025-10-01 31 109556.16 -0.001050 0.022486
2025-11-01 30 90394.31 -0.006121 0.023348
2025-12-01 21 88297.14 -0.000855 0.023515

8 Mini-taller para alumnos (práctica guiada)

8.1 Actividad 1 (Básica)

  1. Cambia fecha_inicio a "2023-01-01"
  2. Renderiza y compara:
  • retorno medio diario
  • volatilidad diaria
  • meses con mayor volatilidad

8.2 Actividad 2 (Intermedia)

  1. Agrega MA 90 días (ma_90)
  2. Grafica close, ma_30, ma_90

8.3 Actividad 3 (Reto)

Obtén:

  • Top 10 retornos positivos
  • Top 10 retornos negativos

y muéstralos en el reporte.

top_pos <- btc |>
  filter(!is.na(return)) |>
  arrange(desc(return)) |>
  select(date, close, return) |>
  head(10)

top_neg <- btc |>
  filter(!is.na(return)) |>
  arrange(return) |>
  select(date, close, return) |>
  head(10)

kable(top_pos, caption = "Top 10 retornos positivos (BTC-USD)")
Top 10 retornos positivos (BTC-USD)
date close return
2024-08-08 61710.14 0.1214426
2023-10-23 33086.23 0.1030989
2024-11-11 88701.48 0.1022352
2024-03-20 67913.67 0.0969250
2025-03-02 94248.35 0.0955045
2024-02-28 62504.79 0.0949353
2023-03-17 27423.93 0.0946458
2023-02-15 24307.84 0.0939227
2023-03-13 24197.53 0.0917519
2024-11-06 75639.08 0.0905357
kable(top_neg, caption = "Top 10 retornos negativos (BTC-USD)")
Top 10 retornos negativos (BTC-USD)
date close return
2025-03-03 86065.67 -0.0868204
2024-03-19 61912.77 -0.0834336
2024-01-12 42853.17 -0.0758146
2024-08-05 53991.46 -0.0709865
2023-08-17 26664.55 -0.0709792
2025-10-10 113214.37 -0.0697685
2024-03-05 63801.20 -0.0662840
2025-03-09 80601.04 -0.0644603
2025-04-06 78214.48 -0.0633534
2023-03-09 20363.02 -0.0623931

9 Conclusiones (plantilla)

  1. Tendencia general (según MA30 y comportamiento del precio).
  2. Periodos de alta volatilidad (según vol_30).
  3. Días extremos (tablas top_pos / top_neg).

10 Reproducibilidad

sessionInfo()
## R version 4.5.2 (2025-10-31 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 10 x64 (build 19044)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=Spanish_Peru.utf8  LC_CTYPE=Spanish_Peru.utf8   
## [3] LC_MONETARY=Spanish_Peru.utf8 LC_NUMERIC=C                 
## [5] LC_TIME=Spanish_Peru.utf8    
## 
## time zone: America/Lima
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] scales_1.4.0    tibble_3.3.0    knitr_1.51      lubridate_1.9.4
##  [5] ggplot2_4.0.1   dplyr_1.1.4     quantmod_0.4.28 TTR_0.24.4     
##  [9] xts_0.14.1      zoo_1.8-15     
## 
## loaded via a namespace (and not attached):
##  [1] gtable_0.3.6       jsonlite_2.0.0     compiler_4.5.2     tidyselect_1.2.1  
##  [5] jquerylib_0.1.4    yaml_2.3.12        fastmap_1.2.0      lattice_0.22-7    
##  [9] R6_2.6.1           labeling_0.4.3     generics_0.1.4     curl_7.0.0        
## [13] bslib_0.9.0        pillar_1.11.1      RColorBrewer_1.1-3 rlang_1.1.6       
## [17] cachem_1.1.0       xfun_0.55          sass_0.4.10        S7_0.2.1          
## [21] timechange_0.3.0   cli_3.6.5          withr_3.0.2        magrittr_2.0.4    
## [25] digest_0.6.39      grid_4.5.2         rstudioapi_0.17.1  lifecycle_1.0.4   
## [29] vctrs_0.6.5        evaluate_1.0.5     glue_1.8.0         farver_2.1.2      
## [33] rmarkdown_2.30     tools_4.5.2        pkgconfig_2.0.3    htmltools_0.5.9

10.1 Nota importante

Yahoo Finance puede cambiar disponibilidad o límites. Si falla la descarga:

  • revisa conexión
  • actualiza paquetes
  • intenta nuevamente con otra fecha de inicio