Volver al inicio

Documentación del Motor PEPS

Referencia técnica completa del pipeline de valuación de activos financieros

1. Visión General

El sistema procesa archivos Excel de la sociedad de bolsa Balanz junto con archivos de tipo de cambio (TC) para clasificar movimientos bursátiles, asignar tipos de cambio correspondientes y ejecutar la valuación FIFO (First In, First Out) — conocida localmente como PEPS (Primero Entrado, Primero Salido) — para la determinación de resultados gravados.

Dos páginas principales

  • Clasificador — Pipeline parcial: importa el extracto, clasifica movimientos, asigna tipo de cambio y separa por moneda. No ejecuta la valuación FIFO.
  • Motor PEPS — Pipeline completo: incluye todo lo del Clasificador más la consolidación de lotes, validaciones y la valuación FIFO con cálculo de resultados.

Arquitectura

Los archivos se suben via FormData desde el cliente. El flujo es:

Cliente (FormData)
  → API Routes (app/api/*)        — Validación, manejo de errores HTTP
    → Server Actions (app/actions/*) — Lógica de negocio ("use server")
      → Engine Functions (lib/activos/) — Funciones puras de procesamiento

El frontend nunca llama directamente a las server actions; siempre pasa por las API routes.

2. Pipeline del Clasificador

Cuando el usuario sube los archivos y presiona "CLASIFICAR", se ejecutan los siguientes pasos en orden:

Paso 1 — parseBalanz()

Lee el archivo xlsx de Balanz. Busca la fila de encabezado escaneando hasta encontrar la celda que contiene IMPORTE. A partir de ahí extrae las siguientes columnas:

CampoOrigen
DescripcionColumna A
TickerColumna B
TipoInstrumentoColumna C
FechaColumna D (Concertación)
CantidadColumna E
PrecioColumna F
LiquidacionColumna G
MonedaColumna H
ImporteColumna I

Adicionalmente extrae el número de boleto del texto de la descripción y determina la fuente (ARGENTINA o EXTRANJERA) según el tipo de instrumento.

Paso 2 — clasificarBalanz()

Aplica 21+ reglas secuenciales basadas en palabras clave del campo "Detalle" (descripción). La última regla que matchea gana (no la primera). Las reglas son:

ReglaCondiciónClasificación
R0Contiene "ANULADO"Se omite (skip)
R1"COMPRA" + precio > 0COMPRA
R1"COMPRA" + precio < 0GASTOS
R1"Acreditación" + "ratio"CAMBIO RATIO
R1"Distrib" + "acciones"COMPRA
R2"VENTA" + precio > 0VENTA
R2"VENTA" + precio < 0GASTOS
R3"Recibo de Cobro"TRANSFERENCIA RECIBIDA
R4"Comprobante de Pago"TRANSFERENCIA REALIZADA
R5"Renta" + monto > 0RENTA
R6"Movimiento Manual"MOVIMIENTO MANUAL
R8"Cargo por Descubierto"GASTOS
R9"Dividendo en efectivo" + monto > 0 (Cedears)DIVIDENDOS GRAVADOS
R9"Dividendo en efectivo" + monto > 0 (argentinas)DIVIDENDOS GRAVADOS AL 7%
R9"Dividendo en efectivo" + monto < 0GASTOS
R10"APCOLFUT" + monto > 0VENCIMIENTO CAUCIÓN
R11"APCOLCON" + monto < 0COLOCACIÓN CAUCIÓN
R12"Garant"GARANTÍA
R13"Div" + "especie"DIVIDENDOS EN ESPECIE
R14"Interes" / "Amortizaci" + monto > 0INTERESES
R14"Interes" / "Amortizaci" / "Renta" + monto < 0GASTOS
R15"Transfer" + "Externa"TRANSF. EXTERNA
R16"Devoluci"DEVOLUCIÓN
R17"Liquidación" (no Futuro) según cantidadCOMPRA / VENTA
R7"Liquidación de Futuro" (overrides R17)LIQUIDACIÓN FUTUROS
R18"Opera" + "Diferida" según cantidadCOMPRA / VENTA
R18b"Suscrip"COMPRA
R18b"Rescate"VENTA
R19"Interes" / "Amortizaci" + Bonos + fuente ARGINTERESES BONOS ARG
R19"Interes" / "Amortizaci" + Bonos + fuente EXTINTERESES BONOS EXT
R20"Ret" (no Renta ni Rescate)RETENCIÓN GANANCIAS
R21"Convers" + combinaciones de monedaCONVERSIÓN A DOLAR MEP / CV
Sin coincidenciaA CLASIFICAR

Post-procesamiento: los movimientos cuyo ticker sea "Dólares ROFEX" se reclasifican como tipo Futuros. Los movimientos de Futuros con clasificación FICOMPRA o FIVENTA se reclasifican como GASTOS.

Paso 3 — parseTipoCambio()

Lee el archivo xlsx de tipo de cambio. Extrae las columnas:

  • Codigo Moneda — Identificador de la moneda
  • Fecha — Fecha de cotización
  • Compra — Tipo de cambio comprador
  • Venta — Tipo de cambio vendedor

Filtra filas de encabezado duplicadas o vacías.

Paso 4 — lookupTC()

Para cada movimiento, busca el tipo de cambio por fecha y moneda. Si no encuentra la fecha exacta, retrocede al día hábil anterior más cercano. Los movimientos en pesos siempre tienen TC = 1. Asigna tanto tcc (tipo cambio compra) como tcv (tipo cambio venta).

Paso 5 — Cálculo de montoPesos

montoPesos = monto × tcc

Convierte el importe original a pesos argentinos usando el tipo de cambio comprador.

Paso 6 — splitPorMoneda()

Separa los movimientos en 4 arrays según la moneda:

ArrayMonedaCódigo
PesosPesos argentinosARS
USDDólares estadounidensesUSD
CableDólares C.V. 7000D.CV 7000
FuturosDólares ROFEXROFEX

Para cada array calcula el saldo corrido (running balance) acumulando los importes en orden cronológico.

3. Pipeline del Motor PEPS

Incluye todos los pasos del Clasificador (1–6) y agrega los siguientes:

Tab RESUMEN — Configuración global

Antes de procesar, el usuario configura los parámetros globales del período: Banco, Período, Moneda, CUIT, Razón Social y Nro. Cuenta. Después de procesar, este tab muestra un resumen global de transacciones por clasificación.

Tab TRANSFERENCIA_ACTIVOS (G-1) — Transferencias entre cuentas

Tabla editable para registrar transferencias de títulos entre cuentas propias o de terceros. Campos: Nombre, Código, Tipo Activo, Fecha, Cantidad, Monto, TC, Es Repago.

El motor cruza las transferencias con DETALLE_MOV por código + fecha + cantidad para asignar montos y TC cuando la operación original solo muestra cantidades sin precio. Actualmente solo se muestra la tabla editable — el procesamiento automático de transferencias se implementará en una versión futura.

Paso 7 — buildTotal()

Consolida los movimientos relevantes para la valuación. Solo incluye las clasificaciones que afectan el stock de activos:

  • COMPRA
  • VENTA
  • AMORTIZACION
  • TRANSF. EXTERNA
  • CAMBIO RATIO
  • DIVIDENDOS EN ESPECIE
  • ACTIVOS_INICIO (cargados como SALDO INICIAL)

Ordena por:

  1. código ASC (alfabético)
  2. fecha ASC (cronológico)
  3. Compras antes que ventas en la misma fecha

Asigna un Nro.Ref secuencial por cada código de activo único.

Paso 8 — Validaciones

Ejecuta validaciones sobre los movimientos consolidados:

  • Código faltante — COMPRA o VENTA sin código de activo asignado
  • Cantidad cero — COMPRA o VENTA con cantidad = 0

Genera un array de errores que se muestra al usuario antes de continuar.

Paso 9 — valuarFIFO() — EL NÚCLEO

Esta es la función central del sistema. Para cada activo (agrupado por Nro.Ref) ejecuta el motor FIFO bidireccional.

Normalización de signos

TipoCantidadMontoLógica
COMPRA / SALDO INICIAL+abs-abs"Pagué plata"
VENTA-abs+abs"Recibí plata"
DIVIDENDOS EN ESPECIE+abs0"Recibí acciones gratis"
TRANSF. EXTERNAsigno originalsigno originalSegún dirección de la transferencia
CAMBIO RATIOResetea todo el stock a un solo lote con nuevo costo promedio

Motor FIFO bidireccional (buyLayers + sellLayers)

El motor mantiene dos pilas de lotes: buyLayers (compras pendientes de consumir) y sellLayers (ventas en corto / stock negativo).

ENTRADA (compra):

  1. Si hay sellLayers pendientes (ventas en corto previas), la compra las cierra primero (FIFO inverso).
  2. El remanente va a buyLayers como un lote nuevo.
  3. Fórmula de costo unitario: cu = |monto| / |cantidad|

SALIDA (venta):

  1. Consume buyLayers del más viejo al más nuevo (FIFO puro).
  2. Para cada lote consumido calcula:
    compraPesos = take × |cuCompra| × tcCompra
    ventaPesos  = take × cuVenta   × tcVenta
    resultado   = ventaPesos - compraPesos
  3. Si sobra cantidad sin stock disponible, se crea un sellLayer (posición corta / stock negativo).

Outputs de valuarFIFO

  • VALUACION (G-2) — Cada operación con TC compra, costo unitario compra, TC venta, costo unitario venta, compra en pesos, venta en pesos, resultado
  • STOCK FINAL (G-4) — Lotes remanentes en buyLayers (cantidad > 0) + sellLayers (mostrados como negativos)
  • RESULTADO por activo — Sumatoria de rdo de todas las operaciones del mismo Ref

Paso 10 — Enriquecimiento del RESULTADO (G-3)

Para cada código de activo, suma desde DETALLE_MOVIMIENTOS los conceptos complementarios:

ConceptoClasificaciones incluidas
GastosMovimientos clasificados como GASTOS con código coincidente
RentaMovimientos clasificados como RENTA
DividendosMovimientos con "DIVIDENDO" (no EN ESPECIE)
InteresesMovimientos con "INTERES"

La fórmula aplicada para cada concepto es: montoPesos = monto × tcc, acumulado por código.

4. Enciclopedia de Clasificaciones

Tabla completa de todas las clasificaciones posibles y su impacto en el sistema:

ClasificaciónDescripciónPEPSCash
COMPRAAdquisición de activos financieros
VENTAEnajenación de activos financieros
AMORTIZACIONRepago parcial de capital de bonos/ONs
REPAGO CAPITALDevolución de capital invertido (similar a amortización)
SALDO INICIALPosición de activos al inicio del período (cargada manualmente)No
DIVIDENDOSDividendos en efectivo (genérico)No
DIVIDENDOS GRAVADOSDividendos gravados de Cedears (fuente extranjera)No
DIVIDENDOS GRAVADOS AL 7%Dividendos de acciones argentinas (alícuota 7%)No
DIVIDENDOS EN ESPECIEDividendos pagados en acciones (no efectivo)No
CAMBIO RATIOCambio de ratio de conversión (ej. split de Cedear)No
INTERESESCobro de intereses (genérico)No
INTERESES BONOS ARGIntereses/amortización de bonos fuente argentinaNo
INTERESES BONOS EXTIntereses/amortización de bonos fuente extranjeraNo
GASTOSComisiones, derechos de mercado, impuestos operativosNo
RETENCION TAXRetención impositiva genéricaNo
RETENCIÓN GANANCIASRetención del impuesto a las gananciasNo
TRANSF. EXTERNATransferencia de títulos desde/hacia otro brokerNo
TRANSFERENCIA RECIBIDAIngreso de fondos (recibo de cobro)No
TRANSFERENCIA REALIZADAEgreso de fondos (comprobante de pago)No
CONSUMOConsumos con tarjeta asociada a la cuentaNo
COLOCACIÓN CAUCIÓNColocación de caución bursátil (préstamo)No
VENCIMIENTO CAUCIÓNVencimiento/cobro de caución bursátilNo
RENTACobro de renta de títulos (cupón)No
LIQUIDACIÓN FUTUROSLiquidación de contratos de futurosNo
CONVERSIÓN A DOLAR MEPConversión de moneda vía operatoria MEPNo
CONVERSIÓN A DOLAR CVConversión de moneda vía cable (contado con liquidación)No
GARANTÍAConstitución/liberación de garantíasNo
DEVOLUCIÓNDevolución de montos cobrados/debitados por errorNo
MOVIMIENTO MANUALAjuste manual ingresado por el brokerNo
ANULACIÓNMovimiento anulado (se descarta del procesamiento)NoNo
A CLASIFICARNinguna regla coincidió — requiere clasificación manualNo

5. Formato de Archivos de Entrada

Archivo Balanz (.xlsx)

Extracto de cuenta exportado desde la plataforma de Balanz. El sistema busca automáticamente la fila de encabezado.

ColumnaCampoTipo
ADescripcionstring
BTickerstring
CTipoInstrumentostring
DConcertación (Fecha)date
ECantidadnumber
FPrecionumber
GLiquidacióndate
HMonedastring
IImportenumber

Archivo Tipo de Cambio (.xlsx)

Archivo con cotizaciones históricas de monedas extranjeras.

ColumnaCampoTipo
BCodigo Monedastring
CFechadate
DCompranumber
EVentanumber

Activos Inicio (carga manual)

Posición de activos al inicio del período fiscal, ingresada manualmente por el usuario. Se incorporan al pipeline como SALDO INICIAL.

CampoDescripciónTipo
TipoInstrumentoTipo del instrumento (Acción, Cedear, Bono, etc.)string
CódigoTicker/código del activostring
FechaFecha de valuación del saldo inicialdate
CantidadCantidad de unidades en carteranumber
MontoCosto total de la posición en moneda originalnumber
TCTipo de cambio al momento de la valuaciónnumber

6. Hojas de Output

El sistema genera múltiples hojas/tabs de resultados. Cada una representa una vista distinta de los datos procesados:

DETALLE_MOVIMIENTOS (G-1)

Todos los movimientos clasificados del extracto Balanz con tipo de cambio asignado, monto en pesos y clasificación. Es la base de datos completa del período.

DETALLE PESOS / USD / CABLE / FUTUROS

Movimientos separados por moneda con saldo corrido. Cada hoja muestra únicamente los movimientos de esa moneda con columnas de saldo y saldoPesos acumulados.

ACTIVOS_TOTAL

Movimientos consolidados que afectan la valuación PEPS (COMPRA, VENTA, AMORTIZACION, TRANSF. EXTERNA, CAMBIO RATIO, DIVIDENDOS EN ESPECIE, SALDO INICIAL). Ordenados por código y fecha con Nro.Ref asignado.

VALUACION_ACTIVOS (G-2)

Resultado del matching FIFO. 21 columnas: Ref, Tipo Op, NroOp, Nombre, Código, Tipo Activo, Fecha, Cant, Monto USD, TC Compra, CU Compra, TCV Venta, CU Venta, TCC Venta, Compra $, Venta $, Rdo (V/C), Dif Cambio, Rdo USD, Val Op USD, Control.

VALUACION_REPAGO_CAPITAL (G-2-1)

FIFO separado para operaciones de Repago de Capital (amortización programada de bonos). Misma estructura que G-2. Placeholder — se implementará cuando se agregue la lógica de separación por tipo.

VALUACION_DERIVADOS (G-2-2)

Valuación FIFO de derivados (opciones put/call). Soporta stock negativo (short selling). Solo Morgan Stanley por ahora. Placeholder.

VALUACION_EJERCIDAS (G-2-3)

Derivados que fueron ejercidos (opciones ejecutadas). Solapas segregadas. Placeholder.

RESULTADO_ACTIVOS (G-3)

Una fila por activo con 18 columnas: Ref, Nombre, Código, Cant, Costo USD, Valor IAG ARS, Mkt Value 31/12, Val. IBP $, Tipo Activo, Fuente, Intereses, Dividendos, Rdo Vta ARS, Dif. Cambio, Int+Div, RENDIMIENTO, RESULTADO C/V, BS.PERS. Columnas de tratamiento impositivo (GRAVADO 7%, CEDULAR 15%, ESCALA, EXENTO, CDI, BIENES PERSONALES) se agregarán en versión futura.

RESULTADO_DERIVADOS (G-3)

Resultado por derivado con tratamiento impositivo. Misma estructura que RESULTADO_ACTIVOS pero para categoría DERIV. Placeholder.

STOCK_FINAL_ACTIVOS (G-4)

Lotes remanentes al cierre del período. 12 columnas incluyendo flag Es Repago Capital. Muestra buyLayers con cantidad positiva y sellLayers con cantidad negativa.

STOCK_FINAL_DERIVADOS (G-4)

Stock de derivados al cierre. Misma estructura que STOCK_FINAL_ACTIVOS pero para categoría DERIV. Placeholder.

IPC

Tabla IPC Nacional mensual para ajuste de costo de ADRs argentinas. Se usará para calcular coeficiente = IPC_venta / IPC_compra y costo actualizado. Placeholder.

7. Fórmulas Clave

Todas las fórmulas utilizadas en el pipeline de valuación:

Conversión a pesos:

montoPesos = monto × tcc

Costo unitario de un lote:

costoUnitario = |monto| / |cantidad|

Costo de compra en pesos (al consumir un lote FIFO):

compraPesos = cantidadTomada × |costoUnitCompra| × tcCompra

Ingreso de venta en pesos:

ventaPesos = cantidadTomada × costoUnitVenta × tcVenta

Resultado de la operación:

resultado = ventaPesos - compraPesos

Saldo corrido en moneda original:

saldo = saldoAnterior + monto

Saldo corrido en pesos:

saldoPesos = saldoPesosAnterior + montoPesos

8. Errores Comunes

Errores frecuentes durante el procesamiento y cómo resolverlos:

ErrorCausaResolución
Falta Código ActivoUn movimiento de COMPRA o VENTA no tiene ticker/código de activo asignado en el extracto de Balanz.Verificar el extracto original. Si el movimiento es válido, asignar manualmente el código del activo antes de reprocesar.
Stock NegativoSe vendieron más unidades de las que había en stock. El motor crea un sellLayer (posición corta) para la cantidad excedente.Verificar si falta un SALDO INICIAL o una COMPRA previa. Si es correcto (venta en corto real), el sellLayer se resolverá cuando ingrese una compra posterior.
A CLASIFICARNinguna regla de clasificación coincidió con la descripción del movimiento.Revisar la descripción del movimiento y clasificarlo manualmente. Si es un patrón nuevo recurrente, agregar una regla al clasificador.
TC = 0No se encontró tipo de cambio para la fecha y moneda del movimiento en el archivo TC, ni para fechas anteriores cercanas.Verificar que el archivo de tipo de cambio cubra el rango de fechas del extracto. Agregar las cotizaciones faltantes y reprocesar.
Cantidad = 0Un movimiento de COMPRA o VENTA tiene cantidad cero, lo cual invalida el cálculo del costo unitario (división por cero).Revisar el extracto original. Si el movimiento es un gasto o comisión, reclasificarlo como GASTOS. Si es un error de datos, corregir la cantidad.

9. Ejemplo PEPS Paso a Paso

Ejemplo concreto de valuación FIFO para el activo AAPL (Cedear de Apple) con tres operaciones:

Operaciones de entrada

Compra 1:  100 AAPL a USD 150  (01/03, TC = 900)
Compra 2:   50 AAPL a USD 160  (15/05, TC = 950)
Venta:     120 AAPL a USD 180  (01/09, TC = 1.000)

Estado de buyLayers antes de la venta

LoteCantidadCU (USD)TC
Compra 1100150,00900
Compra 250160,00950

Ejecución FIFO de la Venta (120 unidades)

Paso 1 — Consumir Compra 1 (100 unidades)

take        = 100 (se agota el lote completo)
compraPesos = 100 × 150 × 900   = 13.500.000
ventaPesos  = 100 × 180 × 1.000 = 18.000.000
resultado   = 18.000.000 - 13.500.000 = +4.500.000

Quedan 120 - 100 = 20 unidades por consumir. Compra 1 se agota.

Paso 2 — Consumir Compra 2 (20 de 50 unidades)

take        = 20 (consumo parcial del lote)
compraPesos = 20 × 160 × 950   = 3.040.000
ventaPesos  = 20 × 180 × 1.000 = 3.600.000
resultado   = 3.600.000 - 3.040.000 = +560.000

Se consumieron las 120 unidades. Compra 2 queda con 30 unidades remanentes.

Stock Final

LoteCantidadCU (USD)TC
Compra 2 (remanente)30160,00950

Resultado Total

Resultado Compra 1 → Venta:  +4.500.000
Resultado Compra 2 → Venta:    +560.000
                              ──────────
Resultado Total AAPL:        +5.060.000

El resultado total de +5.060.000 ARS representa la ganancia gravada por la enajenación de 120 Cedears de AAPL, calculada respetando el orden FIFO de adquisición y convirtiendo tanto el costo de compra como el ingreso de venta al tipo de cambio vigente en cada momento.

10. Funcionalidad Futura

Las siguientes funcionalidades están planificadas pero aún no implementadas. Los tabs correspondientes aparecen como placeholders en el Motor PEPS:

  • Ajuste IPC para ADRs argentinas — Coeficiente de inflación IPC_venta / IPC_compra para actualizar el costo histórico de activos de fuente ARGENTINA.
  • Derivados y Short-Selling — Soporte para opciones put/call y futuros. Usa sellLayers para stock negativo. Hojas segregadas: VALUACION_DERIVADOS (G-2-2), VALUACION_EJERCIDAS (G-2-3), RESULTADO_DERIVADOS (G-3), STOCK_FINAL_DERIVADOS (G-4).
  • Repago de Capital separado — FIFO aparte para amortizaciones programadas de bonos. Hoja VALUACION_REPAGO_CAPITAL (G-2-1).
  • Tratamiento impositivo — Columnas de IIGG: Gravado 7%, Cedular 15%, Gravado a Escala, Exento, Exento CDI. Clasificación automática por tipo de activo y fuente.
  • Bienes Personales — Valuación al cierre para la declaración de Bienes Personales. Columna Val. IBP $ en RESULTADO (G-3).
  • Market Value al 31/12 — Cotización de cierre de cada activo para valorizar la cartera a precios de mercado.
  • Composición de efectivo al cierre — Análisis del saldo de efectivo por capas con TC asignado (equivale a VBA: EjecutarEfectivoParaTresSolapas).
  • Soporte brokers exterior — Pershing, Morgan Stanley, BP Securities, Stone X. Parsers dedicados para cada formato de extracto.