UNPKG

kestrel.markets

Version:

A typed, token-efficient language + runtime for agentic trading: agents author bounded plans, the runtime fires them at the tick. CLI + typed library + MCP server.

171 lines (135 loc) 9.06 kB
# First Plan — a bounded-risk contingent program A **Plan** is a standing, bounded-risk contingent program: **trigger → actions → bracket → invalidation → TTL**. The agent authors it once; the runtime fires it at machine speed and informs the author in parallel — **fire-then-inform**. The agent is never in the hot path. This page reads one Plan clause by clause. ```kestrel id=plan-open-drive check=roundtrip PLAN open-drive budget 0.25R ttl 15:55 USING signal SPX exec ODX 0dte WHEN spot crosses above hod DO buy 2 +1 C @ ask TP 2x frac 0.5 @ fair EXIT spot < vwap held 120s @ fair ``` This Plan is the marquee `kestrel card first-plan` prints, and it is **authored to run on the free 0DTE options cell** — the one `kestrel sim` lists with the `ODX` instrument. Run it with `kestrel sim <that-cell> --plans <file>`, copy it verbatim, and it *fills*. Every choice below is made against that one tape; the recurring lesson is that **a Plan must be authored to the tape it will run on** — its instrument universe, the series it writes, and how it fills. ## The header: bounded risk is a type ``` PLAN open-drive budget 0.25R ttl 15:55 ``` Every Plan is defined-risk before it can arm. `budget 0.25R` is a **positive risk fraction** — the position is bounded by construction, and a non-positive budget is refused at parse time. `ttl 15:55` is the time-to-live: the Plan expires at the clock. This Plan carries **no `regime` gate**, so it arms the moment it is submitted — which is what you want on a synthetic or free-tier tape. An optional `regime {scope: value}` clause is a **hard arming gate**, not a label: a Plan that carries one stays `authored (blocked)` — it never arms, never fires — until the session's tape writes a matching `REGIME` event, and a tape with no regime writer can *never* satisfy it. Free and synthetic tapes carry no regime stream, so a gated Plan silently places zero orders on them; **omit the gate to trade a free cell**, and add one only when your tape (or a live feed) actually writes the regime you gate on. `validate --arm` warns you at author time when a gate can never fire on the context you hand it — the same dead-on-arrival verdict a run surfaces, so you never learn it from an empty blotter. `USING signal SPX exec ODX 0dte` sets scoped defaults for the document — read the signal off one instrument, **execute on another** — so each leg need not repeat them. **The exec instrument must live on the tape you will run against — this is the first way a Plan is authored to its tape.** A leg executes on the ambient `exec` symbol, and the runtime can only fill a leg whose instrument is actually quoted on the session's tape. The free options cell here is an **`ODX` 0DTE chain**, so `exec ODX` resolves against a real chain and fills. Name an *off-tape* instrument instead — `exec SPY 0dte` on this ODX cell — and the option leg is **unresolvable**: there is no SPY chain to price the strike against, so the runtime fail-closes the leg and the Plan places **zero orders**. It is not an error you see; it is a silent, empty blotter — the same dead-on-arrival outcome as a trigger that reads a series the tape never writes (below). Match `exec` to the tape's instrument universe: name the cell's own instrument — here `ODX`, the symbol `kestrel sim` lists for the free cell. Run the cell and the blotter tells you plainly — an on-tape exec fills, an off-tape one places nothing. ## The trigger: WHEN it may fire ``` WHEN spot crosses above hod ``` The `WHEN` clause is the trigger algebra: named series (`spot`, `hod`) and predicates (`crosses above`) composed with `AND / OR / NOT`. Here the opening drive fires on a clean break of the high-of-day — the momentum signal the cell is built around. This same algebra is shared with Wake and Grade; see the [shared lexical core](./lexical-core.md). **Every series in a `WHEN` must be a stream the tape actually writes — the second way a Plan is authored to its tape.** You could tighten this trigger with an acceleration gate, `WHEN spot crosses above hod AND velocity(5m) >= p95``p95` is a **baseline-relative** threshold (the 95th percentile of that window's own trailing distribution, not an absolute number, so the Plan stays portable across instruments). But `velocity(5m)` is a *derived series a tape has to carry*, and a coarse free or synthetic tape may not write one. A `WHEN` that reads an unwritten series never resolves true, so the Plan expires having placed **zero orders** — the same silent empty blotter as an off-tape `exec`. So the marquee arms on the bare `crosses above hod`, which the free cell does write; add the velocity gate only once your tape (or a live feed) carries velocity — and the same check applies: run the cell and let the blotter confirm the trigger actually fires. ## The action: what fires, and at what price ``` DO buy 2 +1 C @ ask ``` When the trigger confirms, the runtime places the order: buy two calls, one strike out (`+1`). The price expression is the discipline. On a fast opening drive you want the fill *now*, so this leg **lifts the offer** (`@ ask`) — it prices through the resting queue and crosses immediately. This is the **third way a Plan is authored to its tape**: the runtime only fills what actually crosses the book, and on the short free cell a limit resting *below* the market never gets there before the tape settles. Lift the offer and the marquee fills; rest under it and you get another silent empty blotter. Lifting the offer is the right call *on a momentum entry you must not miss*. A patient entry — a fade, or any thesis where a worse price is a better one — inverts the discipline: there you rest, and you cap what you will pay. `fair` is a **value** anchor (model worth); `mid` is a **book** anchor (where the queue sits). `@ min(fair, mid) peg cap fair` rests at the better of the two, `peg` re-prices as the market moves, and `cap fair` guarantees you **never pay past fair value** — a quote is where the queue is, never what a thing is worth. The [shared lexical core](./lexical-core.md) shows that resting, capped discipline on the fade Plan. The leg above is an **option** leg — a quantity, a strike (`+1`), and a right (`C`/`P`). To buy the underlying instead, write an **equity** leg: the `shares` marker replaces the strike+right, and the ambient `exec` symbol is the instrument (ADR-0017). ``` DO buy 100 shares @ spot ``` `buy 100 shares` is complete — an equity/spot leg carries no strike or right, and `spot` is its price anchor. Omit `shares` and write `buy 100 @ spot` and the parser refuses it, naming both continuations: a strike for an option leg, or `shares` for an equity leg. ## The bracket: taking profit ``` TP 2x frac 0.5 @ fair ``` `TP` (take-profit) banks a fraction of the position at a multiple — here, half the position at 2x, resting at a value anchor. Take-profit tiers run in the manage phase of every fired Plan. ## The out: EXIT on the underlying, never on the mark ``` EXIT spot < vwap held 120s @ fair ``` An `EXIT` is an active out — the thesis is dead, get flat. Crucially it conditions on the **underlying** (`spot < vwap held 120s`), never on the option's mark. A quote is a health signal, not a value; an EXIT that watched the mark would be refused at parse time. Giveback that holds for two minutes below VWAP means the drive is over. ## Two more contingent clauses Two clauses this Plan does not use, but every author should know, express the rest of the contingency: - **RELOAD** adds rungs into the thesis on further confirmation — for a fade, a worse price is a *better* entry, so the ladder itself is the thesis. - **INVALIDATE** is distinct from EXIT: the thesis broke, so **stop adding** and ride the bounded remainder — it does not flatten. The [shared lexical core](./lexical-core.md) page shows a fade Plan built from RELOAD and INVALIDATE, next to a Wake and a Grade over the same series. ## What is real today The Plan runtime is the most exercised part of Kestrel — it drives a Plan through authored → armed → fired → managing → done and has been run end-to-end in a **mechanically-graded practice** session. That is not a certified result; the [certified honest-tier cohort is 0](./capability-truth.md). Read each clause's runtime and evidence axes on the [status page](./status.md) before treating any of it as proven trading edge. ## Next - **[First Grade](./first-grade.md)** — the fourth kind: *did it actually work?* The honest result of a run — graded, never asserted. - **[Adopt](./adopt.md)** — the exit escape hatch: when your `EXIT` sits in a *replacement* plan that opened no leg, `ARM … foreach held leg` carries the held position across the wake so the covered sell can close it. Walks the whole fill → adopt → exit loop with a runnable example. - **[The shared lexical core](./lexical-core.md)** — the series and price expressions a Plan shares with the other three statement kinds.