Files
Michelle 4aa8789cba Initial commit — BTC 5-minute binary options edge study
Reconstructed strategy engine + execution layer, trained XGBoost models, a manual
trading tool, and the research writeup. Paper mode runs keyless over live WebSocket
feeds; live trading requires your own wallet. No secrets committed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 22:49:05 -07:00

105 lines
7.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Mini-PRD — Quick-Trade: a hotkey execution interface for 5-minute binaries
> *Written retrospectively: this documents the product decisions behind a tool I built and used during the study. The tool itself belongs to the full (private) system — no live-trading code ships in this repo.*
## Problem
A 5-minute binary market prices in new information within seconds; the actionable moment for any late-window signal is the **final 1040 seconds**. Polymarket's native web UI needs multiple clicks and page-state changes to place one order, gives no feedback on how long an order actually took, and is unusable for building intuition about how the book behaves under time pressure.
If Pillar 3 of the study asks *"can a human capture the edge at all?"*, the native UI answers "no" for the wrong reason — **tool latency, not market latency**. To make the test fair, execution overhead had to be driven to its floor and *measured*, so that whatever latency remained was attributable to the market, not the mouse.
## User
One power user: me. (n = 1 by design — this is a research instrument, not a consumer product. That constraint drives most scope cuts below.)
## Goals & success metrics
| Goal | Metric |
|---|---|
| Minimal click-to-submit path | **One keystroke** = one signed, posted order (no Enter, no confirmation dialog) |
| Latency visible, not assumed | Every order prints its **measured sign-and-submit round-trip in ms** (`create_order` + `post_order` → API ack) |
| Fill outcome reported, not assumed | After the order: **filled or not, matched size, fill price, and PnL** — read from the order's `size_matched` |
| Zero per-click network overhead beyond the order itself | Price display and order parameters require **0 extra HTTP calls** at trade time |
| Usable across windows without operator work | New 5-minute market auto-discovered and re-warmed in the background |
## Non-goals (explicit cuts)
- **No variable order size** — fixed 10 shares per keystroke. Fewer keys to think about, and it caps fat-finger damage.
- **No order management** — no cancel/modify UI. GTD expiry does the cleanup.
- **No position dashboard, no charts** — the separate watch screen owns market display; this tool owns the trigger.
- **No multi-market support** — current window only.
## Functional requirements (the entire keyboard surface)
| Key | Action |
|---|---|
| `u` / `d` | Buy UP / DOWN, 10 shares, at market (ask + $0.02 buffer, capped at $0.99) |
| `Shift`+`1``6` | Resting limit "lottery" bids at $0.01 / $0.02 / $0.03 — cheap maker orders (`1``3` = UP, `4``6` = DOWN) |
| `i` / `o` | Sell UP / DOWN at best bid, most expensive lot first |
| `b` / `r` / `w` | Balance check · redeem settled tokens · force window refresh |
| `q` | Quit (restores terminal state) |
## Component structure
```
① PRICE FEED — always live in the background. THIS is why a click needs no network:
Polymarket WebSocket ──► collector ──► snapshots.jsonl ──► tail -F ──► Price panel
(chainlink price + (local file, the (live bid/ask,
CLOB book, real-time) collector streams it) countdown)
② HOT PATH — fires on ONE keystroke; it reads the current ask from the Price panel
above (a local read), so no network call is needed to price the order:
keystroke (raw tty, no Enter)
Key listener (select() loop)
Order router u/d = market · cheap limits · i/o = sell
Preflight cache tick_size + neg_risk, warmed once per window
Order builder + signer client-side signing; HTTP/1.1 keep-alive
REST post_order (GTD) ──► Polymarket CLOB
③ REPORTING — every order writes one line to a JSONL journal (the study's dataset):
• on submit: sign → ack latency (ms)
• at settle: poll order status (REST) ──► size_matched · fill price · PnL
Background: a window manager auto-detects each new 5-minute market, resolves its
token IDs (one REST call), and re-warms the Preflight cache before the window opens.
```
## Key decisions & tradeoffs
| Decision | Why | Cost accepted |
|---|---|---|
| Single keystroke, no confirmation | The confirmation dialog *is* the latency problem | Fat-finger risk — mitigated by fixed small size |
| Fixed 10-share size | Removes a decision (and keystrokes) from the hot path | No sizing flexibility |
| Prices from a local file tail, not REST | The collector already streams every tick to disk; reading it costs ~0ms and no rate limits | Depends on the collector running |
| Warm order params once per window | `tick_size`/`neg_risk` lookups are per-token constants; fetching them per order wastes a round trip inside the hot path | Stale cache on rare market config change |
| Market buys pay ask + $0.02 | In the last seconds, a missed fill costs more than 2¢ of price improvement | Slightly worse average entry |
| Sell most-expensive-lot-first | Realizes the best exit first when unwinding under time pressure | — |
| Terminal UI, not web | tty raw mode delivers a keypress in microseconds; a browser adds an event loop you don't control | No visual polish |
## The real cost center: the fill lifecycle
The interface optimizes the *submit* path — but a keystroke doesn't buy anything; it opens an order lifecycle:
```
quote (best ask) → post → { full fill | partial fill | no fill } → retry / cancel
```
This is deliberately **not** managed in the tool (fixed size, GTD auto-expiry does the cleanup — see Non-goals), and that scoping choice is exactly where the honesty lives: **order management is the pain, not a feature I could polish away.** On a thin binary book, partial fills and no-fills are routine. Each retry chases an ask the maker has already moved, so you cross to a worse price (slippage) or miss entirely. The exit runs the same lifecycle as a ladder — post the ask → step to the bid → cross at market — and a latency circuit breaker halts trading when the round trip degrades. The full loop regularly takes longer than the edge exists. **Latency inside this lifecycle plus thin-book slippage consumes essentially the entire margin** — which is why the fast-submit interface, though necessary, was never going to be sufficient.
## Outcome
The interface doubled as the study's **measurement instrument**: every order writes one line to a JSONL journal — sign-and-submit latency, whether it filled, matched size, fill price, PnL. That log is the raw dataset behind Pillar 3, turning "execution is slow" from a hunch into distributions you can read. Order latency became a **measured number printed after every trade** instead of a guess, and — together with the fill-lifecycle cost above — that is what makes Pillar 3's conclusion honest: even with the human reduced to a single keystroke and the software path stripped to its floor, the remaining round-trip is orders of magnitude slower than the market makers' millisecond repricing. The bottleneck was never the UI; it's the speed of light plus someone else's colo. **Knowing that changed the product question** — from "how do I trade this faster?" to "what game can retail actually win?" (see the study's conclusion in the [README](../README.md)).