feat: add autonomous paper-trading and calibration pipeline

This commit is contained in:
ImBenji
2026-08-03 14:03:27 +01:00
parent 5a9a2e4c6d
commit c4028cc394
46 changed files with 2246 additions and 115 deletions
+192
View File
@@ -0,0 +1,192 @@
const AUTONOMY_SCHEMA_VERSION = 1;
function initAutonomySchema(db) {
db.exec(`
CREATE TABLE IF NOT EXISTS autonomy_schema (
version INTEGER PRIMARY KEY,
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_jobs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
job_type TEXT NOT NULL,
lane TEXT NOT NULL CHECK (lane IN ('live', 'historical', 'maintenance')),
priority INTEGER NOT NULL DEFAULT 0,
entity_type TEXT NOT NULL,
entity_id TEXT NOT NULL,
idempotency_key TEXT NOT NULL UNIQUE,
status TEXT NOT NULL DEFAULT 'pending'
CHECK (status IN ('pending', 'leased', 'complete', 'failed', 'dead_letter')),
attempts INTEGER NOT NULL DEFAULT 0,
available_at TEXT NOT NULL DEFAULT (datetime('now')),
leased_by TEXT,
lease_expires_at TEXT,
last_error TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
completed_at TEXT
);
CREATE INDEX IF NOT EXISTS idx_autonomy_jobs_claim
ON autonomy_jobs(status, lane, priority DESC, available_at);
CREATE TABLE IF NOT EXISTS autonomy_cursors (
key TEXT PRIMARY KEY,
value INTEGER NOT NULL DEFAULT 0,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_proposals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
event_id INTEGER,
payload TEXT NOT NULL,
information_cutoff TEXT NOT NULL,
coordinator_model TEXT,
prompt_version TEXT,
status TEXT NOT NULL DEFAULT 'candidate'
CHECK (status IN ('candidate', 'accepted', 'rejected', 'superseded')),
rejection_reason TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
reviewed_at TEXT
);
CREATE TABLE IF NOT EXISTS autonomy_instruments (
symbol TEXT PRIMARY KEY,
broker TEXT NOT NULL,
asset_class TEXT NOT NULL DEFAULT 'us_equity',
active INTEGER NOT NULL DEFAULT 0,
tradable INTEGER NOT NULL DEFAULT 0,
shortable INTEGER NOT NULL DEFAULT 0,
fractionable INTEGER NOT NULL DEFAULT 0,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_legacy_records (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source_table TEXT NOT NULL,
source_id INTEGER NOT NULL,
payload TEXT NOT NULL,
calibration_eligible INTEGER NOT NULL DEFAULT 0,
imported_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(source_table, source_id)
);
CREATE TABLE IF NOT EXISTS autonomy_predictions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
proposal_id INTEGER NOT NULL REFERENCES autonomy_proposals(id),
event_id INTEGER,
instrument TEXT NOT NULL,
direction TEXT NOT NULL CHECK (direction IN ('positive', 'negative')),
event_type TEXT NOT NULL,
causal_channel TEXT,
horizon_days INTEGER NOT NULL,
information_cutoff TEXT NOT NULL,
evidence_article_ids TEXT NOT NULL,
invalidation_condition TEXT,
learning_eligible INTEGER NOT NULL DEFAULT 0,
strategy_version TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'open'
CHECK (status IN ('open', 'resolved', 'unresolvable', 'invalidated')),
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_autonomy_predictions_resolution
ON autonomy_predictions(status, information_cutoff, instrument);
CREATE TABLE IF NOT EXISTS autonomy_outcomes (
prediction_id INTEGER PRIMARY KEY REFERENCES autonomy_predictions(id),
price_0 REAL,
price_horizon REAL,
benchmark_0 REAL,
benchmark_horizon REAL,
excess_return REAL,
direction_correct INTEGER,
error_type TEXT,
evaluated_at TEXT NOT NULL DEFAULT (datetime('now')),
notes TEXT
);
CREATE TABLE IF NOT EXISTS autonomy_calibration_snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cohort_key TEXT NOT NULL,
sample_size INTEGER NOT NULL,
effective_sample_size REAL NOT NULL,
directional_probability REAL NOT NULL,
expected_excess_return REAL,
lower_return REAL,
upper_return REAL,
parent_cohort_key TEXT,
version TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_autonomy_calibration_lookup
ON autonomy_calibration_snapshots(cohort_key, created_at DESC);
CREATE TABLE IF NOT EXISTS autonomy_decisions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
prediction_id INTEGER NOT NULL REFERENCES autonomy_predictions(id),
action TEXT NOT NULL CHECK (action IN ('BUY', 'SELL', 'HOLD', 'ABSTAIN')),
calibrated_probability REAL,
expected_excess_return REAL,
rationale TEXT NOT NULL,
strategy_version TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_order_intents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
decision_id INTEGER NOT NULL REFERENCES autonomy_decisions(id),
client_order_id TEXT NOT NULL UNIQUE,
instrument TEXT NOT NULL,
side TEXT NOT NULL CHECK (side IN ('buy', 'sell')),
notional REAL NOT NULL CHECK (notional > 0),
status TEXT NOT NULL DEFAULT 'shadow'
CHECK (status IN ('shadow', 'pending', 'submitted', 'filled', 'partially_filled', 'rejected', 'cancelled')),
broker_order_id TEXT,
attempts INTEGER NOT NULL DEFAULT 0,
last_error TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_broker_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
broker TEXT NOT NULL,
event_type TEXT NOT NULL,
broker_id TEXT,
payload TEXT NOT NULL,
occurred_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(broker, event_type, broker_id, occurred_at)
);
CREATE TABLE IF NOT EXISTS autonomy_account_snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
broker TEXT NOT NULL,
account_id TEXT,
equity REAL,
cash REAL,
buying_power REAL,
payload TEXT NOT NULL,
captured_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS autonomy_position_snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
broker TEXT NOT NULL,
instrument TEXT NOT NULL,
quantity REAL,
market_value REAL,
unrealized_pl REAL,
payload TEXT NOT NULL,
captured_at TEXT NOT NULL DEFAULT (datetime('now'))
);
INSERT OR IGNORE INTO autonomy_schema(version) VALUES (${AUTONOMY_SCHEMA_VERSION});
`);
for (const statement of [
'ALTER TABLE autonomy_order_intents ADD COLUMN attempts INTEGER NOT NULL DEFAULT 0',
'ALTER TABLE autonomy_order_intents ADD COLUMN last_error TEXT',
'ALTER TABLE autonomy_predictions ADD COLUMN learning_eligible INTEGER NOT NULL DEFAULT 0',
]) {
try { db.exec(statement); } catch (_) {}
}
}
module.exports = { AUTONOMY_SCHEMA_VERSION, initAutonomySchema };