/*
* 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.math.MathContext;
import java.util.Objects;
import javax.money.MonetaryAmount;
import javax.money.MonetaryOperator;
/**
* <img src=
* "http://www.financeformulas.net/Formula%20Images/FV%20of%20Annuity%20-%20Continuous%20Compounding%201.gif"
* />
* <p>
* The future value (FV) of an annuity with continuous compounding formula is used to calculate the
* ending balance on a series of periodic payments that are compounded continuously. Understanding
* the future value of annuity with continuous compounding formula requires the understanding of two
* specific financial and mathematical concepts, which are future value of an annuity and continuous
* compounding.
* <h3>Future Value of Annuity, Continuous Compounding, and Geometric Series</h3>
* <p>
* Future Value of Annuity - The future value of an annuity is the sum of a series of periodic
* payments and typically involves compounding of interest as the balance increases. The formula for
* future value of annuity alone generally solves the question
* "How much will I have saved at X dollars per month after Y months." Continuous Compounding -
* Continuous compounding is compounding that is constant. One way some try to visualize the concept
* of continuous compounding is that is fluid, constantly compounding moment by moment, as opposed
* to daily, monthly, quarterly, or annually. The question a few sentences above regarding 'How much
* will I have saved' must also take into consideration how often interest is compounded in the
* interest bearing account. The formula for continuous compounding is
* </p>
* <h3>Continuous Compounding Formula</h3>
* <p>
* The future value of annuity with continuous compounding formula applies both of these concepts
* for one saving in an account that has continuous compounding.
* </p>
*
* @author Anatole Tresch
* @see http://www.financeformulas.net/Future_Value_of_Annuity.html
*/
public final class FutureValueOfAnnuityWithContCompounding implements MonetaryOperator {
/**
* the target rate, not null.
*/
private Rate rate;
/**
* the periods, >= 0.
*/
private int periods;
/**
* Private constructor.
*
* @param rate the target rate, not null.
* @param periods the periods.
*/
private FutureValueOfAnnuityWithContCompounding(Rate rate, int periods) {
this.rate = Objects.requireNonNull(rate);
this.periods = periods;
}
/**
* Access a MonetaryOperator for calculation.
*
* @param rate The discount rate, not null.
* @param periods the target periods, >= 0.
* @return the operator, never null.
*/
public static FutureValueOfAnnuityWithContCompounding of(Rate rate, int periods) {
return new FutureValueOfAnnuityWithContCompounding(rate, periods);
}
/**
* Performs the calculation.
*
* @param amount the first payment
* @param rate The rate, not null.
* @param periods the target periods, >= 0.
* @return the resulting amount, never null.
*/
public static MonetaryAmount calculate(MonetaryAmount amount, Rate rate, int periods) {
Objects.requireNonNull(amount, "Amount required");
Objects.requireNonNull(rate, "Rate required");
// FVofA/CC = CF * [ (e.pow(r*n) - 1) / ((e.pow(r) - 1)) ]
double num = Math.pow(Math.E, rate.get().doubleValue() * periods) - 1.0;
double denum = Math.pow(Math.E, rate.get().doubleValue()) - 1.0;
BigDecimal factor = new BigDecimal(num, CalculationContext.mathContext())
.divide(new BigDecimal(denum, CalculationContext.mathContext()));
return amount.multiply(factor);
}
@Override
public MonetaryAmount apply(MonetaryAmount amount) {
return calculate(amount, rate, periods);
}
}