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 | +31.3% | 0.63 | +9.4% | +94.7% | +1.6% | 19 |
| QQQ | +63.0% | 0.99 | +10.7% | +94.7% | +3.3% | 19 |
| IWM | +36.5% | 0.51 | +13.9% | +89.5% | +1.9% | 19 |
| DIA | +11.7% | 0.27 | +8.9% | +94.7% | +0.6% | 19 |
| Avg | +35.6% | 0.60 | +10.7% | +93.4% | — | 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