UNPKG

financial-calc-br

Version:

Calculadora financeira brasileira com suporte a financiamentos, investimentos e cartão de crédito

280 lines (279 loc) 13 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("../utils/utils"); const rates_1 = __importDefault(require("../services/rates")); class InvestmentCalc { constructor(rates) { this.rates = rates; } static async create() { const rates = await rates_1.default.create(); return new InvestmentCalc(rates); } /** * Calcula rendimento da poupança * @param {number} valor - Valor inicial do investimento * @param {number} meses - Período de investimento em meses * @returns {ResultadoPoupanca} Objeto com detalhes do rendimento da poupança */ investmentPoupanca(valor, meses) { const validation = (0, utils_1.validateFinancialParams)(valor, this.rates.getPoupanca(), meses); if (!validation.isValid) { throw new Error(`Parâmetros inválidos: ${validation.errors.join(", ")}`); } const taxaPoupanca = this.rates.getPoupanca(); const taxaMensal = taxaPoupanca / 100; const montante = valor * Math.pow(1 + taxaMensal, meses); const rendimento = montante - valor; return { investimento: "Poupança", valorInicial: valor, periodo: meses, taxaMensal: taxaPoupanca / 100, montanteFinal: montante, rendimento: rendimento, rentabilidade: rendimento / valor, isento: true, observacao: "Isento de Imposto de Renda e IOF", formatted: { valorInicial: (0, utils_1.formatMoney)(valor), periodo: (0, utils_1.formatPeriod)(meses), taxaMensal: `${taxaPoupanca.toFixed(2)}%`, montanteFinal: (0, utils_1.formatMoney)(montante), rendimento: (0, utils_1.formatMoney)(rendimento), rentabilidade: `${((rendimento / valor) * 100).toFixed(2)}%`, }, }; } /** * Calcula rendimento do Tesouro Selic * @param {number} valor - Valor inicial do investimento * @param {number} meses - Período de investimento em meses * @returns {ResultadoTesouroSelic} Objeto com detalhes do rendimento do Tesouro Selic */ investmentTesouroSelic(valor, meses) { const validation = (0, utils_1.validateFinancialParams)(valor, this.rates.getSelic(), meses); if (!validation.isValid) { throw new Error(`Parâmetros inválidos: ${validation.errors.join(", ")}`); } const taxaMensal = (0, utils_1.convertRate)(this.rates.getSelic(), "anual", "mensal") / 100; const montanteBruto = valor * Math.pow(1 + taxaMensal, meses); const rendimentoBruto = montanteBruto - valor; const dias = Math.round(meses * 30.44); const aliquotaIR = (0, utils_1.calcIRRate)(dias); const ir = rendimentoBruto * (aliquotaIR / 100); const rendimentoLiquido = rendimentoBruto - ir; return { investimento: "Tesouro Selic", valorInicial: valor, periodo: meses, taxaAnual: this.rates.getSelic() / 100, montanteBruto: montanteBruto, impostoRenda: ir, aliquotaIR: aliquotaIR / 100, montanteLiquido: valor + rendimentoLiquido, rendimentoLiquido: rendimentoLiquido, rentabilidade: rendimentoLiquido / valor, observacao: `Tributação regressiva: ${aliquotaIR}% de IR após ${Math.floor(dias)} dias`, formatted: { valorInicial: (0, utils_1.formatMoney)(valor), periodo: (0, utils_1.formatPeriod)(meses), taxaAnual: `${this.rates.getSelic()}%`, montanteBruto: (0, utils_1.formatMoney)(montanteBruto), impostoRenda: (0, utils_1.formatMoney)(ir), aliquotaIR: `${aliquotaIR}%`, montanteLiquido: (0, utils_1.formatMoney)(valor + rendimentoLiquido), rendimentoLiquido: (0, utils_1.formatMoney)(rendimentoLiquido), rentabilidade: `${((rendimentoLiquido / valor) * 100).toFixed(2)}%`, }, }; } /** * Calcula rendimento do CDB (Certificado de Depósito Bancário) * @param {number} valor - Valor inicial do investimento * @param {number} meses - Período de investimento em meses * @param {number} percentualCDI - Percentual do CDI pago pelo CDB (padrão: 100%) * @returns {ResultadoCDB} Objeto com detalhes do rendimento do CDB */ investmentCDB(valor, meses, percentualCDI = 100) { const taxaCDI = this.rates.getCDI() * (percentualCDI / 100); const validation = (0, utils_1.validateFinancialParams)(valor, taxaCDI, meses); if (!validation.isValid) { throw new Error(`Parâmetros inválidos: ${validation.errors.join(", ")}`); } const taxaMensal = (0, utils_1.convertRate)(taxaCDI, "anual", "mensal") / 100; const montanteBruto = valor * Math.pow(1 + taxaMensal, meses); const rendimentoBruto = montanteBruto - valor; const dias = Math.round(meses * 30.44); const aliquotaIR = (0, utils_1.calcIRRate)(dias); const ir = rendimentoBruto * (aliquotaIR / 100); const rendimentoLiquido = rendimentoBruto - ir; return { investimento: `CDB ${percentualCDI}% CDI`, valorInicial: valor, periodo: meses, taxaAnual: taxaCDI / 100, percentualCDI: percentualCDI / 100, montanteBruto: montanteBruto, impostoRenda: ir, aliquotaIR: aliquotaIR / 100, montanteLiquido: valor + rendimentoLiquido, rendimentoLiquido: rendimentoLiquido, rentabilidade: rendimentoLiquido / valor, formatted: { valorInicial: (0, utils_1.formatMoney)(valor), periodo: (0, utils_1.formatPeriod)(meses), taxaAnual: `${taxaCDI.toFixed(2)}%`, percentualCDI: `${percentualCDI}%`, montanteBruto: (0, utils_1.formatMoney)(montanteBruto), impostoRenda: (0, utils_1.formatMoney)(ir), aliquotaIR: `${aliquotaIR}%`, montanteLiquido: (0, utils_1.formatMoney)(valor + rendimentoLiquido), rendimentoLiquido: (0, utils_1.formatMoney)(rendimentoLiquido), rentabilidade: `${((rendimentoLiquido / valor) * 100).toFixed(2)}%`, }, }; } /** * Compara diferentes opções de investimento * @param {number} valor - Valor inicial do investimento * @param {number} meses - Período de investimento em meses * @param {number[]} opcoes - Array com percentuais de CDI para comparação (padrão: [100, 110, 120]) * @returns {ResultadoComparacaoInvestment} Objeto com comparação detalhada entre investimentos */ compareInvestments(valor, meses, opcoes = [100, 110, 120]) { const poupanca = this.investmentPoupanca(valor, meses); const selic = this.investmentTesouroSelic(valor, meses); const cdbs = opcoes.map((perc) => this.investmentCDB(valor, meses, perc)); const rendPoupanca = poupanca.rendimento; const rendSelic = selic.rendimentoLiquido; const rendCDBs = cdbs.map((cdb) => ({ nome: cdb.investimento, rendimento: cdb.rendimentoLiquido, rentabilidade: cdb.rentabilidade, })); const todasOpcoes = [ { nome: "Poupança", rendimento: rendPoupanca, rentabilidade: poupanca.rentabilidade, }, { nome: "Tesouro Selic", rendimento: rendSelic, rentabilidade: selic.rentabilidade, }, ...rendCDBs, ]; const melhorOpcao = todasOpcoes.reduce((melhor, atual) => atual.rendimento > melhor.rendimento ? atual : melhor); return { cenario: { valor: valor, periodo: (0, utils_1.formatPeriod)(meses), dataAnalise: new Date().toLocaleDateString("pt-BR"), }, opcoes: { poupanca: { rendimento: poupanca.rendimento, rentabilidade: poupanca.rentabilidade, }, tesouroSelic: { rendimento: selic.rendimentoLiquido, rentabilidade: selic.rentabilidade, }, cdbs: cdbs.map((cdb) => ({ nome: cdb.investimento, rendimento: cdb.rendimentoLiquido, rentabilidade: cdb.rentabilidade, })), }, ranking: todasOpcoes.sort((a, b) => b.rendimento - a.rendimento), melhorOpcao: { nome: melhorOpcao.nome, rendimento: melhorOpcao.rendimento, rentabilidade: melhorOpcao.rentabilidade, vantagem: melhorOpcao.rendimento - Math.min(...todasOpcoes.map((option) => option.rendimento)), }, taxasUtilizadas: { selic: this.rates.getAllRates().formatted.selic, cdi: this.rates.getAllRates().formatted.cdi, poupanca: this.rates.getAllRates().formatted.poupanca, atualizadoEm: new Date().toLocaleDateString("pt-BR"), }, }; } /** * Simula investimento com aportes mensais * @param {number} valorInicial - Valor inicial do investimento * @param {number} aporteMensal - Valor do aporte mensal * @param {number} meses - Período total de investimento em meses * @param {number} taxaAnual - Taxa de juros anual (em percentual) * @param {boolean} temIR - Indica se há incidência de Imposto de Renda (padrão: true) * @returns {SimulacaoAportes} Objeto com simulação completa dos aportes mensais */ simulateMonthlyContributions(valorInicial, aporteMensal, meses, taxaAnual, temIR = true) { const validation = (0, utils_1.validateFinancialParams)(valorInicial, taxaAnual, meses); if (!validation.isValid) { throw new Error(`Parâmetros inválidos: ${validation.errors.join(", ")}`); } const taxaMensal = (0, utils_1.convertRate)(taxaAnual, "anual", "mensal") / 100; let montante = valorInicial; let totalAportado = valorInicial; const evolucao = []; for (let mes = 1; mes <= meses; mes++) { montante = montante * (1 + taxaMensal); montante += aporteMensal; totalAportado += aporteMensal; if (mes <= 12 || mes % 12 === 0 || mes === meses) { evolucao.push({ mes: mes, montante: montante, totalAportado: totalAportado, rendimento: montante - totalAportado, }); } } const rendimentoBruto = montante - totalAportado; let rendimentoLiquido = rendimentoBruto; let ir = 0; if (temIR) { const aliquotaIR = (0, utils_1.calcIRRate)(meses * 30); ir = rendimentoBruto * (aliquotaIR / 100); rendimentoLiquido -= ir; } return { simulacao: "Aportes Mensais", valorInicial: valorInicial, aporteMensal: aporteMensal, periodo: meses, taxaAnual: taxaAnual / 100, totalAportado: totalAportado, montanteBruto: montante, rendimentoBruto: rendimentoBruto, impostoRenda: temIR ? ir : 0, montanteLiquido: montante - (temIR ? ir : 0), rendimentoLiquido: rendimentoLiquido, rentabilidadeTotal: rendimentoLiquido / totalAportado, evolucao: evolucao, formatted: { valorInicial: (0, utils_1.formatMoney)(valorInicial), aporteMensal: (0, utils_1.formatMoney)(aporteMensal), periodo: (0, utils_1.formatPeriod)(meses), taxaAnual: `${taxaAnual}%`, totalAportado: (0, utils_1.formatMoney)(totalAportado), montanteBruto: (0, utils_1.formatMoney)(montante), rendimentoBruto: (0, utils_1.formatMoney)(rendimentoBruto), impostoRenda: temIR ? (0, utils_1.formatMoney)(ir) : (0, utils_1.formatMoney)(0), montanteLiquido: (0, utils_1.formatMoney)(montante - (temIR ? ir : 0)), rendimentoLiquido: (0, utils_1.formatMoney)(rendimentoLiquido), rentabilidadeTotal: `${((rendimentoLiquido / totalAportado) * 100).toFixed(2)}%`, }, }; } } exports.default = InvestmentCalc;