Loan Mortgage Amortizer

Date: 1982
Type: Cassette
Platform(s): TS 1000
Tags: Finance

This program calculates and displays amortization data for fixed-rate mortgages, accepting principal, term (up to 30 years), and annual interest rate as inputs. It pre-computes all monthly payment breakdowns into a two-dimensional array T(N,3), storing per-payment interest, cumulative interest paid, and remaining principal balance for up to 360 entries. Five report modes are available: single payment detail, single year summary, monthly profile scrolling table, yearly profile scrolling table, and a character-graphics plot of the interest/principal split over the loan term. Column alignment for dollar amounts is handled manually by computing display offsets based on the magnitude of each value, using a cascading series of IF comparisons to set tab positions.


Program Analysis

Program Structure

The program is organized as a main setup sequence with five subroutine modules and a main menu loop. Execution begins at line 10 with GOTO 3500, jumping past all subroutine code to the splash/intro section. Control flow is summarized below:

Line RangePurpose
10Entry point — jumps to initialization
95–496Subroutine: Single Payment Report
499–1090Subroutine: Single Year Report
1195–1530Subroutine: Monthly Profile (scrolling table)
1595–2020Subroutine: Yearly Profile (scrolling table)
2195–2470Subroutine: Interest/Principal Plot
3500–3730Splash screens and introduction text
3800–4180Data entry (principal, years, rate) and preliminary results
4200–4490First-payment date entry and amortization table computation loop
4490–4850Report menu and dispatch loop
4900–4910Program termination (CLEAR, CLS)

Amortization Table Computation

After all inputs are validated, a DIM T(N,3) statement at line 4020 allocates the full payment table, where N = Y * 12 (number of monthly payments, capped at 360 for a 30-year loan). The loop at lines 44104480 runs in FAST mode and fills three columns per payment:

  • T(X,1) — interest portion of payment X
  • T(X,2) — cumulative interest paid through payment X
  • T(X,3) — remaining principal balance after payment X

The monthly payment amount M is computed using the standard annuity formula at line 4030: M = P*I / (1 - (1+I)^(-N)), where I = A/12 is the monthly rate. The rounded value M1 is used for display, while the unrounded M is used in the amortization loop to avoid accumulating rounding errors over the life of the loan — a deliberate and correct design choice.

Rounding Convention

Throughout the program, monetary values are rounded to two decimal places using the idiom (INT (X*100+.5))/100. This banker-style rounding by half-up addition appears consistently in all five report subroutines and in the main computation. A threshold check, IF T3<.1 THEN LET T3=0 (lines 250, 850) and IF ABS T3<.6 THEN LET T3=0 (lines 1400, 1900), handles floating-point residuals in the final balance, preventing a nearly-zero balance from being displayed as a small non-zero number.

Manual Column Alignment

Because the platform’s PRINT statement does not support right-justified numeric output, the program manually computes a starting column Z1, Z2, or Z3 for each dollar figure by testing its magnitude with a cascade of IF statements. For example, lines 300330 set Z1 to 5, 6, 7, or 8 depending on whether the interest amount is ≥1000, ≥100, ≥10, or smaller. This shifts the dollar sign leftward by one column for each additional digit, approximating right-alignment within a fixed field.

Report Subroutines

All five reports are implemented as GOSUB targets ending with RETURN, called from the dispatch block at lines 47604820. After returning, a PAUSE 40000 at line 4830 holds the display until a key is pressed (a standard long-pause keypress-wait idiom), then FAST is set and the menu redraws.

The two profile reports (monthly at 1200, yearly at 1600) implement paginated output: a counter CT tracks rows printed, and at 19 rows the program hits a STOP statement at lines 1430 or 1930. This is intended to pause output, but it unconditionally halts execution rather than waiting for a keypress and continuing — a functional bug. The CLS and header reprint at lines 14401460 and 19401960 are unreachable dead code because they follow STOP with no conditional path to reach them.

Interest/Principal Plot

The plot subroutine at lines 22002470 draws a character-graphics chart using PLOT commands. A Y-axis label is printed character by character from the string Y$=" DOLLARS" using PRINT AT J,0;Y$(J) in a loop, placing one character per screen row. Axis lines are drawn with PLOT loops. Data points are sampled every 6 payments (STEP 6) and scaled to a 40-unit vertical range proportional to the monthly payment M. Both the interest fraction and the principal fraction are plotted per sample, and labels “P” and “I” are positioned at the midpoints of their respective curves using computed AT coordinates.

Input Validation

All numeric inputs are validated with range checks, and invalid entries restart the relevant input section via GOTO. Notable constraints enforced include:

  • Principal must be positive (line 3834)
  • Term must be 1–30 years (line 3864); a special case at line 4015 handles a half-year term (Y=.5, N=6), inconsistent with the prompt restricting Y>0 as integer
  • Rate must be in decimal form, between 0 and 1 exclusive (line 3894)
  • Month inputs must be 1–12; year inputs must fall within the computed loan span

A confirmation step at lines 39103930 allows the user to re-enter all data if any value is wrong, by checking whether the input string K$ is empty.

Notable Anomalies

  • Line 1230 contains a typo: “PLEAE ENTER” instead of “PLEASE ENTER”.
  • The STOP-based pagination in the profile routines (lines 1430, 1930) unconditionally terminates the program rather than pausing; the CLS/reprint code immediately following is dead code.
  • The variable Y is reused: it stores the loan term in years during setup, but within the yearly profile subroutine Y1 is computed as the number of remaining years. If Y were overwritten this would corrupt data, but the subroutine uses Y1 as its loop counter, so the loan-term value in Y is preserved.
  • Line 4015 tests IF Y=.5 THEN LET N=6 to support a six-month loan term, but the input validation at line 3864 only rejects Y<=0, so fractional year values other than 0.5 would produce a non-integer N passed to DIM, likely causing an error.

Content

Appears On

Related Products

Compare the cost of loans from different banks. 16K.

Related Articles

Related Content

Image Gallery

Loan Mortgage Amortizer

Source Code

  10 GOTO 3500
  95 REM SINGLE PAYMENT ROUTINE
 100 CLS 
 110 PRINT "     SINGLE PAYMENT MODE"
 120 PRINT "     ''''''''''''''''''''''''''''''''''''''"
 130 PRINT AT 5,1;"ENTER THE DATE OF THE PAYMENT  IN WHICH YOU ARE INTERESTED"
 140 PRINT AT 11,3;"FIRST THE MONTH (2 DIGITS)"
 150 INPUT MN
 160 IF MN<1 OR MN>12 THEN GOTO 100
 170 PRINT AT 15,3;"AND THE YEAR (4 DIGITS)"
 180 INPUT YR
 190 LET X=(YR-FY)*12+MN-FM+1
 200 IF X<1 OR X>N THEN GOTO 100
 210 FAST 
 220 LET T1=(INT (T(X,1)*100+.5))/100
 230 LET T2=(INT (T(X,2)*100+.5))/100
 240 LET T3=(INT (T(X,3)*100+.5))/100
 250 IF T3<.1 THEN LET T3=0
 260 LET MP=M1-T1
 270 LET MP=(INT (MP*100+.5))/100
 280 LET TP=OP-T3+T2
 290 LET TP=(INT (TP*100+.5))/100
 300 LET Z1=5
 310 IF T1<1000 THEN LET Z1=6
 320 IF T1<100 THEN LET Z1=7
 330 IF T1<10 THEN LET Z1=8
 340 LET Z2=5
 350 IF MP<1000 THEN LET Z2=6
 360 IF MP<100 THEN LET Z2=7
 370 IF MP<10 THEN LET Z2=8
 380 LET Z3=5
 390 IF M1<1000 THEN LET Z3=6
 400 IF M1<100 THEN LET Z3=7
 410 CLS 
 420 PRINT "MORTGAGE DATA FOR ";MN;"/";YR
 430 PRINT AT 4,4;"PAYMENT:"
 440 PRINT AT 6,Z1;"$";T1;TAB 13;"  INTEREST"
 450 PRINT AT 7,Z2;"$";MP;TAB 13;"  PRINCIPAL"
 460 PRINT AT 8,5;"................"
 470 PRINT AT 9,Z3;"$";M1;TAB 13;"  TOTAL"
 475 PRINT AT 12,0;"AFTER THIS PAYMENT:"
 480 PRINT AT 14,2;"PRINCIPAL BALANCE = $";T3
 490 PRINT AT 16,2;"INTEREST PAID     = $";T2
 494 PRINT AT 18,2;"TOTAL PAID        = $";TP
 496 RETURN 
 499 REM SINGLE YEAR ROUTINE
 500 CLS 
 510 LET YI=0
 520 PRINT "       SINGLE YEAR MODE"
 530 PRINT "       ''''''''''''''''''''''''''''''''"
 540 PRINT AT 8,3;"ENTER THE YEAR IN WHICH YOU   ARE INTERESTED (4 DIGITS)"
 560 INPUT YR
 570 LET LY=FY+Y
 580 IF YR<FY OR YR>LY THEN GOTO 500
 590 FAST 
 600 IF YR<>FY THEN GOTO 640
 610 LET Z=1
 620 LET W=13-FM
 630 GOTO 680
 640 LET Z=(YR-FY)*12+2-FM
 650 LET W=Z+11
 660 IF W<N THEN GOTO 680
 670 LET W=N
 680 FOR X=Z TO W
 690 LET YI=YI+T(X,1)
 700 NEXT X
 710 LET YI=(INT (YI*100+.5))/100
 720 IF W<>N AND YR<>FY THEN GOTO 780
 730 IF YR=FY THEN GOTO 760
 740 LET YP=M1*LM-YI
 750 GOTO 790
 760 LET YP=M1*(13-FM)-YI
 770 GOTO 790
 780 LET YP=M1*12-YI
 790 LET TPY=YI+YP
 800 LET YP=(INT (YP*100+.5))/100
 810 LET TP=OP-T(W,3)+T(W,2)
 820 LET TP=(INT (TP*100+.5))/100
 830 LET T2=(INT (T(W,2)*100+.5))/100
 840 LET T3=(INT (T(W,3)*100+.5))/100
 850 IF T3<.1 THEN LET T3=0
 860 LET Z1=5
 870 IF YI<10000 THEN LET Z1=6
 880 IF YI<1000 THEN LET Z1=7
 890 IF YI<100 THEN LET Z1=8
 900 LET Z2=5
 910 IF YP<10000 THEN LET Z2=6
 920 IF YP<1000 THEN LET Z2=7
 930 IF YP<100 THEN LET Z2=8
 935 IF YP<10 THEN LET Z2=9
 940 LET Z3=5
 950 IF TPY<10000 THEN LET Z3=6
 960 IF TPY<1000 THEN LET Z3=7
 970 IF TPY<100 THEN LET Z3=8
 980 CLS 
 990 PRINT "MORTGAGE DATA FOR YEAR ";YR
 1000 PRINT AT 4,4;"TOTALS FOR THE YEAR:"
 1010 PRINT AT 6,Z1;"$";YI;TAB 17;"INTEREST"
 1020 PRINT AT 7,Z2;"$";YP;TAB 17;"PRINCIPAL"
 1030 PRINT AT 8,5;"...................."
 1040 PRINT AT 9,Z3;"$";TPY;TAB 17;"TOTAL"
 1050 PRINT AT 12,0;"AT YEAR END:"
 1060 PRINT AT 14,2;"PRINCIPAL BALANCE = $";T3
 1070 PRINT AT 16,2;"INTEREST PAID     = $";T2
 1080 PRINT AT 18,2;"TOTAL PAID        = $";TP
 1090 RETURN 
 1195 REM MONTHLY PROFILE ROUTINE
 1200 CLS 
 1210 PRINT "     MONTHLY PROFILE MODE"
 1220 PRINT "     ''''''''''''''''''''''''''''''''''''''''"
 1230 PRINT AT 6,2;"PLEAE ENTER THE DATE AT WHICH   THE REPORT SHOULD START"
 1240 PRINT AT 12,4;"FIRST THE MONTH (2 DIGITS)"
 1250 INPUT MN
 1260 IF MN<1 OR MN>12 THEN GOTO 1200
 1270 PRINT AT 17,4;"NOW THE YEAR (4 DIGITS)"
 1280 INPUT YR
 1290 LET Z=(YR-FY)*12+MN-FM+1
 1300 IF Z<1 OR Z>N THEN GOTO 1200
 1310 FAST 
 1320 CLS  
 1330 PRINT "DATE   INT   TOTAL INT  PRIN BAL"
 1340 LET CT=0
 1350 FOR X=Z TO N
 1360 LET T1=(INT (T(X,1)*100+.5))/100
 1370 LET T2=(INT (T(X,2)*100+.5))/100
 1380 LET T3=(INT (T(X,3)*100+.5))/100
 1390 LET CT=CT+1
 1400 IF ABS T3<.6 THEN LET T3=0
 1410 PRINT " ";MN;TAB 5;T1;TAB 13;T2;TAB 24;T3
 1415 IF T3=0 THEN GOTO 1530
 1420 IF CT<19 THEN GOTO 1470
 1430 STOP 
 1440 CLS 
 1450 PRINT "DATE   INT   TOTAL INT  PRIN BAL"
 1460 LET CT=0
 1470 LET MN=MN+1
 1480 IF MN<=12 THEN GOTO 1520
 1490 LET MN=1
 1500 LET YR=YR+1
 1510 PRINT YR
 1520 NEXT X
 1530 RETURN 
 1595 REM YEARLY PROFILE ROUTINE
 1600 CLS 
 1610 LET CT=0
 1620 LET YI=0
 1630 PRINT "     PROFILE BY YEAR MODE"
 1640 PRINT "     ''''''''''''''''''''''''''''''''''''''''"
 1650 PRINT AT 8,2;"PLEASE ENTER THE YEAR AT WHICH  THE REPORT SHOULD START"
 1660 INPUT YR
 1670 LET LY=FY+Y
 1680 IF YR<FY OR YR>LY THEN GOTO 1600
 1690 FAST 
 1700 IF YR<>FY THEN GOTO 1740
 1710 LET Z=1
 1720 LET W=13-FM
 1730 GOTO 1760
 1740 LET Z=(YR-FY)*12+2-FM
 1750 LET W=Z+11
 1760 LET Y1=FY+Y+1-YR
 1770 IF W>N THEN LET W=N
 1780 CLS 
 1790 PRINT "YEAR   INT   TOTAL INT  PRIN BAL"
 1800 FOR I=1 TO Y1
 1810 LET YI=0
 1820 FOR X=Z TO W
 1830 LET YI=YI+T(X,1)
 1840 NEXT X
 1850 LET Y2=YR+I-1
 1860 LET YI=(INT (YI*100+.5))/100
 1870 LET T2=(INT (T(W,2)*100+.5))/100
 1880 LET T3=(INT (T(W,3)*100+.5))/100
 1890 LET CT=CT+1
 1900 IF ABS T3<.6 THEN LET T3=0
 1910 PRINT Y2;TAB 5;YI;TAB 14;T2;TAB 24;T3
 1915 IF T3=0 THEN GOTO 2020
 1920 IF CT<19 THEN GOTO 1970
 1930 STOP 
 1940 CLS 
 1950 LET CT=0
 1960 PRINT "YEAR   INT   TOTAL INT  PRIN BAL"
 1970 LET Z=X
 1980 LET W=Z+11
 1990 IF W<N THEN GOTO 2010
 2000 LET W=N
 2010 NEXT I
 2020 RETURN 
 2195 REM P/I PLOT ROUTINE
 2200 CLS 
 2210 FAST 
 2220 LET Y$="     DOLLARS"
 2230 FOR J=1 TO 12
 2240 PRINT AT J,0;Y$(J)
 2250 NEXT J
 2260 FOR J=3 TO 43
 2270 PLOT 3,J
 2280 NEXT J
 2290 FOR J=3 TO 63
 2300 PLOT J,3
 2310 NEXT J
 2320 SLOW 
 2330 PRINT AT 21,12;"YEARS"
 2340 PRINT AT 21,1;"0";TAB 30;"30"
 2350 LET C=3
 2360 FOR J=1 TO N STEP 6
 2370 LET C=C+1
 2380 PLOT C,T(J,1)*40/M+3
 2390 PLOT C,(M-T(J,1))*40/M+3
 2400 NEXT J
 2410 LET J=J-1
 2420 LET AB=(T(J,1)*40/M+3)/2
 2430 LET AC=((M-T(J,1))*40/M+3)/2
 2440 PRINT AT AB-1,(C/2)-2;"P"
 2450 PRINT AT AC-2,(C/2)-2;"I"
 2470 RETURN 
 3500 SLOW 
 3510 PRINT AT 11,2;"A  T.J. SOFTWARE PRODUCTION"    
 3520 PAUSE 200
 3530 CLS 
 3540 PRINT AT 11,6;"ALL RIGHTS RESERVED"
 3550 PAUSE 200
 3560 CLS 
 3565 PRINT AT 0,10;"INTRODUCTION"
 3566 PRINT AT 1,10;"''''''''''''''''''''''''"
 3570 PRINT AT 3,3;"THIS PROGRAM WILL ENABLE YOU"
 3580 PRINT "TO INVESTIGATE THE DETAILS OF A" 
 3590 PRINT "FIXED RATE MORTGAGE. TO USE THIS"
 3600 PRINT "PROGRAM YOU WILL NEED TO KNOW,"
 3610 PRINT "THE AMOUNT YOU WISH TO BORROW OR"
 3620 PRINT "THE PRINCIPAL, THE NUMBER OF "
 3630 PRINT "YEARS YOU NEED TO PAY IT BACK,"
 3640 PRINT "THE INTEREST RATE THE BANK WILL"
 3650 PRINT "CHARGE YOU AND THE DATE OF YOUR"
 3660 PRINT "FIRST PAYMENT."
 3670 PRINT 
 3680 PRINT "   THERE ARE FIVE DIFFERENT"
 3690 PRINT "REPORTS AVAILABLE, AFTER VIEWING"
 3700 PRINT "A REPORT PRESS ENTER TO RETURN"
 3710 PRINT "TO REPORT MENU."
 3720 PRINT AT 21,0;"PRESS ENTER TO CONTINUE"
 3730 PAUSE 4000
 3800 SLOW 
 3810 CLS 
 3814 PRINT "          DATA ENTRY"
 3815 PRINT "          ''''''''''''''''''''"
 3816 CLEAR 
 3820 PRINT AT 4,2;"PLEASE ENTER THE PRINCIPAL"
 3830 INPUT P
 3834 IF P<=0 THEN GOTO 3810
 3840 PRINT AT 6,11;"$";P
 3850 PRINT AT 9,2;"NOW ENTER THE NUMBER OF YEARS"
 3860 INPUT Y
 3864 IF Y<=0 OR Y>30 THEN GOTO 3810
 3870 PRINT AT 11,11;Y;" YEARS"
 3880 PRINT AT 14,2;"AND THE RATE IN DECIMAL FORM"
 3890 INPUT A
 3894 IF A<=0 OR A>1 THEN GOTO 3810
 3900 PRINT AT 16,11;A*100;" PERCENT"
 3910 PRINT AT 19,0;"  IF ALL DATA IS CORRECT PRESS     ENTER. OTHERWISE PRESS ANY         CHARACTER AND ENTER."
 3920 INPUT K$
 3930 IF K$<>"" THEN GOTO 3800
 3940 LET OP=P
 3950 CLS 
 4000 LET I=A/12
 4010 LET N=Y*12
 4015 IF Y=.5 THEN LET N=6
 4020 DIM T(N,3)
 4030 LET M=P*I/(1-((1+I)**(-N)))
 4040 LET M1=(INT (M*100+.5))/100
 4050 LET TPD=(INT (M*N*100+.5))/100
 4060 CLS 
 4064 PRINT "       BASIC RESULTS"
 4065 PRINT "       ''''''''''''''''''''''''''"
 4070 PRINT "$";P;" FOR ";Y;" YEARS AT ";A
 4080 PRINT "$";M1;" MONTHLY"
 4090 PRINT "$";TPD;" TOTAL"
 4100 LET S=0
 4110 LET ST=0
 4120 PRINT AT 11,4;"SELECT OPTION CODE"
 4130 PRINT AT 13,6;"CODE   DESCRIPTION"
 4140 PRINT AT 15,8;"1    NEW DATA"
 4150 PRINT AT 16,8;"2    CONTINUE"
 4155 PRINT AT 17,8;"3    END"
 4160 INPUT C1
 4164 LET C1=INT C1
 4165 IF C1<1 OR C1>3 THEN GOTO 4060
 4170 IF C1=1 THEN GOTO 3800
 4180 IF C1=3 THEN GOTO 4900
 4200 CLS 
 4205 PRINT "           DATE DATA"
 4206 PRINT "           ''''''''''''''''''"
 4210 PRINT AT 3,2;"PLEASE ENTER THE DATE OF THE    FIRST PAYMENT"
 4220 PRINT AT 8,2;"FIRST THE MONTH (2 DIGITS)"
 4230 INPUT FM
 4235 IF FM<=0 OR FM>12 THEN GOTO 4200
 4240 PRINT AT 12,2;"NOW THE YEAR (4 DIGITS)"
 4250 INPUT FY
 4255 IF FY<=0 THEN GOTO 4200
 4260 PRINT AT 18,4;"FIRST PAYMENT  ";FM;"/";FY
 4270 LET LM=FM-1
 4280 IF LM<>0 THEN GOTO 4300
 4290 LET LM=12
 4300 PAUSE 200
 4400 FAST 
 4410 FOR X=1 TO N
 4420 LET S=I*P
 4430 LET T(X,1)=S
 4440 LET ST=ST+S
 4450 LET T(X,2)=ST
 4460 LET P=P-M+S
 4470 LET T(X,3)=P
 4480 NEXT X
 4490 CLS 
 4500 SLOW 
 4600 PRINT "       BASIC RESULTS"
 4605 PRINT "       ''''''''''''''''''''''''''"
 4608 PRINT "$";OP;" FOR ";Y;" YEARS AT ";A
 4610 PRINT "$";M1;" MONTHLY"
 4620 PRINT "$";TPD;" TOTAL"
 4625 PRINT AT 8,7;"REPORT MENU"
 4626 PRINT AT 9,7;"''''''''''''''''''''''"
 4630 PRINT AT 10,4;"SELECT REPORT CODE:"
 4640 PRINT AT 12,4;"CODE  DESCRIPTION"
 4660 PRINT 
 4670 PRINT TAB 5;"1    SINGLE PAYMENT DATA"
 4680 PRINT TAB 5;"2    SINGLE YEAR DATA"
 4690 PRINT TAB 5;"3    PROFILE BY MONTH"
 4700 PRINT TAB 5;"4    PROFILE BY YEAR"
 4710 PRINT TAB 5;"5    INT/PRIN PLOT"
 4720 PRINT TAB 5;"6    NEW DATA"
 4730 PRINT TAB 5;"7    END"
 4735 SLOW 
 4740 INPUT C2
 4750 IF C2<1 OR C2>7 THEN GOTO 4840
 4760 IF C2=1 THEN GOSUB 100
 4770 IF C2=2 THEN GOSUB 500
 4780 IF C2=3 THEN GOSUB 1200
 4790 IF C2=4 THEN GOSUB 1600
 4800 IF C2=5 THEN GOSUB 2200
 4810 IF C2=6 THEN GOTO 3800
 4820 IF C2=7 THEN GOTO 4900
 4830 PAUSE 40000
 4835 FAST 
 4840 CLS 
 4850 GOTO 4600
 4900 CLEAR 
 4910 CLS 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top