refinance 0.0.1 → 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.
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 reInteractive
1
+ Copyright (c) 2012-2013 reInteractive Pty Ltd
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -5,15 +5,17 @@ Currently, it contains algorithms for calculating the properties of ordinary
5
5
  annuities: principal, interest rate, number of payment periods, and payment
6
6
  amount.
7
7
 
8
- The algorithms are simple rather than fast. At present, they deal only with
9
- _annuities immediate_ (in which the interest is accumulated _before_ the
10
- payment), not _annuities due_ (in which the interest is accumulated _after_ the
11
- payment). There are many opportunities for extension and improvement.
8
+ The algorithms are simple rather than fast and numerically robust. Thanks to
9
+ duck typing, they work with both BigDecimals and Floats. At present, they deal
10
+ only with _annuities immediate_ (in which the interest is accumulated _before_
11
+ the payment), not _annuities due_ (in which the interest is accumulated _after_
12
+ the payment). There are many opportunities for extension and improvement.
12
13
 
13
14
  ## Requirements
14
15
 
15
- This library requires Ruby 1.9.3 or newer. (However, it will work with Ruby
16
- 1.9.2 if you only use Float, not BigDecimal, for floating-point values.)
16
+ This library is tested with versions 1.9.3 and 2.0.0 of MRI (Matz's Ruby
17
+ Interpreter). It also works with version 1.9.2 if you only use Float, not
18
+ BigDecimal, for floating-point values.
17
19
 
18
20
  ## Installation
19
21
 
@@ -1,3 +1,3 @@
1
1
  module Refinance
2
- VERSION = "0.0.1"
2
+ VERSION = "1.0.0"
3
3
  end
data/refinance.gemspec CHANGED
@@ -19,6 +19,6 @@ Gem::Specification.new do |gem|
19
19
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
20
  gem.require_paths = ["lib"]
21
21
 
22
- gem.add_development_dependency 'rake', '0.9.2.2'
23
- gem.add_development_dependency 'minitest', '3.5.0'
22
+ gem.add_development_dependency 'rake', '10.0.4'
23
+ gem.add_development_dependency 'minitest', '4.7.4'
24
24
  end
@@ -1,109 +1,62 @@
1
- require 'minitest/autorun'
1
+ require 'test_helper'
2
2
  require 'bigdecimal'
3
- require 'refinance'
4
3
 
5
- class BigDecimalAnnuitiesTest < MiniTest::Unit::TestCase
4
+ class BigDecimalAnnuitiesTest < AnnuitiesTest
6
5
 
7
6
  def test_improve_interest_rate
8
7
  # Based on Example 6 in http://oakroadsystems.com/math/loan.htm .
9
- payment = BigDecimal.new('291')
10
- periods = BigDecimal.new('48')
11
- principal = BigDecimal.new('11200')
12
- guess = BigDecimal.new('0.01')
13
-
14
- expected = BigDecimal.new('0.0094295242')
15
- actual = Refinance::Annuities.improve_interest_rate(payment, periods,
16
- principal, guess)
17
-
18
- assert_in_delta expected, actual, BigDecimal.new('0.00000001')
8
+ assert_improve_interest_rate payment: BigDecimal.new('291'),
9
+ periods: BigDecimal.new('48'), principal: BigDecimal.new('11200'),
10
+ guess: BigDecimal.new('0.01'), expected: BigDecimal.new('0.0094295242'),
11
+ delta: BigDecimal.new('0.00000001')
19
12
  end
20
13
 
21
14
  def test_interest_rate_stops_if_improvement_is_small
22
15
  # Based on Example 6 in http://oakroadsystems.com/math/loan.htm .
23
- payment = BigDecimal.new('291')
24
- periods = BigDecimal.new('48')
25
- principal = BigDecimal.new('11200')
26
- guess = BigDecimal.new('0.01')
27
- imprecision = BigDecimal.new('0.5')
28
-
29
- expected = BigDecimal.new('0.0094295242')
30
- actual = Refinance::Annuities.interest_rate(payment, periods, principal,
31
- guess, imprecision)
32
-
33
- assert_in_delta expected, actual, BigDecimal.new('0.00000001')
34
- end
35
-
36
- def test_interest_rate_stops_if_max_iterations_reached
37
- extreme_precision = BigDecimal.new('0')
38
- guess = BigDecimal.new('0.01')
39
-
40
- expected = guess
41
- actual = Refinance::Annuities.interest_rate(0, 0, 0, guess,
42
- extreme_precision, 1, 0)
43
-
44
- assert_equal expected, actual
16
+ assert_interest_rate_stops_if_improvement_is_small \
17
+ payment: BigDecimal.new('291'), periods: BigDecimal.new('48'),
18
+ principal: BigDecimal.new('11200'), guess: BigDecimal.new('0.01'),
19
+ precision: BigDecimal.new('0.5'),
20
+ expected: BigDecimal.new('0.0094295242'),
21
+ delta: BigDecimal.new('0.00000001')
45
22
  end
46
23
 
47
24
  def test_interest_rate_does_multiple_iterations
48
25
  # Based on Example 6 in http://oakroadsystems.com/math/loan.htm .
49
- payment = BigDecimal.new('291')
50
- periods = BigDecimal.new('48')
51
- principal = BigDecimal.new('11200')
52
- guess = BigDecimal.new('0.01')
53
- extreme_precision = BigDecimal.new('0')
54
- max_iterations = 4
55
-
56
- expected = BigDecimal.new('0.0094007411')
57
- actual = Refinance::Annuities.interest_rate(payment, periods, principal,
58
- guess, extreme_precision, 10, 4)
59
-
60
- assert_in_delta expected, actual, BigDecimal.new('0.0000000001')
26
+ assert_interest_rate_does_multiple_iterations \
27
+ payment: BigDecimal.new('291'), periods: BigDecimal.new('48'),
28
+ principal: BigDecimal.new('11200'), guess: BigDecimal.new('0.01'),
29
+ precision: BigDecimal.new('0'), max_decimals: 10, max_iterations: 4,
30
+ expected: BigDecimal.new('0.0094007411'),
31
+ delta: BigDecimal.new('0.0000000001')
61
32
  end
62
33
 
63
34
  def test_payment
64
35
  # Based on Example 2 in http://oakroadsystems.com/math/loan.htm .
65
- interest_rate = BigDecimal.new('0.0065')
66
- periods = BigDecimal.new('360')
67
- principal = BigDecimal.new('225000')
68
-
69
- expected = BigDecimal.new('1619.708627')
70
- actual = Refinance::Annuities.payment(interest_rate, periods, principal)
71
-
72
- assert_in_delta expected, actual, BigDecimal.new('0.000001')
36
+ assert_payment interest_rate: BigDecimal.new('0.0065'),
37
+ periods: BigDecimal.new('360'), principal: BigDecimal.new('225000'),
38
+ expected: BigDecimal.new('1619.708627'),
39
+ delta: BigDecimal.new('0.000001')
73
40
  end
74
41
 
75
42
  def test_periods
76
43
  # Based on Example 3 in http://oakroadsystems.com/math/loan.htm .
77
- interest_rate = BigDecimal.new('0.005')
78
- payment = BigDecimal.new('100')
79
- principal = BigDecimal.new('3500')
80
-
81
- expected = BigDecimal.new('38.57')
82
- actual = Refinance::Annuities.periods(interest_rate, payment, principal)
83
-
84
- assert_in_delta expected, actual, BigDecimal.new('0.01')
44
+ assert_periods interest_rate: BigDecimal.new('0.005'),
45
+ payment: BigDecimal.new('100.0'), principal: BigDecimal.new('3500.0'),
46
+ expected: BigDecimal.new('38.57'), delta: BigDecimal.new('0.01')
85
47
  end
86
48
 
87
49
  def test_principal
88
50
  # Based on Example 5 in http://oakroadsystems.com/math/loan.htm .
89
- interest_rate = BigDecimal.new('0.014083')
90
- payment = BigDecimal.new('60')
91
- periods = BigDecimal.new('36')
92
-
93
- expected = BigDecimal.new('1685.26') # Example fudges to 1685.25.
94
- actual = Refinance::Annuities.principal(interest_rate, payment, periods)
95
-
96
- assert_in_delta expected, actual, BigDecimal.new('0.01')
51
+ assert_principal interest_rate: BigDecimal.new('0.014083'),
52
+ payment: BigDecimal.new('60'), periods: BigDecimal.new('36'),
53
+ expected: BigDecimal.new('1685.26'), delta: BigDecimal.new('0.01')
97
54
  end
98
55
 
99
56
  def test_effective_interest_rate
100
- nominal_annual_interest_rate = BigDecimal.new('0.1')
101
- compounding_periods_per_year = BigDecimal.new('12')
102
-
103
- expected = BigDecimal.new('0.10471')
104
- actual = Refinance::Annuities.effective_interest_rate(
105
- nominal_annual_interest_rate, compounding_periods_per_year)
106
-
107
- assert_in_delta expected, actual, BigDecimal.new('0.00001')
57
+ assert_effective_interest_rate \
58
+ nominal_annual_interest_rate: BigDecimal.new('0.1'),
59
+ compounding_periods_per_year: BigDecimal.new('12'),
60
+ expected: BigDecimal.new('0.10471'), delta: BigDecimal.new('0.00001')
108
61
  end
109
62
  end
@@ -1,108 +1,48 @@
1
- require 'minitest/autorun'
2
- require 'refinance'
1
+ require 'test_helper'
3
2
 
4
- class FloatAnnuitiesTest < MiniTest::Unit::TestCase
3
+ class FloatAnnuitiesTest < AnnuitiesTest
5
4
 
6
5
  def test_improve_interest_rate
7
6
  # Based on Example 6 in http://oakroadsystems.com/math/loan.htm .
8
- payment = 291.0
9
- periods = 48.0
10
- principal = 11200.0
11
- guess = 0.01
12
-
13
- expected = 0.0094295242
14
- actual = Refinance::Annuities.improve_interest_rate(payment, periods,
15
- principal, guess)
16
-
17
- assert_in_delta expected, actual, 0.00000001
7
+ assert_improve_interest_rate payment: 291.0, periods: 48.0,
8
+ principal: 11200.0, guess: 0.01, expected: 0.0094295242,
9
+ delta: 0.00000001
18
10
  end
19
11
 
20
12
  def test_interest_rate_stops_if_improvement_is_small
21
13
  # Based on Example 6 in http://oakroadsystems.com/math/loan.htm .
22
- payment = 291.0
23
- periods = 48.0
24
- principal = 11200.0
25
- guess = 0.01
26
- imprecision = 0.5
27
-
28
- expected = 0.0094295242
29
- actual = Refinance::Annuities.interest_rate(payment, periods, principal,
30
- guess, imprecision)
31
-
32
- assert_in_delta expected, actual, 0.00000001
33
- end
34
-
35
- def test_interest_rate_stops_if_max_iterations_reached
36
- extreme_precision = 0.0
37
- guess = 0.01
38
-
39
- expected = guess
40
- actual = Refinance::Annuities.interest_rate(0, 0, 0, guess,
41
- extreme_precision, 1, 0)
42
-
43
- assert_equal expected, actual
14
+ assert_interest_rate_stops_if_improvement_is_small payment: 291.0,
15
+ periods: 48.0, principal: 11200.0, guess: 0.01, precision: 0.5,
16
+ expected: 0.0094295242, delta: 0.00000001
44
17
  end
45
18
 
46
19
  def test_interest_rate_does_multiple_iterations
47
20
  # Based on Example 6 in http://oakroadsystems.com/math/loan.htm .
48
- payment = 291.0
49
- periods = 48.0
50
- principal = 11200.0
51
- guess = 0.01
52
- extreme_precision = 0.0
53
- max_iterations = 4
54
-
55
- expected = 0.0094007411
56
- actual = Refinance::Annuities.interest_rate(payment, periods, principal,
57
- guess, extreme_precision, 10, 4)
58
-
59
- assert_in_delta expected, actual, 0.0000000001
21
+ assert_interest_rate_does_multiple_iterations payment: 291.0,
22
+ periods: 48.0, principal: 11200.0, guess: 0.01, precision: 0.0,
23
+ max_decimals: 10, max_iterations: 4, expected: 0.0094007411,
24
+ delta: 0.0000000001
60
25
  end
61
26
 
62
27
  def test_payment
63
- # Based on Example 2 in http://oakroadsystems.com/math/loan.htm .
64
- interest_rate = 0.0065
65
- periods = 360.0
66
- principal = 225000.0
67
-
68
- expected = 1619.708627
69
- actual = Refinance::Annuities.payment(interest_rate, periods, principal)
70
-
71
- assert_in_delta expected, actual, 0.000001
28
+ assert_payment interest_rate: 0.0065, periods: 360.0, principal: 225000.0,
29
+ expected: 1619.708627, delta: 0.000001
72
30
  end
73
31
 
74
32
  def test_periods
75
33
  # Based on Example 3 in http://oakroadsystems.com/math/loan.htm .
76
- interest_rate = 0.005
77
- payment = 100.0
78
- principal = 3500.0
79
-
80
- expected = 38.57
81
- actual = Refinance::Annuities.periods(interest_rate, payment, principal)
82
-
83
- assert_in_delta expected, actual, 0.01
34
+ assert_periods interest_rate: 0.005, payment: 100.0, principal: 3500.0,
35
+ expected: 38.57, delta: 0.01
84
36
  end
85
37
 
86
38
  def test_principal
87
39
  # Based on Example 5 in http://oakroadsystems.com/math/loan.htm .
88
- interest_rate = 0.014083
89
- payment = 60.0
90
- periods = 36.0
91
-
92
- expected = 1685.26 # Example fudges to 1685.25.
93
- actual = Refinance::Annuities.principal(interest_rate, payment, periods)
94
-
95
- assert_in_delta expected, actual, 0.01
40
+ assert_principal interest_rate: 0.014083, payment: 60.0, periods: 36.0,
41
+ expected: 1685.26, delta: 0.01
96
42
  end
97
43
 
98
44
  def test_effective_interest_rate
99
- nominal_annual_interest_rate = 0.1
100
- compounding_periods_per_year = 12.0
101
-
102
- expected = 0.10471
103
- actual = Refinance::Annuities.effective_interest_rate(
104
- nominal_annual_interest_rate, compounding_periods_per_year)
105
-
106
- assert_in_delta expected, actual, 0.00001
45
+ assert_effective_interest_rate nominal_annual_interest_rate: 0.1,
46
+ compounding_periods_per_year: 12.0, expected: 0.10471, delta: 0.00001
107
47
  end
108
48
  end
@@ -1,7 +1,6 @@
1
- require 'minitest/autorun'
2
- require 'refinance'
1
+ require 'test_helper'
3
2
 
4
- class RefinanceTest < MiniTest::Unit::TestCase
3
+ class RefinanceTest < Minitest::Unit::TestCase
5
4
  def test_refinance_is_a_module
6
5
  assert_kind_of Module, ::Refinance
7
6
  end
@@ -9,4 +8,11 @@ class RefinanceTest < MiniTest::Unit::TestCase
9
8
  def test_version_is_a_string
10
9
  assert_kind_of String, ::Refinance::VERSION
11
10
  end
11
+
12
+ def test_interest_rate_stops_if_max_iterations_reached
13
+ expected = 0.42
14
+ actual = Refinance::Annuities.interest_rate(0, 0, 0, expected, 0, 1, 0)
15
+
16
+ assert_equal expected, actual
17
+ end
12
18
  end
@@ -0,0 +1,60 @@
1
+ require 'minitest/autorun'
2
+ require 'refinance'
3
+
4
+ class AnnuitiesTest < Minitest::Unit::TestCase
5
+ def assert_improve_interest_rate options
6
+ actual = Refinance::Annuities.improve_interest_rate(
7
+ options.fetch(:payment),
8
+ options.fetch(:periods),
9
+ options.fetch(:principal),
10
+ options.fetch(:guess))
11
+
12
+ assert_in_delta options.fetch(:expected), actual, options.fetch(:delta)
13
+ end
14
+
15
+ def assert_interest_rate_stops_if_improvement_is_small options
16
+ actual = Refinance::Annuities.interest_rate(options.fetch(:payment),
17
+ options.fetch(:periods), options.fetch(:principal),
18
+ options.fetch(:guess), options.fetch(:precision))
19
+
20
+ assert_in_delta options.fetch(:expected), actual, options.fetch(:delta)
21
+ end
22
+
23
+ def assert_interest_rate_does_multiple_iterations options
24
+ actual = Refinance::Annuities.interest_rate(options.fetch(:payment),
25
+ options.fetch(:periods), options.fetch(:principal),
26
+ options.fetch(:guess), options.fetch(:precision),
27
+ options.fetch(:max_decimals), options.fetch(:max_iterations))
28
+
29
+ assert_in_delta options.fetch(:expected), actual, options.fetch(:delta)
30
+ end
31
+
32
+ def assert_payment options
33
+ actual = Refinance::Annuities.payment(options.fetch(:interest_rate),
34
+ options.fetch(:periods), options.fetch(:principal))
35
+
36
+ assert_in_delta options.fetch(:expected), actual, options.fetch(:delta)
37
+ end
38
+
39
+ def assert_periods options
40
+ actual = Refinance::Annuities.periods(options.fetch(:interest_rate),
41
+ options.fetch(:payment), options.fetch(:principal))
42
+
43
+ assert_in_delta options.fetch(:expected), actual, options.fetch(:delta)
44
+ end
45
+
46
+ def assert_principal options
47
+ actual = Refinance::Annuities.principal(options.fetch(:interest_rate),
48
+ options.fetch(:payment), options.fetch(:periods))
49
+
50
+ assert_in_delta options.fetch(:expected), actual, options.fetch(:delta)
51
+ end
52
+
53
+ def assert_effective_interest_rate options
54
+ actual = Refinance::Annuities.effective_interest_rate(
55
+ options.fetch(:nominal_annual_interest_rate),
56
+ options.fetch(:compounding_periods_per_year))
57
+
58
+ assert_in_delta options.fetch(:expected), actual, options.fetch(:delta)
59
+ end
60
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: refinance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-27 00:00:00.000000000 Z
12
+ date: 2013-05-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - '='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.9.2.2
21
+ version: 10.0.4
22
22
  type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - '='
28
28
  - !ruby/object:Gem::Version
29
- version: 0.9.2.2
29
+ version: 10.0.4
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: minitest
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - '='
36
36
  - !ruby/object:Gem::Version
37
- version: 3.5.0
37
+ version: 4.7.4
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - '='
44
44
  - !ruby/object:Gem::Version
45
- version: 3.5.0
45
+ version: 4.7.4
46
46
  description: A collection of finance algorithms related to annuities.
47
47
  email:
48
48
  - enquiries@reinteractive.net
@@ -62,6 +62,7 @@ files:
62
62
  - test/bigdecimal_annuities_test.rb
63
63
  - test/float_annuities_test.rb
64
64
  - test/refinance_test.rb
65
+ - test/test_helper.rb
65
66
  homepage: https://github.com/reinteractive-open/refinance
66
67
  licenses:
67
68
  - MIT
@@ -83,10 +84,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
84
  version: '0'
84
85
  segments:
85
86
  - 0
86
- hash: 803431032426501235
87
+ hash: 1916847891747794597
87
88
  requirements: []
88
89
  rubyforge_project:
89
- rubygems_version: 1.8.24
90
+ rubygems_version: 1.8.25
90
91
  signing_key:
91
92
  specification_version: 3
92
93
  summary: Simple annuity algorithms
@@ -94,3 +95,4 @@ test_files:
94
95
  - test/bigdecimal_annuities_test.rb
95
96
  - test/float_annuities_test.rb
96
97
  - test/refinance_test.rb
98
+ - test/test_helper.rb