1 Contexto del estudio

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.

2 Supuestos de simulación

Casas de cambio: 6

Divisas: USD y EUR

Precio base:

USD: $3,600 pesos

EUR: $3,950 pesos

3 Transacciones diarias: Entre 80 y 90 operaciones.

Margen con convenio: $80 – $100 pesos.

Margen sin convenio: Media de $70 pesos, con alta volatilidad (desviación estándar de 45).

4 Parámetros base

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)
)

5 Simulación completa (6 días, 2 escenarios)

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>

6 Márgenes por día y escenario

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.

7 Identificación de días fuera del rango saludable

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.

8 Gráfico de Ganancia vs Margen — DENTRO DEL CONVENIO

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.

9 Gráfico de Ganancia vs Margen — FUERA DEL CONVENIO

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.

10 Gráfico Comparativo Directo

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.

11 2. Probabilidad de Pérdida Diaria

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")
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%

12 Conclusión Final:

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.