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
+19 -1
View File
@@ -4,6 +4,10 @@
async function runQueueFeeder(archiveDb, intelligenceDb, config) {
const batchSize = config.workers?.queueFeederBatchSize ?? 100;
const loopDelay = config.workers?.queueFeederLoopDelayMs ?? 3000;
const maxPending = Math.max(
batchSize,
config.workers?.queueFeederMaxPending ?? 250
);
const getCursor = intelligenceDb.prepare(
"SELECT value FROM cursors WHERE key = 'queue_feeder'"
@@ -16,11 +20,21 @@ async function runQueueFeeder(archiveDb, intelligenceDb, config) {
INSERT OR IGNORE INTO article_queue (article_id, status, created_at)
VALUES (?, 'pending', CURRENT_TIMESTAMP)
`);
const getPendingCount = intelligenceDb.prepare(
"SELECT COUNT(*) AS count FROM article_queue WHERE status = 'pending'"
);
while (true) {
try {
const pending = getPendingCount.get().count;
if (pending >= maxPending) {
await sleep(loopDelay);
continue;
}
const cursorRow = getCursor.get();
const cursor = cursorRow ? cursorRow.value : 0;
const availableSlots = Math.min(batchSize, maxPending - pending);
const articles = archiveDb.prepare(`
SELECT id FROM articles
@@ -31,7 +45,7 @@ async function runQueueFeeder(archiveDb, intelligenceDb, config) {
AND event_id IS NOT NULL
ORDER BY id ASC
LIMIT ?
`).all(cursor, batchSize);
`).all(cursor, availableSlots);
if (articles.length === 0) {
await sleep(loopDelay);
@@ -53,6 +67,10 @@ async function runQueueFeeder(archiveDb, intelligenceDb, config) {
console.log(`[feeder] queued ${inserted} articles, cursor now ${newCursor}`);
}
// Always yield between archive scans. The query is synchronous and can
// otherwise monopolise the event loop while catching up a large archive.
await sleep(loopDelay);
} catch (err) {
console.error("[feeder] error:", err.message);
await sleep(loopDelay);