From fc8565e562353dd2ebdcf2c24aa4268b69955497 Mon Sep 17 00:00:00 2001 From: multipleof4 Date: Mon, 16 Mar 2026 00:33:56 -0700 Subject: [PATCH] Feat: Auto-load strategies dynamically from folder --- worker.js | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/worker.js b/worker.js index e0c837e..5f2df98 100644 --- a/worker.js +++ b/worker.js @@ -1,17 +1,13 @@ import { MarketTracker } from './lib/market/tracker.js'; import { PaperEngine } from './lib/paper/engine.js'; -import { MartingaleStrategy } from './lib/strategies/martingale.js'; -import { MartingaleAlphaStrategy } from './lib/strategies/martingale-alpha.js'; -import { ThresholdStrategy } from './lib/strategies/threshold.js'; -import { BullDipBuyer } from './lib/strategies/bull-dip-buyer.js'; -import { SniperReversalStrategy } from './lib/strategies/sniper-reversal.js'; -import { MomentumRiderStrategy } from './lib/strategies/momentum-rider.js'; -import { DontDoubtBullStrategy } from './lib/strategies/dont-doubt-bull.js'; import { getMarket } from './lib/kalshi/rest.js'; import { db } from './lib/db.js'; import { notify } from './lib/notify.js'; import fs from 'fs'; +import path from 'path'; +import { fileURLToPath, pathToFileURL } from 'url'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); const STATE_FILE = '/tmp/kalbot-state.json'; const HEARTBEAT_MS = 2000; @@ -35,22 +31,33 @@ async function main() { const paper = new PaperEngine(1000); await paper.init(); - // Load all 7 strategies! - const strategies = [ - new MartingaleStrategy({ threshold: 70, baseBet: 1, maxDoublings: 5 }), - new MartingaleAlphaStrategy({ minPct: 40, maxPct: 60, baseBet: 1, maxRounds: 3 }), - new ThresholdStrategy({ triggerPct: 65, betSize: 1 }), - new BullDipBuyer({ maxYesPrice: 45, minYesPrice: 15, betSize: 2 }), - new SniperReversalStrategy({ triggerPct: 95, minsLeft: 3, betSize: 1 }), - new MomentumRiderStrategy({ triggerPct: 75, betSize: 2 }), - new DontDoubtBullStrategy({ minYesPct: 30, maxYesPct: 40, betSize: 2 }) - ]; + // Dynamically load all strategies from the strategies directory! + const strategies = []; + const strategiesDir = path.join(__dirname, 'lib', 'strategies'); + const stratFiles = fs.readdirSync(strategiesDir).filter(f => f.endsWith('.js') && f !== 'base.js'); + + for (const file of stratFiles) { + try { + const fileUrl = pathToFileURL(path.join(strategiesDir, file)).href; + const mod = await import(fileUrl); + + // Grab the first exported class/function + for (const key in mod) { + if (typeof mod[key] === 'function') { + strategies.push(new mod[key]()); // Instances use their own internal default configs! + break; + } + } + } catch (err) { + console.error(`[Worker] Failed to load strategy ${file}:`, err.message); + } + } for (const s of strategies) { paper._getAccount(s.name); } - console.log(`[Worker] Loaded ${strategies.length} strategies: ${strategies.map((s) => s.name).join(', ')}`); + console.log(`[Worker] Dynamically loaded ${strategies.length} strategies: ${strategies.map((s) => s.name).join(', ')}`); let latestMarketState = null; @@ -146,7 +153,7 @@ async function main() { }); await tracker.start(); - await notify('🤖 Kalbot Worker started with 7 strats!', 'Kalbot Online', 'low', 'robot,green_circle'); + await notify(`🤖 Kalbot Worker started with ${strategies.length} strats!`, 'Kalbot Online', 'low', 'robot,green_circle'); heartbeatTimer = setInterval(() => { writeState(latestMarketState, paper, strategies);