finance_rb 0.2.2 → 1.0.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: 07e154f5ba5d444fe1e2c782c39a3d21a79b9fd3d413fba6e7c5285fa5f07df4
4
- data.tar.gz: bef7aea3a7f54df1fc69d05619e9416637c717ce7e8b4d3a211573fbfbf5a6df
3
+ metadata.gz: 0abc599e1b7158a3095f3b9ac1627c54a0a85a9808a9afcc915a98fadfaff42d
4
+ data.tar.gz: f4417a96a3226bf76574e37fcf4c7f7e2bba9a92ea6586f43087444f4ecc239a
5
5
  SHA512:
6
- metadata.gz: bf67fafbda3defb85d73581d02b3dc00b26f83c6b03e4f35bd5c2d3a0ac661a823cd737d8055c54309b8a6d6feba8be7d03675b39ddb95b2e8f7ceaa94a7e472
7
- data.tar.gz: 4f429be0368ac5e986c689fcd6afd146cec1676741d149ced828ae6d03e38e2d2e1ebdfeae88fce1d76de1a31c51a08fb0809577362f07f1de0e70e761bfa8b1
6
+ metadata.gz: fd17e47f2b8418ef8e1e1c7b24385bb6aff9f6d4342915a901f5590a4b3dc25c0d6154bf8af273bc377fa743e5104391ce05a67c80fbd93b9509f38bbf678ec4
7
+ data.tar.gz: 69ed50d7d91a8b416af2796ef0232dbf32bcae226e7cc71c174de163f4ddab4169af9f09952b7b5104367848b892fcafa971c737b50384bba8019dc0c71fa6bd
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [1.0.0] - 2021-05-01
2
+
3
+ ### Added
4
+ * Implement `Finance::Loan#rate`
5
+
1
6
  ## [0.2.2] - 2021-05-01
2
7
 
3
8
  ### Added
data/README.md CHANGED
@@ -17,11 +17,19 @@ which are as follows:
17
17
  | ppmt | ✅ | Computes principal payment for a loan|
18
18
  | nper | ✅ | Computes the number of periodic payments|
19
19
  | pv | ✅ | Computes the present value of a payment|
20
- | rate | | Computes the rate of interest per period|
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:
@@ -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.
@@ -88,7 +88,7 @@ module Finance
88
88
  #
89
89
  # Required Loan arguments: period, nominal_rate, duration, amount, future_value*
90
90
  #
91
- # @return [Float] Interest payment for a loan.
91
+ # @return [Float] The interest payment for a loan.
92
92
  #
93
93
  # @example
94
94
  # require 'finance_rb'
@@ -116,7 +116,7 @@ module Finance
116
116
  #
117
117
  # Required Loan arguments: period, nominal_rate, duration, amount, future_value*
118
118
  #
119
- # @return [Float] Principal payment for a loan under a given period.
119
+ # @return [Float] The principal payment for a loan under a given period.
120
120
  #
121
121
  # @example
122
122
  # require 'finance_rb'
@@ -137,7 +137,7 @@ module Finance
137
137
  #
138
138
  # Required Loan arguments: payment, nominal_rate, period, amount, future_value*
139
139
  #
140
- # @return [Float] Number of periodic payments.
140
+ # @return [Float] The number of periodic payments.
141
141
  #
142
142
  # @example
143
143
  # require 'finance_rb'
@@ -202,8 +202,59 @@ module Finance
202
202
  -(future_value + (payment.to_f * second_factor)) / factor
203
203
  end
204
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
+
205
238
  private
206
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
207
258
  def initialize_payment_type(ptype)
208
259
  @ptype =
209
260
  if ptype.nil? || !PAYMENT_TYPE_MAPPING.keys.include?(ptype)
@@ -213,6 +264,7 @@ module Finance
213
264
  end
214
265
  end
215
266
 
267
+ # @api private
216
268
  def remaining_balance
217
269
  self.class.new(
218
270
  nominal_rate: nominal_rate.to_f, duration: period - 1.0,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Finance
4
- VERSION = "0.2.2"
4
+ VERSION = "1.0.0"
5
5
  end
@@ -186,4 +186,15 @@ RSpec.describe Finance::Loan do
186
186
  end
187
187
  end
188
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
189
200
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finance_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vlad Dyachenko