chart/docs/archived/esquotes.md
2026-08-14 23:28:44 -05:00

71 lines
3.2 KiB
Markdown

# /ES futures-options quote finder
**Status:** first version shipped. Sidebar **Options** is a lazy-load snapshot
finder. It does not stream, poll, or place orders.
## Purpose
Find `/ES` futures options faster than the thinkorswim chain UI: pick a nearby
expiration, filter by approximate delta or mark, list the matches, and copy a
thinkorswim contract string. The user reviews and enters every order in
thinkorswim.
## UI
Same sidebar level as Tools and Drawings. Closed by default.
- **Until opened:** no calendar work, no HTTP, no Schwab.
- **On first open:** `GET /api/es-options/expirations` (calendar only).
- **On Search/Refresh only:** `GET /api/es-options/search` → batched
`get_quotes()`.
Controls: next 3 dailies, next Friday weekly, next monthly; Puts/Calls (default
Puts); Delta or Price from/to; Search. Results show strike, mark, **Δ ≈**, and
Copy. Last expiration, side, mode, and ranges persist in `localStorage`.
## Schwab API status
Checked against the configured live credentials on 2026-08-14. Read-only.
| Capability | Result | Implication |
|---|---|---|
| OAuth token and Schwab client | Available | The app already authenticates and streams `/ES`. |
| `get_quotes(["/ES"])` | Works: `/ESU26`, `assetMainType: FUTURE` | Use the plural quote endpoint. |
| `get_option_expiration_chain("/ES")` | Works, but only four standard `ES` monthlies | Not used. Dailies/weeklies are built from a calendar. |
| `get_option_chain("/ES")` / `("/ESU26")` | HTTP 400 | No chain discovery. |
| `get_quotes(["./E3AQ26P7780:XCME"])` | HTTP 200 + `errors.invalidSymbols` | TOS text is not the REST symbol. |
| `get_quotes(["./E3AQ26P7780"])` | `FUTURE_OPTION`; description is the TOS form | REST symbol = TOS text without `:XCME`. |
| Futures-option quote fields | bid, ask, mark, last, volume, OI; **no Greeks** | Delta is Black-76, labeled approximate. |
| Weekday 5-point grids | 81/81 valid for `EW2`, `E3A`, `E3B`, `EW3` | Daily/weekly search uses a ±200 / 5-point grid. |
| Monthly `ESU26` | 18/81 at 5-point; 25-point strikes quote | Monthly `ES` roots use a ±600 / 25-point grid. |
| `LEVEL_ONE_FUTURES_OPTIONS` | Not used | Snapshots only. |
| History / order entry | Not available | Current quotes; execute in thinkorswim. |
## Symbol construction
Verified August 2026 weekday roots:
| Weekday | Root | Example |
|---|---|---|
| Mon | `E{n}A` | `E3AQ26` = Aug 17 |
| Tue | `E{n}B` | `E3BQ26` = Aug 18 |
| Wed | `E{n}C` | `E3CQ26` = Aug 19 |
| Thu | `E{n}D` | `E3DQ26` = Aug 20 |
| Fri | `EW{n}` | `EW2Q26` = Aug 14 |
| Quarterly monthly | `ES{month}{yy}` | `ESU26` = Sep 18 |
| Serial monthly | that 3rd Friday's `EW{n}` | `EW3Q26` = Aug 21 |
API: `./{root}{C\|P}{strike}`. TOS copy: that string plus `:XCME`.
## Implementation
- `app/market/es_options.py` — calendar, symbols, Black-76, filters. No I/O.
- `app/market/schwab_quotes.py` — REST `get_quotes` via the existing token.
- `GET /api/es-options/expirations` and `GET /api/es-options/search`
- Search runs in `asyncio.to_thread` so Schwab I/O does not block the loop.
- IV is implied from the ATM mid; |Δ| is computed. Label **Δ ≈**.
- Broker code stays in `app/market/`. No stream subscription.
## Out of scope
Spreads, streaming, prefetch on page load, order entry.