Class: Flt::Solver::TVM
- Inherits:
-
Object
- Object
- Flt::Solver::TVM
- Defined in:
- lib/solver/tvm.rb
Overview
A Time-Value-of-Money solver
Example:
tvm = TVM.new(Tolerance(3, :decimals), Float.context)
puts tvm.solve(:t=>240, :m0=>10000, :m=>0, :i=>3, :p=>12).inspect # => {:pmt=>-55.45975978539105}
Instance Method Summary collapse
- #equation(m, t, m0, pmt, i, p) ⇒ Object
-
#initialize(tol, context = Float.context) ⇒ TVM
constructor
A new instance of TVM.
-
#lnp1(x) ⇒ Object
ln(x+1).
- #parameter_descriptions ⇒ Object
-
#solve(parameters) ⇒ Object
Parameters: (using cash-flow sign convention) :t time in periods :p number of periods per year :i percent yearly interest rate :pmt payment per period :m0 initial value :m value at time :t.
- #value(parameters) ⇒ Object
Constructor Details
#initialize(tol, context = Float.context) ⇒ TVM
Returns a new instance of TVM.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/solver/tvm.rb', line 11 def initialize(tol, context=Float.context) @context = context @var_descriptions = { :m=>'money value at time t', :t=>'time', :m0=>'initial money value', :pmt=>'payment per time unit', :i=>'percent interest per year', :p=>'number of time units per year' } @vars = @var_descriptions.keys vars = @vars tvm = self @solver = PSolver.new(context, tol) do |m, t, m0, pmt, i, p| tvm.equation(m, t, m0, pmt, i, p) end @solver.default_guesses = 1,2 @one = @context.Num(1) end |
Instance Method Details
#equation(m, t, m0, pmt, i, p) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/solver/tvm.rb', line 55 def equation(m, t, m0, pmt, i, p) i /= 100 i /= p n = -t k = @context.exp(lnp1(i)*n) # (i+1)**n # Equation: -m*k = m0 + pmt*(1-k)/i if i == 0 # TODO: with tolerance? m0 + pmt*t + m # k == 1 else m0 + pmt*(@one-k)/i + m*k end end |
#lnp1(x) ⇒ Object
ln(x+1)
69 70 71 72 |
# File 'lib/solver/tvm.rb', line 69 def lnp1(x) v = x + 1 (v == 1) ? x : (x*@context.ln(v) / (v - 1)) end |
#parameter_descriptions ⇒ Object
31 32 33 |
# File 'lib/solver/tvm.rb', line 31 def parameter_descriptions @var_descriptions end |
#solve(parameters) ⇒ Object
Parameters: (using cash-flow sign convention)
:t time in periods
:p number of periods per year
:i percent yearly interest rate
:pmt payment per period
:m0 initial value
:m value at time :t
42 43 44 45 46 47 48 49 |
# File 'lib/solver/tvm.rb', line 42 def solve(parameters) nil_vars = @vars.select{|var| parameters[var].nil?} raise "Too many unknowns" if nil_vars.size>1 raise "Nothing to solve" if nil_vars.empty? var = nil_vars.first # determine sensible initial value? => parameters[var] = initial_value {var=>@solver.root(var, parameters)} end |
#value(parameters) ⇒ Object
51 52 53 |
# File 'lib/solver/tvm.rb', line 51 def value(parameters) @solver.equation_value(paramters) end |