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.
1,222 lines (1,209 loc) • 102 kB
JavaScript
import {
sha256
} from "./bin-8pchjxn2.js";
import {
MS_PER_YEAR,
greeks,
impliedVol
} from "./bin-df1tn094.js";
// src/session/specs.ts
function specFromMeta(si) {
const isOption = si.assetClass === "option-underlier";
return {
symbol: si.symbol,
tickSize: 0.01,
strikeStep: 1,
multiplier: isOption ? 100 : 1,
...si.role !== undefined ? { role: si.role } : {}
};
}
function resolveSpecs(meta, override) {
const specs = override !== undefined ? [...override] : meta.instruments.map(specFromMeta);
if (specs.length === 0)
throw new Error("session: no instruments (fail-closed, RUNTIME §8)");
return specs;
}
function requireMeta(events) {
const meta = events.find((e) => e.stream === "META");
if (meta === undefined) {
throw new Error("session: no META header in bus (a well-formed bus opens with exactly one META, RUNTIME §8)");
}
return meta;
}
// src/frame/types.ts
class KernelHonestyError extends Error {
constructor(message) {
super(message);
this.name = "KernelHonestyError";
}
}
function isHonestConfidence(confidence) {
return confidence >= 0 && confidence <= 1;
}
function makeField(spec) {
const { attribution } = spec;
if (attribution === "MODEL") {
if (spec.source === undefined || spec.source === "") {
throw new KernelHonestyError("MODEL Field carries no source watermark — a MODEL value MUST carry source(modelVer) + confidence");
}
if (spec.modelVer === undefined || spec.modelVer === "") {
throw new KernelHonestyError("MODEL Field carries no modelVer receipt — a MODEL value MUST carry source(modelVer) + confidence");
}
if (spec.confidence === undefined) {
throw new KernelHonestyError("MODEL Field carries no confidence — a MODEL value MUST carry source(modelVer) + confidence");
}
if (!isHonestConfidence(spec.confidence)) {
throw new KernelHonestyError(`MODEL Field carries an out-of-range confidence ${spec.confidence} — MODEL confidence MUST be in [0,1]`);
}
} else {
if (spec.confidence !== undefined) {
throw new KernelHonestyError(`${attribution} Field must carry no confidence`);
}
if (spec.modelVer !== undefined) {
throw new KernelHonestyError(`${attribution} Field must carry no modelVer receipt`);
}
}
const out = { value: spec.value, attribution };
if (spec.source !== undefined)
out.source = spec.source;
if (spec.modelVer !== undefined)
out.modelVer = spec.modelVer;
if (spec.confidence !== undefined)
out.confidence = spec.confidence;
if (spec.asOfSeq !== undefined)
out.asOfSeq = spec.asOfSeq;
return out;
}
function assertClaimHonest(claim) {
const label = claim.claimType;
const f = claim.field;
if (f === undefined || f === null) {
throw new KernelHonestyError(`claim ${label} carries no Field`);
}
if (f.attribution !== "MODEL") {
throw new KernelHonestyError(`claim ${label} is attributed ${f.attribution}, not MODEL — a predictor/regime claim MUST be ` + "a MODEL Field with source + confidence (honesty guard)");
}
if (f.source === undefined || f.source === "") {
throw new KernelHonestyError(`MODEL claim ${label} carries no source watermark`);
}
if (f.modelVer === undefined || f.modelVer === "") {
throw new KernelHonestyError(`MODEL claim ${label} carries no modelVer receipt`);
}
if (f.confidence === undefined) {
throw new KernelHonestyError(`MODEL claim ${label} carries no confidence`);
}
if (!isHonestConfidence(f.confidence)) {
throw new KernelHonestyError(`MODEL claim ${label} carries an out-of-range confidence ${f.confidence} — MODEL confidence MUST be in [0,1]`);
}
}
var KERNEL_LEAD_SENTINEL = "==== SAFETY / CONTROL KERNEL (non-configurable; leads every frame) ====";
var KERNEL_DELTA_SENTINEL = "==== KERNEL DELTA (unlisted fields unchanged) ====";
var KERNEL_SECTION_LABELS = [
"-- WAKE --",
"-- DATA-HEALTH --",
"-- POSITIONS / INVENTORY-CLAIMS --",
"-- RESTING ORDERS --",
"-- BUDGET / REMAINING-R --",
"-- OWNER ENVELOPE + ACTS --",
"-- L0/L1 ENGINE LOG --",
"-- PREDICTOR / REGIME CLAIMS --"
];
var RESERVED_PANE_IDS = ["kernel", "cockpit"];
function assertPaneIdAllowed(paneId) {
const id = paneId.trim().toLowerCase();
if (RESERVED_PANE_IDS.includes(id)) {
throw new KernelHonestyError(`pane id "${paneId}" is reserved for the non-configurable cockpit kernel and cannot be ` + "claimed by a configured pane (fail-closed)");
}
}
// src/frame/brief.ts
function briefHashOf(text) {
return `sha256:${sha256(text)}`;
}
function assertBriefHashHonest(brief) {
const expected = briefHashOf(brief.text);
if (brief.hash !== expected) {
throw new KernelHonestyError(`brief hash mismatch — supplied ${JSON.stringify(brief.hash)} but text hashes to ${JSON.stringify(expected)} ` + "(fail-closed: a Brief's content hash must match its text so provenance attributes the real thesis).");
}
}
// src/frame/format.ts
var DASH = "—";
function px(x) {
if (x === null || x === undefined || !Number.isFinite(x))
return DASH;
return Number.isInteger(x) ? String(x) : x.toFixed(2);
}
function num(x, prec = 2) {
if (x === null || x === undefined || !Number.isFinite(x))
return DASH;
return x.toFixed(prec);
}
function money(x) {
if (x === null || x === undefined || !Number.isFinite(x))
return DASH;
return (x >= 0 ? "+" : "") + x.toFixed(2);
}
function usd(x) {
if (x === null || x === undefined || !Number.isFinite(x))
return DASH;
return (x < 0 ? "-$" : "+$") + Math.abs(x).toFixed(2);
}
function signedInt(n) {
return (n >= 0 ? "+" : "") + String(n);
}
function isSpotLeg(leg) {
return leg.strike === undefined || leg.right === undefined || leg.strike === null || leg.right === null;
}
function toClose(min) {
return `T-${min === null || !Number.isFinite(min) ? DASH : String(Math.round(min))}m to close`;
}
function pad(s, w) {
return s.length >= w ? s : s + " ".repeat(w - s.length);
}
// src/frame/kernel-walk.ts
function walkKernel(kernel, frameKind, sink) {
sink.sentinel(frameKind);
sink.frameLine(frameKind);
if (kernel.mandate !== undefined && kernel.mandate !== null)
sink.mandate(kernel.mandate);
if (kernel.brief !== undefined && kernel.brief !== null)
sink.brief(kernel.brief);
sink.wake(kernel.wake);
sink.dataHealth(kernel.dataHealth ?? [], kernel.unavailable ?? []);
sink.positions(kernel.positions ?? []);
sink.resting(kernel.resting ?? []);
sink.budget(kernel.budgetEnvelope);
sink.ownerActs(kernel.budgetEnvelope, kernel.ownerActs ?? []);
sink.engineLog(kernel.engineLog ?? []);
sink.claims(kernel.claims ?? []);
}
var ENGINE_LOG_BUCKETS = ["fired", "cancelled", "rejected", "clamped"];
function bucketEngineLog(elog) {
const known = new Set(ENGINE_LOG_BUCKETS);
return {
buckets: ENGINE_LOG_BUCKETS.map((kind) => ({ kind, items: elog.filter((e) => e.kind === kind) })),
other: elog.filter((e) => !known.has(e.kind))
};
}
function restingLabel(o, labels) {
const live = o.live === true;
const clamped = o.clamped === true;
if (live)
return clamped ? labels.liveClamped : labels.live;
return clamped ? labels.clamped : labels.off;
}
function actionToken(e, style) {
const reason = e.reason != null && e.reason !== "" ? `${style.reasonSpace ? " " : ""}(${e.reason})` : "";
return `${e.id}@${style.seqPrefix}${e.asofSeq}${reason}`;
}
function collapseActionTokens(items, style) {
const out = [];
for (let i = 0;i < items.length; ) {
const e = items[i];
let j = i + 1;
while (j < items.length && items[j].id === e.id && (items[j].reason ?? null) === (e.reason ?? null))
j++;
const count = j - i;
const token = actionToken(e, style);
out.push(count > 1 ? `${count}x ${token}` : token);
i = j;
}
return out;
}
// src/frame/founder-views.generated.ts
var FOUNDER_VIEWS = {
"strategist-open": { name: "strategist-open", panes: [{ name: "instruments" }, { name: "levels" }, { name: "tape" }, { name: "chain" }, { name: "acting" }] },
"watcher-wake": { name: "watcher-wake", panes: [{ name: "delta" }, { name: "tape" }, { name: "levels" }, { name: "chain" }, { name: "acting" }] },
"scan-fire": { name: "scan-fire", panes: [{ name: "levels" }, { name: "series-summary" }, { name: "prior-context" }, { name: "tape", args: [{ kind: "arg-window", window: { value: 5, unit: "m" } }] }] }
};
// src/frame/founder-registry.ts
var FOUNDER_VIEW_NAME_BY_SEAT_FRAME = {
"strategist/OPEN": "strategist-open",
"watcher/WAKE": "watcher-wake",
"pm/WAKE": "scan-fire"
};
function founderViewFor(seat, frameKind) {
const name = FOUNDER_VIEW_NAME_BY_SEAT_FRAME[`${seat}/${frameKind}`];
if (name === undefined)
return;
const view = FOUNDER_VIEWS[name];
if (view === undefined) {
throw new Error(`founder registry maps ${seat}/${frameKind} → "${name}", but that View is absent from the generated FOUNDER_VIEWS ` + `(regenerate: bun scripts/gen-founder-view-registry.ts). This is registry/golden drift, never honest absence.`);
}
return view;
}
var FOUNDER_SEED_KEYS = Object.keys(FOUNDER_VIEW_NAME_BY_SEAT_FRAME);
// src/frame/session-scheme.ts
var SESSION_SCHEMES = [
"equity-rth",
"cme-rth-overnight",
"perp-utc-day",
"fx-week"
];
var DEFAULT_SESSION_SCHEME = "equity-rth";
var SESSION_SCHEME_BOUNDARIES = {
"equity-rth": { open: true, close: true, sessionSplit: false },
"cme-rth-overnight": { open: true, close: true, sessionSplit: true },
"perp-utc-day": { open: false, close: false, sessionSplit: false, rollingAnchor: "rolling 24h extreme" },
"fx-week": { open: true, close: true, sessionSplit: true }
};
function isSessionScheme(s) {
return SESSION_SCHEMES.includes(s);
}
function unknownSchemeRefusal(served) {
return new KernelHonestyError(`SessionScheme "${served}" is not in the closed roster {${SESSION_SCHEMES.join(", ")}} — a ` + `series-registry attribute must name a DECLARED scheme (each carries its own boundary stream). ` + `Judgment REFUSED (fail-closed, never a silent equity-rth default): an undeclared scheme has no ` + `open/close/session-split declaration, so its boundaries cannot be honestly rendered. Add the ` + `scheme + its SchemeBoundaries to open the roster, or correct the value (ADR-0041 §1/§3).`);
}
function resolveScheme(scheme) {
if (scheme === undefined || scheme === null)
return DEFAULT_SESSION_SCHEME;
if (!isSessionScheme(scheme))
throw unknownSchemeRefusal(scheme);
return scheme;
}
function schemeHasBoundary(scheme, kind) {
const b = SESSION_SCHEME_BOUNDARIES[scheme];
return kind === "open" ? b.open : kind === "close" ? b.close : b.sessionSplit;
}
function rollingAnchorOf(scheme) {
return SESSION_SCHEME_BOUNDARIES[scheme].rollingAnchor;
}
// src/frame/paradigm-ledger.ts
var ATTESTED_CELLS = [
{ pane: "levels", sort: "LevelName", state: "ATTESTED", form: "levels vwap hod" },
{ pane: "tape", sort: "Window", state: "ATTESTED", form: "tape 5m" },
{ pane: "chain", sort: "Count", state: "ATTESTED", form: "chain 12" },
{ pane: "tape", sort: "SessionOrdinal", state: "ATTESTED", form: "tape d-0" },
{ pane: "chain", sort: "ExpiryOrdinal", state: "ATTESTED", form: "chain e-0" }
];
var LATENT_CELLS = [
{
pane: "chain",
sort: "Instrument",
state: "LATENT",
train: "chain Instrument (cross-instrument leg source) — a LATER train, NOT Train 1B (ADR-0041 §1: the " + "marked cross-instrument read is a CALC lexeme taking two Instrument args; Train 1A added Count, " + "Train 1B added ExpiryOrdinal, neither added Instrument)"
}
];
var DEFECTIVE_CELLS = [];
var DEFECTIVE_FIRST_ARRIVAL = "No UNCONDITIONED (pane × sort) cell is DEFECTIVE. The first production DEFECTIVE is " + "SCHEME-CONDITIONED and LANDED with kestrel-wa0j.44 (prior-context × SessionOrdinal under a " + "SessionScheme with no close boundary: reason 'no close under this SessionScheme', periphrasis " + "'anchor to the declared rolling extreme' — see schemeConditioned). A further DEFECTIVE source " + "arrives with kestrel-wa0j.42 (social/sentiment — no as-of source, determinism unachievable at the feed).";
var PANE_BOUNDARY_REQUIREMENT = {
"prior-context": "close",
tape: "close"
};
var CONDITIONED_SORT = "SessionOrdinal";
function conditionedReason(kind) {
return `no ${kind} under this SessionScheme`;
}
var CONDITIONED_PERIPHRASIS = "anchor to the declared rolling extreme";
function schemeConditionedDefect(pane, scheme) {
const req = PANE_BOUNDARY_REQUIREMENT[pane];
if (req === undefined)
return;
if (schemeHasBoundary(scheme, req))
return;
return {
pane,
sort: CONDITIONED_SORT,
state: "DEFECTIVE",
reason: conditionedReason(req),
periphrasis: CONDITIONED_PERIPHRASIS,
conditioning: { sessionScheme: scheme }
};
}
var SCHEME_CONDITIONED_CELLS = Object.keys(PANE_BOUNDARY_REQUIREMENT).flatMap((pane) => SESSION_SCHEMES.map((scheme) => schemeConditionedDefect(pane, scheme))).filter((c) => c !== undefined);
var PARADIGM_CELLS = [...ATTESTED_CELLS, ...LATENT_CELLS, ...DEFECTIVE_CELLS];
var DESTINATION_BACKLOG = {
macro: "macro period/context sub-selectors (a later train — outside Train 1A/1B)",
vol: "vol straddle / expected-move sub-selectors (a later train)",
tape: "multi-arg tape — style/overlay/strip position classes (deferred; Train 1A migrated the Window arg, Train 1B added the SessionOrdinal address — style/overlay/strip remain LATENT)",
levels: "named / band-keyed level-set idents (e.g. `registry`) — deferred; Train 1A serves individual-level idents only",
chain: "chain sub-selectors (fair/realness) + Instrument — deferred to a LATER train (Train 1A added Count, Train 1B added ExpiryOrdinal; Instrument + fair/realness sub-selectors remain LATENT)"
};
function latentTrainFor(pane) {
return DESTINATION_BACKLOG[pane];
}
// src/frame/refusals.ts
function argStr(a) {
if (a.kind === "arg-ident")
return a.name;
if (a.kind === "arg-count")
return `${a.count}`;
if (a.kind === "arg-ordinal")
return `d-${a.ordinal}`;
if (a.kind === "arg-expiry")
return `e-${a.expiry}`;
return `${a.window.value}${a.window.unit}`;
}
function argsStr(args) {
return args.map(argStr).join(" ");
}
function syntacticSupersort(a) {
switch (a.kind) {
case "arg-ident":
return "ident";
case "arg-count":
return "numeral";
case "arg-ordinal":
return "ordinal";
case "arg-expiry":
return "expiry";
case "arg-window":
return "window";
}
}
var SORT_ACCEPTS = {
Instrument: "ident",
LevelName: "ident",
Window: "window",
Count: "numeral",
SessionOrdinal: "ordinal",
ExpiryOrdinal: "expiry"
};
function supersortPhrase(s) {
switch (s) {
case "ident":
return "a bare ident";
case "window":
return "a window (a numeral + a time unit, e.g. `5m`)";
case "numeral":
return "a bare count numeral (e.g. `12`)";
case "ordinal":
return "a session ordinal (`d-<n>`, e.g. `d-0`)";
case "expiry":
return "an expiry ordinal (`e-<n>`, e.g. `e-0`)";
}
}
function slotSpecOf(slots) {
return slots.map((s) => `${s.name}:${s.sort}${s.arity === "many" ? "…" : ""}`).join(", ");
}
function paneRefusal(r) {
return new KernelHonestyError(refusalMessage(r));
}
function refusalMessage(r) {
switch (r.kind) {
case "unknown-pane":
return `View "${r.view}" names pane "${r.pane}", which is NOT in the pane catalog — the pane cannot ` + `render (single-source: a View selects only catalogued panes). Known panes: ` + `${r.known.join(", ")} (fail-closed, never a silent drop).`;
case "takes-no-args":
return `View "${r.view}" passes arg${r.args.length === 1 ? "" : "s"} "${argsStr(r.args)}" ` + `to pane "${r.pane}", which takes no arguments — an arg a pane does not understand is refused ` + `(fail-closed, never silently ignored).`;
case "no-signature":
return `pane "${r.pane}" received arg${r.args.length === 1 ? "" : "s"} "${argsStr(r.args)}" but declares ` + `no ParamSlot signature — cannot elaborate its args (fail-closed at the \`mat\` rung; a catalog defect).`;
case "arity":
return `pane "${r.pane}" was served ${r.args.length} arg${r.args.length === 1 ? "" : "s"} "${argsStr(r.args)}" ` + `but its signature binds only [${slotSpecOf(r.slots)}] — too many arguments. Judgment REFUSED at the \`mat\` rung ` + `(materializable: an argument must elaborate at its slot's sort and arity, ADR-0041 §3; fail-closed, never silently dropped).`;
case "sort-mismatch": {
const want = SORT_ACCEPTS[r.slot.sort];
const got = syntacticSupersort(r.arg);
return `pane "${r.pane}" · slot "${r.slot.name}" (sort ${r.slot.sort}): expected ${supersortPhrase(want)} but was served ` + `${supersortPhrase(got)} "${argStr(r.arg)}". Judgment REFUSED at the \`mat\` rung (materializable: an argument ` + `must elaborate at its slot's sort, ADR-0041 §3; fail-closed, never a silent coercion).`;
}
case "count-not-integer":
return `pane "${r.pane}" · slot "${r.slot.name}" (sort Count): a Count must be a positive integer, got "${argStr(r.arg)}". ` + `Judgment REFUSED at the \`mat\` rung (a cardinal names N nearest-money addresses; fail-closed, never a fractional count).`;
case "ordinal-not-nonneg-integer":
return `pane "${r.pane}" · slot "${r.slot.name}" (sort ${r.slot.sort}): an ordinal must be a non-negative integer, got "${argStr(r.arg)}". ` + `Judgment REFUSED at the \`mat\` rung (a ${r.slot.sort} names an ordinal into the declared boundary stream — ` + `${r.slot.sort === "SessionOrdinal" ? "d-0 the current session, d-1 the prior" : "e-0 the nearest expiry, e-1 the next out"}; ` + `fail-closed, never a fractional or negative ordinal).`;
case "window-not-servable":
return `pane "${r.pane}" cannot serve window arg "${argStr(r.arg)}": the tape rows are served pre-bucketed at ` + `${r.servedBucketMin}m — a renderable window must be a multiple of the served ${r.servedBucketMin}m (a sub-resolution or ` + `non-multiple window cannot be expressed by these rows; rendering them under a "${argStr(r.arg)}" ` + `label would misstate the scale — fail-closed, never mismatched data as if requested).`;
case "unknown-value-naming-roster":
return `pane "${r.pane}" · slot "${r.slot}": "${r.value}" is not a known level — the levels roster is ` + `{${r.roster.join(", ")}}. Judgment REFUSED (an ident must name a cell the LevelSet carries; ` + `fail-closed, never a silent drop). Cell state: a named level-SET like \`registry\` is LATENT — the ` + `band-keyed level-set inflection (a later train), NOT Train 1A's individual-level idents (ADR-0041 §3).`;
case "latent-cell": {
const train = latentTrainFor(r.pane);
const named = train ?? "(no train recorded in the ledger — a ledger gap, fail-closed)";
return `pane "${r.pane}" · form "${r.form}": the paradigm cell is LATENT — not yet materializable, but a ` + `named train will land it. Deferred train: ${named}. Judgment REFUSED at the \`mat\` rung ` + `(ADR-0041 §3: a LATENT refusal names its train; fail-closed, never a silent drop).`;
}
case "defective-cell": {
const cond = r.conditioning !== undefined ? ` (conditioned on ${r.conditioning})` : "";
return `pane "${r.pane}" · form "${r.form}": the paradigm cell is DEFECTIVE — it never materializes${cond}. ` + `Written reason: ${r.reason}. Sanctioned periphrasis: ${r.periphrasis}. Judgment REFUSED ` + `(ADR-0041 §3: a DEFECTIVE refusal names its written reason + its sanctioned periphrasis; ` + `absent-not-hidden — the address has no value under this paradigm, and the periphrasis renders in its place, never an invented one).`;
}
case "over-budget":
return `View "${r.view}" is over its token budget: the selected panes (${r.paneIds.join(", ")}) ` + `measured ${r.spent} tokens under tokenizer "${r.tokenizer}", exceeding the budget of ${r.budget}. ` + "Refusing to render a View that does not fit its own budget (fail-closed — trim the View or raise its budget; " + "the non-configurable kernel is not counted against the View budget).";
case "unreachable-bound-arg":
return `pane "${r.pane}" expected ${r.expected} but was reached with "${argsStr(r.args)}" (fail-closed).`;
case "unreachable-not-catalogued":
return `pane "${r.pane}" is not in the catalog — cannot materialize (fail-closed).`;
case "unreachable-args-on-argless":
return `pane "${r.pane}" takes no arguments but was resolved with "${argsStr(r.args)}" ` + `— cannot materialize (fail-closed).`;
}
}
// src/frame/options-analytics.ts
function legKey(expiry, strike, right) {
return `${expiry}:${strike}:${right}`;
}
function reduceOptionSurface(events, throughSeq) {
const legs = new Map;
let underlier = "";
let spot = null;
let spotTs = null;
let cutoffSeq = -1;
let cutoffTs = 0;
for (const e of events) {
if (throughSeq !== undefined && e.seq > throughSeq)
break;
cutoffSeq = e.seq;
cutoffTs = e.ts;
if (e.stream !== "TICK")
continue;
if (e.type === "SPOT") {
spot = e.px;
spotTs = e.ts;
if (underlier === "")
underlier = e.instrument;
} else if (e.type === "BOOK") {
const expiry = e.expiry ?? "";
if (underlier === "")
underlier = e.instrument;
for (const l of e.legs) {
legs.set(legKey(expiry, l.strike, l.right), {
expiry,
strike: l.strike,
right: l.right,
bid: l.bid,
ask: l.ask
});
}
}
}
return { underlier, legs, spot, spotTs, cutoffSeq, cutoffTs };
}
var SPOT_STALE_AFTER_MS = 120000;
function liquidMid(bid, ask) {
if (bid === null || ask === null)
return null;
const mid = 0.5 * (bid + ask);
return mid > 0 ? mid : null;
}
function daysBetween(fromTs, toTs) {
return Math.max(0, Math.floor((toTs - fromTs) / 86400000));
}
function buildOptionsAnalytics(surface, config) {
const multiplier = config.multiplier ?? 100;
const rate = config.rate ?? 0;
const staleMs = config.staleMs ?? SPOT_STALE_AFTER_MS;
const { spot, spotTs, cutoffTs, cutoffSeq } = surface;
const spotStaleSeconds = spotTs === null ? null : Math.max(0, Math.floor((cutoffTs - spotTs) / 1000));
const spotStale = spot === null || spotTs === null || cutoffTs - spotTs > staleMs;
const byExpiry = new Map;
for (const l of surface.legs.values()) {
const arr = byExpiry.get(l.expiry) ?? [];
arr.push({ strike: l.strike, right: l.right, bid: l.bid, ask: l.ask });
byExpiry.set(l.expiry, arr);
}
const expiries = [];
for (const [expiry, rawLegs] of byExpiry) {
const closeTs = config.expiryCloseTs.get(expiry);
const tauYears = closeTs === undefined ? null : Math.max(0, (closeTs - cutoffTs) / MS_PER_YEAR);
const daysToExpiry = closeTs === undefined ? null : daysBetween(cutoffTs, closeTs);
const legs = rawLegs.map((r) => {
const mid = liquidMid(r.bid, r.ask);
const oi = config.openInterest?.get(legKey(expiry, r.strike, r.right)) ?? null;
let iv = null;
let delta = null;
let gamma = null;
let vega = null;
if (mid !== null && spot !== null && !spotStale && tauYears !== null && tauYears > 0) {
iv = impliedVol({ forward: spot, strike: r.strike, tauYears, price: mid, right: r.right });
if (iv !== null) {
const g = greeks({ forward: spot, strike: r.strike, tauYears, sigma: iv, right: r.right });
delta = g.delta;
gamma = g.gamma;
vega = g.vega;
}
}
return { strike: r.strike, right: r.right, bid: r.bid, ask: r.ask, mid, iv, delta, gamma, vega, oi };
}).sort((a, b) => a.strike - b.strike || (a.right < b.right ? -1 : a.right > b.right ? 1 : 0));
expiries.push({ expiry, tauYears, daysToExpiry, legs });
}
expiries.sort((a, b) => {
const ca = config.expiryCloseTs.get(a.expiry);
const cb = config.expiryCloseTs.get(b.expiry);
if (ca === undefined && cb === undefined)
return a.expiry < b.expiry ? -1 : 1;
if (ca === undefined)
return 1;
if (cb === undefined)
return -1;
return ca - cb;
});
const method = `Black-Scholes r=${rate}; tau=(expiry-close − cutoff)/365d; IV from two-sided NBBO mid`;
return {
underlier: surface.underlier,
spot,
spotStale,
spotStaleSeconds,
asOfSeq: cutoffSeq,
multiplier,
rate,
method,
expiries
};
}
// src/frame/tape-geometry.ts
var TAPE_WIDTH = 40;
function tapeBounds(rows) {
let lo = Infinity;
let hi = -Infinity;
for (const r of rows) {
lo = Math.min(lo, r.low, r.open, r.close);
hi = Math.max(hi, r.high, r.open, r.close);
}
return { lo, hi };
}
function candleLine(row, lo, hi, width = TAPE_WIDTH) {
const span = hi - lo;
const colOf = (p) => {
if (span <= 0)
return 0;
const c = Math.round((p - lo) / span * (width - 1));
return c < 0 ? 0 : c > width - 1 ? width - 1 : c;
};
const loCol = colOf(row.low);
const hiCol = colOf(row.high);
const bodyLo = Math.min(colOf(row.open), colOf(row.close));
const bodyHi = Math.max(colOf(row.open), colOf(row.close));
const cells = Array(width).fill(" ");
for (let c = loCol;c <= hiCol; c += 1)
cells[c] = "─";
for (let c = bodyLo;c <= bodyHi; c += 1)
cells[c] = "█";
cells[bodyLo] = "█";
return cells.join("").replace(/\s+$/, "");
}
// src/frame/pane-catalog.ts
function renderInstruments(instruments) {
if (instruments.length === 0)
return `instruments:
(none)`;
const lines = instruments.map((i) => {
const role = i.role !== undefined ? ` ${i.role}` : "";
const mult = `mult ${px(i.multiplier)}`;
const tick = `tick ${px(i.tick)}`;
return ` ${i.symbol} ${i.assetClass}${role} ${mult} ${tick}`;
});
return ["instruments:", ...lines].join(`
`);
}
function spotCell(lv) {
const age = lv.spotStaleSeconds;
if (age === undefined || age === null || age * 1000 <= SPOT_STALE_AFTER_MS)
return `spot ${px(lv.spot)}`;
return `spot ${px(lv.spot)} [STALE ${Math.round(age / 60)}m]`;
}
function renderLevels(instrument, lv) {
const parts = [
spotCell(lv),
`prior_close ${px(lv.priorClose)}`,
`hod ${px(lv.hod)}`,
`lod ${px(lv.lod)}`,
`vwap ${px(lv.vwap)}`,
`or ${px(lv.orLow)}–${px(lv.orHigh)}`
];
return `levels · ${instrument}
${parts.join(" · ")}`;
}
var LEVEL_ROSTER = ["spot", "prior_close", "hod", "lod", "vwap", "or"];
function levelCell(name, lv) {
switch (name) {
case "spot":
return spotCell(lv);
case "prior_close":
return `prior_close ${px(lv.priorClose)}`;
case "hod":
return `hod ${px(lv.hod)}`;
case "lod":
return `lod ${px(lv.lod)}`;
case "vwap":
return `vwap ${px(lv.vwap)}`;
case "or":
return `or ${px(lv.orLow)}–${px(lv.orHigh)}`;
}
}
function renderLevelsWithArgs(ctx, args) {
const lv = ctx.market.levels;
const cells = [];
for (const a of args) {
if (a.kind !== "arg-ident") {
throw paneRefusal({ kind: "unreachable-bound-arg", pane: "levels", expected: "bound LevelName idents", args: [a] });
}
if (!LEVEL_ROSTER.includes(a.name)) {
throw paneRefusal({ kind: "unknown-value-naming-roster", pane: "levels", slot: "level-set", value: a.name, roster: LEVEL_ROSTER });
}
cells.push(levelCell(a.name, lv));
}
return `levels · ${ctx.market.instrument}
${cells.join(" · ")}`;
}
function renderTape(rows, bucketMin, sessionTag) {
const tag = sessionTag !== undefined ? ` · ${sessionTag}` : "";
if (rows.length === 0) {
return [`tape ${bucketMin}m${tag} · (no prints this window)`].join(`
`);
}
const { lo, hi } = tapeBounds(rows);
const anchorClock = rows[0].clock;
const header = `tape ${bucketMin}m${tag} · axis ${px(lo)}→${px(hi)} · anchor @ ${anchorClock} ET`;
const body = rows.map((r) => `${r.clock} ${candleLine(r, lo, hi)}`);
return [header, ...body].join(`
`);
}
function rebucketTape(rows, factor) {
const out = [];
for (let i = 0;i < rows.length; i += factor) {
const run = rows.slice(i, i + factor);
const first = run[0];
const last = run[run.length - 1];
let high = -Infinity;
let low = Infinity;
let volume = 0;
let allVolumed = true;
for (const r of run) {
if (r.high > high)
high = r.high;
if (r.low < low)
low = r.low;
if (r.volume === null || r.volume === undefined || !Number.isFinite(r.volume))
allVolumed = false;
else
volume += r.volume;
}
out.push({
clock: last.clock,
open: first.open,
high,
low,
close: last.close,
...allVolumed ? { volume } : {}
});
}
return out;
}
function windowServableBy(bucketMin, window) {
const w = windowMinutes(window);
if (w === null || !Number.isFinite(bucketMin) || bucketMin <= 0)
return false;
const factor = w / bucketMin;
return Number.isInteger(factor) && factor >= 1;
}
function renderTapeWithArgs(ctx, args) {
const windowArg = args.find((a) => a.kind === "arg-window");
const sessionArg = args.find((a) => a.kind === "arg-ordinal");
if (sessionArg !== undefined && sessionArg.ordinal >= 1) {
return renderTapePriorSession(ctx, sessionArg.ordinal, windowArg);
}
const available = ctx.market.tapeBucketMin;
if (windowArg === undefined)
return renderTape(ctx.market.tape, available);
const requested = windowMinutes(windowArg.window);
if (requested === null || !windowServableBy(available, windowArg.window)) {
throw paneRefusal({ kind: "window-not-servable", pane: "tape", arg: windowArg, servedBucketMin: available });
}
const factor = requested / available;
if (factor === 1)
return renderTape(ctx.market.tape, requested);
return renderTape(rebucketTape(ctx.market.tape, factor), requested);
}
function renderTapePriorSession(ctx, ordinal, windowArg) {
const scheme = schemeOfMarket(ctx);
const label = windowArg !== undefined ? ` ${windowArg.window.value}${windowArg.window.unit}` : "";
const addr = `d-${ordinal}`;
const head = `tape${label} · ${ctx.market.instrument} · ${addr}`;
const defect = schemeConditionedDefect("tape", scheme);
if (defect !== undefined) {
const anchor = rollingAnchorOf(scheme) ?? "rolling extreme";
return `${head} · (${defect.reason} (${scheme}) — no prior-session address under this SessionScheme; ${defect.periphrasis}: ${anchor})`;
}
const carried = ctx.priorSessions?.find((s) => s.ordinal === ordinal);
if (carried !== undefined && carried.rows.length > 0) {
return renderPriorSessionBlock(ctx, carried, ordinal, windowArg);
}
return `${head} · (frozen frame carries no session at ${addr} — the current session only; multiday tape data threads with kestrel-wa0j.20)`;
}
function renderPriorSessionBlock(ctx, session, ordinal, windowArg) {
const available = ctx.market.tapeBucketMin;
const tag = session.sessionLabel !== undefined ? `d-${ordinal} (${session.sessionLabel})` : `d-${ordinal}`;
if (windowArg === undefined)
return renderTape(session.rows, available, tag);
const requested = windowMinutes(windowArg.window);
if (requested === null || !windowServableBy(available, windowArg.window)) {
throw paneRefusal({ kind: "window-not-servable", pane: "tape", arg: windowArg, servedBucketMin: available });
}
const factor = requested / available;
if (factor === 1)
return renderTape(session.rows, requested, tag);
return renderTape(rebucketTape(session.rows, factor), requested, tag);
}
function darkFlag(row) {
const bidDark = row.bid === null;
const askDark = row.ask === null;
if (bidDark && askDark)
return "dark";
if (bidDark)
return "bid dark";
if (askDark)
return "ask dark";
return DASH;
}
function renderChain(underlier, chain, dte) {
const dteTag = dte !== undefined && dte !== null && Number.isFinite(dte) ? ` · ${dte}dte` : "";
if (chain.length === 0) {
return `chain (near-money) · ${underlier}${dteTag}
(no legs)`;
}
const head = ` ${pad("strike", 8)}${pad("R", 3)}${pad("bid", 8)}${pad("ask", 8)}${pad("fair", 10)}flags`;
const lines = chain.map((r) => {
const fair = r.fairNote !== undefined && r.fair !== null && r.fair !== undefined ? `${px(r.fair)} ${r.fairNote}` : px(r.fair);
const fairCell = pad(fair, Math.max(10, fair.length + 2));
return ` ${pad(px(r.strike), 8)}${pad(r.right, 3)}${pad(px(r.bid), 8)}${pad(px(r.ask), 8)}${fairCell}${darkFlag(r)}`;
});
return [`chain (near-money) · ${underlier}${dteTag}`, head, ...lines].join(`
`);
}
function selectNearMoneyStrikes(chain, n) {
const seen = new Set;
const ordered = [];
for (const r of chain) {
if (!seen.has(r.strike)) {
seen.add(r.strike);
ordered.push(r.strike);
}
}
const keep = new Set(ordered.slice(0, n));
return { rows: chain.filter((r) => keep.has(r.strike)), availableStrikes: ordered.length };
}
function renderChainWithArgs(ctx, args) {
const countArg = args.find((a) => a.kind === "arg-count");
const expiryArg = args.find((a) => a.kind === "arg-expiry");
if (expiryArg !== undefined && expiryArg.expiry >= 1) {
return renderChainFurtherExpiry(ctx, expiryArg.expiry, countArg);
}
if (countArg === undefined) {
return renderChain(ctx.market.instrument, ctx.market.chain, ctx.market.chainDte);
}
const n = countArg.count;
const { rows, availableStrikes } = selectNearMoneyStrikes(ctx.market.chain, n);
const base = renderChain(ctx.market.instrument, rows, ctx.market.chainDte);
if (availableStrikes >= n)
return base;
const missing = n - availableStrikes;
const shortfall = ` (requested ${n} near-money strikes; ${availableStrikes} available — ${missing} absent with reason: ` + `the frozen near-money chain carries only ${availableStrikes} strike${availableStrikes === 1 ? "" : "s"})`;
return `${base}
${shortfall}`;
}
function renderChainFurtherExpiry(ctx, expiry, countArg) {
const countLabel = countArg !== undefined ? ` ${countArg.count}` : "";
const addr = `e-${expiry}`;
return `chain (near-money)${countLabel} · ${ctx.market.instrument} · ${addr} · ` + `(frozen chain carries no expiry at ${addr} — the nearest expiry only; multi-expiry chain data threads with kestrel-wa0j.20)`;
}
var MACRO_PANE = "macro: unavailable (v1 harness)";
function planTag(plan) {
return plan === undefined ? "" : ` (${plan})`;
}
function renderPositions(positions) {
if (positions.length === 0)
return `positions:
(none)`;
const lines = positions.map((p) => isSpotLeg(p) ? ` ${signedInt(p.qty)} ${p.instrument} shares basis ${px(p.basis)}${unrealTag(p)}${planTag(p.plan)}` : ` ${signedInt(p.qty)} ${p.instrument} ${px(p.strike)}${p.right} basis ${px(p.basis)} fair ${px(p.fair)}${unrealTag(p)}${planTag(p.plan)}`);
return ["positions:", ...lines].join(`
`);
}
function unrealTag(p) {
return p.unrealUsd === undefined ? "" : ` unreal ${usd(p.unrealUsd)}`;
}
function renderResting(resting) {
if (resting.length === 0)
return `resting:
(none)`;
const lines = resting.map((o) => {
const note = o.note !== undefined ? ` [${o.note}]` : "";
const leg = isSpotLeg(o) ? "shares" : `${px(o.strike)}${o.right}`;
return ` ${o.side.toUpperCase()} ${o.qty} ${o.instrument} ${leg} @ ${px(o.px)}${note}${planTag(o.plan)}`;
});
return ["resting:", ...lines].join(`
`);
}
function renderFills(fills) {
if (fills.length === 0)
return `fills since last:
(none)`;
const lines = fills.map((f) => {
const at = f.clock !== undefined ? ` @${f.clock}` : "";
const leg = isSpotLeg(f) ? "shares" : `${px(f.strike)}${f.right}`;
return ` ${f.side.toUpperCase()} ${f.qty} ${f.instrument} ${leg} @ ${px(f.px)}${at}${planTag(f.plan)}`;
});
return ["fills since last:", ...lines].join(`
`);
}
function renderBudget(budget) {
if (budget === null || budget === undefined)
return `premium budget: ${DASH}`;
const total = budget.total !== undefined ? ` (total ${px(budget.total)}` : "";
const maxR = budget.maxConcurrentR !== undefined ? `, maxR ${px(budget.maxConcurrentR)})` : total !== "" ? ")" : "";
return `premium budget: used ${money(budget.used)} / remaining ${money(budget.remaining)}${total}${maxR}`;
}
function renderPlans(kernel) {
if (kernel.plans.length === 0)
return `plans:
(none)`;
const lines = kernel.plans.map((p) => {
const outcome = p.outcome !== undefined ? `(${p.outcome})` : "";
const blocked = p.blockedReason !== undefined ? ` (blocked: ${p.blockedReason})` : "";
const note = p.note !== undefined ? ` — ${p.note}` : "";
return ` ${p.name}: ${p.state}${outcome === "" ? "" : " " + outcome}${blocked}${note}`;
});
return ["plans:", ...lines].join(`
`);
}
function renderActingDetail(kernel) {
return [
"KERNEL (acting)",
renderPositions(kernel.positions),
renderResting(kernel.resting),
renderFills(kernel.fillsSinceLast),
renderBudget(kernel.budget),
renderPlans(kernel)
].join(`
`);
}
function pokesForLevel(rows, level, dir) {
const pierces = (r) => dir === "up" ? r.high > level : r.low < level;
const pastBy = (p) => dir === "up" ? p - level : level - p;
const pokes = [];
const n = rows.length;
let i = 0;
while (i < n) {
if (!pierces(rows[i])) {
i += 1;
continue;
}
let j = i;
let excursion = 0;
while (j < n && pierces(rows[j])) {
const r = rows[j];
const ex = pastBy(dir === "up" ? r.high : r.low);
if (ex > excursion)
excursion = ex;
j += 1;
}
const reachesEnd = j === n;
const lastClose = rows[j - 1].close;
const held = reachesEnd && (dir === "up" ? lastClose > level : lastClose < level);
pokes.push({ excursion, bars: j - i, held });
i = j;
}
return pokes;
}
function failedBreakLine(rows, lv) {
if (lv.value === null || lv.value === undefined || !Number.isFinite(lv.value)) {
return { line: ` ${lv.label} ${DASH}: level unknown`, failed: 0 };
}
const pokes = pokesForLevel(rows, lv.value, lv.dir);
const probed = pokes.length;
const held = pokes.filter((p) => p.held).length;
const failedPokes = pokes.filter((p) => !p.held);
const failed = failedPokes.length;
const head = ` ${lv.label} ${px(lv.value)}: probed ${probed}×`;
if (probed === 0)
return { line: head, failed: 0 };
const detail = `${head} · held ${held}× · failed ${failed}×`;
if (failed === 0)
return { line: `${detail} · clean break (held)`, failed: 0 };
const maxExc = failedPokes.reduce((m, p) => p.excursion > m ? p.excursion : m, 0);
const longest = failedPokes.reduce((m, p) => p.bars > m ? p.bars : m, 0);
return {
line: `${detail} · max excursion ${num(maxExc, 2)} · longest ${longest} bar${longest === 1 ? "" : "s"}`,
failed
};
}
function renderFailedBreaks(market) {
const lv = market.levels;
const levels = [
{ label: "hod", value: lv.hod, dir: "up" },
{ label: "lod", value: lv.lod, dir: "down" },
{ label: "orHigh", value: lv.orHigh, dir: "up" },
{ label: "orLow", value: lv.orLow, dir: "down" }
];
if (market.tape.length === 0) {
return `failed-breaks · ${market.instrument} · (no prints this window)`;
}
const built = levels.map((l) => failedBreakLine(market.tape, l));
const total = built.reduce((s, b) => s + b.failed, 0);
const header = `failed-breaks · ${market.instrument} · ${total} failed this session`;
return [header, ...built.map((b) => b.line)].join(`
`);
}
function pastSplit(r, level, dir) {
const bodyHi = Math.max(r.open, r.close);
const bodyLo = Math.min(r.open, r.close);
if (dir === "up") {
const body2 = Math.max(0, bodyHi - level);
const wick2 = r.high - Math.max(bodyHi, level);
return { wick: wick2, body: body2 };
}
const body = Math.max(0, level - bodyLo);
const wick = Math.min(bodyLo, level) - r.low;
return { wick, body };
}
function breakInteractionLine(rows, lv) {
if (lv.value === null || lv.value === undefined || !Number.isFinite(lv.value)) {
return ` ${lv.label} ${DASH}: level unknown`;
}
const level = lv.value;
const touches = rows.filter((r) => r.low <= level && level <= r.high);
if (touches.length === 0)
return ` ${lv.label} ${px(level)}: no touch`;
const last = touches[touches.length - 1];
const broke = lv.dir === "up" ? last.close > level : last.close < level;
const verb = broke ? "broke (body through)" : "rejected (wick, closed inside)";
const { wick, body } = pastSplit(last, level, lv.dir);
const wickLabel = lv.dir === "up" ? "upper-wick" : "lower-wick";
return ` ${lv.label} ${px(level)}: ${touches.length} touch${touches.length === 1 ? "" : "es"} · ${verb} · ${wickLabel} ${num(wick, 2)} / body ${num(body, 2)}`;
}
function vwapInteractionLine(rows, vwap) {
if (vwap === null || vwap === undefined || !Number.isFinite(vwap)) {
return ` vwap ${DASH}: level unknown`;
}
const touches = rows.filter((r) => r.low <= vwap && vwap <= r.high);
if (touches.length === 0)
return ` vwap ${px(vwap)}: no touch`;
const last = touches[touches.length - 1];
const side = last.close > vwap ? "closed above (reclaim)" : last.close < vwap ? "closed below (loss)" : "closed at vwap";
const up = last.high - vwap;
const down = vwap - last.low;
return ` vwap ${px(vwap)}: ${touches.length} touch${touches.length === 1 ? "" : "es"} · ${side} · reach up ${num(up, 2)} / down ${num(down, 2)}`;
}
function renderLevelInteraction(market) {
const lv = market.levels;
if (market.tape.length === 0) {
return `level-interaction · ${market.instrument} · (no prints this window)`;
}
const breakLevels = [
{ label: "hod", value: lv.hod, dir: "up" },
{ label: "lod", value: lv.lod, dir: "down" },
{ label: "orHigh", value: lv.orHigh, dir: "up" },
{ label: "orLow", value: lv.orLow, dir: "down" }
];
const lines = [
breakInteractionLine(market.tape, breakLevels[0]),
breakInteractionLine(market.tape, breakLevels[1]),
vwapInteractionLine(market.tape, lv.vwap),
breakInteractionLine(market.tape, breakLevels[2]),
breakInteractionLine(market.tape, breakLevels[3])
];
return [`level-interaction · ${market.instrument}`, ...lines].join(`
`);
}
function p99NearestRank(sample) {
const sorted = [...sample].sort((a, b) => a - b);
const rank = Math.max(1, Math.ceil(0.99 * sorted.length));
return sorted[rank - 1];
}
function renderRangeVelocity(market) {
const rows = market.tape;
const head = `range-velocity · ${market.instrument}`;
if (rows.length === 0) {
return `${head} · (no prints this window)`;
}
let hi = -Infinity;
let lo = Infinity;
for (const r of rows) {
if (r.high > hi)
hi = r.high;
if (r.low < lo)
lo = r.low;
}
const range = hi - lo;
if (rows.length < 2) {
return [
head,
` range ${num(range, 2)} · velocity ${DASH} · 1 bar (insufficient for a close-to-close velocity)`,
" read: UNKNOWN — need ≥2 bars for a velocity read (insufficient)"
].join(`
`);
}
const deltas = [];
for (let i = 1;i < rows.length; i += 1)
deltas.push(rows[i].close - rows[i - 1].close);
const absDeltas = deltas.map((d) => Math.abs(d));
const net = rows[rows.length - 1].close - rows[0].close;
const move = Math.abs(net);
const p99 = p99NearestRank(absDeltas);
const lastAbs = absDeltas[absDeltas.length - 1];
const barVel = deltas[deltas.length - 1];
const bars = rows.length;
const ratioPct = p99 > 0 ? Math.round(lastAbs / p99 * 100) : null;
const ratioStr = ratioPct === null ? DASH : `${ratioPct}%`;
const l2 = ` range ${num(range, 2)} · velocity ${money(net)} · move ${num(move, 2)} over ${bars} bars`;
const l3base = ` bar velocity now ${money(barVel)} · p99 ${num(p99, 2)} (${ratioStr} of p99)`;
const prevAbs = absDeltas.length >= 2 ? absDeltas[absDeltas.length - 2] : null;
if (prevAbs === null || ratioPct === null) {
return [
head,
l2,
`${l3base} · trend UNKNOWN`,
" read: UNKNOWN — need ≥3 bars to judge accelerating vs decelerating (insufficient)"
].join(`
`);
}
const trend = lastAbs > prevAbs ? "ACCELERATING" : lastAbs < prevAbs ? "DECELERATING" : "STEADY";
const l3 = `${l3base} · ${trend}`;
let read;
if (trend === "ACCELERATING" && ratioPct >= 50) {
read = " read: IMPULSIVE — break on accelerating velocity at/near its p99, fundable";
} else if (trend === "DECELERATING" && ratioPct < 50) {
read = " read: GRINDING — poke on decelerating velocity far below p99, unfunded (EQ fakeout)";
} else {
read = ` read: MIXED — velocity ${ratioStr} of p99, ${trend.toLowerCase()}; inconclusive (neither clean impulse nor clean grind)`;
}
return [head, l2, l3, read].join(`
`);
}
function percentileNearestRank(sample, p) {
const sorted = [...sample].sort((a, b) => a - b);
const rank = Math.max(1, Math.ceil(p * sorted.length));
return sorted[rank - 1];
}
function leastSquaresSlope(closes) {
const n = closes.length;
const xBar = (n - 1) / 2;
let yBar = 0;
for (const y of closes)
yBar += y;
yBar /= n;
let num2 = 0;
let den = 0;
for (let i = 0;i < n; i += 1) {
const dx = i - xBar;
num2 += dx * (closes[i] - yBar);
den += dx * dx;
}
return num2 / den;
}
function closeVsVwapLine(lastClose, vwap) {
if (vwap === null || vwap === undefined || !Number.isFinite(vwap)) {
return ` close-vs-vwap ${DASH} (vwap unknown)`;
}
const dist = lastClose - vwap;
const pctCell = vwap === 0 ? DASH : `${money(dist / vwap * 100)}%`;
return ` close-vs-vwap ${money(dist)} (${pctCell}) — close ${px(lastClose)} vs vwap ${px(vwap)}`;
}
function renderSeriesSummary(market) {
const rows = market.tape;
const head = `series-summary · ${market.instrument}`;
if (rows.length === 0) {
return `${head} · (no prints this window)`;
}
const closes = rows.map((r) => r.close);
const lastClose = closes[closes.length - 1];
const vwap = market.levels.vwap;
const bucketMin = market.tapeBucketMin;
if (rows.length < 2) {
return [
head,
` window 1 bucket · ${num(bucketMin, 0)}m each`,
` drift ${DASH} (need ≥2 buckets for a close-to-close read)`,
closeVsVwapLine(lastClose, vwap),
` slope ${DASH} (need ≥2 buckets for a least-squares slope)`,
` velocity 1-bucket |move| ${DASH} (need ≥2 buckets; n=0)`
].join(`
`);
}
const firstClose = closes[0];
const drift = lastClose - firstClose;
const driftPct = firstClose === 0 ? DASH : `${money(drift / firstClose * 100)}%`;
const absDeltas = [];
for (let i = 1;i < closes.length; i += 1)
absDeltas.push(Math.abs(closes[i] - closes[i - 1]));
const p50 = percentileNearestRank(absDeltas, 0.5);
const p90 = percentileNearestRank(absDeltas, 0.9);
const max = Math.max(...absDeltas);
const slope = leastSquaresSlope(closes);
return [
head,
` window ${rows.length} buckets · ${num(bucketMin, 0)}m each`,
` drift ${money(drift)} (${driftPct}) — close ${px(firstClose)} → ${px(lastClose)}`,
closeVsVwapLine(lastClose, vwap),
` slope ${money(slope)} pts/bucket (least-squares over ${rows.length} closes)`,
` velocity 1-bucket |move| p50=${num(p50, 2)} p90=${num(p90, 2)} max=${num(max, 2)} n=${absDeltas.length}`
].join(`
`);
}
var GEX_ASSUMPTION = "assume dealer short calls / long puts ⇒ short γ above spot, long γ below";
function ivPct(iv) {
return iv === null || iv === undefined || !Number.isFinite(iv) ? DASH : `${(iv * 100).toFixed(1)}%`;
}
function millions(x) {
if (x === null || x === undefined || !Number.isFinite(x))
return DASH;
const m = x / 1e6;
return `${m >= 0 ? "+" : "−"}${Math.abs(m).toFixed(1)}M`;
}
function gexProfile(o) {
const spot = o.spot;
if (spot === null || !Number.isFinite(spot))
return null;
const spot2 = spot * spot;
const byStrike = new Map;
let computed = 0;
let withOi = 0;
for (const exp of o.expiries) {
for (const l of exp.legs) {
if (l.oi !== null && l.oi > 0)
withOi += 1;
if (l.gamma === null || l.oi === null || l.oi <= 0)
continue;
const sign = l.right === "C" ? -1 : 1;
const dealerGamma = sign * l.gamma * l.oi * o.multiplier * spot2 * 0.01;
byStrike.set(l.strike, (byStrike.get(l.strike) ?? 0) + dealerGamma);
computed += 1;
}
}
if (computed === 0)
return null;
const perStrike = [...byStrike.entries()].map(([strike, net2]) => ({ strike, net: net2 })).sort((a, b) => a.strike - b.strike);
const net = perStrike.reduce((s, p) => s + p.net, 0);
let flip = null;
let cum = 0;
let prevK = null;
let prevCum = 0;
for (const p of perStrike) {
const nextCum = cum + p.net;
if (prevK !== null && (cum <= 0 && nextCum > 0 || cum >= 0 && nextCum < 0)) {
const span = p.strike - prevK;
const denom = nextCum - cum;
flip = denom === 0 ? p.strike : Number((prevK + span * ((0 - cum) / denom)).toFixed(2));
}
prevK = p.strike;
prevCum = cum;
cum = nextCum;
}
let posWall = null;
let negWall = null;
for (const p of perStrike) {
if (p.net > 0 && (posWall === null || p.net > posWall.net))
posWall = p;
if (p.net < 0 && (negWall === null || p.net < negWall.net))
negWall = p;
}
return { net, perStrike, flip, posWall, negWall, computed, withOi };
}
function nearestStrike(perStrike, level) {
let best = null;
let bestD = Infinity;
for (const p of perStrike) {
const d = Math.abs(p.strike - level);
if (d < bestD) {
bestD = d;
best = p;
}
}
return best;
}
function gexConfidence(p) {
if (p.withOi === 0)
return 0;
const c = p.computed / p.withOi;
return c < 0 ? 0 : c > 1 ? 1 : c;
}
function renderGex(market) {
const o = market.options;
const head = `gex · ${market.instrument} (MODEL)`;
const assume = ` ${GEX_ASSUMPTION} · gex-v1`;
if (o === undefined) {
return [`${head} · ${DASH} — no options-analytics projection (fail-closed)`, assume].join(`
`);
}
if (o.spotStale || o.spot === null) {
const age = o.spotStaleSeconds === null ? "never observed" : `sta