Stock Option Analyzer

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

Stock Option Analyzer calculates return-on-investment metrics for covered call option strategies. Given a stock symbol, strike price, option expiration date, current date, share count, share price, dividends, commissions, number of call contracts, and option premium, the program computes both “exercised” and “unexercised” ROI figures along with annualized rates, net proceeds, break-even price per share, and the last trading day before expiration. Date arithmetic is handled entirely in BASIC using a Julian-day-number conversion routine (subroutine 2000) that accumulates cumulative month offsets from array W and accounts for leap years, while subroutine 3000 reverses the process to convert a day number back to a MM/DD/YY string. All input prompts are displayed in inverse video characters, and the program switches between FAST and SLOW modes to balance display speed with computation speed.


Program Analysis

Program Structure

The program is organized into a main flow (lines 48–999) and four subroutines:

  • Lines 48–99: Initialization — enters SLOW mode, calls the title splash (5000), dimensions the days-per-month array Q, sets flag Q1=0.
  • Lines 80–344: Interactive input loop — collects stock symbol, strike price, option expiration date, today’s date, share/option parameters, and commissions.
  • Lines 347–720: Financial calculations and formatted output display.
  • Lines 780–787: Continue/quit prompt.
  • Subroutine 2000: Converts a date string in Z$ (MM/DD/YY) to a Julian day number stored in NZ.
  • Subroutine 3000: Reverses that process — converts a day number N back to a date string Z$.
  • Subroutine 4000: Populates array W with cumulative day-of-year offsets for each month (Jan=0, Feb=31, Mar=59, …).
  • Subroutine 4500: A leap-year helper that converts the fractional part of B/4 (Q7) into a 0-or-1 flag indicating whether the year is a leap year.
  • Subroutine 5000: Title splash screen.

Date Arithmetic

Subroutine 2000 constructs a simplified Julian day number. It extracts month, day, and two-digit year from Z$ into T(1), T(2), T(3). Years below 48 are assumed to be 2000s by adding 100 (line 2021), then offset by 48 (line 2023) to produce a zero-based year. A leap-year adjustment JJ is computed, and January/February of a leap year subtract one from JJ (line 2028). The day number is NZ = W(month) + day + year*365 + JJ.

Subroutine 3000 inverts this: it iterates years 0–99 (variable B), subtracting 365 or 366 from N until it fits within a single year, then iterates months using array Q (which has leap-year February set at line 3008) until the remaining days fit. The result is formatted into Z$.

The last-trading-day calculation uses N = D1 - 1 (line 680) — one day before the computed expiration day number — then calls subroutine 3000 to produce the human-readable date printed at line 684.

Expiration Day Calculation

Lines 230–250 compute the expiration Saturday for a standard US listed option. The day-of-week of the Julian number NZ is found via C1 = NZ - 7*INT(NZ/7), then adjusted so that C1 represents days to the following Saturday. Adding 15 lands on the Saturday on or after the 15th of the expiration month, which is the standard expiration date convention used at the time. The last trading day (line 680) is then one day prior.

Financial Calculations

VariableMeaningFormula
L1Gross stock costNS * PS
L2Total stock cost (with commission doubled)L1 + UC
L3Gross option premium receivedNC * PR (PR already ×100)
L4Net option proceedsL3 - OC
D3Dividend incomePD * NS
P1Proceeds if exercisedNS * P
L5Capital gain if exercisedP1 - (L2 + UC)
L6Net return if exercisedL5 + D3 + L4
L7Net return if unexercisedD3 + L4
R1/R2ROI / Annualized ROI (exercised), %L6/L2 * 100, annualized ×365/D2
R3/R4ROI / Annualized ROI (unexercised), %L7/L2 * 100, annualized ×365/D2
L8Break-even price per share(L2 - L7) / NS

Note that line 380 computes L5 = P1 - (L2 + UC), effectively subtracting the stock commission UC twice (it was already included in L2). This is a potential bug that would slightly understate the exercised return.

Input Handling and Display Idioms

All input prompts use inverse-video characters (the %X encoding), giving them visual emphasis on screen. After each INPUT the value is immediately PRINTed back (e.g., lines 94, 117, 129) — a common idiom to confirm input to the user. Date strings are validated by length check (IF LEN Z$<>4/6 THEN GOTO) before being reformatted into MM/DD/YY form by string slicing.

The program switches to FAST mode at line 347 for the calculation block and returns to SLOW mode at line 750 before displaying results, a standard technique to speed up computation without sacrificing display quality.

One-Time Initialization Guard

The flag variable Q1 (initialized to 0 at line 70) prevents subroutine 2000 from re-dimensioning arrays T and W and re-running subroutine 4000 on subsequent calls. Line 2003 tests Q1=1 and jumps past the setup code; line 2009 sets Q1=1 after the first execution. This is important because the “Continue?” prompt at line 787 loops back to line 51 (which re-dimensions Q) rather than line 70, so Q1 would still be 1 on the next pass and the guard works correctly.

Subroutine 4500 — Leap Year Flag

This small subroutine converts the fractional remainder of B/4 (stored in Q7 by line 3001) into a binary leap-year indicator: if Q7 is exactly 0 (divisible by 4, i.e., leap year candidate), it is set to 1 and the subroutine returns; otherwise it is set to 0. The result is used both to determine 365-vs-366 day years in subroutine 3000 and to set February’s length at line 3008. Note that century-year corrections (1900, 2100) are not implemented.

Notable Anomalies

  • Line 380 subtracts UC (stock commission) a second time in the exercised-return calculation, likely overstating costs.
  • The “Continue?” handler at line 785–787 has a race condition: lines 785 and 787 both call INKEY$ independently. A key press detected at line 785 may not still be held at line 787, causing INKEY$ to return an empty string and fall through without acting on “Y”. A single LET K$=INKEY$ intermediate variable would fix this.
  • Lines 1100 and 999 are both STOP statements; line 1100 appears unreachable.
  • Lines 3006 and 3017 are STOP statements inside subroutines, acting as error handlers for out-of-range date values.
  • The \@@ escape sequences in the display lines (434, 442, 450) produce inverse-space block characters, rendering as solid filled bars that serve as section dividers.

Content

Appears On

Related Products

Evaluate stock options quickly. Output includes an unexercised ROI, annual ROI, and net worth. 16K.

Related Articles

Related Content

Image Gallery

Source Code

  48 SLOW 
  50 GOSUB 5000
  51 DIM Q(12)
  52 LET Q(1)=31
  53 LET Q(2)=28
  54 LET Q(3)=31
  55 LET Q(4)=30
  56 LET Q(5)=31
  57 LET Q(6)=30
  58 LET Q(7)=31
  59 LET Q(8)=31
  60 LET Q(9)=30
  62 LET Q(10)=31
  64 LET Q(11)=30
  66 LET Q(12)=31
  70 LET Q1=0
  80 CLS 
  90 PRINT "%E%N%T%E%R% %S%T%O%C%K% %S%Y%M%B%O%L"
  92 INPUT S$
  94 PRINT S$
 110 PRINT "%E%N%T%E%R% %S%T%R%I%K%E% %P%R%I%C%E"
 115 INPUT P
 117 PRINT P
 120 PRINT "%E%N%T%E%R% %O%P%T%I%O%N% %D%A%T%E MMYY"
 125 INPUT Z$
 127 IF LEN Z$<>4 THEN GOTO 120
 128 LET Z$=Z$(1 TO 2)+"/01/"+Z$(3 TO 4)
 129 PRINT Z$
 140 GOSUB 2000
 210 IF NZ=0 THEN GOTO 120
 230 LET C1=NZ-7*INT (NZ/7)
 240 LET C1=9-C1
 242 LET C1=C1-7*INT (C1/7)
 250 LET D1=NZ+15+C1
 251 REM PRINT D1
 260 PRINT "%E%N%T%E%R% %T%O%D%A%Y%S% %D%A%T%E MMDDYY"
 262 INPUT Z$
 263 IF LEN Z$<>6 THEN GOTO 260
 264 LET Z$=Z$(1 TO 2)+"/"+Z$(3 TO 4)+"/"+Z$(5 TO 6)
 266 PRINT Z$
 270 GOSUB 2000
 272 IF NZ=0 THEN GOTO 260
 280 LET D2=D1-NZ
 282 REM PRINT D2
 300 PRINT "%E%N%T%E%R% %N%O%.% %O%F% %S%H%A%R%E%S"
 305 INPUT NS
 307 PRINT NS
 309 PRINT "%E%N%T%E%R% %P%R%I%C%E%/%S%H%A%R%E"
 311 INPUT PS
 313 PRINT PS
 315 PRINT "%E%N%T%E%R% %P%E%R%I%O%D% %D%I%V%I%D%E%N%D"
 317 INPUT PD
 319 PRINT PD
 320 PRINT "%E%N%T%E%R% %U%N%D%E%R%L%Y%I%N%G% %C%O%M%M%I%S%S%I%O%N"
 322 INPUT UC
 324 PRINT UC
 325 CLS 
 326 PRINT "%E%N%T%E%R% %N%O%.% %O%F% %C%A%L%L%S"
 327 INPUT NC
 329 PRINT NC
 332 PRINT "%E%N%T%E%R% %P%R%E%M%I%U%M"
 334 INPUT PR
 336 PRINT PR
 340 PRINT "%E%N%T%E%R% %O%P%T%I%O%N% %C%O%M%M%I%S%S%I%O%N"
 342 INPUT OC
 344 PRINT OC
 347 FAST 
 350 LET PR=PR*100
 360 LET L1=NS*PS
 362 LET L2=L1+UC
 364 LET L3=NC*PR
 366 LET L4=L3-OC
 370 LET D3=PD*NS
 372 LET P1=NS*P
 380 LET L5=P1-(L2+UC)
 382 LET L6=L5+D3+L4
 390 LET R1=L6/L2
 392 LET R2=R1*(365/D2)
 400 LET R1=R1*100
 402 LET R2=R2*100
 410 LET L7=D3+L4
 412 LET R3=100*(L7/L2)
 414 LET R4=R3*(365/D2)
 420 LET L8=(L2-L7)/NS
 430 CLS 
 432 PRINT AT 0,2;"%C%O%V%E%R%E%D% %O%P%T%I%O%N% %A%N%A%L%Y%S%I%S%-%-";S$
 434 PRINT AT 1,1;"@@@@@@@@@@@@EXERCISED@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
 436 PRINT AT 2,1;"%R%O%I%= ";R1
 438 PRINT AT 3,1;"%A%N%N%.% %R%O%I%= ";R2
 440 PRINT AT 4,1;"%N%E%T% %R%E%T%U%R%N%= ";L6
 442 PRINT AT 5,1;"@@@@@@@@@@@@UNEXERCISED@@@@@@@@@@@@@@@@@@@@@@@@@@"
 444 PRINT AT 6,1;"%R%O%I%= ";R3
 446 PRINT AT 7,1;"%A%N%N%.% %R%O%I%= ";R4
 448 PRINT AT 8,1;"%N%E%T% %R%E%T%U%R%N%= ";L7
 450 PRINT AT 9,1;"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
 460 PRINT AT 10,1;"NET PROCEEDS: $";L4
 590 PRINT AT 11,1;"BRK.EVEN $";L8;" /SHARE"
 595 PRINT AT 12,1;"NET CAPITAL INVESTED $";L2-L4
 650 PRINT AT 13,1;"BUY ";NS;" SHARES AT ";PS
 660 PRINT AT 14,1;"SELL ";NC;" OPTIONS AT ";PR/100
 670 PRINT AT 15,1;"DAYS TO EXPIRATION ";D2
 680 LET N=D1-1
 682 GOSUB 3000
 684 PRINT AT 16,1;"LAST TRADING DAY ";Z$
 700 PRINT AT 17,1;"COMMISSIONS: "
 702 PRINT AT 18,4;"STOCK= ";UC;" OPTION= ";OC
 710 PRINT AT 19,1;"PERIOD DIVIDEND= ";PD
 720 PRINT AT 20,1;"STRIKE PRICE= $";P
 750 SLOW 
 780 PRINT AT 21,1;"%C%O%N%T%I%N%U%E% %? Y/N "
 785 IF INKEY$="" THEN GOTO 780
 787 IF INKEY$="Y" THEN GOTO 51
 999 STOP 
 1100 STOP 
 2000 REM 
 2003 IF Q1=1 THEN GOTO 2009
 2004 DIM T(3)
 2005 DIM W(12)
 2006 GOSUB 4000
 2009 LET Q1=1
 2011 LET T(1)=0
 2012 LET T(2)=0
 2013 LET T(3)=0
 2015 LET T(1)=VAL Z$(1 TO 2)
 2017 LET T(2)=VAL Z$(4 TO 5)
 2019 LET T(3)=VAL Z$(7 TO 8)
 2021 IF T(3)<48 THEN LET T(3)=T(3)+100
 2023 LET T(3)=T(3)-48
 2024 LET JJ=INT (1+T(3)/4)
 2026 IF JJ<0 THEN LET JJ=0
 2028 IF T(1)<3 AND (INT (T(3)/4)=(T(3)/4)) THEN LET JJ=JJ-1
 2030 LET T(1)=W(T(1))
 2032 LET NZ=T(1)+T(2)+(T(3)*365)+JJ
 2036 RETURN 
 3000 FOR B=0 TO 99
 3001 LET Q7=(B/4)-INT (B/4)
 3002 GOSUB 4500
 3003 IF 0>=N-(365+Q7) THEN GOTO 3007
 3004 LET N=(N-(365+Q7))
 3005 NEXT B
 3006 STOP 
 3007 LET Q8=48+B
 3008 LET Q(2)=28+Q7
 3009 FOR A=1 TO 12
 3010 IF 0>=N-Q(A) THEN GOTO 3020
 3012 LET N=N-Q(A)
 3014 NEXT A
 3017 STOP 
 3020 LET Q9=A
 3025 LET P7=N
 3030 LET Z$=STR$ (Q9)+"/"+STR$ (P7)+"/"+STR$ (Q8)
 3050 RETURN 
 4000 LET W(1)=0
 4001 LET W(2)=31
 4002 LET W(3)=59
 4003 LET W(4)=90
 4004 LET W(5)=120
 4006 LET W(6)=151
 4008 LET W(7)=181
 4009 LET W(8)=212
 4010 LET W(9)=243
 4011 LET W(10)=273
 4012 LET W(11)=304
 4013 LET W(12)=334
 4015 RETURN 
 4500 REM 
 4510 IF Q7=0 THEN LET Q7=1
 4520 IF Q7=1 THEN RETURN 
 4530 LET Q7=0
 4540 RETURN 
 5000 REM 
 5010 PRINT AT 10,10;"%T%S%-%S%T%O%C%K"
 5012 PRINT AT 11,3;"COVERED OPTION ANALYSIS"
 5020 FOR N=1 TO 25
 5030 NEXT N
 5040 CLS 
 5099 RETURN 

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

People

No people associated with this content.

Scroll to Top