diff --git a/worker.js b/worker.js index 760c5ac..f2e54c0 100644 --- a/worker.js +++ b/worker.js @@ -60,7 +60,6 @@ async function main() { let latestMarketState = null; - // Fetch Kalshi balance periodically async function pollBalance() { try { await live.fetchBalance(); } catch {} try { await live.fetchPositions(); } catch {} @@ -68,7 +67,6 @@ async function main() { await pollBalance(); setInterval(pollBalance, BALANCE_POLL_MS); - // Orphan checker for paper async function processOrphans() { if (paper._resetting) return; await lockSettling(); @@ -109,23 +107,21 @@ async function main() { for (const strategy of strategies) { if (!strategy.enabled) continue; - // Paper trading (all strategies, always on) + // ===== PAPER TRADING (isolated evaluation) ===== const paperAcct = paper._getAccount(strategy.name); if (paperAcct.openPositions.size === 0) { - const signal = strategy.evaluate(state); - if (signal) { - console.log(`[Worker] Paper signal from ${strategy.name}: ${signal.side} @ ${signal.price}¢`); - if (strategy.mode === 'paper') { - await paper.executeTrade(signal, state); - } + const paperSignal = strategy.evaluate(state, 'paper'); + if (paperSignal) { + console.log(`[Worker] Paper signal from ${strategy.name}: ${paperSignal.side} @ ${paperSignal.price}¢`); + await paper.executeTrade(paperSignal, state); } } - // Live trading (only enabled strategies) + // ===== LIVE TRADING (separate evaluation, won't poison paper) ===== if (live.isStrategyEnabled(strategy.name) && !live.hasOpenPositionForStrategy(strategy.name)) { - const liveSignal = strategy.evaluate(state); + const liveSignal = strategy.evaluate(state, 'live'); if (liveSignal) { - console.log(`[Worker] LIVE signal from ${strategy.name}: ${liveSignal.side} @ ${liveSignal.price}¢`); + console.log(`[Worker] LIVE signal from ${strategy.name}: ${liveSignal.side} @ ${liveSignal.price}¢ (max: ${liveSignal.maxPrice}¢)`); await live.executeTrade(liveSignal, state); } } @@ -142,7 +138,6 @@ async function main() { if (result) { await lockSettling(); try { - // Settle paper positions const settledPaper = await paper.settle(ticker, result); if (settledPaper) { for (const strategy of strategies) { @@ -152,7 +147,6 @@ async function main() { } } - // Settle live positions const settledLive = await live.settle(ticker, result); if (settledPaper || settledLive) { @@ -192,8 +186,10 @@ async function main() { if (s.cycleWins !== undefined) s.cycleWins = 0; if (s.cycleLosses !== undefined) s.cycleLosses = 0; if (s.totalCycles !== undefined) s.totalCycles = 0; - s.lastTradeTicker = null; - s.lastTradeTime = 0; + if (s._lastTrade) { + s._lastTrade.paper = { time: 0, ticker: null }; + s._lastTrade.live = { time: 0, ticker: null }; + } } writeState(latestMarketState, paper, live, strategies); await notify('🔄 Paper trading reset by admin', 'Kalbot Reset', 'default', 'recycle'); @@ -256,7 +252,7 @@ async function main() { function writeState(marketState, paper, live, strategies) { const paperData = { - market: marketState, + market: marketState ? { ...marketState, orderbook: undefined } : null, paper: paper.getStats(), paperByStrategy: paper.getPerStrategyStats(), strategies: strategies.map(s => s.toJSON()), @@ -265,7 +261,7 @@ function writeState(marketState, paper, live, strategies) { }; const liveData = { - market: marketState, + market: marketState ? { ...marketState, orderbook: undefined } : null, live: live.getStats(), strategies: strategies.map(s => s.toJSON()), workerUptime: process.uptime(),