Panel Financiero sobre datos del tipo de cambio en Argentina.
Los precios en Argentina cambian con mucha frecuencia, también lo hacen los precios relativos y, a veces, con variaciones altas durante el día. Justamente este ultimo caso es para el tipo de cambio.
La relación peso dolar en Argentina se mide a través de distintos tipos de cambios como el financiero, el dolar calle (Blue) y el comercial. Para poder seguir estos precios y la brecha cambiaria entre los principales tipos de cambio desarrolle esta sencilla aplicación utilizando el framework Shiny a los efectos de poder tener una dimensión de los precios, variaciones y relaciones entre ellos.
Esta aplicación en R se desarrollo utilizando el framework bs4Dash para consultar los datos de los distintos tipos de cambio en Argentina. El Dashboard contiene la siguientes funcionalidades para interactuar con los datos de ámbito dolar:
A continuación se muestra un ejemplo de la extracción de los datos del dolar informal desde la API de Ambito.
En primer lugar se obtienen la urls de acceso para el valor diario y el histórico:
url_informal = "https://mercados.ambito.com/dolar/informal/historico-general/"
url_informal_diario <- "https://mercados.ambito.com/dolar/informal/variacion"
Luego creamos una función que puede ser reutilizable para obtener en formato json la respuesta de la API:
get_json <- function(url) {
tryCatch({
response <- httr::GET(url, headers = c("sec-ch-ua" = "^Chromium^;v=^116^, ^Not"))
status <- httr::http_status(response)$reason
if (status == "OK") {
response_content <- httr::content(response, "text")
tryCatch({
response_json <- jsonlite::fromJSON(response_content, simplifyVector = FALSE)
return(response_json)
}, error = function(e) {
cat("Error al analizar el JSON:", e$message,url, "\n")
return(NULL)
})
} else {
cat("La solicitud no se pudo completar. Código de estado:", status,url, "\n")
return(NULL)
}
}, error = function(e) {
cat("Error en la solicitud HTTP:", e$message, "\n")
return(NULL)
})
}
El siguiente paso es obtener los datos diarios del tipo de cambio, para ello realizamos una request a la API, transformamos el json en un tibble y por ultimo le damos el formato deseado al tibble:
format_df_informal = function(df){
return(
df %>% mutate(
Fecha = as.Date(strsplit(fecha, " - ")[[1]][1], format = "%d/%m/%Y"),
Compra = round(as.numeric(gsub(",", ".", compra)),2),
Venta = round(as.numeric(gsub(",", ".", venta)),2),
Promedio = ((Compra + Venta) / 2),
variacion = round(as.numeric(gsub(",", ".", gsub("%", "", variacion))),4)) %>%
select(Fecha, Compra, Venta, Promedio, variacion)
)
}
informal_json_diario = format_df_informal(
as_tibble(get_json(url_informal_diario))
)
head(informal_json_diario)%>% gt()
Fecha | Compra | Venta | Promedio | variacion |
---|---|---|---|---|
2023-11-21 | 1025 | 1075 | 1050 | 13.16 |
Luego obtenemos los datos históricos utilizando un rango temporal:
get_dolar_informal = function(url, from, to){
url_historico <- paste0(url, from,"/",to)
response_json = get_json(url_historico)
data_frame <- response_json %>%
purrr::map_dfr(~setNames(as.list(.x), c("Fecha", "Compra", "Venta")))
mi_tibble <- as_tibble(data_frame)[-1, ]
df <- mi_tibble %>%
mutate(Fecha = as.Date(Fecha, format = "%d/%m/%Y")) %>%
arrange(Fecha) %>%
group_by(Fecha) %>%
filter(Venta == max(Venta)) %>%
ungroup() %>%
distinct()
return(
df %>% arrange(Fecha) %>% mutate(
Fecha = as.Date(Fecha, format = "%d/%m/%Y"),
Compra = round(as.numeric(gsub(",", ".", Compra)),2),
Venta = round(as.numeric(gsub(",", ".", Venta)),2),
Promedio = ((Compra + Venta) / 2),
variacion = round((Promedio - lag(Promedio, n = 1)) /
lag(Promedio, n = 1),4)*100) %>%
select(Fecha, Compra, Venta, Promedio, variacion)
)
}
today = as.Date(today())
from = as.Date(today() - years(1))
to = as.Date(today())
informal_json_anual = get_dolar_informal(url_informal, from, to) %>%
filter(Fecha != to, Fecha != today) %>% arrange(desc(Fecha))
head(informal_json_anual) %>% gt()
Fecha | Compra | Venta | Promedio | variacion |
---|---|---|---|---|
2023-11-17 | 900 | 950 | 925 | 0.00 |
2023-11-16 | 900 | 950 | 925 | -2.12 |
2023-11-15 | 920 | 970 | 945 | 5.00 |
2023-11-14 | 875 | 925 | 900 | 0.00 |
2023-11-13 | 875 | 925 | 900 | -3.74 |
2023-11-10 | 910 | 960 | 935 | 1.08 |
El ultimo paso es juntar el dataframe diario con el historico y ya tenemos los datos:
informal = rbind(
informal_json_anual,
informal_json_diario
) %>% arrange(desc(Fecha)) %>% distinct()
head(informal) %>% gt()
Fecha | Compra | Venta | Promedio | variacion |
---|---|---|---|---|
2023-11-21 | 1025 | 1075 | 1050 | 13.16 |
2023-11-17 | 900 | 950 | 925 | 0.00 |
2023-11-16 | 900 | 950 | 925 | -2.12 |
2023-11-15 | 920 | 970 | 945 | 5.00 |
2023-11-14 | 875 | 925 | 900 | 0.00 |
2023-11-13 | 875 | 925 | 900 | -3.74 |
Si queremos desarrollar una Shiny App y que en en la interfaz de usuario podamos ver los cambios en los precios cuando actualizamos la aplicación y que en consecuencia se modifiquen otros elementos existentes dependientes de esos precios tenemos que utilizar variables reactivas.
En Shiny, la Programacion Reactiva se utiliza para construir aplicaciones que pueden responder de manera dinámica a las interacciones del usuario y a los cambios en los datos.
En R, reactive y reactiveVal son funciones que se utilizan en el contexto de programación reactiva, especialmente en el desarrollo de aplicaciones Shiny.
reactiveVal es una función que se utiliza para crear un contenedor reactivo mutable con un valor inicial. A diferencia de reactive, que encapsula expresiones reactivas, reactiveVal encapsula un valor reactivo específico. Puede ser útil cuando se necesita almacenar y modificar un valor en respuesta a eventos sin tener que crear una función completa.
reactive se utiliza para definir objetos reactivos. Un objeto reactivo es aquel cuyo valor puede cambiar en respuesta a cambios en otros objetos reactivos o eventos externos. Los objetos reactivos se utilizan comúnmente para encapsular operaciones o cálculos que dependen de entradas dinámicas, como widgets de la interfaz de usuario (por ejemplo, un deslizador o un cuadro de texto). Se usa dentro de una función Shiny para crear un objeto reactivo. La función reactive toma como argumento una expresión R y devuelve un objeto reactivo que representa el resultado de esa expresión.
Para esta aplicación se utilizo con reactiveVal la obtención de los datos desde la API y como reactive los elementos que dependen de esa extracción de datos.
Este es un ejemplo sencillo de reactive y reactiveVal:
dolarmepcierre depende de mep, si hay un cambio en mep eso hace que la variable reactiva dolarmepcierre cambie si se pueda visualizar en la UI los cambios.
= reactiveVal(
mep rbind(
mep_json_anual,
mep_json_diario%>% arrange(Fecha) %>% distinct()
)
)
= reactive(
dolarmepcierre mep()$Promedio[nrow(mep())]
)
Mas informacion sobre reactividad en shiny: Mastering-Shiny
Para correr la app en un contenedor de Docker hay que utilizar el siguiente comando:
(Primero cambiar las source de los volumes en docker-compose.yml)
docker-compose up -d
Este comando va a crear una instancia de una imagen (un contenedor) en el puerto que se encuentra configurado en el docker-compose.yaml.
Si la imagen no esta descargada primero lo que va a hacer es descargarla y luego levantar el contenedor.
Para detener y eliminar el contenedor hay que correr:
docker-compose down