"Mortgage"

#
# All based on this formula:
#
# fv (1 + i) ^ -n = pv + pmt * (1 - (1 + i) ^ -n) / i;
#
#   pv = Present Value
#   fv = Future Value
#   i = Interest Rate
#   n = Period
#   pmt = Payment
#

define private fvf (fvf) (i, n)
{
    fvf = (1 + i) ^ -n;
}

define private pf (pf) (i, n)
{
    pf = (1 - fvf(i,n)) / i;
}

define private pmt "Loan Payment" 
    (pmt "Payment",
     cost "Interest Paid")
    (pv "Present Value",
     fv "Future Value", 
     i "Interest", 
     n "Period")
{
    pmt = - (fv * fvf (i, n) + pv) / pf(i,n);
    cost = pmt * n + (pv - fv);
}

define private abs (a) (i)
{
	if (i < 0) a = -i; else a=i;
}

define private i "Interest Rate" 
    (i "Interest",
     cost "Interest Paid")
    (pv "Present Value",
     fv "Future Value", 
     n "Period", 
     pmt "Payment")
{
    local   oi, r, dr, p1, p2, p3, dmort, mort;
    
    i = 0.01;
    do
    {
	oi = i;
	r = pmt * pf (i, n) - fv * fvf(i,n) + pv;
	p1 = i * (-n) * (1 + i) ^ (-n - 1) - (1-(1+i)^-n);
	p2 = pmt * p1 / (i ^ 2);
	p3 = -fv * (-n) * (1 + i) ^ (-n - 1);
	dr = p2 + p3 + pv;
	i = i - r / dr;
    } while (abs (i - oi) > 1/10000000);
    cost = pmt * n + (pv - fv);
}

define private fv "Future Value" 
    (fv "Future Value",
     cost "Interest Paid")
    (pv "Present Value",
     i "Interest", 
     n "Period", 
     pmt "Payment")
{
    fv = (pmt * pf(i,n) + pv) / fvf (i, n);
    cost = pmt * n + (pv - fv);
}

define private pv "Present Value" 
    (pv "Present Value",
     cost "Interest Paid")
    (fv "Future Value",
     i "Interest",
     n "Period",
     pmt "Payment")
{
    pv = fv * fvf (i, n) - pmt * pf(i,n);
    cost = pmt * n + (pv - fv);
}

define private n "Loan Period" 
    (n "Period",
     cost "Interest Paid")
    (pv "Present Value",
     fv "Future Value",
     i "Interest",
     pmt "Payment")
{
    local    num, den;

    if (pmt - fv * i < 0)
	num = log (-pmt + fv * i) - log (-pmt - pv * i);
    else
	num = log (pmt - fv * i) - log (pmt + pv * i);
    den = log (1 + i);
    n = num / den;
    cost = pmt * n + (pv - fv);
}

prev = 4;

define Mortgage *
    (pv ? "Present Value",
      fv ? "Future Value",
      i ? "Interest",
      n ? "Period",
      pmt ? "Payment",
      cost ? "Interest Paid")
{
     if (!?pv) prev = 0;
     else if (!?fv) prev = 1;
     else if (!?i) prev = 2;
     else if (!?n) prev = 3;
     else if (!?pmt) prev = 4;
     if (?i && i >= 1) i= i/1200;
     if (prev == 0)
        pv, cost = pv (fv, i, n, pmt);
     else if (prev == 1)
        fv, cost = fv (pv, i, n, pmt);
     else if (prev == 2)
        i, cost = i (pv, fv, n, pmt);
     else if (prev == 3)
       n, cost = n (pv, fv, i, pmt);
     else
        pmt, cost = pmt (pv, fv, i, n);
}

define loan "Loan Cost"
    (loan "Total cost",
    pmt "Payment",
     cfv "Balance")
    (pv "Loan Amount",
     ai "Annual %",
     pts "Points %",
     ny "Loan Years",
     cny "Cost Years")
{
    local    i, n, cn,  inv_pv, inv_fv, inv_cost, cost, shortcost;

    i = ai / 1200;
    n = ny * 12;
    cn = cny * 12;
    pmt, cost = pmt (pv, 0, i, n);
    cfv, shortcost = fv (pv, i, cn, pmt);
    inv_pv = pv * pts / 100;
    inv_fv, inv_cost = fv (inv_pv, i, cn, -pmt);

    loan = inv_fv + cfv - pv;
}

define thirty "30 year fixed"
	(pmt "Payment",
	  cost "Cost")
	(pv "Amount",
	  iy "Yearly %")
{
	pmt, cost = pmt(pv, 0, iy/1200, 360);
}
