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.

116 lines (115 loc) 6.07 kB
/** * # src/fill/held-position — the HELD POSITION AS OF THE GRADED BUS (the theta-floor owner) * * ## What this owns (and why it exists) * ONE surface answers the whole question "what is held, at what basis, worth what at each wake, and * therefore what does standing pat cost?" — reconstruction + basis + marking + the floor decision: * * 1. **Reconstruction** — net the graded ORDER `fill` stream per (strike, right) into the option * inventory a STAND-PAT watcher actually carries ({@link reconstructHeldOptionLegs}). * 2. **Basis** — each held leg's ABS-qty-weighted blended premium over the FULL fill history, * including the portion later closed (the cost basis the bleed marks against). * 3. **Marking** — the per-wake mark of those legs against the tape's own option book * ({@link markHeldLegsPerWake}, the pure marking kernel this owner drives). * 4. **The floor decision** — the stand-down floor and the `theta_bleed` record (or `null`) the sim * driver folds into the graded Blotter. * * Before this owner, (1)+(2) lived as an *untested private function inside the sim driver* and the driver * hand-assembled (4) around a call to (3). The floor was therefore decided by driver glue sitting * downstream of reconstruction nothing could reach: a tested leaf below an untested private step. The * theta gate's own history is the cautionary tale — `markHeldLegsPerWake` had a green UNIT test while * nothing threaded the flag into the sim, so the property was inert in production. Concentrating the * three steps behind this one surface makes the TESTED thing the thing that decides the floor. * * ## Gated, additive, byte-identical when OFF * The gate is {@link HeldPositionInput.markToModel}. `false`/absent ⇒ nothing is reconstructed, nothing * marked, `standDownFloorUsd` is exactly `0` and {@link HeldPositionResult.thetaBleed} is `null` — the * driver emits no record and every existing pinned floor is byte-identical. The bleed only binds when a * position is actually HELD across ≥1 delivered wake: a flat book, or a watcher that closed out * (net-zero inventory), yields no legs and hence no record. * * Pure: no wall clock, no RNG, no lookahead (each wake folds the book only up to its own ts). */ import { markHeldLegsPerWake } from "./mark-to-model.js"; /** * Reconstruct the NET HELD option legs of `instrument` from the graded ORDER `fill` stream — the * inventory a STAND-PAT watcher carries across the wakes. Nets buys against sells per (strike, right): a * closed round-trip nets to zero and is dropped, an open lot leaves a held leg. Each leg's * `basisPremium` is the ABS-qty-weighted average fill price over the FULL fill history (including the * closed portion) — the cost basis the theta bleed marks against. SPOT/equity legs (no strike/right, * ADR-0017) carry no option book to mark and are skipped. The leg `expiry` is deliberately omitted (a * fill carries none) — a reconstructed leg marks against the book's own single expiry, so the marking * kernel's multi-tenor guard is never engaged. Pure; no wall clock, no RNG. * * Exported so the reconstruction rule is reachable BESIDE the surface that consumes it; the sim driver * calls {@link heldPositionAsOfGradedBus}, never this directly. */ export function reconstructHeldOptionLegs(graded, instrument) { const acc = new Map(); for (const e of graded) { if (e.stream !== "ORDER" || e.type !== "fill") continue; if (e.instrument !== instrument) continue; if (e.strike === undefined || e.right === undefined) continue; // a spot/equity leg — no option book to mark const signed = e.side === "buy" ? e.qty : -e.qty; const key = `${e.strike}|${e.right}`; const a = acc.get(key) ?? { qty: 0, absQtyPx: 0, absQty: 0, strike: e.strike, right: e.right }; a.qty += signed; a.absQtyPx += Math.abs(e.qty) * (e.px ?? 0); a.absQty += Math.abs(e.qty); acc.set(key, a); } const legs = []; for (const a of acc.values()) { if (a.qty === 0) continue; // a closed round-trip — nothing held to bleed legs.push({ side: a.qty > 0 ? "buy" : "sell", qty: Math.abs(a.qty), strike: a.strike, right: a.right, basisPremium: a.absQty > 0 ? a.absQtyPx / a.absQty : 0, }); } return legs; } const INERT = { enabled: false, legs: [], marks: [], standDownFloorUsd: 0, thetaBleed: null }; /** * The held position as of the graded bus: reconstruct → basis → mark → decide the theta floor. See the * module header. The sim driver's ENTIRE theta-cell step is one call to this plus emitting * {@link HeldPositionResult.thetaBleed} when it is non-`null`. Pure. */ export function heldPositionAsOfGradedBus(input) { if (input.markToModel !== true || input.wakeTsList.length === 0) return INERT; const legs = reconstructHeldOptionLegs(input.graded, input.instrument); if (legs.length === 0) return INERT; // flat, or the watcher closed out — nothing held to bleed const multOpt = input.multiplier === undefined ? {} : { multiplier: input.multiplier }; const marked = markHeldLegsPerWake({ events: input.tape, instrument: input.instrument, legs, wakeTsList: input.wakeTsList, markToModel: true, ...multOpt, }); const lastMark = marked.marks[marked.marks.length - 1]; if (lastMark === undefined) return { ...INERT, legs }; // no wake resolved to a mark — nothing to charge return { enabled: true, legs, marks: marked.marks, standDownFloorUsd: marked.standDownFloorUsd, thetaBleed: { ts: input.recordTs, instrument: input.instrument, floor_pnl: marked.standDownFloorUsd, wakes: marked.marks.length, last_sellable: lastMark.sellablePerContract, }, }; }