financial_calculator 3.1.0 → 3.2.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: 7ece241c288b5547ac0946a57d3488646427c41744219e0a7f2d86a164a8e088
4
- data.tar.gz: b8fa7e3149792486255d06c54b53998e5f1846fe013d1152d511642349e5080c
3
+ metadata.gz: 57f4d8c3b636807234e0abea5bda7cb5137c0bd8147677f9dec480303c68e214
4
+ data.tar.gz: 9df5a5db44050c530da5e66bf3afcb2a57dedc5aa28cc96d98520b33a01affdd
5
5
  SHA512:
6
- metadata.gz: 880f9c1d6b98aadc025c246ba46e88b4f09928c92d395f59bfccb816796c806e2d1a9e3ce1358bf0c6ae288f4068c92bf9c466cd5d8013e68ff675a33dd0d6a4
7
- data.tar.gz: bc10cbf71ecc8478778b46f61cbd25adbebb79dc074203200a14d31688ea6c4cf123cf728957a0f3c6a99e300648d15cf52718dee74fc395eb23128953dcd499
6
+ metadata.gz: b43701fce76029ec660519740cfbc31e0ce3b4b9180a5ec47f2b3bcf080c6d6b7650188d852c6e79d44505ba9704b750227ff9b334a646a2bc43596a412216de
7
+ data.tar.gz: 648eaa40c214a467c40fe148be87fc1fb7b2b4ffec7f04cff640904a7720b96709fa28fd0d92333380e2f638eb838579735dd486d3e0b8ebd51bfd0c352d2040
data/CHANGELOG.md CHANGED
@@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [3.2.0] - 2018-06-09
10
+ ### Added
11
+ - New class for FV, IPMT and PPMT calculations
12
+
13
+ ### Removed
14
+
15
+ ### Changed
16
+
9
17
  ## [3.1.0] - 2018-05-20
10
18
  ### Added
11
19
  - New class for PMT calculation (FinancialCalculator::Pmt)
data/README.md CHANGED
@@ -106,10 +106,13 @@ You can also increase your payment to a specific amount:
106
106
 
107
107
  >> extra_payments_2 = 250000.amortize(rate){ -1500 }
108
108
 
109
- ## SUPPORTED STANDARD CALCUALTIONS
109
+ ## SUPPORTED CALCUALTIONS
110
+ - FV
111
+ - IPMT
110
112
  - IRR
111
113
  - NPV
112
114
  - PMT
115
+ - PPMT
113
116
  - PV
114
117
  - XIRR
115
118
  - XNPV
@@ -12,10 +12,13 @@ module FinancialCalculator
12
12
  require 'financial_calculator/amortization'
13
13
  require 'financial_calculator/rates'
14
14
  require 'financial_calculator/transaction'
15
+ require 'financial_calculator/ipmt'
15
16
  require 'financial_calculator/irr'
17
+ require 'financial_calculator/ppmt'
16
18
  require 'financial_calculator/pv'
17
19
  require 'financial_calculator/npv'
18
20
  require 'financial_calculator/xnpv'
19
21
  require 'financial_calculator/xirr'
20
22
  require 'financial_calculator/pmt'
23
+ require 'financial_calculator/fv'
21
24
  end
@@ -0,0 +1,69 @@
1
+ module FinancialCalculator
2
+ # Calculate the future value of a series of equal of payments
3
+ class Fv
4
+ include ::Validator
5
+
6
+ # @return [Numeric] The discount rate used in the calculation
7
+ attr_reader :rate
8
+
9
+ # @return [Numeric] The number of periodic payments
10
+ attr_reader :num_periods
11
+
12
+ # @return [Numeric] The amount of the periodic payment
13
+ attr_reader :payment
14
+
15
+ # @return [Numeric] The current value
16
+ attr_reader :present_value
17
+
18
+ # @return [Numeric] The result of the future value calculation
19
+ attr_reader :result
20
+
21
+ # Create a new future value calculation
22
+ #
23
+ # @see https://en.wikipedia.org/wiki/Future_value
24
+ # @example
25
+ # FinancialCalculator::Fv.new(0.02, 10, -100) #=> FV(1094.972100)
26
+ # @param [Numeric] rate The discount (interest) rate to use
27
+ # @param [Numeric] num_periods The number of periodic payments
28
+ # @param [Numeric] payment The amount of the periodic payment
29
+ # @param [Numeric] present_value The current value
30
+ # @param [Boolean] pay_at_beginning Whether the payments are made at the beginning or end of each period
31
+ # @return [FinancialCalculator::Fv] A Fv object
32
+ # @raise [ArgumentError] Raises an ArgumentError if num_periods is less than 0 or a required numeric
33
+ # field is given a non-numeric value
34
+ def initialize(rate, num_periods, payment, present_value = 0, pay_at_beginning = false)
35
+ validate_numerics(rate: rate, num_periods: num_periods, payment: payment, present_value: present_value)
36
+
37
+ if num_periods < 0
38
+ raise ArgumentError.new('Cannot calculate future value with negative periods. Use present value instead.')
39
+ end
40
+
41
+ @rate = Flt::DecNum(rate.to_s)
42
+ @num_periods = Flt::DecNum(num_periods.to_s)
43
+ @payment = Flt::DecNum(payment.to_s)
44
+ @present_value = Flt::DecNum(present_value.to_s)
45
+ @pay_at_beginning = pay_at_beginning
46
+ @result = solve(@rate, @num_periods, @payment, @present_value, pay_at_beginning)
47
+ end
48
+
49
+ def inspect
50
+ "FV(#{result})"
51
+ end
52
+
53
+ # @return [Boolean] Whether the payments are made at the beginning of each period
54
+ def pays_at_beginning?
55
+ @pay_at_beginning
56
+ end
57
+
58
+ private
59
+
60
+ def solve(rate, num_periods, payment, future_value, pay_at_beginning)
61
+ annuity_due = pay_at_beginning ? 1 : 0
62
+ compound = (1 + rate) ** num_periods
63
+
64
+ -((present_value * compound) + (payment * (1 + rate * annuity_due) * (compound - 1) / rate))
65
+ end
66
+ end
67
+
68
+ FutureValue = Fv
69
+ end
@@ -0,0 +1,77 @@
1
+ module FinancialCalculator
2
+ # Calculates the interest portion of a fixed rate annuity.
3
+ class Ipmt
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 amortization period
11
+ # @api public
12
+ attr_reader :period
13
+
14
+ # @return [Numeric] The number of payments to be made
15
+ # @api public
16
+ attr_reader :num_periods
17
+
18
+ # @return [Numeric] The current value of the annuity
19
+ # @api public
20
+ attr_reader :present_value
21
+
22
+ # @return [Numeric] The ending value of the annuity. Defaults to 0
23
+ # @api public
24
+ attr_reader :future_value
25
+
26
+ # @return [Boolean] Whether the payment is made at the beginning of the
27
+ # period (true) or end of the period (false)
28
+ # @api public
29
+ attr_reader :pay_at_beginning
30
+
31
+ # @return [DecNum] Result of the PMT calculation
32
+ # @api public
33
+ attr_reader :result
34
+
35
+ # Create a new object for calculating the periodic payment of an ordinary annuity
36
+ # @param [Numeric] rate The discount (interest) rate
37
+ # @param [Numeric] period The amortization period
38
+ # @param [Numeric] num_periods The number of payments to be made
39
+ # @param [Numeric] present_value The current value of the annuity
40
+ # @param [Numeric] future_value The ending value of the annuity
41
+ # @param [Boolean] pay_at_beginning. Whether the payment is made at the beginning
42
+ # of the period (true) or end of the period (false)
43
+ # @return [FinancialCalculator::Npv] An instance of a PMT calculation
44
+ def initialize(rate, period, num_periods, present_value, future_value = 0, pay_at_beginning = false)
45
+ validate_numerics(rate: rate, period: period, num_periods: num_periods, present_value: present_value, future_value: future_value)
46
+
47
+ @rate = Flt::DecNum(rate.to_s)
48
+ @period = Flt::DecNum(period)
49
+ @num_periods = Flt::DecNum(num_periods.to_s)
50
+ @present_value = Flt::DecNum(present_value.to_s)
51
+ @future_value = Flt::DecNum(future_value.to_s)
52
+ @pay_at_beginning = pay_at_beginning
53
+ @result = solve(@rate, @period, @num_periods, @present_value, @future_value, @pay_at_beginning)
54
+ end
55
+
56
+ # @return [Boolean] Whether the payments are made at the beginning of each period
57
+ # @api public
58
+ def pays_at_beginning?
59
+ @pay_at_beginning
60
+ end
61
+
62
+ def inspect
63
+ "IPMT(#{result})"
64
+ end
65
+
66
+ private
67
+
68
+ def solve(rate, period, nper, pv, fv, pay_at_beginning)
69
+ payment = FinancialCalculator::Pmt.new(rate, nper, pv, fv, pay_at_beginning).result
70
+ @result = if pays_at_beginning?
71
+ (FinancialCalculator::FutureValue.new(rate, period - 2, payment, pv, pay_at_beginning).result - payment) * rate
72
+ else
73
+ FinancialCalculator::FutureValue.new(rate, period - 1, payment, pv, pay_at_beginning).result * rate
74
+ end
75
+ end
76
+ end
77
+ end
@@ -40,7 +40,7 @@ module FinancialCalculator
40
40
  validate_numerics(rate: rate, num_periods: num_periods, present_value: present_value, future_value: future_value)
41
41
 
42
42
  @rate = Flt::DecNum(rate.to_s)
43
- @num_periods = Flt::DecNum(num_periods.to_s)
43
+ @num_periods = Flt::DecNum(num_periods.to_s)
44
44
  @present_value = Flt::DecNum(present_value.to_s)
45
45
  @future_value = Flt::DecNum(future_value || "0")
46
46
  @pay_at_beginning = pay_at_beginning || false
@@ -59,9 +59,9 @@ module FinancialCalculator
59
59
 
60
60
  private
61
61
 
62
- def solve(i, nper, pv, fv, pay_at_beginning)
62
+ def solve(rate, nper, pv, fv, pay_at_beginning)
63
63
  type = pay_at_beginning ? 1 : 0
64
- @result = ((pv * (1 + i) ** nper) + fv) * i / ((1 + i * type) * (1 - (1 + i) ** nper))
64
+ @result = ((pv * (1 + rate) ** nper) + fv) * rate / ((1 + rate * type) * (1 - (1 + rate) ** nper))
65
65
  end
66
66
  end
67
67
  end
@@ -0,0 +1,74 @@
1
+ module FinancialCalculator
2
+ # Calculates the principal portion of a loan or annuity for a particular period
3
+ class Ppmt
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 amortization period
11
+ # @api public
12
+ attr_reader :period
13
+
14
+ # @return [Numeric] The number of payments to be made
15
+ # @api public
16
+ attr_reader :num_periods
17
+
18
+ # @return [Numeric] The current value of the annuity
19
+ # @api public
20
+ attr_reader :present_value
21
+
22
+ # @return [Numeric] The ending value of the annuity. Defaults to 0
23
+ # @api public
24
+ attr_reader :future_value
25
+
26
+ # @return [Boolean] Whether the payment is made at the beginning of the
27
+ # period (true) or end of the period (false)
28
+ # @api public
29
+ attr_reader :pay_at_beginning
30
+
31
+ # @return [DecNum] Result of the PMT calculation
32
+ # @api public
33
+ attr_reader :result
34
+
35
+ # Create a new object for calculating the periodic payment of an ordinary annuity
36
+ # @param [Numeric] rate The discount (interest) rate
37
+ # @param [Numeric] period The amortization period
38
+ # @param [Numeric] num_periods The number of payments to be made
39
+ # @param [Numeric] present_value The current value of the annuity
40
+ # @param [Numeric] future_value The ending value of the annuity
41
+ # @param [Boolean] pay_at_beginning. Whether the payment is made at the beginning
42
+ # of the period (true) or end of the period (false)
43
+ # @return [FinancialCalculator::Npv] An instance of a PMT calculation
44
+ def initialize(rate, period, num_periods, present_value, future_value = 0, pay_at_beginning = false)
45
+ validate_numerics(rate: rate, period: period, num_periods: num_periods, present_value: present_value, future_value: future_value)
46
+
47
+ @rate = Flt::DecNum(rate.to_s)
48
+ @period = Flt::DecNum(period)
49
+ @num_periods = Flt::DecNum(num_periods.to_s)
50
+ @present_value = Flt::DecNum(present_value.to_s)
51
+ @future_value = Flt::DecNum(future_value.to_s)
52
+ @pay_at_beginning = pay_at_beginning
53
+ @result = solve(@rate, @period, @num_periods, @present_value, @future_value, @pay_at_beginning)
54
+ end
55
+
56
+ # @return [Boolean] Whether the payments are made at the beginning of each period
57
+ # @api public
58
+ def pays_at_beginning?
59
+ @pay_at_beginning
60
+ end
61
+
62
+ def inspect
63
+ "PPMT(#{result})"
64
+ end
65
+
66
+ private
67
+
68
+ def solve(rate, period, nper, pv, fv, pay_at_beginning)
69
+ payment = FinancialCalculator::Pmt.new(rate, nper, pv, fv, pay_at_beginning).result
70
+ ipmt = FinancialCalculator::Ipmt.new(rate, period, nper, pv, fv, pay_at_beginning).result
71
+ @result = payment - ipmt
72
+ end
73
+ end
74
+ end
@@ -1,5 +1,5 @@
1
1
  module FinancialCalculator
2
- # Calculate the future value of a series of equal of payments
2
+ # Calculate the present value of a series of equal of payments
3
3
  class Pv
4
4
  include ::Validator
5
5
 
@@ -61,7 +61,7 @@ module FinancialCalculator
61
61
  start_period = pay_at_beginning ? 0 : 1
62
62
  end_period = pay_at_beginning ? num_periods - 1 : num_periods
63
63
 
64
- present_value = (start_period..end_period.abs).reduce(0) do |total, t|
64
+ present_value = (start_period..end_period.abs).reduce(Flt::DecNum('0')) do |total, t|
65
65
  total += discount(payment, rate, t)
66
66
  end
67
67
 
@@ -1,3 +1,3 @@
1
1
  module FinancialCalculator
2
- VERSION = '3.1.0'
2
+ VERSION = '3.2.0'
3
3
  end
data/spec/fv_spec.rb ADDED
@@ -0,0 +1,121 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe "Fv" do
4
+ let(:rate) { 0.1 }
5
+ let(:num_periods) { 10 }
6
+ let(:payment) { -100 }
7
+ let(:present_value) { 0 }
8
+ let(:pays_at_beginning) { false }
9
+ let(:future_value) { Fv.new(rate, num_periods, payment) }
10
+
11
+ subject { future_value }
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 payment attribute' do
22
+ expect(subject).to have_attributes(payment: payment)
23
+ end
24
+
25
+ it 'has a present_value attribute that defaults to 0' do
26
+ expect(subject).to have_attributes(present_value: 0)
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 whose value is positive' do
34
+ expect(subject).to have_attributes(result: (a_value > 0))
35
+ end
36
+
37
+ context 'when the payment is positive' do
38
+ let(:payment) { 100 }
39
+
40
+ it 'has a result attribute whose value is negative' do
41
+ expect(subject).to have_attributes(result: (a_value < 0))
42
+ end
43
+ end
44
+
45
+ context 'when the payment is 0' do
46
+ let(:payment) { 0 }
47
+
48
+ it 'has a future value of 0' do
49
+ expect(subject.result).to eql Flt::DecNum(0)
50
+ end
51
+ end
52
+
53
+ context 'when the number of periods is negative' do
54
+ let(:num_periods) { -1 }
55
+ it_behaves_like 'it has invalid arguments'
56
+ end
57
+
58
+ context 'when rate is non-numeric' do
59
+ let(:rate) { 'string' }
60
+ it_behaves_like 'it has invalid arguments'
61
+ end
62
+
63
+ context 'when num_periods is non-numeric' do
64
+ let(:num_periods) { 'string' }
65
+ it_behaves_like 'it has invalid arguments'
66
+ end
67
+
68
+ context 'when payment is non-numeric' do
69
+ let(:payment) { 'string' }
70
+ it_behaves_like 'it has invalid arguments'
71
+ end
72
+
73
+ context 'when present_value is non-numeric' do
74
+ let(:present_value) { 'string' }
75
+
76
+ subject { Fv.new(rate, num_periods, payment, future_value) }
77
+
78
+ it_behaves_like 'it has invalid arguments'
79
+ end
80
+
81
+ context 'when the number of periods is 0' do
82
+ let(:num_periods) { 0 }
83
+
84
+ it 'has a result equal to the present value' do
85
+ expect(subject.result).to eql Flt::DecNum(present_value.to_s)
86
+ end
87
+ end
88
+
89
+ context 'when provided with a present value' do
90
+ let(:present_value) { 100 }
91
+
92
+ subject { Fv.new(rate, num_periods, payment, present_value) }
93
+
94
+ it { is_expected.to have_attributes(present_value: present_value) }
95
+ end
96
+
97
+ context 'when payments occur at the beginning of each period' do
98
+ let(:pays_at_beginning) { true }
99
+
100
+ subject { Fv.new(rate, num_periods, payment, 0, pays_at_beginning) }
101
+
102
+ it { is_expected.to have_attributes(pays_at_beginning?: true) }
103
+ end
104
+
105
+ describe '#inspect' do
106
+
107
+ subject { future_value.inspect }
108
+
109
+ it { is_expected.to be_a String }
110
+ it { is_expected.to include 'FV' }
111
+ it 'includes the result of the future value calculation' do
112
+ expect(subject).to include future_value.result.to_s
113
+ end
114
+ end
115
+
116
+ describe '#result' do
117
+ subject { future_value.result }
118
+
119
+ it { is_expected.to be_a Flt::DecNum }
120
+ end
121
+ end
data/spec/ipmt_spec.rb ADDED
@@ -0,0 +1,87 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe "Ipmt" do
4
+ let(:rate) { 0.1 }
5
+ let(:period) { 10 }
6
+ let(:num_periods) { 20 }
7
+ let(:present_value) { 1000 }
8
+ let(:future_value) { 0 }
9
+ let(:pay_at_beginning) { false }
10
+ let(:ipmt) { Ipmt.new(rate, period, num_periods, present_value) }
11
+
12
+ subject { ipmt }
13
+
14
+ it 'has a rate attribute' do
15
+ expect(subject).to have_attributes(rate: rate)
16
+ end
17
+
18
+ it 'has a period attribute' do
19
+ expect(subject).to have_attributes(period: period)
20
+ end
21
+
22
+ it 'has a num_periods attribute' do
23
+ expect(subject).to have_attributes(num_periods: num_periods)
24
+ end
25
+
26
+ it 'has a present_value attribute' do
27
+ expect(subject).to have_attributes(present_value: present_value)
28
+ end
29
+
30
+ it 'has a future_value attribute the defaults to 0' do
31
+ expect(subject).to have_attributes(future_value: future_value)
32
+ end
33
+
34
+ it 'has a pays_at_beginning? attribute that defaults to false' do
35
+ expect(subject).to have_attributes(pays_at_beginning?: false)
36
+ end
37
+
38
+ it 'has a result attribute' do
39
+ expect(subject.result).to be_a Numeric
40
+ end
41
+
42
+ context 'when payments occur at the beginning of each period' do
43
+ let(:pay_at_beginning) { true }
44
+
45
+ subject { Ipmt.new(rate, period, num_periods, present_value, 0, pay_at_beginning) }
46
+
47
+ it { is_expected.to have_attributes(pays_at_beginning?: true) }
48
+ end
49
+
50
+ context 'when given a non-numeric rate' do
51
+ let(:rate) { 'string' }
52
+ it_behaves_like 'it has invalid arguments'
53
+ end
54
+
55
+ context 'when given a non-numeric period' do
56
+ let(:period) { 'string' }
57
+ it_behaves_like 'it has invalid arguments'
58
+ end
59
+
60
+ context 'when given a non-numeric number of periods' do
61
+ let(:num_periods) { 'string' }
62
+ it_behaves_like 'it has invalid arguments'
63
+ end
64
+
65
+ context 'when given a non-numeric present value' do
66
+ let(:present_value) { 'string' }
67
+ it_behaves_like 'it has invalid arguments'
68
+ end
69
+
70
+ context 'when give a non-numeric future value' do
71
+ let(:future_value) { 'string' }
72
+
73
+ subject { Ipmt.new(rate, period, num_periods, present_value, future_value) }
74
+
75
+ it_behaves_like 'it has invalid arguments'
76
+ end
77
+
78
+ describe '#inspect' do
79
+ subject { ipmt.inspect }
80
+
81
+ it { is_expected.to be_a String }
82
+ it { is_expected.to include 'IPMT' }
83
+ it 'includes the result of the IPMT calculation' do
84
+ expect(subject).to include ipmt.result.to_s
85
+ end
86
+ end
87
+ end
data/spec/ppmt_spec.rb ADDED
@@ -0,0 +1,87 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe "Ppmt" do
4
+ let(:rate) { 0.1 }
5
+ let(:period) { 10 }
6
+ let(:num_periods) { 20 }
7
+ let(:present_value) { 1000 }
8
+ let(:future_value) { 0 }
9
+ let(:pay_at_beginning) { false }
10
+ let(:ppmt) { Ppmt.new(rate, period, num_periods, present_value) }
11
+
12
+ subject { ppmt }
13
+
14
+ it 'has a rate attribute' do
15
+ expect(subject).to have_attributes(rate: rate)
16
+ end
17
+
18
+ it 'has a period attribute' do
19
+ expect(subject).to have_attributes(period: period)
20
+ end
21
+
22
+ it 'has a num_periods attribute' do
23
+ expect(subject).to have_attributes(num_periods: num_periods)
24
+ end
25
+
26
+ it 'has a present_value attribute' do
27
+ expect(subject).to have_attributes(present_value: present_value)
28
+ end
29
+
30
+ it 'has a future_value attribute the defaults to 0' do
31
+ expect(subject).to have_attributes(future_value: future_value)
32
+ end
33
+
34
+ it 'has a pays_at_beginning? attribute that defaults to false' do
35
+ expect(subject).to have_attributes(pays_at_beginning?: false)
36
+ end
37
+
38
+ it 'has a result attribute' do
39
+ expect(subject.result).to be_a Numeric
40
+ end
41
+
42
+ context 'when payments occur at the beginning of each period' do
43
+ let(:pay_at_beginning) { true }
44
+
45
+ subject { Ppmt.new(rate, period, num_periods, present_value, 0, pay_at_beginning) }
46
+
47
+ it { is_expected.to have_attributes(pays_at_beginning?: true) }
48
+ end
49
+
50
+ context 'when given a non-numeric rate' do
51
+ let(:rate) { 'string' }
52
+ it_behaves_like 'it has invalid arguments'
53
+ end
54
+
55
+ context 'when given a non-numeric period' do
56
+ let(:period) { 'string' }
57
+ it_behaves_like 'it has invalid arguments'
58
+ end
59
+
60
+ context 'when given a non-numeric number of periods' do
61
+ let(:num_periods) { 'string' }
62
+ it_behaves_like 'it has invalid arguments'
63
+ end
64
+
65
+ context 'when given a non-numeric present value' do
66
+ let(:present_value) { 'string' }
67
+ it_behaves_like 'it has invalid arguments'
68
+ end
69
+
70
+ context 'when give a non-numeric future value' do
71
+ let(:future_value) { 'string' }
72
+
73
+ subject { Ppmt.new(rate, period, num_periods, present_value, future_value) }
74
+
75
+ it_behaves_like 'it has invalid arguments'
76
+ end
77
+
78
+ describe '#inspect' do
79
+ subject { ppmt.inspect }
80
+
81
+ it { is_expected.to be_a String }
82
+ it { is_expected.to include 'PPMT' }
83
+ it 'includes the result of the PPMT calculation' do
84
+ expect(subject).to include ppmt.result.to_s
85
+ end
86
+ end
87
+ end
data/spec/pv_spec.rb CHANGED
@@ -1,11 +1,5 @@
1
1
  require_relative 'spec_helper'
2
2
 
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
-
9
3
  describe "Pv" do
10
4
  let(:rate) { 0.1 }
11
5
  let(:num_periods) { 10 }
@@ -52,7 +46,7 @@ describe "Pv" do
52
46
  let(:payment) { 0 }
53
47
 
54
48
  it 'has a present value of 0' do
55
- expect(subject.result).to eql 0
49
+ expect(subject.result).to eql Flt::DecNum('0')
56
50
  end
57
51
  end
58
52
 
@@ -76,7 +70,7 @@ describe "Pv" do
76
70
  it_behaves_like 'it has invalid arguments'
77
71
  end
78
72
 
79
- context 'when future_values non-numeric' do
73
+ context 'when future_value is non-numeric' do
80
74
  let(:future_value) { 'string' }
81
75
 
82
76
  subject { Pv.new(rate, num_periods, payment, future_value) }
@@ -88,7 +82,7 @@ describe "Pv" do
88
82
  let(:num_periods) { 0 }
89
83
 
90
84
  it 'has a result equal to the future value' do
91
- expect(subject.result).to eql future_value
85
+ expect(subject.result).to eql Flt::DecNum(future_value.to_s)
92
86
  end
93
87
  end
94
88
 
@@ -122,6 +116,6 @@ describe "Pv" do
122
116
  describe '#result' do
123
117
  subject { present_value.result }
124
118
 
125
- it {is_expected.to be_a Flt::DecNum }
119
+ it { is_expected.to be_a Flt::DecNum }
126
120
  end
127
121
  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.1.0
4
+ version: 3.2.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-20 00:00:00.000000000 Z
11
+ date: 2018-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: flt
@@ -160,9 +160,12 @@ files:
160
160
  - financial_calculator.gemspec
161
161
  - lib/financial_calculator.rb
162
162
  - lib/financial_calculator/amortization.rb
163
+ - lib/financial_calculator/fv.rb
164
+ - lib/financial_calculator/ipmt.rb
163
165
  - lib/financial_calculator/irr.rb
164
166
  - lib/financial_calculator/npv.rb
165
167
  - lib/financial_calculator/pmt.rb
168
+ - lib/financial_calculator/ppmt.rb
166
169
  - lib/financial_calculator/pv.rb
167
170
  - lib/financial_calculator/rates.rb
168
171
  - lib/financial_calculator/transaction.rb
@@ -171,9 +174,12 @@ files:
171
174
  - lib/financial_calculator/xirr.rb
172
175
  - lib/financial_calculator/xnpv.rb
173
176
  - spec/amortization_spec.rb
177
+ - spec/fv_spec.rb
178
+ - spec/ipmt_spec.rb
174
179
  - spec/irr_spec.rb
175
180
  - spec/npv_spec.rb
176
181
  - spec/pmt_spec.rb
182
+ - spec/ppmt_spec.rb
177
183
  - spec/pv_spec.rb
178
184
  - spec/rates_spec.rb
179
185
  - spec/spec_helper.rb
@@ -208,9 +214,12 @@ specification_version: 4
208
214
  summary: A library for financial modelling in Ruby.
209
215
  test_files:
210
216
  - spec/amortization_spec.rb
217
+ - spec/fv_spec.rb
218
+ - spec/ipmt_spec.rb
211
219
  - spec/irr_spec.rb
212
220
  - spec/npv_spec.rb
213
221
  - spec/pmt_spec.rb
222
+ - spec/ppmt_spec.rb
214
223
  - spec/pv_spec.rb
215
224
  - spec/rates_spec.rb
216
225
  - spec/spec_helper.rb