Premium-selling bots usually encode a schedule: sell the 30-day put on the first of the month, sell 0DTE every morning. The hard part is not placing the order. It is knowing when to stand aside.
sell-window turns that decision into one GET request. For SPY, QQQ and IWM it returns four expiry windows, each with sell, skip or unavailable, and on a sell it lists candidate trades with strikes, bid/ask, delta, mid credit and an exit rule. Treat it as a gate in front of your own strategy, not as the strategy.
It came out of more than 5 million backtests on 2018 to 2026 minute-level option quotes. In those backtests, standing aside on skip days cut max drawdown on the same trades at the same size from $958,924 to $255,105 and lifted Sharpe from 0.61 to 0.76. Details and limitations are further down.
The request
curl -H "X-Api-Key: $FLASHALPHA_API_KEY" \
"https://lab.flashalpha.com/v1/strategies/sell-window/SPY"
| Name | In | Required | Notes |
|---|---|---|---|
symbol |
path | yes |
SPY, QQQ or IWM. Any other symbol returns every window as unavailable. |
No query parameters. The decision is set from the previous session's close and fixed for the session. The session rolls at 16:00 ET (13:00 ET on early-close days): before the close you get the current session, after it you get the next one.
The response
Top-level fields:
| Field | Meaning |
|---|---|
symbol |
Upper-cased symbol |
session |
Session the answer applies to (yyyy-MM-dd) |
spot |
Underlying mid used to pick strikes (present when a window sells) |
quoted_at |
UTC time of the quotes (present when a window sells) |
legs_indicative |
true when quotes predate that session's 09:35 ET entry, so re-check strikes after 09:35 |
windows[] |
Always four entries: same day, ~1 week, ~2 weeks, ~1 month |
endpoint_version, data_as_of
|
Standard response envelope |
Each window:
| Field | Meaning |
|---|---|
expiry, days_to_expiry
|
Listed expiry closest to the window target; absent if none falls in range |
action |
sell, skip or unavailable
|
candidates[] |
Only on sell: structure, exit, legs[], mid_credit
|
legs[] |
side, quantity, type, strike, delta, bid, ask (quantity is 2 on the sold body of put_bwb, else 1) |
mid_credit |
Net credit per share at mid. Multiply by 100 for dollars per unit. |
Window ranges:
| Window | Target | Accepted |
|---|---|---|
| Same day | 0 days | 0 |
| ~1 week | 7 days | 4 to 10 |
| ~2 weeks | 14 days | 11 to 17 |
| ~1 month | 30 days | 25 to 35 |
Structures: short_put, short_call, short_strangle, short_straddle, tail_hedged_put, put_credit_spread, put_bwb.
Exits: expiry (hold to expiration) or tp50 (close once it can be bought back for half the credit or less, otherwise hold).
A skip day is short. This is the first window from SPY on 5 November 2026, where all four windows skipped:
{ "expiry": "2026-11-05", "days_to_expiry": 0, "action": "skip" }
A minimal client
import os
import requests
API = "https://lab.flashalpha.com/v1/strategies/sell-window/{}"
HEADERS = {"X-Api-Key": os.environ["FLASHALPHA_API_KEY"]}
def sell_window(symbol: str) -> dict:
r = requests.get(API.format(symbol), headers=HEADERS, timeout=10)
r.raise_for_status()
return r.json()
for sym in ("SPY", "QQQ", "IWM"):
d = sell_window(sym)
flag = " (indicative, re-check after 09:35 ET)" if d.get("legs_indicative") else ""
print(f"{sym} session {d['session']}{flag}")
for w in d["windows"]:
print(f" {w.get('expiry', '-'):>10} {w['action']}")
for c in w.get("candidates", []):
legs = " / ".join(
f"{l['side']} {l['quantity']}x {l['strike']} {l['type']}" for l in c["legs"]
)
print(f" {c['structure']:<18} exit={c['exit']:<6} "
f"${c['mid_credit'] * 100:,.0f} {legs}")
Treat unavailable exactly like skip. Budget three calls per poll (one per symbol), and note that rejected requests, including 403s, count toward your daily quota.
| Status | When |
|---|---|
401 |
Missing or invalid key (empty body) |
403 tier_restricted |
Plan below the required tier |
429 Quota exceeded |
Daily quota used; Retry-After gives seconds to the 00:00 UTC reset |
Strike selection, so you can reproduce it
Every leg must be out of the money, have a bid above zero, a bid/ask spread no wider than 20% of mid, and open interest of at least 250. Among qualifying contracts the leg is the one whose delta is closest to the backtest target, within 0.05. Ties go to the tighter spread, then higher open interest. If any leg cannot be found, the candidate is dropped rather than approximated.
Backtesting it yourself
The same route is mirrored on the historical host. Pass at set to 09:35 ET to get what the endpoint would have said that morning (Alpha plan):
import os
import requests
r = requests.get(
"https://historical.flashalpha.com/v1/strategies/sell-window/SPY",
params={"at": "2024-03-01T09:35:00"},
headers={"X-Api-Key": os.environ["FLASHALPHA_API_KEY"]},
timeout=30,
)
print(r.json()["windows"])
Loop that over sessions, price each candidate to its listed exit, and you can check the published backtest trade by trade.
What the backtest shows
January 2018 to October 2026, SPY, QQQ and IWM, one unit per listed candidate. Entries at 09:35 ET filled halfway between mid and the bid or ask, plus $0.01 per share and $1 per contract. Positions valued daily and closed at the 15:55 ET quote on expiry day.
| Metric | sell-window | Same trades every session |
|---|---|---|
| Max drawdown | $255,105 | $958,924 |
| Worst month | -$170,829 | -$307,241 |
| Sharpe, 2018 to 2026 | 0.76 | 0.61 |
| Sharpe, 2022 to 2026 | 0.89 | 0.66 |
| Total P&L | $945,541 | $2,321,150 |
| Trades | 20,883 | 56,975 |
Total P&L is lower because it trades about a third as often. Scaled 3.76x to the same max drawdown, it earned $3,554,225 against $2,321,150.
Limitations
- In-sample: candidates were chosen with 2018 to 2026 visible. Chosen on 2018 to 2021 only, the 2022 to 2026 Sharpe was 0.67.
- Losing years: 2018 and 2022. 29% of months lost money.
- In 2017, a calm year before the backtest window with no selloff to avoid, it lagged selling every day (Sharpe 1.55 vs 1.70).
- A skip blocks new trades only. It does not manage open positions.
- Overlapping candidates can stack: roughly eight one-month positions open at once is plausible.
- Early assignment and margin interest are not modelled.
The forward test is a paper bot posting trades and P&L on Discord: https://discord.gg/UtH22J8df2
Access
Basic plan through November 2026, Growth from 1 December. Historical replay requires Alpha.
- Guide: https://flashalpha.com/articles/complete-guide-trading-sell-window-spy-qqq-iwm
- Every trade, 2018 to 2026: https://flashalpha.com/articles/sell-window-backtest-every-trade-2018-2026
- API reference: https://flashalpha.com/docs/lab-api-strategies-sell-window
Hypothetical, pre-tax backtest results. Not investment advice.
Top comments (0)