This program performs covered call option analysis, calculating return on investment figures for both exercised and unexercised scenarios on a stock option position. The user enters the stock symbol, strike price, option expiration date, today’s date, share count, share price, periodic dividend, commissions, number of call contracts, and option premium. Two date-to-serial-number conversion routines (subroutines at lines 2000 and 3000) handle the calendar arithmetic, including a leap-year adjustment, to compute days remaining until expiration and to reverse-convert a serial day number back into a human-readable date for the last trading day display. Results shown include ROI, annualized ROI (scaled to 365 days), net return, break-even price per share, net capital invested, and a commission summary, all formatted with AT-positioned PRINT statements filling the screen.
Program Analysis
Program Structure
The program is organized into a main flow (lines 50–999) and five subroutines:
| Line Range | Purpose |
|---|---|
| 50–66 | Initialization: call splash screen, build days-per-month array Q(12) |
| 70–344 | Input gathering: symbol, strike price, dates, shares, dividends, commissions, option details |
| 350–720 | Financial calculations and full-screen results display |
| 780–999 | Continue/quit prompt loop |
| 2000–2036 | Subroutine: date string → serial day number (NZ) |
| 3000–3050 | Subroutine: serial day number → date string (Z$), used for last trading day |
| 4000–4015 | Subroutine: populate cumulative day-of-year offsets array W(12) |
| 4500–4540 | Subroutine: convert fractional leap-year indicator Q7 to 0 or 1 |
| 5000–5099 | Splash screen subroutine |
Date Arithmetic
The date-to-serial routine at line 2000 converts a MM/DD/YY string stored in Z$ into a linear day count NZ. It extracts month, day, and two-digit year into array T(3). Years below 48 are treated as 2000s by adding 100, then 48 is subtracted to obtain an offset from a base epoch (1948). A simple leap-year correction JJ is computed as INT(1 + T(3)/4); if the current month is January or February of a leap year, JJ is decremented by one. The cumulative month offset is looked up from W(12) (populated by the subroutine at 4000), and the final serial is W(month) + day + year*365 + JJ.
The inverse routine at line 3000 walks forward year by year, subtracting 365 or 366 days, using subroutine 4500 to resolve the leap-year flag Q7 from a fractional value. Once the target year is found, it iterates through months using Q(A) to find the month and remaining day, then formats the result back into Z$.
Financial Calculations
The core option analysis is computed at lines 350–414. Key intermediate values:
L1 = NS * PS— gross cost of sharesL2 = L1 + UC— total capital invested (stock cost + underlying commission)L3 = NC * PR— gross premium received (premium is multiplied by 100 at line 350)L4 = L3 - OC— net option premium after option commissionD3 = PD * NS— total period dividendP1 = NS * P— proceeds at strike priceL5 = P1 - (L2 + UC)— capital gain/loss if exercised (note:UCis double-counted here, which is a bug)L6 = L5 + D3 + L4— total net return if exercisedL7 = D3 + L4— net return if unexercised (premium + dividend only)R1, R2— exercised ROI and annualized ROI (×100 for percentage)R3, R4— unexercised ROI and annualized ROIL8 = (L2 - L7) / NS— break-even price per share
Day-of-Week Calculation for Expiration
Lines 230–250 compute the last Saturday of the expiration month as the option expiry date. The serial number of the first of the expiration month (NZ) is used: C1 = 9 - (NZ MOD 7), further reduced modulo 7, then D1 = NZ + 15 + C1. This places the result on the third Saturday of the month, consistent with standard U.S. equity options expiration conventions of the era. The last trading day is then D1 - 1 (the Friday before), computed at line 680 and decoded by subroutine 3000.
Notable Techniques and Idioms
- The flag variable
Q1at line 2003 prevents re-dimensioningT(3)andW(12)and re-running theWinitialization on subsequent calls to the date subroutine — a guard idiom common in BASIC programs that share subroutines across multiple input loops. - Input validation uses length checks (
LEN Z$<>4at line 127,LEN Z$<>6at line 263) and re-prompts withGO TOon failure. - Date strings entered as compact
MMYYorMMDDYYare reformatted by string slicing and concatenation intoMM/DD/YYbefore use (lines 128, 264), avoiding the need to parse separators during input. - The
INKEY$polling loop at lines 785–787 first waits for any keypress, then checks for “Y” to restart — but becauseINKEY$is re-read at line 787 independently, a fast typist may miss the “Y” check (a subtle timing bug). - The splash subroutine at 5000 uses a short
FOR/NEXTloop (lines 5020–5030, only 25 iterations) as a minimal delay before clearing the screen — effectively negligible on this hardware.
Bugs and Anomalies
- Double commission deduction: At line 380,
L5 = P1 - (L2 + UC)subtractsUCtwice (once already included inL2 = L1 + UC), overstating the commission cost and understating the exercised net return. - Leap-year subroutine 4500: This routine converts a fractional
Q7(0.25 for a leap year, 0 otherwise) to a boolean 0 or 1. However, the logic setsQ7=1when it equals 0, then immediately returns — meaning non-leap years are counted as leap years. Only whenQ7was already 1 does it return 1, which never happens sinceQ7is computed as a fraction. The effective result is that every year is treated as having 366 days in subroutine 3000, causing incorrect last-trading-day output. - Line 347 and 750: These are empty statement lines with no code, likely remnants of deleted lines.
- STOP at lines 3006 and 3017: These act as error traps if the date arithmetic overflows its loop bounds, providing no user-facing error message.
Content
Image Gallery
Source Code
50 GO SUB 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 "ENTER\::STOCK\::SYMBOL"
92 INPUT S$
94 PRINT S$
110 PRINT "ENTER\::STRIKE\::PRICE"
115 INPUT P
117 PRINT P
120 PRINT "ENTER\::OPTION\::DATE MMYY"
125 INPUT Z$
127 IF LEN Z$<>4 THEN GO TO 120
128 LET Z$=Z$(1 TO 2)+"/01/"+Z$(3 TO 4)
129 PRINT Z$
140 GO SUB 2000
210 IF NZ=0 THEN GO TO 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 "ENTER\::TODAYS\::DATE MMDDYY"
262 INPUT Z$
263 IF LEN Z$<>6 THEN GO TO 260
264 LET Z$=Z$(1 TO 2)+"/"+Z$(3 TO 4)+"/"+Z$(5 TO 6)
266 PRINT Z$
270 GO SUB 2000
272 IF NZ=0 THEN GO TO 260
280 LET D2=D1-NZ
282 REM PRINT D2
300 PRINT "ENTER\::NO.\::OF\::SHARES"
305 INPUT NS
307 PRINT NS
309 PRINT "ENTER\::PRICE/SHARE"
311 INPUT PS
313 PRINT PS
315 PRINT "ENTER\::PERIOD\::DIVIDEND"
317 INPUT PD
319 PRINT PD
320 PRINT "ENTER\::UNDERLYING\::COMMISSION"
322 INPUT UC
324 PRINT UC
325 CLS
326 PRINT "ENTER\::NO.\::OF\::CALLS"
327 INPUT NC
329 PRINT NC
332 PRINT "ENTER\::PREMIUM"
334 INPUT PR
336 PRINT PR
340 PRINT "ENTER\::OPTION\::COMMISSION"
342 INPUT OC
344 PRINT OC
347
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;"COVERED\::OPTION\::ANALYSIS--";S$
434 PRINT AT 1,1;"\::\::\::\::\::\::EXERCISED\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::"
436 PRINT AT 2,1;"ROI= ";R1
438 PRINT AT 3,1;"ANN.\::ROI= ";R2
440 PRINT AT 4,1;"NET\::RETURN= ";L6
442 PRINT AT 5,1;"\::\::\::\::\::\::UNEXERCISED\::\::\::\::\::\::\::\::\::\::\::\::\::"
444 PRINT AT 6,1;"ROI= ";R3
446 PRINT AT 7,1;"ANN.\::ROI= ";R4
448 PRINT AT 8,1;"NET\::RETURN= ";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 GO SUB 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
780 PRINT AT 21,1;"CONTINUE\::? Y/N "
785 IF INKEY$="" THEN GO TO 780
787 IF INKEY$="Y" THEN GO TO 51
999 STOP
1100 STOP
2000 REM
2003 IF Q1=1 THEN GO TO 2009
2004 DIM T(3)
2005 DIM W(12)
2006 GO SUB 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 GO SUB 4500
3003 IF 0>=N-(365+Q7) THEN GO TO 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 GO TO 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;"TS-STOCK"
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.