xirr 0.5.4 → 0.7.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 19f0ca0058f57982916f0a8e2b96ceb6717a6dc4
4
- data.tar.gz: e2467167fa94e1f7132815933034502a0a999b9a
2
+ SHA256:
3
+ metadata.gz: c709c5e546741c7000bd7e496c33bcc3dc01217bbb658d3a11f32133fcbc6497
4
+ data.tar.gz: f3b599422007ddfab2054b82e2aa2ea8e8cd2eb8c7704d4dddeca3e0fe857bc4
5
5
  SHA512:
6
- metadata.gz: d6ab5e1fe60ef7859c938938b23ca06e01b148e2c1e5cb9cd8fb82f4d15e9ba30818abea6004440da26ad90016c31191bab62cde26c7e635d78ac64b3a3b0a0f
7
- data.tar.gz: 38da74ebbfe057d53139d13d25d73553db8edb1b6fbe5492dfac8816920ee0efab77ae2fb21a7edc5dfc7039cb5b77a6e7ec0a91f1b0c08d084db23affb700e8
6
+ metadata.gz: 7c4a8e5b379d2da61d3fd5294a7615dfe9d023cc027d8c33cf8144e82b8ab05ecffe80095638821becec30e0d14840bff6d1aa1a16c4f67eec3c13eb5d87c13d
7
+ data.tar.gz: 5e79738f91734d2717d0292c29c3ec3bfe0960a53c2ecef784f75591e0cf60f761a9c36286f3051ff3ca8f331adffaa71427bab5b492a95476ac4e4ceb8ddea8
data/.gitignore CHANGED
Binary file
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.2.1
1
+ 3.3
data/.travis.yml CHANGED
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - '2.2.1'
4
- - '2.1.5'
5
- - '2.0.0'
3
+ - '2.6.9'
4
+ - '2.7.6'
5
+ - '3.0.4'
6
+ - '3.3.0'
6
7
  script:
7
8
  - bundle exec rake test_units
data/CHANGE_LOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## Version 0.7.0
2
+ * Removed `RubyInLine`
3
+ * Removed possibility to return false from `irr_guess`
4
+ * Removed global newton module
5
+ * Bumped dependencies
6
+
1
7
  ## Version 0.5.4
2
8
  * Fallsback If Newton Methods returns NaN
3
9
 
data/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  # Xirr
2
- [![Build Status](https://travis-ci.org/tubedude/xirr.svg)](https://travis-ci.org/tubedude/xirr)[![Coverage Status](https://coveralls.io/repos/tubedude/xirr/badge.svg?branch=master)](https://coveralls.io/r/tubedude/xirr?branch=master)[![Code Climate](https://codeclimate.com/github/tubedude/xirr/badges/gpa.svg)](https://codeclimate.com/github/tubedude/xirr)[![Dependency Status](https://gemnasium.com/tubedude/xirr.svg)](https://gemnasium.com/tubedude/xirr)
3
-
2
+ [![Build Status](https://travis-ci.org/tubedude/xirr.svg)](https://travis-ci.org/tubedude/xirr)[![Coverage Status](https://coveralls.io/repos/tubedude/xirr/badge.svg?branch=master)](https://coveralls.io/r/tubedude/xirr?branch=master)[![Code Climate](https://codeclimate.com/github/tubedude/xirr/badges/gpa.svg)](https://codeclimate.com/github/tubedude/xirr)[![Ebert](https://ebertapp.io/github/tubedude/xirr.svg)](https://ebertapp.io/github/tubedude/xirr)
4
3
 
5
4
  This is a gem to calculate XIRR on Bisection Method or Newton Method.
6
5
 
@@ -20,29 +19,29 @@ Or install it yourself as:
20
19
 
21
20
  ## Usage
22
21
 
22
+ ```rb
23
+ include Xirr
23
24
 
24
- include Xirr
25
-
26
- cf = Cashflow.new
27
- cf << Transaction.new(-1000, date: '2014-01-01'.to_date)
28
- cf << Transaction.new(-2000, date: '2014-03-01'.to_date)
29
- cf << Transaction.new( 4500, date: '2015-12-01'.to_date)
30
- cf.xirr
31
- # 0.25159694345042327 # [BigDecimal]
32
-
33
- flow = []
34
- flow << Transaction.new(-1000, date: '2014-01-01'.to_date)
35
- flow << Transaction.new(-2000, date: '2014-03-01'.to_date)
36
- flow << Transaction.new( 4500, date: '2015-12-01'.to_date)
25
+ cf = Xirr::Cashflow.new
26
+ cf << Xirr::Transaction.new(-1000, date: '2014-01-01'.to_date)
27
+ cf << Xirr::Transaction.new(-2000, date: '2014-03-01'.to_date)
28
+ cf << Xirr::Transaction.new( 4500, date: '2015-12-01'.to_date)
29
+ cf.xirr
30
+ # 0.25159694345042327 # [BigDecimal]
37
31
 
38
- cf = Cashflow.new flow: flow
39
- cf.xirr
32
+ flow = []
33
+ flow << Xirr::Transaction.new(-1000, date: '2014-01-01'.to_date)
34
+ flow << Xirr::Transaction.new(-2000, date: '2014-03-01'.to_date)
35
+ flow << Xirr::Transaction.new( 4500, date: '2015-12-01'.to_date)
40
36
 
37
+ cf = Xirr::Cashflow.new(flow: flow)
38
+ cf.xirr
39
+ ```
41
40
 
42
41
  ## Configuration
43
42
 
44
43
  # intializer/xirr.rb
45
-
44
+
46
45
  Xirr.configure do |config|
47
46
  config.eps = '1.0e-12'
48
47
  config.days_in_year = 365.25
@@ -53,6 +52,20 @@ Or install it yourself as:
53
52
 
54
53
  http://rubydoc.info/github/tubedude/xirr/master/frames
55
54
 
55
+ ## Supported versions
56
+
57
+ Ruby:
58
+ - 2.2.1
59
+ - 2.3
60
+ - 2.4
61
+ - 2.7
62
+
63
+ ActiveSupport:
64
+ - 4.2
65
+ - 5
66
+ - 6
67
+ - 7
68
+
56
69
  ## Thanks
57
70
 
58
71
  http://puneinvestor.wordpress.com/2013/10/01/calculate-xirr-in-ruby-bisection-method/
@@ -62,6 +75,7 @@ https://github.com/wkranec/finance
62
75
 
63
76
  1. Fork it ( https://github.com/tubedude/xirr/fork )
64
77
  2. Create your feature branch (`git checkout -b my-new-feature`)
65
- 3. Commit your changes (`git commit -am 'Add some feature'`)
66
- 4. Push to the branch (`git push origin my-new-feature`)
67
- 5. Create a new Pull Request
78
+ 3. Run specs (`rake default`)
79
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 5. Push to the branch (`git push origin my-new-feature`)
81
+ 6. Create a new Pull Request
data/Rakefile CHANGED
@@ -10,4 +10,3 @@ Rake::TestTask.new("test_units") do |t|
10
10
  t.verbose = false
11
11
  t.warning = false
12
12
  end
13
-
data/lib/xirr/base.rb CHANGED
@@ -1,5 +1,6 @@
1
- module Xirr
1
+ # frozen_string_literal: true
2
2
 
3
+ module Xirr
3
4
  # Base module for XIRR calculation Methods
4
5
  module Base
5
6
  extend ActiveSupport::Concern
@@ -24,17 +25,9 @@ module Xirr
24
25
  # @return [BigDecimal]
25
26
  def xnpv(rate)
26
27
  cf.inject(0) do |sum, t|
27
- sum += xnpv_c rate, t.amount, periods_from_start(t.date)
28
+ # sum + (xnpv_c rate, t.amount, periods_from_start(t.date))
29
+ sum + t.amount / (1+rate.to_f) ** periods_from_start(t.date)
28
30
  end
29
31
  end
30
-
31
- inline { |builder|
32
- builder.include '<math.h>'
33
- builder.c '
34
- double xnpv_c(double rate, double amount, double period) {
35
- return amount / pow(1 + rate, period);
36
- }'
37
- }
38
-
39
32
  end
40
33
  end
@@ -1,5 +1,6 @@
1
- module Xirr
1
+ # frozen_string_literal: true
2
2
 
3
+ module Xirr
3
4
  # Methods that will be included in Cashflow to calculate XIRR
4
5
  class Bisection
5
6
  include Base
@@ -8,28 +9,25 @@ module Xirr
8
9
  # @return [BigDecimal]
9
10
  # @param midpoint [Float]
10
11
  # An initial guess rate will override the {Cashflow#irr_guess}
11
- def xirr midpoint, options
12
-
12
+ def xirr(midpoint, options)
13
13
  # Initial values
14
- left = [BigDecimal.new(-0.99999999, Xirr::PRECISION), cf.irr_guess].min
15
- right = [BigDecimal.new(9.99999999, Xirr::PRECISION), cf.irr_guess + 1].max
14
+ left = [BigDecimal(-0.99999999, Xirr.config.precision), cf.irr_guess].min
15
+ right = [BigDecimal(9.99999999, Xirr.config.precision), cf.irr_guess + 1].max
16
16
  @original_right = right
17
17
  midpoint ||= cf.irr_guess
18
18
 
19
19
  midpoint, runs = loop_rates(left, midpoint, right, options[:iteration_limit])
20
20
 
21
21
  get_answer(midpoint, options, runs)
22
-
23
22
  end
24
23
 
25
-
26
24
  private
27
25
 
28
26
  # @param midpoint [BigDecimal]
29
27
  # @return [Boolean]
30
28
  # Checks if result is the right limit.
31
29
  def right_limit_reached?(midpoint)
32
- (@original_right - midpoint).abs < Xirr::EPS
30
+ (@original_right - midpoint).abs < Xirr.config.eps
33
31
  end
34
32
 
35
33
  # @param left [BigDecimal]
@@ -38,9 +36,10 @@ module Xirr
38
36
  # @return [Array]
39
37
  # Calculates the Bisections
40
38
  def bisection(left, midpoint, right)
41
- _left, _mid = npv_positive?(left), npv_positive?(midpoint)
39
+ _left = xnpv(left).positive?
40
+ _mid = xnpv(midpoint).positive?
42
41
  if _left && _mid
43
- return left, left, left, true if npv_positive?(right) # Not Enough Precision in the left to find the IRR
42
+ return left, left, left, true if xnpv(right).positive? # Not Enough Precision in the left to find the IRR
44
43
  end
45
44
  if _left == _mid
46
45
  return midpoint, format_irr(midpoint, right), right, false # Result is to the Right
@@ -49,48 +48,35 @@ module Xirr
49
48
  end
50
49
  end
51
50
 
52
- # @param midpoint [Float]
53
- # @return [Bolean]
54
- # Returns true if result is to the right ot the range
55
- def npv_positive?(midpoint)
56
- xnpv(midpoint) > 0
57
- end
58
-
59
51
  # @param left [Float]
60
52
  # @param right [Float]
61
53
  # @return [Float] IRR of the Cashflow
62
54
  def format_irr(left, right)
63
- irr = (right+left) / 2
55
+ irr = (right + left) / 2
64
56
  end
65
57
 
66
58
  def get_answer(midpoint, options, runs)
67
59
  if runs >= options[:iteration_limit]
68
60
  if options[:raise_exception]
69
61
  raise ArgumentError, "Did not converge after #{runs} tries."
70
- else
71
- nil
72
62
  end
73
63
  else
74
- midpoint.round Xirr::PRECISION
64
+ midpoint.round Xirr.config.precision
75
65
  end
76
66
  end
77
67
 
78
68
  def loop_rates(left, midpoint, right, iteration_limit)
79
69
  runs = 0
80
- while (right - left).abs > Xirr::EPS && runs < iteration_limit do
81
- runs += 1
70
+ while (right - left).abs > Xirr.config.eps && runs < iteration_limit do
71
+ runs += 1
82
72
  left, midpoint, right, should_stop = bisection(left, midpoint, right)
83
73
  break if should_stop
84
74
  if right_limit_reached?(midpoint)
85
- right = right * 2
86
- @original_right = @original_right * 2
75
+ right *= 2
76
+ @original_right *= 2
87
77
  end
88
78
  end
89
- return midpoint, runs
79
+ [midpoint, runs]
90
80
  end
91
-
92
-
93
81
  end
94
-
95
82
  end
96
-
data/lib/xirr/cashflow.rb CHANGED
@@ -1,5 +1,6 @@
1
- module Xirr
1
+ # frozen_string_literal: true
2
2
 
3
+ module Xirr
3
4
  # Expands [Array] to store a set of transactions which will be used to calculate the XIRR
4
5
  # @note A Cashflow should consist of at least two transactions, one positive and one negative.
5
6
  class Cashflow < Array
@@ -12,12 +13,12 @@ module Xirr
12
13
  # cf << Transaction.new(-1234, date: '2013-03-31'.to_date)
13
14
  # Or
14
15
  # cf = Cashflow.new Transaction.new( 1000, date: '2013-01-01'.to_date), Transaction.new(-1234, date: '2013-03-31'.to_date)
15
- def initialize(flow: [], period: Xirr::PERIOD, ** options)
16
+ def initialize(flow: [], period: Xirr.config.period, ** options)
16
17
  @period = period
17
- @fallback = options[:fallback] || Xirr::FALLBACK
18
+ @fallback = options[:fallback] || Xirr.config.fallback
18
19
  @options = options
19
20
  self << flow
20
- self.flatten!
21
+ flatten!
21
22
  end
22
23
 
23
24
  # Check if Cashflow is invalid
@@ -35,21 +36,21 @@ module Xirr
35
36
  # @return [Float]
36
37
  # Sums all amounts in a cashflow
37
38
  def sum
38
- self.map(&:amount).sum
39
+ map(&:amount).sum
39
40
  end
40
41
 
41
42
  # Last investment date
42
43
  # @return [Time]
43
44
  def max_date
44
- @max_date ||= self.map(&:date).max
45
+ @max_date ||= map(&:date).max
45
46
  end
46
47
 
47
48
  # Calculates a simple IRR guess based on period of investment and multiples.
48
49
  # @return [Float]
49
50
  def irr_guess
50
51
  return @irr_guess = 0.0 if periods_of_investment.zero?
51
- @irr_guess = valid? ? ((multiple ** (1 / periods_of_investment)) - 1).round(3) : false
52
- @irr_guess == 1.0/0 ? 0.0 : @irr_guess
52
+ @irr_guess = valid? ? ((multiple**(1 / periods_of_investment)) - 1).round(3) : 0.0
53
+ @irr_guess == 1.0 / 0 ? 0.0 : @irr_guess
53
54
  end
54
55
 
55
56
  # @param guess [Float]
@@ -59,18 +60,18 @@ module Xirr
59
60
  method, options = process_options(method, options)
60
61
  if invalid?
61
62
  raise ArgumentError, invalid_message if options[:raise_exception]
62
- BigDecimal.new(0, Xirr::PRECISION)
63
+ BigDecimal(0, Xirr.config.precision)
63
64
  else
64
65
  xirr = choose_(method).send :xirr, guess, options
65
66
  xirr = choose_(other_calculation_method(method)).send(:xirr, guess, options) if (xirr.nil? || xirr.nan?) && fallback
66
- xirr || Xirr::REPLACE_FOR_NIL
67
+ xirr || Xirr.config.replace_for_nil
67
68
  end
68
69
  end
69
70
 
70
71
  def process_options(method, options)
71
72
  @temporary_period = options[:period]
72
- options[:raise_exception] ||= @options[:raise_exception] || Xirr::RAISE_EXCEPTION
73
- options[:iteration_limit] ||= @options[:iteration_limit] || Xirr::ITERATION_LIMIT
73
+ options[:raise_exception] ||= @options[:raise_exception] || Xirr.config.raise_exception
74
+ options[:iteration_limit] ||= @options[:iteration_limit] || Xirr.config.iteration_limit
74
75
  return switch_fallback(method), options
75
76
  end
76
77
 
@@ -78,13 +79,13 @@ module Xirr
78
79
  # it return either the provided method or the system default
79
80
  # @param method [Symbol]
80
81
  # @return [Symbol]
81
- def switch_fallback method
82
+ def switch_fallback(method)
82
83
  if method
83
84
  @fallback = false
84
85
  method
85
86
  else
86
- @fallback = Xirr::FALLBACK
87
- Xirr::DEFAULT_METHOD
87
+ @fallback = Xirr.config.fallback
88
+ Xirr.config.default_method
88
89
  end
89
90
  end
90
91
 
@@ -95,14 +96,14 @@ module Xirr
95
96
  def compact_cf
96
97
  # self
97
98
  compact = Hash.new 0
98
- self.each { |flow| compact[flow.date] += flow.amount }
99
+ each { |flow| compact[flow.date] += flow.amount }
99
100
  Cashflow.new flow: compact.map { |key, value| Transaction.new(value, date: key) }, options: options, period: period
100
101
  end
101
102
 
102
103
  # First investment date
103
104
  # @return [Time]
104
105
  def min_date
105
- @min_date ||= self.map(&:date).min
106
+ @min_date ||= map(&:date).min
106
107
  end
107
108
 
108
109
  # @return [String]
@@ -116,9 +117,9 @@ module Xirr
116
117
  @temporary_period || @period
117
118
  end
118
119
 
119
- def << arg
120
+ def <<(arg)
120
121
  super arg
121
- self.sort! { |x, y| x.date <=> y.date }
122
+ sort! { |x, y| x.date <=> y.date }
122
123
  self
123
124
  end
124
125
 
@@ -129,12 +130,12 @@ module Xirr
129
130
  # @return [Class]
130
131
  def choose_(method)
131
132
  case method
132
- when :bisection
133
- Bisection.new compact_cf
134
- when :newton_method
135
- NewtonMethod.new compact_cf
136
- else
137
- raise ArgumentError, "There is no method called #{method} "
133
+ when :bisection
134
+ Bisection.new compact_cf
135
+ when :newton_method
136
+ NewtonMethod.new compact_cf
137
+ else
138
+ raise ArgumentError, "There is no method called #{method} "
138
139
  end
139
140
  end
140
141
 
@@ -145,7 +146,7 @@ module Xirr
145
146
  # @return [Integer]
146
147
  def first_transaction_direction
147
148
  # self.sort! { |x, y| x.date <=> y.date }
148
- @first_transaction_direction ||= self.first.amount / self.first.amount.abs
149
+ @first_transaction_direction ||= first.amount / first.amount.abs
149
150
  end
150
151
 
151
152
  # Based on the direction of the first investment finds the multiple cash-on-cash
@@ -173,7 +174,7 @@ module Xirr
173
174
  # @see #outflows
174
175
  # Selects all positives transactions from Cashflow
175
176
  def inflow
176
- self.select { |x| x.amount * first_transaction_direction < 0 }
177
+ select { |x| x.amount * first_transaction_direction < 0 }
177
178
  end
178
179
 
179
180
  # @api private
@@ -181,9 +182,7 @@ module Xirr
181
182
  # @see #inflow
182
183
  # Selects all negatives transactions from Cashflow
183
184
  def outflows
184
- self.select { |x| x.amount * first_transaction_direction > 0 }
185
+ select { |x| x.amount * first_transaction_direction > 0 }
185
186
  end
186
-
187
187
  end
188
-
189
188
  end
data/lib/xirr/config.rb CHANGED
@@ -3,15 +3,15 @@ module Xirr
3
3
 
4
4
  # Sets as constants all the entries in the Hash Default values
5
5
  default_values = {
6
- eps: '1.0e-6'.to_f,
7
- period: 365.0,
8
- iteration_limit: 50,
9
- precision: 6,
10
- default_method: :newton_method,
11
- fallback: true,
12
- replace_for_nil: 0.0,
13
- compact: true,
14
- raise_exception: false
6
+ eps: '1.0e-6'.to_f,
7
+ period: 365.0,
8
+ iteration_limit: 50,
9
+ precision: 6,
10
+ default_method: :newton_method,
11
+ fallback: true,
12
+ replace_for_nil: 0.0,
13
+ compact: true,
14
+ raise_exception: false
15
15
  }
16
16
 
17
17
  # Iterates though default values and sets in config
@@ -1,16 +1,18 @@
1
+ # frozen_string_literal: true
1
2
  require 'bigdecimal/newton'
2
- include Newton
3
3
 
4
4
  module Xirr
5
5
  # Class to calculate IRR using Newton Method
6
6
  class NewtonMethod
7
7
  include Base
8
+ include Newton
9
+
8
10
 
9
11
  # Base class for working with Newton's Method.
10
12
  # @api private
11
13
  class Function
12
14
  values = {
13
- eps: Xirr::EPS,
15
+ eps: Xirr.config.eps,
14
16
  one: '1.0',
15
17
  two: '2.0',
16
18
  ten: '10.0',
@@ -20,7 +22,7 @@ module Xirr
20
22
  # define default values
21
23
  values.each do |key, value|
22
24
  define_method key do
23
- BigDecimal.new(value, Xirr::PRECISION)
25
+ BigDecimal(value, Xirr.config.precision)
24
26
  end
25
27
  end
26
28
 
@@ -35,22 +37,22 @@ module Xirr
35
37
  # Necessary for #nlsolve
36
38
  # @param x [BigDecimal]
37
39
  def values(x)
38
- value = @transactions.send(@function, BigDecimal.new(x[0].to_s, Xirr::PRECISION))
39
- [BigDecimal.new(value.to_s, Xirr::PRECISION)]
40
+ value = @transactions.send(@function, BigDecimal(x[0].to_s, Xirr.config.precision))
41
+ [BigDecimal(value.to_s, Xirr.config.precision)]
40
42
  end
41
43
  end
42
44
 
43
45
  # Calculates XIRR using Newton method
44
46
  # @return [BigDecimal]
45
47
  # @param guess [Float]
46
- def xirr guess, options
48
+ def xirr(guess, _options)
47
49
  func = Function.new(self, :xnpv)
48
50
  rate = [guess || cf.irr_guess]
49
51
  begin
50
52
  nlsolve(func, rate)
51
- (rate[0] <= -1 || rate[0].nan?) ? nil : rate[0].round(Xirr::PRECISION)
53
+ (rate[0] <= -1 || rate[0].nan?) ? nil : rate[0].round(Xirr.config.precision)
52
54
 
53
- # rate[0].round(Xirr::PRECISION)
55
+ # rate[0].round(Xirr.config.precision)
54
56
  rescue
55
57
  nil
56
58
  end
@@ -1,5 +1,6 @@
1
- module Xirr
1
+ # frozen_string_literal: true
2
2
 
3
+ module Xirr
3
4
  # A unit of the Cashflow.
4
5
  class Transaction
5
6
  attr_reader :amount, :date
@@ -9,7 +10,7 @@ module Xirr
9
10
  # @param amount [Numeric]
10
11
  # @param opts [Hash]
11
12
  # @note Don't forget to add date: [Date] in the opts hash.
12
- def initialize(amount, opts={})
13
+ def initialize(amount, opts = {})
13
14
  self.amount = amount
14
15
 
15
16
  # Set optional attributes..
@@ -22,7 +23,7 @@ module Xirr
22
23
  # @param value [Date, Time]
23
24
  # @return [Date]
24
25
  def date=(value)
25
- @date = value.kind_of?(Time) ? value.to_date : value
26
+ @date = value.is_a?(Time) ? value.to_date : value
26
27
  end
27
28
 
28
29
  # Sets the amount
@@ -36,7 +37,5 @@ module Xirr
36
37
  def inspect
37
38
  "T(#{@amount},#{@date})"
38
39
  end
39
-
40
40
  end
41
-
42
41
  end
data/lib/xirr/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Xirr
2
2
  # Version of the Gem
3
- VERSION = '0.5.4'
3
+ VERSION = '0.7.0'
4
4
  end
data/lib/xirr.rb CHANGED
@@ -10,8 +10,6 @@ require 'xirr/newton_method'
10
10
  # @abstract adds a {Xirr::Cashflow} and {Xirr::Transaction} classes to calculate IRR of irregular transactions.
11
11
  # Calculates Xirr
12
12
  module Xirr
13
-
14
13
  autoload :Transaction, 'xirr/transaction'
15
14
  autoload :Cashflow, 'xirr/cashflow'
16
-
17
15
  end
@@ -1,7 +1,6 @@
1
1
  require_relative 'test_helper'
2
2
 
3
3
  describe 'Cashflows' do
4
-
5
4
  describe 'of an ok investment' do
6
5
  before(:all) do
7
6
  @cf = Cashflow.new
@@ -39,7 +38,6 @@ describe 'Cashflows' do
39
38
  end
40
39
  end
41
40
 
42
-
43
41
  describe 'of an inverted ok investment' do
44
42
  before(:all) do
45
43
  @cf = Cashflow.new
@@ -136,10 +134,9 @@ describe 'Cashflows' do
136
134
  end
137
135
 
138
136
  it 'returns 0 instead of exception ' do
139
- assert_equal BigDecimal.new(0, 6), @cf.xirr
137
+ assert_equal BigDecimal(0, 6), @cf.xirr
140
138
  end
141
139
 
142
-
143
140
  it 'with a wrong method is invalid' do
144
141
  assert_raises(ArgumentError) { @cf.xirr raise_exception: true, method: :no_method }
145
142
  end
@@ -151,7 +148,6 @@ describe 'Cashflows' do
151
148
  it 'raises error when xirr is called' do
152
149
  assert true, !@cf.irr_guess
153
150
  end
154
-
155
151
  end
156
152
 
157
153
  describe 'an all-positive Cashflow' do
@@ -194,7 +190,6 @@ describe 'Cashflows' do
194
190
  it 'has an educated guess' do
195
191
  assert_equal -0.022, @cf.irr_guess
196
192
  end
197
-
198
193
  end
199
194
 
200
195
  describe 'of a long investment' do
@@ -213,7 +208,6 @@ describe 'Cashflows' do
213
208
  it 'has an educated guess' do
214
209
  assert_equal 0.112, @cf.irr_guess.round(6)
215
210
  end
216
-
217
211
  end
218
212
 
219
213
  describe 'reapeated cashflow' do
@@ -232,7 +226,6 @@ describe 'Cashflows' do
232
226
  it 'sums all transactions' do
233
227
  assert_equal -3000.0, @cf.compact_cf.map(&:amount).inject(&:+)
234
228
  end
235
-
236
229
  end
237
230
 
238
231
  describe 'of a real case' do
@@ -272,13 +265,12 @@ describe 'Cashflows' do
272
265
  @cf << Transaction.new(84710.65, date: '2013-05-21'.to_date)
273
266
  @cf << Transaction.new(-84710.65, date: '2013-05-21'.to_date)
274
267
  @cf << Transaction.new(-144413.24, date: '2013-05-21'.to_date)
275
-
276
268
  end
277
269
 
278
270
  it 'is a long and bad investment and newton generates an error' do
271
+ skip 'Test is weirdly taking too long'
279
272
  assert_equal '-1.0'.to_f, @cf.xirr #(method: :newton_method)
280
273
  end
281
-
282
274
  end
283
275
 
284
276
  describe 'xichen27' do
@@ -290,8 +282,8 @@ describe 'Cashflows' do
290
282
  assert_equal '-0.996814607'.to_f.round(3), cf.xirr.to_f.round(3)
291
283
  end
292
284
  end
293
- describe 'marano' do
294
285
 
286
+ describe 'marano' do
295
287
  it 'it matchs Excel' do
296
288
  cf = Cashflow.new
297
289
  cf << Transaction.new(900.0, date: '2014-11-07'.to_date)
@@ -301,7 +293,6 @@ describe 'Cashflows' do
301
293
  end
302
294
 
303
295
  describe 'period' do
304
-
305
296
  it 'has zero for years of investment' do
306
297
  cf = Cashflow.new flow: [Transaction.new(105187.06, date: '2011-12-07'.to_date), Transaction.new(-105187.06 * 1.0697668105671994, date: '2011-12-07'.to_date)]
307
298
  assert_equal 0.0, cf.irr_guess
@@ -317,7 +308,40 @@ describe 'Cashflows' do
317
308
  cf = Cashflow.new period: 100, flow: [Transaction.new(-1000, date: Date.new(1957, 1, 1)), Transaction.new(390000, date: Date.new(2013, 1, 1))]
318
309
  assert_equal 0.112339, cf.xirr(period: 365.0)
319
310
  end
320
-
321
311
  end
322
312
 
313
+ describe 'with changing precision values' do
314
+ before(:all) do
315
+ # {"2021-05-17"=>-3005.69, "2021-06-03"=>-4781.38, "2021-06-17"=>3.09, "2021-06-21"=>8509.93}
316
+ @cf = Cashflow.new
317
+ @cf << Transaction.new(-117.38, date: '2021-03-17'.to_date)
318
+ @cf << Transaction.new(-2370.02, date: '2021-03-23'.to_date)
319
+ @cf << Transaction.new(0.29, date: '2021-03-26'.to_date)
320
+ @cf << Transaction.new(0.32, date: '2021-04-01'.to_date)
321
+ @cf << Transaction.new(-3005.69, date: '2021-05-17'.to_date)
322
+ @cf << Transaction.new(-4781.38, date: '2021-06-03'.to_date)
323
+ @cf << Transaction.new(3.09, date: '2021-06-17'.to_date)
324
+ @cf << Transaction.new(8509.93, date: '2021-06-21'.to_date)
325
+ end
326
+
327
+ it 'gives nil value for xirr' do
328
+ assert_equal 0.0, @cf.xirr
329
+ end
330
+
331
+ it 'gives correct value with configuration' do
332
+ Xirr.configure do |config|
333
+ config.precision = 10
334
+ config.eps = '1.0e-8'.to_f
335
+ end
336
+ assert_equal -0.8317173694e0, @cf.xirr
337
+ end
338
+
339
+ # resetting configuration
340
+ after(:all) do
341
+ Xirr.configure do |config|
342
+ config.precision = 6
343
+ config.eps = '1.0e-6'.to_f
344
+ end
345
+ end
346
+ end
323
347
  end
data/test/test_helper.rb CHANGED
@@ -1,5 +1,7 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
2
+
1
3
  require 'coveralls'
2
- Coveralls.wear!
4
+ # Coveralls.wear!
3
5
 
4
6
  require 'minitest/autorun'
5
7
  require 'minitest/spec'
@@ -14,28 +16,3 @@ require 'xirr/cashflow.rb'
14
16
  require 'xirr/transaction.rb'
15
17
  include Xirr
16
18
 
17
- =begin
18
-
19
- require 'active_support/all'
20
- require_relative 'lib/xirr.rb'
21
- require_relative 'lib/xirr/config.rb'
22
- require_relative 'lib/xirr/base.rb'
23
- require_relative 'lib/xirr/bisection.rb'
24
- require_relative 'lib/xirr/newton_method.rb'
25
- require_relative 'lib/xirr/cashflow.rb'
26
- require_relative 'lib/xirr/transaction.rb'
27
- include Xirr
28
- @x = Cashflow.new
29
- @x << Transaction.new(-10000.0, :date => Date.new(2014,4,15))
30
- @x << Transaction.new(-10000.0, :date => Date.new(2014,04,16))
31
- @x << Transaction.new(305.6, :date => Date.new(2014,05,16))
32
- @x << Transaction.new(9800.07, :date => Date.new(2014,06,15))
33
- @x << Transaction.new(5052.645, :date => Date.new(2014,06,15))
34
- @x.xirr
35
-
36
- cf << Transaction.new(1000000, date: Date.today - 180)
37
- cf << Transaction.new(-2200000, date: Date.today - 60)
38
- cf << Transaction.new(-800000, date: Date.today - 30)
39
- cf.xirr
40
-
41
- =end
@@ -4,14 +4,16 @@ describe 'Transaction' do
4
4
  before(:all) do
5
5
  @t = Transaction.new(1000, date: Date.today)
6
6
  end
7
+
7
8
  it 'converts amount to float' do
8
9
  assert true, @t.amount.kind_of?(Float)
9
10
  end
11
+
10
12
  it 'retreives the date' do
11
13
  assert_equal Date.today, @t.date
12
14
  end
15
+
13
16
  it 'has inspect' do
14
17
  assert_equal "T(1000.0,#{Date.today})", @t.inspect
15
18
  end
16
-
17
19
  end
data/xirr.gemspec CHANGED
@@ -18,13 +18,14 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.6'
22
- spec.add_development_dependency 'rake', '~> 10'
21
+ spec.required_ruby_version = '>=2.2.2'
23
22
 
24
- spec.required_ruby_version = '>=2.0'
25
- spec.add_dependency 'activesupport', '~> 4'
26
- spec.add_dependency 'RubyInline', '~> 3'
27
- spec.add_development_dependency 'minitest', '~> 5.4'
28
- spec.add_development_dependency 'coveralls', '~> 0'
23
+ spec.add_dependency 'activesupport', '>= 5.2', '< 7'
24
+
25
+ spec.add_development_dependency 'activesupport', '>= 5.2', '< 7'
26
+ spec.add_development_dependency 'minitest', '~> 5.14'
27
+ spec.add_development_dependency 'coveralls', '~> 0.8'
28
+ spec.add_development_dependency 'bundler', '>= 2.2'
29
+ spec.add_development_dependency 'rake', '~> 13.0'
29
30
 
30
31
  end
metadata CHANGED
@@ -1,99 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xirr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tubedude
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-06 00:00:00.000000000 Z
11
+ date: 2024-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
20
- type: :development
19
+ version: '5.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7'
23
+ type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: '1.6'
29
+ version: '5.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7'
27
33
  - !ruby/object:Gem::Dependency
28
- name: rake
34
+ name: activesupport
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
- - - "~>"
37
+ - - ">="
32
38
  - !ruby/object:Gem::Version
33
- version: '10'
39
+ version: '5.2'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '7'
34
43
  type: :development
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
- - - "~>"
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '5.2'
50
+ - - "<"
39
51
  - !ruby/object:Gem::Version
40
- version: '10'
52
+ version: '7'
41
53
  - !ruby/object:Gem::Dependency
42
- name: activesupport
54
+ name: minitest
43
55
  requirement: !ruby/object:Gem::Requirement
44
56
  requirements:
45
57
  - - "~>"
46
58
  - !ruby/object:Gem::Version
47
- version: '4'
48
- type: :runtime
59
+ version: '5.14'
60
+ type: :development
49
61
  prerelease: false
50
62
  version_requirements: !ruby/object:Gem::Requirement
51
63
  requirements:
52
64
  - - "~>"
53
65
  - !ruby/object:Gem::Version
54
- version: '4'
66
+ version: '5.14'
55
67
  - !ruby/object:Gem::Dependency
56
- name: RubyInline
68
+ name: coveralls
57
69
  requirement: !ruby/object:Gem::Requirement
58
70
  requirements:
59
71
  - - "~>"
60
72
  - !ruby/object:Gem::Version
61
- version: '3'
62
- type: :runtime
73
+ version: '0.8'
74
+ type: :development
63
75
  prerelease: false
64
76
  version_requirements: !ruby/object:Gem::Requirement
65
77
  requirements:
66
78
  - - "~>"
67
79
  - !ruby/object:Gem::Version
68
- version: '3'
80
+ version: '0.8'
69
81
  - !ruby/object:Gem::Dependency
70
- name: minitest
82
+ name: bundler
71
83
  requirement: !ruby/object:Gem::Requirement
72
84
  requirements:
73
- - - "~>"
85
+ - - ">="
74
86
  - !ruby/object:Gem::Version
75
- version: '5.4'
87
+ version: '2.2'
76
88
  type: :development
77
89
  prerelease: false
78
90
  version_requirements: !ruby/object:Gem::Requirement
79
91
  requirements:
80
- - - "~>"
92
+ - - ">="
81
93
  - !ruby/object:Gem::Version
82
- version: '5.4'
94
+ version: '2.2'
83
95
  - !ruby/object:Gem::Dependency
84
- name: coveralls
96
+ name: rake
85
97
  requirement: !ruby/object:Gem::Requirement
86
98
  requirements:
87
99
  - - "~>"
88
100
  - !ruby/object:Gem::Version
89
- version: '0'
101
+ version: '13.0'
90
102
  type: :development
91
103
  prerelease: false
92
104
  version_requirements: !ruby/object:Gem::Requirement
93
105
  requirements:
94
106
  - - "~>"
95
107
  - !ruby/object:Gem::Version
96
- version: '0'
108
+ version: '13.0'
97
109
  description: Calculates IRR of a Cashflow, similar to Excel's, XIRR formula. It defaults
98
110
  to Newton Method, but will calculate Bisection as well.
99
111
  email:
@@ -128,7 +140,7 @@ homepage: https://github.com/tubedude/xirr
128
140
  licenses:
129
141
  - MIT
130
142
  metadata: {}
131
- post_install_message:
143
+ post_install_message:
132
144
  rdoc_options: []
133
145
  require_paths:
134
146
  - lib
@@ -136,16 +148,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
136
148
  requirements:
137
149
  - - ">="
138
150
  - !ruby/object:Gem::Version
139
- version: '2.0'
151
+ version: 2.2.2
140
152
  required_rubygems_version: !ruby/object:Gem::Requirement
141
153
  requirements:
142
154
  - - ">="
143
155
  - !ruby/object:Gem::Version
144
156
  version: '0'
145
157
  requirements: []
146
- rubyforge_project:
147
- rubygems_version: 2.4.6
148
- signing_key:
158
+ rubygems_version: 3.5.6
159
+ signing_key:
149
160
  specification_version: 4
150
161
  summary: Calculates XIRR (Bisection and Newton method) of a cashflow
151
162
  test_files: