Portfolio Analysis

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

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:

  1. Initialization and splash screens (lines 12–99, subroutines at 9160 and 9282)
  2. Master menu (lines 100–277)
  3. Beta plot / efficient frontier (lines 280–940, chart subroutines 3030–7050)
  4. Portfolio computation (lines 1050–1430)
  5. Data entry (lines 2440–2614)
  6. Help screen (lines 8005–8160)
  7. 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 contribution
  • F2 = S4 / (2 * R(I)^2) — the normalization term
  • X9 = F1 * (B(I) - S3) + F2 — the weight for security I

The subroutine at 1890 computes the weighted sums S1S4 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 1E38 and 4E-39 are 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) and O(300) shadow the loop variable I used elsewhere; while legal in this BASIC dialect, this can cause confusion when reading the code.
  • The SLOW and FAST commands are used strategically: FAST is engaged before computationally intensive plotting and optimization loops, and SLOW is restored before interactive prompts.
  • Lines 9400–9410 provide a SAVE followed by RUN, implementing a self-restarting save routine at the end of the program listing.

Content

Appears On

Related Products

Program performs minimum risk and market sensitivity calculations for a portfolio composed from a set of stocks. A portfolio is...

Related Articles

Related Content

Image Gallery

Portfolio Analysis

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.

People

No people associated with this content.

Scroll to Top