Este análisis simula el comportamiento de 6 casas de cambio que operan con USD y EUR bajo dos escenarios:
Días 1–3: Todas las casas operan bajo un convenio de márgenes fijos.
Días 4–6: Ninguna casa opera en convenio (libre mercado).
El objetivo es comparar la estabilidad, la ganancia diaria y el riesgo asociado a cada escenario.
Casas de cambio: 6
Divisas: USD y EUR
Precio base:
USD: $3,600 pesos
EUR: $3,950 pesos
Margen con convenio: $80 – $100 pesos.
Margen sin convenio: Media de $70 pesos, con alta volatilidad (desviación estándar de 45).
set.seed(123)
n_casas <- 6
dias <- 1:6
casas <- paste("Casa", 1:n_casas)
divisas <- tibble(
divisa = c("USD", "EUR"),
precio_base = c(3600, 3950)
)
La simulación que desarrollaré consiste en 6 días de trabajo bajo 2 escenarios: dentro y fuera del convenio.
datos <- expand_grid(
dia = dias,
casa = casas,
divisa = divisas$divisa
) %>%
left_join(divisas, by = "divisa") %>%
mutate(
escenario = if_else(dia <= 3, "Convenio", "Sin convenio"),
# Variación diaria del precio base de la divisa
precio_dia = precio_base + rnorm(n(), mean = 0, sd = 20),
# Márgenes según el escenario en el que nos encontremos
margen = if_else(
escenario == "Convenio",
runif(n(), 80, 100),
rnorm(n(), mean = 70, sd = 45)
),
# Volumen diario de operaciones
transacciones = sample(80:90, n(), replace = TRUE),
# Cálculo financiero principal
ganancia_diaria = margen * transacciones,
# Variables auxiliares para los gráficos y análisis
fuera_rango = margen < 80 | margen > 100,
categoria_margen = case_when(
margen < 80 ~ "Bajo (<80)",
margen >= 80 & margen <= 100 ~ "Convenio (80–100)",
margen > 100 ~ "Alto (>100)"
)
)
# Vista previa de los datos generados
head(datos)
## # A tibble: 6 × 11
## dia casa divisa precio_base escenario precio_dia margen transacciones
## <int> <chr> <chr> <dbl> <chr> <dbl> <dbl> <int>
## 1 1 Casa 1 USD 3600 Convenio 3589. 96.9 81
## 2 1 Casa 1 EUR 3950 Convenio 3945. 84.6 80
## 3 1 Casa 2 USD 3600 Convenio 3631. 84.8 80
## 4 1 Casa 2 EUR 3950 Convenio 3951. 81.5 81
## 5 1 Casa 3 USD 3600 Convenio 3603. 84.9 80
## 6 1 Casa 3 EUR 3950 Convenio 3984. 94.6 81
## # ℹ 3 more variables: ganancia_diaria <dbl>, fuera_rango <lgl>,
## # categoria_margen <chr>
Para que los datos sean visualmente legibles, organizaremos los días en el eje X y el margen operativo con el que trabajó la casa de cambio en el eje Y.
ggplot(datos, aes(x = factor(dia), y = margen, fill = escenario)) +
geom_boxplot(alpha = 0.8, color = "gray30") +
facet_wrap(~divisa) +
scale_y_continuous(labels = label_dollar(prefix = "$")) +
scale_fill_manual(values = c("Convenio" = "#2E86AB", "Sin convenio" = "#D64550")) +
labs(
title = "Distribución de Márgenes Diarios",
subtitle = "Comparativa de 6 casas de cambio en 6 días simulados",
x = "Día",
y = "Margen por operación",
fill = "Escenario:"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", size = 16),
plot.subtitle = element_text(color = "gray40", margin = margin(b = 15)),
legend.position = "bottom",
legend.title = element_text(face = "bold"),
strip.background = element_rect(fill = "gray90", color = NA),
strip.text = element_text(face = "bold", size = 12),
panel.grid.minor = element_blank()
)
# ¿Qué nos dice esta gráfica?
Estamos observando la comparativa entre los márgenes en EUR y USD, tanto dentro como fuera del convenio. A simple vista, podría parecer atractivo tener un margen superior a $100 pesos cuando nos convenga, y reducirlo cuando necesitemos vender volumen. Sin embargo, en la práctica el mercado no funciona así de forma sostenida, lo cual demostraré en el siguiente gráfico simulando el impacto directo en las ganancias.
Se visualiza claramente la estabilidad durante los días de convenio.
Se evidencia una dispersión extrema (y riesgo) en los días sin el pacto.
ggplot(datos, aes(x = factor(dia), y = ganancia_diaria, fill = escenario)) +
geom_point(shape = 21, size = 3, alpha = 0.8, stroke = 0.3, color = "white") +
facet_grid(divisa ~ casa) +
scale_y_continuous(labels = label_dollar(prefix = "$")) +
scale_fill_manual(values = c("Convenio" = "#2E86AB", "Sin convenio" = "#D64550")) +
labs(
title = "Ganancia Diaria por Casa y Divisa",
x = "Día de operación",
y = "Ganancia diaria",
fill = "Escenario:"
) +
theme_minimal(base_size = 11) +
theme(
plot.title = element_text(face = "bold", size = 14),
legend.position = "bottom",
strip.background = element_rect(fill = "gray90", color = NA),
strip.text = element_text(face = "bold"),
panel.grid.minor = element_blank(),
axis.text.x = element_text(angle = 45, hjust = 1)
)
# ¿Cómo interpretar este gráfico?
Cada casa de cambio operó 3 días dentro del convenio y 3 días fuera de él. Las casas que estuvieron bajo el pacto mantuvieron ganancias estables. Por otro lado, fuera del convenio, algunas casas tuvieron márgenes muy elevados un día (generando picos de ganancia excepcionales por aprovechar una ventaja temporal en el sector), pero al día siguiente sufrieron márgenes demasiado reducidos. Incluso, llegaron a operar por debajo del precio de compra de la divisa, lo que se tradujo en pérdidas netas.
Con el siguiente gráfico visualizaremos exclusivamente aquellas operaciones que salieron del rango óptimo acordado.
ggplot(filter(datos, fuera_rango),
aes(x = casa, y = margen, fill = escenario)) +
geom_point(shape = 21, size = 3, alpha = 0.9, color = "white", stroke = 0.4) +
facet_wrap(~divisa) +
scale_y_continuous(labels = label_dollar(prefix = "$")) +
scale_fill_manual(values = c("Sin convenio" = "#D64550")) +
labs(
title = "Márgenes Fuera del Rango Acordado (Menos de $80 o más de $100)",
x = "Casa de Cambio",
y = "Margen por operación",
fill = "Escenario:"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", size = 14),
legend.position = "bottom",
strip.background = element_rect(fill = "gray90", color = NA),
strip.text = element_text(face = "bold"),
axis.text.x = element_text(angle = 45, hjust = 1)
)
## Interpretación:
Aquí observamos la magnitud del desvío en los márgenes cuando no existe un convenio. Ahora comparémoslo de frente con el impacto en ganancias mediante diagramas de dispersión.
ggplot(
filter(datos, escenario == "Convenio"),
aes(x = margen, y = ganancia_diaria, fill = categoria_margen)
) +
geom_point(shape = 21, size = 3, alpha = 0.8, stroke = 0.4, color = "white") +
facet_wrap(~divisa) +
scale_fill_manual(
values = c("Convenio (80–100)" = "#2E86AB")
) +
scale_x_continuous(labels = label_dollar(prefix = "$")) +
scale_y_continuous(labels = label_dollar(prefix = "$")) +
labs(
title = "Relación Margen vs Ganancia",
subtitle = "Casas de cambio EN Convenio",
x = "Margen por operación",
y = "Ganancia diaria",
fill = "Categoría de Margen:"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", size = 16),
plot.subtitle = element_text(color = "gray40", margin = margin(b = 15)),
legend.position = "bottom",
legend.title = element_text(face = "bold"),
strip.background = element_rect(fill = "gray90", color = NA),
strip.text = element_text(face = "bold", size = 12),
panel.grid.minor = element_blank(),
panel.spacing = unit(1, "lines")
)
# Interpretación:
Se observa una relación clara y predecible. No existen puntos extremos ni caídas peligrosas, lo que proporciona mayor seguridad sobre el capital de trabajo. Esta estabilidad garantiza ganancias previsibles, fundamentales para organizar los gastos operativos fijos de cada casa de cambio.
ggplot(
filter(datos, escenario == "Sin convenio"),
aes(x = margen, y = ganancia_diaria, fill = categoria_margen)
) +
geom_point(shape = 21, size = 3, alpha = 0.8, stroke = 0.4, color = "white") +
facet_wrap(~divisa) +
scale_fill_manual(
values = c(
"Bajo (<80)" = "#D64550",
"Alto (>100)" = "#6C3483"
)
) +
scale_x_continuous(labels = label_dollar(prefix = "$")) +
scale_y_continuous(labels = label_dollar(prefix = "$")) +
labs(
title = "Relación Margen vs Ganancia",
subtitle = "Casas de cambio FUERA del Convenio",
x = "Margen por operación",
y = "Ganancia diaria",
fill = "Categoría de Margen:"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", size = 16),
plot.subtitle = element_text(color = "gray40", margin = margin(b = 15)),
legend.position = "bottom",
legend.title = element_text(face = "bold"),
strip.background = element_rect(fill = "gray90", color = NA),
strip.text = element_text(face = "bold", size = 12),
panel.grid.minor = element_blank(),
panel.spacing = unit(1, "lines")
)
# Interpretación:
Existe una altísima dispersión. Los márgenes fluctúan severamente, cayendo a cifras mínimas (e incluso negativas) o disparándose a niveles poco realistas. Siendo sensatos, si una casa intentara mantener un margen tan elevado frente a la competencia, eventualmente otra casa reduciría el suyo para captar el mercado, forzando a todos a cerrar sus propios márgenes y reduciendo las ganancias generales del sector.
ggplot(datos, aes(
x = margen,
y = ganancia_diaria,
fill = categoria_margen
)) +
geom_point(shape = 21, size = 3, alpha = 0.8, stroke = 0.3, color = "white") +
facet_grid(escenario ~ divisa) +
scale_x_continuous(labels = label_dollar(prefix = "$")) +
scale_y_continuous(labels = label_dollar(prefix = "$")) +
scale_fill_viridis_d(option = "mako", begin = 0.2, end = 0.9) +
labs(
title = "Comparación Global: Margen vs Ganancia",
subtitle = "Análisis cruzado: Convenio vs Sin Convenio",
x = "Margen por operación",
y = "Ganancia diaria",
fill = "Categoría de Margen"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", size = 16, hjust = 0.5),
plot.subtitle = element_text(color = "gray40", hjust = 0.5, margin = margin(b = 15)),
legend.position = "bottom",
legend.title = element_text(face = "bold"),
strip.background = element_rect(fill = "gray90", color = NA),
strip.text = element_text(face = "bold", size = 11),
panel.grid.minor = element_blank(),
panel.spacing = unit(1, "lines")
)
# Análisis Complementario ## 1. Ganancia Acumulada (6 días) Para
entender el impacto real en el bolsillo al finalizar la semana,
sumaremos la ganancia total obtenida por cada casa bajo ambos
escenarios.
ganancia_acumulada <- datos %>%
group_by(casa, escenario) %>%
summarise(ganancia_total = sum(ganancia_diaria), .groups = "drop")
ggplot(ganancia_acumulada, aes(x = casa, y = ganancia_total, fill = escenario)) +
geom_col(position = "dodge", color = "white", alpha = 0.9) +
scale_y_continuous(labels = label_dollar(prefix = "$")) +
scale_fill_manual(values = c("Convenio" = "#2E86AB", "Sin convenio" = "#D64550")) +
labs(
title = "Ganancia Total Acumulada por Casa",
subtitle = "Suma de ganancias: 3 días con convenio vs 3 días sin convenio",
x = "Casa de Cambio",
y = "Ganancia Total",
fill = "Escenario:"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", size = 16),
plot.subtitle = element_text(color = "gray40", margin = margin(b = 15)),
legend.position = "bottom",
legend.title = element_text(face = "bold"),
panel.grid.minor = element_blank(),
axis.text.x = element_text(face = "bold")
)
# Interpretación: Como se observa en las barras, el escenario “Sin
convenio” no garantiza una mayor ganancia acumulada a pesar de tener
picos esporádicos de rentabilidad. La estabilidad del “Convenio” suele
entregar retornos más sólidos y parejos al final del periodo
evaluado.
Finalmente, mediremos el riesgo financiero. ¿Qué probabilidad hay de cerrar el día con pérdidas (ganancia negativa) si operamos con o sin convenio?
probabilidad_perdida <- datos %>%
group_by(escenario) %>%
summarise(
dias_totales = n(),
dias_perdida = sum(ganancia_diaria < 0),
prob_perdida_pct = percent(dias_perdida / dias_totales, accuracy = 0.1)
) %>%
rename(
"Escenario Operativo" = escenario,
"Operaciones Totales" = dias_totales,
"Días con Pérdidas" = dias_perdida,
"Probabilidad de Pérdida" = prob_perdida_pct
)
kable(probabilidad_perdida, align = "lccc", caption = "Riesgo de registrar ganancias diarias negativas según escenario")
| Escenario Operativo | Operaciones Totales | Días con Pérdidas | Probabilidad de Pérdida |
|---|---|---|---|
| Convenio | 36 | 0 | 0.0% |
| Sin convenio | 36 | 1 | 2.8% |
Operar bajo un esquema de convenio elimina por completo el riesgo de operar con pérdidas diarias en esta simulación, mientras que el libre mercado (sin convenio) introduce un porcentaje considerable de días donde el negocio pierde dinero debido a márgenes negativos forzados por la volatilidad y la competencia.