class Flt::Solver::TVM

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}

Public Class Methods

new(tol, context=Float.context) click to toggle source
# 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

Public Instance Methods

equation(m, t, m0, pmt, i, p) click to toggle source
# 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) click to toggle source

ln(x+1)

# 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() click to toggle source
# File lib/solver/tvm.rb, line 31
def parameter_descriptions
  @var_descriptions
end
solve(parameters) click to toggle source

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
# 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) click to toggle source
# File lib/solver/tvm.rb, line 51
def value(parameters)
  @solver.equation_value(paramters)
end