UNPKG

finmath-engine

Version:

Motor de cálculos financeiros de alta precisão para o mercado brasileiro

93 lines 2.9 kB
"use strict"; /** * CET (Custo Efetivo Total) - Versão Básica * Sprint 4 - H15 (Parte 3) * * Escopo MVP: CET com tarifas t0 apenas (sem IOF/seguros) * Referência: Guia CET — Source of Truth v1.0 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateCETBasic = calculateCETBasic; exports.formatCET = formatCET; const decimal_js_1 = require("decimal.js"); const brent_1 = require("../irr/brent"); /** * Calcula CET básico usando solver de Brent * * Fórmula (Guia CET - SoT §4): * 1. CF[0] = +PV - tarifas_t0 * 2. CF[k] = -PMT[k] (k=1..n) * 3. IRR_m = solveIRR(CF, tolerance=1e-8) * 4. CET_aa = (1 + IRR_m)^base - 1 * * @param input - Parâmetros do cálculo * @returns Resultado com IRR mensal e CET anual * * @example * ```typescript * const result = calculateCETBasic({ * pv: new Decimal('10000'), * schedule: [ * new Decimal('946.56'), // PMT_1 * new Decimal('946.56'), // PMT_2 * // ... 12 parcelas * ], * feesT0: [new Decimal('85')], // Tarifa de cadastro * baseAnnual: 12 * }); * * console.log(result.cetAnnual.toNumber()); // 0.3367 (33.67% a.a.) * ``` */ function calculateCETBasic(input) { const { pv, schedule, feesT0 = [], baseAnnual = 12 } = input; // Validações if (schedule.length === 0) { throw new Error("Schedule cannot be empty"); } if (pv.lessThanOrEqualTo(0)) { throw new Error("PV must be positive"); } if (baseAnnual <= 0) { throw new Error("baseAnnual must be positive"); } // 1. Calcular entrada líquida do cliente (t=0) const totalFeesT0 = feesT0.reduce((sum, fee) => sum.plus(fee), new decimal_js_1.Decimal(0)); const netInflow = pv.minus(totalFeesT0); if (netInflow.lessThanOrEqualTo(0)) { throw new Error("Net inflow must be positive (PV > fees)"); } // 2. Montar fluxo de caixa const cashflows = [ netInflow, // CF[0]: +PV - tarifas_t0 (entrada do cliente) ...schedule.map((pmt) => pmt.neg()), // CF[k]: -PMT (saídas) ]; // 3. Resolver IRR com Brent const irrResult = (0, brent_1.solveIRR)(cashflows, { tolerance: new decimal_js_1.Decimal("1e-8"), }); if (!irrResult.converged || !irrResult.irr) { throw new Error(`IRR did not converge. Diagnostics: ${JSON.stringify(irrResult.diagnostics)}`); } const irrMonthly = irrResult.irr; // 4. Converter para CET anual const cetAnnual = (0, brent_1.convertToAnnual)(irrMonthly, baseAnnual); return { irrMonthly, cetAnnual, cashflows, breakdown: { pv, totalFeesT0, netInflow, }, irrResult, }; } /** * Helper: converte CET para porcentagem formatada */ function formatCET(cet, decimals = 2) { return `${cet.mul(100).toFixed(decimals)}%`; } //# sourceMappingURL=basic.js.map