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