finance_math 0.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cbdffc4856090cc7d1e509ba4e9d0489017a7e44
4
- data.tar.gz: 577779f78950688be481d7446c4fda4135f4e027
3
+ metadata.gz: d9b7d65feab360a3535bf1578c17326c237249e6
4
+ data.tar.gz: 591d90ccad4311cf1fa67a5479b1a3b7995c1ca6
5
5
  SHA512:
6
- metadata.gz: 6c12c0a09ab26a16c7e8a7ef3bfa2b7964e3a284f1b371607fe7552dfc0fd90230c2b911cff9c3956534fd7ce7993b4012c820ccb03bed40d2617fd73814e26e
7
- data.tar.gz: d31f8f44e884db52c0ac328391fdf9eadcc36f33222bdab02352b079441b16186b616c0c277db5abd7027f5b2a5496ac44e2afece6741294ae13930fbd1eb2d6
6
+ metadata.gz: 9645d21dd559a86f61f55f417f1ae640581b4a96c0a99f0a75966e527612ba74a33824fc1fbc1b12194486da5d4147069367ff3025bb3287323ec32d759e73db
7
+ data.tar.gz: 3db071b7b84bd12b44fba98cbce71c97ffcca778e707839d0f1b671ea29a8591e88acc6103a7627ae89c9dd7384ff0a6facaa3b4a86105b0912a4d857add5310
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
- ![Gem Version](https://img.shields.io/badge/finance_math-0.2-blue.svg)
1
+ ![Gem Version](https://img.shields.io/badge/finance_math-1.0-blue.svg)
2
2
  [![Build Status](https://semaphoreapp.com/api/v1/projects/869d7630-55d3-46e5-9dc2-03d0d1cfecfe/363108/shields_badge.svg)](https://semaphoreapp.com/kolosek/finance_math)
3
3
  [![Code Climate](https://codeclimate.com/github/kolosek/finance_math/badges/gpa.svg)](https://codeclimate.com/github/kolosek/finance_math)
4
4
 
5
5
 
6
6
  ## What is FinanceMath?
7
7
 
8
- FinanceMath is a Ruby library for mapping Exel functions. Due to lack such libraries to handle every day need, this library is created.
8
+ FinanceMath is a Ruby library for mapping Loan based Exel functions. It deals with problem of calculating the PMT and APR functions. It implements advanced usage, taking into account bank fees, fee for for each payment and currency protection (if currency other than $ USD). Highly precise with high speed of execution.
9
9
 
10
10
  ## Installation
11
11
 
@@ -28,29 +28,47 @@ Create an instance, and pass parameters for nominal annual rate, duration (in mo
28
28
  Loan.new(10.5, 12, 15000)
29
29
  ```
30
30
 
31
+ ## Advanced Usage
32
+
33
+ Create an instance, and pass parameters for nominal annual rate, duration (in months), and amount of loan, and additional values such as bank fee, currency protection, and fee for each monthly payment.
34
+
35
+ Defaults are bank fee = 5, currency protection = 3, so please update if you need other values.
36
+
37
+ ```ruby
38
+
39
+ Loan.new(10.5, 12, 15000, 5.1, 2.75, 25)
40
+ ```
41
+
31
42
  ## Functions
32
43
 
33
44
  This is the list of available functions.
34
45
 
35
- ## PMT
46
+ ### Loan.pmt
36
47
 
37
48
  Calculates the periodic payment for an annuity investment based on constant-amount periodic payments and a constant interest rate.
38
49
 
39
50
  ```ruby
40
51
 
41
- loan = Loan.new(10.5, 12, 15000)
52
+ loan = Loan.new(10, 12, 1000)
42
53
  loan.pmt
54
+ # 87.9158872300099
55
+
43
56
  ```
44
57
 
45
- ## APR
58
+ ### Loan.apr
46
59
 
47
60
  Calculates the Annual Percentage Rate.
48
61
 
49
62
  ```ruby
50
63
 
51
- loan = Loan.new(10.5, 12, 15000)
64
+ loan = Loan.new(13, 12, 10000)
65
+ loan.apr
66
+ #29.179538647635006
52
67
 
68
+ loan = Loan.new(15, 36, 10000, 5, 3, 10)
53
69
  loan.apr
70
+ #23.964418264624054
71
+
54
72
  ```
55
73
 
56
74
  ## Contributing
@@ -65,12 +83,13 @@ loan.apr
65
83
 
66
84
  Please cover with tests your pull requests
67
85
 
68
- ## License
69
-
70
- MIT License. See LICENSE for details.
71
-
72
86
  ## Copyright
73
87
 
74
88
  Copyright (c) 2014-2015 Nebojsa Zoric, and Kolosek, Inc. (http://kolosek.com)
75
89
 
76
- For any Ruby on Rails related work, please contact directly via form on http://kolosek.com
90
+ ###Follow up @nebojsaz and @kolosek
91
+
92
+
93
+ ## License
94
+
95
+ MIT License. See LICENSE for details.
@@ -1,16 +1,16 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'finance_math/version'
4
+ require 'version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "finance_math"
8
8
  spec.version = FinanceMath::VERSION
9
9
  spec.authors = ["Nebojsa Zoric"]
10
10
  spec.email = ["office@kolosek.com"]
11
- spec.summary = %q{Finance library for Ruby.}
12
- spec.description = %q{Implementation of Loan/Mortgage functions in Ruby language}
13
- spec.homepage = ""
11
+ spec.summary = %q{Finance and mortgage library for Ruby.}
12
+ spec.description = %q{Implementation of Loan/Mortgage functions in Ruby language. APR function and PMT function. In calculations it includes implementation of bank fee, marketplace fee, fees for each payment to provide the most precise calculation at very high speed. }
13
+ spec.homepage = "http://kolosek.com/gems/finance_math"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
@@ -1,5 +1,6 @@
1
- require "finance_math/version"
1
+ require "version"
2
2
 
3
3
  module FinanceMath
4
- autoload :Loan, 'finance_math/loan'
4
+ autoload :Loan, 'finance_math/loan'
5
+ autoload :Mortgage, 'finance_math/mortgage'
5
6
  end
@@ -28,9 +28,11 @@ module FinanceMath
28
28
 
29
29
  # @return [DecNum] P principal
30
30
  # @api public
31
- attr_reader :principal
32
-
31
+ attr_reader :principal
33
32
 
33
+ # @return [Float] fee
34
+ # @api public
35
+ attr_reader :fee
34
36
 
35
37
  # create a new Loan instance
36
38
  # @return [Loan]
@@ -44,8 +46,8 @@ module FinanceMath
44
46
  # @see http://en.wikipedia.org/wiki/Nominal_interest_rate
45
47
  # @api public
46
48
 
47
- def initialize(nominal_rate, duration, amount, structure_fee=5, currency_protection=3)
48
- @nominal_rate, @amount, @duration, @structure_fee, @currency_protection = nominal_rate.to_f, amount, duration, structure_fee.to_f, currency_protection.to_f
49
+ def initialize(nominal_rate, duration, amount, structure_fee=5, currency_protection=3, fee=0)
50
+ @nominal_rate, @amount, @duration, @structure_fee, @currency_protection, @fee = nominal_rate.to_f, amount, duration, structure_fee.to_f, currency_protection.to_f, fee.to_f
49
51
  @principal = principal_calculation
50
52
  @monthly_rate = @nominal_rate / 100 / 12
51
53
  end
@@ -55,35 +57,7 @@ module FinanceMath
55
57
  end
56
58
 
57
59
  def apr
58
- pmt_base = pmt
59
- n = duration.to_f / 12
60
- q = (duration > 12) ? 12 : duration
61
- i = pmt_base * n * q / principal - 1
62
- #puts "n: #{n} q: #{q} i: #{i} pmt: #{pmt_base}"
63
- find(pmt_base, n, q, i)
64
- end
65
-
66
- def principal_base(m, n, q, i)
67
- m * ( 1 - ( 1 + ( i / q ) ) ** (- n * q) ) * q / i
68
- end
69
-
70
- def near(a, b)
71
- r = 0.1
72
- return ((a - r) < b && (a + r) > b) || ((b - r) < a && (b + r) > a)
73
- end
74
-
75
- def find(pmt_base, n, q, i)
76
- p = principal_base(pmt_base, n, q, i)
77
-
78
- return i if near(p, principal)
79
-
80
- if p < principal
81
- i -= 0.00001
82
- elsif p > principal
83
- i += 0.00001
84
- end
85
-
86
- find(pmt_base, n, q, i)
60
+ @apr ||= calculate_apr
87
61
  end
88
62
 
89
63
  protected
@@ -107,7 +81,36 @@ module FinanceMath
107
81
  private
108
82
 
109
83
  def principal_calculation
110
- amount * (1 - currency_protection/100 - structure_fee / 100 )
84
+ amount * (1 - currency_protection/100 - structure_fee / 100 ) - fee * duration
85
+ end
86
+
87
+ # solves APR
88
+ # [a (1 + a)^N] / [(1 + a)^N - 1] - P/C = 0
89
+ # where a = APR/1200, N = duration, P = monthly payment, C = loan_amount
90
+ # Newton-Raphson finds root (the value for 'a' that makes f(a) = 0)
91
+ def calculate_apr
92
+ payment_ratio = pmt / principal_calculation
93
+ duration = @duration
94
+ f = lambda {|k| (k**(duration + 1) - (k**duration * (payment_ratio + 1)) + payment_ratio)}
95
+ f_deriv = lambda { |k| ((duration + 1) * k**duration) - (duration * (payment_ratio + 1) * k**(duration - 1))}
96
+
97
+ root = newton_raphson(f, f_deriv, monthly_rate + 1)
98
+ 100 * 12 * (root -1).to_f
99
+ end
100
+
101
+ # 'start' is the monthly_rate, Newton Raphson will find the apr root very quickly
102
+ # k1 = k0 - f(k0)/f'(k0)
103
+ # k_plus_one = k - f(k)/f_deriv(k) f_deriv should be an positive number!
104
+ # We find the k-intercept of the tangent line at point k_plus_one and compare k to k_plus_one.
105
+ # This is repeated until a sufficiently accurate value is reached, which can be specified with the 'precision' parameter
106
+ def newton_raphson(f, f_deriv, start, precision = 5)
107
+ k_plus_one = start
108
+ k = 0.0
109
+ while ((k - 1) * 10**precision).to_f.floor != ((k_plus_one - 1) * 10**precision).to_f.floor
110
+ k = k_plus_one
111
+ k_plus_one = k - f.call(k) / f_deriv.call(k).abs
112
+ end
113
+ k_plus_one
111
114
  end
112
115
  end
113
116
  end
@@ -1,3 +1,3 @@
1
1
  module FinanceMath
2
- VERSION = "0.2"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -37,33 +37,73 @@ describe Loan do
37
37
  loan = Loan.new(0, 6, 10000)
38
38
  expect(loan.pmt).to eq(1666.6666666666667)
39
39
  end
40
+
41
+ it "should return correct pmt value" do
42
+ loan = Loan.new(13, 90, 1000000)
43
+ expect(loan.pmt).to eq(17449.90775727763)
44
+ end
40
45
  end
41
46
 
42
- context ".apr" do
47
+ context ".apr, edge cases" do
43
48
 
44
49
  it "should return correct apr value" do
45
- loan = Loan.new(16, 24, 10000)
46
- expect(loan.apr).to eq(0.24699853524196447)
50
+ loan = Loan.new(16, 24, 9200)
51
+ expect(loan.apr).to eq(24.699310868498614)
47
52
  end
48
53
 
49
54
  it "should return correct apr value" do
50
55
  loan = Loan.new(13, 24, 10000)
51
- expect(loan.apr).to eq(0.2159014588291408)
56
+ expect(loan.apr).to eq(21.589972932434698)
52
57
  end
53
58
 
54
59
  it "should return correct apr value" do
55
60
  loan = Loan.new(13, 18, 10000)
56
- expect(loan.apr).to eq(0.2418055150965281)
61
+ expect(loan.apr).to eq(24.1815502466296)
62
+ end
63
+
64
+ it "should return correct apr value" do
65
+ loan = Loan.new(13, 12, 10000)
66
+ expect(loan.apr).to eq(29.179538647635006)
67
+ end
68
+
69
+ it "should return correct apr value" do
70
+ loan = Loan.new(13, 6, 10000)
71
+ expect(loan.apr).to eq(42.82076503747119)
72
+ end
73
+
74
+ it "should return correct apr value" do
75
+ loan = Loan.new(13, 36, 10000)
76
+ expect(loan.apr).to eq(18.93638316167774)
77
+ end
78
+
79
+ it "should return correct apr value" do
80
+ loan = Loan.new(13, 90, 10000000)
81
+ expect(loan.apr).to eq(15.690778147507167)
82
+ end
83
+
84
+ it "should return correct apr value" do
85
+ loan = Loan.new(13, 90, 50000000)
86
+ expect(loan.apr).to eq(15.690778147507167)
87
+ end
88
+
89
+ it "should return correct apr value" do
90
+ loan = Loan.new(13, 1, 50000000)
91
+ expect(loan.apr).to eq(118.47826151517138)
57
92
  end
58
93
 
59
- # it "should return correct apr value" do
60
- # loan = Loan.new(13, 6, 10000)
61
- # expect(loan.apr).to eq(0.2418055150965281)
62
- # end
94
+ it "should return correct apr value" do
95
+ loan = Loan.new(80, 1, 1000)
96
+ expect(loan.apr).to eq(191.30434783476406)
97
+ end
63
98
 
64
- # it "should return correct apr value" do
65
- # loan = Loan.new(13, 36, 10000)
66
- # expect(loan.apr).to eq(0.2418055150965281)
67
- # end
99
+ it "should return correct apr value" do
100
+ loan = Loan.new(36, 200, 500)
101
+ expect(loan.apr).to eq(39.173057290003044)
102
+ end
103
+
104
+ it "should return correct apr value" do
105
+ loan = Loan.new(15, 36, 10000, 5, 3, 10)
106
+ expect(loan.apr).to eq(23.964418264624054)
107
+ end
68
108
  end
69
109
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finance_math
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nebojsa Zoric
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-03 00:00:00.000000000 Z
11
+ date: 2015-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,7 +52,10 @@ dependencies:
52
52
  - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- description: Implementation of Loan/Mortgage functions in Ruby language
55
+ description: 'Implementation of Loan/Mortgage functions in Ruby language. APR function
56
+ and PMT function. In calculations it includes implementation of bank fee, marketplace
57
+ fee, fees for each payment to provide the most precise calculation at very high
58
+ speed. '
56
59
  email:
57
60
  - office@kolosek.com
58
61
  executables: []
@@ -67,10 +70,10 @@ files:
67
70
  - finance_math.gemspec
68
71
  - lib/finance_math.rb
69
72
  - lib/finance_math/loan.rb
70
- - lib/finance_math/version.rb
73
+ - lib/version.rb
71
74
  - spec/lib/loan_spec.rb
72
75
  - spec/spec_helper.rb
73
- homepage: ''
76
+ homepage: http://kolosek.com/gems/finance_math
74
77
  licenses:
75
78
  - MIT
76
79
  metadata: {}
@@ -93,7 +96,7 @@ rubyforge_project:
93
96
  rubygems_version: 2.2.2
94
97
  signing_key:
95
98
  specification_version: 4
96
- summary: Finance library for Ruby.
99
+ summary: Finance and mortgage library for Ruby.
97
100
  test_files:
98
101
  - spec/lib/loan_spec.rb
99
102
  - spec/spec_helper.rb