finance_rb 0.1.1 → 1.0.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 +4 -4
- data/CHANGELOG.md +28 -0
- data/README.md +13 -5
- data/lib/finance/calculations.rb +2 -0
- data/lib/finance/loan.rb +154 -2
- data/lib/finance/version.rb +1 -1
- data/spec/finance/loan_spec.rb +133 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0abc599e1b7158a3095f3b9ac1627c54a0a85a9808a9afcc915a98fadfaff42d
|
4
|
+
data.tar.gz: f4417a96a3226bf76574e37fcf4c7f7e2bba9a92ea6586f43087444f4ecc239a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd17e47f2b8418ef8e1e1c7b24385bb6aff9f6d4342915a901f5590a4b3dc25c0d6154bf8af273bc377fa743e5104391ce05a67c80fbd93b9509f38bbf678ec4
|
7
|
+
data.tar.gz: 69ed50d7d91a8b416af2796ef0232dbf32bcae226e7cc71c174de163f4ddab4169af9f09952b7b5104367848b892fcafa971c737b50384bba8019dc0c71fa6bd
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
## [1.0.0] - 2021-05-01
|
2
|
+
|
3
|
+
### Added
|
4
|
+
* Implement `Finance::Loan#rate`
|
5
|
+
|
6
|
+
## [0.2.2] - 2021-05-01
|
7
|
+
|
8
|
+
### Added
|
9
|
+
* Implement `Finance::Loan#pv`
|
10
|
+
|
11
|
+
## [0.2.1] - 2021-05-01
|
12
|
+
|
13
|
+
### Added
|
14
|
+
* Implement `Finance::Loan#nper`
|
15
|
+
|
16
|
+
## [0.2.0] - 2021-04-30
|
17
|
+
|
18
|
+
### Added
|
19
|
+
* Implement `Finance::Loan#ppmt`
|
20
|
+
|
21
|
+
### Changed
|
22
|
+
* By default `Finance::Loan#pmt` returns negative values.
|
23
|
+
|
24
|
+
## [0.1.2] - 2021-04-05
|
25
|
+
|
26
|
+
### Added
|
27
|
+
* Implement `Finance::Loan#ipmt`
|
28
|
+
|
1
29
|
## [0.1.1] - 2021-03-30
|
2
30
|
|
3
31
|
### Added
|
data/README.md
CHANGED
@@ -12,16 +12,24 @@ which are as follows:
|
|
12
12
|
| numpy-financial function | ruby native function ported? | info|
|
13
13
|
|:------------------------: |:------------------: | :------------------|
|
14
14
|
| fv | ✅ | Computes the future value|
|
15
|
-
| ipmt |
|
15
|
+
| ipmt | ✅ | Computes interest payment for a loan|
|
16
16
|
| pmt | ✅ | Computes the fixed periodic payment(principal + interest) made against a loan amount|
|
17
|
-
| ppmt |
|
18
|
-
| nper |
|
19
|
-
| pv |
|
20
|
-
| rate |
|
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
21
|
| irr | ✅ | Computes the internal rate of return|
|
22
22
|
| npv | ✅ | Computes the net present value of a series of cash flow|
|
23
23
|
| mirr | ✅ | Computes the modified internal rate of return|
|
24
24
|
|
25
|
+
|
26
|
+
Things to be done:
|
27
|
+
|
28
|
+
1. Xirr
|
29
|
+
2. More specs for edge cases
|
30
|
+
3. Fee, currency protection and other cool stuff for advanced usage
|
31
|
+
4. Better errors
|
32
|
+
|
25
33
|
## Installation
|
26
34
|
|
27
35
|
finance_rb is available as a gem, to install it just install the gem:
|
data/lib/finance/calculations.rb
CHANGED
@@ -98,6 +98,7 @@ module Finance
|
|
98
98
|
|
99
99
|
private
|
100
100
|
|
101
|
+
# @api private
|
101
102
|
def correct_cashflows?(values)
|
102
103
|
inflows, outflows = values.partition{ |i| i >= 0 }
|
103
104
|
!(inflows.empty? || outflows.empty?)
|
@@ -105,6 +106,7 @@ module Finance
|
|
105
106
|
|
106
107
|
# Base class for working with Newton's Method.
|
107
108
|
# For more details, see Bigdecimal::Newton.
|
109
|
+
#
|
108
110
|
# @api private
|
109
111
|
class Function
|
110
112
|
def initialize(values)
|
data/lib/finance/loan.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Finance
|
4
4
|
class Loan
|
5
|
-
PAYMENT_TYPE_MAPPING = { end: 0, beginning: 1 }.freeze
|
5
|
+
PAYMENT_TYPE_MAPPING = { end: 0.0, beginning: 1.0 }.freeze
|
6
6
|
|
7
7
|
# @return [Float] The amount of loan request (I.e. a present value)
|
8
8
|
# You can use #pv method to calculate value if param is not defined.
|
@@ -25,6 +25,7 @@ module Finance
|
|
25
25
|
|
26
26
|
# @return [Float] The number of periods to be compounded for. (I.e. Nper())
|
27
27
|
# Defaults to 1.
|
28
|
+
# You can use #nper method to calculate value if param is not defined.
|
28
29
|
attr_accessor :duration
|
29
30
|
|
30
31
|
# @return [Float] Future value.
|
@@ -36,6 +37,9 @@ module Finance
|
|
36
37
|
# You can use #pmt method to calculate value if param is not defined.
|
37
38
|
attr_accessor :payment
|
38
39
|
|
40
|
+
# @return [Float] Period under consideration.
|
41
|
+
attr_accessor :period
|
42
|
+
|
39
43
|
# Create a new Loan instance.
|
40
44
|
def initialize(**options)
|
41
45
|
initialize_payment_type(options[:ptype])
|
@@ -43,6 +47,7 @@ module Finance
|
|
43
47
|
@duration = options.fetch(:duration, 1).to_f
|
44
48
|
@amount = options.fetch(:amount, 0).to_f
|
45
49
|
@future_value = options.fetch(:future_value, 0).to_f
|
50
|
+
@period = options[:period]
|
46
51
|
@payment = options[:payment]
|
47
52
|
@monthly_rate = @nominal_rate / 12
|
48
53
|
end
|
@@ -76,7 +81,72 @@ module Finance
|
|
76
81
|
(factor - 1) * (1 + monthly_rate * ptype) / monthly_rate
|
77
82
|
end
|
78
83
|
|
79
|
-
(
|
84
|
+
-((future_value + amount * factor) / second_factor)
|
85
|
+
end
|
86
|
+
|
87
|
+
# IPmt computes interest payment for a loan under a given period.
|
88
|
+
#
|
89
|
+
# Required Loan arguments: period, nominal_rate, duration, amount, future_value*
|
90
|
+
#
|
91
|
+
# @return [Float] The interest payment for a loan.
|
92
|
+
#
|
93
|
+
# @example
|
94
|
+
# require 'finance_rb'
|
95
|
+
# Finance::Loan.new(nominal_rate: 0.0824, duration: 12, amount: 2500, period: 1).ipmt
|
96
|
+
# #=> -17.166666666666668
|
97
|
+
#
|
98
|
+
# @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
|
99
|
+
# @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
|
100
|
+
# Open Document Format for Office Applications (OpenDocument)v1.2,
|
101
|
+
# Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
|
102
|
+
# Pre-Draft 12. Organization for the Advancement of Structured Information
|
103
|
+
# Standards (OASIS). Billerica, MA, USA. [ODT Document].
|
104
|
+
def ipmt
|
105
|
+
raise ArgumentError, 'no period given' if period.nil?
|
106
|
+
|
107
|
+
ipmt_val = remaining_balance * monthly_rate
|
108
|
+
if ptype == PAYMENT_TYPE_MAPPING[:beginning]
|
109
|
+
period == 1 ? 0.0 : (ipmt_val / 1 + monthly_rate)
|
110
|
+
else
|
111
|
+
ipmt_val
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# PPmt computes principal payment for a loan under a given period.
|
116
|
+
#
|
117
|
+
# Required Loan arguments: period, nominal_rate, duration, amount, future_value*
|
118
|
+
#
|
119
|
+
# @return [Float] The principal payment for a loan under a given period.
|
120
|
+
#
|
121
|
+
# @example
|
122
|
+
# require 'finance_rb'
|
123
|
+
# Finance::Loan.new(nominal_rate: 0.0824, duration: 12, amount: 2500, period: 1).ppmt
|
124
|
+
# #=> -200.58192368678277
|
125
|
+
#
|
126
|
+
# @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
|
127
|
+
# @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
|
128
|
+
# Open Document Format for Office Applications (OpenDocument)v1.2,
|
129
|
+
# Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
|
130
|
+
# Pre-Draft 12. Organization for the Advancement of Structured Information
|
131
|
+
# Standards (OASIS). Billerica, MA, USA. [ODT Document].
|
132
|
+
def ppmt
|
133
|
+
pmt - ipmt
|
134
|
+
end
|
135
|
+
|
136
|
+
# Nper computes the number of periodic payments.
|
137
|
+
#
|
138
|
+
# Required Loan arguments: payment, nominal_rate, period, amount, future_value*
|
139
|
+
#
|
140
|
+
# @return [Float] The number of periodic payments.
|
141
|
+
#
|
142
|
+
# @example
|
143
|
+
# require 'finance_rb'
|
144
|
+
# Finance::Loan.new(nominal_rate: 0.07, amount: 8000, payment: -150).nper
|
145
|
+
# #=> 64.0733487706618586
|
146
|
+
def nper
|
147
|
+
z = payment * (1.0 + monthly_rate * ptype) / monthly_rate
|
148
|
+
|
149
|
+
Math.log(-future_value + z / (amount + z)) / Math.log(1.0 + monthly_rate)
|
80
150
|
end
|
81
151
|
|
82
152
|
# Fv computes future value at the end of some periods (duration).
|
@@ -109,8 +179,82 @@ module Finance
|
|
109
179
|
-((amount * factor) + (final_payment.to_f * second_factor))
|
110
180
|
end
|
111
181
|
|
182
|
+
# Pv computes present value.
|
183
|
+
# Required Loan arguments: nominal_rate, duration, payment, future_value, *ptype
|
184
|
+
#
|
185
|
+
# @return [Float] The present value.
|
186
|
+
#
|
187
|
+
# @example
|
188
|
+
# require 'finance_rb'
|
189
|
+
# Finance::Loan.new(nominal_rate: 0.24, duration: 12, future_value: 1000, payment: -300, ptype: :ending).pv
|
190
|
+
# #=> 2384.1091906935
|
191
|
+
#
|
192
|
+
# @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
|
193
|
+
# @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
|
194
|
+
# Open Document Format for Office Applications (OpenDocument)v1.2,
|
195
|
+
# Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
|
196
|
+
# Pre-Draft 12. Organization for the Advancement of Structured Information
|
197
|
+
# Standards (OASIS). Billerica, MA, USA. [ODT Document].
|
198
|
+
def pv
|
199
|
+
factor = (1.0 + monthly_rate)**duration
|
200
|
+
second_factor = (factor - 1) * (1 + monthly_rate * ptype) / monthly_rate
|
201
|
+
|
202
|
+
-(future_value + (payment.to_f * second_factor)) / factor
|
203
|
+
end
|
204
|
+
|
205
|
+
# Rate computes the interest rate per period
|
206
|
+
# by running Newton Rapson to find an approximate value.
|
207
|
+
#
|
208
|
+
# @return [Float] The interest rate.
|
209
|
+
#
|
210
|
+
# @param tolerance [Float] Required tolerance for the solution.
|
211
|
+
# @param initial_guess [Float] Starting guess for solving the rate of interest.
|
212
|
+
# @param iterations [Integer] Maximum iterations in finding the solution.
|
213
|
+
#
|
214
|
+
# @example
|
215
|
+
# require 'finance_rb'
|
216
|
+
# Finance::Loan.new(nominal_rate: 10, amount: -3500, payment: 0, duration: 10, future_value: 10000).rate
|
217
|
+
# #=> 0.11069085371426901
|
218
|
+
#
|
219
|
+
# @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
|
220
|
+
# @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
|
221
|
+
# Open Document Format for Office Applications (OpenDocument)v1.2,
|
222
|
+
# Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
|
223
|
+
# Pre-Draft 12. Organization for the Advancement of Structured Information
|
224
|
+
# Standards (OASIS). Billerica, MA, USA. [ODT Document].
|
225
|
+
def rate(tolerance: 1e-6, iterations: 100, initial_guess: 0.1)
|
226
|
+
next_iteration_rate = nil
|
227
|
+
current_iteration_rate = initial_guess
|
228
|
+
|
229
|
+
(0..iterations).each do |iteration|
|
230
|
+
next_iteration_rate = current_iteration_rate - rate_ratio(current_iteration_rate)
|
231
|
+
break if (next_iteration_rate - current_iteration_rate).abs <= tolerance
|
232
|
+
current_iteration_rate = next_iteration_rate
|
233
|
+
end
|
234
|
+
|
235
|
+
next_iteration_rate
|
236
|
+
end
|
237
|
+
|
112
238
|
private
|
113
239
|
|
240
|
+
# rate_ratio computes the ratio
|
241
|
+
# that is used to find a single value that sets the non-liner equation to zero.
|
242
|
+
#
|
243
|
+
# @api private
|
244
|
+
def rate_ratio(rate)
|
245
|
+
t1 = (rate+1.0) ** duration
|
246
|
+
t2 = (rate+1.0) ** (duration-1.0)
|
247
|
+
g = future_value + t1 * amount + payment * (t1 - 1.0) * (rate * ptype + 1.0) / rate
|
248
|
+
derivative_g = \
|
249
|
+
(duration * t2 * amount)
|
250
|
+
- (payment * (t1 - 1.0) * (rate * ptype + 1.0) / (rate ** 2.0))
|
251
|
+
+ (duration * payment * t2 * (rate * ptype + 1.0) / rate)
|
252
|
+
+ (payment * (t1 - 1.0) * ptype/rate)
|
253
|
+
|
254
|
+
g / derivative_g
|
255
|
+
end
|
256
|
+
|
257
|
+
# @api private
|
114
258
|
def initialize_payment_type(ptype)
|
115
259
|
@ptype =
|
116
260
|
if ptype.nil? || !PAYMENT_TYPE_MAPPING.keys.include?(ptype)
|
@@ -119,5 +263,13 @@ module Finance
|
|
119
263
|
PAYMENT_TYPE_MAPPING[ptype]
|
120
264
|
end
|
121
265
|
end
|
266
|
+
|
267
|
+
# @api private
|
268
|
+
def remaining_balance
|
269
|
+
self.class.new(
|
270
|
+
nominal_rate: nominal_rate.to_f, duration: period - 1.0,
|
271
|
+
amount: amount.to_f, ptype: PAYMENT_TYPE_MAPPING.key(ptype)
|
272
|
+
).fv(payment: pmt)
|
273
|
+
end
|
122
274
|
end
|
123
275
|
end
|
data/lib/finance/version.rb
CHANGED
data/spec/finance/loan_spec.rb
CHANGED
@@ -5,37 +5,37 @@ RSpec.describe Finance::Loan do
|
|
5
5
|
context 'w/o a full set of params' do
|
6
6
|
it 'calculates correct pmt value w/o :ptype' do
|
7
7
|
loan = Finance::Loan.new(nominal_rate: 0.1, duration: 12, amount: 1000)
|
8
|
-
expect(loan.pmt).to eq(87.9158872300099)
|
8
|
+
expect(loan.pmt).to eq(-87.9158872300099)
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'calculates correct pmt value w/o :nominal_rate' do
|
12
12
|
loan = Finance::Loan.new(duration: 12, amount: 1200, ptype: :end)
|
13
|
-
expect(loan.pmt).to eq(100)
|
13
|
+
expect(loan.pmt).to eq(-100)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
context 'with zero rates' do
|
18
18
|
it 'calculates correct pmt value for 3 years' do
|
19
19
|
loan = Finance::Loan.new(nominal_rate: 0, duration: 36, amount: 10_000, ptype: :end)
|
20
|
-
expect(loan.pmt).to eq(277.77777777777777)
|
20
|
+
expect(loan.pmt).to eq(-277.77777777777777)
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'calculates correct pmt value for 6 months' do
|
24
24
|
loan = Finance::Loan.new(nominal_rate: 0, duration: 6, amount: 10_000, ptype: :end)
|
25
|
-
expect(loan.pmt).to eq(1666.6666666666667)
|
25
|
+
expect(loan.pmt).to eq(-1666.6666666666667)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
context 'with :beginning ptype' do
|
30
30
|
it 'calculates correct pmt value' do
|
31
31
|
loan = Finance::Loan.new(nominal_rate: 0.12, duration: 6, amount: 1000, ptype: :beginning)
|
32
|
-
expect(loan.pmt).to eq(170.8399670404763)
|
32
|
+
expect(loan.pmt).to eq(-170.8399670404763)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'calculates correct pmt value' do
|
37
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)
|
38
|
+
expect(loan.pmt).to eq(-17_449.90775727763)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -70,4 +70,131 @@ RSpec.describe Finance::Loan do
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
73
|
+
|
74
|
+
describe '#pv' do
|
75
|
+
context 'when :ptype == beginning' do
|
76
|
+
it 'calculates correct pv value' do
|
77
|
+
loan = Finance::Loan.new(
|
78
|
+
nominal_rate: 0.24, duration: 12, future_value: 1000, payment: -300, ptype: :beginning
|
79
|
+
)
|
80
|
+
expect(loan.pv).to eq(2447.5612380190028)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when :ptype == ending' do
|
85
|
+
it 'calculates correct pv value' do
|
86
|
+
loan = Finance::Loan.new(
|
87
|
+
nominal_rate: 0.24, duration: 12, future_value: 1000, payment: -300, ptype: :ending
|
88
|
+
)
|
89
|
+
expect(loan.pv).to eq(2384.1091906935)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#ipmt' do
|
95
|
+
context 'when 1 period' do
|
96
|
+
it 'calculates correct ipmt value' do
|
97
|
+
loan = Finance::Loan.new(
|
98
|
+
nominal_rate: 0.0824, duration: 12, amount: 2500, period: 1
|
99
|
+
)
|
100
|
+
expect(loan.ipmt).to eq(-17.166666666666668)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when 2 periods' do
|
105
|
+
it 'calculates correct ipmt value' do
|
106
|
+
loan = Finance::Loan.new(
|
107
|
+
nominal_rate: 0.0824, duration: 12, amount: 2500, period: 2
|
108
|
+
)
|
109
|
+
expect(loan.ipmt).to eq(-15.789337457350777)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when 3 periods' do
|
114
|
+
it 'calculates correct ipmt value' do
|
115
|
+
loan = Finance::Loan.new(
|
116
|
+
nominal_rate: 0.0824, duration: 12.0, amount: 2500.0, period: 3.0, fv: 0.0
|
117
|
+
)
|
118
|
+
expect(loan.ipmt).to eq(-14.402550587464257)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '#ppmt' do
|
124
|
+
context 'when 1 period' do
|
125
|
+
it 'calculates correct ppmt value' do
|
126
|
+
loan = Finance::Loan.new(
|
127
|
+
nominal_rate: 0.0824, duration: 12, amount: 2500, period: 1
|
128
|
+
)
|
129
|
+
expect(loan.ppmt).to eq(-200.58192368678277)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'when 2 periods' do
|
134
|
+
it 'calculates correct ppmt value' do
|
135
|
+
loan = Finance::Loan.new(
|
136
|
+
nominal_rate: 0.0824, duration: 12, amount: 2500, period: 2
|
137
|
+
)
|
138
|
+
expect(loan.ppmt).to eq(-201.95925289609866)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'when 3 periods' do
|
143
|
+
it 'calculates correct ppmt value' do
|
144
|
+
loan = Finance::Loan.new(
|
145
|
+
nominal_rate: 0.0824, duration: 12, amount: 2500, period: 3
|
146
|
+
)
|
147
|
+
expect(loan.ppmt).to eq(-203.34603976598518)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'when 4 periods' do
|
152
|
+
it 'calculates correct ppmt value' do
|
153
|
+
loan = Finance::Loan.new(
|
154
|
+
nominal_rate: 0.0824, duration: 12, amount: 2500, period: 4
|
155
|
+
)
|
156
|
+
expect(loan.ppmt).to eq(-204.7423492390449)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'when 5 periods' do
|
161
|
+
it 'calculates correct ppmt value' do
|
162
|
+
loan = Finance::Loan.new(
|
163
|
+
nominal_rate: 0.0824, duration: 12, amount: 2500, period: 5
|
164
|
+
)
|
165
|
+
expect(loan.ppmt).to eq(-206.1482467038197)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe '#nper' do
|
171
|
+
context 'with normal arguments' do
|
172
|
+
it 'calculates correct nper value' do
|
173
|
+
loan = Finance::Loan.new(
|
174
|
+
nominal_rate: 0.07, amount: 8000, payment: -150, future_value: 0
|
175
|
+
)
|
176
|
+
expect(loan.nper).to eq(64.0733487706618586)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'with incorrect arguments' do
|
181
|
+
it 'raises Math::DomainError' do
|
182
|
+
loan = Finance::Loan.new(
|
183
|
+
nominal_rate: 1e100, amount: 8000, payment: -150, future_value: 0
|
184
|
+
)
|
185
|
+
expect { loan.nper }.to raise_error(Math::DomainError)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe '#rate' do
|
191
|
+
context 'with default arguments' do
|
192
|
+
it 'calculates correct rate value' do
|
193
|
+
loan = Finance::Loan.new(
|
194
|
+
nominal_rate: 10, amount: -3500, payment: 0, duration: 10, future_value: 10000
|
195
|
+
)
|
196
|
+
expect(loan.rate).to eq(0.11069085371426901)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
73
200
|
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.
|
4
|
+
version: 1.0.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-
|
11
|
+
date: 2021-05-01 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
|