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;
// 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(),