This program implements a securities portfolio analysis and optimization tool based on the Capital Asset Pricing Model (CAPM), allowing users to enter beta values and non-market risk figures for up to 10 securities. The core algorithm iterates through critical lambda values to find the minimum non-market risk portfolio for a desired beta level, using the efficient frontier computation technique. A graphical scatter plot of the efficient frontier is generated using the pixel PLOT command, with axes labeled and scaled dynamically to fit the data range. The program uses two 300-element arrays (W and Z) to store computed beta and risk coordinates for plotting, with separate subroutines handling menu display, data entry, portfolio computation, and chart rendering.
Program Analysis
Program Structure
The program is organized as a menu-driven application with a master menu at line 110 dispatching to five functional areas via INKEY$ polling. The main sections are:
- Initialization and splash screens (lines 12–99, subroutines at 9160 and 9282)
- Master menu (lines 100–277)
- Beta plot / efficient frontier (lines 280–940, chart subroutines 3030–7050)
- Portfolio computation (lines 1050–1430)
- Data entry (lines 2440–2614)
- Help screen (lines 8005–8160)
- Shared math subroutines (lines 1460–1990, 8200–9150)
Data Structures
The program maintains parallel arrays for up to 10 securities: B(10) for beta values, R(10) for non-market risk, C(10) and D(10) for portfolio weight calculation intermediates, and S(10) as a binary in/out flag array for each security. Two large 300-element arrays, W(300) and Z(300), store the computed efficient frontier points (beta and risk coordinates), with I(300) and O(300) holding the normalized versions for plotting.
Portfolio Optimization Algorithm
The optimization follows a critical-line algorithm for mean-variance portfolio selection. The subroutine at line 1470 seeds the process by finding the security with the highest beta and making it the initial single-asset portfolio. The subroutine at 1610 finds the next critical lambda value (stored in L7) by scanning securities not yet in the active set, computing a threshold based on the ratio of the aggregate sum S4 to the beta difference from the current corner portfolio’s weighted beta S3. The subroutine at 1710 recomputes portfolio weights using:
F1 = L9 / (2 * R(I)^2)— the lambda-scaled contributionF2 = S4 / (2 * R(I)^2)— the normalization termX9 = F1 * (B(I) - S3) + F2— the weight for security I
The subroutine at 1890 computes the weighted sums S1–S4 used throughout, where S3 = S1/S2 acts as the current weighted-average beta and S4 = 1/S2 is its reciprocal variance.
Efficient Frontier Plotting
The plot section (lines 280–940 and 8200–8390) accumulates frontier points in W and Z, then at line 8200 normalizes them via subroutine 9000 into I and O arrays. Axes are drawn by iterating PLOT commands (lines 3040–3090) and labeled with PRINT AT. The scale factors SX and SY at lines 8310–8320 map the data range onto a 51×33 pixel display area offset from the axis origin at pixel (12, 10). Tick marks on the Y-axis use the block graphic character ▝ (\ ') for a clean visual indicator.
Menu Input Handling
The master menu uses a three-phase INKEY$ pattern: line 222 busy-waits until any key is pressed, lines 230–262 test for valid digits 1–5 and branch accordingly, and lines 263–277 handle invalid input by displaying the erroneous key and prompting to continue. This means the INKEY$ at line 264 (assigning to A$) may capture a different key than the one that triggered the fall-through, since the key may have been released — a minor timing artifact common in polling-based input loops.
Data Entry Logic
Data entry (lines 2440–2614) enforces a 10-security limit via M=10. A local counter L4 is incremented each entry; when L4=4, a special branch at line 2603 re-checks for a 0,0 terminator and jumps to the menu on valid data at line 2606 instead of looping. This appears intended to force a screen clear every 4 entries to avoid scrolling off the screen, though the CLS at line 2520 only fires at the start of the entry block, not mid-loop — the logic at lines 2587–2606 is somewhat convoluted and the L4 reset is missing, so L4 never resets to 0 during a data entry session.
Interpolation Between Corner Portfolios
When a specific beta target V7 is requested, subroutine 1990 interpolates linearly between the previous corner portfolio beta V6 and the current B9, computing blending coefficients R1 and R2. The final security weights are then X9 = R1*D(I) + R2*C(I), a convex combination of the two adjacent corner portfolios’ weight vectors.
Notable Techniques and Anomalies
- The sentinel values
1E38and4E-39are used as practical infinity and near-zero initializers for min/max scans throughout, a common idiom given the floating-point range available. - The
**operator (lines 1330, 1340, 1800, 1810, 1920) is used for exponentiation alongside the more common^— both are accepted. - The comment at line 885 —
REM LET KK=KK+1— is commented out, with the actual increment moved to line 910, making the frontier point only stored when it falls within the plotted axis range. Points outside the range are computed but discarded. - Line 6151 contains the no-op
IF Y0=0 THEN LET Y0=0, which has no effect. - Arrays
I(300)andO(300)shadow the loop variableIused elsewhere; while legal in this BASIC dialect, this can cause confusion when reading the code. - The
SLOWandFASTcommands are used strategically:FASTis engaged before computationally intensive plotting and optimization loops, andSLOWis restored before interactive prompts. - Lines 9400–9410 provide a
SAVEfollowed byRUN, implementing a self-restarting save routine at the end of the program listing.
Content
Source Code
12 DIM W(300)
14 DIM Z(300)
20 LET M=10
22 REM
24 GOSUB 9160
26 GOSUB 9282
45 DIM B(10)
50 DIM C(10)
55 DIM D(10)
60 DIM R(10)
61 DIM I(300)
62 DIM O(300)
65 DIM S(10)
70 REM S(10),N,P1,P2,P3 = INTEGER
71 LET K=0
72 LET N=0
73 LET KK=1
88 LET H1=.05
90 REM INITIALIZING
93 FOR E=1 TO 10
94 LET B(E)=0
95 LET C(E)=0
96 LET D(E)=0
97 LET R(E)=0
98 LET S(E)=0
99 NEXT E
100 PRINT
104 REM
105 REM PRINT MASTER MENUE
106 SLOW
110 CLS
115 PRINT "SECURITIES PORTFOLIO ANALYSIS AND DETERMINATION"
120 PRINT
125 PRINT
130 PRINT " SELECTION OPTION"
135 PRINT " ================"
140 PRINT
150 PRINT " 1==ENTER DATA"
160 PRINT " 2==PLOT BETA"
170 PRINT " 3==COMPUTE PORTFOLIO"
180 PRINT " 4==HELP"
185 PRINT " 5==END OF PROGRAM"
190 PRINT
195 PRINT
199 PRINT " ENTER SELECTION CODE"
200 PRINT " --------------------"
222 IF INKEY$="" THEN GOTO 222
230 IF INKEY$="1" THEN GOTO 2440
240 IF INKEY$="2" THEN GOTO 280
250 IF INKEY$="3" THEN GOTO 1060
260 IF INKEY$="4" THEN GOTO 8005
262 IF INKEY$="5" THEN GOTO 3000
263 PRINT
264 LET A$=INKEY$
270 PRINT "SELECTION CODE MUST NOT BE ";A$
271 PRINT " ="
272 PRINT
273 PRINT
274 PRINT "(PRESS KEY C TO CONTINUE)"
275 IF INKEY$="" THEN GOTO 275
277 GOTO 110
280 REM FIND LOW AND HIGH X AND Y
281 CLS
282 IF N=0 THEN GOTO 7500
290 LET X0=1E38
292 LET Y0=1E38
294 LET X8=4E-39
296 LET Y8=4E-39
310 LET I3=0
320 FOR I=1 TO N
330 IF X0>B(I) THEN LET X0=B(I)
340 IF Y0>R(I) THEN LET Y0=R(I)
350 IF X8<B(I) THEN LET X8=B(I)
360 IF Y8<R(I) THEN LET Y8=R(I)
370 NEXT I
380 LET X8=INT (X8*4+.5)/4
390 LET Y8=INT (Y8*4+.5)/4
400 LET X0=INT (X0*4)/4
405 IF Y0<.5 THEN GOTO 413
410 LET Y0=INT (Y0*4+.00001)/4-.25
411 GOTO 415
413 LET Y0=0
415 FAST
710 REM PRINT CHART
720 GOSUB 1470
730 GOSUB 1890
740 GOSUB 1610
750 IF L7<=-1E38 THEN GOTO 940
760 LET S(I9)=1-S(I9)
770 LET L9=L7
780 GOSUB 1710
790 IF V6>=H2 AND B9<=H2 THEN GOTO 810
800 GOTO 730
810 LET V7=H2
820 GOSUB 1990
830 LET B3=0
832 LET R3=0
840 FOR I=1 TO N
850 LET X9=R1*D(I)+R2*C(I)
860 LET B3=B3+X9*B(I)
870 LET R3=R3+X9*X9*R(I)*R(I)
880 NEXT I
882 LET W(KK)=B3
884 LET Z(KK)=SQR (R3)
885 REM LET KK=KK+1
890 IF B3<X0 OR B3>X8 THEN GOTO 920
900 IF SQR (R3)<Y0 OR SQR (R3)>Y8 THEN GOTO 920
910 LET KK=KK+1
920 LET H2=H2-H1
930 GOTO 790
940 GOTO 8200
1050 REM COMPUTE PORFOLIO
1060 PRINT
1062 IF N=0 THEN GOTO 7500
1065 REM ENTER LEVEL OF BETA
1070 LET I3=0
1080 PRINT "DESIRED LEVEL OF BETA ?"
1090 INPUT V7
1091 PRINT V7
1092 CLS
1093 FAST
1095 PRINT "DESIRED LEVEL OF BETA = ";V7
1096 PRINT
1100 GOSUB 1470
1110 GOSUB 1890
1120 GOSUB 1610
1130 IF L7>-1E37 THEN GOTO 1170
1140 LET R1=1
1150 LET R2=0
1160 GOTO 1240
1170 REM VARIABLE IS I9,LAMDA IS L7
1180 LET S(I9)=1-S(I9)
1190 LET L9=L7
1200 GOSUB 1710
1210 IF B9>=V7 THEN GOTO 1110
1220 REM PRINT PORTFOLIO
1230 GOSUB 1990
1240 LET B3=0
1245 LET R3=0
1260 PRINT "MINIMUM NON MARKET RISK"
1270 PRINT " PORTFOLIO"
1280 PRINT "SECURITY PERCENT"
1290 PRINT "-------- -------"
1300 FOR I=1 TO N
1310 LET X9=R1*D(I)+R2*C(I)
1320 LET B3=B3+X9*B(I)
1330 LET R3=R3+X9**2*R(I)**2
1340 IF X9<.00001 THEN GOTO 1370
1350 PRINT " ";I;" ";INT (100*X9*100)/100
1370 NEXT I
1380 PRINT
1390 PRINT "BETA= ";B3
1410 PRINT "RELATIVE NON-MARKET RISK = ";INT (SQR (R3)*100)/100
1412 PRINT
1414 PRINT
1416 SLOW
1420 PRINT "(PRESS KEY C TO CONTINUE)"
1425 IF INKEY$="" THEN GOTO 1425
1430 GOTO 110
1460 REM FIND FIRST PORTFOLIO
1470 LET B9=1E-39
1480 FOR I=1 TO N
1490 IF B(I)<=B9 THEN GOTO 1520
1500 LET B9=B(I)
1510 LET I9=I
1520 NEXT I
1530 FOR I=1 TO N
1540 LET S(I)=0
1545 LET D(I)=0
1550 NEXT I
1560 LET S(I9)=1
1565 LET D(I9)=1
1570 LET L9=1E38
1575 LET V6=B(I9)
1580 LET H2=1+H1*INT ((V6-1)/H1)
1590 RETURN
1600 REM FIND NEXT CRITICAL VALUE OF LAMDA
1610 LET L7=-1E38
1620 LET I8=I9
1630 FOR I=1 TO N
1640 IF I=I8 OR B(I)=S3 THEN GOTO 1680
1650 LET L8=-(S4/(B(I)-S3))
1660 IF L8>=L9 OR L8<L7 THEN GOTO 1680
1670 LET L7=L8
1675 LET I9=I
1680 NEXT I
1690 RETURN
1700 REM COMPUTE PORTFOLIO
1710 LET I3=I3+1
1720 FOR I=1 TO N
1730 LET C(I)=D(I)
1740 NEXT I
1750 LET V6=B9
1760 LET B9=0
1765 LET R9=0
1770 FOR I=1 TO N
1780 LET D(I)=0
1790 IF S(I)=0 THEN GOTO 1860
1800 LET F1=L9/(2*R(I)**2)
1810 LET F2=S4/(2*R(I)**2)
1820 LET X9=F1*(B(I)-S3)+F2
1830 LET B9=B9+X9*B(I)
1840 LET R9=R9+X9*X9*R(I)*R(I)
1850 LET D(I)=X9
1860 NEXT I
1870 RETURN
1880 REM FORM SUMS
1890 LET S1=0
1892 LET S2=0
1894 LET S3=0
1896 LET S4=0
1900 FOR I=1 TO N
1910 IF S(I)=0 THEN GOTO 1950
1920 LET R9=2*R(I)**2
1930 LET S1=S1+B(I)/R9
1940 LET S2=S2+1/R9
1950 NEXT I
1960 LET S3=S1/S2
1970 LET S4=1/S2
1980 RETURN
1990 LET R1=1
1992 LET R2=0
2000 IF B9=V6 THEN GOTO 2030
2010 LET R1=(V7-V6)/(B9-V6)
2020 LET R2=(B9-V7)/(B9-V6)
2030 RETURN
2251 PRINT
2440 REM DATA ENTRY
2444 REM
2490 IF N<M THEN GOTO 2520
2495 CLS
2497 PRINT
2498 PRINT
2499 PRINT
2500 PRINT AT 7,0;" *** DATA ARRAY IS FULL ***"
2501 PRINT
2502 PRINT " TO ENTER A NEW SET OF DATA "
2503 PRINT " YOU MUST EXIT AND THEN RUN"
2504 PRINT " THE PROGRAM AGAIN ."
2505 PRINT
2506 PRINT
2507 PRINT
2514 PRINT "( PRESS KEY C TO CONTINUE )"
2516 IF INKEY$="" THEN GOTO 2516
2518 GOTO 110
2520 CLS
2522 LET L4=0
2530 PRINT "FOR EACH SECURITY, ENTER A BETA"
2540 PRINT "VALUE AND THE SECURITY"
2550 PRINT "RELATIVE NON-MARKET RISK"
2551 PRINT
2552 PRINT "- ENTER 0,0 TO END DATA ENTRY -"
2555 REM CHECK FOR END OF DATA
2560 IF N>=M THEN GOTO 2495
2565 PRINT
2570 PRINT " ";N+1;" - BETA AND RISK ?"
2580 INPUT B(N+1)
2582 PRINT " BETA = ";B(N+1)
2584 INPUT R(N+1)
2586 PRINT " RISK = ";R(N+1)
2587 LET L4=L4+1
2588 IF L4=4 THEN GOTO 2603
2590 IF B(N+1)<>0 AND R(N+1)<>0 THEN GOTO 2612
2592 LET L=0
2600 CLS
2602 GOTO 110
2603 IF B(N+1)=0 OR R(N+1)=0 THEN GOTO 110
2604 LET N=N+1
2606 GOTO 2520
2612 LET N=N+1
2614 GOTO 2560
3000 CLS
3010 PRINT AT 11,2;"**** END OF PROGRAM ****"
3020 STOP
3030 REM DRAW X-AXIS
3032 CLS
3040 FOR I=12 TO 63
3050 PLOT I,10
3060 NEXT I
3061 REM LABEL X-AXIS
3062 PRINT AT 19,15;"BETA"
3065 REM DRAW Y-AXIS
3070 FOR I=10 TO 43
3080 PLOT 12,I
3090 NEXT I
4040 REM LABEL Y-AXIS
4042 PRINT AT 8,0;"R"
4043 PRINT AT 9,0;"I"
4044 PRINT AT 10,0;"S"
4045 PRINT AT 11,0;"K"
6140 REM
6150 LET L=16
6151 IF Y0=0 THEN LET Y0=0
6153 PRINT AT L,1;Y0
6155 LET VY=(Y9-Y1)/4
6157 LET V=VY
6160 FOR I=1 TO 4
6165 LET L=L-4
6175 LET V=(VY*I)+Y1
6177 IF I=4 THEN GOTO 6200
6180 PRINT AT L,1;INT (V*100)/100
6190 PRINT AT L,5;" '"
6200 NEXT I
6990 REM
7000 LET C=6
7002 LET VX=(X10-X1)/5
7003 PRINT AT 18,C;X1
7004 LET V=VX
7005 FOR I=1 TO 5
7010 LET C=C+5
7015 LET V=(VX*I)+X1
7017 IF I=5 THEN GOTO 7040
7020 PRINT AT 18,C;INT (V*100)/100;AT 17,C;" '"
7040 NEXT I
7050 RETURN
7500 REM N0 DATA
7505 CLS
7510 REM CONTROL GOES BACK TO MASTER MENUE
7515 PRINT
7520 PRINT AT 10,6;"*** NO DATA ***"
7521 PRINT
7522 PRINT " YOU MUST ENTER DATA FIRST"
7530 PRINT
7532 PRINT
7535 PRINT "( PRESS KEY C TO CONTINUE )"
7536 IF INKEY$="" THEN GOTO 7536
7540 GOTO 110
8000 STOP
8005 CLS
8010 PRINT " HELP"
8020 PRINT " ===="
8030 PRINT
8040 PRINT "BETA = MARKET SENSITIVITY"
8050 PRINT "RISK = RISK FOR SECURITY"
8060 PRINT
8070 PRINT
8080 PRINT "TO ENTER A NEW SET OF DATA YOU MUST EXIT AND THEN RUN THE "
8082 PRINT "PROGRAM AGAIN ."
8085 PRINT
8090 PRINT "TO ADD DATA TO YOUR LIST YOU MUST SELECT CODE (1) IN THE MENU"
8100 PRINT
8102 PRINT
8104 PRINT
8110 PRINT "( PRESS KEY C TO CONTINUE )"
8150 IF INKEY$="" THEN GOTO 8150
8160 GOTO 110
8200 REM FIND HIGH,LOW OF W,Z
8210 REM X1=LOW,X10=HIGH
8220 REM Y1=LOW,Y9=HIGH
8230 LET X1=1E38
8234 LET Y1=1E38
8236 LET X10=4E-39
8240 LET Y9=4E-39
8250 FOR I=1 TO KK-1
8260 IF X1>W(I) THEN LET X1=W(I)
8270 IF Y1>Z(I) THEN LET Y1=Z(I)
8280 IF X10<W(I) THEN LET X10=W(I)
8290 IF Y9<Z(I) THEN LET Y9=Z(I)
8300 NEXT I
8302 GOSUB 3030
8305 GOSUB 9000
8310 LET SX=51/(X11)
8320 LET SY=33/(Y11)
8330 FOR I=1 TO KK-1
8340 PLOT INT (SX*I(I)+.5)+12,INT (SY*O(I)+.5)+10
8350 NEXT I
8355 SLOW
8360 PRINT AT 21,7;"(PRESS KEY C TO CONTINUE)"
8370 IF INKEY$="" THEN GOTO 8370
8390 GOTO 110
9000 REM SUBROUTINE
9005 FOR I=1 TO KK-1
9010 LET I(I)=W(I)-X1
9020 LET O(I)=Z(I)-Y1
9030 NEXT I
9040 REM FIND HIGH OF I,O
9050 LET X2=1E38
9060 LET Y2=1E38
9070 LET X11=4E-39
9080 LET Y11=4E-39
9090 FOR I=1 TO KK-1
9100 IF X2>I(I) THEN LET X2=I(I)
9110 IF Y2>O(I) THEN LET Y2=O(I)
9120 IF X11<I(I) THEN LET X11=I(I)
9130 IF Y11<O(I) THEN LET Y11=O(I)
9140 NEXT I
9150 RETURN
9160 REM SUBROUTINES
9170 CLS
9180 PRINT AT 7,12;"AMERICAN"
9190 FOR I=23 TO 40
9200 PLOT I,27
9210 NEXT I
9220 PRINT AT 10,7;"MICRO PRODUCTS, INC."
9230 FOR I=13 TO 53
9240 PLOT I,21
9250 NEXT I
9260 PRINT AT 16,9;"RICHARDSON, TEXAS"
9270 FOR I=1 TO 100
9272 NEXT I
9280 RETURN
9282 CLS
9290 PRINT AT 7,2;"SECURITIES PORTFOLIO ANALYSIS";AT 8,2;"-----------------------------"
9302 PRINT AT 9,8;"AND DETERMINATION";AT 10,8;"-----------------"
9304 PRINT AT 17,8;"COPYRIGHT, 1982"
9306 PRINT AT 19,8;"ALL RIGHT RESERVED"
9308 FOR I=1 TO 100
9309 NEXT I
9310 RETURN
9400 SAVE "SM%2"
9410 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

