Class: Finrb::Utils
- Inherits:
-
Object
- Object
- Finrb::Utils
- Defined in:
- lib/finrb/utils.rb
Defined Under Namespace
Classes: NlFunctionStub
Class Method Summary collapse
-
.bdy(d:, f:, t:) ⇒ Object
Computing bank discount yield (BDY) for a T-bill.
-
.bdy2mmy(bdy:, t:) ⇒ Object
Computing money market yield (MMY) for a T-bill.
-
.cash_ratio(cash:, ms:, cl:) ⇒ Object
cash ratio – Liquidity ratios measure the firm’s ability to satisfy its short-term obligations as they come due.
-
.coefficient_variation(sd:, avg:) ⇒ Object
Computing Coefficient of variation.
-
.cogs(uinv:, pinv:, units:, price:, sinv:, method: 'FIFO') ⇒ Object
Cost of goods sold and ending inventory under three methods (FIFO,LIFO,Weighted average).
-
.current_ratio(ca:, cl:) ⇒ Object
current ratio – Liquidity ratios measure the firm’s ability to satisfy its short-term obligations as they come due.
-
.ddb(cost:, rv:, t:) ⇒ Object
Depreciation Expense Recognition – double-declining balance (DDB), the most common declining balance method, which applies two times the straight-line rate to the declining balance.
-
.debt_ratio(td:, ta:) ⇒ Object
debt ratio – Solvency ratios measure the firm’s ability to satisfy its long-term obligations.
-
.diluted_eps(ni:, pd:, w:, cpd: 0, cdi: 0, tax: 0, cps: 0, cds: 0, iss: 0) ⇒ Object
diluted Earnings Per Share.
-
.discount_rate(n:, pv:, fv:, pmt:, type: 0, lower: 0.0001, upper: 100) ⇒ Object
Computing the rate of return for each period.
-
.ear(r:, m:) ⇒ Object
Convert stated annual rate to the effective annual rate.
-
.ear2bey(ear:) ⇒ Object
bond-equivalent yield (BEY), 2 x the semiannual discount rate.
-
.ear2hpr(ear:, t:) ⇒ Object
Computing HPR, the holding period return.
-
.ear_continuous(r:) ⇒ Object
Convert stated annual rate to the effective annual rate with continuous compounding.
-
.eir(r:, n: 1, p: 12, type: 'e') ⇒ Object
Equivalent/proportional Interest Rates.
-
.eps(ni:, pd:, w:) ⇒ Object
Basic Earnings Per Share.
-
.financial_leverage(te:, ta:) ⇒ Object
financial leverage – Solvency ratios measure the firm’s ability to satisfy its long-term obligations.
-
.fv(r:, n:, pv: 0, pmt: 0, type: 0) ⇒ Object
Estimate future value (fv).
-
.fv_annuity(r:, n:, pmt:, type: 0) ⇒ Object
Estimate future value of an annuity.
-
.fv_simple(r:, n:, pv:) ⇒ Object
Estimate future value (fv) of a single sum.
-
.fv_uneven(r:, cf:) ⇒ Object
Computing the future value of an uneven cash flow series.
-
.geometric_mean(r:) ⇒ Object
Geometric mean return.
-
.gpm(gp:, rv:) ⇒ Object
gross profit margin – Evaluate a company’s financial performance.
-
.harmonic_mean(p:) ⇒ Object
harmonic mean, average price.
-
.hpr(ev:, bv:, cfr: 0) ⇒ Object
Computing HPR, the holding period return.
-
.hpr2bey(hpr:, t:) ⇒ Object
bond-equivalent yield (BEY), 2 x the semiannual discount rate.
-
.hpr2ear(hpr:, t:) ⇒ Object
Convert holding period return to the effective annual rate.
-
.hpr2mmy(hpr:, t:) ⇒ Object
Computing money market yield (MMY) for a T-bill.
-
.irr(cf:) ⇒ Object
Computing IRR, the internal rate of return.
-
.iss(amp:, ep:, n:) ⇒ Object
calculate the net increase in common shares from the potential exercise of stock options or warrants.
-
.lt_d2e(ltd:, te:) ⇒ Object
long-term debt-to-equity – Solvency ratios measure the firm’s ability to satisfy its long-term obligations.
-
.mmy2hpr(mmy:, t:) ⇒ Object
Computing HPR, the holding period return.
-
.n_period(r:, pv:, fv:, pmt:, type: 0) ⇒ Object
Estimate the number of periods.
-
.npm(ni:, rv:) ⇒ Object
net profit margin – Evaluate a company’s financial performance.
-
.npv(r:, cf:) ⇒ Object
Computing NPV, the PV of the cash flows less the initial (time = 0) outlay.
-
.pmt(r:, n:, pv:, fv:, type: 0) ⇒ Object
Estimate period payment.
-
.pv(r:, n:, fv: 0, pmt: 0, type: 0) ⇒ Object
Estimate present value (pv).
-
.pv_annuity(r:, n:, pmt:, type: 0) ⇒ Object
Estimate present value (pv) of an annuity.
-
.pv_perpetuity(r:, pmt:, g: 0, type: 0) ⇒ Object
Estimate present value of a perpetuity.
-
.pv_simple(r:, n:, fv:) ⇒ Object
Estimate present value (pv) of a single sum.
-
.pv_uneven(r:, cf:) ⇒ Object
Computing the present value of an uneven cash flow series.
-
.quick_ratio(cash:, ms:, rc:, cl:) ⇒ Object
quick ratio – Liquidity ratios measure the firm’s ability to satisfy its short-term obligations as they come due.
-
.r_continuous(r:, m:) ⇒ Object
Convert a given norminal rate to a continuous compounded rate.
-
.r_norminal(rc:, m:) ⇒ Object
Convert a given continuous compounded rate to a norminal rate.
-
.r_perpetuity(pmt:, pv:) ⇒ Object
Rate of return for a perpetuity.
-
.sampling_error(sm:, mu:) ⇒ Object
Computing Sampling error.
-
.sf_ratio(rp:, rl:, sd:) ⇒ Object
Computing Roy’s safety-first ratio.
-
.sharpe_ratio(rp:, rf:, sd:) ⇒ Object
Computing Sharpe Ratio.
-
.slde(cost:, rv:, t:) ⇒ Object
Depreciation Expense Recognition – Straight-line depreciation (SL) allocates an equal amount of depreciation each year over the asset’s useful life.
-
.total_d2e(td:, te:) ⇒ Object
total debt-to-equity – Solvency ratios measure the firm’s ability to satisfy its long-term obligations.
-
.twrr(ev:, bv:, cfr:) ⇒ Object
Computing TWRR, the time-weighted rate of return.
-
.was(ns:, nm:) ⇒ Object
calculate weighted average shares – weighted average number of common shares.
-
.wpr(r:, w:) ⇒ Object
Weighted mean as a portfolio return.
Class Method Details
.bdy(d:, f:, t:) ⇒ Object
Computing bank discount yield (BDY) for a T-bill
35 36 37 38 39 40 41 |
# File 'lib/finrb/utils.rb', line 35 def self.bdy(d:, f:, t:) d = Flt::DecNum(d.to_s) f = Flt::DecNum(f.to_s) t = Flt::DecNum(t.to_s) (d * 360 / f / t) end |
.bdy2mmy(bdy:, t:) ⇒ Object
Computing money market yield (MMY) for a T-bill
49 50 51 52 53 54 |
# File 'lib/finrb/utils.rb', line 49 def self.bdy2mmy(bdy:, t:) bdy = Flt::DecNum(bdy.to_s) t = Flt::DecNum(t.to_s) (bdy * 360 / (360 - (t * bdy))) end |
.cash_ratio(cash:, ms:, cl:) ⇒ Object
cash ratio – Liquidity ratios measure the firm’s ability to satisfy its short-term obligations as they come due.
63 64 65 66 67 68 69 |
# File 'lib/finrb/utils.rb', line 63 def self.cash_ratio(cash:, ms:, cl:) cash = Flt::DecNum(cash.to_s) ms = Flt::DecNum(ms.to_s) cl = Flt::DecNum(cl.to_s) ((cash + ms) / cl) end |
.coefficient_variation(sd:, avg:) ⇒ Object
Computing Coefficient of variation
77 78 79 80 81 82 |
# File 'lib/finrb/utils.rb', line 77 def self.coefficient_variation(sd:, avg:) sd = Flt::DecNum(sd.to_s) avg = Flt::DecNum(avg.to_s) (sd / avg) end |
.cogs(uinv:, pinv:, units:, price:, sinv:, method: 'FIFO') ⇒ Object
Cost of goods sold and ending inventory under three methods (FIFO,LIFO,Weighted average)
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/finrb/utils.rb', line 100 def self.cogs(uinv:, pinv:, units:, price:, sinv:, method: 'FIFO') uinv = Flt::DecNum(uinv.to_s) pinv = Flt::DecNum(pinv.to_s) units = Array.wrap(units).map { |value| Flt::DecNum(value.to_s) } price = Array.wrap(price).map { |value| Flt::DecNum(value.to_s) } sinv = Flt::DecNum(sinv.to_s) method = method.to_s n = units.size m = price.size cost_of_goods = 0 ending_inventory = 0 if m == n case method when 'FIFO' if sinv <= uinv cost_of_goods = sinv * pinv ending_inventory = (uinv - sinv) * pinv (0...n).each do |i| ending_inventory += (units[i] * price[i]) end else cost_of_goods = uinv * pinv sinv -= uinv (0...n).each do |i| if sinv <= units[i] cost_of_goods += (sinv * price[i]) ending_inventory = (units[i] - sinv) * price[i] if i < n temp = i + 1 (temp...n).each do |j| ending_inventory += (units[j] * price[j]) end end sinv = 0 next else cost_of_goods += (units[i] * price[i]) sinv -= units[i] end end raise(FinrbError, "Inventory is not enough to sell\n") if sinv.positive? end when 'WAC' ending_inventory = uinv * pinv tu = uinv (0...n).each do |i| ending_inventory += (units[i] * price[i]) tu += units[i] end if tu >= sinv cost_of_goods = ending_inventory / tu * sinv ending_inventory = ending_inventory / tu * (tu - sinv) else raise(FinrbError, "Inventory is not enough to sell\n") end when 'LIFO' (n - 1).downto(0).each do |i| if sinv <= units[i] cost_of_goods += (sinv * price[i]) ending_inventory = (units[i] - sinv) * price[i] if i > 1 temp = i - 1 temp.downto(0).each do |j| ending_inventory += (units[j] * price[j]) end end ending_inventory += (uinv * pinv) sinv = 0 next else cost_of_goods += (units[i] * price[i]) sinv -= units[i] end end if sinv.positive? if sinv <= uinv cost_of_goods += (sinv * pinv) ending_inventory += ((uinv - sinv) * pinv) else raise(FinrbError, "Inventory is not enough to sell\n") end end end else raise(FinrbError, "length of units and price are not the same\n") end { cost_of_goods: cost_of_goods, ending_inventory: ending_inventory } end |
.current_ratio(ca:, cl:) ⇒ Object
current ratio – Liquidity ratios measure the firm’s ability to satisfy its short-term obligations as they come due.
202 203 204 205 206 207 |
# File 'lib/finrb/utils.rb', line 202 def self.current_ratio(ca:, cl:) ca = Flt::DecNum(ca.to_s) cl = Flt::DecNum(cl.to_s) (ca / cl) end |
.ddb(cost:, rv:, t:) ⇒ Object
Depreciation Expense Recognition – double-declining balance (DDB), the most common declining balance method, which applies two times the straight-line rate to the declining balance.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/finrb/utils.rb', line 216 def self.ddb(cost:, rv:, t:) cost = Flt::DecNum(cost.to_s) rv = Flt::DecNum(rv.to_s) t = Flt::DecNum(t.to_s) raise(FinrbError, 't should be larger than 1') if t < 2 ddb = [0] * t ddb[0] = cost * 2 / t if cost - ddb[0] <= rv ddb[0] = cost - rv else cost -= ddb[0] (1...t).each do |i| ddb[i] = cost * 2 / t if cost - ddb[i] <= rv ddb[i] = cost - rv break else cost -= ddb[i] end end end { t: (0...t).to_a, ddb: ddb } end |
.debt_ratio(td:, ta:) ⇒ Object
debt ratio – Solvency ratios measure the firm’s ability to satisfy its long-term obligations.
248 249 250 251 252 253 |
# File 'lib/finrb/utils.rb', line 248 def self.debt_ratio(td:, ta:) td = Flt::DecNum(td.to_s) ta = Flt::DecNum(ta.to_s) (td / ta) end |
.diluted_eps(ni:, pd:, w:, cpd: 0, cdi: 0, tax: 0, cps: 0, cds: 0, iss: 0) ⇒ Object
diluted Earnings Per Share
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/finrb/utils.rb', line 277 def self.diluted_eps(ni:, pd:, w:, cpd: 0, cdi: 0, tax: 0, cps: 0, cds: 0, iss: 0) ni = Flt::DecNum(ni.to_s) pd = Flt::DecNum(pd.to_s) w = Flt::DecNum(w.to_s) cpd = Flt::DecNum(cpd.to_s) cdi = Flt::DecNum(cdi.to_s) tax = Flt::DecNum(tax.to_s) cps = Flt::DecNum(cps.to_s) cds = Flt::DecNum(cds.to_s) iss = Flt::DecNum(iss.to_s) basic = (ni - pd) / w diluted = (ni - pd + cpd + (cdi * (1 - tax))) / (w + cps + cds + iss) diluted = (ni - pd + cpd) / (w + cps + iss) if diluted > basic diluted end |
.discount_rate(n:, pv:, fv:, pmt:, type: 0, lower: 0.0001, upper: 100) ⇒ Object
Computing the rate of return for each period
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/finrb/utils.rb', line 305 def self.discount_rate(n:, pv:, fv:, pmt:, type: 0, lower: 0.0001, upper: 100) n = Flt::DecNum(n.to_s) pv = Flt::DecNum(pv.to_s) fv = Flt::DecNum(fv.to_s) pmt = Flt::DecNum(pmt.to_s) type = Flt::DecNum(type.to_s) lower = Flt::DecNum(lower.to_s) upper = Flt::DecNum(upper.to_s) nlfunc = NlFunctionStub.new nlfunc.func = lambda do |x| [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)] end root = [(upper - lower) / 2] nlsolve(nlfunc, root) root[0] end |
.ear(r:, m:) ⇒ Object
Convert stated annual rate to the effective annual rate
334 335 336 337 338 339 |
# File 'lib/finrb/utils.rb', line 334 def self.ear(r:, m:) r = Flt::DecNum(r.to_s) m = Flt::DecNum(m.to_s) ((((r / m) + 1)**m) - 1) end |
.ear2bey(ear:) ⇒ Object
bond-equivalent yield (BEY), 2 x the semiannual discount rate
360 361 362 363 364 |
# File 'lib/finrb/utils.rb', line 360 def self.ear2bey(ear:) ear = Flt::DecNum(ear.to_s) ((((ear + 1)**0.5) - 1) * 2) end |
.ear2hpr(ear:, t:) ⇒ Object
Computing HPR, the holding period return
372 373 374 375 376 377 |
# File 'lib/finrb/utils.rb', line 372 def self.ear2hpr(ear:, t:) ear = Flt::DecNum(ear.to_s) t = Flt::DecNum(t.to_s) (((ear + 1)**(t / 365)) - 1) end |
.ear_continuous(r:) ⇒ Object
Convert stated annual rate to the effective annual rate with continuous compounding
349 350 351 352 353 |
# File 'lib/finrb/utils.rb', line 349 def self.ear_continuous(r:) r = Flt::DecNum(r.to_s) (r.to_dec.exp - 1) end |
.eir(r:, n: 1, p: 12, type: 'e') ⇒ Object
An interest rate to be applied n times p.a. can be converted to an equivalent rate to be applied p times p.a.
Equivalent/proportional Interest Rates
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
# File 'lib/finrb/utils.rb', line 414 def self.eir(r:, n: 1, p: 12, type: 'e') r = Flt::DecNum(r.to_s) n = Flt::DecNum(n.to_s) p = Flt::DecNum(p.to_s) type = type.to_s case type when 'e' eir = (((r / n) + 1)**(n / p)) - 1 when 'p' eir = r / p else raise(FinrbError, "type must be 'e' or 'p'") end eir end |
.eps(ni:, pd:, w:) ⇒ Object
Basic Earnings Per Share
438 439 440 441 442 443 444 |
# File 'lib/finrb/utils.rb', line 438 def self.eps(ni:, pd:, w:) ni = Flt::DecNum(ni.to_s) pd = Flt::DecNum(pd.to_s) w = Flt::DecNum(w.to_s) ((ni - pd) / w) end |
.financial_leverage(te:, ta:) ⇒ Object
financial leverage – Solvency ratios measure the firm’s ability to satisfy its long-term obligations.
452 453 454 455 456 457 |
# File 'lib/finrb/utils.rb', line 452 def self.financial_leverage(te:, ta:) te = Flt::DecNum(te.to_s) ta = Flt::DecNum(ta.to_s) (ta / te) end |
.fv(r:, n:, pv: 0, pmt: 0, type: 0) ⇒ Object
Estimate future value (fv)
468 469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/finrb/utils.rb', line 468 def self.fv(r:, n:, pv: 0, pmt: 0, type: 0) r = Flt::DecNum(r.to_s) n = Flt::DecNum(n.to_s) pv = Flt::DecNum(pv.to_s) pmt = Flt::DecNum(pmt.to_s) type = Flt::DecNum(type.to_s) if type != 0 && type != 1 raise(FinrbError, 'Error: type should be 0 or 1!') else (Finrb::Utils.fv_simple(r: r, n: n, pv: pv) + Finrb::Utils.fv_annuity(r: r, n: n, pmt: pmt, type: type)) end end |
.fv_annuity(r:, n:, pmt:, type: 0) ⇒ Object
Estimate future value of an annuity
493 494 495 496 497 498 499 500 501 502 503 504 505 |
# File 'lib/finrb/utils.rb', line 493 def self.fv_annuity(r:, n:, pmt:, type: 0) r = Flt::DecNum(r.to_s) n = Flt::DecNum(n.to_s) pmt = Flt::DecNum(pmt.to_s) type = Flt::DecNum(type.to_s) if type != 0 && type != 1 raise(FinrbError, 'Error: type should be 0 or 1!') else (pmt / r * (((r + 1)**n) - 1)) * ((r + 1)**type) * -1 end end |
.fv_simple(r:, n:, pv:) ⇒ Object
Estimate future value (fv) of a single sum
517 518 519 520 521 522 523 |
# File 'lib/finrb/utils.rb', line 517 def self.fv_simple(r:, n:, pv:) r = Flt::DecNum(r.to_s) n = Flt::DecNum(n.to_s) pv = Flt::DecNum(pv.to_s) ((pv * ((r + 1)**n)) * -1) end |
.fv_uneven(r:, cf:) ⇒ Object
Computing the future value of an uneven cash flow series
531 532 533 534 535 536 537 538 539 540 541 542 |
# File 'lib/finrb/utils.rb', line 531 def self.fv_uneven(r:, cf:) r = Flt::DecNum(r.to_s) cf = Array.wrap(cf).map { |value| Flt::DecNum(value.to_s) } m = cf.size sum = 0 (0...m).each do |i| n = m - (i + 1) sum += Finrb::Utils.fv_simple(r: r, n: n, pv: cf[i]) end sum end |
.geometric_mean(r:) ⇒ Object
Geometric mean return
549 550 551 552 553 554 |
# File 'lib/finrb/utils.rb', line 549 def self.geometric_mean(r:) r = Array.wrap(r).map { |value| Flt::DecNum(value.to_s) } rs = r.map { |value| value + 1 } ((rs.reduce(:*)**(1.to_f / rs.size)) - 1) end |
.gpm(gp:, rv:) ⇒ Object
gross profit margin – Evaluate a company’s financial performance
562 563 564 565 566 567 |
# File 'lib/finrb/utils.rb', line 562 def self.gpm(gp:, rv:) gp = Flt::DecNum(gp.to_s) rv = Flt::DecNum(rv.to_s) (gp / rv) end |
.harmonic_mean(p:) ⇒ Object
harmonic mean, average price
573 574 575 576 577 |
# File 'lib/finrb/utils.rb', line 573 def self.harmonic_mean(p:) p = Array.wrap(p).map { |value| Flt::DecNum(value.to_s) } (1.to_f / (p.sum { |val| 1.to_f / val } / p.size)) end |
.hpr(ev:, bv:, cfr: 0) ⇒ Object
Computing HPR, the holding period return
586 587 588 589 590 591 592 |
# File 'lib/finrb/utils.rb', line 586 def self.hpr(ev:, bv:, cfr: 0) ev = Flt::DecNum(ev.to_s) bv = Flt::DecNum(bv.to_s) cfr = Flt::DecNum(cfr.to_s) ((ev - bv + cfr) / bv) end |
.hpr2bey(hpr:, t:) ⇒ Object
bond-equivalent yield (BEY), 2 x the semiannual discount rate
600 601 602 603 604 605 |
# File 'lib/finrb/utils.rb', line 600 def self.hpr2bey(hpr:, t:) hpr = Flt::DecNum(hpr.to_s) t = Flt::DecNum(t.to_s) ((((hpr + 1)**(6 / t)) - 1) * 2) end |
.hpr2ear(hpr:, t:) ⇒ Object
Convert holding period return to the effective annual rate
613 614 615 616 617 618 |
# File 'lib/finrb/utils.rb', line 613 def self.hpr2ear(hpr:, t:) hpr = Flt::DecNum(hpr.to_s) t = Flt::DecNum(t.to_s) (((hpr + 1)**(365 / t)) - 1) end |
.hpr2mmy(hpr:, t:) ⇒ Object
Computing money market yield (MMY) for a T-bill
626 627 628 629 630 631 |
# File 'lib/finrb/utils.rb', line 626 def self.hpr2mmy(hpr:, t:) hpr = Flt::DecNum(hpr.to_s) t = Flt::DecNum(t.to_s) (hpr * 360 / t) end |
.irr(cf:) ⇒ Object
Computing IRR, the internal rate of return
638 639 640 641 642 643 644 645 646 647 648 649 650 651 |
# File 'lib/finrb/utils.rb', line 638 def self.irr(cf:) cf = Array.wrap(cf).map { |value| Flt::DecNum(value.to_s) } subcf = cf.drop(1) nlfunc = NlFunctionStub.new nlfunc.func = lambda do |x| [BigDecimal(((Finrb::Utils.pv_uneven(r: x[0], cf: subcf) * -1) + cf[0]).to_s)] end root = [0] nlsolve(nlfunc, root) root[0] end |
.iss(amp:, ep:, n:) ⇒ Object
calculate the net increase in common shares from the potential exercise of stock options or warrants
660 661 662 663 664 665 666 667 668 669 670 |
# File 'lib/finrb/utils.rb', line 660 def self.iss(amp:, ep:, n:) amp = Flt::DecNum(amp.to_s) ep = Flt::DecNum(ep.to_s) n = Flt::DecNum(n.to_s) if amp > ep ((amp - ep) * n / amp) else raise(FinrbError, 'amp must larger than ep') end end |
.lt_d2e(ltd:, te:) ⇒ Object
long-term debt-to-equity – Solvency ratios measure the firm’s ability to satisfy its long-term obligations.
678 679 680 681 682 683 |
# File 'lib/finrb/utils.rb', line 678 def self.lt_d2e(ltd:, te:) ltd = Flt::DecNum(ltd.to_s) te = Flt::DecNum(te.to_s) (ltd / te) end |
.mmy2hpr(mmy:, t:) ⇒ Object
Computing HPR, the holding period return
691 692 693 694 695 696 |
# File 'lib/finrb/utils.rb', line 691 def self.mmy2hpr(mmy:, t:) mmy = Flt::DecNum(mmy.to_s) t = Flt::DecNum(t.to_s) (mmy * t / 360) end |
.n_period(r:, pv:, fv:, pmt:, type: 0) ⇒ Object
Estimate the number of periods
710 711 712 713 714 715 716 717 718 719 720 721 722 723 |
# File 'lib/finrb/utils.rb', line 710 def self.n_period(r:, pv:, fv:, pmt:, type: 0) r = Flt::DecNum(r.to_s) pv = Flt::DecNum(pv.to_s) fv = Flt::DecNum(fv.to_s) pmt = Flt::DecNum(pmt.to_s) type = Flt::DecNum(type.to_s) if type != 0 && type != 1 raise(FinrbError, 'Error: type should be 0 or 1!') else (((fv * r) - (pmt * ((r + 1)**type))) * -1 / ((pv * r) + (pmt * ((r + 1)**type)))).to_dec.log / (r + 1).to_dec.log end end |
.npm(ni:, rv:) ⇒ Object
net profit margin – Evaluate a company’s financial performance
731 732 733 734 735 736 |
# File 'lib/finrb/utils.rb', line 731 def self.npm(ni:, rv:) ni = Flt::DecNum(ni.to_s) rv = Flt::DecNum(rv.to_s) (ni / rv) end |
.npv(r:, cf:) ⇒ Object
Computing NPV, the PV of the cash flows less the initial (time = 0) outlay
744 745 746 747 748 749 750 |
# File 'lib/finrb/utils.rb', line 744 def self.npv(r:, cf:) r = Flt::DecNum(r.to_s) cf = Array.wrap(cf).map { |value| Flt::DecNum(value.to_s) } subcf = cf.drop(1) ((Finrb::Utils.pv_uneven(r: r, cf: subcf) * -1) + cf[0]) end |
.pmt(r:, n:, pv:, fv:, type: 0) ⇒ Object
Estimate period payment
767 768 769 770 771 772 773 774 775 776 777 778 779 |
# File 'lib/finrb/utils.rb', line 767 def self.pmt(r:, n:, pv:, fv:, type: 0) r = Flt::DecNum(r.to_s) n = Flt::DecNum(n.to_s) pv = Flt::DecNum(pv.to_s) fv = Flt::DecNum(fv.to_s) type = Flt::DecNum(type.to_s) if type != 0 && type != 1 raise(FinrbError, 'Error: type should be 0 or 1!') else (pv + (fv / ((r + 1)**n))) * r / (1 - (1.to_f / ((r + 1)**n))) * -1 * ((r + 1)**(type * -1)) end end |
.pv(r:, n:, fv: 0, pmt: 0, type: 0) ⇒ Object
Estimate present value (pv)
793 794 795 796 797 798 799 800 801 802 803 804 805 806 |
# File 'lib/finrb/utils.rb', line 793 def self.pv(r:, n:, fv: 0, pmt: 0, type: 0) r = Flt::DecNum(r.to_s) n = Flt::DecNum(n.to_s) fv = Flt::DecNum(fv.to_s) pmt = Flt::DecNum(pmt.to_s) type = Flt::DecNum(type.to_s) if type != 0 && type != 1 raise(FinrbError, 'Error: type should be 0 or 1!') else Finrb::Utils.pv_simple(r: r, n: n, fv: fv) + Finrb::Utils.pv_annuity(r: r, n: n, pmt: pmt, type: type) end end |
.pv_annuity(r:, n:, pmt:, type: 0) ⇒ Object
Estimate present value (pv) of an annuity
819 820 821 822 823 824 825 826 827 828 829 830 831 |
# File 'lib/finrb/utils.rb', line 819 def self.pv_annuity(r:, n:, pmt:, type: 0) r = Flt::DecNum(r.to_s) n = Flt::DecNum(n.to_s) pmt = Flt::DecNum(pmt.to_s) type = Flt::DecNum(type.to_s) if type != 0 && type != 1 raise(FinrbError, 'Error: type should be 0 or 1!') else (pmt / r * (1 - (1.to_f / ((r + 1)**n)))) * ((r + 1)**type) * -1 end end |
.pv_perpetuity(r:, pmt:, g: 0, type: 0) ⇒ Object
Estimate present value of a perpetuity
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 |
# File 'lib/finrb/utils.rb', line 847 def self.pv_perpetuity(r:, pmt:, g: 0, type: 0) r = Flt::DecNum(r.to_s) pmt = Flt::DecNum(pmt.to_s) g = Flt::DecNum(g.to_s) type = Flt::DecNum(type.to_s) if type != 0 && type != 1 raise(FinrbError, 'Error: type should be 0 or 1!') elsif g >= r raise(FinrbError, 'Error: g is not smaller than r!') else (pmt / (r - g)) * ((r + 1)**type) * -1 end end |
.pv_simple(r:, n:, fv:) ⇒ Object
Estimate present value (pv) of a single sum
873 874 875 876 877 878 879 |
# File 'lib/finrb/utils.rb', line 873 def self.pv_simple(r:, n:, fv:) r = Flt::DecNum(r.to_s) n = Flt::DecNum(n.to_s) fv = Flt::DecNum(fv.to_s) ((fv / ((r + 1)**n)) * -1) end |
.pv_uneven(r:, cf:) ⇒ Object
Computing the present value of an uneven cash flow series
887 888 889 890 891 892 893 894 895 896 897 |
# File 'lib/finrb/utils.rb', line 887 def self.pv_uneven(r:, cf:) r = Flt::DecNum(r.to_s) cf = Array.wrap(cf).map { |value| Flt::DecNum(value.to_s) } n = cf.size sum = 0 (0...n).each do |i| sum += Finrb::Utils.pv_simple(r: r, n: i + 1, fv: cf[i]) end sum end |
.quick_ratio(cash:, ms:, rc:, cl:) ⇒ Object
quick ratio – Liquidity ratios measure the firm’s ability to satisfy its short-term obligations as they come due.
907 908 909 910 911 912 913 914 |
# File 'lib/finrb/utils.rb', line 907 def self.quick_ratio(cash:, ms:, rc:, cl:) cash = Flt::DecNum(cash.to_s) ms = Flt::DecNum(ms.to_s) rc = Flt::DecNum(rc.to_s) cl = Flt::DecNum(cl.to_s) ((cash + ms + rc) / cl) end |
.r_continuous(r:, m:) ⇒ Object
Convert a given norminal rate to a continuous compounded rate
922 923 924 925 926 927 |
# File 'lib/finrb/utils.rb', line 922 def self.r_continuous(r:, m:) r = Flt::DecNum(r.to_s) m = Flt::DecNum(m.to_s) (m * ((r / m) + 1).to_dec.log) end |
.r_norminal(rc:, m:) ⇒ Object
Convert a given continuous compounded rate to a norminal rate
938 939 940 941 942 943 |
# File 'lib/finrb/utils.rb', line 938 def self.r_norminal(rc:, m:) rc = Flt::DecNum(rc.to_s) m = Flt::DecNum(m.to_s) (m * ((rc / m).to_dec.exp - 1)) end |
.r_perpetuity(pmt:, pv:) ⇒ Object
Rate of return for a perpetuity
951 952 953 954 955 956 |
# File 'lib/finrb/utils.rb', line 951 def self.r_perpetuity(pmt:, pv:) pmt = Flt::DecNum(pmt.to_s) pv = Flt::DecNum(pv.to_s) (pmt * -1 / pv) end |
.sampling_error(sm:, mu:) ⇒ Object
Computing Sampling error
964 965 966 967 968 969 |
# File 'lib/finrb/utils.rb', line 964 def self.sampling_error(sm:, mu:) sm = Flt::DecNum(sm.to_s) mu = Flt::DecNum(mu.to_s) (sm - mu) end |
.sf_ratio(rp:, rl:, sd:) ⇒ Object
Computing Roy’s safety-first ratio
978 979 980 981 982 983 984 |
# File 'lib/finrb/utils.rb', line 978 def self.sf_ratio(rp:, rl:, sd:) rp = Flt::DecNum(rp.to_s) rl = Flt::DecNum(rl.to_s) sd = Flt::DecNum(sd.to_s) ((rp - rl) / sd) end |
.sharpe_ratio(rp:, rf:, sd:) ⇒ Object
Computing Sharpe Ratio
993 994 995 996 997 998 999 |
# File 'lib/finrb/utils.rb', line 993 def self.sharpe_ratio(rp:, rf:, sd:) rp = Flt::DecNum(rp.to_s) rf = Flt::DecNum(rf.to_s) sd = Flt::DecNum(sd.to_s) ((rp - rf) / sd) end |
.slde(cost:, rv:, t:) ⇒ Object
Depreciation Expense Recognition – Straight-line depreciation (SL) allocates an equal amount of depreciation each year over the asset’s useful life
1008 1009 1010 1011 1012 1013 1014 |
# File 'lib/finrb/utils.rb', line 1008 def self.slde(cost:, rv:, t:) cost = Flt::DecNum(cost.to_s) rv = Flt::DecNum(rv.to_s) t = Flt::DecNum(t.to_s) ((cost - rv) / t) end |
.total_d2e(td:, te:) ⇒ Object
total debt-to-equity – Solvency ratios measure the firm’s ability to satisfy its long-term obligations.
1022 1023 1024 1025 1026 1027 |
# File 'lib/finrb/utils.rb', line 1022 def self.total_d2e(td:, te:) td = Flt::DecNum(td.to_s) te = Flt::DecNum(te.to_s) (td / te) end |
.twrr(ev:, bv:, cfr:) ⇒ Object
Computing TWRR, the time-weighted rate of return
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 |
# File 'lib/finrb/utils.rb', line 1036 def self.twrr(ev:, bv:, cfr:) ev = Array.wrap(ev).map { |value| Flt::DecNum(value.to_s) } bv = Array.wrap(bv).map { |value| Flt::DecNum(value.to_s) } cfr = Array.wrap(cfr).map { |value| Flt::DecNum(value.to_s) } r = ev.size s = bv.size t = cfr.size wr = 1 if r != s || r != t || s != t raise(FinrbError, 'Different number of values!') else (0...r).each do |i| wr *= (Finrb::Utils.hpr(ev: ev[i], bv: bv[i], cfr: cfr[i]) + 1) end ((wr**(1.to_f / r)) - 1) end end |
.was(ns:, nm:) ⇒ Object
calculate weighted average shares – weighted average number of common shares
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 |
# File 'lib/finrb/utils.rb', line 1064 def self.was(ns:, nm:) ns = Array.wrap(ns).map { |value| Flt::DecNum(value.to_s) } nm = Array.wrap(nm).map { |value| Flt::DecNum(value.to_s) } m = ns.size n = nm.size sum = 0 if m == n (0...m).each do |i| sum += (ns[i] * nm[i]) end else raise(FinrbError, 'length of ns and nm must be equal') end sum /= 12 sum end |
.wpr(r:, w:) ⇒ Object
Weighted mean as a portfolio return
1088 1089 1090 1091 1092 1093 1094 1095 1096 |
# File 'lib/finrb/utils.rb', line 1088 def self.wpr(r:, w:) r = Array.wrap(r).map { |value| Flt::DecNum(value.to_s) } w = Array.wrap(w).map { |value| Flt::DecNum(value.to_s) } # TODO: need to change puts('sum of weights is NOT equal to 1!') if w.sum != 1 r.zip(w).sum { |arr| arr.reduce(:*) } end |