/** * Emulates Excel/Calc's PMT(interest_rate, number_payments, PV, FV, 0) function, which calculates the mortgage or * annuity payment / yield per period. * @param r - periodic interest rate represented as a decimal. * @param nper - number of total payments / periods. * @param pv - present value -- borrowed or invested principal. * @param fv - future value of loan or annuity. * @return Representing periodic payment amount. */ public static BigDecimal pmt(final BigDecimal r, final int nper, final BigDecimal pv, final BigDecimal fv) { // pmt = r / ((1 + r)^N - 1) * -(pv * (1 + r)^N + fv) final BigDecimal tmp = plus(1, r).pow(nper); return times( divide(r, minus(tmp, 1)), plus(times(pv, tmp), fv).negate() ); }
public static BigDecimal toScale(final BigDecimal number) { return toScale(number, DEFAULT_SCALE); }
public static BigDecimal divide(final Number numerator, final Number denominator) { return divide(toBigDecimal(numerator), denominator); }
public static BigDecimal times(final BigDecimal multiplicand, final Number multiplier) { return times(multiplicand, toBigDecimal(multiplier)); }
public static BigDecimal minus(final Number minuend, final Number subtrahend) { return minus(toBigDecimal(minuend), subtrahend); }
@Override public BigDecimal getShareAtRisk() { if (isZero(czkInvested)) { // protected against division by zero return BigDecimal.ZERO; } return divide(czkAtRisk, czkInvested); }
static BigDecimal feePaid(final BigDecimal originalValue, final BigDecimal interestRate, final int originalTerm, final BigDecimal annualFee, final int totalMonths) { final BigDecimal monthlyRate = divide(interestRate, 12); final BigDecimal monthlyFee = divide(annualFee, 12); final BigDecimal pmt = FinancialUtil.pmt(monthlyRate, originalTerm, originalValue); final BigDecimal result = IntStream.range(0, totalMonths) .mapToObj(term -> FinancialUtil.fv(monthlyRate, term + 1, pmt, originalValue).negate()) .map(fv -> times(fv, monthlyFee)) .reduce(BigDecimal.ZERO, BigDecimalCalculator::plus); LOGGER.debug("Fee paid from {} CZK at {} rate for {} months with {} annual fee over {} months is {} CZK.", originalValue, interestRate, originalTerm, annualFee, totalMonths, result.doubleValue()); return toScale(result); }
public static BigDecimal plus(final Number addend1, final Number addend2) { return plus(toBigDecimal(addend1), addend2); }
public static BigDecimal actualInterestAfterFees(final Investment investment, final long totalInvested, final boolean includeSmpSaleFee) { final int termsInZonky = countTermsInZonky(investment); final BigDecimal fee = feePaid(investment, totalInvested, termsInZonky); final BigDecimal actualFee = includeSmpSaleFee ? plus(fee, investment.getSmpFee().orElse(BigDecimal.ZERO)) : fee; final BigDecimal interest = plus(investment.getPaidInterest(), investment.getPaidPenalty()); return minus(interest, actualFee); }
public static BigDecimal expectedInterestRateAfterFees(final Investment investment, final long totalInvested) { final BigDecimal interestRate = investment.getInterestRate(); final BigDecimal feeRate = estimateFeeRate(investment, totalInvested); return minus(interestRate, feeRate); } }
private static BigDecimal sum(final OverallPortfolio portfolio) { return BigDecimalCalculator.plus(portfolio.getDue(), portfolio.getUnpaid()); }
/** * Emulates Excel/Calc's IPMT(interest_rate, period, number_payments, PV, FV, 0) function, which calculates the * portion of the payment at a given period that is the interest on previous balance. * @param r - periodic interest rate represented as a decimal. * @param per - period (payment number) to check value at. * @param nper - number of total payments / periods. * @param pv - present value -- borrowed or invested principal. * @param fv - future value of loan or annuity. * @return Representing interest portion of payment. * @see #pmt(BigDecimal, int, BigDecimal, BigDecimal) * @see #fv(BigDecimal, int, BigDecimal, BigDecimal) */ public static BigDecimal ipmt(final BigDecimal r, final int per, final int nper, final BigDecimal pv, final BigDecimal fv) { // Prior period (i.e., per-1) balance times periodic interest rate. // i.e., ipmt = fv(r, per-1, c, pv, type) * r // where c = pmt(r, nper, pv, fv, type) return times(fv(r, per - 1, pmt(r, nper, pv, fv), pv), r); }
@Override public BigDecimal getShareAtRisk() { if (isZero(czkInvested)) { // protected against division by zero return BigDecimal.ZERO; } return divide(czkAtRisk, czkInvested); }
static BigDecimal feePaid(final BigDecimal originalValue, final BigDecimal interestRate, final int originalTerm, final BigDecimal annualFee, final int totalMonths) { final BigDecimal monthlyRate = divide(interestRate, 12); final BigDecimal monthlyFee = divide(annualFee, 12); final BigDecimal pmt = FinancialUtil.pmt(monthlyRate, originalTerm, originalValue); final BigDecimal result = IntStream.range(0, totalMonths) .mapToObj(term -> FinancialUtil.fv(monthlyRate, term + 1, pmt, originalValue).negate()) .map(fv -> times(fv, monthlyFee)) .reduce(BigDecimal.ZERO, BigDecimalCalculator::plus); LOGGER.debug("Fee paid from {} CZK at {} rate for {} months with {} annual fee over {} months is {} CZK.", originalValue, interestRate, originalTerm, annualFee, totalMonths, result.doubleValue()); return toScale(result); }
public static BigDecimal plus(final Number addend1, final BigDecimal addend2) { return plus(toBigDecimal(addend1), addend2); }
public static BigDecimal actualInterestAfterFees(final Investment investment, final long totalInvested, final boolean includeSmpSaleFee) { final int termsInZonky = countTermsInZonky(investment); final BigDecimal fee = feePaid(investment, totalInvested, termsInZonky); final BigDecimal actualFee = includeSmpSaleFee ? plus(fee, investment.getSmpFee().orElse(BigDecimal.ZERO)) : fee; final BigDecimal interest = plus(investment.getPaidInterest(), investment.getPaidPenalty()); return minus(interest, actualFee); }
public static BigDecimal times(final BigDecimal multiplicand, final Number multiplier) { return times(multiplicand, toBigDecimal(multiplier)); }
public static BigDecimal minus(final Number minuend, final BigDecimal subtrahend) { return minus(toBigDecimal(minuend), subtrahend); }