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.fin.env;
22  
23  import java.math.BigDecimal;
24  
25  import com.nickokiss.investor.calc.MathCalc;
26  
27  /**
28   * 
29   * @author Tomasz Koscinski <tomasz.koscinski@nickokiss.com>
30   */
31  public class PeriodicCompoundingStrategy implements CompoundingStrategy {
32  
33    private MathCalc mathCalc = new MathCalc();
34    
35    private BigDecimal periodsPerYear;
36    
37    public PeriodicCompoundingStrategy(BigDecimal periodsPerYear) {
38      this.periodsPerYear = periodsPerYear;
39    }
40  
41    public PeriodicCompoundingStrategy(String string) {
42      this(new BigDecimal(string));
43    }
44  
45    public BigDecimal getPeriodsPerYear() {
46      return periodsPerYear;
47    }
48  
49    public void setPeriodsPerYear(BigDecimal periodsPerYear) {
50      this.periodsPerYear = periodsPerYear;
51    }
52  
53    /**
54     * <pre>
55     * f[i,j] = m * ( ((1 + sj/m)^j) / ((1+si/m)^i) )^(1/(j-i)) - m
56     * 
57     * m - payments per year
58     * si - spot rate at time i
59     * sj - spot rate at time j
60     * i - time i
61     * j - time j
62     * </pre> 
63     */
64    public BigDecimal getForwardRate(BigDecimal startTime, BigDecimal endTime, InterestRateStrategy interestRateStrategy) {
65      // ((1 + sj/m)^j)
66      BigDecimal sjPart = mathCalc.pow(mathCalc.div(interestRateStrategy.getSpotRate(endTime), periodsPerYear).add(mathCalc.ONE), endTime);
67      // ((1 + si/m)^i)
68      BigDecimal siPart = mathCalc.pow(mathCalc.div(interestRateStrategy.getSpotRate(startTime), periodsPerYear).add(mathCalc.ONE), startTime);
69      // ((1 + sj/m)^j) / ((1+si/m)^i)
70      BigDecimal base = mathCalc.div(sjPart, siPart);
71      // (1/(j-i))
72      BigDecimal exponent = mathCalc.div(mathCalc.ONE, endTime.subtract(startTime));
73      // m * ( ((1 + sj/m)^j) / ((1+si/m)^i) )^(1/(j-i)) - m
74      return periodsPerYear.multiply(mathCalc.pow(base, exponent)).subtract(periodsPerYear);
75    }
76  
77    /**
78     * d[i,j] = (1 / 1 + f[i,j]/m)^(m*(j-i)) 
79     */
80    public BigDecimal getDiscountFactor(BigDecimal startTime, BigDecimal endTime, InterestRateStrategy interestRateStrategy) {
81      // m * (j-i)
82      BigDecimal exponent = periodsPerYear.multiply(endTime.subtract(startTime));
83      if (exponent.compareTo(mathCalc.ZERO) == 0) {
84        return mathCalc.ONE;
85      }
86      BigDecimal forwardRate = getForwardRate(startTime, endTime, interestRateStrategy);
87      // (1 / 1 + f[i,j]/m)
88      BigDecimal base = mathCalc.div(mathCalc.ONE, mathCalc.ONE.add(mathCalc.div(forwardRate, periodsPerYear)));
89      // (1 / 1 + f[i,j]/m)^(m*(j-i))
90      return mathCalc.pow(base, exponent);
91    }
92  
93    /**
94     * dm = (1 + r/m)^(-1 * (t*m + 1))
95     */
96    public BigDecimal getDurationMultiplicand(BigDecimal time, BigDecimal spotRate) {
97      BigDecimal base = mathCalc.div(spotRate, periodsPerYear).add(mathCalc.ONE);
98      BigDecimal exponent = time.multiply(periodsPerYear).add(mathCalc.ONE).negate();
99      return mathCalc.pow(base, exponent);
100   }
101 
102   
103 }