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 +4 -4
- data/CHANGELOG.md +9 -1
- data/README.md +4 -3
- data/lib/financial_calculator.rb +2 -0
- data/lib/financial_calculator/pmt.rb +67 -0
- data/lib/financial_calculator/pv.rb +1 -8
- data/lib/financial_calculator/validator.rb +10 -0
- data/lib/financial_calculator/version.rb +1 -1
- data/spec/pmt_spec.rb +71 -0
- data/spec/pv_spec.rb +10 -10
- data/spec/spec_helper.rb +6 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ece241c288b5547ac0946a57d3488646427c41744219e0a7f2d86a164a8e088
|
4
|
+
data.tar.gz: b8fa7e3149792486255d06c54b53998e5f1846fe013d1152d511642349e5080c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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::
|
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
|
|
data/lib/financial_calculator.rb
CHANGED
@@ -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
|
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
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
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
|
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
|
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
|
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
|
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.
|
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-
|
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
|