/* rexx */ i = 1 do until rc = 0 say 'Enter the name of the dataset you wish to write to (SEQUENTIAL ONLY!):' parse pull dataSetName upper dataSetName do until (dataformat = 'TEXT' | dataformat = 'HTML') say 'Enter a data format (TEXT or HTML):' parse pull dataFormat upper dataFormat if dataformat = 'HTML' then do RECORD.i = '' i = i + 1 RECORD.i = '' i = i + 1 RECORD.i = 'Loan Amortization' i = i + 1 RECORD.i = '' i = i + 1 end end say 'Attempting to allocate dataset "'||userID()||'.'||dataSetName||'"...' address tso status = SYSDSN("'"||userID()||'.'||dataSetName||"'") if status = "DATASET NOT FOUND" then do "ALLOC F(OUTPUT) DA('"userID()||"."||dataSetName||"')", ||" NEW SPACE (100,200) TRACK LRECL(200) RECFM(F B) ", ||" BLKSIZE(32600)" end; else do say "Dataset already exists! Would you like to overwite? (y/n)" parse pull response upper response if (response = 'Y' | response = 'YES') then do "DELETE '"userID()||"."||dataSetName||"' SCRATCH NONVSAM" "ALLOC F(OUTPUT) DA('"userID()||"."||dataSetName||"')", ||" NEW SPACE (100,200) TRACK LRECL(200) RECFM(F B) ", ||" BLKSIZE(32600)" rc = 0 end; else do rc = 1 end end if rc > 1 then do say "An error has occured while allocating! Please try again!" say "" end end principal = getNumericInput("principal amount", "Principal") rate = getNumericInput("annual interest rate as a percentage ", ||"(Ex: for 5.5%, enter 5.5)", "Interest rate") years = getNumericInput("loan length in years", "Loan length") addPayment = getNumericInput("additional payment ammount", "Additional payment") RECORD.i = 'Principal : $'||format(principal, , 2) i = i + 1 if dataFormat = 'HTML' then do RECORD.i = '
' i = i + 1 end RECORD.i = 'Rate :' rate||"%" i = i + 1 if dataFormat = 'HTML' then do RECORD.i = '
' i = i + 1 end RECORD.i = 'Length :' years 'years' i = i + 1 if dataFormat = 'HTML' then do RECORD.i = '
' i = i + 1 end RECORD.i = 'Addt. Payment: $'||format(addPayment, , 2) i = i + 1 if dataFormat = 'HTML' then do RECORD.i = '
' i = i + 1 end if printTable = 1 then do RECORD.i = ' ' i = i + 1 end if dataFormat = 'HTML' then do RECORD.i = '
' i = i + 1 end totalPaid = generateAmortization(principal, rate/100, years, addPayment, 1, i) if dataFormat = 'TEXT' then do RECORD.i = ' ' i = i + 1 end if dataFormat = 'HTML' then do RECORD.i = '
' i = i + 1 end RECORD.i = "Total amount paid: $"||totalPaid i = i + 1 if dataFormat = 'HTML' then do RECORD.i = '
' i = i + 1 end if addPayment > 0 then do noPaymentTotal = generateAmortization(principal, rate/100, years, 0, 0, i) RECORD.i = "ROI from additional payments: $"||(noPaymentTotal - totalPaid) i = i + 1 if dataFormat = 'HTML' then do RECORD.i = '
' i = i + 1 end end if dataFormat = 'TEXT' then do RECORD.i = ' ' i = i + 1 end if dataFormat = 'HTML' then do RECORD.i = '
' i = i + 1 end RECORD.i = "Amortization run by user" userID() "on" date("W")||"," date() "at", ||" "||time("C")||"." i = i + 1 if dataFormat = 'HTML' then do RECORD.i = '' i = i + 1 RECORD.i = "" i = i + 1 end "EXECIO * DISKW OUTPUT (OPEN FINIS STEM RECORD.)" "FREE F(OUTPUT)" say "Amortization complete!" exit generateAmortization: parse arg loanAmount, intRate, numYears, extraPayment, printTable, i total = 0 month = 0 year = 0 remainPrincipal = loanAmount if (printTable = 1 & dataFormat = 'TEXT') then do RECORD.i = ' ' i = i + 1 RECORD.i = "| Period | Beginning Principal | Payment Amount ", ||"| Extra Payment Amount | Total Interest | Total Principal ", ||"| New Principal |" i = i + 1 end if (printTable = 1 & dataFormat = 'HTML') then do RECORD.i = ' ' i = i + 1 RECORD.i = '' i = i + 1 RECORD.i = "", ||"", ||"", ||"" i = i + 1 RECORD.i = '' i = i + 1 end monthlyPayment = (loanAmount*(intRate/12))/(1-((1+intRate/12)**(-12*numYears))) monthlyPayment = trunc(monthlyPayment, 2) /*truncation means more money :)*/ do while remainPrincipal > 0 beginPrincipal = format(remainPrincipal, , 2) intPayment = format(remainPrincipal * intRate / 12, , 2) if remainPrincipal >= (monthlyPayment - intPayment) then do princPayment = monthlyPayment - intPayment if (remainPrincipal - princPayment) < extraPayment then do extraPayment = max(remainPrincipal - princPayment, 0) end end; else do princPayment = remainPrincipal extraPayment = 0 end total = total + intPayment + extraPayment + princPayment remainPrincipal = remainPrincipal - princPayment - extraPayment if remainPrincipal < 0 then do remainPrincipal = 0 end if (printTable = 1 & dataFormat = 'TEXT') then do RECORD.i = "|" monthOf(left(date('U'),2)+month) right(date(),4)+year, ||" |" right("$"||beginPrincipal,19), ||" |" right("$"||(extraPayment + princPayment + intPayment),14,), ||" |" right("$"||format(extraPayment,,2),20), ||" |" right("$"||intPayment,14), ||" |" right("$"||(princPayment),15), ||" |" right("$"||remainPrincipal,13) "|" i = i + 1 end if (printTable = 1 & dataFormat = 'HTML') then do RECORD.i = '' i = i + 1 RECORD.i = "" i = i + 1 RECORD.i = "' i = i + 1 RECORD.i = "' i = i + 1 RECORD.i = "' i = i + 1 RECORD.i = "' i = i + 1 RECORD.i = "' i = i + 1 RECORD.i = "' i = i + 1 RECORD.i = '' i = i + 1 end month = month + 1 if left(date('U'),2)+month > 12 then do month = -1*left(date('U'),2)+1 /* reset to January */ year = year + 1 end end if (printTable = 1 & dataFormat = 'HTML') then do RECORD.i = '
PeriodBeginning PrincipalPayment AmountExtra Payment AmountTotal InterestTotal PrincipalNew Principal
" monthOf(left(date('U'),2)+month) right(date(),4)+year, ||""right("$"||beginPrincipal,19)||'", ||right("$"||(extraPayment + princPayment + intPayment),14,), ||'"right("$"||format(extraPayment,,2),20)||'"right("$"||intPayment,14)||'"right("$"||(princPayment),15)||'"right("$"||remainPrincipal,13)||'
' i = i + 1 end return total monthOf: parse arg num if num < 1 or num > 12 then do return "???" end if num = 1 then do return "Jan" end if num = 2 then do return "Feb" end if num = 3 then do return "Mar" end if num = 4 then do return "Apr" end if num = 5 then do return "May" end if num = 6 then do return "Jun" end if num = 7 then do return "Jul" end if num = 8 then do return "Aug" end if num = 9 then do return "Sep" end if num = 10 then do return "Oct" end if num = 11 then do return "Nov" end if num = 12 then do return "Dec" end getNumericInput: parse arg prompt, name say "Enter" prompt||":" flag = 0 do until flag = 1 parse pull input say "" if datatype(input) \= 'NUM' then do say "ERROR:" name "must be a number!" say "Enter" prompt||":" iterate end if input < 0 then do say "ERROR:" name "cannot be negative!" say "Enter" prompt||":" iterate end flag = 1 end return input