88 lines
5.9 KiB
Markdown
88 lines
5.9 KiB
Markdown
# /ES futures-options quote finder
|
|
|
|
**Status:** future feature; no quote-finder UI, API route, or futures-options
|
|
subscription is implemented yet.
|
|
|
|
## Purpose
|
|
|
|
Find a small, user-selected set of `/ES` futures options more quickly than the
|
|
thinkorswim option-chain UI, show their live tradable quotes, and produce an
|
|
unambiguous leg or spread description that the user can copy into thinkorswim.
|
|
The app assists research and pricing only. The user reviews and enters every
|
|
order in thinkorswim; it must not submit, simulate, or automate orders.
|
|
|
|
The first useful workflow is deliberately narrow:
|
|
|
|
1. Select a futures-option expiration and call/put side.
|
|
2. Select one or more strikes, including the two legs of a vertical spread.
|
|
3. Fetch a current snapshot of bid, ask, mark, last, volume, and open interest
|
|
for that small set of exact contracts.
|
|
4. Copy a thinkorswim-tested contract or spread description for manual entry.
|
|
|
|
Do not subscribe to or poll the whole option universe. Discovery should narrow
|
|
the candidates first, then one REST request obtains the selected quotes. A user
|
|
may explicitly refresh a stale snapshot; continuous streaming is out of scope.
|
|
|
|
## Schwab API status
|
|
|
|
Checked against the configured live Schwab credentials on 2026-08-14. These
|
|
were read-only requests; no account or order endpoint was called.
|
|
|
|
| Capability | Result | Implication |
|
|
|---|---|---|
|
|
| OAuth token and Schwab client | Available | The existing app already authenticates and streams `/ES` futures. |
|
|
| `get_quotes(["/ES"])` | Works: HTTP 200, resolving to active future `/ESU26` with `assetMainType: FUTURE` | Use the plural quote endpoint. `get_quote("/ES")` puts the slash in a URL path and can return the `ES` equity instead. |
|
|
| `get_option_expiration_chain("/ES")` | Works: HTTP 200; it returned four `/ES` expiry entries and option root `ES` | Use it to enumerate available expiration dates and roots. |
|
|
| `get_option_chain("/ES")` | Fails: HTTP 400 | It is not a usable `/ES` futures-options chain/discovery endpoint. |
|
|
| `get_option_chain("/ESU26")` | Fails: HTTP 400 | Resolving the active underlying contract does not make the chain endpoint work. |
|
|
| `get_quotes()` for the supplied thinkorswim text `./E3AQ26P7780:XCME` | Fails semantically: HTTP 200 with `errors.invalidSymbols` | A thinkorswim identifier is not automatically a valid Schwab REST symbol. Resolve the API equivalent explicitly. |
|
|
| `get_quotes(["./E3AQ26P7780"])` | Works: `assetMainType: FUTURE_OPTION`; its reference description is `./E3AQ26P7780:XCME` | For this verified contract, the API form is the thinkorswim text with the `:XCME` exchange suffix removed. The snapshot included bid, ask, mark, last, volume, and open interest. |
|
|
| `LEVEL_ONE_FUTURES_OPTIONS` for `./E3AQ26P7780:XCME` | The subscription command was accepted, but no quote handler message arrived during a 15-second premarket probe | Not needed for this feature: it uses snapshots, not continuous updates. This result is retained only as future reference. |
|
|
| Historical futures-options prices | Not available | Schwab price history is not available for futures or options; the finder is a current-quote tool, not a historical-pricing system. |
|
|
| Futures-options order entry | Not available for this workflow | Keep execution in thinkorswim. Schwab Trader API support for equities and standard options must not be mistaken for `/ES` futures-options routing. |
|
|
|
|
The expiration endpoint narrows the date/root, but it does **not** return every
|
|
strike or a quoteable option symbol. Exact futures-option symbol resolution is
|
|
therefore the feature's critical discovery problem, not a formatting detail.
|
|
|
|
## Symbol and thinkorswim contract
|
|
|
|
Do not invent a futures-option symbol from a guessed `ES`, month, strike, and
|
|
call/put pattern. The supplied thinkorswim string `./E3AQ26P7780:XCME` maps to
|
|
the verified API symbol `./E3AQ26P7780`: removing `:XCME` returned the intended
|
|
`FUTURE_OPTION`, whose description returned the original thinkorswim form. This
|
|
is one tested mapping, not yet a general rule for every exchange, product,
|
|
expiration, or option root. Before building the finder, prove the following for
|
|
representative current `/ES` options:
|
|
|
|
1. Schwab `get_quotes()` returns the intended futures option, including a valid
|
|
bid and ask rather than an equity or an error.
|
|
2. The finder output can be pasted or searched in thinkorswim to select the
|
|
same leg. A two-leg spread must preserve buy/sell direction and quantity as
|
|
well as strike, expiration, and call/put side.
|
|
|
|
Store separately any Schwab API symbol and the thinkorswim copy text. They may
|
|
be identical, but that is an acceptance criterion to prove, not an assumption.
|
|
|
|
## Implementation constraints
|
|
|
|
- Keep future-options code isolated with the existing broker integration in
|
|
`app/market/`; no analysis, bars, or UI code should call Schwab directly.
|
|
- Request REST snapshots only after a user has selected exact contracts or
|
|
explicitly asked to refresh. Batch all displayed contracts into one
|
|
`get_quotes()` request; do not open a futures-options WebSocket subscription.
|
|
- Show quote freshness and whether data is delayed. A stale, wide, or missing
|
|
market is more important than a calculated spread mark.
|
|
- Treat a spread mark as a display calculation from the two current legs, not
|
|
an executable price. Preserve both bid/ask combinations so the UI can show
|
|
realistic debit/credit bounds.
|
|
- Do not persist credentials, account details, or order state in this feature.
|
|
|
|
## First implementation gate
|
|
|
|
Add a small read-only probe using representative current `/ES` options copied
|
|
from thinkorswim and their mapped Schwab API identifiers. Capture both forms,
|
|
the REST response type and quote fields, snapshot timestamp or delay status,
|
|
and the expiration/strike shown by each system. Add a regression fixture only
|
|
after that probe establishes a stable real payload and mapping rule. Until
|
|
then, a full-chain UI or automatic symbol construction would be speculative.
|