Module: Finance::Cashflow
- Included in:
- Array
- Defined in:
- lib/finance/cashflows.rb
Overview
Provides methods for working with cash flows (collections of transactions)
Defined Under Namespace
Classes: Function
Instance Method Summary collapse
-
#irr ⇒ DecNum
calculate the internal rate of return for a sequence of cash flows.
- #method_missing(name, *args, &block) ⇒ Object
-
#npv(rate) ⇒ DecNum
calculate the net present value of a sequence of cash flows.
-
#xirr(iterations = 100) ⇒ Rate
calculate the internal rate of return for a sequence of cash flows with dates.
-
#xnpv(rate) ⇒ DecNum
calculate the net present value of a sequence of cash flows.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object
59 60 61 62 |
# File 'lib/finance/cashflows.rb', line 59 def method_missing(name, *args, &block) return self.inject(:+) if name.to_s == "sum" super end |
Instance Method Details
#irr ⇒ DecNum
calculate the internal rate of return for a sequence of cash flows
46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/finance/cashflows.rb', line 46 def irr # Make sure we have a valid sequence of cash flows. positives, negatives = self.partition{ |i| i >= 0 } if positives.empty? || negatives.empty? raise ArgumentError, "Calculation does not converge." end func = Function.new(self, :npv) rate = [ func.one ] nlsolve( func, rate ) rate[0] end |
#npv(rate) ⇒ DecNum
calculate the net present value of a sequence of cash flows
71 72 73 74 75 76 77 78 79 80 |
# File 'lib/finance/cashflows.rb', line 71 def npv(rate) self.collect! { |entry| Flt::DecNum.new(entry.to_s) } rate, total = Flt::DecNum.new(rate.to_s), Flt::DecNum.new(0.to_s) self.each_with_index do |cashflow, index| total += cashflow / (1 + rate) ** index end total end |
#xirr(iterations = 100) ⇒ Rate
calculate the internal rate of return for a sequence of cash flows with dates
91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/finance/cashflows.rb', line 91 def xirr(iterations=100) # Make sure we have a valid sequence of cash flows. positives, negatives = self.partition{ |t| t.amount >= 0 } if positives.empty? || negatives.empty? raise ArgumentError, "Calculation does not converge." end func = Function.new(self, :xnpv) rate = [ func.one ] nlsolve( func, rate ) Rate.new(rate[0], :apr, :compounds => :annually) end |
#xnpv(rate) ⇒ DecNum
calculate the net present value of a sequence of cash flows
113 114 115 116 117 118 119 120 121 |
# File 'lib/finance/cashflows.rb', line 113 def xnpv(rate) rate = Flt::DecNum.new(rate.to_s) start = self[0].date self.inject(0) do |sum, t| n = t.amount / ( (1 + rate) ** ((t.date-start) / Flt::DecNum.new(31536000.to_s))) # 365 * 86400 sum + n end end |