hedgequantx 2.6.88 → 2.6.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/pages/algo/one-account.js +57 -73
package/package.json
CHANGED
|
@@ -399,84 +399,68 @@ const launchAlgo = async (service, account, contract, config) => {
|
|
|
399
399
|
}
|
|
400
400
|
|
|
401
401
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
402
|
-
// REAL-TIME P&L VIA WEBSOCKET
|
|
403
|
-
//
|
|
402
|
+
// REAL-TIME P&L VIA WEBSOCKET
|
|
403
|
+
// - Rithmic: Uses EventEmitter (service.on) for real-time updates
|
|
404
|
+
// - ProjectX: Uses HTTP polling (handled in pollPnL function below)
|
|
404
405
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
405
406
|
const rithmicAccountId = account.rithmicAccountId || account.accountId;
|
|
407
|
+
const serviceHasEvents = typeof service.on === 'function';
|
|
406
408
|
|
|
407
|
-
|
|
408
|
-
//
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// Net Liquidation Value (balance + openPnl) - same as R Trader
|
|
436
|
-
if (pnlData.netLiquidation !== undefined) {
|
|
437
|
-
stats.netLiquidation = parseFloat(pnlData.netLiquidation);
|
|
438
|
-
} else if (stats.balance !== null) {
|
|
439
|
-
// Calculate if not provided directly
|
|
440
|
-
stats.netLiquidation = stats.balance + (stats.openPnl || 0);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
// Total P&L = openPnl (from positionUpdate) + closedPnl (from pnlUpdate)
|
|
444
|
-
// This matches R Trader's "Today's P&L" calculation
|
|
445
|
-
stats.pnl = (stats.openPnl || 0) + (stats.closedPnl || 0);
|
|
446
|
-
});
|
|
447
|
-
|
|
448
|
-
// Listen to position updates for real-time position tracking (like R Trader)
|
|
449
|
-
// INSTRUMENT_PNL_UPDATE (450) provides per-instrument P&L in real-time
|
|
450
|
-
service.on('positionUpdate', (pos) => {
|
|
451
|
-
if (!pos || pos.accountId !== rithmicAccountId) return;
|
|
452
|
-
if (pos.symbol !== symbolName && !pos.symbol?.includes(symbolName.replace(/[A-Z]\d+$/, ''))) return;
|
|
453
|
-
|
|
454
|
-
// Update position info (like R Trader Positions panel)
|
|
455
|
-
const wasFlat = stats.position === 0;
|
|
456
|
-
stats.position = pos.quantity || 0;
|
|
457
|
-
stats.entryPrice = pos.averagePrice || 0;
|
|
458
|
-
currentPosition = pos.quantity || 0;
|
|
459
|
-
|
|
460
|
-
// Track entry time when opening a new position
|
|
461
|
-
if (wasFlat && stats.position !== 0) {
|
|
462
|
-
stats.entryTime = Date.now();
|
|
463
|
-
} else if (stats.position === 0) {
|
|
464
|
-
stats.entryTime = null;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// CRITICAL: Update Open P&L from instrument-level data (real-time, same as R Trader)
|
|
468
|
-
// pos.openPnl comes from INSTRUMENT_PNL_UPDATE (450) - this is the unrealized P&L
|
|
469
|
-
if (pos.openPnl !== undefined && pos.openPnl !== null) {
|
|
470
|
-
stats.openPnl = pos.openPnl;
|
|
471
|
-
// Recalculate total P&L whenever Open P&L changes
|
|
472
|
-
// Total P&L = openPnl + closedPnl (same formula as R Trader)
|
|
409
|
+
if (serviceHasEvents) {
|
|
410
|
+
// RITHMIC ONLY: Real-time P&L via WebSocket
|
|
411
|
+
service.on('pnlUpdate', (pnlData) => {
|
|
412
|
+
// Only update for our account
|
|
413
|
+
if (pnlData.accountId !== rithmicAccountId) return;
|
|
414
|
+
|
|
415
|
+
// ACCOUNT_PNL_UPDATE (451) - All R Trader account-level metrics
|
|
416
|
+
if (pnlData.closedPositionPnl !== undefined) {
|
|
417
|
+
stats.closedPnl = parseFloat(pnlData.closedPositionPnl);
|
|
418
|
+
}
|
|
419
|
+
if (pnlData.accountBalance !== undefined) {
|
|
420
|
+
stats.balance = parseFloat(pnlData.accountBalance);
|
|
421
|
+
}
|
|
422
|
+
if (pnlData.availableBuyingPower !== undefined) {
|
|
423
|
+
stats.buyingPower = parseFloat(pnlData.availableBuyingPower);
|
|
424
|
+
}
|
|
425
|
+
if (pnlData.marginBalance !== undefined) {
|
|
426
|
+
stats.margin = parseFloat(pnlData.marginBalance);
|
|
427
|
+
}
|
|
428
|
+
if (pnlData.netLiquidation !== undefined) {
|
|
429
|
+
stats.netLiquidation = parseFloat(pnlData.netLiquidation);
|
|
430
|
+
} else if (stats.balance !== null) {
|
|
431
|
+
stats.netLiquidation = stats.balance + (stats.openPnl || 0);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Total P&L = openPnl + closedPnl (same as R Trader)
|
|
473
435
|
stats.pnl = (stats.openPnl || 0) + (stats.closedPnl || 0);
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
// RITHMIC ONLY: Real-time position updates
|
|
439
|
+
service.on('positionUpdate', (pos) => {
|
|
440
|
+
if (!pos || pos.accountId !== rithmicAccountId) return;
|
|
441
|
+
if (pos.symbol !== symbolName && !pos.symbol?.includes(symbolName.replace(/[A-Z]\d+$/, ''))) return;
|
|
442
|
+
|
|
443
|
+
const wasFlat = stats.position === 0;
|
|
444
|
+
stats.position = pos.quantity || 0;
|
|
445
|
+
stats.entryPrice = pos.averagePrice || 0;
|
|
446
|
+
currentPosition = pos.quantity || 0;
|
|
447
|
+
|
|
448
|
+
if (wasFlat && stats.position !== 0) {
|
|
449
|
+
stats.entryTime = Date.now();
|
|
450
|
+
} else if (stats.position === 0) {
|
|
451
|
+
stats.entryTime = null;
|
|
477
452
|
}
|
|
478
|
-
|
|
479
|
-
|
|
453
|
+
|
|
454
|
+
// Update Open P&L from INSTRUMENT_PNL_UPDATE (450)
|
|
455
|
+
if (pos.openPnl !== undefined && pos.openPnl !== null) {
|
|
456
|
+
stats.openPnl = pos.openPnl;
|
|
457
|
+
stats.pnl = (stats.openPnl || 0) + (stats.closedPnl || 0);
|
|
458
|
+
if (stats.balance !== null) {
|
|
459
|
+
stats.netLiquidation = stats.balance + stats.openPnl;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}
|
|
480
464
|
|
|
481
465
|
// Initialize AI Strategy Supervisor - agents observe, learn & optimize
|
|
482
466
|
// Only if user enabled AI in config
|