MEng FinTech · Algorithmic Trading II · Assignment 2

Covered Call ·

Long 100 shares, short one weekly call, one name, no rolls. The strategy is small enough to state in a sentence, which means the whole result lives in the decisions around it — which strike, at what price, and at which moment. This page books all three explicitly and then measures how much each one was worth.

The rules, before the results

Every line below is executed by one loop in lib/covered_call.py. Nothing on this page is chosen by hand, and nothing is chosen after seeing the outcome.

  1. entry On the first session of each week — not "Monday", see below — at the bar: if the book is flat, buy 100 shares at the stock print. Cash decreases.
  2. strike In the same bar, sell one call expiring at the end of that same week, struck at the lowest listed strike at or above spot. When spot sits exactly on a listed strike, that strike is the answer — the rule is "at or above", not "strictly above", which is what makes the ATM case work instead of silently selling an extra strike of upside.
  3. fill The call fills at mid = (BID + ASK) / 2 in that same bar. Both legs come from one bar, so neither leg sees the other's future. No two-sided quote, no fill — and because the combo is one decision, an unpriceable call also means we do not buy the stock.
  4. wait Hold to expiry. No rolls, no buy-to-close, no adjustment of any kind. At the closing print of the week's last session:
    ST > K → assigned. Deliver the shares, cash increases by 100 × K, the book is flat, and the next week starts the combo again.
    ST ≤ K → expires worthless. Keep the shares, keep the premium, and next week simply write another call against stock we already own.
The tie is decided on purpose. At ST exactly equal to K the call has no intrinsic value and is not rationally exercised, so we treat it as expiring. It is a measure-zero case on real prices, but it has to be decided somewhere rather than falling out of a floating-point comparison by accident. tests/test_covered_call.py pins both sides of it.

Blotter

Only trades that were actually booked. No working orders, no signals, no intentions. Each row names the rule that produced it.

Ledger

Shares, the short call with its strike and expiry, cash, and the marks — at the close of every session. The ledger is derived from the blotter rather than accumulated alongside it, so the two cannot drift apart: cash at any bar is the starting cash plus the deltas of the blotter events that have happened by then, and a test asserts exactly that at every one of the bars.

Reg T, used like an account

Reg T rather than portfolio margin, for a reason that is not just "the handout said so": Reg T is computable without a broker's PM engine, and a book that clears Reg T also clears PM. The implication runs one way only, so the conservative requirement is the one worth reporting.

LMV = shares × stock mark NAV = cash + stock MV + option MV (a short call is NEGATIVE) initial = 50% × LMV covered short call adds $0 maint = 25% × LMV FINRA available = NAV − initial excess = NAV − maint

The covered call adds nothing to the initial requirement, which is the whole reason the position is called covered: the short call's only obligation is to deliver stock the account already owns. Cash moves on blotter events and nowhere else — buy stock, collect premium, expire at zero, assign at the strike. Marks move NAV; they never move cash.

Does the mid predict the trade?

The whole book fills at the mid, so the assumption deserves evidence rather than a sentence. Below is every hourly bar in which a call both had a two-sided quote and actually printed: of them.

The test that settles it: squeeze the price range

A pooled R² over contracts worth one cent to ninety-nine dollars is inflated by range alone. The honest check is whether the fit survives inside a narrow band, where knowing that a $3 option is not a $6 option is actually difficult. It does — which was not the expected answer, and is reported here because it was not.

By moneyness

By how often it traded in the bar

An undeclared parameter, and what it was worth

"Fill at mid" is only half an assumption. The other half is which mid — and nothing in the assignment, or in most backtests, says. Below is the identical book, same rule and same strike logic and same calendar, written at each tradeable hour of the entry session. Only the clock moves.

What the strike rule cost

The booked rule is the assignment's baseline. The others run through the identical engine — same calendar, same fills, same ledger — so the difference between them is a difference of decisions and not of two implementations that drifted. Two of them are not fixed distances at all: they solve for the strike the week's own at-the-money implied volatility prices at a stated chance of being breached, reusing the Black-76 inversion written for Assignment 1.1.

Checking the bar against a 1-minute pull

Two claims on this page rest on what an hourly bar is: that its BID/ASK is the quote standing at the end of the hour, and that prints landing outside their own bar's quote are a timing artefact rather than something real. Both were assumptions. So the same contracts were re-pulled at one minute — two-sided quoted bars — and both were measured.

What happened

Methods, and the things that had to be checked

Two of these are corrections to the handout. The rest are assumptions this page would otherwise have been resting on quietly — including two bugs of my own, which are here because of how they were caught rather than despite it.

Data