xirr_newton_calculator 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/xirr_newton_calculator.rb +30 -35
- data/spec/xirr_newton_calculator_spec.rb +2 -2
- metadata +1 -1
@@ -1,29 +1,30 @@
|
|
1
1
|
class XirrNewtonCalculator
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
2
|
+
# Calculate Xirr using Newton Raphson
|
3
|
+
|
4
|
+
# Arguments
|
5
|
+
# flows: (Array)
|
6
|
+
# init_rate: (Fixnum, Bignum)
|
7
|
+
# max_iteration: (Fixnum)
|
8
|
+
|
9
|
+
EPS = 10 ** -10
|
10
|
+
|
11
|
+
def initialize(flows, init_rate, max_iteration=10_000)
|
12
|
+
initial_date = Date.parse flows[0].date.to_s
|
13
|
+
@flows = flows.collect do |flow|
|
14
|
+
{
|
15
|
+
amount: flow.amount,
|
16
|
+
diff_date: (Date.parse(flow.date.to_s) - initial_date) / 365.0
|
17
|
+
}
|
18
|
+
end
|
19
|
+
@x_n = init_rate
|
20
|
+
@max_iteration = max_iteration
|
18
21
|
end
|
19
22
|
|
20
23
|
def calculate
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@x_n = next_value(@x_n)
|
26
|
-
iteration += 1
|
24
|
+
f(@x_n)
|
25
|
+
@max_iteration.times do
|
26
|
+
break if @f_xn.abs < EPS
|
27
|
+
@x_n = next_value(@x_n)
|
27
28
|
end
|
28
29
|
@x_n
|
29
30
|
end
|
@@ -33,24 +34,18 @@ class XirrNewtonCalculator
|
|
33
34
|
# Argument X_n
|
34
35
|
# Returns X_n+1
|
35
36
|
def next_value(x)
|
36
|
-
|
37
|
+
x - f(x) / dfdx(x)
|
37
38
|
end
|
38
39
|
|
39
40
|
def dfdx(x)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
41
|
+
@flows[1..-1].inject(0) do |result, flow|
|
42
|
+
result += flow[:amount] * (-flow[:diff_date]) / ((1.0 + x) ** (flow[:diff_date] + 1.0))
|
43
|
+
end
|
44
44
|
end
|
45
45
|
|
46
46
|
def f(x)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def discount_factor_to_irr (disc_fac)
|
54
|
-
1.0/disc_fac - 1
|
47
|
+
@f_xn = @flows.inject(0) do |result, flow|
|
48
|
+
result += flow[:amount] / ((1.0 + x) ** flow[:diff_date])
|
49
|
+
end
|
55
50
|
end
|
56
51
|
end
|
@@ -60,8 +60,8 @@ describe "XirrNewtonCalculator" do
|
|
60
60
|
end
|
61
61
|
|
62
62
|
it "returns proper value for x=1" do
|
63
|
-
xirr_calculator.stub(dfdx: 2)
|
64
|
-
xirr_calculator.
|
63
|
+
xirr_calculator.stub(dfdx: 2.0)
|
64
|
+
xirr_calculator.stub(f: 1.0)
|
65
65
|
expect(xirr_calculator.send(:next_value,1)).to eq 0.5
|
66
66
|
end
|
67
67
|
end
|