finrb 0.0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/finrb/utils.rb CHANGED
@@ -30,29 +30,27 @@ module Finrb
30
30
  # @param d the dollar discount, which is equal to the difference between the face value of the bill and the purchase price
31
31
  # @param f the face value (par value) of the bill
32
32
  # @param t number of days remaining until maturity
33
- # @export
34
- # @examples
35
- # bdy(d=1500,f=100000,t=120)
36
- def self.bdy(d, f, t)
37
- d = d.to_d
38
- f = f.to_d
39
- t = t.to_d
40
-
41
- (360 * d / f / t)
33
+ # @example
34
+ # Finrb::Utils.bdy(d=1500,f=100000,t=120)
35
+ def self.bdy(d:, f:, t:)
36
+ d = DecNum(d.to_s)
37
+ f = DecNum(f.to_s)
38
+ t = DecNum(t.to_s)
39
+
40
+ (d * 360 / f / t)
42
41
  end
43
42
 
44
43
  # Computing money market yield (MMY) for a T-bill
45
44
  #
46
45
  # @param bdy bank discount yield
47
46
  # @param t number of days remaining until maturity
48
- # @export
49
- # @examples
50
- # bdy2mmy(bdy=0.045,t=120)
51
- def self.bdy2mmy(bdy, t)
52
- bdy = bdy.to_d
53
- t = t.to_d
54
-
55
- (360 * bdy / (360 - (t * bdy)))
47
+ # @example
48
+ # Finrb::Utils.bdy2mmy(bdy=0.045,t=120)
49
+ def self.bdy2mmy(bdy:, t:)
50
+ bdy = DecNum(bdy.to_s)
51
+ t = DecNum(t.to_s)
52
+
53
+ (bdy * 360 / (360 - (t * bdy)))
56
54
  end
57
55
 
58
56
  # cash ratio -- Liquidity ratios measure the firm's ability to satisfy its short-term obligations as they come due.
@@ -60,13 +58,12 @@ module Finrb
60
58
  # @param cash cash
61
59
  # @param ms marketable securities
62
60
  # @param cl current liabilities
63
- # @export
64
- # @examples
65
- # Finrb::Utils.cash_ratio(cash=3000,ms=2000,cl=2000)
66
- def self.cash_ratio(cash, ms, cl)
67
- cash = cash.to_d
68
- ms = ms.to_d
69
- cl = cl.to_d
61
+ # @example
62
+ # Finrb::Utils.cash_ratio(cash=3000,ms=2000,cl=2000)
63
+ def self.cash_ratio(cash:, ms:, cl:)
64
+ cash = DecNum(cash.to_s)
65
+ ms = DecNum(ms.to_s)
66
+ cl = DecNum(cl.to_s)
70
67
 
71
68
  ((cash + ms) / cl)
72
69
  end
@@ -75,12 +72,11 @@ module Finrb
75
72
  #
76
73
  # @param sd standard deviation
77
74
  # @param avg average value
78
- # @export
79
- # @examples
80
- # Finrb::Utils.coefficient_variation(sd=0.15,avg=0.39)
81
- def self.coefficient_variation(sd, avg)
82
- sd = sd.to_d
83
- avg = avg.to_d
75
+ # @example
76
+ # Finrb::Utils.coefficient_variation(sd=0.15,avg=0.39)
77
+ def self.coefficient_variation(sd:, avg:)
78
+ sd = DecNum(sd.to_s)
79
+ avg = DecNum(avg.to_s)
84
80
 
85
81
  (sd / avg)
86
82
  end
@@ -88,71 +84,72 @@ module Finrb
88
84
  # Cost of goods sold and ending inventory under three methods (FIFO,LIFO,Weighted average)
89
85
  #
90
86
  # @param uinv units of beginning inventory
91
- # @param pinv prince of beginning inventory
87
+ # @param pinv price of beginning inventory
92
88
  # @param units nx1 vector of inventory units. inventory purchased ordered by time (from first to last)
93
89
  # @param price nx1 vector of inventory price. same order as units
94
90
  # @param sinv units of sold inventory
95
91
  # @param method inventory methods: FIFO (first in first out, permitted under both US and IFRS), LIFO (late in first out, US only), WAC (weighted average cost,US and IFRS)
96
- # @export
97
- # @examples
98
- # cogs(uinv=2,pinv=2,units=c(3,5),price=c(3,5),sinv=7,method="FIFO")
99
- #
100
- # cogs(uinv=2,pinv=2,units=c(3,5),price=c(3,5),sinv=7,method="LIFO")
101
- #
102
- # cogs(uinv=2,pinv=2,units=c(3,5),price=c(3,5),sinv=7,method="WAC")
103
- def self.cogs(uinv, pinv, units, price, sinv, method = 'FIFO')
104
- uinv = uinv.to_d
105
- pinv = pinv.to_d
106
- units = Array.wrap(units).map(&:to_d)
107
- price = Array.wrap(price).map(&:to_d)
108
- sinv = sinv.to_d
92
+ # @example
93
+ # Finrb::Utils.cogs(uinv=2,pinv=2,units=[3,5],price=[3,5],sinv=7,method="FIFO")
94
+ #
95
+ # @example
96
+ # Finrb::Utils.cogs(uinv=2,pinv=2,units=[3,5],price=[3,5],sinv=7,method="LIFO")
97
+ #
98
+ # @example
99
+ # Finrb::Utils.cogs(uinv=2,pinv=2,units=[3,5],price=[3,5],sinv=7,method="WAC")
100
+ def self.cogs(uinv:, pinv:, units:, price:, sinv:, method: 'FIFO')
101
+ uinv = DecNum(uinv.to_s)
102
+ pinv = DecNum(pinv.to_s)
103
+ units = Array.wrap(units).map { |value| DecNum(value.to_s) }
104
+ price = Array.wrap(price).map { |value| DecNum(value.to_s) }
105
+ sinv = DecNum(sinv.to_s)
109
106
  method = method.to_s
110
107
 
111
108
  n = units.size
112
109
  m = price.size
113
- costOfGoods = 0
114
- endingInventory = 0
110
+ cost_of_goods = 0
111
+ ending_inventory = 0
115
112
  if m == n
116
113
  case method
117
114
  when 'FIFO'
118
115
  if sinv <= uinv
119
- costOfGoods = sinv * pinv
120
- endingInventory = (uinv - sinv) * pinv
116
+ cost_of_goods = sinv * pinv
117
+ ending_inventory = (uinv - sinv) * pinv
121
118
  (0...n).each do |i|
122
- endingInventory += (units[i] * price[i])
119
+ ending_inventory += (units[i] * price[i])
123
120
  end
124
121
  else
125
- costOfGoods = uinv * pinv
122
+ cost_of_goods = uinv * pinv
126
123
  sinv -= uinv
127
124
  (0...n).each do |i|
128
125
  if sinv <= units[i]
129
- costOfGoods += (sinv * price[i])
130
- endingInventory = (units[i] - sinv) * price[i]
126
+ cost_of_goods += (sinv * price[i])
127
+ ending_inventory = (units[i] - sinv) * price[i]
131
128
  if i < n
132
129
  temp = i + 1
133
130
  (temp...n).each do |j|
134
- endingInventory += (units[j] * price[j])
131
+ ending_inventory += (units[j] * price[j])
135
132
  end
136
133
  end
137
134
  sinv = 0
138
135
  next
139
136
  else
140
- costOfGoods += (units[i] * price[i])
137
+ cost_of_goods += (units[i] * price[i])
141
138
  sinv -= units[i]
142
139
  end
143
140
  end
144
141
  raise(FinrbError, "Inventory is not enough to sell\n") if sinv.positive?
145
142
  end
146
143
  when 'WAC'
147
- endingInventory = uinv * pinv
144
+ ending_inventory = uinv * pinv
148
145
  tu = uinv
149
146
  (0...n).each do |i|
150
- endingInventory += (units[i] * price[i])
147
+ ending_inventory += (units[i] * price[i])
151
148
  tu += units[i]
152
149
  end
153
150
  if tu >= sinv
154
- costOfGoods = endingInventory / tu * sinv
155
- endingInventory = endingInventory / tu * (tu - sinv)
151
+ cost_of_goods = ending_inventory / tu * sinv
152
+ ending_inventory = ending_inventory / tu * (tu - sinv)
156
153
  else
157
154
  raise(FinrbError, "Inventory is not enough to sell\n")
158
155
  end
@@ -160,26 +157,26 @@ module Finrb
160
157
  when 'LIFO'
161
158
  (n - 1).downto(0).each do |i|
162
159
  if sinv <= units[i]
163
- costOfGoods += (sinv * price[i])
164
- endingInventory = (units[i] - sinv) * price[i]
160
+ cost_of_goods += (sinv * price[i])
161
+ ending_inventory = (units[i] - sinv) * price[i]
165
162
  if i > 1
166
163
  temp = i - 1
167
- (temp).downto(0).each do |j|
168
- endingInventory += (units[j] * price[j])
164
+ temp.downto(0).each do |j|
165
+ ending_inventory += (units[j] * price[j])
169
166
  end
170
167
  end
171
- endingInventory += (uinv * pinv)
168
+ ending_inventory += (uinv * pinv)
172
169
  sinv = 0
173
170
  next
174
171
  else
175
- costOfGoods += (units[i] * price[i])
172
+ cost_of_goods += (units[i] * price[i])
176
173
  sinv -= units[i]
177
174
  end
178
175
  end
179
176
  if sinv.positive?
180
177
  if sinv <= uinv
181
- costOfGoods += (sinv * pinv)
182
- endingInventory += ((uinv - sinv) * pinv)
178
+ cost_of_goods += (sinv * pinv)
179
+ ending_inventory += ((uinv - sinv) * pinv)
183
180
  else
184
181
  raise(FinrbError, "Inventory is not enough to sell\n")
185
182
  end
@@ -190,19 +187,21 @@ module Finrb
190
187
  raise(FinrbError, "length of units and price are not the same\n")
191
188
  end
192
189
 
193
- [costOfGoods, endingInventory]
190
+ {
191
+ cost_of_goods: cost_of_goods,
192
+ ending_inventory: ending_inventory
193
+ }
194
194
  end
195
195
 
196
196
  # current ratio -- Liquidity ratios measure the firm's ability to satisfy its short-term obligations as they come due.
197
197
  #
198
198
  # @param ca current assets
199
199
  # @param cl current liabilities
200
- # @export
201
- # @examples
202
- # Finrb::Utils.current_ratio(ca=8000,cl=2000)
203
- def self.current_ratio(ca, cl)
204
- ca = ca.to_d
205
- cl = cl.to_d
200
+ # @example
201
+ # Finrb::Utils.current_ratio(ca=8000,cl=2000)
202
+ def self.current_ratio(ca:, cl:)
203
+ ca = DecNum(ca.to_s)
204
+ cl = DecNum(cl.to_s)
206
205
 
207
206
  (ca / cl)
208
207
  end
@@ -212,24 +211,23 @@ module Finrb
212
211
  # @param cost cost of long-lived assets
213
212
  # @param rv residual value of the long-lived assets at the end of its useful life. DDB does not explicitly use the asset's residual value in the calculations, but depreciation ends once the estimated residual value has been reached. If the asset is expected to have no residual value, the DB method will never fully depreciate it, so the DB method is typically changed to straight-line at some point in the asset's life.
214
213
  # @param t length of the useful life
215
- # @export
216
- # @examples
217
- # ddb(cost=1200,rv=200,t=5)
218
- def self.ddb(cost, rv, t)
219
- cost = cost.to_d
220
- rv = rv.to_d
221
- t = t.to_d
214
+ # @example
215
+ # Finrb::Utils.ddb(cost=1200,rv=200,t=5)
216
+ def self.ddb(cost:, rv:, t:)
217
+ cost = DecNum(cost.to_s)
218
+ rv = DecNum(rv.to_s)
219
+ t = DecNum(t.to_s)
222
220
 
223
221
  raise(FinrbError, 't should be larger than 1') if t < 2
224
222
 
225
223
  ddb = [0] * t
226
- ddb[0] = 2 * cost / t
224
+ ddb[0] = cost * 2 / t
227
225
  if cost - ddb[0] <= rv
228
226
  ddb[0] = cost - rv
229
227
  else
230
228
  cost -= ddb[0]
231
229
  (1...t).each do |i|
232
- ddb[i] = 2 * cost / t
230
+ ddb[i] = cost * 2 / t
233
231
  if cost - ddb[i] <= rv
234
232
  ddb[i] = cost - rv
235
233
  break
@@ -238,19 +236,18 @@ module Finrb
238
236
  end
239
237
  end
240
238
  end
241
- { t: (0...t).to_a, ddb: }
239
+ { t: (0...t).to_a, ddb: ddb }
242
240
  end
243
241
 
244
242
  # debt ratio -- Solvency ratios measure the firm's ability to satisfy its long-term obligations.
245
243
  #
246
244
  # @param td total debt
247
245
  # @param ta total assets
248
- # @export
249
- # @examples
250
- # Finrb::Utils.debt_ratio(td=6000,ta=20000)
251
- def self.debt_ratio(td, ta)
252
- td = td.to_d
253
- ta = ta.to_d
246
+ # @example
247
+ # Finrb::Utils.debt_ratio(td=6000,ta=20000)
248
+ def self.debt_ratio(td:, ta:)
249
+ td = DecNum(td.to_s)
250
+ ta = DecNum(ta.to_s)
254
251
 
255
252
  (td / ta)
256
253
  end
@@ -266,25 +263,27 @@ module Finrb
266
263
  # @param cps shares from conversion of convertible preferred stock
267
264
  # @param cds shares from conversion of convertible debt
268
265
  # @param iss shares issuable from stock options
269
- # @export
270
- # @examples
271
- # Finrb::Utils.diluted_eps(ni=115600,pd=10000,cdi=42000,tax=0.4,w=200000,cds=60000)
272
- #
273
- # Finrb::Utils.diluted_eps(ni=115600,pd=10000,cpd=10000,w=200000,cps=40000)
274
- #
275
- # Finrb::Utils.diluted_eps(ni=115600,pd=10000,w=200000,iss=2500)
276
- #
277
- # Finrb::Utils.diluted_eps(ni=115600,pd=10000,cpd=10000,cdi=42000,tax=0.4,w=200000,cps=40000,cds=60000,iss=2500)
278
- def self.diluted_eps(ni, pd, w, cpd = 0, cdi = 0, tax = 0, cps = 0, cds = 0, iss = 0)
279
- ni = ni.to_d
280
- pd = pd.to_d
281
- w = w.to_d
282
- cpd = cpd.to_d
283
- cdi = cdi.to_d
284
- tax = tax.to_d
285
- cps = cps.to_d
286
- cds = cds.to_d
287
- iss = iss.to_d
266
+ # @example
267
+ # Finrb::Utils.diluted_eps(ni=115600,pd=10000,cdi=42000,tax=0.4,w=200000,cds=60000)
268
+ #
269
+ # @example
270
+ # Finrb::Utils.diluted_eps(ni=115600,pd=10000,cpd=10000,w=200000,cps=40000)
271
+ #
272
+ # @example
273
+ # Finrb::Utils.diluted_eps(ni=115600,pd=10000,w=200000,iss=2500)
274
+ #
275
+ # @example
276
+ # Finrb::Utils.diluted_eps(ni=115600,pd=10000,cpd=10000,cdi=42000,tax=0.4,w=200000,cps=40000,cds=60000,iss=2500)
277
+ def self.diluted_eps(ni:, pd:, w:, cpd: 0, cdi: 0, tax: 0, cps: 0, cds: 0, iss: 0)
278
+ ni = DecNum(ni.to_s)
279
+ pd = DecNum(pd.to_s)
280
+ w = DecNum(w.to_s)
281
+ cpd = DecNum(cpd.to_s)
282
+ cdi = DecNum(cdi.to_s)
283
+ tax = DecNum(tax.to_s)
284
+ cps = DecNum(cps.to_s)
285
+ cds = DecNum(cds.to_s)
286
+ iss = DecNum(iss.to_s)
288
287
 
289
288
  basic = (ni - pd) / w
290
289
  diluted = (ni - pd + cpd + (cdi * (1 - tax))) / (w + cps + cds + iss)
@@ -301,23 +300,22 @@ module Finrb
301
300
  # @param type payments occur at the end of each period (type=0); payments occur at the beginning of each period (type=1)
302
301
  # @param lower the lower end points of the rate of return to be searched.
303
302
  # @param upper the upper end points of the rate of return to be searched.
304
- # @importFrom stats uniroot
305
- # @export
306
- # @examples
307
- # Finrb::Utils.discount_rate(n=5,pv=0,fv=600,pmt=-100,type=0)
308
- def self.discount_rate(n, pv, fv, pmt, type = 0, lower = 0.0001, upper = 100)
309
- n = n.to_d
310
- pv = pv.to_d
311
- fv = fv.to_d
312
- pmt = pmt.to_d
313
- type = type.to_d
314
- lower = lower.to_d
315
- upper = upper.to_d
303
+ # @example
304
+ # Finrb::Utils.discount_rate(n=5,pv=0,fv=600,pmt=-100,type=0)
305
+ def self.discount_rate(n:, pv:, fv:, pmt:, type: 0, lower: 0.0001, upper: 100)
306
+ n = DecNum(n.to_s)
307
+ pv = DecNum(pv.to_s)
308
+ fv = DecNum(fv.to_s)
309
+ pmt = DecNum(pmt.to_s)
310
+ type = DecNum(type.to_s)
311
+ lower = DecNum(lower.to_s)
312
+ upper = DecNum(upper.to_s)
316
313
 
317
314
  nlfunc = NlFunctionStub.new
318
- nlfunc.func = lambda do |x|
319
- BigDecimal((Finrb::Utils.fv_simple(x[0],n,pv) + Finrb::Utils.fv_annuity(x[0],n,pmt,type) - fv).to_s)
320
- end
315
+ nlfunc.func =
316
+ lambda do |x|
317
+ [BigDecimal((Finrb::Utils.fv_simple(r: x[0], n: n, pv: pv) + Finrb::Utils.fv_annuity(r: x[0], n: n, pmt: pmt, type: type) - fv).to_s)]
318
+ end
321
319
 
322
320
  root = [(upper - lower) / 2]
323
321
  nlsolve(nlfunc, root)
@@ -328,97 +326,100 @@ module Finrb
328
326
  #
329
327
  # @param r stated annual rate
330
328
  # @param m number of compounding periods per year
331
- # @export
332
- # @examples
333
- # ear(r=0.12,m=12)
329
+ # @example
330
+ # Finrb::Utils.ear(r=0.12,m=12)
334
331
  #
335
- # ear(0.04,365)
336
- def self.ear(r, m)
337
- r = r.to_d
338
- m = m.to_d
332
+ # @example
333
+ # Finrb::Utils.ear(0.04,365)
334
+ def self.ear(r:, m:)
335
+ r = DecNum(r.to_s)
336
+ m = DecNum(m.to_s)
339
337
 
340
- (((1 + (r / m))**m) - 1)
338
+ ((((r / m) + 1)**m) - 1)
341
339
  end
342
340
 
343
341
  # Convert stated annual rate to the effective annual rate with continuous compounding
344
342
  #
345
343
  # @param r stated annual rate
346
- # @export
347
- # @examples
348
- # Finrb::Utils.ear_continuous(r=0.1)
344
+ # @example
345
+ # Finrb::Utils.ear_continuous(r=0.1)
349
346
  #
350
- # Finrb::Utils.ear_continuous(0.03)
351
- def self.ear_continuous(r)
352
- r = r.to_d
347
+ # @example
348
+ # Finrb::Utils.ear_continuous(0.03)
349
+ def self.ear_continuous(r:)
350
+ r = DecNum(r.to_s)
353
351
 
354
- (r.to_d.exp - 1)
352
+ (r.to_dec.exp - 1)
355
353
  end
356
354
 
357
355
  # bond-equivalent yield (BEY), 2 x the semiannual discount rate
358
356
  #
359
357
  # @param ear effective annual rate
360
- # @export
361
- # @examples
362
- # ear2bey(ear=0.08)
363
- def self.ear2bey(ear)
364
- ear = ear.to_d
358
+ # @example
359
+ # Finrb::Utils.ear2bey(ear=0.08)
360
+ def self.ear2bey(ear:)
361
+ ear = DecNum(ear.to_s)
365
362
 
366
- ((((1 + ear)**0.5) - 1) * 2)
363
+ ((((ear + 1)**0.5) - 1) * 2)
367
364
  end
368
365
 
369
366
  # Computing HPR, the holding period return
370
367
  #
371
368
  # @param ear effective annual rate
372
369
  # @param t number of days remaining until maturity
373
- # @export
374
- # @examples
375
- # ear2hpr(ear=0.05039,t=150)
376
- def self.ear2hpr(ear, t)
377
- ear = ear.to_d
378
- t = t.to_d
379
-
380
- (((1 + ear)**(t / 365)) - 1)
370
+ # @example
371
+ # Finrb::Utils.ear2hpr(ear=0.05039,t=150)
372
+ def self.ear2hpr(ear:, t:)
373
+ ear = DecNum(ear.to_s)
374
+ t = DecNum(t.to_s)
375
+
376
+ (((ear + 1)**(t / 365)) - 1)
381
377
  end
382
378
 
383
379
  # Equivalent/proportional Interest Rates
384
- # @description An interest rate to be applied n times p.a. can be converted to an equivalent rate to be applied p times p.a.
380
+ # @note An interest rate to be applied n times p.a. can be converted to an equivalent rate to be applied p times p.a.
385
381
  # @param r interest rate to be applied n times per year (r is annual rate!)
386
382
  # @param n times that the interest rate r were compounded per year
387
383
  # @param p times that the equivalent rate were compounded per year
388
384
  # @param type equivalent interest rates ('e',default) or proportional interest rates ('p')
389
- # @export
390
- # @examples
391
- # # monthly interest rat equivalent to 5% compounded per year
392
- # Finrb::Utils.eir(r=0.05,n=1,p=12)
393
- #
394
- # # monthly interest rat equivalent to 5% compounded per half year
395
- # Finrb::Utils.eir(r=0.05,n=2,p=12)
396
- #
397
- # # monthly interest rat equivalent to 5% compounded per quarter
398
- # Finrb::Utils.eir(r=0.05,n=4,p=12)
399
- #
400
- # # annual interest rate equivalent to 5% compounded per month
401
- # Finrb::Utils.eir(r=0.05,n=12,p=1)
402
- # # this is equivalent to
403
- # ear(r=0.05,m=12)
404
- #
405
- # # quarter interest rate equivalent to 5% compounded per year
406
- # Finrb::Utils.eir(r=0.05,n=1,p=4)
407
- #
408
- # # quarter interest rate equivalent to 5% compounded per month
409
- # Finrb::Utils.eir(r=0.05,n=12,p=4)
410
- #
411
- # # monthly proportional interest rate which is equivalent to a simple annual interest
412
- # Finrb::Utils.eir(r=0.05,p=12,type='p')
413
- def self.eir(r, n = 1, p = 12, type = 'e')
414
- r = r.to_d
415
- n = n.to_d
416
- p = p.to_d
385
+ # @example
386
+ # # monthly interest rat equivalent to 5% compounded per year
387
+ # Finrb::Utils.eir(r=0.05,n=1,p=12)
388
+ #
389
+ # @example
390
+ # # monthly interest rat equivalent to 5% compounded per half year
391
+ # Finrb::Utils.eir(r=0.05,n=2,p=12)
392
+ #
393
+ # @example
394
+ # # monthly interest rat equivalent to 5% compounded per quarter
395
+ # Finrb::Utils.eir(r=0.05,n=4,p=12)
396
+ #
397
+ # @example
398
+ # # annual interest rate equivalent to 5% compounded per month
399
+ # Finrb::Utils.eir(r=0.05,n=12,p=1)
400
+ # # this is equivalent to
401
+ # Finrb::Utils.ear(r=0.05,m=12)
402
+ #
403
+ # @example
404
+ # # quarter interest rate equivalent to 5% compounded per year
405
+ # Finrb::Utils.eir(r=0.05,n=1,p=4)
406
+ #
407
+ # @example
408
+ # # quarter interest rate equivalent to 5% compounded per month
409
+ # Finrb::Utils.eir(r=0.05,n=12,p=4)
410
+ #
411
+ # @example
412
+ # # monthly proportional interest rate which is equivalent to a simple annual interest
413
+ # Finrb::Utils.eir(r=0.05,p=12,type='p')
414
+ def self.eir(r:, n: 1, p: 12, type: 'e')
415
+ r = DecNum(r.to_s)
416
+ n = DecNum(n.to_s)
417
+ p = DecNum(p.to_s)
417
418
  type = type.to_s
418
419
 
419
420
  case type
420
421
  when 'e'
421
- eir = ((1 + (r / n))**(n / p)) - 1
422
+ eir = (((r / n) + 1)**(n / p)) - 1
422
423
  when 'p'
423
424
  eir = r / p
424
425
  else
@@ -432,13 +433,12 @@ module Finrb
432
433
  # @param ni net income
433
434
  # @param pd preferred dividends
434
435
  # @param w weighted average number of common shares outstanding
435
- # @export
436
- # @examples
437
- # Finrb::Utils.eps(ni=10000,pd=1000,w=11000)
438
- def self.eps(ni, pd, w)
439
- ni = ni.to_d
440
- pd = pd.to_d
441
- w = w.to_d
436
+ # @example
437
+ # Finrb::Utils.eps(ni=10000,pd=1000,w=11000)
438
+ def self.eps(ni:, pd:, w:)
439
+ ni = DecNum(ni.to_s)
440
+ pd = DecNum(pd.to_s)
441
+ w = DecNum(w.to_s)
442
442
 
443
443
  ((ni - pd) / w)
444
444
  end
@@ -447,12 +447,11 @@ module Finrb
447
447
  #
448
448
  # @param te total equity
449
449
  # @param ta total assets
450
- # @export
451
- # @examples
452
- # Finrb::Utils.financial_leverage(te=16000,ta=20000)
453
- def self.financial_leverage(te, ta)
454
- te = te.to_d
455
- ta = ta.to_d
450
+ # @example
451
+ # Finrb::Utils.financial_leverage(te=16000,ta=20000)
452
+ def self.financial_leverage(te:, ta:)
453
+ te = DecNum(te.to_s)
454
+ ta = DecNum(ta.to_s)
456
455
 
457
456
  (ta / te)
458
457
  end
@@ -464,20 +463,19 @@ module Finrb
464
463
  # @param pv present value
465
464
  # @param pmt payment per period
466
465
  # @param type payments occur at the end of each period (type=0); payments occur at the beginning of each period (type=1)
467
- # @export
468
- # @examples
469
- # fv(r=0.07,n=10,pv=1000,pmt=10)
470
- def self.fv(r, n, pv = 0, pmt = 0, type = 0)
471
- r = r.to_d
472
- n = n.to_d
473
- pv = pv.to_d
474
- pmt = pmt.to_d
475
- type = type.to_d
466
+ # @example
467
+ # Finrb::Utils.fv(r=0.07,n=10,pv=1000,pmt=10)
468
+ def self.fv(r:, n:, pv: 0, pmt: 0, type: 0)
469
+ r = DecNum(r.to_s)
470
+ n = DecNum(n.to_s)
471
+ pv = DecNum(pv.to_s)
472
+ pmt = DecNum(pmt.to_s)
473
+ type = DecNum(type.to_s)
476
474
 
477
475
  if type != 0 && type != 1
478
476
  raise(FinrbError, 'Error: type should be 0 or 1!')
479
477
  else
480
- (Finrb::Utils.fv_simple(r, n, pv) + Finrb::Utils.fv_annuity(r, n, pmt, type))
478
+ (Finrb::Utils.fv_simple(r: r, n: n, pv: pv) + Finrb::Utils.fv_annuity(r: r, n: n, pmt: pmt, type: type))
481
479
  end
482
480
  end
483
481
 
@@ -487,21 +485,21 @@ module Finrb
487
485
  # @param n number of periods
488
486
  # @param pmt payment per period
489
487
  # @param type payments occur at the end of each period (type=0); payments occur at the beginning of each period (type=1)
490
- # @export
491
- # @examples
492
- # Finrb::Utils.fv_annuity(0.03,12,-1000)
488
+ # @example
489
+ # Finrb::Utils.fv_annuity(0.03,12,-1000)
493
490
  #
494
- # Finrb::Utils.fv_annuity(r=0.03,n=12,pmt=-1000,type=1)
495
- def self.fv_annuity(r, n, pmt, type = 0)
496
- r = r.to_d
497
- n = n.to_d
498
- pmt = pmt.to_d
499
- type = type.to_d
491
+ # @example
492
+ # Finrb::Utils.fv_annuity(r=0.03,n=12,pmt=-1000,type=1)
493
+ def self.fv_annuity(r:, n:, pmt:, type: 0)
494
+ r = DecNum(r.to_s)
495
+ n = DecNum(n.to_s)
496
+ pmt = DecNum(pmt.to_s)
497
+ type = DecNum(type.to_s)
500
498
 
501
499
  if type != 0 && type != 1
502
500
  raise(FinrbError, 'Error: type should be 0 or 1!')
503
501
  else
504
- (pmt / r * (((1 + r)**n) - 1)) * ((1 + r)**type) * -1
502
+ (pmt / r * (((r + 1)**n) - 1)) * ((r + 1)**type) * -1
505
503
 
506
504
  end
507
505
  end
@@ -511,35 +509,34 @@ module Finrb
511
509
  # @param r discount rate, or the interest rate at which the amount will be compounded each period
512
510
  # @param n number of periods
513
511
  # @param pv present value
514
- # @export
515
- # @examples
516
- # Finrb::Utils.fv_simple(0.08,10,-300)
512
+ # @example
513
+ # Finrb::Utils.fv_simple(0.08,10,-300)
517
514
  #
518
- # Finrb::Utils.fv_simple(r=0.04,n=20,pv=-50000)
519
- def self.fv_simple(r, n, pv)
520
- r = r.to_d
521
- n = n.to_d
522
- pv = pv.to_d
515
+ # @example
516
+ # Finrb::Utils.fv_simple(r=0.04,n=20,pv=-50000)
517
+ def self.fv_simple(r:, n:, pv:)
518
+ r = DecNum(r.to_s)
519
+ n = DecNum(n.to_s)
520
+ pv = DecNum(pv.to_s)
523
521
 
524
- ((pv * ((1 + r)**n)) * -1)
522
+ ((pv * ((r + 1)**n)) * -1)
525
523
  end
526
524
 
527
525
  # Computing the future value of an uneven cash flow series
528
526
  #
529
527
  # @param r stated annual rate
530
528
  # @param cf uneven cash flow
531
- # @export
532
- # @examples
533
- # Finrb::Utils.fv_uneven(r=0.1, cf=c(-1000, -500, 0, 4000, 3500, 2000))
534
- def self.fv_uneven(r, cf)
535
- r = r.to_d
536
- cf = Array.wrap(cf).map(&:to_d)
529
+ # @example
530
+ # Finrb::Utils.fv_uneven(r=0.1, cf=[-1000, -500, 0, 4000, 3500, 2000])
531
+ def self.fv_uneven(r:, cf:)
532
+ r = DecNum(r.to_s)
533
+ cf = Array.wrap(cf).map { |value| DecNum(value.to_s) }
537
534
 
538
535
  m = cf.size
539
536
  sum = 0
540
537
  (0...m).each do |i|
541
- n = m - i
542
- sum += Finrb::Utils.fv_simple(r, n, cf[i])
538
+ n = m - (i + 1)
539
+ sum += Finrb::Utils.fv_simple(r: r, n: n, pv: cf[i])
543
540
  end
544
541
  sum
545
542
  end
@@ -547,39 +544,36 @@ module Finrb
547
544
  # Geometric mean return
548
545
  #
549
546
  # @param r returns over multiple periods
550
- # @export
551
- # @examples
552
- # Finrb::Utils.geometric_mean(r=c(-0.0934, 0.2345, 0.0892))
553
- def self.geometric_mean(r)
554
- r = Array.wrap(r).map(&:to_d)
555
-
556
- rs = r + 1
557
- ((rs.reduce(:*)**(1 / rs.size)) - 1)
547
+ # @example
548
+ # Finrb::Utils.geometric_mean(r=[-0.0934, 0.2345, 0.0892])
549
+ def self.geometric_mean(r:)
550
+ r = Array.wrap(r).map { |value| DecNum(value.to_s) }
551
+
552
+ rs = r.map { |value| value + 1 }
553
+ ((rs.reduce(:*)**(1.to_f / rs.size)) - 1)
558
554
  end
559
555
 
560
556
  # gross profit margin -- Evaluate a company's financial performance
561
557
  #
562
558
  # @param gp gross profit, equal to revenue minus cost of goods sold (cogs)
563
559
  # @param rv revenue (sales)
564
- # @export
565
- # @examples
566
- # gpm(gp=1000,rv=20000)
567
- def self.gpm(gp, rv)
568
- gp = gp.to_d
569
- rv = rv.to_d
560
+ # @example
561
+ # Finrb::Utils.gpm(gp=1000,rv=20000)
562
+ def self.gpm(gp:, rv:)
563
+ gp = DecNum(gp.to_s)
564
+ rv = DecNum(rv.to_s)
570
565
 
571
566
  (gp / rv)
572
567
  end
573
568
 
574
569
  # harmonic mean, average price
575
570
  # @param p price over multiple periods
576
- # @export
577
- # @examples
578
- # Finrb::Utils.harmonic_mean(p=c(8,9,10))
579
- def self.harmonic_mean(p)
580
- p = Array.wrap(p).map(&:to_d)
571
+ # @example
572
+ # Finrb::Utils.harmonic_mean(p=[8,9,10])
573
+ def self.harmonic_mean(p:)
574
+ p = Array.wrap(p).map { |value| DecNum(value.to_s) }
581
575
 
582
- (1 / (p.sum { |val| 1 / val } / p.size))
576
+ (1.to_f / (p.sum { |val| 1.to_f / val } / p.size))
583
577
  end
584
578
 
585
579
  # Computing HPR, the holding period return
@@ -587,13 +581,12 @@ module Finrb
587
581
  # @param ev ending value
588
582
  # @param bv beginning value
589
583
  # @param cfr cash flow received
590
- # @export
591
- # @examples
592
- # hpr(ev=33,bv=30,cfr=0.5)
593
- def self.hpr(ev, bv, cfr = 0)
594
- ev = ev.to_d
595
- bv = bv.to_d
596
- cfr = cfr.to_d
584
+ # @example
585
+ # Finrb::Utils.hpr(ev=33,bv=30,cfr=0.5)
586
+ def self.hpr(ev:, bv:, cfr: 0)
587
+ ev = DecNum(ev.to_s)
588
+ bv = DecNum(bv.to_s)
589
+ cfr = DecNum(cfr.to_s)
597
590
 
598
591
  ((ev - bv + cfr) / bv)
599
592
  end
@@ -602,122 +595,72 @@ module Finrb
602
595
  #
603
596
  # @param hpr holding period return
604
597
  # @param t number of month remaining until maturity
605
- # @export
606
- # @examples
607
- # hpr2bey(hpr=0.02,t=3)
608
- def self.hpr2bey(hpr, t)
609
- hpr = hpr.to_d
610
- t = t.to_d
611
-
612
- ((((1 + hpr)**(6 / t)) - 1) * 2)
598
+ # @example
599
+ # Finrb::Utils.hpr2bey(hpr=0.02,t=3)
600
+ def self.hpr2bey(hpr:, t:)
601
+ hpr = DecNum(hpr.to_s)
602
+ t = DecNum(t.to_s)
603
+
604
+ ((((hpr + 1)**(6 / t)) - 1) * 2)
613
605
  end
614
606
 
615
607
  # Convert holding period return to the effective annual rate
616
608
  #
617
609
  # @param hpr holding period return
618
610
  # @param t number of days remaining until maturity
619
- # @export
620
- # @examples
621
- # hpr2ear(hpr=0.015228,t=120)
622
- def self.hpr2ear(hpr, t)
623
- hpr = hpr.to_d
624
- t = t.to_d
625
-
626
- (((1 + hpr)**(365 / t)) - 1)
611
+ # @example
612
+ # Finrb::Utils.hpr2ear(hpr=0.015228,t=120)
613
+ def self.hpr2ear(hpr:, t:)
614
+ hpr = DecNum(hpr.to_s)
615
+ t = DecNum(t.to_s)
616
+
617
+ (((hpr + 1)**(365 / t)) - 1)
627
618
  end
628
619
 
629
620
  # Computing money market yield (MMY) for a T-bill
630
621
  #
631
622
  # @param hpr holding period return
632
623
  # @param t number of days remaining until maturity
633
- # @export
634
- # @examples
635
- # hpr2mmy(hpr=0.01523,t=120)
636
- def self.hpr2mmy(hpr, t)
637
- hpr = hpr.to_d
638
- t = t.to_d
639
-
640
- (360 * hpr / t)
624
+ # @example
625
+ # Finrb::Utils.hpr2mmy(hpr=0.01523,t=120)
626
+ def self.hpr2mmy(hpr:, t:)
627
+ hpr = DecNum(hpr.to_s)
628
+ t = DecNum(t.to_s)
629
+
630
+ (hpr * 360 / t)
641
631
  end
642
632
 
643
633
  # Computing IRR, the internal rate of return
644
634
  #
645
635
  # @param cf cash flow,the first cash flow is the initial outlay
646
- # @importFrom stats uniroot
647
- # @export
648
- # @examples
649
- # irr(cf=c(-5, 1.6, 2.4, 2.8))
650
- def self.irr(cf)
651
- cf = Array.wrap(cf).map(&:to_d)
636
+ # @example
637
+ # Finrb::Utils.irr(cf=[-5, 1.6, 2.4, 2.8])
638
+ def self.irr(cf:)
639
+ cf = Array.wrap(cf).map { |value| DecNum(value.to_s) }
652
640
 
653
- n = cf.size
654
641
  subcf = cf.drop(1)
655
-
656
642
  nlfunc = NlFunctionStub.new
657
- nlfunc.func = lambda do |x|
658
- BigDecimal((-1 * Finrb::Utils.pv_uneven(x[0], subcf) + cf[0]).to_s)
659
- end
643
+ nlfunc.func =
644
+ lambda do |x|
645
+ [BigDecimal(((Finrb::Utils.pv_uneven(r: x[0], cf: subcf) * -1) + cf[0]).to_s)]
646
+ end
660
647
 
661
648
  root = [0]
662
649
  nlsolve(nlfunc, root)
663
650
  root[0]
664
651
  end
665
652
 
666
- # Computing IRR, the internal rate of return
667
- # @description This function is the same as irr but can calculate negative value. This function may take a very long time. You can use larger cutoff and larger step to get a less precision irr first. Then based on the result, change from and to, to narrow down the interval, and use a smaller step to get a more precision irr.
668
- # @param cf cash flow,the first cash flow is the initial outlay
669
- # @param cutoff threshold to take npv as zero
670
- # @param from smallest irr to try
671
- # @param to largest irr to try
672
- # @param step increment of the irr
673
- # @export
674
- # @examples
675
- # irr2(cf=c(-5, 1.6, 2.4, 2.8))
676
- # irr2(cf=c(-200, 50, 60, -70, 30, 20))
677
- def self.irr2(cf, cutoff = 0.1, from = -1, to = 10, step = 0.000001)
678
- cf = Array.wrap(cf).map(&:to_d)
679
- cutoff = cutoff.to_d
680
- from = from.to_d
681
- to = to.to_d
682
- step = step.to_d
683
-
684
- r0 = nil
685
- n = cf.size
686
- from.step((to - 1), step).each do |r|
687
- npv = cf[0]
688
- (1...n).each do |i|
689
- npv += (cf[i] / ((1 + r)**(i - 1)))
690
- end
691
- next if npv.nil?
692
-
693
- if npv.abs < cutoff
694
- r0 = r
695
- break
696
- end
697
- end
698
-
699
- if r0.nil?
700
- raise(
701
- FinrbError,
702
- 'can not find irr in the given interval, you can try smaller step, and/or larger to, and/or larger cutoff'
703
- )
704
- end
705
-
706
- r0
707
- end
708
-
709
653
  # calculate the net increase in common shares from the potential exercise of stock options or warrants
710
654
  #
711
655
  # @param amp average market price over the year
712
656
  # @param ep exercise price of the options or warrants
713
657
  # @param n number of common shares that the options and warrants can be convened into
714
- # @export
715
- # @examples
716
- # iss(amp=20,ep=15,n=10000)
717
- def self.iss(amp, ep, n)
718
- amp = amp.to_d
719
- ep = ep.to_d
720
- n = n.to_d
658
+ # @example
659
+ # Finrb::Utils.iss(amp=20,ep=15,n=10000)
660
+ def self.iss(amp:, ep:, n:)
661
+ amp = DecNum(amp.to_s)
662
+ ep = DecNum(ep.to_s)
663
+ n = DecNum(n.to_s)
721
664
 
722
665
  if amp > ep
723
666
  ((amp - ep) * n / amp)
@@ -730,12 +673,11 @@ module Finrb
730
673
  #
731
674
  # @param ltd long-term debt
732
675
  # @param te total equity
733
- # @export
734
- # @examples
735
- # Finrb::Utils.lt_d2e(ltd=8000,te=20000)
736
- def self.lt_d2e(ltd, te)
737
- ltd = ltd.to_d
738
- te = te.to_d
676
+ # @example
677
+ # Finrb::Utils.lt_d2e(ltd=8000,te=20000)
678
+ def self.lt_d2e(ltd:, te:)
679
+ ltd = DecNum(ltd.to_s)
680
+ te = DecNum(te.to_s)
739
681
 
740
682
  (ltd / te)
741
683
  end
@@ -744,12 +686,11 @@ module Finrb
744
686
  #
745
687
  # @param mmy money market yield
746
688
  # @param t number of days remaining until maturity
747
- # @export
748
- # @examples
749
- # mmy2hpr(mmy=0.04898,t=150)
750
- def self.mmy2hpr(mmy, t)
751
- mmy = mmy.to_d
752
- t = t.to_d
689
+ # @example
690
+ # Finrb::Utils.mmy2hpr(mmy=0.04898,t=150)
691
+ def self.mmy2hpr(mmy:, t:)
692
+ mmy = DecNum(mmy.to_s)
693
+ t = DecNum(t.to_s)
753
694
 
754
695
  (mmy * t / 360)
755
696
  end
@@ -761,22 +702,22 @@ module Finrb
761
702
  # @param fv future value
762
703
  # @param pmt payment per period
763
704
  # @param type payments occur at the end of each period (type=0); payments occur at the beginning of each period (type=1)
764
- # @export
765
- # @examples
766
- # Finrb::Utils.n_period(0.1,-10000,60000000,-50000,0)
767
- #
768
- # Finrb::Utils.n_period(r=0.1,pv=-10000,fv=60000000,pmt=-50000,type=1)
769
- def self.n_period(r, pv, fv, pmt, type = 0)
770
- r = r.to_d
771
- pv = pv.to_d
772
- fv = fv.to_d
773
- pmt = pmt.to_d
774
- type = type.to_d
705
+ # @example
706
+ # Finrb::Utils.n_period(0.1,-10000,60000000,-50000,0)
707
+ #
708
+ # @example
709
+ # Finrb::Utils.n_period(r=0.1,pv=-10000,fv=60000000,pmt=-50000,type=1)
710
+ def self.n_period(r:, pv:, fv:, pmt:, type: 0)
711
+ r = DecNum(r.to_s)
712
+ pv = DecNum(pv.to_s)
713
+ fv = DecNum(fv.to_s)
714
+ pmt = DecNum(pmt.to_s)
715
+ type = DecNum(type.to_s)
775
716
 
776
717
  if type != 0 && type != 1
777
718
  raise(FinrbError, 'Error: type should be 0 or 1!')
778
719
  else
779
- (-1 * ((fv * r) - (pmt * ((1 + r)**type))) / ((pv * r) + (pmt * ((1 + r)**type)))).to_d.log / (1 + r).to_d.log
720
+ (((fv * r) - (pmt * ((r + 1)**type))) * -1 / ((pv * r) + (pmt * ((r + 1)**type)))).to_dec.log / (r + 1).to_dec.log
780
721
 
781
722
  end
782
723
  end
@@ -785,12 +726,11 @@ module Finrb
785
726
  #
786
727
  # @param ni net income
787
728
  # @param rv revenue (sales)
788
- # @export
789
- # @examples
790
- # npm(ni=8000,rv=20000)
791
- def self.npm(ni, rv)
792
- ni = ni.to_d
793
- rv = rv.to_d
729
+ # @example
730
+ # Finrb::Utils.npm(ni=8000,rv=20000)
731
+ def self.npm(ni:, rv:)
732
+ ni = DecNum(ni.to_s)
733
+ rv = DecNum(rv.to_s)
794
734
 
795
735
  (ni / rv)
796
736
  end
@@ -799,16 +739,14 @@ module Finrb
799
739
  #
800
740
  # @param r discount rate, or the interest rate at which the amount will be compounded each period
801
741
  # @param cf cash flow,the first cash flow is the initial outlay
802
- # @export
803
- # @examples
804
- # npv(r=0.12, cf=c(-5, 1.6, 2.4, 2.8))
805
- def self.npv(r, cf)
806
- r = r.to_d
807
- cf = Array.wrap(cf).map(&:to_d)
742
+ # @example
743
+ # Finrb::Utils.npv(r=0.12, cf=[-5, 1.6, 2.4, 2.8])
744
+ def self.npv(r:, cf:)
745
+ r = DecNum(r.to_s)
746
+ cf = Array.wrap(cf).map { |value| DecNum(value.to_s) }
808
747
 
809
- n = cf.size
810
748
  subcf = cf.drop(1)
811
- ((-1 * Finrb::Utils.pv_uneven(r, subcf)) + cf[0])
749
+ ((Finrb::Utils.pv_uneven(r: r, cf: subcf) * -1) + cf[0])
812
750
  end
813
751
 
814
752
  # Estimate period payment
@@ -818,25 +756,25 @@ module Finrb
818
756
  # @param pv present value
819
757
  # @param fv future value
820
758
  # @param type payments occur at the end of each period (type=0); payments occur at the beginning of each period (type=1)
821
- # @export
822
- # @examples
823
- # pmt(0.08,10,-1000,10)
759
+ # @example
760
+ # Finrb::Utils.pmt(0.08,10,-1000,10)
824
761
  #
825
- # pmt(r=0.08,n=10,pv=-1000,fv=0)
762
+ # @example
763
+ # Finrb::Utils.pmt(r=0.08,n=10,pv=-1000,fv=0)
826
764
  #
827
- # pmt(0.08,10,-1000,10,1)
828
- def self.pmt(r, n, pv, fv, type = 0)
829
- r = r.to_d
830
- n = n.to_d
831
- pv = pv.to_d
832
- fv = fv.to_d
833
- type = type.to_d
765
+ # @example
766
+ # Finrb::Utils.pmt(0.08,10,-1000,10,1)
767
+ def self.pmt(r:, n:, pv:, fv:, type: 0)
768
+ r = DecNum(r.to_s)
769
+ n = DecNum(n.to_s)
770
+ pv = DecNum(pv.to_s)
771
+ fv = DecNum(fv.to_s)
772
+ type = DecNum(type.to_s)
834
773
 
835
774
  if type != 0 && type != 1
836
775
  raise(FinrbError, 'Error: type should be 0 or 1!')
837
776
  else
838
- (pv + (fv / ((1 + r)**n))) * r / (1 - (1 / ((1 + r)**n))) * -1 * ((1 + r)**(-1 * type))
839
-
777
+ (pv + (fv / ((r + 1)**n))) * r / (1 - (1.to_f / ((r + 1)**n))) * -1 * ((r + 1)**(type * -1))
840
778
  end
841
779
  end
842
780
 
@@ -847,22 +785,22 @@ module Finrb
847
785
  # @param fv future value
848
786
  # @param pmt payment per period
849
787
  # @param type payments occur at the end of each period (type=0); payments occur at the beginning of each period (type=1)
850
- # @export
851
- # @examples
852
- # pv(0.07,10,1000,10)
853
- #
854
- # pv(r=0.05,n=20,fv=1000,pmt=10,type=1)
855
- def self.pv(r, n, fv = 0, pmt = 0, type = 0)
856
- r = r.to_d
857
- n = n.to_d
858
- fv = fv.to_d
859
- pmt = pmt.to_d
860
- type = type.to_d
788
+ # @example
789
+ # Finrb::Utils.pv(0.07,10,1000,10)
790
+ #
791
+ # @example
792
+ # Finrb::Utils.pv(r=0.05,n=20,fv=1000,pmt=10,type=1)
793
+ def self.pv(r:, n:, fv: 0, pmt: 0, type: 0)
794
+ r = DecNum(r.to_s)
795
+ n = DecNum(n.to_s)
796
+ fv = DecNum(fv.to_s)
797
+ pmt = DecNum(pmt.to_s)
798
+ type = DecNum(type.to_s)
861
799
 
862
800
  if type != 0 && type != 1
863
801
  raise(FinrbError, 'Error: type should be 0 or 1!')
864
802
  else
865
- Finrb::Utils.pv_simple(r, n, fv) + Finrb::Utils.pv_annuity(r, n, pmt, type)
803
+ Finrb::Utils.pv_simple(r: r, n: n, fv: fv) + Finrb::Utils.pv_annuity(r: r, n: n, pmt: pmt, type: type)
866
804
 
867
805
  end
868
806
  end
@@ -873,21 +811,21 @@ module Finrb
873
811
  # @param n number of periods
874
812
  # @param pmt payment per period
875
813
  # @param type payments occur at the end of each period (type=0); payments occur at the beginning of each period (type=1)
876
- # @export
877
- # @examples
878
- # Finrb::Utils.pv_annuity(0.03,12,1000)
814
+ # @example
815
+ # Finrb::Utils.pv_annuity(0.03,12,1000)
879
816
  #
880
- # Finrb::Utils.pv_annuity(r=0.0425,n=3,pmt=30000)
881
- def self.pv_annuity(r, n, pmt, type = 0)
882
- r = r.to_d
883
- n = n.to_d
884
- pmt = pmt.to_d
885
- type = type.to_d
817
+ # @example
818
+ # Finrb::Utils.pv_annuity(r=0.0425,n=3,pmt=30000)
819
+ def self.pv_annuity(r:, n:, pmt:, type: 0)
820
+ r = DecNum(r.to_s)
821
+ n = DecNum(n.to_s)
822
+ pmt = DecNum(pmt.to_s)
823
+ type = DecNum(type.to_s)
886
824
 
887
825
  if type != 0 && type != 1
888
826
  raise(FinrbError, 'Error: type should be 0 or 1!')
889
827
  else
890
- (pmt / r * (1 - (1 / ((1 + r)**n)))) * ((1 + r)**type) * -1
828
+ (pmt / r * (1 - (1.to_f / ((r + 1)**n)))) * ((r + 1)**type) * -1
891
829
 
892
830
  end
893
831
  end
@@ -898,25 +836,26 @@ module Finrb
898
836
  # @param g growth rate of perpetuity
899
837
  # @param pmt payment per period
900
838
  # @param type payments occur at the end of each period (type=0); payments occur at the beginning of each period (type=1)
901
- # @export
902
- # @examples
903
- # Finrb::Utils.pv_perpetuity(r=0.1,pmt=1000,g=0.02)
839
+ # @example
840
+ # Finrb::Utils.pv_perpetuity(r=0.1,pmt=1000,g=0.02)
904
841
  #
905
- # Finrb::Utils.pv_perpetuity(r=0.1,pmt=1000,type=1)
842
+ # @example
843
+ # Finrb::Utils.pv_perpetuity(r=0.1,pmt=1000,type=1)
906
844
  #
907
- # Finrb::Utils.pv_perpetuity(r=0.1,pmt=1000)
908
- def self.pv_perpetuity(r, pmt, g = 0, type = 0)
909
- r = r.to_d
910
- pmt = pmt.to_d
911
- g = g.to_d
912
- type = type.to_d
845
+ # @example
846
+ # Finrb::Utils.pv_perpetuity(r=0.1,pmt=1000)
847
+ def self.pv_perpetuity(r:, pmt:, g: 0, type: 0)
848
+ r = DecNum(r.to_s)
849
+ pmt = DecNum(pmt.to_s)
850
+ g = DecNum(g.to_s)
851
+ type = DecNum(type.to_s)
913
852
 
914
853
  if type != 0 && type != 1
915
854
  raise(FinrbError, 'Error: type should be 0 or 1!')
916
855
  elsif g >= r
917
856
  raise(FinrbError, 'Error: g is not smaller than r!')
918
857
  else
919
- (pmt / (r - g)) * ((1 + r)**type) * -1
858
+ (pmt / (r - g)) * ((r + 1)**type) * -1
920
859
 
921
860
  end
922
861
  end
@@ -926,34 +865,33 @@ module Finrb
926
865
  # @param r discount rate, or the interest rate at which the amount will be compounded each period
927
866
  # @param n number of periods
928
867
  # @param fv future value
929
- # @export
930
- # @examples
931
- # Finrb::Utils.pv_simple(0.07,10,100)
868
+ # @example
869
+ # Finrb::Utils.pv_simple(0.07,10,100)
932
870
  #
933
- # Finrb::Utils.pv_simple(r=0.03,n=3,fv=1000)
934
- def self.pv_simple(r, n, fv)
935
- r = r.to_d
936
- n = n.to_d
937
- fv = fv.to_d
871
+ # @example
872
+ # Finrb::Utils.pv_simple(r=0.03,n=3,fv=1000)
873
+ def self.pv_simple(r:, n:, fv:)
874
+ r = DecNum(r.to_s)
875
+ n = DecNum(n.to_s)
876
+ fv = DecNum(fv.to_s)
938
877
 
939
- ((fv / ((1 + r)**n)) * -1)
878
+ ((fv / ((r + 1)**n)) * -1)
940
879
  end
941
880
 
942
881
  # Computing the present value of an uneven cash flow series
943
882
  #
944
883
  # @param r discount rate, or the interest rate at which the amount will be compounded each period
945
884
  # @param cf uneven cash flow
946
- # @export
947
- # @examples
948
- # Finrb::Utils.pv_uneven(r=0.1, cf=c(-1000, -500, 0, 4000, 3500, 2000))
949
- def self.pv_uneven(r, cf)
950
- r = r.to_d
951
- cf = Array.wrap(cf).map(&:to_d)
885
+ # @example
886
+ # Finrb::Utils.pv_uneven(r=0.1, cf=[-1000, -500, 0, 4000, 3500, 2000])
887
+ def self.pv_uneven(r:, cf:)
888
+ r = DecNum(r.to_s)
889
+ cf = Array.wrap(cf).map { |value| DecNum(value.to_s) }
952
890
 
953
891
  n = cf.size
954
892
  sum = 0
955
893
  (0...n).each do |i|
956
- sum += Finrb::Utils.pv_simple(r, i, cf[i])
894
+ sum += Finrb::Utils.pv_simple(r: r, n: i + 1, fv: cf[i])
957
895
  end
958
896
  sum
959
897
  end
@@ -964,14 +902,13 @@ module Finrb
964
902
  # @param ms marketable securities
965
903
  # @param rc receivables
966
904
  # @param cl current liabilities
967
- # @export
968
- # @examples
969
- # Finrb::Utils.quick_ratio(cash=3000,ms=2000,rc=1000,cl=2000)
970
- def self.quick_ratio(cash, ms, rc, cl)
971
- cash = cash.to_d
972
- ms = ms.to_d
973
- rc = rc.to_d
974
- cl = cl.to_d
905
+ # @example
906
+ # Finrb::Utils.quick_ratio(cash=3000,ms=2000,rc=1000,cl=2000)
907
+ def self.quick_ratio(cash:, ms:, rc:, cl:)
908
+ cash = DecNum(cash.to_s)
909
+ ms = DecNum(ms.to_s)
910
+ rc = DecNum(rc.to_s)
911
+ cl = DecNum(cl.to_s)
975
912
 
976
913
  ((cash + ms + rc) / cl)
977
914
  end
@@ -980,56 +917,53 @@ module Finrb
980
917
  #
981
918
  # @param r norminal rate
982
919
  # @param m number of times compounded each year
983
- # @export
984
- # @examples
985
- # Finrb::Utils.r_continuous(r=0.03,m=4)
986
- def self.r_continuous(r, m)
987
- r = r.to_d
988
- m = m.to_d
989
-
990
- (m * (1 + (r / m)).to_d.log)
920
+ # @example
921
+ # Finrb::Utils.r_continuous(r=0.03,m=4)
922
+ def self.r_continuous(r:, m:)
923
+ r = DecNum(r.to_s)
924
+ m = DecNum(m.to_s)
925
+
926
+ (m * ((r / m) + 1).to_dec.log)
991
927
  end
992
928
 
993
929
  # Convert a given continuous compounded rate to a norminal rate
994
930
  #
995
931
  # @param rc continuous compounded rate
996
932
  # @param m number of desired times compounded each year
997
- # @export
998
- # @examples
999
- # Finrb::Utils.r_norminal(0.03,1)
933
+ # @example
934
+ # Finrb::Utils.r_norminal(0.03,1)
1000
935
  #
1001
- # Finrb::Utils.r_norminal(rc=0.03,m=4)
1002
- def self.r_norminal(rc, m)
1003
- rc = rc.to_d
1004
- m = m.to_d
936
+ # @example
937
+ # Finrb::Utils.r_norminal(rc=0.03,m=4)
938
+ def self.r_norminal(rc:, m:)
939
+ rc = DecNum(rc.to_s)
940
+ m = DecNum(m.to_s)
1005
941
 
1006
- (m * ((rc / m).to_d.exp - 1))
942
+ (m * ((rc / m).to_dec.exp - 1))
1007
943
  end
1008
944
 
1009
945
  # Rate of return for a perpetuity
1010
946
  #
1011
947
  # @param pmt payment per period
1012
948
  # @param pv present value
1013
- # @export
1014
- # @examples
1015
- # Finrb::Utils.r_perpetuity(pmt=4.5,pv=-75)
1016
- def self.r_perpetuity(pmt, pv)
1017
- pmt = pmt.to_d
1018
- pv = pv.to_d
1019
-
1020
- (-1 * pmt / pv)
949
+ # @example
950
+ # Finrb::Utils.r_perpetuity(pmt=4.5,pv=-75)
951
+ def self.r_perpetuity(pmt:, pv:)
952
+ pmt = DecNum(pmt.to_s)
953
+ pv = DecNum(pv.to_s)
954
+
955
+ (pmt * -1 / pv)
1021
956
  end
1022
957
 
1023
958
  # Computing Sampling error
1024
959
  #
1025
960
  # @param sm sample mean
1026
961
  # @param mu population mean
1027
- # @export
1028
- # @examples
1029
- # Finrb::Utils.sampling_error(sm=0.45, mu=0.5)
1030
- def self.sampling_error(sm, mu)
1031
- sm = sm.to_d
1032
- mu = mu.to_d
962
+ # @example
963
+ # Finrb::Utils.sampling_error(sm=0.45, mu=0.5)
964
+ def self.sampling_error(sm:, mu:)
965
+ sm = DecNum(sm.to_s)
966
+ mu = DecNum(mu.to_s)
1033
967
 
1034
968
  (sm - mu)
1035
969
  end
@@ -1039,13 +973,12 @@ module Finrb
1039
973
  # @param rp portfolio return
1040
974
  # @param rl threshold level return
1041
975
  # @param sd standard deviation of portfolio retwns
1042
- # @export
1043
- # @examples
1044
- # Finrb::Utils.sf_ratio(rp=0.09,rl=0.03,sd=0.12)
1045
- def self.sf_ratio(rp, rl, sd)
1046
- rp = rp.to_d
1047
- rl = rl.to_d
1048
- sd = sd.to_d
976
+ # @example
977
+ # Finrb::Utils.sf_ratio(rp=0.09,rl=0.03,sd=0.12)
978
+ def self.sf_ratio(rp:, rl:, sd:)
979
+ rp = DecNum(rp.to_s)
980
+ rl = DecNum(rl.to_s)
981
+ sd = DecNum(sd.to_s)
1049
982
 
1050
983
  ((rp - rl) / sd)
1051
984
  end
@@ -1055,13 +988,12 @@ module Finrb
1055
988
  # @param rp portfolio return
1056
989
  # @param rf risk-free return
1057
990
  # @param sd standard deviation of portfolio retwns
1058
- # @export
1059
- # @examples
1060
- # Finrb::Utils.sharpe_ratio(rp=0.038,rf=0.015,sd=0.07)
1061
- def self.sharpe_ratio(rp, rf, sd)
1062
- rp = rp.to_d
1063
- rf = rf.to_d
1064
- sd = sd.to_d
991
+ # @example
992
+ # Finrb::Utils.sharpe_ratio(rp=0.038,rf=0.015,sd=0.07)
993
+ def self.sharpe_ratio(rp:, rf:, sd:)
994
+ rp = DecNum(rp.to_s)
995
+ rf = DecNum(rf.to_s)
996
+ sd = DecNum(sd.to_s)
1065
997
 
1066
998
  ((rp - rf) / sd)
1067
999
  end
@@ -1071,13 +1003,12 @@ module Finrb
1071
1003
  # @param cost cost of long-lived assets
1072
1004
  # @param rv residual value of the long-lived assets at the end of its useful life
1073
1005
  # @param t length of the useful life
1074
- # @export
1075
- # @examples
1076
- # slde(cost=1200,rv=200,t=5)
1077
- def self.slde(cost, rv, t)
1078
- cost = cost.to_d
1079
- rv = rv.to_d
1080
- t = t.to_d
1006
+ # @example
1007
+ # Finrb::Utils.slde(cost=1200,rv=200,t=5)
1008
+ def self.slde(cost:, rv:, t:)
1009
+ cost = DecNum(cost.to_s)
1010
+ rv = DecNum(rv.to_s)
1011
+ t = DecNum(t.to_s)
1081
1012
 
1082
1013
  ((cost - rv) / t)
1083
1014
  end
@@ -1086,12 +1017,11 @@ module Finrb
1086
1017
  #
1087
1018
  # @param td total debt
1088
1019
  # @param te total equity
1089
- # @export
1090
- # @examples
1091
- # Finrb::Utils.total_d2e(td=6000,te=20000)
1092
- def self.total_d2e(td, te)
1093
- td = td.to_d
1094
- te = te.to_d
1020
+ # @example
1021
+ # Finrb::Utils.total_d2e(td=6000,te=20000)
1022
+ def self.total_d2e(td:, te:)
1023
+ td = DecNum(td.to_s)
1024
+ te = DecNum(te.to_s)
1095
1025
 
1096
1026
  (td / te)
1097
1027
  end
@@ -1101,13 +1031,12 @@ module Finrb
1101
1031
  # @param ev ordered ending value list
1102
1032
  # @param bv ordered beginning value list
1103
1033
  # @param cfr ordered cash flow received list
1104
- # @export
1105
- # @examples
1106
- # twrr(ev=c(120,260),bv=c(100,240),cfr=c(2,4))
1107
- def self.twrr(ev, bv, cfr)
1108
- ev = Array.wrap(ev).map(&:to_d)
1109
- bv = Array.wrap(bv).map(&:to_d)
1110
- cfr = Array.wrap(cfr).map(&:to_d)
1034
+ # @example
1035
+ # Finrb::Utils.twrr(ev=[120,260],bv=[100,240],cfr=[2,4])
1036
+ def self.twrr(ev:, bv:, cfr:)
1037
+ ev = Array.wrap(ev).map { |value| DecNum(value.to_s) }
1038
+ bv = Array.wrap(bv).map { |value| DecNum(value.to_s) }
1039
+ cfr = Array.wrap(cfr).map { |value| DecNum(value.to_s) }
1111
1040
 
1112
1041
  r = ev.size
1113
1042
  s = bv.size
@@ -1117,9 +1046,9 @@ module Finrb
1117
1046
  raise(FinrbError, 'Different number of values!')
1118
1047
  else
1119
1048
  (0...r).each do |i|
1120
- wr *= (hpr(ev[i], bv[i], cfr[i]) + 1)
1049
+ wr *= (Finrb::Utils.hpr(ev: ev[i], bv: bv[i], cfr: cfr[i]) + 1)
1121
1050
  end
1122
- ((wr**(1 / r)) - 1)
1051
+ ((wr**(1.to_f / r)) - 1)
1123
1052
  end
1124
1053
  end
1125
1054
 
@@ -1127,14 +1056,14 @@ module Finrb
1127
1056
  #
1128
1057
  # @param ns n x 1 vector vector of number of shares
1129
1058
  # @param nm n x 1 vector vector of number of months relate to ns
1130
- # @export
1131
- # @examples
1132
- # s=c(10000,2000);m=c(12,6);was(ns=s,nm=m)
1059
+ # @example
1060
+ # s=[10000,2000];m=[12,6];Finrb::Utils.was(ns=s,nm=m)
1133
1061
  #
1134
- # s=c(11000,4400,-3000);m=c(12,9,4);was(ns=s,nm=m)
1135
- def self.was(ns, nm)
1136
- ns = Array.wrap(ns).map(&:to_d)
1137
- nm = Array.wrap(nm).map(&:to_d)
1062
+ # @example
1063
+ # s=[11000,4400,-3000];m=[12,9,4];Finrb::Utils.was(ns=s,nm=m)
1064
+ def self.was(ns:, nm:)
1065
+ ns = Array.wrap(ns).map { |value| DecNum(value.to_s) }
1066
+ nm = Array.wrap(nm).map { |value| DecNum(value.to_s) }
1138
1067
 
1139
1068
  m = ns.size
1140
1069
  n = nm.size
@@ -1154,16 +1083,14 @@ module Finrb
1154
1083
  #
1155
1084
  # @param r returns of the individual assets in the portfolio
1156
1085
  # @param w corresponding weights associated with each of the individual assets
1157
- # @export
1158
- # @examples
1159
- # wpr(r=c(0.12, 0.07, 0.03),w=c(0.5,0.4,0.1))
1160
- def self.wpr(r, w)
1161
- r = Array.wrap(r).map(&:to_d)
1162
- w = Array.wrap(w).map(&:to_d)
1086
+ # @example
1087
+ # Finrb::Utils.wpr(r=[0.12, 0.07, 0.03],w=[0.5,0.4,0.1])
1088
+ def self.wpr(r:, w:)
1089
+ r = Array.wrap(r).map { |value| DecNum(value.to_s) }
1090
+ w = Array.wrap(w).map { |value| DecNum(value.to_s) }
1163
1091
 
1164
1092
  if w.sum != 1
1165
1093
  puts('sum of weights is NOT equal to 1!') # TODO: need to change
1166
- else
1167
1094
  end
1168
1095
  r.zip(w).sum { |arr| arr.reduce(:*) }
1169
1096
  end