# Wheel Strategy — my reproducible study

## The question

Can a one-contract cash-secured wheel earn a useful return with a smaller drawdown than simply holding AMZN? I expected income to help in a flat or moderately rising market, but expected the calls and time spent in cash to hurt in a strong rally. I did not assume that collecting premium means making a profit.

This is a retrospective fixed-rule study, not a fresh blind test, an optimized result or a live trading record. AMZN is the initial data-complete example, not a claim to have completed the separate mid-cap portfolio project.

## Rules fixed for this run

- Account: $50,000, cash account, at most one short option and 100 shares. No borrowing, no interest on cash, no taxes. Standard 100-share American, PM-settled contracts only.
- Dates: January 3, 2023 through December 31, 2024; 502 evaluated stock sessions. Prior-session warmup starts December 20, 2022. Stock dates are cross-checked against the complete AMD, ADBE and NFLX extracts.
- Entry: first session or Monday, when no option is open. Cash state sells a put; stock state sells a call. No reopening on an expiration session. The next eligible Monday is used; a Monday holiday does not shift entry to Tuesday.
- Select from the prior completed session: valid two-sided quote, positive bid, OI >= 100, spread / midpoint <= 25%, and OTM relative to the prior stock close. Only Friday expirations that are trading sessions are used. Holiday expirations are excluded rather than assigned an invented calendar.
- Expiry: 28–42 calendar DTE measured on the planned execution date. Rank by distance to 35 DTE, then earlier expiration, then absolute-delta distance to 0.30, lower strike, and contract ID. A put must be fully secured by cash before premium is credited; a call must have 100 shares of cover. Do not open an expiry beyond the known study end.
- Execute the selected contract at the next EOD bid for sales and ask for purchases; $0.65 fee per option fill. Require a valid same-session entry quote, positive bid, spread / midpoint <= 25%, and positive reported daily volume. If unavailable, skip; do not replace the prior-selected contract using today's chain. This is a conditional EOD quote-fill simulation, not a timestamped executable order reconstruction; the end-of-day volume gate is not an intraday signal.
- Base: hold to expiry. No stop, profit target or discretionary exit. At expiry, >= $0.01 intrinsic value at the stock close triggers modeled physical assignment. A put deducts strike x 100 cash and adds 100 shares. A call removes 100 shares and adds strike x 100 cash. Remove the short option in the same atomic event. Otherwise remove it with zero cash flow. Assignment fee is assumed zero.
- Roll comparison: separately, when 1–5 DTE remain and the prior close is OTM, buy back and write a new same-type option using the same entry ranking. Check eligibility and funds for both legs before either is booked. Record two fills, two fees and one group ID. If either leg fails, hold. No roll on the study's final session.
- Final close: buy back remaining options at ask and liquidate shares at the stock close minus $0.01/share. All scheduled market stock purchases pay close plus $0.01/share; assignments use strike, not slippage. Final account must be flat.

## What is observed, and what is modeled?

The local source is Duke WRDS / OptionMetrics IvyDB US, source ID `duke_wrds_optionmetrics_full_chain_20261020`. The engine uses observed stock closes, option bid/ask, Delta, Gamma, OI, volume and contract definitions. It does not use Black–Scholes to manufacture prices. The query reads both calls and puts, with 0–60 DTE, for the study and warmup dates. The JSON records input row counts, unique contracts, source-file hashes, an ordered-input hash, source-code hash and runtime versions.

Only EOD data are available here. Quotes do not prove freshness, displayed size or fills. Daily volume is not volume at the quote timestamp. There are no matched transaction prints in this extract, so a mid-versus-trade R² cannot honestly be calculated. Midpoint is used for daily NAV marks, not base fills. The full sensitivity reruns show midpoint, bid/ask, and adverse fills 25% of the full spread beyond touch. All six runs are reported; the better roll result does not replace the base.

American-style early exercise, contrary exercise instructions, pin uncertainty and after-hours moves are not reconstructed. The assignment engine is an explicit expiry-only model. AMZN has no dividend or split event in this study window; changing stock adjustment/return factors makes the engine stop for explicit handling. Missing held-option marks also stop the run; there is no forward fill. Vendor historical revisions are not certified original publication vintages. One stock and one rising window do not establish a general strategy edge.

## Read the book

- Blotter: every open, close, expiration, assignment and roll, with contract, trade date, signal-data date, expiry, quantity, fill, fees, cash flow and post-event portfolio. Assignment quantity is 100 shares and removes one short option; it is not a cash-settled intrinsic-value debit in addition to the stock delivery.
- Ledger: every evaluated EOD, including no-trade days. Includes cash, shares, share cost basis, exact short contract, option mark/liability, cash reserved, available cash, NAV, liquidation NAV and net Delta/Gamma. Net Gamma units are change in delta-share exposure per $1 stock move.
- NAV = cash + shares x unadjusted stock close - short-option midpoint x 100. Available cash = cash - put strike x 100 when a put is open. Reserve is restricted cash, not a second expense. This is a fully funded cash account, not a Reg T margin or portfolio-margin simulation.
- The date selector resolves non-trading dates to the prior saved session within the available range. Event snapshots show the modeled state immediately after each EOD event; they do not imply actual intraday times.
- The study ends flat, so net option cash flows + net stock cash flows = ending cash - starting cash = net P&L. Gross premium alone is not a return.

## Benchmarks and metrics

Both benchmarks start with $50,000 on the same dates and use the same stock-slippage rule. One buys 100 shares and leaves the rest in cash. The other buys the maximum whole shares affordable on day one. Both liquidate on the final date. They have different equity exposure from the wheel; these are not delta-matched comparisons.

Return is total two-year account return, not annualized and not return on premium. Drawdown is peak-to-trough EOD NAV loss, including the starting capital point. Sharpe is mean daily simple return / sample daily standard deviation x sqrt(252), with risk-free rate zero. Annualized volatility is sample daily standard deviation x sqrt(252). Idle cash pays zero in all accounts. Monthly P&L is the difference in consecutive month-end NAVs. Option cycles count completed contracts, not necessarily full cash→shares→cash rotations.

## Reproduce

The source ZIP includes the engine, synthetic edge-case tests, independent public-book reconciliation tests and the derived result JSON. It does not redistribute the licensed raw chain.

With Python 3.12 and the NumPy/Pandas versions recorded in the JSON:

```sh
python -m unittest tests.test_wheel_backtest tests.test_wheel_public_book -v
```

To replay the historical quotes, institutional access to the matching source is required. In the project environment:

```sh
.venv/bin/python -m homework3.wheel_backtest --dsn postgresql://localhost/duke535_research
```

The read-only query and all filters are in `load_database()`. Expected PostgreSQL tables:

- `optionmetrics_security_prices`: source_id, ticker, trade_date, close, cumulative_adjustment_factor, cumulative_return_factor, source_file_sha256.
- `option_eod_quotes`: source_id, underlying, trade_date, canonical_symbol, option_type, expiration, strike, best_bid, best_offer, delta, gamma, open_interest, volume, contract_size, exercise_style, am_settlement, root, suffix, source_file_sha256.

An independent dataset can instead be adapted to `replay(stock_rows, quote_rows, Policy())`; its required row fields are shown in the loader and tests. Keep the same definitions and time availability, then compare the exported ledger and cash reconciliation. Do not call a rerun reproducible from these files alone without access to the licensed inputs.

Raw chain rows stay local. The public files contain derived results and diagnostics for the traded legs. The static webpage needs no database login or API keys. AI helped with implementation and checking; the visible hypothesis, rules and limitations are my study notes.

Reference: [Schwab — three things to know about the wheel strategy](https://www.schwab.com/learn/story/three-things-to-know-about-wheel-strategy).
