financial_calculator 3.1.0 → 3.2.0

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.
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