diff --git a/lib/paper/engine.js b/lib/paper/engine.js index af55370..04fed73 100644 --- a/lib/paper/engine.js +++ b/lib/paper/engine.js @@ -96,8 +96,11 @@ export class PaperEngine { return null; } + // FIX: Pre-format the ID exactly as SurrealDB expects it to ensure perfect sync + const tradeId = `paper_positions:pt_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`; + const trade = { - id: `pt_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`, + id: tradeId, strategy: signal.strategy, ticker: signal.ticker, side: signal.side.toLowerCase(), @@ -124,7 +127,8 @@ export class PaperEngine { acct.openPositions.set(trade.ticker, list); try { - await db.create('paper_positions', trade); + // Force SurrealDB to use our exact record link ID + await db.create(tradeId, trade); await this._saveState(acct); } catch (e) { console.error('[Paper] DB write error:', e.message); @@ -172,21 +176,21 @@ export class PaperEngine { if (won) acct.wins++; else acct.losses++; + const recordId = pos.id.includes(':') ? pos.id : `paper_positions:${pos.id}`; + try { - // FIX: Use explicit record identifier for SurrealDB updates - const recordId = pos.id.includes(':') ? pos.id : `paper_positions:${pos.id}`; const updated = await db.query( `UPDATE ${recordId} SET settled = true, result = $result, pnl = $pnl, settleTime = $settleTime`, { result, pnl: pos.pnl, settleTime: pos.settleTime } ); const rows = updated[0] || []; if (rows.length === 0) { - await db.create('paper_positions', { ...pos }); + await db.create(recordId, { ...pos, id: recordId }); } } catch (e) { console.error('[Paper] Settle DB error:', e.message); try { - await db.create('paper_positions', { ...pos }); + await db.create(recordId, { ...pos, id: recordId }); } catch (e2) { console.error('[Paper] Settle DB fallback error:', e2.message); } @@ -217,9 +221,6 @@ export class PaperEngine { return Array.from(tickers); } - /** - * Check unresolved tickers periodically for delayed Kalshi results - */ async checkOrphans(getMarketFn) { const orphanTickers = this.getOpenTickers(); if (!orphanTickers.length) return { settled: [], expired: [] }; @@ -263,15 +264,16 @@ export class PaperEngine { acct.totalPnL -= pos.cost; acct.losses++; + const recordId = pos.id.includes(':') ? pos.id : `paper_positions:${pos.id}`; + try { - const recordId = pos.id.includes(':') ? pos.id : `paper_positions:${pos.id}`; const updated = await db.query( `UPDATE ${recordId} SET settled = true, result = $result, pnl = $pnl, settleTime = $settleTime`, { result: 'expired', pnl: pos.pnl, settleTime: pos.settleTime } ); const rows = updated[0] || []; if (rows.length === 0) { - await db.create('paper_positions', { ...pos }); + await db.create(recordId, { ...pos, id: recordId }); } } catch (e) { console.error('[Paper] Force-expire DB error:', e.message);