Coin Future Options Chain

Coin Future Options Chain

About the project

Options chains are the canonical UI for derivatives markets: every strike price for a given expiry listed in a two-sided grid, calls on the left, puts on the right. The at-the-money (ATM) strike — closest to the current index price — is the focal point, attracting the most liquidity and the tightest spreads. Building a useful options chain means solving for real-time data freshness, grid density on small screens, and making the ATM row immediately visible without forcing the user to scroll to find it.

  • The Binance Options API is free and public, but aggressively CORS-blocked from cloud IPs — Cloudflare Workers, Vercel, and Bunny.net edges all return 403
  • REST calls are handled in the browser at page load; live pricing flows solely through the WebSocket stream which has no IP restriction
  • Market data (strikes, expiries) is refreshed once per hour to track any intraday changes to available instruments

Check out: Live Demo Live App

The stack was chosen for minimal bundle size and zero server-side coupling. React 19 handles the component tree; Zustand 5 owns all market state with O(1) symbol lookups. Vite 8 + Tailwind CSS v4 keep the build pipeline fast. There are no charting libraries — the candlestick chart and sparklines are hand-rolled SVG. Biome replaces ESLint and Prettier. Vitest covers the market data parsing logic.

  • React 19 + Zustand 5 — fine-grained memoisation; store doubles as a ring buffer for sparkline history (configurable 1–60s sample rate)
  • Custom WebSocket client — JSON-RPC SUBSCRIBE/UNSUBSCRIBE to manage kline streams dynamically as rows expand and collapse
  • Cloudflare Workers + Wrangler — stateless edge deployment; separate worker script proxies /eapi/* REST calls for the browser
  • Hand-rolled SVG charts — no charting dependencies; candlesticks and sparklines computed inline from Zustand state

What we did

The WebSocket layer was the core engineering challenge. BinanceMarketStream opens a single multiplexed connection to wss://fstream.binance.com/market/stream and subscribes to two stream types simultaneously: {underlying}@optionMarkPrice (live prices, Greeks, IV for every active symbol) and {underlying}@optionOpenInterest@{YYMMDD} (per-expiry OI snapshots). Kline streams ({symbol}@kline_15m) are subscribed on demand when a row is expanded and unsubscribed when collapsed, using Zustand state as the source of truth for active subscriptions.

The stream also implements Page Visibility API listeners to close the connection when the tab is backgrounded and reconnect when it returns to focus — preventing unbounded message queuing during long inactive periods.

The grid layout required careful work to stay usable across screen sizes. On desktop, CSS Grid with dynamically computed gridTemplateColumns strings mirrors the calls/puts layout symmetrically around a fixed-width strike column. The column template updates live as the user toggles columns in the settings panel. On mobile (below 768px), the symmetric layout is replaced by a single-column view with CALL/PUT tab switching — maintaining scannability without horizontal overflow.

  • ATM detection: Index price from the WebSocket stream is used to recalculate the ATM strike on every tick; the highlighted row tracks the market live via a ref-based scroll-into-view on initial load
  • Settings panel: Column visibility and decimal precision are persisted in component state; the grid template string is recomputed on change without a page reload
  • Candlestick chart: Hand-written SVG renderer — OHLC bars calculated from Zustand kline history, green/red fill, no external library
  • Cloudflare proxy: A 20-line Workers script forwards /eapi/* requests to eapi.binance.com, bypassing the CORS block that rejected Vercel and Bunny edges
Coin Future Options ChainCoin Future Options ChainCoin Future Options Chain