hedgequantx 2.9.83 → 2.9.85

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.
@@ -65,10 +65,16 @@ var require_config = __commonJS({
65
65
  commissionPerSide: 2
66
66
  // $4 round-trip
67
67
  },
68
- // Session (Futures Market Hours - Sunday 18:00 to Friday 17:00 EST)
68
+ // Session filter (US Regular Hours only - matches backtest)
69
69
  session: {
70
- enabled: false,
71
- // Trade anytime markets are open
70
+ enabled: true,
71
+ // MUST be enabled to match backtest results
72
+ startHour: 9,
73
+ // 9:30 AM EST
74
+ startMinute: 30,
75
+ endHour: 16,
76
+ // 4:00 PM EST
77
+ endMinute: 0,
72
78
  timezone: "America/New_York"
73
79
  }
74
80
  };
@@ -487,6 +493,31 @@ var require_core = __commonJS({
487
493
  message: `[HQX-2B] Params: Stop=${this.config.execution.stopTicks}t, Target=${this.config.execution.targetTicks}t, BE=${this.config.execution.breakevenTicks}t, Trail=${this.config.execution.trailTriggerTicks}/${this.config.execution.trailDistanceTicks}`
488
494
  });
489
495
  }
496
+ /**
497
+ * Check if current time is within trading session (9:30-16:00 EST)
498
+ */
499
+ isWithinSession(timestamp) {
500
+ if (!this.config.session.enabled) return true;
501
+ const date = new Date(timestamp);
502
+ const estOffset = this.isDST(date) ? -4 : -5;
503
+ const utcHours = date.getUTCHours();
504
+ const utcMinutes = date.getUTCMinutes();
505
+ const estHours = (utcHours + estOffset + 24) % 24;
506
+ const { startHour, startMinute, endHour, endMinute } = this.config.session;
507
+ const currentMins = estHours * 60 + utcMinutes;
508
+ const startMins = startHour * 60 + startMinute;
509
+ const endMins = endHour * 60 + endMinute;
510
+ return currentMins >= startMins && currentMins < endMins;
511
+ }
512
+ /**
513
+ * Check if date is in US Daylight Saving Time
514
+ */
515
+ isDST(date) {
516
+ const jan = new Date(date.getFullYear(), 0, 1);
517
+ const jul = new Date(date.getFullYear(), 6, 1);
518
+ const stdOffset = Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
519
+ return date.getTimezoneOffset() < stdOffset;
520
+ }
490
521
  /**
491
522
  * Process incoming tick and aggregate into 1-minute bars
492
523
  * Only calls processBar() when a bar closes (every 60 seconds)
@@ -495,6 +526,9 @@ var require_core = __commonJS({
495
526
  const { contractId, price, volume, timestamp } = tick;
496
527
  const ts = timestamp || Date.now();
497
528
  const vol = volume || 1;
529
+ if (!this.isWithinSession(ts)) {
530
+ return null;
531
+ }
498
532
  let bar = this.currentBar.get(contractId);
499
533
  const barStartTime = Math.floor(ts / this.barIntervalMs) * this.barIntervalMs;
500
534
  if (!bar || bar.startTime !== barStartTime) {
@@ -560,6 +594,7 @@ var require_core = __commonJS({
560
594
  return null;
561
595
  }
562
596
  const swings = this.swingPoints.get(contractId);
597
+ const prevSwingCount = swings.length;
563
598
  const updatedSwings = detectSwings(
564
599
  bars,
565
600
  currentIndex,
@@ -568,7 +603,15 @@ var require_core = __commonJS({
568
603
  this.config.zone.maxZoneAgeBars
569
604
  );
570
605
  this.swingPoints.set(contractId, updatedSwings);
606
+ if (updatedSwings.length > prevSwingCount) {
607
+ const newSwing = updatedSwings[updatedSwings.length - 1];
608
+ this.emit("log", {
609
+ type: "debug",
610
+ message: `[2B] NEW SWING ${newSwing.type.toUpperCase()} @ ${newSwing.price.toFixed(2)} | Total: ${updatedSwings.length}`
611
+ });
612
+ }
571
613
  const zones = this.liquidityZones.get(contractId);
614
+ const prevZoneCount = zones.length;
572
615
  const updatedZones = updateZones(
573
616
  updatedSwings,
574
617
  zones,
@@ -577,6 +620,13 @@ var require_core = __commonJS({
577
620
  this.tickSize
578
621
  );
579
622
  this.liquidityZones.set(contractId, updatedZones);
623
+ if (updatedZones.length > prevZoneCount) {
624
+ const newZone = updatedZones[updatedZones.length - 1];
625
+ this.emit("log", {
626
+ type: "debug",
627
+ message: `[2B] NEW ZONE ${newZone.type.toUpperCase()} @ ${newZone.getLevel().toFixed(2)} | Total: ${updatedZones.length}`
628
+ });
629
+ }
580
630
  const sweep = detectSweep(
581
631
  updatedZones,
582
632
  bars,
@@ -585,6 +635,12 @@ var require_core = __commonJS({
585
635
  this.config.zone,
586
636
  this.tickSize
587
637
  );
638
+ if (sweep) {
639
+ this.emit("log", {
640
+ type: "debug",
641
+ message: `[2B] SWEEP ${sweep.sweepType} | Valid: ${sweep.isValid} | Pen: ${sweep.penetrationTicks.toFixed(1)}t | Q: ${(sweep.qualityScore * 100).toFixed(0)}%`
642
+ });
643
+ }
588
644
  if (sweep && sweep.isValid) {
589
645
  if (Date.now() - this.lastSignalTime < this.config.execution.cooldownMs) {
590
646
  return null;
@@ -1 +1,705 @@
1
- const _0x371eb1=_0x4b27;(function(_0x507643,_0x538df8){const _0x563eca=_0x4b27,_0x3dfc41=_0x507643();while(!![]){try{const _0x42b617=-parseInt(_0x563eca(0x190))/0x1*(-parseInt(_0x563eca(0x156))/0x2)+parseInt(_0x563eca(0x183))/0x3+parseInt(_0x563eca(0x180))/0x4+-parseInt(_0x563eca(0x158))/0x5+parseInt(_0x563eca(0x15e))/0x6*(-parseInt(_0x563eca(0x189))/0x7)+parseInt(_0x563eca(0x137))/0x8+parseInt(_0x563eca(0x13f))/0x9*(-parseInt(_0x563eca(0x181))/0xa);if(_0x42b617===_0x538df8)break;else _0x3dfc41['push'](_0x3dfc41['shift']());}catch(_0xd4d426){_0x3dfc41['push'](_0x3dfc41['shift']());}}}(_0x411a,0x53323));const EventEmitter=require('events'),{v4:uuidv4}=require('uuid'),OrderSide={'BID':0x0,'ASK':0x1},SignalStrength={'WEAK':0x1,'MODERATE':0x2,'STRONG':0x3,'VERY_STRONG':0x4};function _0x411a(){const _0x27a23d=['2475448YZZsWq','kalman','price','kalmanStates','%\x20Kyle:','confidenceBonus','HQX_ULTRA_SCALPING_6MODELS','tickSize','694269rFwgpb','info','exports','BID','profitLockPct','split','ASK','stopMultiplier','trades','length','\x20VPIN:','onTick','\x20Regime:','stats','close','processTick','signal','getAnalysisState','lossStreak','barHistory','_generateSignal','lastSignalTime','getStats','470192mXQQiX','_detectVolatilityRegime','2511350svvQNF','estimate','[HQX-UltraScalping]\x20Initialized\x20for\x20','zscoreThreshold','weights','WEAK','204vdZvxj','now','sell','_computeVPIN','targetMultiplier','_applyKalmanFilter','kalmanProcessNoise',':\x20tick=','zscoreExitThreshold','signals',',\x20streak:\x20','pow','strategy','losses','winStreak','zscoreEntryThreshold','wins','symbol','_calculateATR','baseTargetTicks','filter','ofiLookback','generateSignal','abs','round','buy','initialize','push','reset','toFixed','composite','set','getModelValues','vpinToxicThreshold','1089760NgASxb','110shtkue','shift','2012835ylCsNd',',\x20value=','get','\x20@\x20','emit','Collecting\x20data...\x20','6468ehZsMS','getBarHistory','onTrade','_computeOrderFlowImbalance','high','reduce','breakevenTicks','2KorAWa','6\x20(Z-Score,\x20VPIN,\x20Kyle,\x20Kalman,\x20Vol,\x20OFI)','volumeBuffer','volume','minConfidence','pnl','log','recordTradeResult','long','kyleLambda','processBar','_computeKyleLambda','side','min','kalmanMeasurementNoise','priceBuffer','ofi','errorCovariance','max','short',',\x20VPIN=','slice','zscore','_computeZScore','atrHistory','volatility','low','baseStopTicks'];_0x411a=function(){return _0x27a23d;};return _0x411a();}class HQXUltraScalping extends EventEmitter{constructor(_0x36c01b={}){const _0x500d51=_0x4b27;super(),this[_0x500d51(0x13e)]=_0x36c01b[_0x500d51(0x13e)]||0.25,this['tickValue']=_0x36c01b['tickValue']||0x5,this[_0x500d51(0x16d)]=1.5,this['zscoreExitThreshold']=0.5,this['vpinWindow']=0x32,this['vpinToxicThreshold']=0.7,this[_0x500d51(0x164)]=0.01,this[_0x500d51(0x129)]=0.1,this['volatilityLookback']=0x64,this[_0x500d51(0x173)]=0x14,this['baseStopTicks']=0x8,this[_0x500d51(0x171)]=0x10,this[_0x500d51(0x18f)]=0x4,this['profitLockPct']=0.5,this['minConfidence']=0.55,this[_0x500d51(0x15c)]={'zscore':0.3,'ofi':0.2,'vpin':0.15,'kalman':0.15,'kyleLambda':0.1,'volatility':0.1},this['barHistory']=new Map(),this['priceBuffer']=new Map(),this['volumeBuffer']=new Map(),this[_0x500d51(0x13a)]=new Map(),this['atrHistory']=new Map(),this['recentTrades']=[],this['winStreak']=0x0,this['lossStreak']=0x0,this[_0x500d51(0x154)]=0x0,this['cooldownMs']=0x7530,this['minHoldTimeMs']=0x2710,this['stats']={'signals':0x0,'trades':0x0,'wins':0x0,'losses':0x0,'pnl':0x0};}[_0x371eb1(0x178)](_0x868a52,_0x4a1bf5=0.25,_0x27a4c2=0x5){const _0x4ddb38=_0x371eb1;this[_0x4ddb38(0x13e)]=_0x4a1bf5,this['tickValue']=_0x27a4c2,this[_0x4ddb38(0x152)][_0x4ddb38(0x17d)](_0x868a52,[]),this[_0x4ddb38(0x12a)]['set'](_0x868a52,[]),this[_0x4ddb38(0x192)]['set'](_0x868a52,[]),this[_0x4ddb38(0x133)]['set'](_0x868a52,[]),this[_0x4ddb38(0x13a)][_0x4ddb38(0x17d)](_0x868a52,{'estimate':0x0,'errorCovariance':0x1}),this['emit']('log',{'type':_0x4ddb38(0x140),'message':_0x4ddb38(0x15a)+_0x868a52+_0x4ddb38(0x165)+_0x4a1bf5+_0x4ddb38(0x184)+_0x27a4c2}),this[_0x4ddb38(0x187)](_0x4ddb38(0x121),{'type':_0x4ddb38(0x140),'message':'[HQX-UltraScalping]\x206\x20Models:\x20Z-Score(30%),\x20OFI(20%),\x20VPIN(15%),\x20Kalman(15%),\x20Kyle(10%),\x20Vol(10%)'});}[_0x371eb1(0x14e)](_0x16706f){const _0x4cbeda=_0x371eb1,{contractId:_0x27ef24,price:_0x53c926,volume:_0x388677,side:_0x3dff0d,timestamp:_0x1fd07f}=_0x16706f,_0x4bee87={'timestamp':_0x1fd07f||Date[_0x4cbeda(0x15f)](),'open':_0x53c926,'high':_0x53c926,'low':_0x53c926,'close':_0x53c926,'volume':_0x388677||0x1};return this[_0x4cbeda(0x125)](_0x27ef24,_0x4bee87);}['onTick'](_0x1328b5){const _0x5386f7=_0x371eb1;return this[_0x5386f7(0x14e)](_0x1328b5);}['onTrade'](_0xb54c4c){const _0x4d0ae5=_0x371eb1;return this[_0x4d0ae5(0x14e)]({'contractId':_0xb54c4c['contractId']||_0xb54c4c[_0x4d0ae5(0x16f)],'price':_0xb54c4c[_0x4d0ae5(0x139)],'volume':_0xb54c4c['size']||_0xb54c4c['volume']||0x1,'side':_0xb54c4c[_0x4d0ae5(0x127)],'timestamp':_0xb54c4c['timestamp']||Date[_0x4d0ae5(0x15f)]()});}[_0x371eb1(0x125)](_0x16055a,_0x283841){const _0x48a98e=_0x371eb1;let _0x4f34c0=this[_0x48a98e(0x152)]['get'](_0x16055a);!_0x4f34c0&&(this['initialize'](_0x16055a),_0x4f34c0=this[_0x48a98e(0x152)]['get'](_0x16055a));_0x4f34c0['push'](_0x283841);if(_0x4f34c0[_0x48a98e(0x148)]>0x1f4)_0x4f34c0[_0x48a98e(0x182)]();const _0x1254f0=this['priceBuffer']['get'](_0x16055a);_0x1254f0['push'](_0x283841['close']);if(_0x1254f0[_0x48a98e(0x148)]>0xc8)_0x1254f0[_0x48a98e(0x182)]();const _0x53a2b7=this['volumeBuffer']['get'](_0x16055a),_0x4eb2a6=_0x283841['high']-_0x283841[_0x48a98e(0x135)];let _0x473033=_0x283841[_0x48a98e(0x193)]*0.5,_0x13bb19=_0x283841['volume']*0.5;if(_0x4eb2a6>0x0){const _0x1c3017=(_0x283841['close']-_0x283841[_0x48a98e(0x135)])/_0x4eb2a6;_0x473033=_0x283841[_0x48a98e(0x193)]*_0x1c3017,_0x13bb19=_0x283841[_0x48a98e(0x193)]*(0x1-_0x1c3017);}_0x53a2b7['push']({'buy':_0x473033,'sell':_0x13bb19});if(_0x53a2b7['length']>0x64)_0x53a2b7[_0x48a98e(0x182)]();if(_0x4f34c0[_0x48a98e(0x148)]<0x32)return null;const _0x3dfcad=this['_computeZScore'](_0x1254f0),_0x1837a2=this[_0x48a98e(0x161)](_0x53a2b7),_0x74821=this[_0x48a98e(0x126)](_0x4f34c0),_0x25c8da=this[_0x48a98e(0x163)](_0x16055a,_0x283841['close']),{regime:_0x91e763,params:_0x24948f}=this[_0x48a98e(0x157)](_0x16055a,_0x4f34c0),_0x26a2b9=this[_0x48a98e(0x18c)](_0x4f34c0);return this['_generateSignal'](_0x16055a,_0x283841['close'],_0x3dfcad,_0x1837a2,_0x74821,_0x25c8da,_0x91e763,_0x24948f,_0x26a2b9,_0x4f34c0);}['_computeZScore'](_0x33dfb0,_0x2cf611=0x32){const _0x134efb=_0x371eb1;if(_0x33dfb0['length']<_0x2cf611)return 0x0;const _0x460593=_0x33dfb0[_0x134efb(0x130)](-_0x2cf611),_0x285e3f=_0x460593['reduce']((_0xd9a79b,_0x5d0d53)=>_0xd9a79b+_0x5d0d53,0x0)/_0x2cf611,_0x2cf47a=_0x460593[_0x134efb(0x18e)]((_0x442e16,_0x5b5e94)=>_0x442e16+Math[_0x134efb(0x169)](_0x5b5e94-_0x285e3f,0x2),0x0)/_0x2cf611,_0x42da2b=Math['sqrt'](_0x2cf47a);if(_0x42da2b<0.0001)return 0x0;const _0x4d38c3=_0x33dfb0[_0x33dfb0['length']-0x1];return(_0x4d38c3-_0x285e3f)/_0x42da2b;}[_0x371eb1(0x161)](_0x3b06d8){const _0x2eeedf=_0x371eb1;if(_0x3b06d8['length']<this['vpinWindow'])return 0.5;const _0x23f368=_0x3b06d8['slice'](-this['vpinWindow']);let _0x4031d1=0x0,_0x38689b=0x0;for(const _0x19a355 of _0x23f368){_0x4031d1+=_0x19a355[_0x2eeedf(0x177)],_0x38689b+=_0x19a355[_0x2eeedf(0x160)];}const _0x113023=_0x4031d1+_0x38689b;if(_0x113023<0x1)return 0.5;return Math['abs'](_0x4031d1-_0x38689b)/_0x113023;}['_computeKyleLambda'](_0xf4971c){const _0x813121=_0x371eb1;if(_0xf4971c['length']<0x14)return 0x0;const _0x33bf14=_0xf4971c['slice'](-0x14),_0x57317b=[],_0x34e3fd=[];for(let _0x56111a=0x1;_0x56111a<_0x33bf14[_0x813121(0x148)];_0x56111a++){_0x57317b['push'](_0x33bf14[_0x56111a][_0x813121(0x14d)]-_0x33bf14[_0x56111a-0x1]['close']),_0x34e3fd['push'](_0x33bf14[_0x56111a][_0x813121(0x193)]);}const _0x3d3b37=_0x57317b['reduce']((_0x738715,_0x3216f2)=>_0x738715+_0x3216f2,0x0)/_0x57317b[_0x813121(0x148)],_0x144ac9=_0x34e3fd[_0x813121(0x18e)]((_0x29a9b9,_0x2e41f7)=>_0x29a9b9+_0x2e41f7,0x0)/_0x34e3fd[_0x813121(0x148)];let _0x4b566e=0x0,_0x374f8d=0x0;for(let _0xa01cf4=0x0;_0xa01cf4<_0x57317b['length'];_0xa01cf4++){_0x4b566e+=(_0x57317b[_0xa01cf4]-_0x3d3b37)*(_0x34e3fd[_0xa01cf4]-_0x144ac9),_0x374f8d+=Math['pow'](_0x34e3fd[_0xa01cf4]-_0x144ac9,0x2);}_0x4b566e/=_0x57317b['length'],_0x374f8d/=_0x57317b[_0x813121(0x148)];if(_0x374f8d<0.0001)return 0x0;return Math['abs'](_0x4b566e/_0x374f8d);}[_0x371eb1(0x163)](_0x57d582,_0x3462ce){const _0x24cba8=_0x371eb1;let _0x486837=this[_0x24cba8(0x13a)]['get'](_0x57d582);if(!_0x486837)return _0x486837={'estimate':_0x3462ce,'errorCovariance':0x1},this['kalmanStates'][_0x24cba8(0x17d)](_0x57d582,_0x486837),_0x3462ce;const _0x2dd1da=_0x486837['estimate'],_0xc39734=_0x486837[_0x24cba8(0x12c)]+this['kalmanProcessNoise'],_0x56a97c=_0xc39734/(_0xc39734+this['kalmanMeasurementNoise']),_0x5a7c33=_0x2dd1da+_0x56a97c*(_0x3462ce-_0x2dd1da),_0x52d3e0=(0x1-_0x56a97c)*_0xc39734;return _0x486837[_0x24cba8(0x159)]=_0x5a7c33,_0x486837['errorCovariance']=_0x52d3e0,_0x5a7c33;}[_0x371eb1(0x157)](_0xc85bad,_0x8b120a){const _0x408ec8=_0x371eb1,_0x5aa785=this['_calculateATR'](_0x8b120a),_0x553dc3=_0x5aa785/this[_0x408ec8(0x13e)];let _0x5e843d=this[_0x408ec8(0x133)][_0x408ec8(0x185)](_0xc85bad);!_0x5e843d&&(_0x5e843d=[],this['atrHistory']['set'](_0xc85bad,_0x5e843d));_0x5e843d[_0x408ec8(0x179)](_0x5aa785);if(_0x5e843d[_0x408ec8(0x148)]>0x1f4)_0x5e843d[_0x408ec8(0x182)]();let _0x57b341=0.5;_0x5e843d['length']>=0x14&&(_0x57b341=_0x5e843d[_0x408ec8(0x172)](_0x5260f5=>_0x5260f5<=_0x5aa785)['length']/_0x5e843d['length']);let _0x2e01b2,_0x347a0e;if(_0x57b341<0.25)_0x2e01b2='low',_0x347a0e={'stopMultiplier':0.8,'targetMultiplier':0.9,'zscoreThreshold':1.2,'confidenceBonus':0.05};else _0x57b341<0.75?(_0x2e01b2='normal',_0x347a0e={'stopMultiplier':0x1,'targetMultiplier':0x1,'zscoreThreshold':1.5,'confidenceBonus':0x0}):(_0x2e01b2=_0x408ec8(0x18d),_0x347a0e={'stopMultiplier':1.3,'targetMultiplier':1.2,'zscoreThreshold':0x2,'confidenceBonus':-0.05});return{'regime':_0x2e01b2,'params':_0x347a0e};}[_0x371eb1(0x170)](_0x2d06a1,_0x169650=0xe){const _0x50f133=_0x371eb1;if(_0x2d06a1['length']<_0x169650+0x1)return 2.5;const _0x3d94b5=[];for(let _0x28cbae=_0x2d06a1['length']-_0x169650;_0x28cbae<_0x2d06a1['length'];_0x28cbae++){const _0x3038c5=_0x2d06a1[_0x28cbae],_0x4eb12b=_0x2d06a1[_0x28cbae-0x1]['close'],_0x1b7ea2=Math[_0x50f133(0x12d)](_0x3038c5[_0x50f133(0x18d)]-_0x3038c5[_0x50f133(0x135)],Math[_0x50f133(0x175)](_0x3038c5[_0x50f133(0x18d)]-_0x4eb12b),Math['abs'](_0x3038c5['low']-_0x4eb12b));_0x3d94b5[_0x50f133(0x179)](_0x1b7ea2);}return _0x3d94b5['reduce']((_0x39b5fd,_0xd20ab0)=>_0x39b5fd+_0xd20ab0,0x0)/_0x3d94b5['length'];}['_computeOrderFlowImbalance'](_0x582a89){const _0x4945c9=_0x371eb1;if(_0x582a89[_0x4945c9(0x148)]<this[_0x4945c9(0x173)])return 0x0;const _0x48d888=_0x582a89['slice'](-this['ofiLookback']);let _0x55edd9=0x0,_0x260a92=0x0;for(const _0x176c62 of _0x48d888){const _0x5b2d5a=_0x176c62['high']-_0x176c62[_0x4945c9(0x135)];if(_0x5b2d5a>0x0){const _0x54db25=(_0x176c62[_0x4945c9(0x14d)]-_0x176c62[_0x4945c9(0x135)])/_0x5b2d5a;_0x55edd9+=_0x54db25*_0x176c62[_0x4945c9(0x193)],_0x260a92+=(0x1-_0x54db25)*_0x176c62['volume'];}}const _0x5492ab=_0x55edd9+_0x260a92;if(_0x5492ab<0x1)return 0x0;return(_0x55edd9-_0x260a92)/_0x5492ab;}[_0x371eb1(0x153)](_0x317a32,_0x51668a,_0x1ee39d,_0x3b8899,_0x229d9c,_0x26fa8a,_0x22a87a,_0x38beeb,_0xd56043,_0x518297){const _0x184de5=_0x371eb1,_0x15d504=Math[_0x184de5(0x175)](_0x1ee39d);if(_0x15d504<_0x38beeb['zscoreThreshold'])return null;if(_0x3b8899>this[_0x184de5(0x17f)])return null;let _0x5759b5;if(_0x1ee39d<-_0x38beeb[_0x184de5(0x15b)])_0x5759b5='long';else{if(_0x1ee39d>_0x38beeb['zscoreThreshold'])_0x5759b5='short';else return null;}const _0x4a1fa1=_0x5759b5===_0x184de5(0x123)&&_0xd56043>0.1||_0x5759b5===_0x184de5(0x12e)&&_0xd56043<-0.1,_0x21e280=_0x51668a-_0x26fa8a,_0x493653=_0x5759b5===_0x184de5(0x123)&&_0x21e280<0x0||_0x5759b5===_0x184de5(0x12e)&&_0x21e280>0x0,_0x141172={'zscore':Math['min'](0x1,_0x15d504/0x4),'vpin':0x1-_0x3b8899,'kyleLambda':_0x229d9c>0.001?0.5:0.8,'kalman':_0x493653?0.8:0.4,'volatility':_0x22a87a==='normal'?0.8:_0x22a87a===_0x184de5(0x135)?0.7:0.6,'ofi':_0x4a1fa1?0.9:0.5,'composite':0x0};_0x141172[_0x184de5(0x17c)]=_0x141172['zscore']*this['weights'][_0x184de5(0x131)]+_0x141172['vpin']*this[_0x184de5(0x15c)]['vpin']+_0x141172['kyleLambda']*this['weights'][_0x184de5(0x124)]+_0x141172[_0x184de5(0x138)]*this['weights']['kalman']+_0x141172[_0x184de5(0x134)]*this[_0x184de5(0x15c)]['volatility']+_0x141172[_0x184de5(0x12b)]*this[_0x184de5(0x15c)]['ofi'];const _0x3b6c87=Math[_0x184de5(0x128)](0x1,_0x141172['composite']+_0x38beeb[_0x184de5(0x13c)]);if(_0x3b6c87<this[_0x184de5(0x11f)])return null;if(Date[_0x184de5(0x15f)]()-this[_0x184de5(0x154)]<this['cooldownMs'])return null;const _0x31f489=Math['round'](this[_0x184de5(0x136)]*_0x38beeb[_0x184de5(0x146)]),_0x2a44b6=Math[_0x184de5(0x176)](this[_0x184de5(0x171)]*_0x38beeb[_0x184de5(0x162)]),_0x422654=Math[_0x184de5(0x12d)](0x6,Math[_0x184de5(0x128)](0xc,_0x31f489)),_0x2353e7=Math['max'](_0x422654*1.5,Math[_0x184de5(0x128)](0x18,_0x2a44b6));let _0x1dcea3,_0x2cce06,_0x43e504,_0x495e95;_0x5759b5===_0x184de5(0x123)?(_0x1dcea3=_0x51668a-_0x422654*this[_0x184de5(0x13e)],_0x2cce06=_0x51668a+_0x2353e7*this['tickSize'],_0x43e504=_0x51668a+this['breakevenTicks']*this['tickSize'],_0x495e95=_0x51668a+_0x2353e7*this[_0x184de5(0x143)]*this[_0x184de5(0x13e)]):(_0x1dcea3=_0x51668a+_0x422654*this[_0x184de5(0x13e)],_0x2cce06=_0x51668a-_0x2353e7*this['tickSize'],_0x43e504=_0x51668a-this['breakevenTicks']*this[_0x184de5(0x13e)],_0x495e95=_0x51668a-_0x2353e7*this[_0x184de5(0x143)]*this['tickSize']);const _0x105cdf=_0x2353e7/_0x422654,_0x131f8c=Math[_0x184de5(0x176)](_0x2353e7*0.5),_0xe9a67d=Math[_0x184de5(0x176)](_0x422654*0.4);let _0x1d1787=SignalStrength['MODERATE'];if(_0x3b6c87>=0.85)_0x1d1787=SignalStrength['VERY_STRONG'];else{if(_0x3b6c87>=0.75)_0x1d1787=SignalStrength['STRONG'];else{if(_0x3b6c87<0.6)_0x1d1787=SignalStrength[_0x184de5(0x15d)];}}const _0x17213a=0.5+(_0x3b6c87-0.5)*0.4,_0x4e77a2=_0x17213a*Math[_0x184de5(0x175)](_0x2cce06-_0x51668a)-(0x1-_0x17213a)*Math['abs'](_0x51668a-_0x1dcea3);this['lastSignalTime']=Date['now'](),this['stats'][_0x184de5(0x167)]++;const _0x37f751={'id':uuidv4(),'timestamp':Date['now'](),'symbol':_0x317a32[_0x184de5(0x144)]('.')[0x0]||_0x317a32,'contractId':_0x317a32,'side':_0x5759b5===_0x184de5(0x123)?OrderSide[_0x184de5(0x142)]:OrderSide[_0x184de5(0x145)],'direction':_0x5759b5,'strategy':_0x184de5(0x13d),'strength':_0x1d1787,'edge':_0x4e77a2,'confidence':_0x3b6c87,'entry':_0x51668a,'entryPrice':_0x51668a,'stopLoss':_0x1dcea3,'takeProfit':_0x2cce06,'riskReward':_0x105cdf,'stopTicks':_0x422654,'targetTicks':_0x2353e7,'trailTriggerTicks':_0x131f8c,'trailDistanceTicks':_0xe9a67d,'beBreakeven':_0x43e504,'profitLockLevel':_0x495e95,'zScore':_0x1ee39d,'zScoreExit':this['zscoreExitThreshold'],'vpinValue':_0x3b8899,'kyleLambda':_0x229d9c,'kalmanEstimate':_0x26fa8a,'volatilityRegime':_0x22a87a,'ofiValue':_0xd56043,'models':_0x141172,'orderFlowConfirmed':_0x4a1fa1,'kalmanConfirmed':_0x493653,'expires':Date['now']()+0xea60};return this['emit'](_0x184de5(0x14f),{'side':_0x5759b5==='long'?'buy':'sell','action':'open','reason':'Z='+_0x1ee39d['toFixed'](0x2)+_0x184de5(0x12f)+(_0x3b8899*0x64)[_0x184de5(0x17b)](0x0)+'%,\x20OFI='+(_0xd56043*0x64)[_0x184de5(0x17b)](0x0)+'%,\x20cf='+(_0x3b6c87*0x64)[_0x184de5(0x17b)](0x0)+'%',..._0x37f751}),this['emit']('log',{'type':_0x184de5(0x140),'message':'[HQX]\x20SIGNAL:\x20'+_0x5759b5['toUpperCase']()+_0x184de5(0x186)+_0x51668a[_0x184de5(0x17b)](0x2)+'\x20|\x20Z:'+_0x1ee39d[_0x184de5(0x17b)](0x2)+_0x184de5(0x149)+(_0x3b8899*0x64)[_0x184de5(0x17b)](0x0)+'%\x20OFI:'+(_0xd56043*0x64)['toFixed'](0x0)+_0x184de5(0x13b)+_0x229d9c['toFixed'](0x5)+_0x184de5(0x14b)+_0x22a87a+'\x20|\x20Conf:'+(_0x3b6c87*0x64)['toFixed'](0x0)+'%'}),_0x37f751;}['shouldExitByZScore'](_0x18198d){const _0xe0018e=_0x371eb1,_0x9c72d7=this[_0xe0018e(0x12a)][_0xe0018e(0x185)](_0x18198d);if(!_0x9c72d7||_0x9c72d7[_0xe0018e(0x148)]<0x32)return![];const _0x287ecd=this[_0xe0018e(0x132)](_0x9c72d7);return Math[_0xe0018e(0x175)](_0x287ecd)<this[_0xe0018e(0x166)];}[_0x371eb1(0x17e)](_0x42ff12){const _0x453183=_0x371eb1,_0x4bc437=this[_0x453183(0x12a)][_0x453183(0x185)](_0x42ff12),_0x1d439f=this[_0x453183(0x192)][_0x453183(0x185)](_0x42ff12),_0xb50dc9=this['barHistory'][_0x453183(0x185)](_0x42ff12);if(!_0x4bc437||!_0x1d439f||!_0xb50dc9||_0xb50dc9['length']<0x32)return null;const _0x260c32=this['_computeZScore'](_0x4bc437),_0x276e0e=this[_0x453183(0x161)](_0x1d439f),_0x183dd3=this['_computeKyleLambda'](_0xb50dc9),_0x3df13c=this['_computeOrderFlowImbalance'](_0xb50dc9);return{'zscore':Math['min'](0x1,Math[_0x453183(0x175)](_0x260c32)/0x4),'vpin':0x1-_0x276e0e,'kyleLambda':_0x183dd3>0.001?0.5:0.8,'kalman':0.7,'volatility':0.7,'ofi':Math['abs'](_0x3df13c)>0.1?0.8:0.5,'composite':0.7,'raw':{'zscore':_0x260c32,'vpin':_0x276e0e,'kyleLambda':_0x183dd3,'ofi':_0x3df13c}};}[_0x371eb1(0x150)](_0x104d11,_0xe08a26){const _0x2a256e=_0x371eb1,_0xce6de4=this['barHistory'][_0x2a256e(0x185)](_0x104d11)||[];if(_0xce6de4['length']<0x32)return{'ready':![],'message':_0x2a256e(0x188)+_0xce6de4['length']+'/50\x20bars'};const _0x2b1fec=this[_0x2a256e(0x12a)][_0x2a256e(0x185)](_0x104d11)||[],_0x277c7d=this[_0x2a256e(0x192)]['get'](_0x104d11)||[],_0x529871=this[_0x2a256e(0x132)](_0x2b1fec),_0x34b9fc=this['_computeVPIN'](_0x277c7d),_0x2eab93=this['_computeOrderFlowImbalance'](_0xce6de4),_0x4e8e17=this[_0x2a256e(0x126)](_0xce6de4),{regime:_0x42fdf3,params:_0x14e667}=this[_0x2a256e(0x157)](_0x104d11,_0xce6de4);return{'ready':!![],'zScore':_0x529871,'vpin':_0x34b9fc,'ofi':_0x2eab93,'kyleLambda':_0x4e8e17,'regime':_0x42fdf3,'stopTicks':Math[_0x2a256e(0x176)](this[_0x2a256e(0x136)]*_0x14e667['stopMultiplier']),'targetTicks':Math[_0x2a256e(0x176)](this['baseTargetTicks']*_0x14e667['targetMultiplier']),'threshold':_0x14e667['zscoreThreshold'],'barsProcessed':_0xce6de4[_0x2a256e(0x148)],'models':_0x2a256e(0x191)};}[_0x371eb1(0x122)](_0x12a30f){const _0x9df8dc=_0x371eb1;this['recentTrades'][_0x9df8dc(0x179)]({'netPnl':_0x12a30f,'timestamp':Date['now']()});if(this['recentTrades'][_0x9df8dc(0x148)]>0x64)this['recentTrades']['shift']();_0x12a30f>0x0?(this['winStreak']++,this['lossStreak']=0x0,this[_0x9df8dc(0x14c)][_0x9df8dc(0x16e)]++):(this[_0x9df8dc(0x151)]++,this['winStreak']=0x0,this['stats'][_0x9df8dc(0x16b)]++),this[_0x9df8dc(0x14c)][_0x9df8dc(0x147)]++,this[_0x9df8dc(0x14c)][_0x9df8dc(0x120)]+=_0x12a30f,this[_0x9df8dc(0x187)]('log',{'type':'debug','message':'[HQX]\x20Trade\x20result:\x20'+(_0x12a30f>0x0?'WIN':'LOSS')+'\x20$'+_0x12a30f['toFixed'](0x2)+_0x9df8dc(0x168)+(_0x12a30f>0x0?this[_0x9df8dc(0x16c)]:-this['lossStreak'])});}[_0x371eb1(0x18a)](_0x48cb29){return this['barHistory']['get'](_0x48cb29)||[];}[_0x371eb1(0x155)](){return this['stats'];}[_0x371eb1(0x17a)](_0x2db903){const _0x29b967=_0x371eb1;this['barHistory']['set'](_0x2db903,[]),this[_0x29b967(0x12a)]['set'](_0x2db903,[]),this[_0x29b967(0x192)][_0x29b967(0x17d)](_0x2db903,[]),this[_0x29b967(0x133)]['set'](_0x2db903,[]),this['kalmanStates'][_0x29b967(0x17d)](_0x2db903,{'estimate':0x0,'errorCovariance':0x1}),this['emit'](_0x29b967(0x121),{'type':'info','message':'[HQX-UltraScalping]\x20Reset\x20state\x20for\x20'+_0x2db903});}}function _0x4b27(_0x5c3c89,_0x39f9b9){_0x5c3c89=_0x5c3c89-0x11f;const _0x411ae3=_0x411a();let _0x4b2782=_0x411ae3[_0x5c3c89];return _0x4b2782;}class UltraScalpingStrategy extends EventEmitter{constructor(_0x35d97c={}){const _0x594019=_0x371eb1;super(),this['config']=_0x35d97c,this[_0x594019(0x16a)]=new HQXUltraScalping(_0x35d97c),this['strategy']['on']('signal',_0x2742d2=>this['emit']('signal',_0x2742d2)),this['strategy']['on'](_0x594019(0x121),_0x3d29fb=>this['emit']('log',_0x3d29fb));}[_0x371eb1(0x14e)](_0x3b7fbe){return this['strategy']['processTick'](_0x3b7fbe);}[_0x371eb1(0x14a)](_0x56cfa0){return this['strategy']['onTick'](_0x56cfa0);}[_0x371eb1(0x18b)](_0xa016de){const _0x2f46cc=_0x371eb1;return this[_0x2f46cc(0x16a)][_0x2f46cc(0x18b)](_0xa016de);}['processBar'](_0x57a8c0,_0x277b59){const _0x126dbd=_0x371eb1;return this['strategy'][_0x126dbd(0x125)](_0x57a8c0,_0x277b59);}['initialize'](_0x23d70e,_0x18cd66,_0x2a4f00){const _0x2e7df3=_0x371eb1;return this[_0x2e7df3(0x16a)][_0x2e7df3(0x178)](_0x23d70e,_0x18cd66,_0x2a4f00);}['getAnalysisState'](_0x370971,_0x8ee12){return this['strategy']['getAnalysisState'](_0x370971,_0x8ee12);}[_0x371eb1(0x122)](_0x403f97){const _0x35f503=_0x371eb1;return this[_0x35f503(0x16a)][_0x35f503(0x122)](_0x403f97);}['reset'](_0x2adeff){const _0x3e03fc=_0x371eb1;return this['strategy'][_0x3e03fc(0x17a)](_0x2adeff);}['getStats'](){const _0x4c050e=_0x371eb1;return this[_0x4c050e(0x16a)][_0x4c050e(0x155)]();}[_0x371eb1(0x18a)](_0x3bc119){return this['strategy']['getBarHistory'](_0x3bc119);}['getModelValues'](_0x2e2674){const _0x30bb59=_0x371eb1;return this['strategy'][_0x30bb59(0x17e)](_0x2e2674);}['shouldExitByZScore'](_0x451471){const _0x2796fe=_0x371eb1;return this[_0x2796fe(0x16a)]['shouldExitByZScore'](_0x451471);}[_0x371eb1(0x174)](_0x32f693){return null;}}module[_0x371eb1(0x141)]={'HQXUltraScalping':HQXUltraScalping,'UltraScalpingStrategy':UltraScalpingStrategy,'M1':UltraScalpingStrategy,'S1':HQXUltraScalping,'OrderSide':OrderSide,'SignalStrength':SignalStrength};
1
+ var __getOwnPropNames = Object.getOwnPropertyNames;
2
+ var __commonJS = (cb, mod) => function __require() {
3
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
4
+ };
5
+
6
+ // ultra-scalping/config.js
7
+ var require_config = __commonJS({
8
+ "ultra-scalping/config.js"(exports2, module2) {
9
+ var DEFAULT_CONFIG = {
10
+ // Model Parameters
11
+ zscoreEntryThreshold: 1.5,
12
+ // Live trading threshold (backtest: 2.5)
13
+ zscoreExitThreshold: 0.5,
14
+ vpinWindow: 50,
15
+ vpinToxicThreshold: 0.7,
16
+ // Skip if VPIN > 0.7
17
+ volatilityLookback: 100,
18
+ ofiLookback: 20,
19
+ // Trade Parameters
20
+ baseStopTicks: 8,
21
+ // $40
22
+ baseTargetTicks: 16,
23
+ // $80
24
+ breakevenTicks: 4,
25
+ // Move to BE at +4 ticks
26
+ profitLockPct: 0.5,
27
+ // Lock 50% of profit
28
+ minConfidence: 0.55,
29
+ // Minimum composite confidence
30
+ cooldownMs: 3e4,
31
+ // 30 seconds between signals
32
+ minHoldTimeMs: 1e4,
33
+ // Minimum 10 seconds hold
34
+ // Model Weights (from Python backtest)
35
+ weights: {
36
+ zscore: 0.3,
37
+ // 30%
38
+ ofi: 0.2,
39
+ // 20%
40
+ vpin: 0.15,
41
+ // 15%
42
+ kalman: 0.15,
43
+ // 15%
44
+ kyleLambda: 0.1,
45
+ // 10%
46
+ volatility: 0.1
47
+ // 10%
48
+ },
49
+ // Session (Futures Market Hours - Sunday 18:00 to Friday 17:00 EST)
50
+ session: {
51
+ enabled: false,
52
+ // Trade anytime markets are open
53
+ timezone: "America/New_York"
54
+ }
55
+ };
56
+ module2.exports = { DEFAULT_CONFIG };
57
+ }
58
+ });
59
+
60
+ // common/types.js
61
+ var require_types = __commonJS({
62
+ "common/types.js"(exports2, module2) {
63
+ var OrderSide2 = { BID: 0, ASK: 1 };
64
+ var SignalStrength2 = { WEAK: 1, MODERATE: 2, STRONG: 3, VERY_STRONG: 4 };
65
+ module2.exports = { OrderSide: OrderSide2, SignalStrength: SignalStrength2 };
66
+ }
67
+ });
68
+
69
+ // ultra-scalping/signal.js
70
+ var require_signal = __commonJS({
71
+ "ultra-scalping/signal.js"(exports2, module2) {
72
+ var { v4: uuidv4 } = require("uuid");
73
+ var { OrderSide: OrderSide2, SignalStrength: SignalStrength2 } = require_types();
74
+ function generateSignal(params) {
75
+ const {
76
+ contractId,
77
+ currentPrice,
78
+ zscore,
79
+ vpin,
80
+ kyleLambda,
81
+ kalmanEstimate,
82
+ regime,
83
+ volParams,
84
+ ofi,
85
+ config,
86
+ tickSize
87
+ } = params;
88
+ const absZscore = Math.abs(zscore);
89
+ if (absZscore < volParams.zscoreThreshold) {
90
+ return null;
91
+ }
92
+ if (vpin > config.vpinToxicThreshold) {
93
+ return null;
94
+ }
95
+ let direction;
96
+ if (zscore < -volParams.zscoreThreshold) {
97
+ direction = "long";
98
+ } else if (zscore > volParams.zscoreThreshold) {
99
+ direction = "short";
100
+ } else {
101
+ return null;
102
+ }
103
+ const ofiConfirms = direction === "long" && ofi > 0.1 || direction === "short" && ofi < -0.1;
104
+ const kalmanDiff = currentPrice - kalmanEstimate;
105
+ const kalmanConfirms = direction === "long" && kalmanDiff < 0 || direction === "short" && kalmanDiff > 0;
106
+ const scores = {
107
+ zscore: Math.min(1, absZscore / 4),
108
+ // Normalize to 0-1
109
+ vpin: 1 - vpin,
110
+ // Lower VPIN = better
111
+ kyleLambda: kyleLambda > 1e-3 ? 0.5 : 0.8,
112
+ // Moderate lambda is good
113
+ kalman: kalmanConfirms ? 0.8 : 0.4,
114
+ volatility: regime === "normal" ? 0.8 : regime === "low" ? 0.7 : 0.6,
115
+ ofi: ofiConfirms ? 0.9 : 0.5,
116
+ composite: 0
117
+ // Calculated below
118
+ };
119
+ scores.composite = scores.zscore * config.weights.zscore + // 30%
120
+ scores.vpin * config.weights.vpin + // 15%
121
+ scores.kyleLambda * config.weights.kyleLambda + // 10%
122
+ scores.kalman * config.weights.kalman + // 15%
123
+ scores.volatility * config.weights.volatility + // 10%
124
+ scores.ofi * config.weights.ofi;
125
+ const confidence = Math.min(1, scores.composite + volParams.confidenceBonus);
126
+ if (confidence < config.minConfidence) {
127
+ return null;
128
+ }
129
+ const stopTicks = Math.round(config.baseStopTicks * volParams.stopMultiplier);
130
+ const targetTicks = Math.round(config.baseTargetTicks * volParams.targetMultiplier);
131
+ const actualStopTicks = Math.max(6, Math.min(12, stopTicks));
132
+ const actualTargetTicks = Math.max(actualStopTicks * 1.5, Math.min(24, targetTicks));
133
+ let stopLoss, takeProfit, beBreakeven, profitLockLevel;
134
+ if (direction === "long") {
135
+ stopLoss = currentPrice - actualStopTicks * tickSize;
136
+ takeProfit = currentPrice + actualTargetTicks * tickSize;
137
+ beBreakeven = currentPrice + config.breakevenTicks * tickSize;
138
+ profitLockLevel = currentPrice + actualTargetTicks * config.profitLockPct * tickSize;
139
+ } else {
140
+ stopLoss = currentPrice + actualStopTicks * tickSize;
141
+ takeProfit = currentPrice - actualTargetTicks * tickSize;
142
+ beBreakeven = currentPrice - config.breakevenTicks * tickSize;
143
+ profitLockLevel = currentPrice - actualTargetTicks * config.profitLockPct * tickSize;
144
+ }
145
+ const riskReward = actualTargetTicks / actualStopTicks;
146
+ const trailTriggerTicks = Math.round(actualTargetTicks * 0.5);
147
+ const trailDistanceTicks = Math.round(actualStopTicks * 0.4);
148
+ let strength = SignalStrength2.MODERATE;
149
+ if (confidence >= 0.85) strength = SignalStrength2.VERY_STRONG;
150
+ else if (confidence >= 0.75) strength = SignalStrength2.STRONG;
151
+ else if (confidence < 0.6) strength = SignalStrength2.WEAK;
152
+ const winProb = 0.5 + (confidence - 0.5) * 0.4;
153
+ const edge = winProb * Math.abs(takeProfit - currentPrice) - (1 - winProb) * Math.abs(currentPrice - stopLoss);
154
+ return {
155
+ id: uuidv4(),
156
+ timestamp: Date.now(),
157
+ symbol: contractId.split(".")[0] || contractId,
158
+ contractId,
159
+ side: direction === "long" ? OrderSide2.BID : OrderSide2.ASK,
160
+ direction,
161
+ strategy: "HQX_ULTRA_SCALPING_6MODELS",
162
+ strength,
163
+ edge,
164
+ confidence,
165
+ entry: currentPrice,
166
+ entryPrice: currentPrice,
167
+ stopLoss,
168
+ takeProfit,
169
+ riskReward,
170
+ stopTicks: actualStopTicks,
171
+ targetTicks: actualTargetTicks,
172
+ trailTriggerTicks,
173
+ trailDistanceTicks,
174
+ beBreakeven,
175
+ profitLockLevel,
176
+ // Model values for debugging/monitoring
177
+ zScore: zscore,
178
+ zScoreExit: config.zscoreExitThreshold,
179
+ vpinValue: vpin,
180
+ kyleLambda,
181
+ kalmanEstimate,
182
+ volatilityRegime: regime,
183
+ ofiValue: ofi,
184
+ models: scores,
185
+ // Order flow confirmation flag
186
+ orderFlowConfirmed: ofiConfirms,
187
+ kalmanConfirmed: kalmanConfirms,
188
+ expires: Date.now() + 6e4
189
+ };
190
+ }
191
+ module2.exports = { generateSignal };
192
+ }
193
+ });
194
+
195
+ // ultra-scalping/models/zscore.js
196
+ var require_zscore = __commonJS({
197
+ "ultra-scalping/models/zscore.js"(exports2, module2) {
198
+ function computeZScore(prices, window = 50) {
199
+ if (prices.length < window) return 0;
200
+ const recentPrices = prices.slice(-window);
201
+ const mean = recentPrices.reduce((a, b) => a + b, 0) / window;
202
+ const variance = recentPrices.reduce((sum, p) => sum + Math.pow(p - mean, 2), 0) / window;
203
+ const std = Math.sqrt(variance);
204
+ if (std < 1e-4) return 0;
205
+ const currentPrice = prices[prices.length - 1];
206
+ return (currentPrice - mean) / std;
207
+ }
208
+ module2.exports = { computeZScore };
209
+ }
210
+ });
211
+
212
+ // ultra-scalping/models/vpin.js
213
+ var require_vpin = __commonJS({
214
+ "ultra-scalping/models/vpin.js"(exports2, module2) {
215
+ function computeVPIN(volumes, vpinWindow = 50) {
216
+ if (volumes.length < vpinWindow) return 0.5;
217
+ const recentVolumes = volumes.slice(-vpinWindow);
218
+ let totalBuy = 0;
219
+ let totalSell = 0;
220
+ for (const v of recentVolumes) {
221
+ totalBuy += v.buy;
222
+ totalSell += v.sell;
223
+ }
224
+ const totalVolume = totalBuy + totalSell;
225
+ if (totalVolume < 1) return 0.5;
226
+ return Math.abs(totalBuy - totalSell) / totalVolume;
227
+ }
228
+ module2.exports = { computeVPIN };
229
+ }
230
+ });
231
+
232
+ // ultra-scalping/models/kyle.js
233
+ var require_kyle = __commonJS({
234
+ "ultra-scalping/models/kyle.js"(exports2, module2) {
235
+ function computeKyleLambda(bars) {
236
+ if (bars.length < 20) return 0;
237
+ const recentBars = bars.slice(-20);
238
+ const priceChanges = [];
239
+ const volumes = [];
240
+ for (let i = 1; i < recentBars.length; i++) {
241
+ priceChanges.push(recentBars[i].close - recentBars[i - 1].close);
242
+ volumes.push(recentBars[i].volume);
243
+ }
244
+ const meanPrice = priceChanges.reduce((a, b) => a + b, 0) / priceChanges.length;
245
+ const meanVol = volumes.reduce((a, b) => a + b, 0) / volumes.length;
246
+ let covariance = 0;
247
+ let varianceVol = 0;
248
+ for (let i = 0; i < priceChanges.length; i++) {
249
+ covariance += (priceChanges[i] - meanPrice) * (volumes[i] - meanVol);
250
+ varianceVol += Math.pow(volumes[i] - meanVol, 2);
251
+ }
252
+ covariance /= priceChanges.length;
253
+ varianceVol /= priceChanges.length;
254
+ if (varianceVol < 1e-4) return 0;
255
+ return Math.abs(covariance / varianceVol);
256
+ }
257
+ module2.exports = { computeKyleLambda };
258
+ }
259
+ });
260
+
261
+ // ultra-scalping/models/kalman.js
262
+ var require_kalman = __commonJS({
263
+ "ultra-scalping/models/kalman.js"(exports2, module2) {
264
+ var KALMAN_PROCESS_NOISE = 0.01;
265
+ var KALMAN_MEASUREMENT_NOISE = 0.1;
266
+ function applyKalmanFilter(state, measurement) {
267
+ if (!state || state.estimate === 0) {
268
+ return {
269
+ estimate: measurement,
270
+ errorCovariance: 1,
271
+ newEstimate: measurement
272
+ };
273
+ }
274
+ const predictedEstimate = state.estimate;
275
+ const predictedCovariance = state.errorCovariance + KALMAN_PROCESS_NOISE;
276
+ const kalmanGain = predictedCovariance / (predictedCovariance + KALMAN_MEASUREMENT_NOISE);
277
+ const newEstimate = predictedEstimate + kalmanGain * (measurement - predictedEstimate);
278
+ const newCovariance = (1 - kalmanGain) * predictedCovariance;
279
+ return {
280
+ estimate: newEstimate,
281
+ errorCovariance: newCovariance,
282
+ newEstimate
283
+ };
284
+ }
285
+ function createKalmanState() {
286
+ return {
287
+ estimate: 0,
288
+ errorCovariance: 1
289
+ };
290
+ }
291
+ module2.exports = {
292
+ applyKalmanFilter,
293
+ createKalmanState,
294
+ KALMAN_PROCESS_NOISE,
295
+ KALMAN_MEASUREMENT_NOISE
296
+ };
297
+ }
298
+ });
299
+
300
+ // ultra-scalping/models/volatility.js
301
+ var require_volatility = __commonJS({
302
+ "ultra-scalping/models/volatility.js"(exports2, module2) {
303
+ function calculateATR(bars, period = 14) {
304
+ if (bars.length < period + 1) return 2.5;
305
+ const trValues = [];
306
+ for (let i = bars.length - period; i < bars.length; i++) {
307
+ const bar = bars[i];
308
+ const prevClose = bars[i - 1].close;
309
+ const tr = Math.max(
310
+ bar.high - bar.low,
311
+ Math.abs(bar.high - prevClose),
312
+ Math.abs(bar.low - prevClose)
313
+ );
314
+ trValues.push(tr);
315
+ }
316
+ return trValues.reduce((a, b) => a + b, 0) / trValues.length;
317
+ }
318
+ function detectVolatilityRegime(atr, atrHistory, tickSize) {
319
+ let atrPercentile = 0.5;
320
+ if (atrHistory.length >= 20) {
321
+ atrPercentile = atrHistory.filter((a) => a <= atr).length / atrHistory.length;
322
+ }
323
+ let regime, params;
324
+ if (atrPercentile < 0.25) {
325
+ regime = "low";
326
+ params = {
327
+ stopMultiplier: 0.8,
328
+ targetMultiplier: 0.9,
329
+ zscoreThreshold: 1.2,
330
+ confidenceBonus: 0.05
331
+ };
332
+ } else if (atrPercentile < 0.75) {
333
+ regime = "normal";
334
+ params = {
335
+ stopMultiplier: 1,
336
+ targetMultiplier: 1,
337
+ zscoreThreshold: 1.5,
338
+ confidenceBonus: 0
339
+ };
340
+ } else {
341
+ regime = "high";
342
+ params = {
343
+ stopMultiplier: 1.3,
344
+ targetMultiplier: 1.2,
345
+ zscoreThreshold: 2,
346
+ confidenceBonus: -0.05
347
+ };
348
+ }
349
+ return { regime, params, atrPercentile };
350
+ }
351
+ module2.exports = { calculateATR, detectVolatilityRegime };
352
+ }
353
+ });
354
+
355
+ // ultra-scalping/models/ofi.js
356
+ var require_ofi = __commonJS({
357
+ "ultra-scalping/models/ofi.js"(exports2, module2) {
358
+ function computeOrderFlowImbalance(bars, lookback = 20) {
359
+ if (bars.length < lookback) return 0;
360
+ const recentBars = bars.slice(-lookback);
361
+ let totalBuyPressure = 0;
362
+ let totalSellPressure = 0;
363
+ for (const bar of recentBars) {
364
+ const barRange = bar.high - bar.low;
365
+ if (barRange > 0) {
366
+ const closePosition = (bar.close - bar.low) / barRange;
367
+ totalBuyPressure += closePosition * bar.volume;
368
+ totalSellPressure += (1 - closePosition) * bar.volume;
369
+ }
370
+ }
371
+ const totalPressure = totalBuyPressure + totalSellPressure;
372
+ if (totalPressure < 1) return 0;
373
+ return (totalBuyPressure - totalSellPressure) / totalPressure;
374
+ }
375
+ module2.exports = { computeOrderFlowImbalance };
376
+ }
377
+ });
378
+
379
+ // ultra-scalping/models/index.js
380
+ var require_models = __commonJS({
381
+ "ultra-scalping/models/index.js"(exports2, module2) {
382
+ var { computeZScore } = require_zscore();
383
+ var { computeVPIN } = require_vpin();
384
+ var { computeKyleLambda } = require_kyle();
385
+ var { applyKalmanFilter, createKalmanState } = require_kalman();
386
+ var { calculateATR, detectVolatilityRegime } = require_volatility();
387
+ var { computeOrderFlowImbalance } = require_ofi();
388
+ module2.exports = {
389
+ computeZScore,
390
+ computeVPIN,
391
+ computeKyleLambda,
392
+ applyKalmanFilter,
393
+ createKalmanState,
394
+ calculateATR,
395
+ detectVolatilityRegime,
396
+ computeOrderFlowImbalance
397
+ };
398
+ }
399
+ });
400
+
401
+ // ultra-scalping/core.js
402
+ var require_core = __commonJS({
403
+ "ultra-scalping/core.js"(exports2, module2) {
404
+ var EventEmitter2 = require("events");
405
+ var { DEFAULT_CONFIG } = require_config();
406
+ var { generateSignal } = require_signal();
407
+ var {
408
+ computeZScore,
409
+ computeVPIN,
410
+ computeKyleLambda,
411
+ applyKalmanFilter,
412
+ createKalmanState,
413
+ calculateATR,
414
+ detectVolatilityRegime,
415
+ computeOrderFlowImbalance
416
+ } = require_models();
417
+ var HQXUltraScalping2 = class extends EventEmitter2 {
418
+ constructor(config = {}) {
419
+ super();
420
+ this.tickSize = config.tickSize || 0.25;
421
+ this.tickValue = config.tickValue || 5;
422
+ this.config = { ...DEFAULT_CONFIG, ...config };
423
+ this.barHistory = /* @__PURE__ */ new Map();
424
+ this.priceBuffer = /* @__PURE__ */ new Map();
425
+ this.volumeBuffer = /* @__PURE__ */ new Map();
426
+ this.kalmanStates = /* @__PURE__ */ new Map();
427
+ this.atrHistory = /* @__PURE__ */ new Map();
428
+ this.recentTrades = [];
429
+ this.winStreak = 0;
430
+ this.lossStreak = 0;
431
+ this.lastSignalTime = 0;
432
+ this.stats = { signals: 0, trades: 0, wins: 0, losses: 0, pnl: 0 };
433
+ }
434
+ initialize(contractId, tickSize = 0.25, tickValue = 5) {
435
+ this.tickSize = tickSize;
436
+ this.tickValue = tickValue;
437
+ this.barHistory.set(contractId, []);
438
+ this.priceBuffer.set(contractId, []);
439
+ this.volumeBuffer.set(contractId, []);
440
+ this.atrHistory.set(contractId, []);
441
+ this.kalmanStates.set(contractId, createKalmanState());
442
+ this.emit("log", {
443
+ type: "info",
444
+ message: `[HQX-UltraScalping] Initialized for ${contractId}: tick=${tickSize}, value=${tickValue}`
445
+ });
446
+ this.emit("log", {
447
+ type: "info",
448
+ message: `[HQX-UltraScalping] 6 Models: Z-Score(30%), OFI(20%), VPIN(15%), Kalman(15%), Kyle(10%), Vol(10%)`
449
+ });
450
+ }
451
+ processTick(tick) {
452
+ const { contractId, price, volume, timestamp } = tick;
453
+ const bar = {
454
+ timestamp: timestamp || Date.now(),
455
+ open: price,
456
+ high: price,
457
+ low: price,
458
+ close: price,
459
+ volume: volume || 1
460
+ };
461
+ return this.processBar(contractId, bar);
462
+ }
463
+ onTick(tick) {
464
+ return this.processTick(tick);
465
+ }
466
+ onTrade(trade) {
467
+ return this.processTick({
468
+ contractId: trade.contractId || trade.symbol,
469
+ price: trade.price,
470
+ volume: trade.size || trade.volume || 1,
471
+ side: trade.side,
472
+ timestamp: trade.timestamp || Date.now()
473
+ });
474
+ }
475
+ processBar(contractId, bar) {
476
+ let bars = this.barHistory.get(contractId);
477
+ if (!bars) {
478
+ this.initialize(contractId);
479
+ bars = this.barHistory.get(contractId);
480
+ }
481
+ bars.push(bar);
482
+ if (bars.length > 500) bars.shift();
483
+ const prices = this.priceBuffer.get(contractId);
484
+ prices.push(bar.close);
485
+ if (prices.length > 200) prices.shift();
486
+ const volumes = this.volumeBuffer.get(contractId);
487
+ const barRange = bar.high - bar.low;
488
+ let buyVol = bar.volume * 0.5;
489
+ let sellVol = bar.volume * 0.5;
490
+ if (barRange > 0) {
491
+ const closePosition = (bar.close - bar.low) / barRange;
492
+ buyVol = bar.volume * closePosition;
493
+ sellVol = bar.volume * (1 - closePosition);
494
+ }
495
+ volumes.push({ buy: buyVol, sell: sellVol });
496
+ if (volumes.length > 100) volumes.shift();
497
+ if (bars.length < 50) return null;
498
+ const zscore = computeZScore(prices);
499
+ const vpin = computeVPIN(volumes, this.config.vpinWindow);
500
+ const kyleLambda = computeKyleLambda(bars);
501
+ const kalmanState = this.kalmanStates.get(contractId);
502
+ const kalmanResult = applyKalmanFilter(kalmanState, bar.close);
503
+ this.kalmanStates.set(contractId, {
504
+ estimate: kalmanResult.estimate,
505
+ errorCovariance: kalmanResult.errorCovariance
506
+ });
507
+ const kalmanEstimate = kalmanResult.newEstimate;
508
+ const atr = calculateATR(bars);
509
+ const atrHist = this.atrHistory.get(contractId);
510
+ atrHist.push(atr);
511
+ if (atrHist.length > 500) atrHist.shift();
512
+ const { regime, params: volParams } = detectVolatilityRegime(atr, atrHist, this.tickSize);
513
+ const ofi = computeOrderFlowImbalance(bars, this.config.ofiLookback);
514
+ if (Date.now() - this.lastSignalTime < this.config.cooldownMs) {
515
+ return null;
516
+ }
517
+ const signal = generateSignal({
518
+ contractId,
519
+ currentPrice: bar.close,
520
+ zscore,
521
+ vpin,
522
+ kyleLambda,
523
+ kalmanEstimate,
524
+ regime,
525
+ volParams,
526
+ ofi,
527
+ config: this.config,
528
+ tickSize: this.tickSize
529
+ });
530
+ if (signal) {
531
+ this.lastSignalTime = Date.now();
532
+ this.stats.signals++;
533
+ this.emit("signal", {
534
+ side: signal.direction === "long" ? "buy" : "sell",
535
+ action: "open",
536
+ reason: `Z=${zscore.toFixed(2)}, VPIN=${(vpin * 100).toFixed(0)}%, OFI=${(ofi * 100).toFixed(0)}%, cf=${(signal.confidence * 100).toFixed(0)}%`,
537
+ ...signal
538
+ });
539
+ this.emit("log", {
540
+ type: "info",
541
+ message: `[HQX] SIGNAL: ${signal.direction.toUpperCase()} @ ${bar.close.toFixed(2)} | Z:${zscore.toFixed(2)} VPIN:${(vpin * 100).toFixed(0)}% OFI:${(ofi * 100).toFixed(0)}% Kyle:${kyleLambda.toFixed(5)} Regime:${regime} | Conf:${(signal.confidence * 100).toFixed(0)}%`
542
+ });
543
+ }
544
+ return signal;
545
+ }
546
+ shouldExitByZScore(contractId) {
547
+ const prices = this.priceBuffer.get(contractId);
548
+ if (!prices || prices.length < 50) return false;
549
+ const zscore = computeZScore(prices);
550
+ return Math.abs(zscore) < this.config.zscoreExitThreshold;
551
+ }
552
+ getModelValues(contractId) {
553
+ const prices = this.priceBuffer.get(contractId);
554
+ const volumes = this.volumeBuffer.get(contractId);
555
+ const bars = this.barHistory.get(contractId);
556
+ if (!prices || !volumes || !bars || bars.length < 50) {
557
+ return null;
558
+ }
559
+ const zscore = computeZScore(prices);
560
+ const vpin = computeVPIN(volumes, this.config.vpinWindow);
561
+ const kyleLambda = computeKyleLambda(bars);
562
+ const ofi = computeOrderFlowImbalance(bars, this.config.ofiLookback);
563
+ return {
564
+ zscore: Math.min(1, Math.abs(zscore) / 4),
565
+ vpin: 1 - vpin,
566
+ kyleLambda: kyleLambda > 1e-3 ? 0.5 : 0.8,
567
+ kalman: 0.7,
568
+ volatility: 0.7,
569
+ ofi: Math.abs(ofi) > 0.1 ? 0.8 : 0.5,
570
+ composite: 0.7,
571
+ raw: { zscore, vpin, kyleLambda, ofi }
572
+ };
573
+ }
574
+ getAnalysisState(contractId, currentPrice) {
575
+ const bars = this.barHistory.get(contractId) || [];
576
+ if (bars.length < 50) {
577
+ return { ready: false, message: `Collecting data... ${bars.length}/50 bars` };
578
+ }
579
+ const prices = this.priceBuffer.get(contractId) || [];
580
+ const volumes = this.volumeBuffer.get(contractId) || [];
581
+ const atrHist = this.atrHistory.get(contractId) || [];
582
+ const zscore = computeZScore(prices);
583
+ const vpin = computeVPIN(volumes, this.config.vpinWindow);
584
+ const ofi = computeOrderFlowImbalance(bars, this.config.ofiLookback);
585
+ const kyleLambda = computeKyleLambda(bars);
586
+ const atr = calculateATR(bars);
587
+ const { regime, params } = detectVolatilityRegime(atr, atrHist, this.tickSize);
588
+ return {
589
+ ready: true,
590
+ zScore: zscore,
591
+ vpin,
592
+ ofi,
593
+ kyleLambda,
594
+ regime,
595
+ stopTicks: Math.round(this.config.baseStopTicks * params.stopMultiplier),
596
+ targetTicks: Math.round(this.config.baseTargetTicks * params.targetMultiplier),
597
+ threshold: params.zscoreThreshold,
598
+ barsProcessed: bars.length,
599
+ models: "6 (Z-Score, VPIN, Kyle, Kalman, Vol, OFI)"
600
+ };
601
+ }
602
+ recordTradeResult(pnl) {
603
+ this.recentTrades.push({ netPnl: pnl, timestamp: Date.now() });
604
+ if (this.recentTrades.length > 100) this.recentTrades.shift();
605
+ if (pnl > 0) {
606
+ this.winStreak++;
607
+ this.lossStreak = 0;
608
+ this.stats.wins++;
609
+ } else {
610
+ this.lossStreak++;
611
+ this.winStreak = 0;
612
+ this.stats.losses++;
613
+ }
614
+ this.stats.trades++;
615
+ this.stats.pnl += pnl;
616
+ this.emit("log", {
617
+ type: "debug",
618
+ message: `[HQX] Trade result: ${pnl > 0 ? "WIN" : "LOSS"} $${pnl.toFixed(2)}, streak: ${pnl > 0 ? this.winStreak : -this.lossStreak}`
619
+ });
620
+ }
621
+ getBarHistory(contractId) {
622
+ return this.barHistory.get(contractId) || [];
623
+ }
624
+ getStats() {
625
+ return this.stats;
626
+ }
627
+ reset(contractId) {
628
+ this.barHistory.set(contractId, []);
629
+ this.priceBuffer.set(contractId, []);
630
+ this.volumeBuffer.set(contractId, []);
631
+ this.atrHistory.set(contractId, []);
632
+ this.kalmanStates.set(contractId, createKalmanState());
633
+ this.emit("log", {
634
+ type: "info",
635
+ message: `[HQX-UltraScalping] Reset state for ${contractId}`
636
+ });
637
+ }
638
+ };
639
+ module2.exports = { HQXUltraScalping: HQXUltraScalping2 };
640
+ }
641
+ });
642
+
643
+ // ultra-scalping/index.js
644
+ var EventEmitter = require("events");
645
+ var { HQXUltraScalping } = require_core();
646
+ var { OrderSide, SignalStrength } = require_types();
647
+ var UltraScalpingStrategy = class extends EventEmitter {
648
+ constructor(config = {}) {
649
+ super();
650
+ this.config = config;
651
+ this.strategy = new HQXUltraScalping(config);
652
+ this.strategy.on("signal", (sig) => this.emit("signal", sig));
653
+ this.strategy.on("log", (log) => this.emit("log", log));
654
+ }
655
+ // Interface methods (compatible with M1)
656
+ processTick(tick) {
657
+ return this.strategy.processTick(tick);
658
+ }
659
+ onTick(tick) {
660
+ return this.strategy.onTick(tick);
661
+ }
662
+ onTrade(trade) {
663
+ return this.strategy.onTrade(trade);
664
+ }
665
+ processBar(contractId, bar) {
666
+ return this.strategy.processBar(contractId, bar);
667
+ }
668
+ initialize(contractId, tickSize, tickValue) {
669
+ return this.strategy.initialize(contractId, tickSize, tickValue);
670
+ }
671
+ getAnalysisState(contractId, price) {
672
+ return this.strategy.getAnalysisState(contractId, price);
673
+ }
674
+ recordTradeResult(pnl) {
675
+ return this.strategy.recordTradeResult(pnl);
676
+ }
677
+ reset(contractId) {
678
+ return this.strategy.reset(contractId);
679
+ }
680
+ getStats() {
681
+ return this.strategy.getStats();
682
+ }
683
+ getBarHistory(contractId) {
684
+ return this.strategy.getBarHistory(contractId);
685
+ }
686
+ getModelValues(contractId) {
687
+ return this.strategy.getModelValues(contractId);
688
+ }
689
+ shouldExitByZScore(contractId) {
690
+ return this.strategy.shouldExitByZScore(contractId);
691
+ }
692
+ generateSignal(params) {
693
+ return null;
694
+ }
695
+ // Signals come from processBar
696
+ };
697
+ module.exports = {
698
+ HQXUltraScalping,
699
+ UltraScalpingStrategy,
700
+ // Aliases for backward compatibility
701
+ M1: UltraScalpingStrategy,
702
+ S1: HQXUltraScalping,
703
+ OrderSide,
704
+ SignalStrength
705
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.9.83",
3
+ "version": "2.9.85",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {