feat: add autonomous paper-trading and calibration pipeline
This commit is contained in:
@@ -60,7 +60,7 @@ function buildArticlesQuery(query) {
|
||||
return {
|
||||
sql: `
|
||||
SELECT id, title, description, content, ${includeEmbedding ? 'embedding,' : ''} url, normalized_title, source, pub_date, ingested_at
|
||||
FROM articles
|
||||
FROM articles INDEXED BY idx_articles_usable_pub_date
|
||||
${whereClause}
|
||||
ORDER BY ${orderBy}
|
||||
LIMIT ? OFFSET ?
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
const path = require('path');
|
||||
const Database = require('better-sqlite3');
|
||||
|
||||
const intelligencePath = process.env.INTELLIGENCE_DB || path.resolve(process.cwd(), 'intelligence.sqlite');
|
||||
const db = new Database(intelligencePath, { readonly: true });
|
||||
|
||||
async function autonomyRoutes(fastify) {
|
||||
fastify.get('/health', async () => ({ ok: true, service: 'duriin-api' }));
|
||||
|
||||
fastify.get('/autonomy/status', async () => {
|
||||
const exists = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='autonomy_jobs'").get();
|
||||
if (!exists) return { enabled: false, reason: 'autonomy schema is not initialized' };
|
||||
const jobs = db.prepare(`
|
||||
SELECT lane, status, COUNT(*) AS count
|
||||
FROM autonomy_jobs
|
||||
GROUP BY lane, status
|
||||
ORDER BY lane, status
|
||||
`).all();
|
||||
const predictions = db.prepare(`
|
||||
SELECT status, COUNT(*) AS count
|
||||
FROM autonomy_predictions
|
||||
GROUP BY status
|
||||
ORDER BY status
|
||||
`).all();
|
||||
const decisions = db.prepare(`
|
||||
SELECT action, COUNT(*) AS count
|
||||
FROM autonomy_decisions
|
||||
GROUP BY action
|
||||
ORDER BY action
|
||||
`).all();
|
||||
const outcomes = db.prepare(`
|
||||
SELECT COUNT(*) AS total,
|
||||
SUM(direction_correct) AS correct,
|
||||
AVG(excess_return) AS average_excess_return
|
||||
FROM autonomy_outcomes
|
||||
`).get();
|
||||
const legacy = db.prepare('SELECT COUNT(*) AS count FROM autonomy_legacy_records').get();
|
||||
const instruments = db.prepare('SELECT COUNT(*) AS count FROM autonomy_instruments WHERE active=1 AND tradable=1').get();
|
||||
return { enabled: true, jobs, predictions, decisions, outcomes, legacyRecords: legacy.count, allowlistedInstruments: instruments.count };
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = autonomyRoutes;
|
||||
+14
-1
@@ -6,7 +6,20 @@ let statusCacheAt = 0;
|
||||
const STATUS_CACHE_TTL_MS = 30 * 1000;
|
||||
|
||||
async function statusRoutes(fastify) {
|
||||
fastify.get('/status', async () => {
|
||||
fastify.get('/status', async (request) => {
|
||||
const deep = String(request.query?.deep || '').toLowerCase() === 'true';
|
||||
if (!deep) {
|
||||
const sequence = db.prepare("SELECT seq FROM sqlite_sequence WHERE name = 'articles'").get();
|
||||
return {
|
||||
total: sequence ? sequence.seq : 0,
|
||||
usable: null,
|
||||
lastIngestionBySource: getLastIngestionBySource(),
|
||||
bySource: null,
|
||||
embeddingModels: null,
|
||||
mode: 'lightweight',
|
||||
deep_status_url: '/status?deep=true',
|
||||
};
|
||||
}
|
||||
const now = Date.now();
|
||||
if (statusCache && now - statusCacheAt < STATUS_CACHE_TTL_MS) {
|
||||
return statusCache;
|
||||
|
||||
Reference in New Issue
Block a user