Stock Projector

This file is part of and Synchro-Sette September 1983. Download the collection to get this file.
Developer(s): Gene G. Buza
Date: September 1983
Type: Program
Platform(s): TS 1000
Tags: Finance

This program is a stock price analysis tool that stores date/price quotation pairs in a single packed string variable, using ASCII delimiters (CHR$ 67 for dates, CHR$ 68 for prices, CHR$ 111 as record terminators) to form a simple flat-file database entirely in RAM. The main menu offers six functions: data entry, a 5-day moving-average peak search with a scaled ASCII bar chart, a 20-day quotation viewer, file initialisation, tape save, and record editing. The peak-search routine normalises each moving-average value to a 24-character bar using repeated “%” and “.” characters, and can optionally produce hard copy via LPRINT. The edit function (line 6000) performs an in-string search-and-replace on A$ to correct a mis-entered date or price, updating both the packed string and the parallel DIM arrays.


Program Structure

The program is organised around a main menu at line 100 with six branches dispatched by GOTO VAL Y$*1000, mapping the digit keys 1–6 directly to line blocks 1000, 2000, 3000, 4000, 5000, and 6000. Initialisation of key globals occurs at lines 10–40 before the menu loop is entered.

Line rangeFunction
10–40Global initialisation (A$, SM, LG, N)
100–250Main menu display and key dispatch
1000–1520Data entry / append records to A$
1800–1940Subroutine: display last entry
2000–2570Peak search: build arrays, compute 5-day MA, bar chart
2900–2960Utility subroutine (date/price lookup by record number — unreachable, preceded by STOP at 2899)
3000–321020-day quotation viewer (relies on arrays built in section 2000)
4000File initialise (RUN)
5000–5040Tape SAVE
6000–6430Edit/correct an existing record
9997–9999Development remnant: STOP, SAVE “STOCK PROJECTOR”, RUN

Data Storage Idiom

All records are packed into a single string A$, with the first three characters storing the record count as a zero-padded decimal string. Each record has the form:

  • STR$ N — record number (1–3 digits)
  • CHR$ 67 — field delimiter (‘C’)
  • 8-character date string
  • CHR$ 68 — field delimiter (‘D’)
  • price quote string
  • CHR$ 111 — record terminator (‘o’)

These delimiter values are ordinary printable ASCII characters, meaning a date or price string accidentally containing ‘C’, ‘D’, or ‘o’ would corrupt parsing. The count field is updated in place at line 1510 via LET A$(1 TO 3)=STR$ (N-1).

Key Dispatch

Menu selection uses INKEY$ at line 210 and validates the key code with IF CODE Y$<29 OR CODE Y$>34. On the ZX81/TS1000, the digit characters ‘1’–’6′ have codes 29–34, so this acts as a range check. The branch GOTO VAL Y$*1000 at line 250 elegantly converts the character to a line number without an explicit lookup table.

5-Day Moving Average and Bar Chart

Section 2000 first parses all records into numeric array S(X) and string array B$(X,8). It then computes a 5-day centred moving average into array Q(XX) where XX = X-4, running from index 3 to XX (line 2330). During this pass it also tracks the global minimum SM and maximum LG to enable normalisation.

The bar chart subroutine at line 2500 normalises each Q(N) value to a 0–24 integer (LQ) and builds a string of that many "%." pairs. Each bar is printed on a scrolled line with the date label prepended. Hard copy is triggered if Y$(1)="Y" was answered at the prompt on line 2106.

Edit Function

The edit routine (line 6000) searches A$ for the concatenation of the old date, CHR$ 68, and the old price (Y$), then checks the following character is CHR$ 111 to confirm a complete record match. The record number is recovered by inspecting the 1–3 characters immediately before the preceding CHR$ 111 delimiter at lines 6202–6206. The packed string is then rebuilt in place at line 6400 using string slicing and concatenation. The parallel arrays B$(AA) and S(AA) are also updated at lines 6255 and 6315.

Notable Techniques and Bugs

  • FAST/SLOW toggling: FAST is used around computation-heavy and display-setup sections; SLOW is restored for user-facing prompts and input, the standard ZX81 idiom to avoid display artifacts during processing.
  • VAL A$( TO 3): The record count is retrieved by slicing and converting the first three characters, avoiding a separate numeric variable that could be lost on RUN.
  • Unreachable code: Lines 2900–2960 are a date/price lookup subroutine that can never be reached because line 2899 is STOP. It appears to be a debugging remnant.
  • Section 3000 depends on section 2000: The 20-day viewer uses arrays B$, S, and variable X that are only populated when the peak search (option 2) has been run first. Choosing option 3 without first running option 2 will cause an error.
  • Delimiter collision risk: CHR$ 67 (‘C’), CHR$ 68 (‘D’), and CHR$ 111 (‘o’) are common characters. A date or stock name containing these letters would silently break all parsing routines.
  • PAUSE 40000 as keypress wait: Used throughout as a long blocking pause to hold a message on screen, effectively waiting for BREAK or Enter rather than a specific key.

Content

Appears On

Cassette to accompany the September 1983 issue of Synchro-Sette.

Related Products

Related Articles

Related Content

Image Gallery

Stock Projector

Source Code

  10 LET A$="000"+CHR$ 111
  20 LET SM=99999999
  30 LET N=0
  40 LET LG=0
 100 FAST 
 110 CLS 
 120 PRINT AT 1,7;"% %S%T%O%C%K% %P%R%O%J%E%C%T%O%R% "
 130 PRINT AT 5,0;"TO INPUT OR ADD DATA";TAB 30;1
 140 PRINT AT 7,0;"TO PERFORM PEAK SEARCH";TAB 30;2
 150 PRINT AT 9,0;"TO SEE 20 DAY 'S QUOTATIONS";TAB 30;3
 160 PRINT AT 11,0;"TO INITIALIZE FILE";TAB 30;4
 170 PRINT AT 13,0;"TO SAVE ON TAPE";TAB 30;5
 180 PRINT AT 15,0;"TO EDIT DATA";TAB 30;6
 190 SLOW 
 200 PRINT AT 21,6;" ENTER ONE OF ABOVE ";AT 21,6;"% %E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% "
 210 LET Y$=INKEY$
 220 IF CODE Y$<29 OR CODE Y$>34 THEN GOTO 200
 230 FAST 
 240 CLS 
 250 GOTO VAL Y$*1000
 1000 LET N=VAL A$( TO 3)
 1002 IF LEN A$>4 THEN GOSUB 1800
 1005 LET N=N+1
 1010 SCROLL 
 1015 PRINT "................................"
 1017 SCROLL 
 1020 PRINT "ENTER DATE FOR QUOTE NO.";N
 1025 SLOW 
 1030 SCROLL 
 1040 PRINT "(JUST PRESS ENTER IF NO MORE)"
 1045 SCROLL 
 1047 PRINT "................................"
 1048 DIM N$(8)
 1050 INPUT D$
 1052 IF D$="" THEN GOTO 1500
 1055 LET N$=D$
 1060 LET D$=N$
 1070 SCROLL 
 1080 SCROLL 
 1090 PRINT "(";N;") - (";D$;")"
 1100 SCROLL 
 1110 SCROLL 
 1120 PRINT "ENTER PRICE QUOTE FOR THAT DAY."
 1130 INPUT Q$
 1140 SCROLL 
 1150 SCROLL 
 1160 PRINT "(";N;") - (";D$;") - (";Q$;")"
 1170 SCROLL 
 1180 SCROLL 
 1190 SCROLL 
 1200 LET A$=A$+STR$ N+CHR$ 67+D$+CHR$ 68+Q$+CHR$ 111
 1210 GOTO 1005
 1500 FAST 
 1510 LET A$(1 TO 3)=STR$ (N-1)
 1520 GOTO 100
 1800 PRINT AT 18,0;"LAST ENTRY WAS :::"
 1810 FOR I=LEN A$-1 TO 4 STEP -1
 1820 IF A$(I)=CHR$ 111 THEN GOTO 1840
 1830 NEXT I
 1840 FOR A=I+1 TO LEN A$-1
 1850 IF A$(A)=CHR$ 67 THEN GOTO 1870
 1860 NEXT A
 1870 LET Z$=A$(I+1 TO A-1)
 1880 FOR I=A+1 TO LEN A$-1
 1890 IF A$(I)=CHR$ 68 THEN GOTO 1910
 1900 NEXT I
 1910 LET D$=A$(A+1 TO I-1)
 1920 LET Q$=A$(I+1 TO LEN A$-1)
 1930 PRINT "(";Z$;") - (";D$;") - (";Q$;")"
 1940 RETURN 
 2000 IF VAL A$( TO 3)>27 THEN GOTO 2100
 2010 PRINT AT 10,0;"THE FILE DOES NOT HAVE AT LEAST 28 QUOTATIONS - PRESS ENTER TO  RETURN :::"
 2020 PAUSE 40000
 2030 GOTO 100
 2100 LET X=(VAL A$( TO 3))
 2105 PRINT "DO YOU WANT HARD COPY?"
 2106 PAUSE 40000
 2107 LET Y$=INKEY$
 2110 DIM S(X)
 2115 DIM B$(X,8)
 2120 LET N=0
 2130 FOR I=5 TO LEN A$
 2150 IF A$(I)=CHR$ 111 THEN GOTO 2200
 2160 NEXT I
 2170 GOTO 2300
 2200 FOR B=I-1 TO 1 STEP -1
 2210 IF A$(B)=CHR$ 68 THEN GOTO 2250
 2220 NEXT B
 2250 LET N=N+1
 2260 LET S(N)=VAL A$(B+1 TO I-1)
 2270 LET B$(N)=A$(B-8 TO B-1)
 2290 GOTO 2160
 2300 LET XX=X-4
 2310 DIM Q(XX)
 2320 FOR N=3 TO XX
 2330 LET Q(N)=(S(N-2)+S(N-1)+S(N)+S(N+1)+S(N+2))/5
 2332 IF Q(N)<SM THEN LET SM=Q(N)
 2334 IF Q(N)>LG THEN LET LG=Q(N)
 2336 LET MQ=LG-SM
 2340 NEXT N
 2350 SLOW 
 2360 FOR N=1 TO XX
 2365 SCROLL 
 2370 IF N>2 THEN PRINT B$(N);
 2375 IF N>2 AND Y$(1)="Y" THEN LPRINT B$(N);
 2380 GOSUB 2500
 2390 NEXT N
 2400 PAUSE 40000
 2410 GOTO 100
 2500 LET LQ=(Q(N)-SM)/MQ
 2510 LET LQ=INT (LQ*24)
 2520 LET C$=""
 2530 FOR J=1 TO LQ
 2540 LET C$=C$+"%."
 2550 NEXT J
 2560 PRINT C$
 2565 IF Y$(1)="Y" THEN LPRINT C$
 2570 RETURN 
 2899 STOP 
 2900 FOR A=1 TO LEN A$
 2910 IF CODE A$(A)=111 THEN GOTO 2950
 2920 NEXT A
 2930 PRINT A$(A+1 TO A+3);" ";A$(A+5 TO A+12);
 2940 RETURN 
 2950 IF VAL A$(A+1 TO A+3)=N THEN GOTO 2930
 2960 GOTO 2920
 3000 PRINT AT 10,0;"INPUT DATE EXACTLY AS ENTERED ::"
 3005 SLOW 
 3010 INPUT D$
 3015 FAST 
 3020 FOR N=1 TO VAL A$( TO 3)
 3030 IF B$(N, TO LEN D$)=D$ THEN GOTO 3100
 3040 NEXT N
 3050 PRINT ,,"DATE NOT IN FILE, PRESS ENTER TOCONTINUE ;;;"
 3060 PAUSE 40000
 3070 GOTO 100
 3100 IF X-N>=19 THEN LET EN=N+19
 3110 IF X-N<=19 THEN LET EN=X
 3120 FAST 
 3130 CLS 
 3140 FOR I=N TO EN
 3150 PRINT I;TAB 3;" - (";B$(I);") - (";S(I);")"
 3160 NEXT I
 3170 PRINT "% %P%R%E%S%S% %<%Z%>% %K%E%Y% %F%O%R% %P%R%I%N%T%O%U%T% %O%R% % % %<%E%N%T%E%R%>% %T%O% %R%E%T%U%R%N% %:%:%:% % % % % % % % % % "
 3175 SLOW 
 3180 LET Y$=INKEY$
 3190 IF Y$="" THEN GOTO 3180
 3200 PRINT AT 20,0;"                                                                "
 3210 GOTO 100
 4000 RUN 
 5000 SLOW 
 5010 PRINT AT 10,0;"ENTER THE NAME OF THE FILE,     PREPARE THE RECORDER AND PRESS  ENTER :::"
 5020 INPUT F$
 5030 SAVE F$
 5040 GOTO 100
 6000 PRINT ,,"ENTER THE DATE OF THE INCORRECT ENTRY? ";
 6005 SLOW 
 6010 INPUT D$
 6020 PRINT D$
 6030 PRINT ,,"ENTER THE PRICE QUOTE OF THE    INCORRECT ENTRY? ";
 6040 INPUT Q$
 6050 PRINT Q$
 6060 LET Y$=D$+CHR$ 68+Q$
 6070 FAST 
 6080 FOR N=1 TO LEN A$-LEN Y$
 6090 IF A$(N TO N+LEN Y$-1)=Y$ AND A$(N+LEN Y$)=CHR$ 111 THEN GOTO 6200
 6100 NEXT N
 6110 CLS 
 6120 PRINT AT 10,0;D$;" AND ";Q$;" ARE NOT"
 6130 PRINT "IN THE DATA FILE. PRESS ENTER TOCONTINUE :::"
 6140 PAUSE 40000
 6150 GOTO 100
 6200 CLS 
 6202 IF A$(N-5)=CHR$ 111 THEN LET AA=VAL A$(N-4 TO N-2)
 6204 IF A$(N-4)=CHR$ 111 THEN LET AA=VAL A$(N-3 TO N-2)
 6206 IF A$(N-3)=CHR$ 111 THEN LET AA=VAL A$(N-2)
 6210 PRINT ,,"THE OLD DATE WAS ";D$
 6220 PRINT "WHAT IS THE CORRECT DATE (IF THESAME, JUST PRESS ENTER :::"
 6225 SLOW 
 6230 INPUT Z$
 6240 IF Z$="" THEN GOTO 6260
 6250 LET D$=Z$
 6255 LET B$(AA)=D$
 6260 PRINT D$
 6270 PRINT ,,,,"THE OLD PRICE QUOTE WAS ";Q$
 6280 PRINT "WHAT IS THE CORRECT QUOTE (IF   THE SAME, JUST PRESS ENTER :::"
 6290 INPUT Z$
 6295 FAST 
 6300 IF Z$="" THEN GOTO 6320
 6310 LET Q$=Z$
 6315 LET S(AA)=VAL Q$
 6320 PRINT Q$
 6400 LET A$=A$( TO N-1)+D$+CHR$ 68+Q$+A$(N+LEN Y$ TO LEN A$)
 6410 PRINT AT 20,0;"DATA HAS BEEN CORRECTED - PRESS ENTER TO CONTINUE :::"
 6420 PAUSE 40000
 6430 GOTO 100
 9997 STOP 
 9998 SAVE "STOCK PROJECTO%R"
 9999 RUN 

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

Scroll to Top