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.
340 lines (333 loc) • 10.8 kB
JavaScript
// src/protocol/support.ts
function isCalibratedSupport(support) {
return support === "calibrated";
}
function partition(cells) {
let calGain = 0;
let calLoss = 0;
let extGain = 0;
let extLoss = 0;
for (const cell of cells) {
if (isCalibratedSupport(cell.support)) {
if (cell.ev >= 0)
calGain += cell.ev;
else
calLoss += cell.ev;
} else {
if (cell.ev >= 0)
extGain += cell.ev;
else
extLoss += cell.ev;
}
}
return {
calibrated: { gain: calGain, loss: calLoss },
extrapolated: { gain: extGain, loss: extLoss }
};
}
function bankableEvOf(p) {
return p.calibrated.gain + p.calibrated.loss + p.extrapolated.loss;
}
// src/protocol/grade.ts
var REPORT_GRID = 1e8;
function roundToGrid(x) {
return Math.round(x * REPORT_GRID) / REPORT_GRID;
}
var round = roundToGrid;
function partitionOf(claims) {
const cal = claims.find((c) => c.support === "calibrated");
const ext = claims.find((c) => c.support === "extrapolated");
return {
calibrated: { gain: cal?.gain ?? 0, loss: cal?.loss ?? 0 },
extrapolated: { gain: ext?.gain ?? 0, loss: ext?.loss ?? 0 }
};
}
function hasCertifiedEvidence(b) {
return b.totals !== undefined && b.fill_claim !== undefined;
}
function grade(blotters) {
const subjectSessionId = blotters.map((b) => b.sessionId).sort().join("+");
let orderCount = 0;
let fillCount = 0;
let positionCount = 0;
let realizedPnl = 0;
let grossTradedQty = 0;
let filledNotional = 0;
for (const b of blotters) {
orderCount += b.orders.length;
fillCount += b.fills.length;
positionCount += b.positions.length;
realizedPnl += b.settlement.realized;
for (const f of b.fills) {
grossTradedQty += Math.abs(f.qty);
filledNotional += Math.abs(f.qty * f.price);
}
}
const metrics = {
realized_pnl: round(realizedPnl),
fill_rate: orderCount > 0 ? round(fillCount / orderCount) : 0,
order_count: orderCount,
fill_count: fillCount,
position_count: positionCount,
gross_traded_qty: round(grossTradedQty),
filled_notional: round(filledNotional)
};
const missing = blotters.filter((b) => !hasCertifiedEvidence(b)).map((b) => b.sessionId);
if (missing.length === 0) {
let floor = 0;
let expected = 0;
let bankable = 0;
for (const b of blotters) {
floor += b.totals.floor;
expected += b.totals.expected;
bankable += bankableEvOf(partitionOf(b.fill_claim));
}
metrics.realized_floor_usd = round(floor);
metrics.expected_usd = round(expected);
metrics.bankable_ev = round(bankable);
return { subjectSessionId, metrics };
}
const named = missing.length === 0 ? "the set" : [...missing].sort().join(", ");
return {
subjectSessionId,
metrics,
labels: {
risk_honest: "unknown",
risk_honest_reason: `certified evidence (totals + fill_claim) absent on: ${named} — risk-honest metrics refused, never a silent zero (kestrel-h314 D6)`
}
};
}
// src/protocol/index.ts
var PROTOCOL_VERSION = "0.4";
var FACES = ["http", "sdk", "cli", "mcp"];
// src/bus/types.ts
var BUS_SCHEMA = 6;
var SUPPORTED_BUS_SCHEMAS = new Set([1, 2, 3, 4, 5, 6]);
var STREAMS = new Set([
"META",
"TICK",
"DETECTOR",
"PLAN",
"ORDER",
"WAKE",
"CONTROL",
"REGIME",
"JOURNAL",
"TELEMETRY"
]);
var CORPUS_TIERS = ["public", "semi-private", "private"];
var JOURNAL_KINDS = new Set(["author", "debrief", "note"]);
var TELEMETRY_TYPES = new Set(["order", "settle", "guard", "hazard", "settle_mark", "theta_bleed"]);
function foldBook(ev, prior) {
let legs;
if (prior === undefined || prior.instrument !== ev.instrument || prior.legs.length === 0) {
legs = ev.legs;
} else {
const merged = new Map;
for (const l of prior.legs)
merged.set(`${l.strike}:${l.right}`, l);
for (const l of ev.legs)
merged.set(`${l.strike}:${l.right}`, l);
legs = [...merged.values()];
}
return {
instrument: ev.instrument,
underlier_px: ev.underlier_px,
...ev.expiry !== undefined ? { expiry: ev.expiry } : {},
legs,
asof_seq: ev.seq,
asof_ts: ev.ts
};
}
function isStream(s) {
return typeof s === "string" && STREAMS.has(s);
}
var TICK_TYPES = new Set([
"SPOT",
"BOOK",
"HEARTBEAT"
]);
var ORDER_ACTIONS = new Set([
"place",
"cancel",
"fill",
"reject"
]);
var WAKE_KINDS = new Set([
"wake",
"coalesced",
"downgraded"
]);
var DELIBERATION_TYPE = "deliberation";
function isValidStreamType(stream, type) {
switch (stream) {
case "META":
return type === "session";
case "TICK":
return TICK_TYPES.has(type);
case "DETECTOR":
return type.length > 0;
case "PLAN":
return type === "lifecycle";
case "ORDER":
return ORDER_ACTIONS.has(type);
case "WAKE":
return WAKE_KINDS.has(type) || type === DELIBERATION_TYPE;
case "CONTROL":
return type.length > 0;
case "REGIME":
return type === "tag";
case "TELEMETRY":
return type.length > 0;
default:
return false;
}
}
// src/bus/read.ts
import { readFileSync } from "node:fs";
var defaultSkipSink = (reason, line) => {
console.warn(`bus skip at line ${line}: ${reason}`);
};
class BusReadError extends Error {
line;
constructor(message, line) {
super(`bus corruption at line ${line}: ${message}`);
this.name = "BusReadError";
this.line = line;
}
}
function looksLikeContent(source) {
return source.trimStart().startsWith("{");
}
function validate(obj, lineNo) {
if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
throw new BusReadError("event is not a JSON object", lineNo);
}
const e = obj;
if (typeof e["seq"] !== "number" || !Number.isFinite(e["seq"])) {
throw new BusReadError("missing/invalid numeric `seq`", lineNo);
}
if (typeof e["ts"] !== "number" || !Number.isFinite(e["ts"])) {
throw new BusReadError("missing/invalid numeric `ts`", lineNo);
}
const stream = e["stream"];
if (!isStream(stream)) {
throw new BusReadError(`unknown stream ${JSON.stringify(stream)}`, lineNo);
}
if (stream === "JOURNAL") {
if (typeof e["kind"] !== "string") {
throw new BusReadError("JOURNAL missing/invalid string `kind`", lineNo);
}
if (typeof e["body"] !== "string") {
throw new BusReadError("JOURNAL missing/invalid string `body`", lineNo);
}
return obj;
}
const type = e["type"];
if (typeof type !== "string") {
throw new BusReadError("missing/invalid string `type`", lineNo);
}
if (!isValidStreamType(stream, type)) {
throw new BusReadError(`invalid (stream,type) pairing ${JSON.stringify(stream)}/${JSON.stringify(type)}`, lineNo);
}
if (stream === "META" && !SUPPORTED_BUS_SCHEMAS.has(e["bus_schema"])) {
throw new BusReadError(`unsupported bus_schema ${JSON.stringify(e["bus_schema"])} (reader supports ${[...SUPPORTED_BUS_SCHEMAS].join(", ")})`, lineNo);
}
if (stream === "WAKE" && type === DELIBERATION_TYPE) {
const intField = (name) => {
const v = e[name];
if (typeof v !== "number" || !Number.isInteger(v)) {
throw new BusReadError(`deliberation record: missing/non-integer \`${name}\``, lineNo);
}
return v;
};
if (intField("wake_seq") < 0)
throw new BusReadError("deliberation record: negative `wake_seq`", lineNo);
if (intField("measured_ms") < 0)
throw new BusReadError("deliberation record: negative `measured_ms`", lineNo);
if (intField("buffer_ms") < 0)
throw new BusReadError("deliberation record: negative `buffer_ms`", lineNo);
}
return obj;
}
function* readBusText(text, opts) {
if (text.length === 0)
return;
const onSkip = opts?.onSkip ?? defaultSkipSink;
const endsWithNewline = text.endsWith(`
`);
const segments = text.split(`
`);
if (endsWithNewline)
segments.pop();
let expectedSeq = 0;
let sawMeta = false;
let metaSchema = 0;
const checkpointTsBySeq = new Map;
for (let i = 0;i < segments.length; i++) {
const raw = segments[i] ?? "";
const lineNo = i + 1;
const isFinalSegment = i === segments.length - 1;
const torniable = isFinalSegment && !endsWithNewline;
if (raw.trim() === "") {
if (torniable)
return;
throw new BusReadError("unexpected blank line", lineNo);
}
let parsed;
try {
parsed = JSON.parse(raw);
} catch {
if (torniable)
return;
throw new BusReadError("unparseable JSON", lineNo);
}
const event = validate(parsed, lineNo);
if (!sawMeta) {
if (event.stream !== "META") {
throw new BusReadError("first event must be the META session header (a well-formed bus opens with exactly one META)", lineNo);
}
sawMeta = true;
metaSchema = event.bus_schema;
} else if (event.stream === "META") {
throw new BusReadError("a second META event (a well-formed bus opens with exactly one META)", lineNo);
}
if (event.seq !== expectedSeq) {
throw new BusReadError(`non-monotonic seq: expected ${expectedSeq}, got ${event.seq} (seq must be gap-free from 0)`, lineNo);
}
expectedSeq += 1;
if (event.stream === "WAKE") {
if (event.type === "wake" && event.wake === "checkpoint") {
checkpointTsBySeq.set(event.seq, event.ts);
} else if (event.type === DELIBERATION_TYPE) {
if (metaSchema < 6) {
throw new BusReadError(`a deliberation record on a bus stamped bus_schema ${metaSchema} — a clocked record on a pre-clocked (<6) bus is corrupt (clock-honest wakes §1)`, lineNo);
}
const d = event;
const cpTs = checkpointTsBySeq.get(d.wake_seq);
if (cpTs === undefined) {
throw new BusReadError(`deliberation record: dangling wake_seq ${d.wake_seq} — it must name an EARLIER WAKE checkpoint on this bus`, lineNo);
}
if (d.ts !== cpTs + d.measured_ms + d.buffer_ms) {
throw new BusReadError(`deliberation record: ts ${d.ts} breaks the return-time identity checkpoint.ts + measured_ms + buffer_ms = ${cpTs + d.measured_ms + d.buffer_ms}`, lineNo);
}
}
}
if (event.stream === "JOURNAL" && !JOURNAL_KINDS.has(event.kind)) {
onSkip(`unknown JOURNAL kind ${JSON.stringify(event.kind)}`, lineNo);
continue;
}
yield event;
}
}
function* readBusFile(path, opts) {
yield* readBusText(readFileSync(path, "utf8"), opts);
}
function* readBus(source, opts) {
if (looksLikeContent(source)) {
yield* readBusText(source, opts);
} else {
yield* readBusFile(source, opts);
}
}
export { isCalibratedSupport, partition, roundToGrid, grade, PROTOCOL_VERSION, FACES, BUS_SCHEMA, CORPUS_TIERS, foldBook, readBusText, readBus };