diff --git a/worker.js b/worker.js index ebed9c5..7999b0b 100644 --- a/worker.js +++ b/worker.js @@ -1,51 +1,48 @@ 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 { db } from './lib/db.js'; import { notify } from './lib/notify.js'; import fs from 'fs'; -// Shared state file for the Next.js frontend to read const STATE_FILE = '/tmp/kalbot-state.json'; const HEARTBEAT_MS = 2000; async function main() { console.log('=== Kalbot Worker Starting ==='); - // Connect to SurrealDB await db.connect(); - // Initialize paper engine const paper = new PaperEngine(1000); await paper.init(); - // Initialize 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 }) ]; + // Ensure each strategy has a paper account initialized + for (const s of strategies) { + paper._getAccount(s.name); + } + console.log(`[Worker] Loaded ${strategies.length} strategies: ${strategies.map((s) => s.name).join(', ')}`); - // Initialize market tracker const tracker = new MarketTracker(); let latestMarketState = null; let heartbeatTimer = null; - // Write initial heartbeat immediately so dashboard never shows "Updated: never" writeState(latestMarketState, paper, strategies); - // On every market update, run strategies tracker.on('update', async (state) => { latestMarketState = state || null; - - // Write state to file for frontend writeState(latestMarketState, paper, strategies); if (!state) return; - // Run each strategy for (const strategy of strategies) { if (!strategy.enabled) continue; @@ -56,21 +53,17 @@ async function main() { if (strategy.mode === 'paper') { await paper.executeTrade(signal, state); } - // TODO: Live mode — use placeOrder() from rest.js } } - // Update state file after potential trades writeState(latestMarketState, paper, strategies); }); - // On market settlement, settle paper positions and notify strategies tracker.on('settled', async ({ ticker, result }) => { console.log(`[Worker] Market ${ticker} settled: ${result}`); const settledPositions = await paper.settle(ticker, result); - // Notify strategies about settlement for (const strategy of strategies) { if (!settledPositions) continue; for (const trade of settledPositions) { @@ -88,11 +81,9 @@ async function main() { writeState(latestMarketState, paper, strategies); }); - // Start tracking await tracker.start(); await notify('🤖 Kalbot Worker started!', 'Kalbot Online', 'low', 'robot,green_circle'); - // Keep state fresh even if market API is temporarily quiet heartbeatTimer = setInterval(() => { writeState(latestMarketState, paper, strategies); }, HEARTBEAT_MS); @@ -107,7 +98,6 @@ async function main() { process.exit(0); }; - // Graceful shutdown process.on('SIGINT', () => shutdown('SIGINT')); process.on('SIGTERM', () => shutdown('SIGTERM')); } @@ -116,6 +106,7 @@ function writeState(marketState, paper, strategies) { const data = { market: marketState, paper: paper.getStats(), + paperByStrategy: paper.getPerStrategyStats(), strategies: strategies.map((s) => s.toJSON()), workerUptime: process.uptime(), lastUpdate: Date.now()