mirror of
https://github.com/multipleof4/KalBot.git
synced 2026-03-16 21:41:02 +00:00
Fix: SurrealDB v2 compatible record IDs for trade history
This commit is contained in:
@@ -51,6 +51,34 @@ export class PaperEngine {
|
||||
return this.accounts.get(strategyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a short unique ID safe for SurrealDB v2 record keys.
|
||||
* Avoids colons so we control the full `table:id` format ourselves.
|
||||
*/
|
||||
_genId() {
|
||||
return `pt_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the raw record key from a SurrealDB id.
|
||||
* e.g. "paper_positions:pt_123_abc" -> "pt_123_abc"
|
||||
* "pt_123_abc" -> "pt_123_abc"
|
||||
*/
|
||||
_rawId(id) {
|
||||
if (!id) return id;
|
||||
const str = typeof id === 'object' && id.id ? String(id.id) : String(id);
|
||||
const idx = str.indexOf(':');
|
||||
return idx >= 0 ? str.slice(idx + 1) : str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the full `table:id` string for use in raw queries.
|
||||
*/
|
||||
_recordId(id) {
|
||||
const raw = this._rawId(id);
|
||||
return raw.startsWith('paper_positions:') ? raw : `paper_positions:⟨${raw}⟩`;
|
||||
}
|
||||
|
||||
async init() {
|
||||
try {
|
||||
const states = await db.query('SELECT * FROM paper_strategy_state ORDER BY timestamp DESC');
|
||||
@@ -96,11 +124,8 @@ 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: tradeId,
|
||||
id: this._genId(),
|
||||
strategy: signal.strategy,
|
||||
ticker: signal.ticker,
|
||||
side: signal.side.toLowerCase(),
|
||||
@@ -127,8 +152,7 @@ export class PaperEngine {
|
||||
acct.openPositions.set(trade.ticker, list);
|
||||
|
||||
try {
|
||||
// Force SurrealDB to use our exact record link ID
|
||||
await db.create(tradeId, trade);
|
||||
await db.create('paper_positions', trade);
|
||||
await this._saveState(acct);
|
||||
} catch (e) {
|
||||
console.error('[Paper] DB write error:', e.message);
|
||||
@@ -176,7 +200,7 @@ export class PaperEngine {
|
||||
if (won) acct.wins++;
|
||||
else acct.losses++;
|
||||
|
||||
const recordId = pos.id.includes(':') ? pos.id : `paper_positions:${pos.id}`;
|
||||
const recordId = this._recordId(pos.id);
|
||||
|
||||
try {
|
||||
const updated = await db.query(
|
||||
@@ -185,12 +209,13 @@ export class PaperEngine {
|
||||
);
|
||||
const rows = updated[0] || [];
|
||||
if (rows.length === 0) {
|
||||
await db.create(recordId, { ...pos, id: recordId });
|
||||
// Record vanished from DB — re-insert the full settled trade
|
||||
await db.create('paper_positions', { ...pos, id: this._rawId(pos.id) });
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[Paper] Settle DB error:', e.message);
|
||||
try {
|
||||
await db.create(recordId, { ...pos, id: recordId });
|
||||
await db.create('paper_positions', { ...pos, id: this._rawId(pos.id) });
|
||||
} catch (e2) {
|
||||
console.error('[Paper] Settle DB fallback error:', e2.message);
|
||||
}
|
||||
@@ -264,7 +289,7 @@ export class PaperEngine {
|
||||
acct.totalPnL -= pos.cost;
|
||||
acct.losses++;
|
||||
|
||||
const recordId = pos.id.includes(':') ? pos.id : `paper_positions:${pos.id}`;
|
||||
const recordId = this._recordId(pos.id);
|
||||
|
||||
try {
|
||||
const updated = await db.query(
|
||||
@@ -273,7 +298,7 @@ export class PaperEngine {
|
||||
);
|
||||
const rows = updated[0] || [];
|
||||
if (rows.length === 0) {
|
||||
await db.create(recordId, { ...pos, id: recordId });
|
||||
await db.create('paper_positions', { ...pos, id: this._rawId(pos.id) });
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[Paper] Force-expire DB error:', e.message);
|
||||
@@ -302,7 +327,7 @@ export class PaperEngine {
|
||||
pos.settleTime = Date.now();
|
||||
|
||||
try {
|
||||
const recordId = pos.id.includes(':') ? pos.id : `paper_positions:${pos.id}`;
|
||||
const recordId = this._recordId(pos.id);
|
||||
await db.query(
|
||||
`UPDATE ${recordId} SET settled = true, result = $result, pnl = $pnl, settleTime = $settleTime`,
|
||||
{ result: 'cancelled', pnl: 0, settleTime: pos.settleTime }
|
||||
|
||||
Reference in New Issue
Block a user