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.
173 lines • 10.2 kB
TypeScript
/**
* # fill/spot — SpotFillEngine: the instrument-keyed resting-order engine for a spot instrument
*
* The equity/crypto sibling of {@link ./engine.ts SimFillEngine} (ADR-0017). The options engine
* keys its strict-cross match on `strike + right` and cash-settles filled inventory at
* **intrinsic** off the final spot — both meaningless for a plain equity (no strike, no expiry).
* This engine keeps the *same* conservative floor and the *same* survival/expected-$ accounting,
* but:
*
* - **matches on `instrument` alone**, against the instrument's own quote/tape observation
* ({@link SpotQuote}) — the strict-cross primitive ({@link spotStrictCross}) is the exact
* instrument-general floor rule, with two arms sharing one strictness doctrine (a definite
* price-priority cross, never same-price):
* • QUOTE arm: a BUY fills iff the ask is present and strictly below the resting price;
* a SELL iff the bid is present and strictly above it. A dark side never crosses.
* • TRADE-THROUGH arm (kestrel-7pq6): a BUY fills iff a trade printed strictly below the
* resting price (`last < px`); a SELL iff strictly above. The derived/catalog tapes are
* quote-less SPOT prints — without this arm the spot floor was structurally inert (every
* resting order unfillable on every catalog scenario, the P&L axis measuring nothing).
* A print AT the limit is not a cross (queue position is unknowable — conservative floor).
* Either arm fills AT the resting price. The far-OTM directional guard / moneyness /
* covered-wing exemption are option concepts with no spot analogue and simply do not exist
* here (the symmetric floor).
* - **settles mark-to-final-spot** ({@link SpotFillEngine.settle}): a filled lot marks at the
* final spot — `(settleSpot − px)·qty·mult` for a buy, the mirror for a sell — instead of
* intrinsic-at-expiry. Per-lot mark-to-spot **telescopes** for a closed round-trip (the spot
* cancels), so no inventory-netting is needed at the settle seam (ADR-0017).
*
* Pure and injected-time (RUNTIME §0): no wall clock, no RNG. **Same quote sequence ⇒ byte-
* identical events + settle**, the determinism invariant. It emits the same {@link OrderPayload}
* shape as the options engine but WITHOUT `strike`/`right` (both already optional on the bus) —
* a spot instrument has neither, and a fictional strike is never written.
*
*/
import type { NewBusEvent } from "../bus/index.ts";
import type { FillSupport } from "../support/index.ts";
/** A spot instrument's own quote at one moment: a two-sided NBBO plus an optional last trade.
* A missing side is `null` (dark), never zero — a one-sided book never crosses (fail-closed). */
export interface SpotQuote {
readonly bid: number | null;
readonly ask: number | null;
/** The last trade price for this instrument, when one has printed. Read by the strict-cross
* floor's trade-through arm (kestrel-7pq6): a print strictly through a resting limit is as
* definite a price-priority fact as a crossing quote — and on the quote-less derived tapes the
* catalog serves, it is the ONLY fill evidence that exists. */
readonly last?: number;
}
/** A resting spot order handed to {@link SpotFillEngine.place}. No strike/right — a spot leg has
* neither; the instrument alone locates it (ADR-0017). */
export interface SpotFillOrder {
readonly ref: string;
readonly plan?: string;
readonly plan_instance?: string;
readonly instrument: string;
readonly side: "buy" | "sell";
readonly qty: number;
/** The resting limit price. A floor fill always fills at this price. */
readonly px: number;
}
/** One spot order's settle outcome — the floor and the expectation, side by side (RUNTIME §6). */
export interface SpotOrderOutcome {
readonly ref: string;
readonly plan?: string;
readonly plan_instance?: string;
readonly instrument: string;
readonly side: "buy" | "sell";
readonly qty: number;
readonly px: number;
readonly floorFilled: boolean;
readonly floorFillPx: number | null;
readonly expectedFillProb: number;
readonly support: FillSupport;
/** The final spot the lot was marked to (mark-to-market, ADR-0017). */
readonly markSpot: number;
/** Realized $ under the strict-cross floor (0 for an unfilled order): mark-to-spot P&L. */
readonly floorPnl: number;
/** E[$] under `pFill`. */
readonly expectedPnl: number;
}
/** The spot settle report — mark-to-final-spot, with the mark's source provenance (ADR-0017). */
export interface SpotSettleReport {
readonly settleSpot: number;
readonly fillModel: string;
readonly multiplier: number;
readonly outcomes: readonly SpotOrderOutcome[];
readonly floorTotal: number;
readonly expectedTotal: number;
/** The `ts` of the quote/print that set the settle spot (the mark's source watermark). */
readonly markAsOf: number;
/** The settle clock `ts`. */
readonly settleTs: number;
/** `true` when the settle spot's source **predates** the settle instant — a stale mark
* (provenance note, not a gate; related: kestrel-xwf staleness-taint). Applying a staleness
* de-arm is the engine's job downstream; this records that the final mark was not concurrent. */
readonly staleMark: boolean;
}
/**
* The instrument-general floor rule (RUNTIME §6, ADR-0017), two arms under one strictness
* doctrine — a definite price-priority cross, never same-price (`<`/`>`, never `≤`/`≥`):
*
* • QUOTE arm: a resting BUY fills iff the ask is present and **strictly below** the resting
* price; a resting SELL iff the bid is present and **strictly above** it. A dark side
* (`null`) never crosses.
* • TRADE-THROUGH arm (kestrel-7pq6): a resting BUY fills iff a trade printed **strictly
* below** the resting price; a resting SELL iff strictly above. A print AT the limit is
* not a cross — queue position is unknowable, so the conservative floor refuses it. On the
* quote-less derived tapes the catalog serves (`SPOT` prints, no book), this arm is the
* only fill evidence that exists; without it the spot floor was structurally inert.
*
* **Same-price doctrine split vs options (kestrel-0gnb).** This spot arm REFUSES a same-price
* trade print; its options sibling {@link ./model.ts strictCross} instead credits *at-or-through*
* (`≤`/`≥`), because a fresh option-tape print AT the level is a real execution the passive order
* shared, while the quote-less catalog tape here leaves queue position unknowable. Both stamp the
* `strict-cross` judge name, so this spot floor is strictly the more conservative reading of it —
* an option-vs-equity comparison under the shared stamp must key on the arm, not the name.
*
* Pure — the conservative floor a spot strategy must clear. Either arm fills at the resting price.
*/
export declare function spotStrictCross(order: {
side: "buy" | "sell";
px: number;
}, quote: SpotQuote): boolean;
/** Construction options. `multiplier` scales per-share P&L to dollars (default `1` — equity). */
export interface SpotFillEngineOptions {
readonly multiplier?: number;
}
/**
* The spot resting-order state machine. Construct one per book/session; drive it with
* `place` / `cancel` / `onQuote`, then `settle`. Every mutator returns the seq-less
* {@link NewBusEvent}s it produced (the owner BusWriter stamps `seq`), also appended to the
* cumulative {@link events} log. The floor judge only: `pFill ∈ {0, 1}` (strict-cross). A hazard
* ceiling for spot instruments is a later slice; the floor is the honest first cut.
*/
export declare class SpotFillEngine {
#private;
constructor(opts?: SpotFillEngineOptions);
/** The cumulative typed bus events this engine has produced, in order. Read-only. */
get events(): readonly NewBusEvent[];
/** The refs of all currently-resting orders. */
restingRefs(): readonly string[];
/** The latest quote observed for `instrument` via {@link onQuote}, paired with the injected `ts`
* it arrived at — `undefined` until the first quote for that instrument. Read-only; the cockpit
* data-health projects an equity vehicle's liquidity from THIS (the SAME NBBO the strict-cross
* floor and `exec-fair-quote-v1` execute against, {@link ../engine/pricing.ts}), so HEALTH and
* PRICING read one source and never disagree (kestrel-710). Pure — no wall clock. */
currentQuote(instrument: string): {
readonly quote: SpotQuote;
readonly ts: number;
} | undefined;
/** Place a resting order (a re-used ref is refused loudly — fail-closed, RUNTIME §8). Emits a
* `place` ORDER event. */
place(order: SpotFillOrder, ts: number): string;
/** Cancel a resting order, effective immediately. No-op (no event) if not currently resting.
* Returns whether a resting order was removed. */
cancel(ref: string, ts: number): boolean;
/**
* Reassess every resting order on `instrument` against a new two-sided quote. A strict-cross is
* a **floor fill**: the order leaves the book into inventory and a `fill` event is emitted.
* Returns the events produced this call. Causal (RUNTIME §0): an order is eligible only against
* quotes at or after its own placement — a rewound/stale quote can never fill it.
*/
onQuote(instrument: string, quote: SpotQuote, ts: number): readonly NewBusEvent[];
/**
* Cash-settle at the final spot (RUNTIME §6, ADR-0017 mark-to-market): filled inventory marks
* to `settleSpot` — `(settleSpot − px)` for a buy, `(px − settleSpot)` for a sell, ×qty×mult;
* still-resting orders expire worthless-unfilled ($0 floor) and emit a `cancel` annotated
* `expired-unfilled`. `markAsOf` is the `ts` of the print that set `settleSpot`; a mark whose
* source predates `ts` is flagged `staleMark` (a provenance note). Idempotent after the first
* call.
*/
settle(settleSpot: number, ts: number, markAsOf: number): SpotSettleReport;
}
//# sourceMappingURL=spot.d.ts.map