hedgequantx 2.6.43 → 2.6.45
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 +34 -6
- package/src/pages/algo/ui.js +37 -15
package/package.json
CHANGED
|
@@ -246,6 +246,13 @@ const launchAlgo = async (service, account, contract, config) => {
|
|
|
246
246
|
propfirm: account.propfirm || 'Unknown',
|
|
247
247
|
platform: connectionType,
|
|
248
248
|
pnl: 0,
|
|
249
|
+
// R Trader style P&L breakdown
|
|
250
|
+
openPnl: 0, // Unrealized P&L (current position)
|
|
251
|
+
closedPnl: 0, // Realized P&L (closed trades today)
|
|
252
|
+
// Position info (like R Trader)
|
|
253
|
+
position: 0, // Current position qty (+ long, - short)
|
|
254
|
+
entryPrice: 0, // Average entry price
|
|
255
|
+
lastPrice: 0, // Last market price
|
|
249
256
|
trades: 0,
|
|
250
257
|
wins: 0,
|
|
251
258
|
losses: 0,
|
|
@@ -372,21 +379,39 @@ const launchAlgo = async (service, account, contract, config) => {
|
|
|
372
379
|
// Only update for our account
|
|
373
380
|
if (pnlData.accountId !== rithmicAccountId) return;
|
|
374
381
|
|
|
375
|
-
//
|
|
376
|
-
|
|
382
|
+
// ACCOUNT_PNL_UPDATE (451) provides account-level totals
|
|
383
|
+
// closedPositionPnl = realized P&L from all closed trades today
|
|
377
384
|
const closedPnl = parseFloat(pnlData.closedPositionPnl || 0);
|
|
378
385
|
|
|
379
|
-
//
|
|
380
|
-
stats.
|
|
386
|
+
// Update closed P&L (realized) from account-level data
|
|
387
|
+
stats.closedPnl = closedPnl;
|
|
388
|
+
|
|
389
|
+
// Total P&L = openPnl (from positionUpdate) + closedPnl (from pnlUpdate)
|
|
390
|
+
// This matches R Trader's "Today's P&L" calculation
|
|
391
|
+
stats.pnl = (stats.openPnl || 0) + (stats.closedPnl || 0);
|
|
381
392
|
});
|
|
382
393
|
|
|
383
|
-
//
|
|
394
|
+
// Listen to position updates for real-time position tracking (like R Trader)
|
|
395
|
+
// INSTRUMENT_PNL_UPDATE (450) provides per-instrument P&L in real-time
|
|
384
396
|
service.on('positionUpdate', (pos) => {
|
|
385
397
|
if (!pos || pos.accountId !== rithmicAccountId) return;
|
|
386
398
|
if (pos.symbol !== symbolName && !pos.symbol?.includes(symbolName.replace(/[A-Z]\d+$/, ''))) return;
|
|
387
399
|
|
|
388
|
-
// Update
|
|
400
|
+
// Update position info (like R Trader Positions panel)
|
|
401
|
+
stats.position = pos.quantity || 0;
|
|
402
|
+
stats.entryPrice = pos.averagePrice || 0;
|
|
389
403
|
currentPosition = pos.quantity || 0;
|
|
404
|
+
|
|
405
|
+
// CRITICAL: Update Open P&L from instrument-level data (real-time, same as R Trader)
|
|
406
|
+
// pos.openPnl comes from INSTRUMENT_PNL_UPDATE (450) - this is the unrealized P&L
|
|
407
|
+
if (pos.openPnl !== undefined && pos.openPnl !== null) {
|
|
408
|
+
stats.openPnl = pos.openPnl;
|
|
409
|
+
}
|
|
410
|
+
// Update day P&L if available
|
|
411
|
+
if (pos.dayPnl !== undefined && pos.dayPnl !== null) {
|
|
412
|
+
// Total P&L = openPnl + closedPnl (same formula as R Trader)
|
|
413
|
+
stats.pnl = (stats.openPnl || 0) + (stats.closedPnl || 0);
|
|
414
|
+
}
|
|
390
415
|
});
|
|
391
416
|
|
|
392
417
|
// Initialize AI Strategy Supervisor - agents observe, learn & optimize
|
|
@@ -624,6 +649,9 @@ const launchAlgo = async (service, account, contract, config) => {
|
|
|
624
649
|
timestamp: tick.timestamp || Date.now()
|
|
625
650
|
};
|
|
626
651
|
|
|
652
|
+
// Update last price for UI (like R Trader)
|
|
653
|
+
stats.lastPrice = tickData.price;
|
|
654
|
+
|
|
627
655
|
// Feed tick to AI supervisor (agents observe same data as strategy)
|
|
628
656
|
if (stats.aiSupervision) {
|
|
629
657
|
StrategySupervisor.feedTick(tickData);
|
package/src/pages/algo/ui.js
CHANGED
|
@@ -182,35 +182,57 @@ class AlgoUI {
|
|
|
182
182
|
|
|
183
183
|
this._line(chalk.cyan(GM));
|
|
184
184
|
|
|
185
|
-
// Row 2:
|
|
186
|
-
const
|
|
185
|
+
// Row 2: Position | P&L (like R Trader)
|
|
186
|
+
const posQty = stats.position || 0;
|
|
187
|
+
const posStr = posQty === 0 ? 'FLAT' : (posQty > 0 ? `+${posQty} LONG` : `${posQty} SHORT`);
|
|
188
|
+
const posColor = posQty === 0 ? chalk.gray : (posQty > 0 ? chalk.green : chalk.red);
|
|
189
|
+
const r2c1 = buildCell('POSITION', posStr, posColor, colL);
|
|
187
190
|
const r2c2 = buildCell('P&L', pnlStr, pnlColor, colR);
|
|
188
191
|
row(r2c1.padded, r2c2.padded);
|
|
189
192
|
|
|
190
193
|
this._line(chalk.cyan(GM));
|
|
191
194
|
|
|
192
|
-
// Row 3:
|
|
195
|
+
// Row 3: Open P&L | Closed P&L (R Trader style breakdown)
|
|
196
|
+
// Data from Rithmic PNL_PLANT WebSocket - show '--' if null (no data from API)
|
|
197
|
+
const openPnl = stats.openPnl;
|
|
198
|
+
const closedPnl = stats.closedPnl;
|
|
199
|
+
const openPnlStr = openPnl === null || openPnl === undefined
|
|
200
|
+
? '--'
|
|
201
|
+
: (openPnl >= 0 ? `+$${openPnl.toFixed(2)}` : `-$${Math.abs(openPnl).toFixed(2)}`);
|
|
202
|
+
const closedPnlStr = closedPnl === null || closedPnl === undefined
|
|
203
|
+
? '--'
|
|
204
|
+
: (closedPnl >= 0 ? `+$${closedPnl.toFixed(2)}` : `-$${Math.abs(closedPnl).toFixed(2)}`);
|
|
205
|
+
const openPnlColor = (openPnl || 0) >= 0 ? chalk.green : chalk.red;
|
|
206
|
+
const closedPnlColor = (closedPnl || 0) >= 0 ? chalk.green : chalk.red;
|
|
207
|
+
const r3c1 = buildCell('OPEN P&L', openPnlStr, openPnlColor, colL);
|
|
208
|
+
const r3c2 = buildCell('CLOSED P&L', closedPnlStr, closedPnlColor, colR);
|
|
209
|
+
row(r3c1.padded, r3c2.padded);
|
|
210
|
+
|
|
211
|
+
this._line(chalk.cyan(GM));
|
|
212
|
+
|
|
213
|
+
// Row 4: Target | Risk
|
|
193
214
|
const targetStr = stats.target !== null && stats.target !== undefined ? '$' + stats.target.toFixed(2) : '--';
|
|
194
215
|
const riskStr = stats.risk !== null && stats.risk !== undefined ? '$' + stats.risk.toFixed(2) : '--';
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
row(
|
|
216
|
+
const r4c1 = buildCell('TARGET', targetStr, chalk.green, colL);
|
|
217
|
+
const r4c2 = buildCell('RISK', riskStr, chalk.red, colR);
|
|
218
|
+
row(r4c1.padded, r4c2.padded);
|
|
198
219
|
|
|
199
220
|
this._line(chalk.cyan(GM));
|
|
200
221
|
|
|
201
|
-
// Row
|
|
202
|
-
const
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
|
|
222
|
+
// Row 5: Trades W/L | Entry Price (if in position)
|
|
223
|
+
const r5c1t = ` ${chalk.bold('TRADES')}: ${chalk.cyan.bold(stats.trades || 0)} ${chalk.bold('W/L')}: ${chalk.green.bold(stats.wins || 0)}/${chalk.red.bold(stats.losses || 0)}`;
|
|
224
|
+
const r5c1p = ` TRADES: ${stats.trades || 0} W/L: ${stats.wins || 0}/${stats.losses || 0}`;
|
|
225
|
+
const entryStr = stats.entryPrice > 0 ? stats.entryPrice.toFixed(2) : '--';
|
|
226
|
+
const r5c2 = buildCell('ENTRY', entryStr, chalk.yellow, colR);
|
|
227
|
+
row(r5c1t + pad(colL - r5c1p.length), r5c2.padded);
|
|
206
228
|
|
|
207
229
|
this._line(chalk.cyan(GM));
|
|
208
230
|
|
|
209
|
-
// Row
|
|
231
|
+
// Row 6: Connection | Propfirm
|
|
210
232
|
const connection = stats.platform || 'ProjectX';
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
row(
|
|
233
|
+
const r6c1 = buildCell('CONNECTION', connection, chalk.cyan, colL);
|
|
234
|
+
const r6c2 = buildCell('PROPFIRM', stats.propfirm || 'N/A', chalk.cyan, colR);
|
|
235
|
+
row(r6c1.padded, r6c2.padded);
|
|
214
236
|
|
|
215
237
|
this._line(chalk.cyan(GB));
|
|
216
238
|
}
|