1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package com.nickokiss.investor.calc;
22
23 import java.math.BigDecimal;
24
25 import com.nickokiss.investor.function.EffectiveInterestRateFunction;
26 import com.nickokiss.investor.function.Function;
27 import com.nickokiss.investor.functioncalc.FunctionCalc;
28 import com.nickokiss.investor.functioncalc.IterativeFunctionCalc;
29 import com.nickokiss.investor.util.Range;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class CompoundInterestCalc {
54
55 private MathCalc mathCalc = new MathCalc();
56
57
58
59
60
61
62
63
64
65
66
67
68 public BigDecimal getNominalInterestRate(BigDecimal futureValue, BigDecimal presentValue, BigDecimal periodsPerYear,
69 BigDecimal investmentPeriods) {
70
71
72 BigDecimal growth = mathCalc.div(futureValue, presentValue);
73
74 BigDecimal growthPerPeriod = mathCalc.pow(growth, mathCalc.invert(investmentPeriods));
75
76 BigDecimal increasePerPeriod = growthPerPeriod.subtract(mathCalc.ONE);
77
78 BigDecimal nominalInterestRate = increasePerPeriod.multiply(periodsPerYear);
79 return nominalInterestRate;
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93 public BigDecimal getPeriodsPerYear(BigDecimal futureValue, BigDecimal presentValue, BigDecimal nominalInterestRate,
94 BigDecimal investmentPeriods) {
95
96
97 BigDecimal growth = mathCalc.div(futureValue, presentValue);
98
99 BigDecimal growthPerPeriod = mathCalc.pow(growth, mathCalc.invert(investmentPeriods));
100
101 BigDecimal increasePerPeriod = growthPerPeriod.subtract(mathCalc.ONE);
102
103 BigDecimal periodsPerYear = mathCalc.div(nominalInterestRate, increasePerPeriod);
104 return periodsPerYear;
105 }
106
107
108
109
110 public BigDecimal getFutureValue(BigDecimal presentValue, BigDecimal nominalInterestRate, BigDecimal periodsPerYear,
111 BigDecimal investmentPeriods) {
112
113
114 BigDecimal growth = getGrowth(nominalInterestRate, periodsPerYear, investmentPeriods);
115 BigDecimal futureValue = presentValue.multiply(growth);
116 return futureValue;
117 }
118
119
120
121
122
123
124
125
126
127 public BigDecimal getPresentValue(BigDecimal futureValue, BigDecimal nominalInterestRate, BigDecimal periodsPerYear,
128 BigDecimal investmentPeriods) {
129
130 BigDecimal growth = getGrowth(nominalInterestRate, periodsPerYear, investmentPeriods);
131 BigDecimal presentValue = mathCalc.div(futureValue, growth);
132 return presentValue;
133 }
134
135
136
137
138 public BigDecimal getGrowth(BigDecimal interest, BigDecimal periodsPerYear, BigDecimal investmentPeriods) {
139
140
141 BigDecimal increasePerPeriod = mathCalc.div(interest, periodsPerYear);
142
143 BigDecimal growthPerPeriod = increasePerPeriod.add(mathCalc.ONE);
144
145 BigDecimal growth = mathCalc.pow(growthPerPeriod, investmentPeriods);
146 return growth;
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160 public BigDecimal getInvestmentPeriods(BigDecimal futureValue, BigDecimal presentValue, BigDecimal nominalInterestRate,
161 BigDecimal periodsPerYear) {
162
163
164 BigDecimal growth = mathCalc.div(futureValue, presentValue);
165
166 BigDecimal increasePerPeriod = mathCalc.div(nominalInterestRate, periodsPerYear);
167
168 BigDecimal growthPerPeriod = increasePerPeriod.add(mathCalc.ONE);
169
170 BigDecimal investmentPeriods = mathCalc.log(growthPerPeriod, growth);
171 return investmentPeriods;
172 }
173
174
175
176
177 public BigDecimal getEffectiveInterestRate(BigDecimal nominalInterestRate, BigDecimal periodsPerYear) {
178
179
180 BigDecimal yearlyGrowth = getGrowth(nominalInterestRate, periodsPerYear, periodsPerYear);
181 BigDecimal effectiveInterestRate = yearlyGrowth.subtract(mathCalc.ONE);
182 return effectiveInterestRate;
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196 public BigDecimal getNominalInterestRate(BigDecimal effectiveInterestRate, BigDecimal periodsPerYear) {
197
198
199 BigDecimal yearlyGrowth = effectiveInterestRate.add(mathCalc.ONE);
200
201 BigDecimal growthPerPeriod = mathCalc.pow(yearlyGrowth, mathCalc.invert(periodsPerYear));
202
203 BigDecimal increasePerPeriod = growthPerPeriod.subtract(mathCalc.ONE);
204
205 BigDecimal nominalInterestRate = periodsPerYear.multiply(increasePerPeriod);
206 return nominalInterestRate;
207 }
208
209 public BigDecimal getPeriodsPerYear(BigDecimal effectiveInterestRate, BigDecimal nominalInterestRate) {
210 FunctionCalc functionCalc = new IterativeFunctionCalc();
211 Range initialRange = new Range(mathCalc.ONE, mathCalc.TEN.pow(3));
212 Function function = new EffectiveInterestRateFunction(nominalInterestRate);
213 Range resultRange = functionCalc.getParameterRange(effectiveInterestRate, function, mathCalc.ONE, initialRange);
214 return resultRange.getMiddle();
215 }
216
217 public BigDecimal getGrowthFactor(BigDecimal nominalInterestRate, BigDecimal periodsPerYear, BigDecimal investmentYears) {
218 return getGrowth(nominalInterestRate, periodsPerYear, periodsPerYear.multiply(investmentYears));
219 }
220
221 public BigDecimal getDiscountFactor(BigDecimal nominalInterestRate, BigDecimal periodsPerYear, BigDecimal investmentYears) {
222 return getGrowth(nominalInterestRate, periodsPerYear, periodsPerYear.multiply(investmentYears.negate()));
223 }
224
225
226
227
228
229
230
231
232
233
234
235
236 public BigDecimal getForwardRate(BigDecimal spotRate1, BigDecimal time1, BigDecimal spotRate2, BigDecimal time2, BigDecimal periodsPerYear) {
237
238 BigDecimal sjPart = mathCalc.pow(mathCalc.div(spotRate2, periodsPerYear).add(mathCalc.ONE), time2);
239
240 BigDecimal siPart = mathCalc.pow(mathCalc.div(spotRate1, periodsPerYear).add(mathCalc.ONE), time1);
241
242 BigDecimal base = mathCalc.div(sjPart, siPart);
243
244 BigDecimal exponent = mathCalc.div(mathCalc.ONE, time2.subtract(time1));
245
246 return periodsPerYear.multiply(mathCalc.pow(base, exponent)).subtract(periodsPerYear);
247 }
248
249 public BigDecimal getDiscountFactor(BigDecimal spotRate1, BigDecimal time1, BigDecimal spotRate2, BigDecimal time2, BigDecimal periodsPerYear) {
250 BigDecimal forwardRate = getForwardRate(spotRate1, time1, spotRate2, time2, periodsPerYear);
251 return getDiscountFactorFromForwardRate(forwardRate, time1, time2);
252 }
253
254
255
256
257 public BigDecimal getDiscountFactorFromForwardRate(BigDecimal forwardRate, BigDecimal time1, BigDecimal time2) {
258
259 return mathCalc.pow(mathCalc.invert(forwardRate.add(mathCalc.ONE)), time2.subtract(time1));
260 }
261 }