mortgage_calc 0.1.6 → 0.1.7
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/Manifest +1 -0
- data/README.rdoc +2 -0
- data/Rakefile +1 -1
- data/Version.yml +1 -1
- data/features/apr.feature +7 -4
- data/lib/mortgage_calc/mortgage_util.rb +15 -15
- data/mortgage_calc.gemspec +4 -4
- data/spec/mortgage_calc/mortgage_util_spec.rb +15 -8
- metadata +4 -4
data/Manifest
CHANGED
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -10,7 +10,7 @@ require 'spec/rake/spectask'
|
|
10
10
|
|
11
11
|
Echoe.new("mortgage_calc", MortgageCalc::VERSION) do |p|
|
12
12
|
p.description = "Mortgage utilities"
|
13
|
-
p.url = "http://
|
13
|
+
p.url = "http://www.pathf.com/blogs/2010/02/mortcalc-gem/"
|
14
14
|
p.author = "Perry Hertler"
|
15
15
|
p.email = "perry@hertler.org"
|
16
16
|
p.ignore_pattern = ["tmp/*", "script/*, .idea/*"]
|
data/Version.yml
CHANGED
data/features/apr.feature
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Feature Calculate APR
|
1
|
+
Feature: Calculate APR
|
2
2
|
In order to show sorted APR search results
|
3
3
|
As a person navigating OMT
|
4
4
|
I want to see correct APRs
|
@@ -10,10 +10,13 @@ Feature Calculate APR
|
|
10
10
|
Scenarios: with APR fields
|
11
11
|
| loan_amount | fees | points | rate | period | apr |
|
12
12
|
| 125000 | 5000 | 0 | 6.5 | 360 | 6.881 |
|
13
|
-
| 125000 | 5000 | -1.25 | 6.5 | 360 | 6.
|
13
|
+
| 125000 | 5000 | -1.25 | 6.5 | 360 | 6.763 |
|
14
14
|
| 400000 | 1200 | 0 | 5.25 | 180 | 5.296 |
|
15
15
|
| 125000 | 811 | 0.375 | 6.125 | 360 | 6.221 |
|
16
|
-
| 125000 | 811 | -0.375 | 6.5 | 360 | 6.
|
16
|
+
| 125000 | 811 | -0.375 | 6.5 | 360 | 6.526 |
|
17
17
|
| 100000 | 1000 | 0 | 7.0 | 360 | 7.099 |
|
18
18
|
| 100000 | 0 | 0 | 7.0 | 360 | 7.0 |
|
19
|
-
| 250000 | 3135 | 2.125 | 6.5 | 360 | 6.822 |
|
19
|
+
| 250000 | 3135 | 2.125 | 6.5 | 360 | 6.822 |
|
20
|
+
| 80000 | 800 | 1.2 | 5.125 | 360 | 5.319 |
|
21
|
+
| 100000 | 2000 | 0 | 5.9 | 480 | 6.056 |
|
22
|
+
| 400000 | 3159 | 0 | 4.375 | 360 | 4.442 |
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module MortgageCalc
|
2
2
|
class MortgageUtil
|
3
|
-
attr_accessor :loan_amount, :interest_rate, :period, :
|
3
|
+
attr_accessor :loan_amount, :interest_rate, :period, :fees, :points
|
4
4
|
|
5
|
-
def initialize(loan_amount, interest_rate, period=360,
|
5
|
+
def initialize(loan_amount, interest_rate, period=360, fees=0, points=0.0)
|
6
6
|
self.loan_amount = Float(loan_amount.to_s)
|
7
7
|
self.interest_rate = Float(interest_rate.to_s)
|
8
8
|
self.period = Integer(period.to_s)
|
9
|
-
self.
|
9
|
+
self.fees = fees
|
10
10
|
self.points = Float(points.to_s)
|
11
11
|
end
|
12
12
|
|
@@ -15,11 +15,11 @@ module MortgageCalc
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def monthly_payment
|
18
|
-
@monthly_payment ||= calculate_monthly_payment(self.loan_amount,
|
18
|
+
@monthly_payment ||= calculate_monthly_payment(self.loan_amount, monthly_interest_rate, self.period)
|
19
19
|
end
|
20
20
|
|
21
21
|
def monthly_payment_with_fees
|
22
|
-
@monthly_payment_with_fees ||= calculate_monthly_payment(self.loan_amount + total_fees,
|
22
|
+
@monthly_payment_with_fees ||= calculate_monthly_payment(self.loan_amount + total_fees, monthly_interest_rate, self.period)
|
23
23
|
end
|
24
24
|
|
25
25
|
def total_fees
|
@@ -27,7 +27,7 @@ module MortgageCalc
|
|
27
27
|
end
|
28
28
|
|
29
29
|
private
|
30
|
-
def
|
30
|
+
def monthly_interest_rate
|
31
31
|
self.interest_rate / 100 / 12
|
32
32
|
end
|
33
33
|
|
@@ -36,36 +36,36 @@ module MortgageCalc
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def calculate_total_fees
|
39
|
-
|
40
|
-
|
39
|
+
total = self.fees + (self.loan_amount * points/100)
|
40
|
+
#fees may not be negative (borrower is not paid)
|
41
|
+
total < 0 ? 0 : total
|
41
42
|
end
|
42
43
|
|
43
44
|
# solves APR
|
44
|
-
# where a = APR/1200, N = period, P = monthly payment, C = loan_amount
|
45
45
|
# [a (1 + a)^N] / [(1 + a)^N - 1] - P/C = 0
|
46
|
+
# where a = APR/1200, N = period, P = monthly payment, C = loan_amount
|
46
47
|
# calculate APR uses the Newton-Raphson to find the root (the value for 'a' that makes f(a) = 0)
|
47
|
-
# for best performance call this with 'start'= interest rate
|
48
48
|
def calculate_apr
|
49
49
|
payment_ratio = monthly_payment_with_fees / loan_amount
|
50
50
|
f = lambda {|k| (k**(self.period + 1) - (k**self.period * (payment_ratio + 1)) + payment_ratio)}
|
51
|
-
|
51
|
+
f_deriv = lambda { |k| ((self.period + 1) * k**self.period) - (self.period * (payment_ratio + 1) * k**(self.period - 1))}
|
52
52
|
|
53
|
-
root = newton_raphson(f,
|
53
|
+
root = newton_raphson(f, f_deriv, monthly_interest_rate + 1)
|
54
54
|
100 * 12 * (root - 1).to_f
|
55
55
|
end
|
56
56
|
|
57
57
|
# if 'start' is the monthly_interest_rate, Newton Raphson will find the apr root very quickly
|
58
58
|
# k1 = k0 - f(k0)/f'(k0)
|
59
|
-
# k_plus_one = k - f(k)/
|
59
|
+
# k_plus_one = k - f(k)/f_deriv(k)
|
60
60
|
# We find the k-intercept of the tangent line at point k_plus_one and compare k to k_plus_one.
|
61
61
|
# This is repeated until a sufficiently accurate value is reached, which can be specified with the 'precision' parameter
|
62
|
-
def newton_raphson(f,
|
62
|
+
def newton_raphson(f, f_deriv, start, precision = 5)
|
63
63
|
k_plus_one = start
|
64
64
|
k = 0.0
|
65
65
|
|
66
66
|
while ((k - 1) * 10**precision).to_f.floor != ((k_plus_one - 1) * 10**precision).to_f.floor
|
67
67
|
k = k_plus_one
|
68
|
-
k_plus_one = k - f.call(k) /
|
68
|
+
k_plus_one = k - f.call(k) / f_deriv.call(k)
|
69
69
|
end
|
70
70
|
k_plus_one
|
71
71
|
end
|
data/mortgage_calc.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{mortgage_calc}
|
5
|
-
s.version = "0.1.
|
5
|
+
s.version = "0.1.7"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Perry Hertler"]
|
9
|
-
s.date = %q{2010-
|
9
|
+
s.date = %q{2010-07-07}
|
10
10
|
s.description = %q{Mortgage utilities}
|
11
11
|
s.email = %q{perry@hertler.org}
|
12
12
|
s.extra_rdoc_files = ["README.rdoc", "lib/mortgage_calc.rb", "lib/mortgage_calc/mortgage_util.rb"]
|
13
|
-
s.files = ["Manifest", "README.rdoc", "Rakefile", "Version.yml", "features/apr.feature", "features/step_definitions/apr_steps.rb", "features/support/env.rb", "lib/mortgage_calc.rb", "lib/mortgage_calc/mortgage_util.rb", "spec/mortgage_calc/mortgage_util_spec.rb", "spec/spec_helper.rb"
|
14
|
-
s.homepage = %q{http://
|
13
|
+
s.files = ["Manifest", "README.rdoc", "Rakefile", "Version.yml", "features/apr.feature", "features/step_definitions/apr_steps.rb", "features/support/env.rb", "lib/mortgage_calc.rb", "lib/mortgage_calc/mortgage_util.rb", "mortgage_calc.gemspec", "spec/mortgage_calc/mortgage_util_spec.rb", "spec/spec_helper.rb"]
|
14
|
+
s.homepage = %q{http://www.pathf.com/blogs/2010/02/mortcalc-gem/}
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Mortgage_calc", "--main", "README.rdoc"]
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
s.rubyforge_project = %q{mortgage_calc}
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require File.
|
2
|
-
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
3
2
|
module MortgageCalc
|
4
3
|
describe MortgageUtil do
|
5
4
|
def assert_monthly_apr_payment_matches(loan_amount, rate, period, fee, points)
|
@@ -15,7 +14,7 @@ module MortgageCalc
|
|
15
14
|
@mortgage_util_with_apr_as_rate = MortgageUtil.new(100000, @mortgage_util.apr, 360, 1200, 1.25)
|
16
15
|
end
|
17
16
|
it "should have proper monthly interest rate" do
|
18
|
-
@mortgage_util.send(:
|
17
|
+
@mortgage_util.send(:monthly_interest_rate).should == 0.005
|
19
18
|
end
|
20
19
|
it "should have proper monthly payment" do
|
21
20
|
@mortgage_util.monthly_payment.should be_close(599.55, 0.001)
|
@@ -35,18 +34,26 @@ module MortgageCalc
|
|
35
34
|
assert_monthly_apr_payment_matches(300000, 6.5, 360, 10000, 7.25)
|
36
35
|
end
|
37
36
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
|
38
|
+
context "net negative fees" do
|
39
|
+
before(:all) do
|
40
|
+
@mortgage_util = MortgageUtil.new(100000, 6.0, 360, 1200, -11.25)
|
41
|
+
@mortgage_util.total_fees.should be 0
|
42
|
+
end
|
43
|
+
it "calculate total fees should return 0 if total fees is less than 0" do
|
44
|
+
@mortgage_util.send(:calculate_total_fees).should be 0
|
45
|
+
end
|
46
|
+
it "should not return APR less than interest rate" do
|
47
|
+
@mortgage_util.apr.should be_close 6.0, 0.00000001
|
42
48
|
end
|
43
49
|
end
|
50
|
+
|
44
51
|
context "initialize convert to best types" do
|
45
52
|
before(:all) do
|
46
53
|
@mortgage_util = MortgageUtil.new('100000', '6.0', 360, 1200, '-1.25')
|
47
54
|
end
|
48
55
|
it "should convert rate to float if necessary" do
|
49
|
-
|
56
|
+
@mortgage_util.interest_rate.class.should == Float
|
50
57
|
end
|
51
58
|
it "should convert points to float if necessary" do
|
52
59
|
@mortgage_util.points.class.should == Float
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mortgage_calc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Perry Hertler
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-07-07 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -33,11 +33,11 @@ files:
|
|
33
33
|
- features/support/env.rb
|
34
34
|
- lib/mortgage_calc.rb
|
35
35
|
- lib/mortgage_calc/mortgage_util.rb
|
36
|
+
- mortgage_calc.gemspec
|
36
37
|
- spec/mortgage_calc/mortgage_util_spec.rb
|
37
38
|
- spec/spec_helper.rb
|
38
|
-
- mortgage_calc.gemspec
|
39
39
|
has_rdoc: true
|
40
|
-
homepage: http://
|
40
|
+
homepage: http://www.pathf.com/blogs/2010/02/mortcalc-gem/
|
41
41
|
licenses: []
|
42
42
|
|
43
43
|
post_install_message:
|