1   /**
2    * Investor, the open-source investment library
3    *
4    * (C) Copyright 2008, by individual contributors as indicated by the @author tag.
5    *
6    * This library is free software; you can redistribute it and/or modify it
7    * under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation; either version 2.1 of
9    * the License, or (at your option) any later version.
10   *
11   * This software is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this software; if not, write to the Free
18   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
20   */
21  package com.nickokiss.investor.calc;
22  
23  import java.math.BigDecimal;
24  
25  /**
26   * 
27   * @author Tomasz Koscinski <tomasz.koscinski@nickokiss.com>
28   */
29  public class ContCompInterestCalc {
30  
31    private MathCalc mathCalc = new MathCalc();
32  
33    /**
34     * growthFactor = e^(r*t)
35     */
36    public BigDecimal getGrowthFactor(BigDecimal nominalInterestRate, BigDecimal time) {
37      BigDecimal scaledNominalInterestRate = nominalInterestRate.multiply(time);
38      return mathCalc.exp(scaledNominalInterestRate);
39    }
40  
41    /**
42     * v = a * e^(r*t)
43     */
44    public BigDecimal getFutureValue(BigDecimal presentValue, BigDecimal nominalInterestRate, BigDecimal time) {
45      BigDecimal growth = getGrowthFactor(nominalInterestRate, time);
46      BigDecimal futureValue = presentValue.multiply(growth);
47      return futureValue;
48    }
49  
50    /**
51     * TRANSFORMATION:
52     *
53     * <pre>
54     * v = a * e^(r*t)
55     * a = v / e^(r*t)
56     * </pre>
57     */
58    public BigDecimal getPresentValue(BigDecimal futureValue, BigDecimal nominalInterestRate, BigDecimal time) {
59      BigDecimal growth = getGrowthFactor(nominalInterestRate, time);
60      BigDecimal presentValue = mathCalc.div(futureValue, growth);
61      return presentValue;
62    }
63  
64    /**
65     * TRANSFORMATION:
66     *
67     * <pre>
68     * v = a * e^(r*t)
69     * v/a = e^(r*t)
70     * log(v/a) = r * t
71     * r = log(v/a) / t
72     * </pre>
73     */
74    public BigDecimal getNominalInterestRate(BigDecimal futureValue, BigDecimal presentValue, BigDecimal time) {
75      BigDecimal growth = mathCalc.div(futureValue, presentValue);
76      BigDecimal scaledNominalInterestRate = mathCalc.log(growth);
77      BigDecimal nominalInterestRate = mathCalc.div(scaledNominalInterestRate, time);
78      return nominalInterestRate;
79    }
80  
81    /**
82     * TRANSFORMATION:
83     *
84     * <pre>
85     * v = a * e^(r*t)
86     * v/a = e^(r*t)
87     * log(v/a) = r * t
88     * t = log(v/a) / r
89     * </pre>
90     */
91    public BigDecimal getTime(BigDecimal futureValue, BigDecimal presentValue, BigDecimal nominalInterestRate) {
92      BigDecimal growth = mathCalc.div(futureValue, presentValue);
93      BigDecimal scaledNominalInterestRate = mathCalc.log(growth);
94      BigDecimal time = mathCalc.div(scaledNominalInterestRate, nominalInterestRate);
95      return time;
96    }
97  
98    /**
99     * er = e^r - 1
100    */
101   public BigDecimal getEffectiveInterestRate(BigDecimal nominalInterestRate) {
102 
103     BigDecimal yearlyGrowth = mathCalc.exp(nominalInterestRate);
104     BigDecimal effectiveInterestRate = yearlyGrowth.subtract(mathCalc.ONE);
105     return effectiveInterestRate;
106   }
107 
108   /**
109    * TRANSFORMATION:
110    *
111    * <pre>
112    * er = e^r - 1
113    * e^r = er + 1
114    * r = log(er + 1)
115    * </pre>
116    */
117   public BigDecimal getNominalInterestRate(BigDecimal effectiveInterestRate) {
118     BigDecimal yearlyGrowth = effectiveInterestRate.add(mathCalc.ONE);
119     BigDecimal nominalInterestRate = mathCalc.log(yearlyGrowth);
120     return nominalInterestRate;
121   }
122 
123   public BigDecimal getDiscountFactor(BigDecimal nominalInterestRate, BigDecimal investmentYears) {
124     return getGrowthFactor(nominalInterestRate, investmentYears.negate());
125   }
126 
127   /**
128    * <pre>
129    * f[i,j] = (sj*j - si*i) / (j - i)
130    * si - spot rate at time i (spotRate1)
131    * sj - spot rate at time j (spotRate2)
132    * i - time i
133    * j - time j
134    * </pre>
135    */
136   public BigDecimal getForwardRate(BigDecimal spotRate1, BigDecimal time1, BigDecimal spotRate2, BigDecimal time2) {
137     BigDecimal sjj = spotRate2.multiply(time2);
138     BigDecimal sii = spotRate1.multiply(time1);
139     return mathCalc.div(sjj.subtract(sii), time2.subtract(time1));
140   }
141 
142   public BigDecimal getDiscountFactor(BigDecimal spotRate1, BigDecimal time1, BigDecimal spotRate2, BigDecimal time2) {
143     BigDecimal forwardRate = getForwardRate(spotRate1, time1, spotRate2, time2);
144     return getDiscountFactorFromForwardRate(forwardRate, time1, time2);
145   }
146 
147   /**
148    * d[i,j] = (1 / 1 + f[i,j])^(j-i)
149    */
150   public BigDecimal getDiscountFactorFromForwardRate(BigDecimal forwardRate, BigDecimal time1, BigDecimal time2) {
151     // (1 / 1 + f[i,j])^(j-i)
152     return mathCalc.pow(mathCalc.invert(forwardRate.add(mathCalc.ONE)), time2.subtract(time1));
153   }
154 
155 }