/* * Copyright (c) 2012, 2013, Credit Suisse (Anatole Tresch), Werner Keil. Licensed under the Apache * License, Version 2.0 (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.javamoney.calc.common; import org.javamoney.calc.CalculationContext; import java.math.BigDecimal; import java.util.Objects; import javax.money.MonetaryAmount; import javax.money.MonetaryOperator; /** * <p> * <img src="http://www.financeformulas.net/Formula%20Images/Growing%20Annuity%20Payment%201.gif"/> * <br/> * <p> * The growing annuity payment from present value formula shown above is used to calculate the * initial payment of a series of periodic payments that grow at a proportionate rate. This formula * is used specifically when present value is known. * <p> * A growing annuity is an annuity where the payments grow at a particular rate. For example, assume * that the initial payment is $100 and the payments are expected to grow each period at 10%. As * stated, the first payment is $100, then the second payment would be $110 ($100 x [1 + g]), and * the third payment would be $121 ($110 x [1 + g]). * <p> * It is important to keep in mind that the formula shown above will only calculate the first * payment. * * @see http://www.financeformulas.net/Growing-Annuity-Payment.html * @author Anatole * @author Werner */ public final class PresentValueGrowingAnnuityPayment implements MonetaryOperator { private Rate discountRate; private Rate growthRate; private int periods; /** * Constructor. * * @param discountRate The discount rate, not null. * @param growthRate The growth rate, not null. * @param periods the target periods, >= 0. * @return the operator, never null. */ private PresentValueGrowingAnnuityPayment(Rate discountRate, Rate growthRate, int periods) { this.discountRate = Objects.requireNonNull(discountRate); this.growthRate = Objects.requireNonNull(growthRate); if (periods < 0) { throw new IllegalArgumentException("Periods < 0"); } this.periods = periods; } /** * Access a MonetaryOperator for calculation. * * @param discountRate The discount rate, not null. * @param growthRate The growth rate, not null. * @param periods the target periods, >= 0. * @return the operator, never null. */ public static PresentValueGrowingAnnuityPayment of(Rate discountRate, Rate growthRate, int periods) { return new PresentValueGrowingAnnuityPayment(discountRate, growthRate, periods); } /** * Performs the calculation. * * @param amount the dividend payment * @param discountRate The discount rate, not null. * @param growthRate The growth rate, not null. * @return the resulting amount, never null. */ public static MonetaryAmount calculate(MonetaryAmount amount, Rate discountRate, Rate growthRate, int periods) { Objects.requireNonNull(amount, "amount required"); Objects.requireNonNull(discountRate, "discountRate required"); Objects.requireNonNull(growthRate, "growthRate required"); BigDecimal numerator = discountRate.get().subtract(growthRate.get()); BigDecimal denum = BigDecimal.ONE.subtract(BigDecimal.ONE .add(growthRate.get()) .divide(BigDecimal.ONE.add(discountRate.get()), CalculationContext.mathContext()) .pow(periods, CalculationContext.mathContext())); return amount.multiply(numerator.divide(denum, CalculationContext.mathContext())); } @Override public MonetaryAmount apply(MonetaryAmount amount) { return calculate(amount, discountRate, growthRate, periods); } @Override public String toString() { return "PresentValueGrowingAnnuityPayment{" + "discountRate=" + discountRate + ", growthRate=" + growthRate + ", periods=" + periods + '}'; } }