finance_rb 0.0.3 → 0.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: 3a0dc37279e3b577acb13a90c61ad4f232573a4d8c0eccdf19a267d42001a9ea
4
- data.tar.gz: ca6db2175dd770056d7539d555b239127bcc5836ae79826edc6807a4f5bd4311
3
+ metadata.gz: d76ff15f6be262332aa729708a548d775f1caaaefaa3135c1d545660c34717ca
4
+ data.tar.gz: 2d75e526b34bf1704686e3fb9bf5198b4b2d302f05e714207d8d06833ce96acf
5
5
  SHA512:
6
- metadata.gz: 395383e7e7c9b2b564a738aae13bc6f95d7180652b951a2fa4cf90118e551cb0cba6e87badb4ca23c7b5ab790be2de0ff5bef0e3736c50c18a7246262b2ae496
7
- data.tar.gz: 5c9a8d1e5b8726234fafa45ed747dcf881f7ae92a9157abf34e9186594775a4e651fc8c09395cdd9fd30e21426e217c4216f2b13644ee15f324a967325d4bf6a
6
+ metadata.gz: 9545eebb0c540d6e5f3d75cdbf8a5b7fabe0ed75860601dd278f2c0b13ca05285a9d0865d978837532c92c2fb70815c5f450a10d6ff7bd008330ae81ac4d915b
7
+ data.tar.gz: bffcb93c73279bea34db04dbc39d0b6747e9d609e91a3a5f8006aaefe6ca08be2a4109b033b622a3382a4232a4e3ffba4d1a2eb168fbf6f1e6fe73fd971ab20c
data/CHANGELOG.md CHANGED
@@ -1,7 +1,29 @@
1
+ ## [0.1.2] - 2021-04-05
2
+
3
+ ### Added
4
+ * Implement `Finance::Loan#ipmt`
5
+
6
+ ## [0.1.1] - 2021-03-30
7
+
8
+ ### Added
9
+ * Implement `Finance::Loan#fv`
10
+
11
+ ## [0.1.0] - 2021-03-28
12
+
13
+ ### Added
14
+ * Create a basic structure for `Finance::Loan`
15
+ * Implement `Finance::Loan#pmt`
16
+
17
+
18
+ ## [0.0.4] - 2021-03-25
19
+
20
+ ### Added
21
+ * Implement `Finance::Calculations#mirr`
22
+
1
23
  ## [0.0.3] - 2021-03-23
2
24
 
3
25
  ### Added
4
- * Implement Finance::Calculations#irr using Newton's method
26
+ * Implement `Finance::Calculations#irr` using Newton's method
5
27
 
6
28
  ## [0.0.2] - 2021-03-22
7
29
 
data/README.md CHANGED
@@ -2,20 +2,50 @@
2
2
 
3
3
  This package is a ruby native port of the numpy-financial package with some helpful additional functions.
4
4
 
5
- The functions in this package are a scalar version of their vectorised counterparts in the [numpy-financial](https://github.com/numpy/numpy-financial) library.
5
+ The functions in this package are a scalar version of their vectorised counterparts in the [numpy-financial](https://github.com/numpy/numpy-financial) library.
6
+
7
+ [![Release](https://img.shields.io/github/v/release/wowinter13/finance_rb.svg?style=flat-square)](https://github.com/wowinter13/finance_rb/releases) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![Maintainability](https://api.codeclimate.com/v1/badges/bbca82ad7815794c6718/maintainability)](https://codeclimate.com/github/wowinter13/finance_rb/maintainability)
6
8
 
7
9
  Currently, only some functions are ported,
8
10
  which are as follows:
9
11
 
10
12
  | numpy-financial function | ruby native function ported? | info|
11
13
  |:------------------------: |:------------------: | :------------------|
12
- | fv | | Computes the future value|
13
- | ipmt | | Computes interest payment for a loan|
14
- | pmt | | Computes the fixed periodic payment(principal + interest) made against a loan amount|
15
- | ppmt | | Computes principal payment for a loan|
14
+ | fv || Computes the future value|
15
+ | ipmt || Computes interest payment for a loan|
16
+ | pmt || Computes the fixed periodic payment(principal + interest) made against a loan amount|
17
+ | ppmt || Computes principal payment for a loan|
16
18
  | nper | | Computes the number of periodic payments|
17
19
  | pv | | Computes the present value of a payment|
18
- | rate || Computes the rate of interest per period|
19
- | irr | | Computes the internal rate of return|
20
+ | rate | | Computes the rate of interest per period|
21
+ | irr || Computes the internal rate of return|
20
22
  | npv | ✅ | Computes the net present value of a series of cash flow|
21
- | mirr | | Computes the modified internal rate of return|
23
+ | mirr || Computes the modified internal rate of return|
24
+
25
+ ## Installation
26
+
27
+ finance_rb is available as a gem, to install it just install the gem:
28
+
29
+ gem install finance_rb
30
+
31
+ If you're using Bundler, add the gem to Gemfile.
32
+
33
+ gem 'finance_rb'
34
+
35
+ Run `bundle install`.
36
+
37
+ ## Running tests
38
+
39
+ bundle exec rspec spec/
40
+
41
+ ## Contributing
42
+
43
+ 1. Fork it ( https://github.com/wowinter13/finance_rb/fork )
44
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
45
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
46
+ 4. Push to the branch (`git push origin my-new-feature`)
47
+ 5. Create a new Pull Request
48
+
49
+ ## License
50
+
51
+ MIT License. See LICENSE for details.
@@ -35,6 +35,8 @@ module Finance
35
35
  # @return [Float] Internal Rate of Return for periodic input values.
36
36
  #
37
37
  # @param [Array<Numeric>] :values Input cash flows per time period.
38
+ # At least, must contain one positive and one negative value.
39
+ # Otherwise, irr equals zero.
38
40
  #
39
41
  # @example
40
42
  # require 'finance_rb'
@@ -44,10 +46,7 @@ module Finance
44
46
  # @see L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed.,
45
47
  # Addison-Wesley, 2003, pg. 348.
46
48
  def irr(values)
47
- inflows, outflows = values.partition{ |i| i >= 0 }
48
- if inflows.empty? || outflows.empty?
49
- return 0.0
50
- end
49
+ return 0.0 unless correct_cashflows?(values)
51
50
 
52
51
  func = BigDecimal.limit(100)
53
52
  func = Function.new(values)
@@ -56,11 +55,54 @@ module Finance
56
55
  rate[0].to_f
57
56
  end
58
57
 
58
+ # MIRR computes the modified Rate of Interest.
59
+ #
60
+ # @return [Float] Modified Internal Rate of Return.
61
+ #
62
+ # @param [Array<Numeric>] :values
63
+ # At least, must contain one positive and one negative value.
64
+ # Otherwise, mirr equals zero.
65
+ # @param [Numeric] :rate Interest rate paid on the cash flows
66
+ # @param [Numeric] :reinvest_rate Interest rate received on the cash flows upon reinvestment
67
+ #
68
+ # @example
69
+ # require 'finance_rb'
70
+ # Finance::Calculations.mirr([100, 200, -50, 300, -200], 0.05, 0.06) => 0.2979256979689131
71
+ #
72
+ # @see https://en.wikipedia.org/wiki/Modified_internal_rate_of_return
73
+ def mirr(values, rate, reinvest_rate)
74
+ inflows = [];
75
+ outflows = [];
76
+ # We prefer manual enumeration over the partition
77
+ # because of the need to replace outflows with zeros.
78
+ values.each do |val|
79
+ if val >= 0
80
+ inflows << val
81
+ outflows << 0.0
82
+ else
83
+ outflows << val
84
+ inflows << 0.0
85
+ end
86
+ end
87
+ if outflows.all?(0.0) || inflows.all?(0.0)
88
+ return 0.0
89
+ end
90
+ fv = npv(reinvest_rate, inflows).abs
91
+ pv = npv(rate, outflows).abs
92
+
93
+ return (fv/pv) ** (1.0/(values.size - 1)) * (1 + reinvest_rate) - 1
94
+ end
95
+
59
96
  alias net_present_value npv
60
97
  alias internal_return_rate irr
61
98
 
62
99
  private
63
100
 
101
+ def correct_cashflows?(values)
102
+ inflows, outflows = values.partition{ |i| i >= 0 }
103
+ !(inflows.empty? || outflows.empty?)
104
+ end
105
+
64
106
  # Base class for working with Newton's Method.
65
107
  # For more details, see Bigdecimal::Newton.
66
108
  # @api private
data/lib/finance/loan.rb CHANGED
@@ -2,12 +2,182 @@
2
2
 
3
3
  module Finance
4
4
  class Loan
5
- def initialize; end
5
+ PAYMENT_TYPE_MAPPING = { end: 0, beginning: 1 }.freeze
6
6
 
7
- def pmt; end
7
+ # @return [Float] The amount of loan request (I.e. a present value)
8
+ # You can use #pv method to calculate value if param is not defined.
9
+ # Defaults to 0.
10
+ attr_accessor :amount
8
11
 
9
- def ipmt; end
12
+ # @return [Integer] Specification of whether payment is made
13
+ # at the beginning (ptype = 1) or the end (ptype = 0) of each period.
14
+ # Defaults to {:end, 0}.
15
+ attr_accessor :ptype
10
16
 
11
- def ppmt; end
17
+ # @return [Float] The nominal annual rate of interest as decimal (not per cent).
18
+ # (e.g., 13% -> 0.13)
19
+ # Defaults to 0.
20
+ attr_accessor :nominal_rate
21
+
22
+ # @return [Float] The monthly rate is the nominal annual rate divided by 12.
23
+ # Defaults to 0.
24
+ attr_reader :monthly_rate
25
+
26
+ # @return [Float] The number of periods to be compounded for. (I.e. Nper())
27
+ # Defaults to 1.
28
+ attr_accessor :duration
29
+
30
+ # @return [Float] Future value.
31
+ # You can use #fv method to calculate value if param is not defined.
32
+ # Defaults to 0.
33
+ attr_accessor :future_value
34
+
35
+ # @return [Float] The (fixed) periodic payment.
36
+ # You can use #pmt method to calculate value if param is not defined.
37
+ attr_accessor :payment
38
+
39
+ # @return [Float] Period under consideration.
40
+ attr_accessor :period
41
+
42
+ # Create a new Loan instance.
43
+ def initialize(**options)
44
+ initialize_payment_type(options[:ptype])
45
+ @nominal_rate = options.fetch(:nominal_rate, 0).to_f
46
+ @duration = options.fetch(:duration, 1).to_f
47
+ @amount = options.fetch(:amount, 0).to_f
48
+ @future_value = options.fetch(:future_value, 0).to_f
49
+ @period = options[:period]
50
+ @payment = options[:payment]
51
+ @monthly_rate = @nominal_rate / 12
52
+ end
53
+
54
+ # Pmt computes the payment against a loan principal plus interest (future_value = 0).
55
+ # It can also be used to calculate the recurring payments needed to achieve
56
+ # a certain future value given an initial deposit,
57
+ # a fixed periodically compounded interest rate, and the total number of periods.
58
+ #
59
+ # Required Loan arguments: nominal_rate, duration, amount, future_value*
60
+ #
61
+ # @return [Numeric] The (fixed) periodic payment.
62
+ #
63
+ # @example
64
+ # require 'finance_rb'
65
+ # Finance::Loan.new(nominal_rate: 0.1, duration: 12, amount: 1000, ptype: :end).pmt
66
+ # #=> 87.9158872300099
67
+ #
68
+ # @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
69
+ # @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
70
+ # Open Document Format for Office Applications (OpenDocument)v1.2,
71
+ # Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
72
+ # Pre-Draft 12. Organization for the Advancement of Structured Information
73
+ # Standards (OASIS). Billerica, MA, USA. [ODT Document].
74
+ def pmt
75
+ factor = (1.0 + monthly_rate)**duration
76
+ second_factor =
77
+ if monthly_rate.zero?
78
+ duration
79
+ else
80
+ (factor - 1) * (1 + monthly_rate * ptype) / monthly_rate
81
+ end
82
+
83
+ -((future_value + amount * factor) / second_factor)
84
+ end
85
+
86
+ # IPmt computes interest payment for a loan under a given period.
87
+ #
88
+ # Required Loan arguments: period, nominal_rate, duration, amount, future_value*
89
+ #
90
+ # @return [Float] Interest payment for a loan.
91
+ #
92
+ # @example
93
+ # require 'finance_rb'
94
+ # Finance::Loan.new(nominal_rate: 0.0824, duration: 12, amount: 2500, period: 1).ipmt
95
+ # #=> -17.166666666666668
96
+ #
97
+ # @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
98
+ # @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
99
+ # Open Document Format for Office Applications (OpenDocument)v1.2,
100
+ # Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
101
+ # Pre-Draft 12. Organization for the Advancement of Structured Information
102
+ # Standards (OASIS). Billerica, MA, USA. [ODT Document].
103
+ def ipmt
104
+ raise ArgumentError, 'no period given' if period.nil?
105
+
106
+ ipmt_val = remaining_balance * monthly_rate
107
+ if ptype == PAYMENT_TYPE_MAPPING[:beginning]
108
+ period == 1 ? 0.0 : (ipmt_val / 1 + monthly_rate)
109
+ else
110
+ ipmt_val
111
+ end
112
+ end
113
+
114
+ # PPmt computes principal payment for a loan under a given period.
115
+ #
116
+ # Required Loan arguments: period, nominal_rate, duration, amount, future_value*
117
+ #
118
+ # @return [Float] Principal payment for a loan under a given period.
119
+ #
120
+ # @example
121
+ # require 'finance_rb'
122
+ # Finance::Loan.new(nominal_rate: 0.0824, duration: 12, amount: 2500, period: 1).ppmt
123
+ # #=> -200.58192368678277
124
+ #
125
+ # @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
126
+ # @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
127
+ # Open Document Format for Office Applications (OpenDocument)v1.2,
128
+ # Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
129
+ # Pre-Draft 12. Organization for the Advancement of Structured Information
130
+ # Standards (OASIS). Billerica, MA, USA. [ODT Document].
131
+ def ppmt
132
+ pmt - ipmt
133
+ end
134
+
135
+ # Fv computes future value at the end of some periods (duration).
136
+ # Required Loan arguments: nominal_rate, duration, payment, amount*
137
+ #
138
+ # @param payment [Float] The (fixed) periodic payment.
139
+ # In case you don't want to modify the original loan, use this parameter to recalculate fv.
140
+ #
141
+ # @return [Float] The value at the end of the `duration` periods.
142
+ #
143
+ # @example
144
+ # require 'finance_rb'
145
+ # Finance::Loan.new(nominal_rate: 0.05, duration: 120, amount: -100, payment: -200).fv
146
+ # #=> 15692.928894335748
147
+ #
148
+ # @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
149
+ # @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
150
+ # Open Document Format for Office Applications (OpenDocument)v1.2,
151
+ # Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
152
+ # Pre-Draft 12. Organization for the Advancement of Structured Information
153
+ # Standards (OASIS). Billerica, MA, USA. [ODT Document].
154
+ def fv(payment: nil)
155
+ raise ArgumentError, 'no payment given' if self.payment.nil? && payment.nil?
156
+
157
+ final_payment = payment || self.payment
158
+
159
+ factor = (1.0 + monthly_rate)**duration
160
+ second_factor = (factor - 1) * (1 + monthly_rate * ptype) / monthly_rate
161
+
162
+ -((amount * factor) + (final_payment.to_f * second_factor))
163
+ end
164
+
165
+ private
166
+
167
+ def initialize_payment_type(ptype)
168
+ @ptype =
169
+ if ptype.nil? || !PAYMENT_TYPE_MAPPING.keys.include?(ptype)
170
+ PAYMENT_TYPE_MAPPING[:end]
171
+ else
172
+ PAYMENT_TYPE_MAPPING[ptype]
173
+ end
174
+ end
175
+
176
+ def remaining_balance
177
+ self.class.new(
178
+ nominal_rate: nominal_rate.to_f, duration: period - 1.0,
179
+ amount: amount.to_f, ptype: PAYMENT_TYPE_MAPPING.key(ptype)
180
+ ).fv(payment: pmt)
181
+ end
12
182
  end
13
183
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Finance
4
- VERSION = "0.0.3"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -26,7 +26,7 @@ RSpec.describe Finance::Calculations do
26
26
  ).to eq(0.14299344106053188)
27
27
  end
28
28
 
29
- it 'calculates zero value for cashflows w/o any inflows' do
29
+ it 'calculates zero for cashflows w/o any inflows' do
30
30
  expect(
31
31
  Finance::Calculations.irr([100,500,200,50])
32
32
  ).to eq(0.0)
@@ -38,4 +38,46 @@ RSpec.describe Finance::Calculations do
38
38
  ).to eq(-0.09549583035161031)
39
39
  end
40
40
  end
41
+
42
+ describe '#mirr' do
43
+ it 'calculates correct mirr value' do
44
+ expect(
45
+ Finance::Calculations.mirr(
46
+ [-120000.0, 39000.0, 30000.0, 21000.0, 37000.0, 46000.0], 0.10, 0.12
47
+ )
48
+ ).to eq(0.1260941303659051)
49
+ end
50
+
51
+ it 'calculates correct mirr value with integers' do
52
+ expect(
53
+ Finance::Calculations.mirr(
54
+ [-4500, -800, 800, 800, 600, 600, 800, 800, 700, 3000], 0.08, 0.055
55
+ )
56
+ ).to eq(0.06659717503155349)
57
+ end
58
+
59
+ it 'calculates zero for cashflows w/o any outflows' do
60
+ expect(
61
+ Finance::Calculations.mirr(
62
+ [39000, 30000, 21000, 37000, 46000], 0.10, 0.12
63
+ )
64
+ ).to eq(0.0)
65
+ end
66
+
67
+ it 'calculates zero for cashflows w/o any inflows' do
68
+ expect(
69
+ Finance::Calculations.mirr(
70
+ [-1000, -5000, -2000, -100, -50], 0.10, 0.12
71
+ )
72
+ ).to eq(0.0)
73
+ end
74
+
75
+ it 'calculates correct mirr value for a shuffled order' do
76
+ expect(
77
+ Finance::Calculations.mirr(
78
+ [100, 200, -50, 300, -200], 0.05, 0.06
79
+ )
80
+ ).to eq(0.3428233878421769)
81
+ end
82
+ end
41
83
  end
@@ -0,0 +1,149 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Finance::Loan do
4
+ describe '#pmt' do
5
+ context 'w/o a full set of params' do
6
+ it 'calculates correct pmt value w/o :ptype' do
7
+ loan = Finance::Loan.new(nominal_rate: 0.1, duration: 12, amount: 1000)
8
+ expect(loan.pmt).to eq(-87.9158872300099)
9
+ end
10
+
11
+ it 'calculates correct pmt value w/o :nominal_rate' do
12
+ loan = Finance::Loan.new(duration: 12, amount: 1200, ptype: :end)
13
+ expect(loan.pmt).to eq(-100)
14
+ end
15
+ end
16
+
17
+ context 'with zero rates' do
18
+ it 'calculates correct pmt value for 3 years' do
19
+ loan = Finance::Loan.new(nominal_rate: 0, duration: 36, amount: 10_000, ptype: :end)
20
+ expect(loan.pmt).to eq(-277.77777777777777)
21
+ end
22
+
23
+ it 'calculates correct pmt value for 6 months' do
24
+ loan = Finance::Loan.new(nominal_rate: 0, duration: 6, amount: 10_000, ptype: :end)
25
+ expect(loan.pmt).to eq(-1666.6666666666667)
26
+ end
27
+ end
28
+
29
+ context 'with :beginning ptype' do
30
+ it 'calculates correct pmt value' do
31
+ loan = Finance::Loan.new(nominal_rate: 0.12, duration: 6, amount: 1000, ptype: :beginning)
32
+ expect(loan.pmt).to eq(-170.8399670404763)
33
+ end
34
+ end
35
+
36
+ it 'calculates correct pmt value' do
37
+ loan = Finance::Loan.new(nominal_rate: 0.13, duration: 90, amount: 1_000_000, ptype: :end)
38
+ expect(loan.pmt).to eq(-17_449.90775727763)
39
+ end
40
+ end
41
+
42
+ describe '#fv' do
43
+ context 'with loan arguments' do
44
+ it 'calculates correct fv value' do
45
+ loan = Finance::Loan.new(nominal_rate: 0.05, duration: 120, amount: -100, payment: -100)
46
+ expect(loan.fv).to eq(15_692.928894335748)
47
+ end
48
+
49
+ context 'with :ptype' do
50
+ it 'calculates correct fv value' do
51
+ loan = Finance::Loan.new(
52
+ nominal_rate: 0.9, duration: 20, amount: 0, payment: -2000, ptype: :beginning
53
+ )
54
+ expect(loan.fv).to eq(93_105.06487352113)
55
+ end
56
+ end
57
+ end
58
+
59
+ context 'with an optional :payment argument' do
60
+ it 'calculates correct fv value' do
61
+ loan = Finance::Loan.new(nominal_rate: 0.05, duration: 120, amount: -100, payment: -200)
62
+ expect(loan.fv(payment: -100)).to eq(15_692.928894335748)
63
+ end
64
+ end
65
+
66
+ context 'w/o any payments' do
67
+ it 'raises an ArgumentError exception w/o loan arguments' do
68
+ loan = Finance::Loan.new(nominal_rate: 0.05, duration: 120, amount: -100)
69
+ expect { loan.fv }.to raise_error(ArgumentError, "no payment given")
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '#ipmt' do
75
+ context 'when 1 period' do
76
+ it 'calculates correct ipmt value' do
77
+ loan = Finance::Loan.new(
78
+ nominal_rate: 0.0824, duration: 12, amount: 2500, period: 1
79
+ )
80
+ expect(loan.ipmt).to eq(-17.166666666666668)
81
+ end
82
+ end
83
+
84
+ context 'when 2 periods' do
85
+ it 'calculates correct ipmt value' do
86
+ loan = Finance::Loan.new(
87
+ nominal_rate: 0.0824, duration: 12, amount: 2500, period: 2
88
+ )
89
+ expect(loan.ipmt).to eq(-15.789337457350777)
90
+ end
91
+ end
92
+
93
+ context 'when 3 periods' do
94
+ it 'calculates correct ipmt value' do
95
+ loan = Finance::Loan.new(
96
+ nominal_rate: 0.0824, duration: 12.0, amount: 2500.0, period: 3.0, fv: 0.0
97
+ )
98
+ expect(loan.ipmt).to eq(-14.402550587464257)
99
+ end
100
+ end
101
+ end
102
+
103
+ describe '#ppmt' do
104
+ context 'when 1 period' do
105
+ it 'calculates correct ppmt value' do
106
+ loan = Finance::Loan.new(
107
+ nominal_rate: 0.0824, duration: 12, amount: 2500, period: 1
108
+ )
109
+ expect(loan.ppmt).to eq(-200.58192368678277)
110
+ end
111
+ end
112
+
113
+ context 'when 2 periods' do
114
+ it 'calculates correct ppmt value' do
115
+ loan = Finance::Loan.new(
116
+ nominal_rate: 0.0824, duration: 12, amount: 2500, period: 2
117
+ )
118
+ expect(loan.ppmt).to eq(-201.95925289609866)
119
+ end
120
+ end
121
+
122
+ context 'when 3 periods' do
123
+ it 'calculates correct ppmt value' do
124
+ loan = Finance::Loan.new(
125
+ nominal_rate: 0.0824, duration: 12, amount: 2500, period: 3
126
+ )
127
+ expect(loan.ppmt).to eq(-203.34603976598518)
128
+ end
129
+ end
130
+
131
+ context 'when 4 periods' do
132
+ it 'calculates correct ppmt value' do
133
+ loan = Finance::Loan.new(
134
+ nominal_rate: 0.0824, duration: 12, amount: 2500, period: 4
135
+ )
136
+ expect(loan.ppmt).to eq(-204.7423492390449)
137
+ end
138
+ end
139
+
140
+ context 'when 5 periods' do
141
+ it 'calculates correct ppmt value' do
142
+ loan = Finance::Loan.new(
143
+ nominal_rate: 0.0824, duration: 12, amount: 2500, period: 5
144
+ )
145
+ expect(loan.ppmt).to eq(-206.1482467038197)
146
+ end
147
+ end
148
+ end
149
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finance_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vlad Dyachenko
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-22 00:00:00.000000000 Z
11
+ date: 2021-04-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A ruby port of numpy-financial functions. This library provides a Ruby
14
14
  interface for working with interest rates, mortgage amortization, and cashflows
@@ -27,6 +27,7 @@ files:
27
27
  - lib/finance/version.rb
28
28
  - lib/finance_rb.rb
29
29
  - spec/finance/calculations_spec.rb
30
+ - spec/finance/loan_spec.rb
30
31
  - spec/spec_helper.rb
31
32
  homepage: https://github.com/wowinter13/finance_rb
32
33
  licenses:
@@ -57,4 +58,5 @@ specification_version: 4
57
58
  summary: A library for finance manipulations in Ruby.
58
59
  test_files:
59
60
  - spec/finance/calculations_spec.rb
61
+ - spec/finance/loan_spec.rb
60
62
  - spec/spec_helper.rb