
Ticket
Ticket is a UI for representing Options Trading in a more intuitive way.
Demo
About
Ticket: options trading that feels like trading perps Options are powerful but hard to use. Most options UIs are a grid of strikes and expiries, and you have to picture the payoff in your head. Ticket turns the price chart itself into the order ticket, so building an options position feels as direct as opening a perp. How it works The screen is a large price chart. Past price shows as candles; the future side shows every listed expiry. Pick Buy/Sell Call or Put and click anywhere in the future: a leg is placed at the nearest listed strike and expiry. The whole future area is shaded as a P&L heat map over time and price: green where the position makes money, red where it loses, and brighter for bigger P&L. On top of the map, Ticket draws: a break-even line; outlines where P&L is within 5% of the max profit or max loss, traced from the exact P&L right up to expiry; hatching and tags when a loss (or profit) is uncapped. Legs can be dragged, and the map morphs smoothly as you move them. A handle between legs drags a whole structure at once (e.g. slide a call spread to a new strike and date while keeping its width). Compounding and tracking Stack any number of legs into spreads, condors, calendars or custom shapes. A sidebar shows: strategy name, net debit/credit, max profit/loss, break-evens, chance of profit and greeks; presets for common structures, plus full undo and redo. A Positions tab tracks open positions with live P&L, a P&L sparkline, and progress toward max profit. You can tick several positions to see their combined exposure on the chart together with a new trade. Draw path Draw where you think price will go, and Ticket builds the position that pays off along that path. It places a call butterfly on each listed expiry your line crosses, centred on your line's price at that date, with wings sized to the expected move. It then shows what you'd make if price follows your line. Built on Derive Live mainnet data: listed expiries and strikes, index price, price history, and each option's mark, bid, ask and implied volatility. Ticket prices with the implied volatility that reproduces Derive's mark, so the map matches exchange prices. Testnet trading on Derive's v3 API (Sepolia): connect with MetaMask, sign in, and authorise a scoped, 7-day trading key created in the browser. That key can trade but not withdraw, and your wallet key never leaves MetaMask. Order review: every leg gets a dry-run quote from Derive (validity, expected fill, fees) before signed orders are sent, as market or limit-at-mark. Your Derive positions and open orders appear in the app, and you can close or cancel them. Builder code: every order carries a Derive builder code and fee. A demo mode with simulated data works anywhere. Transparency AI use: the code was written with Claude Code, working from my direction; every commit is co-authored. I contributed the product concept, feature and design decisions, hands-on testing and bug reports, the Derive and MetaMask setup, and the deployment. Earlier start: an early UI prototype was started shortly before the official start, and recreated in this repo in the first 9 commits. Everything after that was built during the event.
How it's made
Stack: React 19 + TypeScript + Vite, with the chart drawn on a plain HTML canvas. There's no charting library, because the chart is the whole interface. Pricing is Black-Scholes written from scratch. It's deployed on Railway as a static build served by a small dependency-free Node server (server.mjs) with a health check. The Derive TypeScript SDK and ethers handle signing, and MetaMask provides the wallet. Architecture Data layer: the rest of the app only talks to a small MarketSource / Market interface (spot, candles, listed expiries and strikes, IV, quotes). There are three implementations: Demo: a simulated random-walk market with a volatility smile. Live: Derive mainnet. Testnet: Derive's v3 API on Sepolia. Switching is a URL parameter, and the rest of the app doesn't know which one is running. Chart: a canvas that redraws from the current legs and view. P&L heat map: computed on a grid of (time, price) cells and kept in an offscreen canvas, so it's only recalculated when the legs, prices or view change. The grid is coarser while you drag, so dragging stays at 60 fps. Break-even line: where P&L crosses zero between grid cells. Max profit/loss: found over the position's whole life (every expiry and the times in between), not just at the first expiry. That matters for positions with legs on different dates. Strategy model: turns legs into a P&L function of (price, time), plus greeks, break-evens, chance of profit and max profit/loss. Derive integration (our exchange; not a prize partner at this event) Market data: Everything goes over Derive's WebSocket JSON-RPC, including requests. Derive's REST endpoints don't send CORS headers, so a browser app can't call them directly. Ticket loads the instrument list and each expiry's tickers (refreshed every 10 s), plus index price history, and subscribes to the live index. v2 and v3 use different method names (e.g. get_all_instruments and get_index_chart_data on v3), so there's a small adapter for each. Pricing that matches the exchange: Derive's own IV is computed against the forward price, and our model prices off spot. So for every listed option we solve for the IV that makes our Black-Scholes reproduce Derive's mark price exactly. The P&L map therefore starts from real exchange prices. Unlisted strikes interpolate IV between their neighbours. Trading (testnet): Connect: MetaMask switches to Sepolia and signs a Derive login. The app then generates a session key in the browser, and MetaMask authorises it with one EIP-712 signature (set_session_key). Key limits: that key can trade on the orderbook and RFQ but can't withdraw, and it expires after 7 days. After that, orders sign without popups. Review: each leg becomes a limit order on the right tick size and amount step. Derive's order_quote dry-runs every leg (validity, fill, fees) before anything is sent. Orders are then signed and placed one leg at a time, stopping at the first rejection. Builder code: every order carries a referral code and extra fee, set by environment variable. The SDK and ethers are lazy-loaded, so the chart doesn't pay for them until you connect.