finance_rb 0.0.2 → 0.1.2

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: 6fa908552e787182999bb782ed6c7f7f624307f0acd77ff969c0171e07dd0179
4
- data.tar.gz: e0492ef3dd7baa271a4d7893ff32c5c94de852d2328d1c49321bb1d78147f08e
3
+ metadata.gz: 3f920db19ed5b406b8e263c09fac4aba9cd203ebdca989c096b44b441753757e
4
+ data.tar.gz: 435cd054975eee4b5027245d0301551b1b0cfd889153879f02929f1885d55f77
5
5
  SHA512:
6
- metadata.gz: ccc866a27aecf49b0f869f9ddf590ac58d7682bc35c30a5abfda526251b800960b143fa19b05063411e30061a96f950963c4f8c38d867da763b1654ec77bfb52
7
- data.tar.gz: 5ca7d064faf5bb38ad5cd70ddb1595d8983833e4ad9b46290f17b9f5ca8eee2abd4e4c99eedf852bbf79790c28d54e4aa4743beeffbf72921ff0dccc95f1cc94
6
+ metadata.gz: 15fa362a606eacc22aeff3c89312bbedbfbe2d78319b66cd3c146a985a6c5a68114fcb1601986facdc823fa14b03a798708faae3adf704aad8c8ee89c59ec07b
7
+ data.tar.gz: c96d0f272ccee5c88cab312981f7795bac101e7bd3b229b88cfb34f05db3334b63bc61d9f41f13404105c6b6ab6bd4d318ecf3ad98ac89dbe443f1cc920a453a
data/CHANGELOG.md CHANGED
@@ -1,4 +1,29 @@
1
- ## [Unreleased]
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
+
23
+ ## [0.0.3] - 2021-03-23
24
+
25
+ ### Added
26
+ * Implement `Finance::Calculations#irr` using Newton's method
2
27
 
3
28
  ## [0.0.2] - 2021-03-22
4
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|
16
- | nper | | Computes the number of periodic payments|
17
- | 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|
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|
18
+ | nper | | Computes the number of periodic payments|
19
+ | pv | | Computes the present value of a payment|
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.
@@ -1,9 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'bigdecimal'
4
+ require 'bigdecimal/newton'
5
+
6
+ include Newton
7
+
3
8
  module Finance
4
9
  class Calculations
5
10
  class << self
6
11
  # Npv computes the Net Present Value of a cash flow series.
12
+ #
7
13
  # @return [Numeric] The NPV of the input cash flow series `values` at the discount `rate`.
8
14
  #
9
15
  # @param [Numeric] :rate A discount rate applied once per period.
@@ -24,7 +30,100 @@ module Finance
24
30
  npv_value
25
31
  end
26
32
 
33
+ # IRR computes the Rate of Interest per period.
34
+ #
35
+ # @return [Float] Internal Rate of Return for periodic input values.
36
+ #
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.
40
+ #
41
+ # @example
42
+ # require 'finance_rb'
43
+ # Finance::Calculations.irr([-100, 0, 0, 74]) #=> 0.14299344106053188
44
+ #
45
+ # @see http://en.wikipedia.org/wiki/Internal_rate_of_return
46
+ # @see L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed.,
47
+ # Addison-Wesley, 2003, pg. 348.
48
+ def irr(values)
49
+ return 0.0 unless correct_cashflows?(values)
50
+
51
+ func = BigDecimal.limit(100)
52
+ func = Function.new(values)
53
+ rate = [ func.one ]
54
+ nlsolve(func, rate)
55
+ rate[0].to_f
56
+ end
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
+
27
96
  alias net_present_value npv
97
+ alias internal_return_rate irr
98
+
99
+ private
100
+
101
+ def correct_cashflows?(values)
102
+ inflows, outflows = values.partition{ |i| i >= 0 }
103
+ !(inflows.empty? || outflows.empty?)
104
+ end
105
+
106
+ # Base class for working with Newton's Method.
107
+ # For more details, see Bigdecimal::Newton.
108
+ # @api private
109
+ class Function
110
+ def initialize(values)
111
+ @zero = BigDecimal("0.0")
112
+ @one = BigDecimal("1.0")
113
+ @two = BigDecimal("2.0")
114
+ @ten = BigDecimal("10.0")
115
+ @eps = BigDecimal("1.0e-16")
116
+ @values = values
117
+ end
118
+
119
+ def zero; @zero; end
120
+ def one ; @one; end
121
+ def two ; @two; end
122
+ def ten ; @ten; end
123
+ def eps ; @eps; end
124
+
125
+ def values(x); [Finance::Calculations.npv(x[0], @values)]; end
126
+ end
28
127
  end
29
128
  end
30
129
  end
data/lib/finance/loan.rb CHANGED
@@ -2,12 +2,161 @@
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
+ # Fv computes future value at the end of some periods (duration).
115
+ # Required Loan arguments: nominal_rate, duration, payment, amount*
116
+ #
117
+ # @param payment [Float] The (fixed) periodic payment.
118
+ # In case you don't want to modify the original loan, use this parameter to recalculate fv.
119
+ #
120
+ # @return [Float] The value at the end of the `duration` periods.
121
+ #
122
+ # @example
123
+ # require 'finance_rb'
124
+ # Finance::Loan.new(nominal_rate: 0.05, duration: 120, amount: -100, payment: -200).fv
125
+ # #=> 15692.928894335748
126
+ #
127
+ # @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
128
+ # @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
129
+ # Open Document Format for Office Applications (OpenDocument)v1.2,
130
+ # Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
131
+ # Pre-Draft 12. Organization for the Advancement of Structured Information
132
+ # Standards (OASIS). Billerica, MA, USA. [ODT Document].
133
+ def fv(payment: nil)
134
+ raise ArgumentError, 'no payment given' if self.payment.nil? && payment.nil?
135
+
136
+ final_payment = payment || self.payment
137
+
138
+ factor = (1.0 + monthly_rate)**duration
139
+ second_factor = (factor - 1) * (1 + monthly_rate * ptype) / monthly_rate
140
+
141
+ -((amount * factor) + (final_payment.to_f * second_factor))
142
+ end
143
+
144
+ private
145
+
146
+ def initialize_payment_type(ptype)
147
+ @ptype =
148
+ if ptype.nil? || !PAYMENT_TYPE_MAPPING.keys.include?(ptype)
149
+ PAYMENT_TYPE_MAPPING[:end]
150
+ else
151
+ PAYMENT_TYPE_MAPPING[ptype]
152
+ end
153
+ end
154
+
155
+ def remaining_balance
156
+ self.class.new(
157
+ nominal_rate: nominal_rate.to_f, duration: period - 1.0,
158
+ amount: amount.to_f, ptype: PAYMENT_TYPE_MAPPING.key(ptype)
159
+ ).fv(payment: -pmt)
160
+ end
12
161
  end
13
162
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Finance
4
- VERSION = "0.0.2"
4
+ VERSION = "0.1.2"
5
5
  end
@@ -12,10 +12,72 @@ RSpec.describe Finance::Calculations do
12
12
  ).to eq(-85.07888805409468)
13
13
  end
14
14
 
15
- it 'returns correct npv for zero rates' do
15
+ it 'calculates correct npv for zero rates' do
16
16
  expect(
17
17
  Finance::Calculations.net_present_value(0.0, [-2000, 55, 55, 55])
18
18
  ).to eq(-1835.0)
19
19
  end
20
20
  end
21
+
22
+ describe '#irr' do
23
+ it 'calculates correct irr value' do
24
+ expect(
25
+ Finance::Calculations.irr([-4000,1200,1410,1875,1050])
26
+ ).to eq(0.14299344106053188)
27
+ end
28
+
29
+ it 'calculates zero for cashflows w/o any inflows' do
30
+ expect(
31
+ Finance::Calculations.irr([100,500,200,50])
32
+ ).to eq(0.0)
33
+ end
34
+
35
+ it 'is available through alias name' do
36
+ expect(
37
+ Finance::Calculations.internal_return_rate([-100, 0, 0, 74])
38
+ ).to eq(-0.09549583035161031)
39
+ end
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
21
83
  end
@@ -0,0 +1,102 @@
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
+ 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.2
4
+ version: 0.1.2
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-04 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,15 +27,16 @@ 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:
33
34
  - MIT
34
35
  metadata:
35
36
  bug_tracker_uri: https://github.com/wowinter13/finance_rb/issues
36
- changelog_uri: https://github.com/wowinter13/finance_rb/blob/v0.0.2/CHANGELOG.md
37
- documentation_uri: https://www.rubydoc.info/wowinter13/finance_rb/0.0.2
38
- source_code_uri: https://github.com/wowinter13/finance_rb/tree/v0.0.2
37
+ changelog_uri: https://github.com/wowinter13/finance_rb/blob/master/CHANGELOG.md
38
+ documentation_uri: https://www.rubydoc.info/github/wowinter13/finance_rb
39
+ source_code_uri: https://github.com/wowinter13/finance_rb
39
40
  post_install_message:
40
41
  rdoc_options: []
41
42
  require_paths:
@@ -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