financial_calculator 3.0.0 → 3.1.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
  SHA256:
3
- metadata.gz: 5f0d684ffcf8cd34cdad09576834da2057e6879b45af1484123474b6e151baad
4
- data.tar.gz: eccae432dc2cca2470cf1023871c0d9cb58620b080715c8ed00c818a62e4d2b4
3
+ metadata.gz: 7ece241c288b5547ac0946a57d3488646427c41744219e0a7f2d86a164a8e088
4
+ data.tar.gz: b8fa7e3149792486255d06c54b53998e5f1846fe013d1152d511642349e5080c
5
5
  SHA512:
6
- metadata.gz: 5715ae679ff1cc465004bf136989bdee35ce1d60c3c1a21cf6daac07ec4ecbe71f1db8f04ff26d8b3e57a525394e7508601c96be5c5923e443b6504014c94325
7
- data.tar.gz: 449cdc6640b282aea1e34a3de372717986232474310101bcf4097ecbbfac6021087aa26d1b4b429ab017239f40bd337c993f91675f3f7f9823920a1243c7bc70
6
+ metadata.gz: 880f9c1d6b98aadc025c246ba46e88b4f09928c92d395f59bfccb816796c806e2d1a9e3ce1358bf0c6ae288f4068c92bf9c466cd5d8013e68ff675a33dd0d6a4
7
+ data.tar.gz: bc10cbf71ecc8478778b46f61cbd25adbebb79dc074203200a14d31688ea6c4cf123cf728957a0f3c6a99e300648d15cf52718dee74fc395eb23128953dcd499
data/CHANGELOG.md CHANGED
@@ -6,9 +6,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [3.1.0] - 2018-05-20
10
+ ### Added
11
+ - New class for PMT calculation (FinancialCalculator::Pmt)
12
+
13
+ ### Removed
14
+
15
+ ### Changed
16
+
9
17
  ## [3.0.0] - 2018-05-12
10
18
  ### Added
11
- - New class for Present Value calculation (FinancialCalculator::PV)
19
+ - New class for Present Value calculation (FinancialCalculator::Pv)
12
20
 
13
21
  ### Removed
14
22
  - Monkey patched cashflow methods on Array
data/README.md CHANGED
@@ -107,11 +107,12 @@ You can also increase your payment to a specific amount:
107
107
  >> extra_payments_2 = 250000.amortize(rate){ -1500 }
108
108
 
109
109
  ## SUPPORTED STANDARD CALCUALTIONS
110
- - PV
111
- - NPV
112
- - XNPV
113
110
  - IRR
111
+ - NPV
112
+ - PMT
113
+ - PV
114
114
  - XIRR
115
+ - XNPV
115
116
 
116
117
  ## FEATURES
117
118
 
@@ -8,6 +8,7 @@ require 'flt/d'
8
8
  # * *principal* represents the outstanding balance of a loan or annuity.
9
9
  # * *rate* represents the interest rate _per period_.
10
10
  module FinancialCalculator
11
+ require 'financial_calculator/validator'
11
12
  require 'financial_calculator/amortization'
12
13
  require 'financial_calculator/rates'
13
14
  require 'financial_calculator/transaction'
@@ -16,4 +17,5 @@ module FinancialCalculator
16
17
  require 'financial_calculator/npv'
17
18
  require 'financial_calculator/xnpv'
18
19
  require 'financial_calculator/xirr'
20
+ require 'financial_calculator/pmt'
19
21
  end
@@ -0,0 +1,67 @@
1
+ module FinancialCalculator
2
+ # Calculates the payment of an ordinary annuity
3
+ class Pmt
4
+ include ::Validator
5
+
6
+ # @return [Numeric] The rate used for calculating the payment amount
7
+ # @api public
8
+ attr_reader :rate
9
+
10
+ # @return [Numeric] The number of payments to be made
11
+ # @api public
12
+ attr_reader :num_periods
13
+
14
+ # @return [Numeric] The current value of the annuity
15
+ # @api public
16
+ attr_reader :present_value
17
+
18
+ # @return [Numeric] The ending value of the annuity. Defaults to 0
19
+ # @api public
20
+ attr_reader :future_value
21
+
22
+ # @return [Boolean] Whether the payment is made at the beginning of the
23
+ # period (true) or end of the period (false)
24
+ # @api public
25
+ attr_reader :pay_at_beginning
26
+
27
+ # @return [DecNum] Result of the PMT calculation
28
+ # @api public
29
+ attr_reader :result
30
+
31
+ # Create a new object for calculating the periodic payment of an ordinary annuity
32
+ # @param [Numeric] rate The discount (interest) rate
33
+ # @param [Numeric] num_periods The number of payments to be made
34
+ # @param [Numeric] present_value The current value of the annuity
35
+ # @param [Numeric] future_value The ending value of the annuity
36
+ # @param [Boolean] pay_at_beginning. Whether the payment is made at the beginning
37
+ # of the period (true) or end of the period (false)
38
+ # @return [FinancialCalculator::Npv] An instance of a PMT calculation
39
+ def initialize(rate, num_periods, present_value, future_value = 0, pay_at_beginning = false)
40
+ validate_numerics(rate: rate, num_periods: num_periods, present_value: present_value, future_value: future_value)
41
+
42
+ @rate = Flt::DecNum(rate.to_s)
43
+ @num_periods = Flt::DecNum(num_periods.to_s)
44
+ @present_value = Flt::DecNum(present_value.to_s)
45
+ @future_value = Flt::DecNum(future_value || "0")
46
+ @pay_at_beginning = pay_at_beginning || false
47
+ @result = solve(@rate, @num_periods, @present_value, @future_value, @pay_at_beginning)
48
+ end
49
+
50
+ # @return [Boolean] Whether the payments are made at the beginning of each period
51
+ # @api public
52
+ def pays_at_beginning?
53
+ @pay_at_beginning
54
+ end
55
+
56
+ def inspect
57
+ "PMT(#{result})"
58
+ end
59
+
60
+ private
61
+
62
+ def solve(i, nper, pv, fv, pay_at_beginning)
63
+ type = pay_at_beginning ? 1 : 0
64
+ @result = ((pv * (1 + i) ** nper) + fv) * i / ((1 + i * type) * (1 - (1 + i) ** nper))
65
+ end
66
+ end
67
+ end
@@ -1,6 +1,7 @@
1
1
  module FinancialCalculator
2
2
  # Calculate the future value of a series of equal of payments
3
3
  class Pv
4
+ include ::Validator
4
5
 
5
6
  # @return [Numeric] The discount rate used in the calculation
6
7
  attr_reader :rate
@@ -71,14 +72,6 @@ module FinancialCalculator
71
72
  return 0 if amount.zero?
72
73
  amount / (1 + rate) ** periods
73
74
  end
74
-
75
- def validate_numerics(numerics)
76
- numerics.each do |key, value|
77
- unless value.is_a? Numeric
78
- raise ArgumentError.new("#{key} must be a type of Numeric. Got #{value.class} instead.")
79
- end
80
- end
81
- end
82
75
  end
83
76
 
84
77
  PresentValue = Pv
@@ -0,0 +1,10 @@
1
+ module Validator
2
+ protected
3
+ def validate_numerics(numerics)
4
+ numerics.each do |key, value|
5
+ unless value.is_a? Numeric
6
+ raise ArgumentError.new("#{key} must be a type of Numeric. Got #{value.class} instead.")
7
+ end
8
+ end
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module FinancialCalculator
2
- VERSION = '3.0.0'
2
+ VERSION = '3.1.0'
3
3
  end
data/spec/pmt_spec.rb ADDED
@@ -0,0 +1,71 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe "Pmt" do
4
+ let(:rate) { 0.1 }
5
+ let(:present_value) { 1000 }
6
+ let(:num_periods) { 20 }
7
+ let(:future_value) { 0 }
8
+ let(:pay_at_beginning) { false }
9
+ let(:pmt) { Pmt.new(rate, num_periods, present_value, future_value, pay_at_beginning) }
10
+
11
+ subject { pmt }
12
+
13
+ it 'has a rate attribute' do
14
+ expect(subject).to have_attributes(rate: rate)
15
+ end
16
+
17
+ it 'has a num_periods attribute' do
18
+ expect(subject).to have_attributes(num_periods: num_periods)
19
+ end
20
+
21
+ it 'has a present_value attribute' do
22
+ expect(subject).to have_attributes(present_value: present_value)
23
+ end
24
+
25
+ it 'has a future_value attribute' do
26
+ expect(subject).to have_attributes(future_value: future_value)
27
+ end
28
+
29
+ it 'has a pays_at_beginning? attribute that defaults to false' do
30
+ expect(subject).to have_attributes(pays_at_beginning?: false)
31
+ end
32
+
33
+ it 'has a result attribute' do
34
+ expect(subject.result).to be_a Numeric
35
+ end
36
+
37
+ context 'when payments occur at the beginning of each period' do
38
+ let(:pay_at_beginning) { true }
39
+ it { is_expected.to have_attributes(pays_at_beginning?: true) }
40
+ end
41
+
42
+ context 'when given a non-numeric rate' do
43
+ let(:rate) { 'string' }
44
+ it_behaves_like 'it has invalid arguments'
45
+ end
46
+
47
+ context 'when given a non-numeric number of periods' do
48
+ let(:num_periods) { 'string' }
49
+ it_behaves_like 'it has invalid arguments'
50
+ end
51
+
52
+ context 'when given a non-numeric present value' do
53
+ let(:present_value) { 'string' }
54
+ it_behaves_like 'it has invalid arguments'
55
+ end
56
+
57
+ context 'when give a non-numeric future value' do
58
+ let(:future_value) { 'string' }
59
+ it_behaves_like 'it has invalid arguments'
60
+ end
61
+
62
+ describe '#inspect' do
63
+ subject { pmt.inspect }
64
+
65
+ it { is_expected.to be_a String }
66
+ it { is_expected.to include 'PMT' }
67
+ it 'includes the result of the PMT calculation' do
68
+ expect(subject).to include pmt.result.to_s
69
+ end
70
+ end
71
+ end
data/spec/pv_spec.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  require_relative 'spec_helper'
2
2
 
3
- shared_examples_for 'it has invalid present value arguments' do
4
- it 'raises an ArgumentError' do
5
- expect { subject }.to raise_error ArgumentError
6
- end
7
- end
3
+ # shared_examples_for 'it has invalid arguments' do
4
+ # it 'raises an ArgumentError' do
5
+ # expect { subject }.to raise_error ArgumentError
6
+ # end
7
+ # end
8
8
 
9
9
  describe "Pv" do
10
10
  let(:rate) { 0.1 }
@@ -58,22 +58,22 @@ describe "Pv" do
58
58
 
59
59
  context 'when the number of periods is negative' do
60
60
  let(:num_periods) { -1 }
61
- it_behaves_like 'it has invalid present value arguments'
61
+ it_behaves_like 'it has invalid arguments'
62
62
  end
63
63
 
64
64
  context 'when rate is non-numeric' do
65
65
  let(:rate) { 'string' }
66
- it_behaves_like 'it has invalid present value arguments'
66
+ it_behaves_like 'it has invalid arguments'
67
67
  end
68
68
 
69
69
  context 'when num_periods is non-numeric' do
70
70
  let(:num_periods) { 'string' }
71
- it_behaves_like 'it has invalid present value arguments'
71
+ it_behaves_like 'it has invalid arguments'
72
72
  end
73
73
 
74
74
  context 'when payment is non-numeric' do
75
75
  let(:payment) { 'string' }
76
- it_behaves_like 'it has invalid present value arguments'
76
+ it_behaves_like 'it has invalid arguments'
77
77
  end
78
78
 
79
79
  context 'when future_values non-numeric' do
@@ -81,7 +81,7 @@ describe "Pv" do
81
81
 
82
82
  subject { Pv.new(rate, num_periods, payment, future_value) }
83
83
 
84
- it_behaves_like 'it has invalid present value arguments'
84
+ it_behaves_like 'it has invalid arguments'
85
85
  end
86
86
 
87
87
  context 'when the number of periods is 0' do
data/spec/spec_helper.rb CHANGED
@@ -21,4 +21,10 @@ shared_examples_for 'the values do not converge' do
21
21
  it 'should raise an ArgumentError' do
22
22
  expect { subject }.to raise_error ArgumentError
23
23
  end
24
+ end
25
+
26
+ shared_examples_for 'it has invalid arguments' do
27
+ it 'raises an ArgumentError' do
28
+ expect { subject }.to raise_error ArgumentError
29
+ end
24
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: financial_calculator
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Falzone
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-12 00:00:00.000000000 Z
11
+ date: 2018-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: flt
@@ -162,15 +162,18 @@ files:
162
162
  - lib/financial_calculator/amortization.rb
163
163
  - lib/financial_calculator/irr.rb
164
164
  - lib/financial_calculator/npv.rb
165
+ - lib/financial_calculator/pmt.rb
165
166
  - lib/financial_calculator/pv.rb
166
167
  - lib/financial_calculator/rates.rb
167
168
  - lib/financial_calculator/transaction.rb
169
+ - lib/financial_calculator/validator.rb
168
170
  - lib/financial_calculator/version.rb
169
171
  - lib/financial_calculator/xirr.rb
170
172
  - lib/financial_calculator/xnpv.rb
171
173
  - spec/amortization_spec.rb
172
174
  - spec/irr_spec.rb
173
175
  - spec/npv_spec.rb
176
+ - spec/pmt_spec.rb
174
177
  - spec/pv_spec.rb
175
178
  - spec/rates_spec.rb
176
179
  - spec/spec_helper.rb
@@ -207,6 +210,7 @@ test_files:
207
210
  - spec/amortization_spec.rb
208
211
  - spec/irr_spec.rb
209
212
  - spec/npv_spec.rb
213
+ - spec/pmt_spec.rb
210
214
  - spec/pv_spec.rb
211
215
  - spec/rates_spec.rb
212
216
  - spec/spec_helper.rb