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.

69 lines (68 loc) 4.99 kB
/** * # session/wake-frontier — the band-parameterized wake floor + the frontier's wake shapes * * The safety floor + the pending-wake / per-wake-context types the agent-driven wake frontier * (kestrel-5zl.4) is built from, extracted from the Simulate driver ({@link import("./simulate.ts")}) so * the band → floor table lives beside its own interface. After the T-5 OPEN baseline the AGENT drives its * own monitoring cadence via `scheduleWake`; the platform FLOORS it (never replaces it) with the * {@link WakeFloor} resolved here from the cell's timescale band. * * - {@link wakeFloorForBand} / {@link WakeFloor} — the pure `band → floor` table (kestrel-5zl.16.7); the * DAY row reproduces today's day-shaped constants byte-for-byte (the no-churn anchor); * - {@link FrontierWake} — a wake pending on the frontier (a dateless sim-time instant + its provenance); * - {@link WakeCtx} — the per-wake context the driver knows that the snapshot does not. * * PURE: {@link wakeFloorForBand} is a total function of the band alone (no wall clock, no RNG) — same band * ⇒ identical floor ⇒ byte-identical wake schedule. Safety can never be silenced (CLAUDE fail-closed); the * floors are author-tunable config, never removable by the agent. */ import { assertNever } from "../lang/index.js"; // ── The band-parameterized wake floor (kestrel-5zl.16.7) ────────────────────────────────────────── // The three wake-frontier controls below WERE day-shaped module constants; they are now the `day` // row of a pure {@link wakeFloorForBand} table keyed on the cell's timescale band (`carry.band`, the // multi-session horizon Axis A). The DAY row REPRODUCES today's exact defaults byte-for-byte (the // no-churn anchor); the other rows scale the same three controls to their timescale. Threaded once at // the top of `runSimulateSession` from `openingCarry.band` (default `day`), so a standalone / // flat-open run is byte-identical to today. See the design note on kestrel-5zl.16.7. /** The DAY staleness-backstop deadline (minutes): a gap longer than this after any delivered vantage * forces a platform safety wake, so a book is never left unattended (CONTEXT "Staleness backstop"). * This is ALSO the universal fail-closed floor — a HELD book in a WIDER band whose backstop lands past * settle still gets a safety wake before settle (never a silent no-wake window while exposed). */ export const DAY_STALENESS_BACKSTOP_MIN = 30; /** The DAY minimum spacing (minutes) between DELIVERED wakes: an agent wake closer than this to the * last vantage is FOLDED (coalesced) and surfaced on the retained delivery's `attention.coalesced` — * never a separate turn, never a silent drop. The staleness/structural floors are exempt. */ const DAY_MIN_WAKE_SPACING_MIN = 1; /** The DAY per-session ceiling on delivered wakes: past it the agent's wakes are folded (downgraded to * safety-only) so a runaway cadence can't exhaust attention — the staleness/structural floors still fire * (safety is never capped away). A generous default; the budget algebra proper is scoped to b3l. */ const DAY_MAX_WAKES = 512; /** * The band → {@link WakeFloor} table (kestrel-5zl.16.7). Pure + total (every {@link TimescaleBand} maps). * * band backstop spacing (coalesce) ceiling * scalp 2 min 0.25 min (15 s) 4096 — seconds-scale, tick cadence * day 30 min 1 min 512 — TODAY'S EXACT DEFAULTS (the no-churn anchor) * swing 240 min (4 h) 5 min 512 — intraday → multi-day * position 1440 min (~1 d) 15 min 512 — a ~1-day backstop + daily cadence * * The DAY row is the identity of today's day-shaped constants (byte-for-byte); the scalp/swing/position * rows are the minimal shape consistent with `carry.band` + those defaults (design note on 5zl.16.7). * The fail-closed floor (a HELD book in a WIDE band always keeps a backstop before settle — never a * silent no-wake window while exposed) is enforced in `runSimulateSession`'s `armStaleness`, not * by widening this table: widening cadence by band must never create a silent exposed window. */ export function wakeFloorForBand(band) { switch (band) { case "scalp": return { stalenessBackstopMin: 2, minWakeSpacingMin: 0.25, maxWakes: 4096 }; case "day": return { stalenessBackstopMin: DAY_STALENESS_BACKSTOP_MIN, minWakeSpacingMin: DAY_MIN_WAKE_SPACING_MIN, maxWakes: DAY_MAX_WAKES }; case "swing": return { stalenessBackstopMin: 240, minWakeSpacingMin: 5, maxWakes: DAY_MAX_WAKES }; case "position": return { stalenessBackstopMin: 1440, minWakeSpacingMin: 15, maxWakes: DAY_MAX_WAKES }; default: return assertNever(band, "simulate: unknown timescale band"); } }