Sell an OTM put and collect premium. Obligated to buy the underlying at the strike if assigned.
| Symbol | Return % | Sharpe | Max DD % | Win % | Avg/trade % | Trades |
|---|---|---|---|---|---|---|
| SPY | +47.0% | 20.08 | +0.0% | +100.0% | +2.5% | 19 |
| QQQ | +66.5% | 6.47 | +0.0% | +100.0% | +3.5% | 19 |
| IWM | +76.6% | 11.75 | +0.0% | +100.0% | +4.0% | 19 |
| DIA | +31.1% | 2.09 | +1.7% | +94.7% | +1.6% | 19 |
| Avg | +55.3% | 10.10 | +0.4% | +98.7% | — | 19 |
What this shows: Overlayed cumulative return series for this strategy across all available symbols.
How to read it: Look for symbols with smoother curves and faster recoveries to assess whether performance is broad-based or driven by a few outliers.
What this shows: Single-symbol cumulative return path for SPY.
How to read it: Use this detailed view to inspect entry/exit behavior over time and whether drawdowns cluster in specific periods.
| Parameter | Default | Description |
|---|---|---|
| strike_pct | 0.95 | Strike as fraction of spot (5% OTM) |
| dte | 45 | Days to expiration at entry |
| cycle_days | 21 | Trading days between new positions |
A cash-secured put sells an out-of-the-money put option and holds cash equal to the strike price as collateral. The maximum profit is the premium collected; the maximum loss is the strike minus premium (if the underlying goes to zero). The strategy profits when the underlying stays above the strike at expiration. It is equivalent to a covered call in terms of risk/reward and is commonly used to acquire stock at a discount or generate income in neutral-to-bullish markets. Backtested using 45 DTE cycles, rolling every 21 trading days, with strikes at 95% of spot.
def run_cash_secured_put(S, K, T, r, sigma):
"""
Cash-Secured Put: sell OTM put, collect premium.
S: spot price, K: strike (95% of S), T: time to expiry (years)
r: risk-free rate, sigma: implied volatility
"""
premium = black_scholes_put(S, K, T, r, sigma)
# At expiration:
# P&L = premium - max(0, K - S_exp)
# Max profit = premium (if S_exp >= K)
# Max loss = K - premium (if S_exp = 0)
return premium
# Backtest loop (45 DTE, monthly cycles)
for entry in monthly_entries:
S = spot_at_entry
K = round(S * 0.95 / 5) * 5 # 5% OTM put
T = 45 / 365.25
premium = black_scholes_put(S, K, T, RISK_FREE_RATE, avg_iv)
S_exp = spot_at_expiry
pnl = premium - max(0, K - S_exp)
pnl_pct = pnl / K * 100 # as % of collateral