27. Tablas de evolución y comparación de escenarios

Una tabla convierte un resultado final en una trayectoria verificable. Al alinear dos trayectorias bajo el mismo horizonte temporal podemos observar cuándo y cuánto se separan los escenarios.

27.1 Qué aporta una tabla de evolución

Conocer únicamente el monto final responde dónde terminó una operación, pero no muestra cómo llegó allí. Una tabla registra el estado inicial y cada cierre periódico.

una fila = un momento claramente identificado

La secuencia permite explicar, comprobar y comparar el cálculo.

La tabla no crea información nueva: representa los valores producidos por un modelo y sus supuestos.

27.2 Anatomía de una fila

Período k

Posición temporal.

Base

Importe antes del interés.

Interés

Cambio del período.

Monto

Estado después del cambio.

En k = 0 todavía no existe interés del período: el monto coincide con el capital inicial y la base puede indicarse como nula o igual al capital según el diseño elegido.

27.3 Tabla de interés simple

En el modelo simple, cada fila utiliza el capital inicial como base del interés:

function tablaSimple(capital, tasa, periodos) {
  return Array.from({ length: periodos + 1 }, (_, periodo) => ({
    periodo,
    base: periodo === 0 ? null : capital,
    interesPeriodo: periodo === 0 ? 0 : capital * tasa,
    monto: capital * (1 + tasa * periodo)
  }));
}

const tabla = tablaSimple(100000, 0.02, 3);
tabla.forEach(fila => console.log(JSON.stringify(fila)));

El interés periódico es constante y la diferencia entre montos consecutivos siempre vale capital × tasa.

27.4 Tabla de interés compuesto

En el modelo compuesto, el monto anterior se convierte en la base siguiente:

function tablaCompuesta(capital, tasa, periodos) {
  const filas = [{ periodo: 0, base: null, interesPeriodo: 0, monto: capital }];
  let monto = capital;

  for (let periodo = 1; periodo <= periodos; periodo++) {
    const base = monto;
    const interesPeriodo = base * tasa;
    monto = base + interesPeriodo;
    filas.push({ periodo, base, interesPeriodo, monto });
  }

  return filas;
}

const tabla = tablaCompuesta(100000, 0.02, 3);
tabla.forEach(fila => console.log(JSON.stringify(fila)));

Conservar la base y el interés de cada paso hace visible la capitalización.

27.5 Invariantes entre filas

Una tabla bien construida cumple relaciones que pueden verificarse automáticamente:

  • la primera fila tiene periodo = 0 y monto = capital;
  • los períodos avanzan de uno en uno;
  • desde k = 1, monto = base + interesPeriodo;
  • en interés compuesto, cada base coincide con el monto anterior;
  • la última fila corresponde al plazo solicitado;
  • con tasa no negativa, los montos no disminuyen.

Estas condiciones detectan errores de límites, filas omitidas y actualizaciones realizadas en un orden incorrecto.

27.6 Representar un escenario

Para comparar necesitamos agrupar cada conjunto de supuestos bajo una identidad:

const escenario = {
  id: "alternativa-a",
  nombre: "Opción compuesta",
  modelo: "compuesto",
  capital: 250000,
  tasa: 0.03,
  periodos: 12,
  unidad: "meses"
};

console.log("Escenario:", escenario.nombre);
console.log("Tasa decimal:", escenario.tasa);
console.log("Horizonte:", escenario.periodos, escenario.unidad);

El nombre sirve para presentar; el identificador estable sirve para relacionar datos dentro del programa.

27.7 Condiciones comparables

Las filas deben referirse a los mismos momentos. Para aislar el efecto del modelo o de la tasa utilizamos el mismo capital inicial, la misma unidad temporal y el mismo horizonte.

Mismo origen

Ambas tablas comienzan en k = 0.

Misma unidad

Un período significa lo mismo en ambas.

Mismo horizonte

Las filas finales representan la misma duración.

Alcance: colocar tasas mensuales y anuales en columnas contiguas no las vuelve comparables. Primero debe existir una regla válida de equivalencia temporal.

27.8 Alinear dos trayectorias

Cuando las tablas tienen una fila por cada k, podemos combinarlas por índice y calcular la brecha:

function montos(capital, tasa, periodos, modelo) {
  return Array.from({ length: periodos + 1 }, (_, k) =>
    modelo === "simple"
      ? capital * (1 + tasa * k)
      : capital * (1 + tasa) ** k
  );
}

const a = montos(100000, 0.02, 5, "simple");
const b = montos(100000, 0.02, 5, "compuesto");
const comparacion = a.map((montoA, k) => ({
  periodo: k,
  montoA,
  montoB: b[k],
  diferencia: b[k] - montoA
}));

comparacion.forEach(fila => console.log(JSON.stringify(fila)));

Alinear por el número de fila solo es seguro porque ambas series fueron construidas con el mismo origen y sin períodos faltantes.

27.9 Diferencias absolutas y relativas

La diferencia monetaria conserva la unidad del capital. La diferencia relativa toma un escenario como referencia:

Dk = MB,k − MA,k

Diferencia relativa = Dk / MA,k × 100

Si cambiamos el escenario de referencia, cambia el porcentaje. Por eso una tabla debe indicar claramente qué columna ocupa ese papel.

27.10 Presentar sin perder precisión

La tabla conserva números completos en memoria y aplica formato solo al crear las celdas visibles:

const moneda = new Intl.NumberFormat("es-AR", {
  style: "currency",
  currency: "ARS",
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

const montoInterno = 100000 * 1.03 ** 7;

console.log("Valor interno:", montoInterno);
console.log("Valor presentado:", moneda.format(montoInterno));
console.log("Sigue siendo número:", typeof montoInterno);

No utilizamos el texto formateado como base de la fila siguiente.

27.11 Cantidad de filas y rendimiento

Una tabla de n períodos contiene n + 1 filas cuando incluye el origen. Para horizontes grandes, crear miles de nodos HTML puede volver lenta la página aunque el cálculo sea sencillo.

La validación debe imponer un límite apropiado para la interfaz. Un proceso de exportación puede admitir más filas que una vista interactiva, porque no necesita dibujarlas todas simultáneamente.

27.12 Exportar una tabla como CSV

Una tabla también puede convertirse en texto separado por comas para analizarla en otra herramienta:

const filas = [
  { periodo: 0, monto: 100000 },
  { periodo: 1, monto: 103000 },
  { periodo: 2, monto: 106090 }
];

const encabezado = "periodo,monto";
const cuerpo = filas.map(fila => `${fila.periodo},${fila.monto}`).join("\n");
const csv = `${encabezado}\n${cuerpo}`;

console.log(csv);

El archivo exportado debería usar números sin símbolos de moneda. La configuración regional del programa que lo reciba determina el separador decimal y de columnas adecuado.

27.13 Comparador interactivo de escenarios

Definí dos modelos bajo el mismo capital y horizonte. La tabla muestra monto, interés del período y diferencia en cada cierre.

Dos trayectorias alineadas

Una fila compartida por período para comparar sin perder el recorrido.

Escenario A

Escenario B

Monto A$124.000,00
Monto B$126.824,18
Diferencia B − A$2.824,18
Diferencia relativa2,28 %

Montos finales en la misma escala

Escenario A$124.000,00
Escenario B$126.824,18
Comparación durante 12 meses.
PeríodoBase AInterés AMonto ABase BInterés BMonto BB − A
Al finalizar, el escenario B supera al A por $2.824,18.

Las dos tablas contienen 13 filas, incluido el estado inicial.

27.14 Ejercicio propuesto

Compará un capital de $300.000 durante 18 meses bajo dos escenarios: A, interés simple al 2,5 % mensual; B, interés compuesto al 2 % mensual.

  1. Generá ambas tablas desde k = 0.
  2. Comprobá la continuidad de las bases.
  3. Calculá los montos finales.
  4. Obtené la diferencia B − A y su porcentaje respecto de A.
  5. Indicá qué escenario termina con mayor monto.
Ver solución y código

El escenario A alcanza $435.000. El escenario B alcanza aproximadamente $428.473,87. En este horizonte, B − A es aproximadamente −$6.526,13, por lo que A termina con el mayor monto.

function monto(capital, tasa, periodos, modelo) {
  return modelo === "simple"
    ? capital * (1 + tasa * periodos)
    : capital * (1 + tasa) ** periodos;
}

const capital = 300000;
const periodos = 18;
const montoA = monto(capital, 0.025, periodos, "simple");
const montoB = monto(capital, 0.02, periodos, "compuesto");
const diferencia = montoB - montoA;
const relativa = diferencia / montoA * 100;

console.log("Monto A:", montoA.toFixed(2));
console.log("Monto B:", montoB.toFixed(2));
console.log("B - A:", diferencia.toFixed(2));
console.log("Diferencia relativa:", relativa.toFixed(2) + "%");
console.log("Mayor monto:", montoA > montoB ? "Escenario A" : "Escenario B");

27.15 Ideas para recordar

  • Una tabla con origen contiene n + 1 filas.
  • Cada fila distingue período, base, interés y monto.
  • Los invariantes comprueban continuidad y orden.
  • Un escenario reúne modelo, capital, tasa, plazo y unidad.
  • Comparar exige alinear origen, unidad y horizonte.
  • La diferencia relativa siempre necesita un escenario de referencia.
  • Los valores internos conservan precisión y las celdas aplican formato al mostrar.
  • La interfaz limita filas aunque el proceso de exportación pueda admitir más.

En el próximo tema integraremos el recorrido completo en una calculadora de crecimiento de un capital.