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.

298 lines (292 loc) 10.6 kB
import { PaperSessionRefused, parseWakeTimes, runDaySession, runPaperSession, runSimSession } from "./bin-xx1qrxe3.js"; import"./bin-t58k60v9.js"; import"./bin-p5jfg5b0.js"; import"./bin-29be75ss.js"; import"./bin-n77kea5n.js"; import"./bin-mn7wcxhv.js"; import { sha256 } from "./bin-8pchjxn2.js"; import"./bin-am3351y2.js"; import"./bin-73jr945c.js"; import"./bin-df1tn094.js"; import"./bin-3ft0k1jq.js"; import"./bin-2ywrx58g.js"; import"./bin-wckvcay0.js"; // src/ledger/index.ts import { Database } from "bun:sqlite"; // src/ledger/core.ts function deriveRunId(busSha256, plansSha256, fillModel, rUsd) { return sha256(`${busSha256} ${plansSha256} ${fillModel} ${String(rUsd)}`); } function plansSha256Of(plansText) { return sha256(plansText); } function compareCodePoint(a, b) { return a < b ? -1 : a > b ? 1 : 0; } function aggregatePlans(report) { const names = []; const tracesByName = new Map; for (const t of report.plans) { let g = tracesByName.get(t.plan); if (g === undefined) { g = []; tracesByName.set(t.plan, g); names.push(t.plan); } g.push(t); } return names.map((name) => { const traces = tracesByName.get(name); const orders = report.orders.filter((o) => o.plan === name); const fills = orders.filter((o) => o.filled).length; const realizedUsd = orders.reduce((s, o) => s + o.floorPnl, 0); const expectedUsd = orders.reduce((s, o) => s + o.expectedPnl, 0); const lifecycleFired = traces.some((t) => t.lifecycle.some((s) => s.state === "fired" || s.state === "managing")); const lastTrace = traces[traces.length - 1]; const lastStep = lastTrace.lifecycle[lastTrace.lifecycle.length - 1]; const outcome = lastStep?.outcome; const roleAgg = new Map; for (const o of orders) { const cur = roleAgg.get(o.role) ?? { count: 0, escStagesMax: 0 }; cur.count += 1; cur.escStagesMax = Math.max(cur.escStagesMax, o.esc_stages); roleAgg.set(o.role, cur); } const roles = [...roleAgg.entries()].map(([role, v]) => ({ role, count: v.count, escStagesMax: v.escStagesMax })).sort((a, b) => compareCodePoint(a.role, b.role)); return { name, finalState: String(lastTrace.final_state), outcome, fired: lifecycleFired || orders.length > 0, orders: orders.length, fills, realizedUsd, expectedUsd, roles }; }); } // src/ledger/index.ts var SCHEMA_VERSION = 1; var SCHEMA_SQL = ` CREATE TABLE IF NOT EXISTS runs ( run_id TEXT PRIMARY KEY, recorded_at INTEGER NOT NULL, session_date TEXT NOT NULL, mode TEXT NOT NULL, instruments TEXT NOT NULL, bus_sha256 TEXT NOT NULL, plans_sha256 TEXT NOT NULL, fill_model TEXT NOT NULL, calibrated INTEGER NOT NULL, determinism_hash TEXT NOT NULL, r_usd REAL NOT NULL, realized_floor_usd REAL NOT NULL, expected_usd REAL NOT NULL, premium_spent REAL NOT NULL, report_path TEXT, bus_events INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS plan_instances ( run_id TEXT NOT NULL, name TEXT NOT NULL, canonical_sha256 TEXT NOT NULL, final_state TEXT NOT NULL, outcome TEXT, fired INTEGER NOT NULL, orders INTEGER NOT NULL, fills INTEGER NOT NULL, realized_usd REAL NOT NULL, expected_usd REAL NOT NULL, PRIMARY KEY (run_id, name), FOREIGN KEY (run_id) REFERENCES runs(run_id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS orders_summary ( run_id TEXT NOT NULL, name TEXT NOT NULL, role TEXT NOT NULL, count INTEGER NOT NULL, esc_stages_max INTEGER NOT NULL, reprice_count INTEGER NOT NULL, PRIMARY KEY (run_id, name, role), FOREIGN KEY (run_id) REFERENCES runs(run_id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS idx_runs_session_date ON runs(session_date); CREATE INDEX IF NOT EXISTS idx_runs_recorded_at ON runs(recorded_at); CREATE INDEX IF NOT EXISTS idx_plan_instances_name ON plan_instances(name); `; function openLedger(dbPath) { const db = new Database(dbPath); db.exec("PRAGMA journal_mode = WAL"); db.exec("PRAGMA foreign_keys = ON"); const version = currentUserVersion(db); if (version > SCHEMA_VERSION) { db.close(); throw new Error(`ledger: database at ${JSON.stringify(dbPath)} is schema version ${version}, but this build only understands ${SCHEMA_VERSION} — refusing to open a future schema (fail-closed, ADR-0006)`); } if (version === 0) { db.exec(SCHEMA_SQL); db.exec(`PRAGMA user_version = ${SCHEMA_VERSION}`); } return db; } function currentUserVersion(db) { const row = db.query("PRAGMA user_version").get(); return row?.user_version ?? 0; } function record(db, report, opts) { const plansSha256 = plansSha256Of(opts.plansText); const busSha256 = report.session.bus_sha256; const fillModel = report.session.fill_model; const runId = deriveRunId(busSha256, plansSha256, fillModel, opts.rUsd); const perPlan = aggregatePlans(report); const tx = db.transaction(() => { db.query(`INSERT OR REPLACE INTO runs (run_id, recorded_at, session_date, mode, instruments, bus_sha256, plans_sha256, fill_model, calibrated, determinism_hash, r_usd, realized_floor_usd, expected_usd, premium_spent, report_path, bus_events) VALUES ($run_id, $recorded_at, $session_date, $mode, $instruments, $bus_sha256, $plans_sha256, $fill_model, $calibrated, $determinism_hash, $r_usd, $realized_floor_usd, $expected_usd, $premium_spent, $report_path, $bus_events)`).run({ $run_id: runId, $recorded_at: opts.now, $session_date: report.session.date, $mode: report.session.mode, $instruments: report.session.instruments.join(","), $bus_sha256: busSha256, $plans_sha256: plansSha256, $fill_model: fillModel, $calibrated: opts.calibrated ? 1 : 0, $determinism_hash: report.session.determinism_hash, $r_usd: opts.rUsd, $realized_floor_usd: report.totals.realized_floor_usd, $expected_usd: report.totals.expected_usd, $premium_spent: report.totals.premium_spent, $report_path: opts.reportPath ?? null, $bus_events: report.session.bus_events }); db.query("DELETE FROM plan_instances WHERE run_id = $run_id").run({ $run_id: runId }); db.query("DELETE FROM orders_summary WHERE run_id = $run_id").run({ $run_id: runId }); const insertPlan = db.query(`INSERT INTO plan_instances (run_id, name, canonical_sha256, final_state, outcome, fired, orders, fills, realized_usd, expected_usd) VALUES ($run_id, $name, $canonical_sha256, $final_state, $outcome, $fired, $orders, $fills, $realized_usd, $expected_usd)`); const insertRole = db.query(`INSERT INTO orders_summary (run_id, name, role, count, esc_stages_max, reprice_count) VALUES ($run_id, $name, $role, $count, $esc_stages_max, $reprice_count)`); for (const p of perPlan) { insertPlan.run({ $run_id: runId, $name: p.name, $canonical_sha256: plansSha256, $final_state: p.finalState, $outcome: p.outcome ?? null, $fired: p.fired ? 1 : 0, $orders: p.orders, $fills: p.fills, $realized_usd: p.realizedUsd, $expected_usd: p.expectedUsd }); for (const r of p.roles) { insertRole.run({ $run_id: runId, $name: p.name, $role: r.role, $count: r.count, $esc_stages_max: r.escStagesMax, $reprice_count: report.session.reprice_count }); } } }); tx(); return { runId, plansSha256 }; } function listRuns(db, filter = {}) { const where = []; const params = {}; if (filter.sessionDate !== undefined) { where.push("session_date = $session_date"); params.$session_date = filter.sessionDate; } if (filter.mode !== undefined) { where.push("mode = $mode"); params.$mode = filter.mode; } if (filter.fillModel !== undefined) { where.push("fill_model = $fill_model"); params.$fill_model = filter.fillModel; } if (filter.lineage !== undefined) { where.push("run_id IN (SELECT run_id FROM plan_instances WHERE name = $lineage)"); params.$lineage = filter.lineage; } const clause = where.length > 0 ? `WHERE ${where.join(" AND ")}` : ""; return db.query(`SELECT * FROM runs ${clause} ORDER BY recorded_at DESC, run_id ASC`).all(params); } function getRun(db, runId) { const run = db.query("SELECT * FROM runs WHERE run_id = $run_id").get({ $run_id: runId }); if (run === null) return; const plans = db.query("SELECT * FROM plan_instances WHERE run_id = $run_id ORDER BY name ASC").all({ $run_id: runId }); return { run, plans }; } function lineage(db, name) { return db.query(`SELECT pi.run_id, pi.name, pi.canonical_sha256, pi.final_state, pi.outcome, pi.fired, pi.orders, pi.fills, pi.realized_usd, pi.expected_usd, r.recorded_at, r.session_date, r.mode, r.fill_model FROM plan_instances pi JOIN runs r ON r.run_id = pi.run_id WHERE pi.name = $name ORDER BY r.recorded_at DESC, pi.run_id ASC`).all({ $name: name }); } function leaderboard(db, filter = {}) { const where = []; const params = {}; if (filter.mode !== undefined) { where.push("r.mode = $mode"); params.$mode = filter.mode; } if (filter.since !== undefined) { where.push("r.recorded_at >= $since"); params.$since = filter.since; } const clause = where.length > 0 ? `WHERE ${where.join(" AND ")}` : ""; return db.query(`SELECT pi.name AS name, COUNT(DISTINCT pi.run_id) AS runs, SUM(pi.fired) AS fired, SUM(pi.fills) AS fills, SUM(pi.realized_usd) AS realized_sum, SUM(pi.expected_usd) AS expected_sum, AVG(pi.realized_usd) AS realized_avg, AVG(pi.expected_usd) AS expected_avg FROM plan_instances pi JOIN runs r ON r.run_id = pi.run_id ${clause} GROUP BY pi.name ORDER BY realized_sum DESC, pi.name ASC`).all(params); } export { runSimSession, runPaperSession, runDaySession, record, parseWakeTimes, openLedger as openRegistry, listRuns, lineage, leaderboard, getRun, PaperSessionRefused };