xirr 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGE_LOG.md +9 -1
- data/lib/xirr/base.rb +0 -7
- data/lib/xirr/bisection.rb +31 -2
- data/lib/xirr/cashflow.rb +1 -1
- data/lib/xirr/config.rb +7 -5
- data/lib/xirr/version.rb +1 -1
- data/test/test_cashflow.rb +25 -4
- data/test/test_helper.rb +4 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2944764274ca9f0acb15890cfd6540f62f074ff9
|
4
|
+
data.tar.gz: dc62255a7a04825f670208c439ce0adb9437f3a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d8cbf1bcb0d9b47148e748b5db9748061fb4c7ddcae2b2c52b7a046a1d036e80cc0789085e988ef02d8709f0093c7fd158f05283db49855abad729cf31281cf
|
7
|
+
data.tar.gz: d4ee0b6b68097528fd5a28b4d5095fcf73524c8919b4b4cae614c12725fee20f5c0182c88533fce6cdb0421703cb7a74aeef13df7203b86256cd2e4ccea4b611
|
data/CHANGE_LOG.md
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
+
## Version 0.2.7
|
2
|
+
|
3
|
+
* Bisection will now retry XIRR in Newton Method if right limit is reached
|
4
|
+
* Options in config are now module constants
|
5
|
+
|
6
|
+
## Version 0.2.6
|
7
|
+
|
8
|
+
* New Bisection method to avoid not converging to negative IRRs if not enough precision
|
9
|
+
|
1
10
|
## Version 0.2.5
|
2
11
|
|
3
12
|
* Default XIRR does not raise an Exception if cashflow is invalid
|
4
13
|
|
5
|
-
|
6
14
|
## Version 0.2.4
|
7
15
|
|
8
16
|
* Cashflow Invalid Messages are now public.
|
data/lib/xirr/base.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
1
|
module Xirr
|
2
2
|
|
3
|
-
# Precision for BigDecimal
|
4
|
-
PRECISION = Xirr.config.precision.to_i
|
5
|
-
# Days in a year
|
6
|
-
DAYS_IN_YEAR = Xirr.config.days_in_year.to_f
|
7
|
-
# Epsilon: error margin
|
8
|
-
EPS = Xirr.config.eps.to_f
|
9
|
-
|
10
3
|
# Base module for XIRR calculation Methods
|
11
4
|
module Base
|
12
5
|
extend ActiveSupport::Concern
|
data/lib/xirr/bisection.rb
CHANGED
@@ -20,8 +20,7 @@ module Xirr
|
|
20
20
|
while ((right - left).abs > Xirr::EPS && runs < Xirr.config.iteration_limit.to_i) do
|
21
21
|
|
22
22
|
runs += 1
|
23
|
-
|
24
|
-
midpoint = format_irr(left, right)
|
23
|
+
left, midpoint, right = bisection(left, midpoint, right)
|
25
24
|
|
26
25
|
end
|
27
26
|
|
@@ -29,12 +28,42 @@ module Xirr
|
|
29
28
|
raise ArgumentError, "Did not converge after #{runs} tries."
|
30
29
|
end
|
31
30
|
|
31
|
+
# If enabled, will retry XIRR with NewtonMethod
|
32
|
+
if Xirr::FALLBACK && right_limit_reached?(right, midpoint)
|
33
|
+
return NewtonMethod.new(cf).xirr
|
34
|
+
end
|
35
|
+
|
32
36
|
return midpoint.round Xirr::PRECISION
|
33
37
|
|
34
38
|
end
|
35
39
|
|
36
40
|
private
|
37
41
|
|
42
|
+
# @param right [BigDecimal]
|
43
|
+
# @param midpoint [BigDecimal]
|
44
|
+
# @return [Boolean]
|
45
|
+
# Checks if result is the right limit.
|
46
|
+
def right_limit_reached?(right, midpoint)
|
47
|
+
(right - midpoint).abs < Xirr::EPS
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param left [BigDecimal]
|
51
|
+
# @param midpoint [BigDecimal]
|
52
|
+
# @param right [BigDecimal]
|
53
|
+
# @return [Array]
|
54
|
+
# Calculates the Bisections
|
55
|
+
def bisection(left, midpoint, right)
|
56
|
+
_left, _mid = npv_positive?(left), npv_positive?(midpoint)
|
57
|
+
if _left && _mid
|
58
|
+
return left, left, left if npv_positive?(right) # Not Enough Precision in the left to find the IRR
|
59
|
+
end
|
60
|
+
if _left == _mid
|
61
|
+
return midpoint, format_irr(midpoint, right), right # Result is to the Right
|
62
|
+
else
|
63
|
+
return left, format_irr(left, midpoint), midpoint # Result is to the Left
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
38
67
|
# @param midpoint [Float]
|
39
68
|
# @return [Bolean]
|
40
69
|
# Returns true if result is to the right ot the range
|
data/lib/xirr/cashflow.rb
CHANGED
data/lib/xirr/config.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
module Xirr
|
2
2
|
include ActiveSupport::Configurable
|
3
3
|
|
4
|
-
# Default values
|
4
|
+
# Sets as constants all the entries in the Hash Default values
|
5
5
|
default_values = {
|
6
|
-
eps: '1.0e-
|
6
|
+
eps: '1.0e-6'.to_f,
|
7
7
|
days_in_year: 365,
|
8
|
-
iteration_limit:
|
8
|
+
iteration_limit: 50,
|
9
9
|
precision: 6,
|
10
|
-
default_method: :bisection
|
10
|
+
default_method: :bisection,
|
11
|
+
fallback: true
|
11
12
|
}
|
12
13
|
|
13
14
|
# Iterates trhough default values and sets in config
|
14
15
|
default_values.each do |key, value|
|
15
16
|
self.config.send("#{key.to_sym}=", value)
|
17
|
+
const_set key.to_s.upcase.to_sym, value
|
16
18
|
end
|
17
|
-
end
|
19
|
+
end
|
data/lib/xirr/version.rb
CHANGED
data/test/test_cashflow.rb
CHANGED
@@ -61,6 +61,27 @@ describe 'Cashflows' do
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
+
describe 'of a very good investment' do
|
65
|
+
before(:all) do
|
66
|
+
@cf = Cashflow.new
|
67
|
+
@cf << Transaction.new(1000000, date: Date.today - 180)
|
68
|
+
@cf << Transaction.new(-2200000, date: Date.today - 60)
|
69
|
+
@cf << Transaction.new(-800000, date: Date.today - 30)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'has an Internal Rate of Return on Bisection Method' do
|
73
|
+
assert_equal '22.352206 '.to_f, @cf.xirr
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'has an Internal Rate of Return on Newton Method' do
|
77
|
+
assert_equal '22.352206 '.to_f, @cf.xirr(nil, :newton_method)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'has an educated guess' do
|
81
|
+
assert_equal '13.488 '.to_f, @cf.irr_guess
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
64
85
|
describe 'of a good investment' do
|
65
86
|
before(:all) do
|
66
87
|
@cf = Cashflow.new
|
@@ -97,16 +118,16 @@ describe 'Cashflows' do
|
|
97
118
|
end
|
98
119
|
|
99
120
|
it 'returns 0 instead of expection ' do
|
100
|
-
assert_equal BigDecimal.new(0, 6), @cf.
|
121
|
+
assert_equal BigDecimal.new(0, 6), @cf.xirr
|
101
122
|
end
|
102
123
|
|
103
124
|
|
104
125
|
it 'with a wrong method is invalid' do
|
105
|
-
assert_raises(ArgumentError) { @cf.
|
126
|
+
assert_raises(ArgumentError) { @cf.xirr_with_exception(nil, :no_method) }
|
106
127
|
end
|
107
128
|
|
108
129
|
it 'raises error when xirr is called' do
|
109
|
-
assert_raises(ArgumentError) { @cf.
|
130
|
+
assert_raises(ArgumentError) { @cf.xirr_with_exception }
|
110
131
|
end
|
111
132
|
|
112
133
|
it 'raises error when xirr is called' do
|
@@ -127,7 +148,7 @@ describe 'Cashflows' do
|
|
127
148
|
end
|
128
149
|
|
129
150
|
it 'raises error when xirr is called' do
|
130
|
-
assert_raises(ArgumentError) { @cf.
|
151
|
+
assert_raises(ArgumentError) { @cf.xirr_with_exception }
|
131
152
|
end
|
132
153
|
|
133
154
|
it 'raises error when xirr is called' do
|
data/test/test_helper.rb
CHANGED
@@ -26,8 +26,9 @@ require_relative 'lib/xirr/cashflow.rb'
|
|
26
26
|
require_relative 'lib/xirr/transaction.rb'
|
27
27
|
include Xirr
|
28
28
|
cf = Cashflow.new
|
29
|
-
cf << Transaction.new(
|
30
|
-
cf << Transaction.new(-
|
31
|
-
cf.
|
29
|
+
cf << Transaction.new(1000000, date: Date.today - 180)
|
30
|
+
cf << Transaction.new(-2200000, date: Date.today - 60)
|
31
|
+
cf << Transaction.new(-800000, date: Date.today - 30)
|
32
|
+
cf.xirr
|
32
33
|
|
33
34
|
=end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xirr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tubedude
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|