xirr 0.2.3 → 0.2.4
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 +7 -0
- data/lib/xirr/cashflow.rb +41 -22
- data/lib/xirr/version.rb +1 -1
- data/test/test_cashflow.rb +9 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66b347b5dff9686099a5cc4c5edf591f69bfdb80
|
4
|
+
data.tar.gz: cb80f9aba97b06a467e7155f9d787b8de172745d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 098443d1b4836a96cd65544cd932f7dacfecc60632e0dfc5d2db08289948eea691113adaa73a3da21d8508dc3f6272fd62f222e7de4306d66e5c6bb4f2c7cdba
|
7
|
+
data.tar.gz: f1cd69d853329c9efcab026153906c887ccdf565028300fd52d96a24eb5f10f408801e030cd3cb36fad9531f5763ad5bcf55c5cc3dc0242125b7630227ba4664
|
data/CHANGE_LOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## Version 0.2.4
|
2
|
+
|
3
|
+
* Cashflow Invalid Messages are now public.
|
4
|
+
* Cashflow Invalid? won't raise exception
|
5
|
+
* Running XIRR in an invalid cashflow will throw exception
|
6
|
+
* New Cashflow No Exception XIRR call.
|
7
|
+
|
1
8
|
## Version 0.2.3
|
2
9
|
|
3
10
|
* Major fix to Bisection Engine.
|
data/lib/xirr/cashflow.rb
CHANGED
@@ -19,11 +19,7 @@ module Xirr
|
|
19
19
|
# Check if Cashflow is invalid and raises ArgumentError
|
20
20
|
# @return [Boolean]
|
21
21
|
def invalid?
|
22
|
-
|
23
|
-
raise ArgumentError, invalid_message
|
24
|
-
else
|
25
|
-
false
|
26
|
-
end
|
22
|
+
positives.empty? || negatives.empty?
|
27
23
|
end
|
28
24
|
|
29
25
|
# Inverse of #invalid?
|
@@ -47,7 +43,7 @@ module Xirr
|
|
47
43
|
# Calculates a simple IRR guess based on period of investment and multiples.
|
48
44
|
# @return [Float]
|
49
45
|
def irr_guess
|
50
|
-
((multiple ** (1 / years_of_investment)) - 1).round(3)
|
46
|
+
valid? ? ((multiple ** (1 / years_of_investment)) - 1).round(3) : false
|
51
47
|
end
|
52
48
|
|
53
49
|
# @param guess [Float]
|
@@ -55,25 +51,55 @@ module Xirr
|
|
55
51
|
# @return [Float]
|
56
52
|
# Finds the XIRR according to the method provided. Default to Bisection
|
57
53
|
def xirr(guess = nil, method = Xirr.config.default_method)
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
54
|
+
if valid?
|
55
|
+
choose_(method).send :xirr, guess
|
56
|
+
else
|
57
|
+
raise ArgumentError, invalid_message
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Calls XIRR but throws no exception and returns with 0
|
62
|
+
# @param guess [Float]
|
63
|
+
# @param method [Symbol]
|
64
|
+
# @return [Float]
|
65
|
+
def xirr_no_exception(guess = nil, method = Xirr.config.default_method)
|
66
|
+
if invalid?
|
67
|
+
BigDecimal.new(0, Xirr::PRECISION)
|
68
|
+
else
|
69
|
+
xirr(guess, method)
|
70
|
+
end
|
67
71
|
end
|
68
72
|
|
73
|
+
|
69
74
|
# First investment date
|
70
75
|
# @return [Time]
|
71
76
|
def min_date
|
72
77
|
@min_date ||= self.map(&:date).min
|
73
78
|
end
|
74
79
|
|
80
|
+
# @return [String]
|
81
|
+
# Error message depending on the missing transaction
|
82
|
+
def invalid_message
|
83
|
+
return 'No positive transaction' if positives.empty?
|
84
|
+
return 'No negative transaction' if negatives.empty?
|
85
|
+
end
|
86
|
+
|
75
87
|
private
|
76
88
|
|
89
|
+
# @param method [Symbol]
|
90
|
+
# Choose a Method to call.
|
91
|
+
# @return [Class]
|
92
|
+
def choose_(method)
|
93
|
+
case method
|
94
|
+
when :bisection
|
95
|
+
Bisection.new(self)
|
96
|
+
when :newton_method
|
97
|
+
NewtonMethod.new(self)
|
98
|
+
else
|
99
|
+
raise ArgumentError, "There is no #{method} method"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
77
103
|
# @api private
|
78
104
|
# Sorts the {Cashflow} by date ascending
|
79
105
|
# and finds the signal of the first transaction.
|
@@ -129,13 +155,6 @@ module Xirr
|
|
129
155
|
@negatives, @positives = self.partition { |x| x.amount >= 0 } # Inverted as negative amount is good
|
130
156
|
end
|
131
157
|
|
132
|
-
# @api private
|
133
|
-
# @return [String]
|
134
|
-
# Error message depending on the missing transaction
|
135
|
-
def invalid_message
|
136
|
-
return 'No positive transaction' if positives.empty?
|
137
|
-
return 'No negative transaction' if negatives.empty?
|
138
|
-
end
|
139
158
|
|
140
159
|
end
|
141
160
|
|
data/lib/xirr/version.rb
CHANGED
data/test/test_cashflow.rb
CHANGED
@@ -89,9 +89,14 @@ describe 'Cashflows' do
|
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'is invalid' do
|
92
|
-
|
92
|
+
assert true, !@cf.valid?
|
93
93
|
end
|
94
94
|
|
95
|
+
it 'returns 0 instead of expection ' do
|
96
|
+
assert_equal BigDecimal.new(0, 6), @cf.xirr_no_exception
|
97
|
+
end
|
98
|
+
|
99
|
+
|
95
100
|
it 'with a wrong method is invalid' do
|
96
101
|
assert_raises(ArgumentError) { @cf.xirr(nil, :no_method) }
|
97
102
|
end
|
@@ -101,7 +106,7 @@ describe 'Cashflows' do
|
|
101
106
|
end
|
102
107
|
|
103
108
|
it 'raises error when xirr is called' do
|
104
|
-
|
109
|
+
assert true, !@cf.irr_guess
|
105
110
|
end
|
106
111
|
|
107
112
|
end
|
@@ -114,7 +119,7 @@ describe 'Cashflows' do
|
|
114
119
|
end
|
115
120
|
|
116
121
|
it 'is invalid' do
|
117
|
-
|
122
|
+
assert true, !@cf.valid?
|
118
123
|
end
|
119
124
|
|
120
125
|
it 'raises error when xirr is called' do
|
@@ -122,7 +127,7 @@ describe 'Cashflows' do
|
|
122
127
|
end
|
123
128
|
|
124
129
|
it 'raises error when xirr is called' do
|
125
|
-
|
130
|
+
assert true, !@cf.irr_guess
|
126
131
|
end
|
127
132
|
end
|
128
133
|
|