refinance 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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