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