Skip to content

Commit

Permalink
## Version 0.2.4
Browse files Browse the repository at this point in the history
* Cashflow Invalid Messages are now public.
* Cashflow Invalid? won't raise exception
* Running XIRR in an invalid cashflow will throw exception
* New Cashflow No Exception XIRR call.
  • Loading branch information
tubedude committed Aug 7, 2014
1 parent f64ed23 commit b6a343e
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 27 deletions.
7 changes: 7 additions & 0 deletions CHANGE_LOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## Version 0.2.4

* Cashflow Invalid Messages are now public.
* Cashflow Invalid? won't raise exception
* Running XIRR in an invalid cashflow will throw exception
* New Cashflow No Exception XIRR call.

## Version 0.2.3

* Major fix to Bisection Engine.
Expand Down
63 changes: 41 additions & 22 deletions lib/xirr/cashflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ def initialize(*args)
# Check if Cashflow is invalid and raises ArgumentError
# @return [Boolean]
def invalid?
if positives.empty? || negatives.empty?
raise ArgumentError, invalid_message
else
false
end
positives.empty? || negatives.empty?
end

# Inverse of #invalid?
Expand All @@ -47,33 +43,63 @@ def max_date
# Calculates a simple IRR guess based on period of investment and multiples.
# @return [Float]
def irr_guess
((multiple ** (1 / years_of_investment)) - 1).round(3) if valid?
valid? ? ((multiple ** (1 / years_of_investment)) - 1).round(3) : false
end

# @param guess [Float]
# @param method [Symbol]
# @return [Float]
# Finds the XIRR according to the method provided. Default to Bisection
def xirr(guess = nil, method = Xirr.config.default_method)
_method = case method
when :bisection
Bisection.new(self)
when :newton_method
NewtonMethod.new(self)
else
raise ArgumentError, "There is no #{method} method"
end
_method.send :xirr, guess if valid?
if valid?
choose_(method).send :xirr, guess
else
raise ArgumentError, invalid_message
end
end

# Calls XIRR but throws no exception and returns with 0
# @param guess [Float]
# @param method [Symbol]
# @return [Float]
def xirr_no_exception(guess = nil, method = Xirr.config.default_method)
if invalid?
BigDecimal.new(0, Xirr::PRECISION)
else
xirr(guess, method)
end
end


# First investment date
# @return [Time]
def min_date
@min_date ||= self.map(&:date).min
end

# @return [String]
# Error message depending on the missing transaction
def invalid_message
return 'No positive transaction' if positives.empty?
return 'No negative transaction' if negatives.empty?
end

private

# @param method [Symbol]
# Choose a Method to call.
# @return [Class]
def choose_(method)
case method
when :bisection
Bisection.new(self)
when :newton_method
NewtonMethod.new(self)
else
raise ArgumentError, "There is no #{method} method"
end
end

# @api private
# Sorts the {Cashflow} by date ascending
# and finds the signal of the first transaction.
Expand Down Expand Up @@ -129,13 +155,6 @@ def split_transactions
@negatives, @positives = self.partition { |x| x.amount >= 0 } # Inverted as negative amount is good
end

# @api private
# @return [String]
# Error message depending on the missing transaction
def invalid_message
return 'No positive transaction' if positives.empty?
return 'No negative transaction' if negatives.empty?
end

end

Expand Down
2 changes: 1 addition & 1 deletion lib/xirr/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Xirr
# Version of the Gem
VERSION = "0.2.3"
VERSION = "0.2.4"
end
13 changes: 9 additions & 4 deletions test/test_cashflow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,14 @@
end

it 'is invalid' do
assert_raises(ArgumentError) { @cf.valid? }
assert true, !@cf.valid?
end

it 'returns 0 instead of expection ' do
assert_equal BigDecimal.new(0, 6), @cf.xirr_no_exception
end


it 'with a wrong method is invalid' do
assert_raises(ArgumentError) { @cf.xirr(nil, :no_method) }
end
Expand All @@ -101,7 +106,7 @@
end

it 'raises error when xirr is called' do
assert_raises(ArgumentError) { @cf.irr_guess }
assert true, !@cf.irr_guess
end

end
Expand All @@ -114,15 +119,15 @@
end

it 'is invalid' do
assert_raises(ArgumentError) { @cf.valid? }
assert true, !@cf.valid?
end

it 'raises error when xirr is called' do
assert_raises(ArgumentError) { @cf.xirr }
end

it 'raises error when xirr is called' do
assert_raises(ArgumentError) { @cf.irr_guess }
assert true, !@cf.irr_guess
end
end

Expand Down

0 comments on commit b6a343e

Please sign in to comment.