sell-window API - Should You Sell Options Today? SPY, QQQ, IWM - FlashAlpha Lab API
  1. sell-window

sell-window API

Should you sell options today? Built from more than 5 million backtests, sell-window answers that every session for SPY, QQQ and IWM: sell or skip for four expiries, from the same day to about one month out. On a sell, it lists the trades with strikes, quotes and the exit rule.

Endpoint

GET /v1/strategies/sell-window/{symbol}
Auth required (X-Api-Key) Rate Limited: Yes Plan: Basic now, Growth from Dec 1

Parameters

NameInTypeRequiredDefaultDescription
symbolpathstringrequired-SPY, QQQ or IWM. Any other symbol returns every window as unavailable.

Request

curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://lab.flashalpha.com/v1/strategies/sell-window/SPY"
import requests

resp = requests.get(
    "https://lab.flashalpha.com/v1/strategies/sell-window/SPY",
    headers={"X-Api-Key": "YOUR_API_KEY"}
)
resp.raise_for_status()
data = resp.json()
for w in data["windows"]:
    print(w.get("expiry"), w["action"], len(w.get("candidates", [])))
const resp = await fetch(
  "https://lab.flashalpha.com/v1/strategies/sell-window/SPY",
  { headers: { "X-Api-Key": "YOUR_API_KEY" } }
);
if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
const data = await resp.json();
for (const w of data.windows) console.log(w.expiry, w.action, (w.candidates ?? []).length);

Try it live

Runs on live market data and uses 1 request from your daily quota.

GET

Response

A sell day: each window carries an action and, on sell, the trades to place.

{
  "symbol": "SPY",
  "session": "2026-10-16",
  "spot": 772.255,
  "quoted_at": "2026-10-16T13:35:00Z",
  "legs_indicative": false,
  "windows": [
    {
      "expiry": "2026-10-16",
      "days_to_expiry": 0,
      "action": "sell",
      "candidates": [
        {
          "structure": "short_put",
          "exit": "expiry",
          "legs": [
            {
              "side": "sell",
              "quantity": 1,
              "type": "put",
              "strike": 769,
              "delta": -0.19,
              "bid": 0.39,
              "ask": 0.4
            }
          ],
          "mid_credit": 0.395
        },
        {
          "structure": "short_strangle",
          "exit": "expiry",
          "legs": [
            {
              "side": "sell",
              "quantity": 1,
              "type": "call",
              "strike": 774,
              "delta": 0.302,
              "bid": 0.63,
              "ask": 0.64
            },
            {
              "side": "sell",
              "quantity": 1,
              "type": "put",
              "strike": 770,
              "delta": -0.264,
              "bid": 0.58,
              "ask": 0.59
            }
          ],
          "mid_credit": 1.22
        }
      ]
    }
  ],
  "endpoint_version": "2026.09.30"
}

Sending request…

See this endpoint on live data

Send this exact request and the real response shows up here, right next to the example.

Real response for SPY at 09:35 ET on 2026-10-16, shortened to one window and two trades. Download the full response (JSON).

On a skip day there is nothing to do, and each window carries only its expiry and action. A real response from SPY on 2026-11-05:

Skip day
{
  "symbol": "SPY",
  "session": "2026-11-05",
  "windows": [
    {
      "expiry": "2026-11-05",
      "days_to_expiry": 0,
      "action": "skip"
    },
    {
      "expiry": "2026-11-12",
      "days_to_expiry": 7,
      "action": "skip"
    },
    {
      "expiry": "2026-11-18",
      "days_to_expiry": 13,
      "action": "skip"
    },
    {
      "expiry": "2026-12-04",
      "days_to_expiry": 29,
      "action": "skip"
    }
  ],
  "endpoint_version": "2026.09.30",
  "data_as_of": {
    "node": "fa4",
    "equity_feed": "2026-11-05T14:11:16.332Z",
    "equity_options_feed": "2026-11-05T14:11:16Z",
    "index_feed": "2026-11-05T14:10:58.1024266Z",
    "index_options_feed": "2026-11-04T22:00:00Z",
    "futures_feed": "2026-11-05T14:11:13.291Z",
    "futures_options_feed": "2026-11-05T14:11:13.337Z",
    "flow_feed": null,
    "oi_feed": "2026-11-04T21:00:00Z",
    "macro_feed": "2026-11-04T21:15:01Z"
  }
}

Response Fields

This endpoint has its own shape, not the strategy decision envelope.

FieldTypeDescription
symbolstringThe symbol, upper case.
sessionstringyyyy-MM-dd. The trading session the answer applies to.
spotnumberUnderlying mid the strikes were picked against. Present when a window sells.
quoted_atstringUTC time of the quotes behind the strikes. Present when a window sells.
legs_indicativebooleantrue when the quotes are from before that session's 09:35 ET entry: call again at or after 09:35 ET for the strikes to trade. Present when a window sells.
windows[]arrayAlways four entries, in this order: the same-day expiry, then the expiries closest to one week, two weeks and one month out. See how windows are chosen.
windows[].expirystringyyyy-MM-dd. The listed expiry this window trades. Absent when no listed expiry falls in the range or the data is missing.
windows[].days_to_expiryintegerCalendar days from session to expiry.
windows[].actionstringsell: a session to sell at this expiry. skip: stand aside, no new trade. unavailable: no answer (a symbol outside coverage or a missing day of data); treat it like a skip.
windows[].candidates[]arrayPresent only when action is sell. The trades to consider, in a fixed order.
candidates[].structurestringThe trade type. See structures and exits.
candidates[].exitstringexpiry or tp50. See structures and exits.
candidates[].legs[]arrayThe contracts of one unit of the trade.
legs[].sidestringsell or buy.
legs[].quantityintegerContracts per unit of the trade (2 for the sold body of put_bwb, otherwise 1).
legs[].typestringcall or put.
legs[].strikenumberStrike price.
legs[].deltanumberThe contract's own delta when the answer was served (negative for puts).
legs[].bid, legs[].asknumberThe contract's quote when the answer was served.
candidates[].mid_creditnumberNet credit per share at mid: sold mids minus bought mids, times quantity. Multiply by 100 for one unit in dollars.
endpoint_version, data_as_ofstring, objectResponse envelope, see Response envelope.

How windows are chosen

Each window trades the listed expiry closest to its target, counted in calendar days after the session.

WindowTargetAccepted range
Same day0 days0 days
About one week7 days4 to 10 days
About two weeks14 days11 to 17 days
About one month30 days25 to 35 days

When a window sells, the listing is the option chain's at the moment of the answer, as the backtests chose it at entry. Otherwise it is the previous close's listing.

Structures and exits

ValueFieldMeaning
short_putstructureSell one put.
short_callstructureSell one call.
short_stranglestructureSell one call and one put.
short_straddlestructureSell one call and one put near the money.
tail_hedged_putstructureShort put with a far out-of-the-money put bought below it.
put_credit_spreadstructureSell one put and buy a lower-strike put.
put_bwbstructurePut broken-wing butterfly: buy one put above, sell two, buy one further below, for a credit.
expiryexitHold to expiration.
tp50exitClose once the position can be bought back for half of the credit or less, otherwise hold to expiration.

How strikes are picked

Strikes are picked from the chain with the contract rules from our backtests: only out-of-the-money contracts with a bid above zero, a bid/ask spread of at most 20% of the mid and open interest of at least 250. Among those, the contract whose delta is closest to the candidate's target and within 0.05 of it is used; ties go to the tighter spread, then the higher open interest. A candidate whose legs cannot all be found in the chain is left out.

Errors

StatusErrorWhen
401-Missing or invalid X-Api-Key. The body is empty; check the status code before parsing JSON.
403tier_restrictedYour plan is below the one required: Basic through November 2026, Growth from December 1, 2026.
429Quota exceededDaily quota used up. Retry-After gives the seconds until the reset at 00:00 UTC. Rejected requests (including 403) count toward the quota.

About

More than 5 million backtests led to this endpoint. It answers one question: is this a session to sell options? The answer is set from the previous session's close and stays fixed for the whole session. Strikes, deltas and quotes come from the chain at the moment you call.

In the backtest on SPY, QQQ and IWM from January 2018 to October 2026, following it had a maximum drawdown of $255,105 against $958,924 for the same trades sold every session, and a Sharpe ratio of 0.76 against 0.61, on about a third of the trades. See every trade in the backtest.

The session switches at the close (16:00 ET, 13:00 ET on early-close days). Before the close the answer is for the current session. After the close and on closed days it is for the next session.

Plans: Basic or higher through November 2026, Growth or higher from December 1, 2026. Backtesting: on Alpha, the historical API returns the answer for any past session with ?at=, so you can reproduce it on your own fills and sizing. A paper bot follows this endpoint every session and posts its results on our Discord.

The skip call applies to new trades, so it cannot protect positions already open when a sudden shock hits. This is data, not investment advice.

Common Use Cases

  • Daily routine - call once after the open and act only on windows where action is sell
  • Pick a trade - read candidates[] for ready strikes, deltas, bid/ask and mid_credit instead of building the legs by hand
  • Compare expiries - see the same-day, one-week, two-week and one-month windows side by side
  • Manage the exit - exit tells you whether the backtest held to expiration or took profit at 50% of the credit
  • Replay a past session - call the historical endpoint with at=<session>T09:35:00 to see the strikes at the backtests' entry time
  • Handle gaps - treat unavailable like a skip

Related reading

Complementary endpoints

Ready to build with FlashAlpha?

Get your free API key and start pulling live options data in 60 seconds.

No credit card required Setup in 60 seconds Secure & reliable