Feat: Separate paper/live eval, pass orderbook ctx

This commit is contained in:
2026-03-16 12:30:41 -07:00
parent 9e138b22c6
commit 8a06b9b668

View File

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