time_value 0.1.2 → 1.0.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
2
  SHA1:
3
- metadata.gz: b8d062fe004503ddf10aa4868b97ae5de157d066
4
- data.tar.gz: 1bb4988314cb5add83dc1961c433e69933b93bdf
3
+ metadata.gz: 0c6e6b94a394a16cbd8e93aa1af3110fccff9377
4
+ data.tar.gz: 032d98858c34aa563b7d1e7a1407c9fefd6673d7
5
5
  SHA512:
6
- metadata.gz: e9af1844641632a746306d97b8739f08c51ac39fb32934c98c6037a546af7aab600da7cd51ee0806c6ea6dd2822f1a870c1009e36d1521fe9548852f3138e250
7
- data.tar.gz: df779a51ed6d53b9192c33a0fd9f8fda36e5cdd7ddf65d6715d47a99497c95d01e9820e8d6bc8b74b669683154f79ea5652566942bba3d320593ff0a6f4954a4
6
+ metadata.gz: db23d74db7237412e2bc019cfa4859b1239db26d32fabcb1bdd4ebd3dc7b789d7916e5f93d9702fe92f877ad6b26b106e37d95ca77346fe24d8b7c65c7d03be4
7
+ data.tar.gz: 2561d85d74677bbc4a3e77d37716bc8573219e5fb047494e4d632a00e51402b567b6544232b84f3cb7bf41782de4a4d4ecc9240dee7268767045ee5c48696dd0
data/lib/solver.rb CHANGED
@@ -3,20 +3,19 @@ class Solver
3
3
  INTERVAL = 10 ** (-1 * PRECISION)
4
4
  MAX_ITERATIONS = 20
5
5
  attr_reader :time_value, :goal
6
- attr_accessor :guess, :lower_bound, :upper_bound, :upper_cap_met
6
+ attr_accessor :lower_bound, :upper_bound, :upper_cap_met
7
7
 
8
- def initialize(time_value, guess = 10.00, lower_bound = 0.00, upper_bound = 10.00)
9
- @upper_bound = upper_bound
8
+ def initialize(time_value:, lower_bound: 0.00, upper_bound: nil, guess: 0.00)
9
+ @upper_bound = upper_bound || guess
10
10
  @lower_bound = lower_bound
11
- @guess = guess
12
- @time_value = time_value
11
+ @time_value = time_value.dup
12
+ @time_value.i = guess
13
13
  @goal = time_value.fv
14
14
  @upper_cap_met = false
15
15
  end
16
16
 
17
17
  def solve!
18
18
  iteration_count = 0
19
- time_value.i = guess
20
19
  while (upper_bound - lower_bound).round(PRECISION) > INTERVAL &&
21
20
  iteration_count < MAX_ITERATIONS
22
21
  iteration_count += 1
@@ -25,22 +24,33 @@ class Solver
25
24
  rescue FloatDomainError
26
25
  return nil
27
26
  end
28
- adjust_bounds(result)
29
- time_value.i = guess
27
+ adjust_bounds!(result)
28
+ time_value.i = new_guess
30
29
  end
31
- guess.round(2) if iteration_count < MAX_ITERATIONS
30
+ # TODO: This will not handle the case where the 20th iteration
31
+ # finds the solution
32
+ rate if iteration_count < MAX_ITERATIONS
32
33
  end
33
34
 
34
- def adjust_bounds(result)
35
+ private
36
+
37
+ def adjust_bounds!(result)
35
38
  if result > goal
36
39
  # interest rate too high
37
40
  self.upper_cap_met = true
38
- self.upper_bound = guess
41
+ self.upper_bound = rate
39
42
  elsif result < goal
40
43
  # interest rate too low
41
44
  self.upper_bound *= 2 unless upper_cap_met
42
- self.lower_bound = guess
45
+ self.lower_bound = rate
43
46
  end
44
- self.guess = ((upper_bound + lower_bound) / 2).round(PRECISION)
47
+ end
48
+
49
+ def new_guess
50
+ ((upper_bound + lower_bound) / 2).round(PRECISION)
51
+ end
52
+
53
+ def rate
54
+ time_value.i.round(2)
45
55
  end
46
56
  end
data/lib/time_value.rb CHANGED
@@ -1,53 +1,52 @@
1
1
  require 'solver'
2
2
 
3
3
  class TimeValue
4
-
5
- attr_accessor :n, :i, :pv, :pmt, :fv
6
-
7
- def initialize(n = 0, i = 0, pv = 0.0, pmt = 0.0, fv = 0.0)
8
- @n = n
9
- @i = i.to_f
10
- @pv = pv.to_f
11
- @pmt = pmt.to_f
12
- @fv = fv.to_f
13
- end
14
-
15
- #Base formula, ordinary annuity: -PV = [FV/((1+i)^n)] + (PMT/i)*[1-(1/(1+i)^n)]
16
- def calc_pv()
17
- i = @i / 100.0
18
- #Initial contribution
19
- pvf = @fv / ((1 + i) ** @n)
20
- #Present value of annuity
21
- pva = (@pmt/i) * (1-(1/((1+i)**@n)))
22
- @pv = (pvf + pva) * (-1)
23
- #Round
24
- @pv = (@pv*100).round / 100.0
25
- end
26
-
27
- def calc_fv()
28
- i = @i / 100.0
29
- #Growth of initial contribution
30
- fvp = @pv * ((1 + i) ** @n)
31
- #Growth of payments
32
- fva = @pmt * (((1 + i) ** @n)-1) / i
33
- @fv = (fvp + fva) * (-1)
34
- #Round
35
- @fv = (@fv*100).round / 100.0
36
- end
37
-
38
- def calc_n()
39
- i = @i / 100.0
40
- @n = (Math.log((@pmt - (i * @fv))/(@pmt + (i * @pv)))/Math.log(1 + i)).round(0)
41
- end
42
-
43
- def calc_pmt()
44
- i = @i / 100.0
45
- @pmt = (-i*(@fv+(@pv*((1+i)**n))))/(((1+i)**n)-1)
46
- @pmt = (@pmt*100).round / 100.0
47
- end
48
-
49
- def calc_i(guess = 10.0)
50
- solver = Solver.new(self, 10.00, 0.00, 10.00)
51
- solver.solve!
52
- end
4
+ attr_accessor :n, :i, :pv, :pmt, :fv
5
+
6
+ def initialize(n: 0, i: 0, pv: 0.0, pmt: 0.0, fv: 0.0)
7
+ @n = n
8
+ @i = i.to_f
9
+ @pv = pv.to_f
10
+ @pmt = pmt.to_f
11
+ @fv = fv.to_f
12
+ end
13
+
14
+ #Base formula, ordinary annuity: -PV = [FV/((1+i)^n)] + (PMT/i)*[1-(1/(1+i)^n)]
15
+ def calc_pv()
16
+ i = @i / 100.0
17
+ #Initial contribution
18
+ pvf = @fv / ((1 + i) ** @n)
19
+ #Present value of annuity
20
+ pva = (@pmt/i) * (1-(1/((1+i)**@n)))
21
+ @pv = (pvf + pva) * (-1)
22
+ #Round
23
+ @pv = (@pv*100).round / 100.0
24
+ end
25
+
26
+ def calc_fv()
27
+ i = @i / 100.0
28
+ #Growth of initial contribution
29
+ fvp = @pv * ((1 + i) ** @n)
30
+ #Growth of payments
31
+ fva = @pmt * (((1 + i) ** @n)-1) / i
32
+ @fv = (fvp + fva) * (-1)
33
+ #Round
34
+ @fv = (@fv*100).round / 100.0
35
+ end
36
+
37
+ def calc_n()
38
+ i = @i / 100.0
39
+ @n = (Math.log((@pmt - (i * @fv))/(@pmt + (i * @pv)))/Math.log(1 + i)).round(0)
40
+ end
41
+
42
+ def calc_pmt()
43
+ i = @i / 100.0
44
+ @pmt = (-i*(@fv+(@pv*((1+i)**n))))/(((1+i)**n)-1)
45
+ @pmt = (@pmt*100).round / 100.0
46
+ end
47
+
48
+ def calc_i(guess: 10.0)
49
+ solver = Solver.new(time_value: self, lower_bound: 0.00, guess: 10.00)
50
+ solver.solve!
51
+ end
53
52
  end
@@ -1,3 +1,3 @@
1
1
  module TimeValue
2
- VERSION = '0.1.2'
2
+ VERSION = '1.0.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: time_value
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Randall Reed, Jr.