hedgequantx 2.6.59 → 2.6.60
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
package/src/config/settings.js
CHANGED
|
@@ -143,11 +143,15 @@ const FAST_SCALPING = {
|
|
|
143
143
|
MAX_HOLD_MS: 60000, // 60 seconds failsafe (force exit if stuck)
|
|
144
144
|
|
|
145
145
|
// Exit targets (in ticks) - defaults, override per symbol
|
|
146
|
-
TARGET_TICKS: 16, // Take profit target
|
|
147
|
-
STOP_TICKS: 20, // Stop loss
|
|
146
|
+
TARGET_TICKS: 16, // Take profit target (+$80 on NQ)
|
|
147
|
+
STOP_TICKS: 20, // Stop loss (-$100 on NQ)
|
|
148
|
+
|
|
149
|
+
// Breakeven (BE) - move SL to entry price after profit threshold
|
|
150
|
+
BREAKEVEN_ACTIVATION_TICKS: 6, // Activate BE after +6 ticks profit (+$30 on NQ)
|
|
151
|
+
BREAKEVEN_OFFSET_TICKS: 1, // BE at entry + 1 tick (small profit lock)
|
|
148
152
|
|
|
149
153
|
// Trailing stop (activates after MIN_HOLD + profit threshold)
|
|
150
|
-
TRAILING_ACTIVATION_TICKS: 8, // Start trailing after +8 ticks profit
|
|
154
|
+
TRAILING_ACTIVATION_TICKS: 8, // Start trailing after +8 ticks profit (+$40 on NQ)
|
|
151
155
|
TRAILING_DISTANCE_TICKS: 4, // Trail 4 ticks behind high/low
|
|
152
156
|
|
|
153
157
|
// Position monitoring
|
|
@@ -356,6 +356,10 @@ const launchAlgo = async (service, account, contract, config) => {
|
|
|
356
356
|
algoLogger.info(ui, 'READY', `Hold complete - monitoring exit`);
|
|
357
357
|
});
|
|
358
358
|
|
|
359
|
+
positionManager.on('breakevenActivated', ({ orderTag, position, breakevenPrice, pnlTicks }) => {
|
|
360
|
+
algoLogger.info(ui, 'BE', `Breakeven activated @ ${breakevenPrice} | +${pnlTicks} ticks`);
|
|
361
|
+
});
|
|
362
|
+
|
|
359
363
|
positionManager.on('exitOrderFired', ({ orderTag, exitReason, latencyMs }) => {
|
|
360
364
|
// Don't log here - exitFilled will log the result
|
|
361
365
|
});
|
|
@@ -58,6 +58,8 @@ const WEIGHTS = {
|
|
|
58
58
|
* @property {number} lowWaterMark - Lowest price since entry (for trailing)
|
|
59
59
|
* @property {string} status - 'pending' | 'active' | 'holding' | 'exiting' | 'closed'
|
|
60
60
|
* @property {boolean} holdComplete - True after MIN_HOLD_MS elapsed
|
|
61
|
+
* @property {boolean} breakevenActive - True after BE threshold reached
|
|
62
|
+
* @property {number|null} breakevenPrice - Price at which BE stop is set
|
|
61
63
|
* @property {Object|null} exitReason - Why position was exited
|
|
62
64
|
* @property {number} tickSize - Tick size from API
|
|
63
65
|
* @property {number} tickValue - Tick value from API
|
|
@@ -214,6 +216,8 @@ class PositionManager extends EventEmitter {
|
|
|
214
216
|
lowWaterMark: null,
|
|
215
217
|
status: 'pending', // Waiting for fill confirmation
|
|
216
218
|
holdComplete: false,
|
|
219
|
+
breakevenActive: false, // BE not yet activated
|
|
220
|
+
breakevenPrice: null, // Will be set when BE activates
|
|
217
221
|
exitReason: null,
|
|
218
222
|
latencyMs,
|
|
219
223
|
// Contract info from API (NOT hardcoded)
|
|
@@ -483,18 +487,64 @@ class PositionManager extends EventEmitter {
|
|
|
483
487
|
return { type: 'target', reason: 'Target reached', pnlTicks };
|
|
484
488
|
}
|
|
485
489
|
|
|
486
|
-
// 2.
|
|
487
|
-
if (
|
|
490
|
+
// 2. BREAKEVEN CHECK - If BE is active, use BE price as stop
|
|
491
|
+
if (position.breakevenActive && position.breakevenPrice !== null) {
|
|
492
|
+
const tickSize = this._getTickSize(position);
|
|
493
|
+
if (tickSize) {
|
|
494
|
+
// Check if price hit breakeven stop
|
|
495
|
+
if (position.side === 0) { // Long
|
|
496
|
+
if (currentPrice <= position.breakevenPrice) {
|
|
497
|
+
return { type: 'breakeven', reason: 'Breakeven stop hit', pnlTicks };
|
|
498
|
+
}
|
|
499
|
+
} else { // Short
|
|
500
|
+
if (currentPrice >= position.breakevenPrice) {
|
|
501
|
+
return { type: 'breakeven', reason: 'Breakeven stop hit', pnlTicks };
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// 3. STOP HIT - Only if BE not active (original stop)
|
|
508
|
+
if (!position.breakevenActive && pnlTicks <= -stopTicks) {
|
|
488
509
|
return { type: 'stop', reason: 'Stop loss hit', pnlTicks };
|
|
489
510
|
}
|
|
490
511
|
|
|
491
|
-
//
|
|
512
|
+
// 4. ACTIVATE BREAKEVEN - Move stop to entry after profit threshold
|
|
513
|
+
if (!position.breakevenActive && pnlTicks >= FAST_SCALPING.BREAKEVEN_ACTIVATION_TICKS) {
|
|
514
|
+
const tickSize = this._getTickSize(position);
|
|
515
|
+
if (tickSize && position.entryPrice) {
|
|
516
|
+
// Set BE price at entry + offset (small profit lock)
|
|
517
|
+
const offset = FAST_SCALPING.BREAKEVEN_OFFSET_TICKS * tickSize;
|
|
518
|
+
if (position.side === 0) { // Long
|
|
519
|
+
position.breakevenPrice = position.entryPrice + offset;
|
|
520
|
+
} else { // Short
|
|
521
|
+
position.breakevenPrice = position.entryPrice - offset;
|
|
522
|
+
}
|
|
523
|
+
position.breakevenActive = true;
|
|
524
|
+
|
|
525
|
+
log.info('BREAKEVEN ACTIVATED', {
|
|
526
|
+
symbol: position.symbol,
|
|
527
|
+
entryPrice: position.entryPrice,
|
|
528
|
+
bePrice: position.breakevenPrice,
|
|
529
|
+
pnlTicks,
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
this.emit('breakevenActivated', {
|
|
533
|
+
orderTag: position.orderTag,
|
|
534
|
+
position,
|
|
535
|
+
breakevenPrice: position.breakevenPrice,
|
|
536
|
+
pnlTicks,
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// 5. VPIN DANGER - Informed traders detected (from strategy)
|
|
492
542
|
const vpin = this._getVPIN(position);
|
|
493
543
|
if (vpin !== null && vpin > MOMENTUM.VPIN_DANGER) {
|
|
494
544
|
return { type: 'vpin', reason: `VPIN spike ${(vpin * 100).toFixed(0)}% - informed traders`, pnlTicks, vpin };
|
|
495
545
|
}
|
|
496
546
|
|
|
497
|
-
//
|
|
547
|
+
// 6. TRAILING STOP (only if in profit above threshold)
|
|
498
548
|
if (pnlTicks >= FAST_SCALPING.TRAILING_ACTIVATION_TICKS) {
|
|
499
549
|
const trailingPnl = this._calculateTrailingPnl(position, currentPrice);
|
|
500
550
|
if (trailingPnl !== null && trailingPnl <= -FAST_SCALPING.TRAILING_DISTANCE_TICKS) {
|
|
@@ -502,7 +552,7 @@ class PositionManager extends EventEmitter {
|
|
|
502
552
|
}
|
|
503
553
|
}
|
|
504
554
|
|
|
505
|
-
//
|
|
555
|
+
// 7. MOMENTUM-BASED EXIT (using strategy's math models)
|
|
506
556
|
const momentum = this._calculateMomentum(position);
|
|
507
557
|
|
|
508
558
|
if (momentum !== null) {
|