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
36 37 38 39 40 41 42 |
# File 'lib/finrb/utils.rb', line 36 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
50 51 52 53 54 55 |
# File 'lib/finrb/utils.rb', line 50 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.
64 65 66 67 68 69 70 |
# File 'lib/finrb/utils.rb', line 64 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
78 79 80 81 82 83 |
# File 'lib/finrb/utils.rb', line 78 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)
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 195 |
# File 'lib/finrb/utils.rb', line 101 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:, 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.
203 204 205 206 207 208 |
# File 'lib/finrb/utils.rb', line 203 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.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/finrb/utils.rb', line 217 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 = [Flt::DecNum(0)] * t ddb[0] = cost * 2 / t if cost - ddb.first <= rv ddb[0] = cost - rv else cost -= ddb.first (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: } end |
.debt_ratio(td:, ta:) ⇒ Object
debt ratio -- Solvency ratios measure the firm's ability to satisfy its long-term obligations.
249 250 251 252 253 254 |
# File 'lib/finrb/utils.rb', line 249 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
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/finrb/utils.rb', line 278 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
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/finrb/utils.rb', line 306 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.first, n:, pv:) + Finrb::Utils.fv_annuity(r: x.first, n:, pmt:, type:) - fv).to_s)] end root = [BigDecimal(((upper - lower) / 2).to_s)] nlsolve(nlfunc, root) Flt::DecNum(root.first) end |
.ear(r:, m:) ⇒ Object
Convert stated annual rate to the effective annual rate
335 336 337 338 339 340 |
# File 'lib/finrb/utils.rb', line 335 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
361 362 363 364 365 |
# File 'lib/finrb/utils.rb', line 361 def self.ear2bey(ear:) ear = Flt::DecNum(ear.to_s) (((ear + 1).sqrt - 1) * 2) end |
.ear2hpr(ear:, t:) ⇒ Object
Computing HPR, the holding period return
373 374 375 376 377 378 |
# File 'lib/finrb/utils.rb', line 373 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
350 351 352 353 354 |
# File 'lib/finrb/utils.rb', line 350 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
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 |
# File 'lib/finrb/utils.rb', line 415 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
439 440 441 442 443 444 445 |
# File 'lib/finrb/utils.rb', line 439 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.
453 454 455 456 457 458 |
# File 'lib/finrb/utils.rb', line 453 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)
469 470 471 472 473 474 475 476 477 478 479 480 481 |
# File 'lib/finrb/utils.rb', line 469 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:, n:, pv:) + Finrb::Utils.fv_annuity(r:, n:, pmt:, type:)) end end |
.fv_annuity(r:, n:, pmt:, type: 0) ⇒ Object
Estimate future value of an annuity
494 495 496 497 498 499 500 501 502 503 504 505 |
# File 'lib/finrb/utils.rb', line 494 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:, 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(:*)**(Flt::DecNum(1) / 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) } (Flt::DecNum(1) / (p.sum { |val| Flt::DecNum(1) / 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.first, cf: subcf) * -1) + cf.first).to_s)] end root = [0] nlsolve(nlfunc, root) Flt::DecNum(root.first) 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 |
# 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))) * Flt::DecNum(-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
730 731 732 733 734 735 |
# File 'lib/finrb/utils.rb', line 730 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
743 744 745 746 747 748 749 |
# File 'lib/finrb/utils.rb', line 743 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:, cf: subcf) * -1) + cf.first) end |
.pmt(r:, n:, pv:, fv:, type: 0) ⇒ Object
Estimate period payment
766 767 768 769 770 771 772 773 774 775 776 777 778 |
# File 'lib/finrb/utils.rb', line 766 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 - (Flt::DecNum(1) / ((r + 1)**n))) * -1 * ((r + 1)**(type * -1)) end end |
.pv(r:, n:, fv: 0, pmt: 0, type: 0) ⇒ Object
Estimate present value (pv)
792 793 794 795 796 797 798 799 800 801 802 803 804 |
# File 'lib/finrb/utils.rb', line 792 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:, n:, fv:) + Finrb::Utils.pv_annuity(r:, n:, pmt:, type:) end end |
.pv_annuity(r:, n:, pmt:, type: 0) ⇒ Object
Estimate present value (pv) of an annuity
817 818 819 820 821 822 823 824 825 826 827 828 |
# File 'lib/finrb/utils.rb', line 817 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 - (Flt::DecNum(1) / ((r + 1)**n)))) * ((r + 1)**type) * -1 end end |
.pv_perpetuity(r:, pmt:, g: 0, type: 0) ⇒ Object
Estimate present value of a perpetuity
844 845 846 847 848 849 850 851 852 853 854 855 856 857 |
# File 'lib/finrb/utils.rb', line 844 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
869 870 871 872 873 874 875 |
# File 'lib/finrb/utils.rb', line 869 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
883 884 885 886 887 888 889 890 891 892 893 |
# File 'lib/finrb/utils.rb', line 883 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:, 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.
903 904 905 906 907 908 909 910 |
# File 'lib/finrb/utils.rb', line 903 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
918 919 920 921 922 923 |
# File 'lib/finrb/utils.rb', line 918 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
934 935 936 937 938 939 |
# File 'lib/finrb/utils.rb', line 934 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
947 948 949 950 951 952 |
# File 'lib/finrb/utils.rb', line 947 def self.r_perpetuity(pmt:, pv:) pmt = Flt::DecNum(pmt.to_s) pv = Flt::DecNum(pv.to_s) (pmt * Flt::DecNum(-1) / pv) end |
.sampling_error(sm:, mu:) ⇒ Object
Computing Sampling error
960 961 962 963 964 965 |
# File 'lib/finrb/utils.rb', line 960 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
974 975 976 977 978 979 980 |
# File 'lib/finrb/utils.rb', line 974 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
989 990 991 992 993 994 995 |
# File 'lib/finrb/utils.rb', line 989 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
1004 1005 1006 1007 1008 1009 1010 |
# File 'lib/finrb/utils.rb', line 1004 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.
1018 1019 1020 1021 1022 1023 |
# File 'lib/finrb/utils.rb', line 1018 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
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 |
# File 'lib/finrb/utils.rb', line 1032 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 = Flt::DecNum(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**(Flt::DecNum(1) / r)) - 1) end end |
.was(ns:, nm:) ⇒ Object
calculate weighted average shares -- weighted average number of common shares
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 |
# File 'lib/finrb/utils.rb', line 1060 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
1084 1085 1086 1087 1088 1089 1090 1091 1092 |
# File 'lib/finrb/utils.rb', line 1084 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 |