hedgequantx 2.9.144 → 2.9.145
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
CHANGED
|
@@ -358,45 +358,7 @@ class SmartLogsEngine {
|
|
|
358
358
|
|
|
359
359
|
const t = [];
|
|
360
360
|
|
|
361
|
-
// ===
|
|
362
|
-
if (isBull) {
|
|
363
|
-
t.push({ type: 'bullish', message: `${S} ${P} heavy paper on the bid | Size lifting offers ${D} | Tape running` });
|
|
364
|
-
t.push({ type: 'bullish', message: `${SL} bid refreshing at ${P} | ${OFI} | Buyers in control` });
|
|
365
|
-
t.push({ type: 'bullish', message: `Large prints on ${S} ${P} | ${VPIN} toxic | Institutions lifting` });
|
|
366
|
-
t.push({ type: 'bullish', message: `${S} squeeze building at ${P} | Shorts underwater | ${D} accelerating` });
|
|
367
|
-
t.push({ type: 'bullish', message: `Block buyer ${SL} ${P} | ${IMB} buy tape | Iceberg absorbing supply` });
|
|
368
|
-
t.push({ type: 'bullish', message: `${S} momentum ignition at ${P} | DOM stacked bid | Offers lifted` });
|
|
369
|
-
t.push({ type: 'bullish', message: `Aggressive buying ${S} at ${P} | ${ZS} | Sellers capitulating` });
|
|
370
|
-
t.push({ type: 'bullish', message: `${S} ${P} bid wall holding | ${D} | Passive offers exhausted` });
|
|
371
|
-
t.push({ type: 'bullish', message: `Dark pool bid ${SL} ${P} | ${VPIN} | Smart money accumulating` });
|
|
372
|
-
t.push({ type: 'bullish', message: `${S} footprint bullish at ${P} | ${tps} tps | Institutional absorption` });
|
|
373
|
-
}
|
|
374
|
-
// === BEARISH FLOW ===
|
|
375
|
-
else if (isBear) {
|
|
376
|
-
t.push({ type: 'bearish', message: `${S} ${P} heavy paper on offer | Size hitting bids ${D} | Tape dumping` });
|
|
377
|
-
t.push({ type: 'bearish', message: `${SL} offer refreshing at ${P} | ${OFI} | Sellers in control` });
|
|
378
|
-
t.push({ type: 'bearish', message: `Large prints selling ${S} ${P} | ${VPIN} toxic | Institutions hitting` });
|
|
379
|
-
t.push({ type: 'bearish', message: `${S} breakdown at ${P} | Longs underwater | ${D} accelerating` });
|
|
380
|
-
t.push({ type: 'bearish', message: `Block seller ${SL} ${P} | ${IMB} sell tape | Iceberg absorbing demand` });
|
|
381
|
-
t.push({ type: 'bearish', message: `${S} momentum breakdown at ${P} | DOM stacked offer | Bids hit` });
|
|
382
|
-
t.push({ type: 'bearish', message: `Aggressive selling ${S} at ${P} | ${ZS} | Buyers capitulating` });
|
|
383
|
-
t.push({ type: 'bearish', message: `${S} ${P} offer wall capping | ${D} | Passive bids exhausted` });
|
|
384
|
-
t.push({ type: 'bearish', message: `Dark pool offer ${SL} ${P} | ${VPIN} | Smart money distributing` });
|
|
385
|
-
t.push({ type: 'bearish', message: `${S} footprint bearish at ${P} | ${tps} tps | Institutional distribution` });
|
|
386
|
-
}
|
|
387
|
-
// === NEUTRAL/CHOP ===
|
|
388
|
-
else {
|
|
389
|
-
t.push({ type: 'analysis', message: `${S} ${P} two-way paper | ${D} flat | Locals making markets` });
|
|
390
|
-
t.push({ type: 'analysis', message: `${SL} chopping at ${P} | Spread ${spd}t | No directional flow` });
|
|
391
|
-
t.push({ type: 'analysis', message: `${S} balanced at ${P} | ${VPIN} | Waiting for size to show` });
|
|
392
|
-
t.push({ type: 'analysis', message: `Range trade ${S} ${P} | Book symmetric | Mean reversion active` });
|
|
393
|
-
t.push({ type: 'analysis', message: `${S} consolidating at ${P} | ${ZS} | No edge either side` });
|
|
394
|
-
t.push({ type: 'analysis', message: `Quiet tape ${SL} ${P} | ${tps} tps | Institutions on sidelines` });
|
|
395
|
-
t.push({ type: 'analysis', message: `${S} ${P} fair value auction | ${D} | Algos scalping spread` });
|
|
396
|
-
t.push({ type: 'analysis', message: `Flow balanced ${S} at ${P} | ${OFI} | Awaiting catalyst` });
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// === HQX-2B: Liquidity Sweep ===
|
|
361
|
+
// === HQX-2B: Liquidity Sweep Strategy ===
|
|
400
362
|
if (isHQX2B) {
|
|
401
363
|
if (phase === 'ready' && zones > 0) {
|
|
402
364
|
t.push({ type: 'signal', message: `${chalk.green.bold('SWEEP')} ${S} ${P} | ${zones} stops triggered | Reversal confirmed` });
|
|
@@ -406,12 +368,24 @@ class SmartLogsEngine {
|
|
|
406
368
|
t.push({ type: 'analysis', message: `${S} ${P} approaching liquidity | ${zones} clusters mapped | Sweep imminent` });
|
|
407
369
|
t.push({ type: 'analysis', message: `Stop hunt setup ${SL} ${P} | ${swings} swings | Watching penetration` });
|
|
408
370
|
t.push({ type: 'analysis', message: `${S} zone test at ${P} | ${zones} targets | Monitoring rejection` });
|
|
371
|
+
} else if (isBull) {
|
|
372
|
+
t.push({ type: 'bullish', message: `${S} ${P} bid absorption | ${D} | Stops below being hunted` });
|
|
373
|
+
t.push({ type: 'bullish', message: `${SL} liquidity building at ${P} | Sweep setup forming | ${swings} pivots` });
|
|
374
|
+
t.push({ type: 'bullish', message: `Institutional bid ${S} ${P} | ${OFI} | Retail shorts trapped` });
|
|
375
|
+
t.push({ type: 'bullish', message: `${S} false breakdown at ${P} | ${D} | Smart money buying dip` });
|
|
376
|
+
} else if (isBear) {
|
|
377
|
+
t.push({ type: 'bearish', message: `${S} ${P} offer absorption | ${D} | Stops above being hunted` });
|
|
378
|
+
t.push({ type: 'bearish', message: `${SL} liquidity building at ${P} | Sweep setup forming | ${swings} pivots` });
|
|
379
|
+
t.push({ type: 'bearish', message: `Institutional offer ${S} ${P} | ${OFI} | Retail longs trapped` });
|
|
380
|
+
t.push({ type: 'bearish', message: `${S} false breakout at ${P} | ${D} | Smart money selling rally` });
|
|
409
381
|
} else {
|
|
410
|
-
t.push({ type: 'system', message: `Mapping ${S} structure at ${P} | ${bars} bars | ${swings} swings
|
|
411
|
-
t.push({ type: 'system', message: `${SL}
|
|
382
|
+
t.push({ type: 'system', message: `Mapping ${S} structure at ${P} | ${bars} bars | ${swings} swings` });
|
|
383
|
+
t.push({ type: 'system', message: `${SL} scanning zones at ${P} | ${tickCount} ticks | Detecting clusters` });
|
|
384
|
+
t.push({ type: 'analysis', message: `${S} ${P} consolidating | ${D} | Liquidity pooling at extremes` });
|
|
385
|
+
t.push({ type: 'analysis', message: `${SL} range at ${P} | Stops accumulating | Sweep pending` });
|
|
412
386
|
}
|
|
413
387
|
}
|
|
414
|
-
// === ULTRA-SCALPING: Quant/Stats ===
|
|
388
|
+
// === ULTRA-SCALPING: Quant/Stats Strategy ===
|
|
415
389
|
else {
|
|
416
390
|
if (phase === 'ready') {
|
|
417
391
|
t.push({ type: 'signal', message: `${chalk.green.bold('EDGE')} ${S} ${P} | ${ZS} breach | ${VPIN} | Execute` });
|
|
@@ -421,9 +395,19 @@ class SmartLogsEngine {
|
|
|
421
395
|
t.push({ type: 'analysis', message: `${S} ${P} factors building | ${ZS} | Threshold proximity` });
|
|
422
396
|
t.push({ type: 'analysis', message: `${SL} edge forming at ${P} | ${VPIN} | Monitoring` });
|
|
423
397
|
t.push({ type: 'analysis', message: `Statistical setup ${S} ${P} | ${OFI} | Alignment ${IMB}` });
|
|
398
|
+
} else if (isBull) {
|
|
399
|
+
t.push({ type: 'bullish', message: `${S} ${P} heavy paper bid | ${D} | ${VPIN} rising` });
|
|
400
|
+
t.push({ type: 'bullish', message: `${SL} ${P} ${ZS} bullish | ${OFI} | Mean reversion long` });
|
|
401
|
+
t.push({ type: 'bullish', message: `${S} momentum ${P} | ${IMB} buy | Quant signal building` });
|
|
402
|
+
} else if (isBear) {
|
|
403
|
+
t.push({ type: 'bearish', message: `${S} ${P} heavy paper offer | ${D} | ${VPIN} rising` });
|
|
404
|
+
t.push({ type: 'bearish', message: `${SL} ${P} ${ZS} bearish | ${OFI} | Mean reversion short` });
|
|
405
|
+
t.push({ type: 'bearish', message: `${S} momentum ${P} | ${IMB} sell | Quant signal building` });
|
|
424
406
|
} else {
|
|
425
407
|
t.push({ type: 'system', message: `Calibrating ${S} models at ${P} | ${bars} bars | Computing factors` });
|
|
426
408
|
t.push({ type: 'system', message: `${SL} tick analysis at ${P} | ${tickCount} samples | ${tps} tps` });
|
|
409
|
+
t.push({ type: 'analysis', message: `${S} ${P} neutral | ${ZS} | ${VPIN} | Awaiting edge` });
|
|
410
|
+
t.push({ type: 'analysis', message: `${SL} range at ${P} | ${D} | Statistical mean reversion` });
|
|
427
411
|
}
|
|
428
412
|
}
|
|
429
413
|
|
|
@@ -286,16 +286,22 @@ const executeMultiSymbol = async ({ service, account, contracts, config, strateg
|
|
|
286
286
|
let startingPnL = null;
|
|
287
287
|
const pollPnL = async () => {
|
|
288
288
|
try {
|
|
289
|
-
// Get P&L from cache (no API call)
|
|
290
289
|
const accId = account.rithmicAccountId || account.accountId;
|
|
291
|
-
const pnlData = service.getAccountPnL ? service.getAccountPnL(accId) : null;
|
|
292
290
|
|
|
293
|
-
|
|
291
|
+
// Get P&L from cache (sync for RithmicService, async for BrokerClient)
|
|
292
|
+
let pnlData = null;
|
|
293
|
+
if (service.getAccountPnL) {
|
|
294
|
+
const result = service.getAccountPnL(accId);
|
|
295
|
+
pnlData = result && result.then ? await result : result; // Handle both sync/async
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (pnlData && pnlData.pnl !== null && pnlData.pnl !== undefined && !isNaN(pnlData.pnl)) {
|
|
294
299
|
if (startingPnL === null) startingPnL = pnlData.pnl;
|
|
295
|
-
|
|
300
|
+
const newPnl = pnlData.pnl - startingPnL;
|
|
301
|
+
if (!isNaN(newPnl)) globalStats.pnl = newPnl;
|
|
296
302
|
}
|
|
297
303
|
|
|
298
|
-
// Check positions (less frequent - every 10s
|
|
304
|
+
// Check positions (less frequent - every 10s)
|
|
299
305
|
if (Date.now() % 10000 < 2000) {
|
|
300
306
|
const posResult = await service.getPositions(accId);
|
|
301
307
|
if (posResult.success && posResult.positions) {
|
|
@@ -306,13 +312,15 @@ const executeMultiSymbol = async ({ service, account, contracts, config, strateg
|
|
|
306
312
|
}
|
|
307
313
|
}
|
|
308
314
|
|
|
309
|
-
// Risk checks
|
|
310
|
-
if (globalStats.pnl
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
315
|
+
// Risk checks (only if pnl is valid)
|
|
316
|
+
if (!isNaN(globalStats.pnl)) {
|
|
317
|
+
if (globalStats.pnl >= dailyTarget) {
|
|
318
|
+
stopReason = 'target'; running = false;
|
|
319
|
+
ui.addLog('fill_win', `TARGET REACHED! +$${globalStats.pnl.toFixed(2)}`);
|
|
320
|
+
} else if (globalStats.pnl <= -maxRisk) {
|
|
321
|
+
stopReason = 'risk'; running = false;
|
|
322
|
+
ui.addLog('fill_loss', `MAX RISK! -$${Math.abs(globalStats.pnl).toFixed(2)}`);
|
|
323
|
+
}
|
|
316
324
|
}
|
|
317
325
|
} catch (e) { /* silent */ }
|
|
318
326
|
};
|
|
@@ -321,23 +329,29 @@ const executeMultiSymbol = async ({ service, account, contracts, config, strateg
|
|
|
321
329
|
const pnlInterval = setInterval(() => { if (running) pollPnL(); }, 2000);
|
|
322
330
|
pollPnL();
|
|
323
331
|
|
|
324
|
-
// Live analysis logs every
|
|
332
|
+
// Live analysis logs every 5 seconds (rotates through symbols with data)
|
|
325
333
|
let liveLogSymbolIndex = 0;
|
|
326
|
-
let
|
|
334
|
+
let lastLiveLogTime = 0;
|
|
327
335
|
const liveLogInterval = setInterval(() => {
|
|
328
336
|
if (!running) return;
|
|
329
|
-
const now =
|
|
330
|
-
if (now
|
|
331
|
-
|
|
337
|
+
const now = Date.now();
|
|
338
|
+
if (now - lastLiveLogTime < 5000) return; // Every 5 seconds
|
|
339
|
+
lastLiveLogTime = now;
|
|
332
340
|
|
|
333
|
-
// Get
|
|
341
|
+
// Get symbols with tick data (skip symbols without data)
|
|
334
342
|
const symbolCodes = Array.from(symbolData.keys());
|
|
335
343
|
if (symbolCodes.length === 0) return;
|
|
336
344
|
|
|
337
|
-
|
|
338
|
-
|
|
345
|
+
// Find next symbol with data
|
|
346
|
+
let attempts = 0;
|
|
347
|
+
let symbolCode, data;
|
|
348
|
+
do {
|
|
349
|
+
symbolCode = symbolCodes[liveLogSymbolIndex % symbolCodes.length];
|
|
350
|
+
liveLogSymbolIndex++;
|
|
351
|
+
data = symbolData.get(symbolCode);
|
|
352
|
+
attempts++;
|
|
353
|
+
} while ((!data || data.stats.tickCount === 0) && attempts < symbolCodes.length);
|
|
339
354
|
|
|
340
|
-
const data = symbolData.get(symbolCode);
|
|
341
355
|
if (!data) return;
|
|
342
356
|
|
|
343
357
|
const state = data.strategy.getAnalysisState?.(symbolCode, data.stats.lastPrice);
|
|
@@ -353,10 +367,13 @@ const executeMultiSymbol = async ({ service, account, contracts, config, strateg
|
|
|
353
367
|
tickCount: data.stats.tickCount || 0,
|
|
354
368
|
};
|
|
355
369
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
370
|
+
// Only log if we have meaningful data
|
|
371
|
+
if (logState.price > 0 || logState.tickCount > 0) {
|
|
372
|
+
logsEngine.setSymbol(symbolCode);
|
|
373
|
+
const log = logsEngine.getLog(logState);
|
|
374
|
+
ui.addLog(log.type, log.message);
|
|
375
|
+
if (log.logToSession) sessionLogger.log('ANALYSIS', `[${symbolCode}] ${log.message}`);
|
|
376
|
+
}
|
|
360
377
|
}, 1000);
|
|
361
378
|
|
|
362
379
|
// Key handler
|
package/src/pages/algo/ui.js
CHANGED
|
@@ -188,9 +188,9 @@ class AlgoUI {
|
|
|
188
188
|
// Row 1: Account | Symbol(s)
|
|
189
189
|
const accountName = String(stats.accountName || 'N/A').substring(0, 40);
|
|
190
190
|
const isMultiSymbol = stats.symbolCount && stats.symbolCount > 1;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
// Show actual symbols list, truncate if too long
|
|
192
|
+
const symbolsStr = String(stats.symbols || stats.symbol || 'N/A');
|
|
193
|
+
const symbolDisplay = symbolsStr.length > 35 ? symbolsStr.substring(0, 32) + '...' : symbolsStr;
|
|
194
194
|
const r1c1 = buildCell('Account', accountName, chalk.cyan, colL);
|
|
195
195
|
const r1c2 = buildCell(isMultiSymbol ? 'Symbols' : 'Symbol', symbolDisplay, chalk.yellow, colR);
|
|
196
196
|
row(r1c1.padded, r1c2.padded);
|
|
@@ -232,13 +232,13 @@ class RithmicBrokerClient extends EventEmitter {
|
|
|
232
232
|
*/
|
|
233
233
|
getRithmicCredentials() {
|
|
234
234
|
// Sync call - return cached credentials
|
|
235
|
-
|
|
236
|
-
return
|
|
235
|
+
if (!this.credentials) return null;
|
|
236
|
+
return {
|
|
237
237
|
userId: this.credentials.username,
|
|
238
238
|
password: this.credentials.password,
|
|
239
239
|
systemName: this.propfirm?.systemName || 'Apex',
|
|
240
|
-
gateway: 'wss://
|
|
241
|
-
}
|
|
240
|
+
gateway: 'wss://rprotocol.rithmic.com:443',
|
|
241
|
+
};
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
/**
|