Stock Plot

Products: Stock Plot
Developer(s): Kendric Smith
Date: 1983
Type: Program
Platform(s): TS 1000
Tags: Stocks

Stock Plot is a portfolio management and charting program that tracks up to 19 stocks, storing 26 weeks of price and volume data along with purchase price, number of shares, yearly high/low, and P/E ratio for each entry. The main menu offers eight functions: initial data entry, adding a stock in alphabetical order, correcting or deleting entries, updating current prices and volumes, plotting all or one stock graphically, listing statistics, and saving data. The plotting routine (lines 5000–5920) renders a price chart using CHR$ 128 (a block graphic) and detects cell content via PEEK of the display file address registers at 16398–16399 to overlay volume markers without overwriting price points. Statistics screens calculate portfolio cost, current value, profit/loss, and percent gain using VAL to convert string-stored numeric fields. Memory remaining can be checked via a PEEK-based calculation at line 9999.


Program Analysis

Program Structure

The program is organized around a numbered-menu dispatch system. The main menu at lines 10–90 reads a choice Q and jumps to Q*1000, routing options 1–8 to line blocks at 1000, 2000, 3000, 4000, 5000, 6000, 7000, and 8000 respectively. Each major functional block is largely self-contained, with shared subroutines in the 9000s range.

Line RangeFunction
10–90Main menu and dispatch
1000–1460Enter all stocks (initial data entry)
2000–2115Add a stock in alphabetical order (insert with shift)
3000–3030Correct or delete a stock
4000–4155Enter current prices and volumes (weekly roll)
5000–5920Plot all stocks graphically
6000–6205Plot one stock (by symbol lookup)
7000–7290List current statistics (two tables)
8000Save data
9000–9865Shared subroutines: error/correction menus, field re-entry, delete
9990–9999SAVE routine and memory check

Data Storage

All data for up to 19 stocks is held in parallel arrays. String arrays store fixed-width fields; numeric arrays hold the 26-week time series.

  • A$(19,5) — stock symbol (up to 5 characters)
  • B$(19,4) — purchase price as a string (up to 4 characters)
  • C$(19,5) — yearly high/low as a string (e.g., “50/30”)
  • D$(19,2) — P/E ratio as a string (up to 2 characters)
  • F$(19,4) — number of shares as a string
  • A(19,26) — 26-week price history
  • B(19,26) — 26-week volume history
  • D — current count of entered stocks

Numeric fields like purchase price, shares, and P/E are stored as strings and retrieved with VAL when arithmetic is needed. This avoids a separate numeric variable for each field but requires careful string-width discipline.

Weekly Data Roll

Option 4 (lines 4000–4155) implements a sliding window update. Before prompting for new data, it shifts all 26 weeks of prices and volumes one position earlier (A(I,N)=A(I,N+1) for N=1 to 25), then writes the new price and volume into position 26. This maintains a rolling 26-week history automatically.

Charting Routine

The price plot (lines 5100–5320) calculates the range around the purchase price L, determines the maximum excursion F (either upward O or downward M, whichever is greater), and derives a vertical scaling factor H=10/F. Prices are plotted using CHR$ 128 (the block graphic ▝) via PRINT AT. Horizontal axis labels show percentage values relative to purchase price at lines 0, 5, 10, 15, and 20.

The volume plot (lines 5400–5455) scales volumes against the maximum volume K across all 26 weeks. It uses a direct PEEK of the display file pointer registers at addresses 16398 and 16399 to read the character currently at the target screen position. If the cell already contains CHR$ 128 (a price point), it prints CHR$ 187 instead of “V”, allowing both price and volume to be visible at the same location.

Statistics Tables

Option 7 generates two sequential screens. The first (lines 7000–7095) lists each stock’s symbol, high/low, P/E, buy price, current price, and current/buy ratio. It also computes averages of buy price and current price across stocks, excluding index 1 (the loop starts at I=2), suggesting position 1 may be reserved for a benchmark or is intentionally skipped. The second table (lines 7200–7290) shows shares, cost basis, current value, profit/loss, and overall percentage gain for the portfolio.

Insert and Delete Operations

Adding a stock (option 2, lines 2000–2115) asks for the target index I, then shifts all arrays from D+1 down to I+1 one position upward using a FOR R=D+1 TO I+1 STEP -1 loop, making room for the new entry. Deletion (subroutine at line 9800) performs the reverse: it shifts entries from position I upward, overwriting the deleted entry, and decrements D.

Correction Subroutine

The correction menu at line 9300 presents nine options for re-entering individual fields. Input validation at line 9410 explicitly checks that Q$ is one of the digits “1”–”9″ before proceeding, looping back to INKEY$ at 9400 if not. Each field has its own re-entry subroutine in the 9500–9775 range.

Screen vs. Printer Output

The plot routines support both screen and printer output. At line 5000–5004, the user selects “S” or “P”, setting variable Z to either 6100 (screen pause) or 6200 (COPY to printer). The appropriate subroutine is then called via GOSUB Z after each chart is drawn — a clean use of a variable as a subroutine address.

Notable Bugs and Anomalies

  • Lines 4110 and 4112 both read FOR I=1 TO D; line 4110 is immediately superseded by line 4112, making the outer loop at 4110 redundant and effectively a no-op.
  • In the plotting loops at lines 5300–5325 and 5430–5455, the outer FOR P=4 TO 4 executes exactly once. This appears to be vestigial scaffolding from a design that intended multiple plot columns; as written, P is always 4 and X=0+P is always 4, so X serves no meaningful purpose.
  • Line 5300 uses FOR P=4 TO 4 but line 5320 increments NEXT P (after NEXT N at 5320, NEXT P is at 5325) — the loop body is the inner N loop, so the structure is inverted from what the indentation implies.
  • Line 1425 calls GOSUB 1250 but line 1250 begins with LET D=D+1; using it as a subroutine entry point during the correction loop (option 1’s verify step) increments D spuriously each time a correction is made.
  • Line 9999 provides a memory check display but is only reachable by manually entering it as a GO TO at runtime; it is not connected to any menu option.
  • The averages in the statistics table (lines 7041–7054 and 7231–7254) divide by D-1, explicitly excluding the first stock entry. If only one stock is entered (D=1), this causes a division-by-zero error.

Memory Check Utility

Line 9999 computes free memory using 16384-(PEEK 16404+256*PEEK 16405-16283), reading the system variable that tracks the top of BASIC program space. This is a standard technique for reporting available RAM without calling FREE.

Content

Appears On

Related Products

Plots prices and volumes for the prior 26 weeks. The 1000 version holds 19 stocks and the 2068 version holds...

Related Articles

Related Content

Image Gallery

Source Code

  10 PRINT AT 1,7;"STOCK PLOT: ""SP"""
  15 PRINT AT 2,14;"BY"
  20 PRINT AT 3,7;"KENDRIC C. SMITH"
  25 PRINT AT 5,9;"%E%N%T%E%R% %N%U%M%B%E%R"
  30 PRINT AT 7,1;"1  ENTER ALL STOCKS 1ST TIME IN      ALPHABETICAL ORDER"
  35 PRINT AT 9,1;"2  ADD A STOCK IN ALPHABETICAL       ORDER"
  40 PRINT AT 11,1;"3  CORRECT OR DELETE A STOCK"
  45 PRINT AT 13,1;"4  ENTER CURRENT PRICES AND          VOLUMES"
  50 PRINT AT 15,1;"5  PLOT ALL STOCKS"
  55 PRINT AT 17,1;"6  PLOT ONE STOCK"
  60 PRINT AT 19,1;"7  LIST CURRENT STATISTICS"
  65 PRINT AT 21,1;"8  SAVE STOCK DATA"
  70 INPUT Q
  75 CLS 
  80 IF Q<=8 THEN GOTO Q*1000
  85 CLS 
  90 GOTO 10
 1001 DIM A$(19,5)
 1005 DIM B$(19,4)
 1010 DIM C$(19,5)
 1015 DIM D$(19,2)
 1016 DIM F$(19,4)
 1020 DIM A(19,26)
 1025 DIM B(19,26)
 1027 GOSUB 4145
 1030 LET D=0
 1035 FOR I=D+1 TO 19
 1045 GOSUB 1100
 1050 GOTO 1400
 1100 PRINT AT 11,0;"ENTER STOCK SYMBOL: <= 5 LETTERS"
 1105 INPUT A$(I)
 1110 CLS 
 1111 PRINT AT 11,0;"ENTER NUMBER OF SHARES"
 1112 INPUT F$(I)
 1113 CLS 
 1115 PRINT AT 11,0;"ENTER PURCHASE PRICE:<= 4 SPACES"
 1120 INPUT B$(I)
 1125 CLS 
 1130 PRINT AT 11,0;"ENTER YEARLY HIGH AND LOW AS      ""50/30"""
 1135 INPUT C$(I)
 1140 CLS 
 1145 PRINT AT 11,0;"ENTER %P%E RATIO (MAX 2 SPACES)"
 1150 INPUT D$(I)
 1155 CLS 
 1160 PRINT AT 11,0;"ENTER PRICES LAST 26 WEEKS"
 1165 FOR N=1 TO 26
 1170 INPUT A(I,N)
 1175 NEXT N
 1180 CLS 
 1185 PRINT AT 11,0;"ENTER VOLUMES?  (Y/N)"
 1190 INPUT Q$
 1192 CLS 
 1195 IF Q$="N" THEN GOSUB 9100
 1200 IF Q$="N" THEN GOTO 1245
 1205 PRINT AT 11,0;"ENTER VOLUMES LAST 26 WEEKS"
 1210 FOR N=1 TO 26
 1215 INPUT B(I,N)
 1220 NEXT N
 1245 LET D=D+1
 1250 CLS 
 1255 PRINT I;" ";A$(I);" ";F$(I);" ";B$(I);" ";C$(I);" ";D$(I)
 1260 FOR N=1 TO 26
 1265 PRINT A(I,N);" ";
 1270 NEXT N
 1272 PRINT 
 1275 FOR N=1 TO 26
 1280 PRINT B(I,N);" ";
 1285 NEXT N
 1290 RETURN 
 1400 PRINT 
 1405 PRINT AT 10,0;"%A%L%L% %C%O%R%R%E%C%T%?% % %(%Y%/%N%)"
 1410 INPUT Q$
 1415 IF Q$="Y" THEN GOTO 1435
 1417 PRINT AT 10,0;"                    "
 1420 GOSUB 9300
 1425 GOSUB 1250
 1430 GOTO 1405
 1435 CLS 
 1440 PRINT AT 6,0;"%A%N%Y% %M%O%R%E% %E%N%T%R%I%E%S%?% % %(%Y%/%N%)"
 1445 INPUT Q$
 1450 CLS 
 1455 IF Q$="Y" THEN NEXT I
 1457 IF D+1=20 THEN GOTO 9000
 1460 GOTO 85
 2000 IF D+1=20 THEN GOTO 9000
 2002 PRINT AT 11,0;"ENTER VALUE OF ""I"" WHERE NEW      STOCK IS TO BE ENTERED"
 2005 INPUT I
 2010 CLS 
 2015 FOR R=D+1 TO I+1 STEP -1
 2020 LET A$(R)=A$(R-1)
 2025 LET B$(R)=B$(R-1)
 2030 LET C$(R)=C$(R-1)
 2035 LET D$(R)=D$(R-1)
 2037 LET F$(R)=F$(R-1)
 2040 FOR N=1 TO 26
 2045 LET A(R,N)=A(R-1,N)
 2065 LET B(R,N)=B(R-1,N)
 2070 NEXT N
 2075 NEXT R
 2080 GOSUB 1100
 2085 PRINT 
 2090 PRINT AT 10,0;"%A%L%L% %C%O%R%R%E%C%T%?% % %(%Y%/%N%)"
 2095 INPUT Q$
 2097 PRINT AT 10,0;"                    "
 2100 IF Q$="Y" THEN GOTO 85
 2105 GOSUB 9300
 2110 GOSUB 1250
 2115 GOTO 2085
 3000 PRINT AT 11,0;"ENTER VALUE OF ""I"" OF LISTING TO  BE CHANGED"
 3005 INPUT I
 3010 CLS 
 3015 GOSUB 1250
 3020 GOSUB 9300
 3025 GOSUB 1250
 3030 GOTO 2085
 4000 FOR I=1 TO D
 4005 FOR N=1 TO 25
 4010 LET A(I,N)=A(I,N+1)
 4015 NEXT N
 4020 NEXT I
 4035 FOR I=1 TO D
 4040 FOR N=1 TO 25
 4045 LET B(I,N)=B(I,N+1)
 4050 NEXT N
 4055 NEXT I
 4060 FOR I=1 TO D
 4065 PRINT AT 11,0;"ENTER CURRENT PRICE OF: ";A$(I)
 4070 INPUT A(I,26)
 4075 CLS 
 4080 NEXT I
 4085 CLS 
 4110 FOR I=1 TO D
 4112 FOR I=1 TO D
 4115 PRINT AT 11,0;"ENTER CURRENT VOLUME OF: ";A$(I)
 4120 INPUT B(I,26)
 4125 CLS 
 4130 NEXT I
 4140 CLS 
 4142 GOSUB 4145
 4143 GOTO 85
 4145 PRINT AT 11,0;"ENTER THE DATE AS ""08/09/83"""
 4150 INPUT E$
 4155 RETURN 
 5000 PRINT AT 11,0;"PRINT TO SCREEN OR PRINTER?(S/P)"
 5001 INPUT Q$
 5002 CLS 
 5003 IF Q$="S" THEN LET Z=6100
 5004 IF Q$="P" THEN LET Z=6200
 5005 FOR I=1 TO D
 5006 LET L=VAL B$(I)
 5010 CLS 
 5100 LET J=5000
 5105 LET K=0
 5110 FOR N=1 TO 26
 5115 LET X=A(I,N)
 5120 IF X<=J THEN LET J=X
 5125 IF X>=K THEN LET K=X
 5130 NEXT N
 5135 LET M=L-J
 5140 LET O=K-L
 5145 IF O>M THEN LET F=O
 5150 IF M>O THEN LET F=M
 5155 LET H=10/F
 5160 PRINT AT 0,0;L+F;AT 5,0;L+(F/2);AT 10,0;L;AT 15,0;L-(F/2);AT 20,0;L-F
 5165 LET W=10
 5170 GOSUB 5900
 5175 PRINT " ";"BUY"
 5180 LET W=0
 5185 GOSUB 5900
 5190 PRINT " ";INT (((L+F)/L*100)+.5)
 5195 LET W=5
 5200 GOSUB 5900
 5205 PRINT " ";INT (((L+(F/2))/L*100)+.5)
 5210 LET W=15
 5215 GOSUB 5900
 5220 PRINT " ";INT (((L-(F/2))/L*100)+.5)
 5225 LET W=20
 5230 GOSUB 5900
 5235 PRINT " ";INT (((L-F)/L*100)+.5)
 5300 FOR P=4 TO 4
 5305 FOR N=1 TO 26
 5310 LET X=0+P
 5315 PRINT AT ((A(I,N)-(L+F))*(-H)),X;CHR$ 128
 5320 NEXT P
 5325 NEXT N
 5400 LET K=0
 5405 FOR N=1 TO 26
 5410 LET X=B(I,N)
 5415 IF X>=K THEN LET K=X
 5420 NEXT N
 5425 LET H=K/20
 5430 FOR P=4 TO 4
 5435 FOR N=1 TO 26
 5440 LET X=0+P
 5442 IF B(I,N)=0 THEN GOTO 5800
 5445 PRINT AT (B(I,N)-K)/(-H),X;
 5446 IF PEEK (PEEK 16398+256*PEEK 16399)<>128 THEN PRINT "V"
 5447 IF PEEK (PEEK 16398+256*PEEK 16399)=128 THEN PRINT CHR$ 187
 5450 NEXT P
 5455 NEXT N
 5800 PRINT AT 0,13;A$(I)
 5805 PRINT AT 20,11;E$
 5810 IF Q$=A$(I) THEN GOTO 5825
 5815 GOSUB Z
 5820 NEXT I
 5825 PRINT AT 21,0;"ENTER ""%C%O%N%T"" TO REGAIN 1ST MENU"
 5830 STOP 
 5835 GOTO 85
 5900 FOR N=5 TO 26
 5905 LET X=0+N
 5910 PRINT AT W,X;"-";
 5915 NEXT N
 5920 RETURN 
 6000 PRINT AT 21,14;"%E%N%T%E%R% %S%T%O%C%K% %S%Y%M%B%O%L"
 6005 INPUT Q$
 6010 FOR I=1 TO D
 6015 IF Q$=A$(I) THEN GOTO 5006
 6020 NEXT I
 6025 GOTO 85
 6100 PAUSE 400
 6105 RETURN 
 6200 COPY 
 6205 RETURN 
 7000 CLS 
 7005 PRINT "%I% ";TAB 3;"%S%Y%M%B%L";" ";"%H%I%/%L%O";" ";"%P%E";" ";"%B%U%Y% ";" ";"% %C%P% ";" ";"%C%P%/%B"
 7009 DIM C(19)
 7010 FOR I=1 TO D
 7012 LET C(I)=INT (((A(I,26)/VAL B$(I))*100)+.5)/100
 7015 PRINT I;TAB 3;A$(I);TAB 9;C$(I);TAB 15;D$(I);TAB 18;VAL B$(I);TAB 23;A(I,26);TAB 28;C(I)
 7020 NEXT I
 7040 LET Z=0
 7041 FOR I=2 TO D
 7042 LET Z=Z+VAL B$(I)
 7043 NEXT I
 7044 LET G=INT ((Z/(D-1)*10)+.5)/10
 7050 LET Z=0
 7051 FOR I=2 TO D
 7052 LET Z=Z+A(I,26)
 7053 NEXT I
 7054 LET S=INT ((Z/(D-1)*10)+.5)/10
 7070 PRINT TAB 6;"AVERAGE:";TAB 18;G;TAB 23;S
 7080 PRINT TAB 6;"%U%P%D%A%T%E%D% %O%N ";E$
 7085 PRINT AT 1,18;"    ";AT 1,28;"    "
 7090 PRINT AT 21,0;"KEY ""%C%O%N%T% %E%N%T%E%R"" FOR NEXT TABLE"
 7095 STOP 
 7200 CLS 
 7201 DIM G(19)
 7202 DIM H(19)
 7203 DIM J(19)
 7209 PRINT "%S%Y%M%B%L";TAB 6;"%S%H%R%S";TAB 11;"%C%O%S%T% ";TAB 17;"%V%A%L%U%E";TAB 23;"%P%R%O%F%.";TAB 29;"%O%/%O"
 7210 FOR I=2 TO D
 7211 LET G(I)=INT ((VAL F$(I)*VAL B$(I))+.5)
 7212 LET H(I)=INT ((VAL F$(I)*A(I,26))+.5)
 7213 LET J(I)=H(I)-G(I)
 7215 PRINT A$(I);TAB 6;F$(I);TAB 11;G(I);TAB 17;H(I);TAB 23;J(I)
 7220 NEXT I
 7230 LET Z=0
 7231 FOR I=2 TO D
 7232 LET Z=Z+VAL F$(I)
 7233 NEXT I
 7234 LET E=Z
 7240 LET Z=0
 7241 FOR I=2 TO D
 7242 LET Z=Z+G(I)
 7243 NEXT I
 7244 LET F=Z
 7250 LET Z=0
 7251 FOR I=2 TO D
 7252 LET Z=Z+H(I)
 7253 NEXT I
 7254 LET S=Z
 7260 LET Z=0
 7261 FOR I=2 TO D
 7262 LET Z=Z+J(I)
 7263 NEXT I
 7264 LET U=Z
 7270 PRINT "TOTAL:";TAB 6;E;TAB 11;F;TAB 17;S;TAB 23;U;TAB 29;INT (((S/F)*100)+.5)
 7280 PRINT TAB 6;"%U%P%D%A%T%E%D% %O%N ";E$
 7290 GOTO 9005
 8000 GOTO 9990
 9000 PRINT AT 11,10;"%M%E%M%O%R%Y% %F%U%L%L"
 9005 PRINT AT 21,0;"ENTER ""%C%O%N%T"" TO REGAIN 1ST MENU"
 9010 STOP 
 9015 GOTO 85
 9100 FOR N=1 TO 26
 9105 LET B(I,N)=0
 9110 NEXT N
 9115 RETURN 
 9300 PRINT AT 11,6;"%W%H%A%T% %I%S% %I%N%C%O%R%R%E%C%T%?"
 9305 PRINT TAB 9;"%E%N%T%E%R% %N%U%M%B%E%R"
 9310 PRINT "1  STOCK SYMBOL"
 9315 PRINT "2  PURCHASE PRICE"
 9320 PRINT "3  YEARLY HI/LO"
 9325 PRINT "4  PRICES LAST 26 WEEKS"
 9330 PRINT "5  VOLUMES LAST 26 WEEKS"
 9335 PRINT "6  PE RATIO"
 9337 PRINT "7  NO. SHARES"
 9340 PRINT "8  EVERYTHING, DELETE STOCK"
 9345 PRINT "9  NOTHING, RETURN TO 1ST MENU"
 9400 LET Q$=INKEY$
 9405 INPUT Q$
 9410 IF Q$<>"1" AND Q$<>"2" AND Q$<>"3" AND Q$<>"4" AND Q$<>"5" AND Q$<>"6" AND Q$<>"7" AND Q$<>"8" AND Q$<>"9" THEN GOTO 9400
 9415 IF Q$="1" OR Q$="2" OR Q$="3" OR Q$="4" OR Q$="5" OR Q$="6" OR Q$="7" OR Q$="8" OR Q$="9" THEN CLS 
 9420 IF Q$="1" THEN GOSUB 9500
 9425 IF Q$="2" THEN GOSUB 9550
 9430 IF Q$="3" THEN GOSUB 9600
 9435 IF Q$="4" THEN GOSUB 9650
 9440 IF Q$="5" THEN GOSUB 9700
 9445 IF Q$="6" THEN GOSUB 9750
 9447 IF Q$="7" THEN GOSUB 9765
 9450 IF Q$="8" THEN GOTO 9800
 9455 IF Q$="9" THEN GOTO 85
 9460 CLS 
 9465 RETURN 
 9500 PRINT AT 11,0;"ENTER CORRECT SYMBOL"
 9505 INPUT A$(I)
 9510 RETURN 
 9550 PRINT AT 11,0;"ENTER PURCHASE PRICE"
 9555 INPUT B$(I)
 9560 RETURN 
 9600 PRINT AT 11,0;"ENTER YEARLY HI/LO"
 9605 INPUT C$(I)
 9610 RETURN 
 9650 PRINT AT 11,0;"ENTER PRICES LAST 26 WEEKS"
 9655 FOR N=1 TO 26
 9660 INPUT A(I,N)
 9665 NEXT N
 9670 RETURN 
 9700 PRINT AT 11,0;"ENTER VOLUMES LAST 26 WEEKS"
 9705 FOR N=1 TO 26
 9710 INPUT B(I,N)
 9715 NEXT N
 9720 RETURN 
 9750 PRINT AT 11,0;"ENTER %P%E RATIO"
 9755 INPUT D$(I)
 9760 RETURN 
 9765 PRINT AT 11,0;"ENTER NO. OF SHARES"
 9770 INPUT F$(I)
 9775 RETURN 
 9800 FOR R=I TO D-1
 9805 LET A$(R)=A$(R+1)
 9810 LET B$(R)=B$(R+1)
 9815 LET C$(R)=C$(R+1)
 9816 LET D$(R)=D$(R+1)
 9817 LET F$(R)=F$(R+1)
 9820 FOR N=1 TO 26
 9825 LET A(R,N)=A(R+1,N)
 9845 LET B(R,N)=B(R+1,N)
 9850 NEXT N
 9855 NEXT R
 9860 LET D=D-1
 9865 GOTO 85
 9990 SAVE "S%P"
 9995 GOTO 10
 9999 PRINT AT 11,4;"MEMORY LEFT: ";16384-(PEEK 16404+256*PEEK 16405-16283);" BYTES"

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

Scroll to Top