hedgequantx 2.9.79 → 2.9.81

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.
@@ -1 +1,695 @@
1
- const _0x344fde=_0x4752;function _0x4752(_0x295d46,_0x27822c){_0x295d46=_0x295d46-0xe8;const _0x31abd5=_0x31ab();let _0x475228=_0x31abd5[_0x295d46];return _0x475228;}(function(_0x675959,_0x304a92){const _0x264c38=_0x4752,_0x2afbd2=_0x675959();while(!![]){try{const _0x4176b2=-parseInt(_0x264c38(0x140))/0x1+parseInt(_0x264c38(0x144))/0x2*(parseInt(_0x264c38(0x11a))/0x3)+parseInt(_0x264c38(0x111))/0x4+-parseInt(_0x264c38(0x142))/0x5+-parseInt(_0x264c38(0x106))/0x6*(-parseInt(_0x264c38(0x113))/0x7)+-parseInt(_0x264c38(0x117))/0x8*(parseInt(_0x264c38(0x14c))/0x9)+parseInt(_0x264c38(0x101))/0xa;if(_0x4176b2===_0x304a92)break;else _0x2afbd2['push'](_0x2afbd2['shift']());}catch(_0x3301da){_0x2afbd2['push'](_0x2afbd2['shift']());}}}(_0x31ab,0xabf78));const EventEmitter=require(_0x344fde(0x122)),{v4:uuidv4}=require(_0x344fde(0x10c)),OrderSide={'BID':0x0,'ASK':0x1},SignalStrength={'WEAK':0x1,'MODERATE':0x2,'STRONG':0x3,'VERY_STRONG':0x4},SweepType={'HIGH_SWEEP':'high','LOW_SWEEP':_0x344fde(0x100)},ZoneType={'RESISTANCE':'resistance','SUPPORT':'support'},DEFAULT_CONFIG={'tickSize':0.25,'tickValue':0x5,'swing':{'lookbackBars':0x2,'minStrength':0x2,'confirmationBars':0x1},'zone':{'clusterToleranceTicks':0x4,'minTouches':0x1,'maxZoneAgeBars':0xc8,'maxZoneDistanceTicks':0x28,'cooldownBars':0xa},'sweep':{'minPenetrationTicks':0x1,'maxPenetrationTicks':0xc,'maxDurationBars':0x5,'minQualityScore':0.4,'minVolumeRatio':0.8,'minBodyRatio':0.2},'execution':{'stopTicks':0xa,'targetTicks':0x28,'breakevenTicks':0x4,'trailTriggerTicks':0x8,'trailDistanceTicks':0x4,'cooldownMs':0x7530,'minHoldTimeMs':0x2710,'slippageTicks':0x1,'commissionPerSide':0x2},'session':{'enabled':![],'timezone':'America/New_York'}};class SwingPoint{constructor(_0x251145,_0xdc1525,_0x39a033,_0x51c1cc,_0x467304=0x1){const _0x2dbb35=_0x344fde;this[_0x2dbb35(0x104)]=_0x251145,this['price']=_0xdc1525,this[_0x2dbb35(0x15f)]=_0x39a033,this['timestamp']=_0x51c1cc,this[_0x2dbb35(0x107)]=_0x467304;}}class LiquidityZone{constructor(_0x10372b,_0x3ee5dd,_0x37fcec,_0x28d53d,_0x29fe00){const _0x22ea39=_0x344fde;this['id']=uuidv4(),this[_0x22ea39(0x104)]=_0x10372b,this[_0x22ea39(0xea)]=_0x3ee5dd,this['priceLow']=_0x37fcec,this[_0x22ea39(0x146)]=_0x28d53d,this['barIndex']=_0x29fe00,this['touches']=0x1,this['swept']=![],this[_0x22ea39(0x137)]=null,this['lastUsedBarIndex']=-0x3e7,this['qualityScore']=0.5;}['containsPrice'](_0x18e28f,_0x2a9ff8,_0x514d82){const _0x50d117=_0x2a9ff8*_0x514d82;return _0x18e28f>=this['priceLow']-_0x50d117&&_0x18e28f<=this['priceHigh']+_0x50d117;}['getLevel'](){const _0x5a24aa=_0x344fde;return(this['priceHigh']+this[_0x5a24aa(0x167)])/0x2;}}class SweepEvent{constructor(_0x2d3119,_0x2a3cb4,_0x78f9a1,_0x577896,_0x42d20e){const _0x439783=_0x344fde;this[_0x439783(0x157)]=_0x2d3119,this[_0x439783(0x14d)]=_0x2a3cb4,this[_0x439783(0x115)]=_0x78f9a1,this[_0x439783(0xfe)]=_0x577896,this['extremePrice']=_0x42d20e,this['exitBarIndex']=null,this['isValid']=![],this['qualityScore']=0x0,this[_0x439783(0x10a)]=0x0,this[_0x439783(0x166)]=0x0,this['volumeRatio']=0x1;}}class HQX2BLiquiditySweep extends EventEmitter{constructor(_0x433a6a={}){const _0x278aed=_0x344fde;super(),this[_0x278aed(0x163)]=this['_mergeConfig'](DEFAULT_CONFIG,_0x433a6a),this[_0x278aed(0x112)]=this['config'][_0x278aed(0x112)],this[_0x278aed(0xff)]=this[_0x278aed(0x163)][_0x278aed(0xff)],this[_0x278aed(0x150)]=new Map(),this[_0x278aed(0xec)]=new Map(),this['liquidityZones']=new Map(),this['activeSweeps']=new Map(),this[_0x278aed(0x13a)]=0x0,this[_0x278aed(0x108)]={'signals':0x0,'trades':0x0,'wins':0x0,'losses':0x0,'pnl':0x0},this['recentTrades']=[];}['_mergeConfig'](_0x28deb1,_0x2ae4db){const _0x2df59c=_0x344fde,_0x45f8f0={..._0x28deb1};for(const _0x48f57e in _0x2ae4db){typeof _0x2ae4db[_0x48f57e]==='object'&&!Array[_0x2df59c(0xf0)](_0x2ae4db[_0x48f57e])?_0x45f8f0[_0x48f57e]={..._0x28deb1[_0x48f57e],..._0x2ae4db[_0x48f57e]}:_0x45f8f0[_0x48f57e]=_0x2ae4db[_0x48f57e];}return _0x45f8f0;}[_0x344fde(0x12b)](_0x38e2fd,_0x1daee8=0.25,_0x1a2b44=0x5){const _0x4d610e=_0x344fde;this[_0x4d610e(0x112)]=_0x1daee8,this[_0x4d610e(0xff)]=_0x1a2b44,this['config']['tickSize']=_0x1daee8,this['config'][_0x4d610e(0xff)]=_0x1a2b44,this['barHistory'][_0x4d610e(0x114)](_0x38e2fd,[]),this['swingPoints']['set'](_0x38e2fd,[]),this[_0x4d610e(0xf4)][_0x4d610e(0x114)](_0x38e2fd,[]),this['activeSweeps']['set'](_0x38e2fd,[]),this[_0x4d610e(0x134)]('log',{'type':_0x4d610e(0x160),'message':_0x4d610e(0x109)+_0x38e2fd+':\x20tick='+_0x1daee8+',\x20value='+_0x1a2b44}),this[_0x4d610e(0x134)](_0x4d610e(0x16a),{'type':_0x4d610e(0x160),'message':_0x4d610e(0x121)+this[_0x4d610e(0x163)][_0x4d610e(0x138)]['stopTicks']+_0x4d610e(0x135)+this[_0x4d610e(0x163)]['execution'][_0x4d610e(0x129)]+_0x4d610e(0x118)+this['config']['execution']['breakevenTicks']+_0x4d610e(0x147)+this['config'][_0x4d610e(0x138)]['trailTriggerTicks']+'/'+this[_0x4d610e(0x163)][_0x4d610e(0x138)]['trailDistanceTicks']});}[_0x344fde(0x116)](_0xf9fdbc){const _0x361f74=_0x344fde,{contractId:_0xa0b782,price:_0x50d682,volume:_0x330cd2,timestamp:_0x2000e1}=_0xf9fdbc,_0x14d66e={'timestamp':_0x2000e1||Date[_0x361f74(0xef)](),'open':_0x50d682,'high':_0x50d682,'low':_0x50d682,'close':_0x50d682,'volume':_0x330cd2||0x1};return this['processBar'](_0xa0b782,_0x14d66e);}[_0x344fde(0x13d)](_0x29b449){return this['processTick'](_0x29b449);}['onTrade'](_0x4d0678){const _0x5062fd=_0x344fde;return this[_0x5062fd(0x116)]({'contractId':_0x4d0678[_0x5062fd(0x13c)]||_0x4d0678['symbol'],'price':_0x4d0678['price'],'volume':_0x4d0678[_0x5062fd(0xeb)]||_0x4d0678[_0x5062fd(0x13b)]||0x1,'timestamp':_0x4d0678[_0x5062fd(0xf3)]||Date['now']()});}[_0x344fde(0x119)](_0x195427,_0x2b933f){const _0x1a856=_0x344fde;let _0x2d6610=this[_0x1a856(0x150)][_0x1a856(0x102)](_0x195427);!_0x2d6610&&(this['initialize'](_0x195427),_0x2d6610=this['barHistory']['get'](_0x195427));_0x2d6610[_0x1a856(0xed)](_0x2b933f);if(_0x2d6610[_0x1a856(0x148)]>0x1f4)_0x2d6610[_0x1a856(0xf8)]();const _0xea05d1=_0x2d6610['length']-0x1;if(_0x2d6610[_0x1a856(0x148)]<this[_0x1a856(0x163)][_0x1a856(0x155)]['lookbackBars']*0x3)return null;this[_0x1a856(0x12d)](_0x195427,_0x2d6610,_0xea05d1),this[_0x1a856(0x15e)](_0x195427,_0xea05d1);const _0x82f029=this['_detectSweep'](_0x195427,_0x2d6610,_0xea05d1);if(_0x82f029&&_0x82f029[_0x1a856(0x16b)])return this['_generateSignal'](_0x195427,_0x2b933f,_0xea05d1,_0x82f029);return null;}['_detectSwings'](_0x4b875a,_0xaf5c13,_0x333731){const _0x40675a=_0x344fde,_0x45f8c3=this[_0x40675a(0x163)][_0x40675a(0x155)][_0x40675a(0x10d)],_0x3afd0c=this['config'][_0x40675a(0x155)][_0x40675a(0xf5)];if(_0x333731<_0x45f8c3*0x2)return;const _0x8f7b25=this[_0x40675a(0xec)]['get'](_0x4b875a),_0x1bd8eb=_0x333731-_0x45f8c3,_0x35164f=_0xaf5c13[_0x1bd8eb];let _0x5f0d8b=!![],_0x3df7f4=0x0;for(let _0x36327f=_0x1bd8eb-_0x45f8c3;_0x36327f<=_0x1bd8eb+_0x45f8c3;_0x36327f++){if(_0x36327f===_0x1bd8eb||_0x36327f<0x0||_0x36327f>=_0xaf5c13['length'])continue;if(_0xaf5c13[_0x36327f]['high']>=_0x35164f[_0x40675a(0x11d)]){_0x5f0d8b=![];break;}_0x3df7f4++;}if(_0x5f0d8b&&_0x3df7f4>=_0x3afd0c){const _0x33b2c6=_0x8f7b25['find'](_0x21607b=>_0x21607b['barIndex']===_0x1bd8eb&&_0x21607b['type']==='high');!_0x33b2c6&&_0x8f7b25['push'](new SwingPoint('high',_0x35164f[_0x40675a(0x11d)],_0x1bd8eb,_0x35164f['timestamp'],_0x3df7f4));}let _0x3511eb=!![],_0x253561=0x0;for(let _0x2714c1=_0x1bd8eb-_0x45f8c3;_0x2714c1<=_0x1bd8eb+_0x45f8c3;_0x2714c1++){if(_0x2714c1===_0x1bd8eb||_0x2714c1<0x0||_0x2714c1>=_0xaf5c13['length'])continue;if(_0xaf5c13[_0x2714c1][_0x40675a(0x100)]<=_0x35164f['low']){_0x3511eb=![];break;}_0x253561++;}if(_0x3511eb&&_0x253561>=_0x3afd0c){const _0x53f8aa=_0x8f7b25['find'](_0x54059d=>_0x54059d['barIndex']===_0x1bd8eb&&_0x54059d[_0x40675a(0x104)]==='low');!_0x53f8aa&&_0x8f7b25[_0x40675a(0xed)](new SwingPoint('low',_0x35164f['low'],_0x1bd8eb,_0x35164f['timestamp'],_0x253561));}const _0xf6854c=this[_0x40675a(0x163)][_0x40675a(0x14d)]['maxZoneAgeBars'];while(_0x8f7b25['length']>0x0&&_0x8f7b25[0x0][_0x40675a(0x15f)]<_0x333731-_0xf6854c){_0x8f7b25[_0x40675a(0xf8)]();}}['_updateZones'](_0x15994a,_0x59a7ad){const _0x4f0646=_0x344fde,_0x3b23fd=this[_0x4f0646(0xec)]['get'](_0x15994a),_0x2ee5b2=this[_0x4f0646(0xf4)][_0x4f0646(0x102)](_0x15994a),_0x29628a=this[_0x4f0646(0x163)][_0x4f0646(0x14d)][_0x4f0646(0x103)]*this[_0x4f0646(0x112)],_0x3018d2=this[_0x4f0646(0x163)][_0x4f0646(0x14d)]['maxZoneAgeBars'];for(let _0x3e18d1=_0x2ee5b2[_0x4f0646(0x148)]-0x1;_0x3e18d1>=0x0;_0x3e18d1--){_0x59a7ad-_0x2ee5b2[_0x3e18d1]['barIndex']>_0x3018d2&&_0x2ee5b2[_0x4f0646(0x124)](_0x3e18d1,0x1);}for(const _0x414177 of _0x3b23fd){let _0x30fc47=null;for(const _0x83f79e of _0x2ee5b2){if(_0x83f79e[_0x4f0646(0xfb)](_0x414177['price'],this[_0x4f0646(0x163)]['zone'][_0x4f0646(0x103)],this['tickSize'])){_0x30fc47=_0x83f79e;break;}}if(_0x30fc47){_0x30fc47[_0x4f0646(0xf9)]++;if(_0x414177['price']>_0x30fc47[_0x4f0646(0xea)])_0x30fc47['priceHigh']=_0x414177[_0x4f0646(0xee)];if(_0x414177[_0x4f0646(0xee)]<_0x30fc47[_0x4f0646(0x167)])_0x30fc47[_0x4f0646(0x167)]=_0x414177[_0x4f0646(0xee)];_0x30fc47[_0x4f0646(0x149)]=Math['min'](0x1,0.3+_0x30fc47['touches']*0.15);}else{const _0x11a684=_0x414177[_0x4f0646(0x104)]===_0x4f0646(0x11d)?ZoneType['RESISTANCE']:ZoneType[_0x4f0646(0x15c)],_0x272b42=new LiquidityZone(_0x11a684,_0x414177['price']+_0x29628a/0x2,_0x414177['price']-_0x29628a/0x2,_0x414177[_0x4f0646(0xf3)],_0x414177['barIndex']);_0x272b42[_0x4f0646(0x149)]=0.3+_0x414177[_0x4f0646(0x107)]*0.1,_0x2ee5b2[_0x4f0646(0xed)](_0x272b42);}}}[_0x344fde(0x164)](_0x329a9d,_0x135355,_0x4fcc51){const _0x8fbaea=_0x344fde,_0x4ebda6=this[_0x8fbaea(0xf4)]['get'](_0x329a9d),_0x44f746=_0x135355[_0x4fcc51],_0x13eedb=_0x44f746[_0x8fbaea(0x110)],_0x466227=this[_0x8fbaea(0x163)]['sweep'],_0x39d9fc=this['config']['zone'];for(const _0x3f9a83 of _0x4ebda6){if(_0x3f9a83[_0x8fbaea(0x151)]>=0x0&&_0x4fcc51-_0x3f9a83[_0x8fbaea(0x151)]<_0x39d9fc['cooldownBars'])continue;const _0x373346=_0x3f9a83['getLevel'](),_0x2f7a39=Math['abs'](_0x13eedb-_0x373346)/this['tickSize'];if(_0x2f7a39>_0x39d9fc[_0x8fbaea(0x145)])continue;const _0x15d861=Math['max'](0x0,_0x4fcc51-_0x466227['maxDurationBars']*0x2);for(let _0x31a778=_0x15d861;_0x31a778<_0x4fcc51;_0x31a778++){const _0x27c64a=_0x135355[_0x31a778];if(_0x3f9a83['type']===ZoneType['RESISTANCE']){const _0x152bf5=(_0x27c64a['high']-_0x3f9a83[_0x8fbaea(0xea)])/this['tickSize'];if(_0x152bf5>=_0x466227[_0x8fbaea(0x15a)]&&_0x152bf5<=_0x466227['maxPenetrationTicks']){if(_0x13eedb<_0x3f9a83[_0x8fbaea(0xea)]){const _0x17d705=_0x27c64a['high']-_0x27c64a[_0x8fbaea(0x100)],_0x51923b=Math[_0x8fbaea(0x12f)](_0x27c64a[_0x8fbaea(0x110)]-_0x27c64a['open']),_0x426775=_0x17d705>0x0?_0x51923b/_0x17d705:0x0;if(_0x426775>=_0x466227['minBodyRatio']){const _0x411934=this[_0x8fbaea(0x14f)](_0x135355,_0x31a778,0x14);if(_0x411934>=_0x466227[_0x8fbaea(0x131)]){const _0x19efae=new SweepEvent(SweepType[_0x8fbaea(0x12a)],_0x3f9a83,_0x31a778,_0x31a778,_0x27c64a[_0x8fbaea(0x11d)]);_0x19efae['exitBarIndex']=_0x4fcc51,_0x19efae[_0x8fbaea(0x10a)]=_0x152bf5,_0x19efae['durationBars']=_0x4fcc51-_0x31a778,_0x19efae['volumeRatio']=_0x411934,_0x19efae['qualityScore']=this[_0x8fbaea(0x162)](_0x19efae,_0x426775),_0x19efae['isValid']=_0x19efae[_0x8fbaea(0x149)]>=_0x466227['minQualityScore'];if(_0x19efae['isValid'])return _0x19efae;}}}}}if(_0x3f9a83[_0x8fbaea(0x104)]===ZoneType['SUPPORT']){const _0xbd3d2d=(_0x3f9a83['priceLow']-_0x27c64a[_0x8fbaea(0x100)])/this['tickSize'];if(_0xbd3d2d>=_0x466227[_0x8fbaea(0x15a)]&&_0xbd3d2d<=_0x466227['maxPenetrationTicks']){if(_0x13eedb>_0x3f9a83['priceLow']){const _0x597a9c=_0x27c64a[_0x8fbaea(0x11d)]-_0x27c64a['low'],_0x9d26e2=Math[_0x8fbaea(0x12f)](_0x27c64a[_0x8fbaea(0x110)]-_0x27c64a[_0x8fbaea(0x14a)]),_0x2ab029=_0x597a9c>0x0?_0x9d26e2/_0x597a9c:0x0;if(_0x2ab029>=_0x466227['minBodyRatio']){const _0x2e6df4=this['_getVolumeRatio'](_0x135355,_0x31a778,0x14);if(_0x2e6df4>=_0x466227[_0x8fbaea(0x131)]){const _0x381909=new SweepEvent(SweepType[_0x8fbaea(0x153)],_0x3f9a83,_0x31a778,_0x31a778,_0x27c64a[_0x8fbaea(0x100)]);_0x381909['exitBarIndex']=_0x4fcc51,_0x381909['penetrationTicks']=_0xbd3d2d,_0x381909[_0x8fbaea(0x166)]=_0x4fcc51-_0x31a778,_0x381909['volumeRatio']=_0x2e6df4,_0x381909['qualityScore']=this['_scoreSweep'](_0x381909,_0x2ab029),_0x381909[_0x8fbaea(0x16b)]=_0x381909[_0x8fbaea(0x149)]>=_0x466227[_0x8fbaea(0xf2)];if(_0x381909['isValid'])return _0x381909;}}}}}}}return null;}['_getVolumeRatio'](_0x4e28ff,_0x334631,_0x1dadef){const _0x4559f5=_0x344fde,_0x8b7671=Math['max'](0x0,_0x334631-_0x1dadef),_0x47bea6=_0x4e28ff['slice'](_0x8b7671,_0x334631);if(_0x47bea6[_0x4559f5(0x148)]===0x0)return 0x1;const _0x3b2043=_0x47bea6['map'](_0x365a7c=>_0x365a7c['volume'])[_0x4559f5(0xe8)]((_0x229bea,_0x15c7fc)=>_0x229bea-_0x15c7fc),_0x2e3edb=Math[_0x4559f5(0x11f)](_0x3b2043['length']/0x2),_0x579a09=_0x3b2043[_0x2e3edb]||0x1;return _0x4e28ff[_0x334631]['volume']/_0x579a09;}['_scoreSweep'](_0x5989b8,_0x3ef6c4){const _0x157505=_0x344fde;let _0x426dca=0x0;const _0x385423=0x4,_0x229d6b=Math[_0x157505(0x12f)](_0x5989b8[_0x157505(0x10a)]-_0x385423);return _0x426dca+=Math[_0x157505(0xfa)](0x0,0.3-_0x229d6b*0.03),_0x426dca+=Math[_0x157505(0xfa)](0x0,0.25-_0x5989b8[_0x157505(0x166)]*0.05),_0x426dca+=Math[_0x157505(0x105)](0.25,_0x5989b8[_0x157505(0x15d)]*0.1),_0x426dca+=Math['min'](0.2,_0x3ef6c4*0.4),Math['min'](0x1,_0x426dca);}[_0x344fde(0x10e)](_0x2dc239,_0x5d3113,_0x23ec82,_0x24ed2c){const _0x742c42=_0x344fde;if(Date[_0x742c42(0xef)]()-this[_0x742c42(0x13a)]<this[_0x742c42(0x163)]['execution'][_0x742c42(0x133)])return null;const _0x5e6309=this[_0x742c42(0x163)]['execution'],_0x2b7867=_0x5d3113[_0x742c42(0x110)],_0x1496f5=_0x24ed2c[_0x742c42(0x157)]===SweepType['HIGH_SWEEP']?_0x742c42(0xe9):_0x742c42(0x14e);let _0x14b604,_0x2cddc2,_0x3fe5fb,_0x1a30c2;_0x1496f5===_0x742c42(0x14e)?(_0x14b604=_0x2b7867-_0x5e6309['stopTicks']*this[_0x742c42(0x112)],_0x2cddc2=_0x2b7867+_0x5e6309['targetTicks']*this[_0x742c42(0x112)],_0x3fe5fb=_0x2b7867+_0x5e6309[_0x742c42(0x165)]*this[_0x742c42(0x112)],_0x1a30c2=_0x2b7867+_0x5e6309[_0x742c42(0x11b)]*this[_0x742c42(0x112)]):(_0x14b604=_0x2b7867+_0x5e6309[_0x742c42(0xf7)]*this['tickSize'],_0x2cddc2=_0x2b7867-_0x5e6309['targetTicks']*this['tickSize'],_0x3fe5fb=_0x2b7867-_0x5e6309[_0x742c42(0x165)]*this['tickSize'],_0x1a30c2=_0x2b7867-_0x5e6309['trailTriggerTicks']*this['tickSize']);const _0x1166da=_0x5e6309['targetTicks']/_0x5e6309[_0x742c42(0xf7)],_0x2ce4f4=Math[_0x742c42(0x105)](0x1,_0x24ed2c['qualityScore']*0.5+_0x24ed2c[_0x742c42(0x14d)][_0x742c42(0x149)]*0.3+(_0x24ed2c['volumeRatio']>1.5?0.2:_0x24ed2c['volumeRatio']*0.1));let _0x4c5b55=SignalStrength['MODERATE'];if(_0x2ce4f4>=0.8)_0x4c5b55=SignalStrength['VERY_STRONG'];else{if(_0x2ce4f4>=0.65)_0x4c5b55=SignalStrength[_0x742c42(0x12c)];else{if(_0x2ce4f4<0.5)_0x4c5b55=SignalStrength['WEAK'];}}const _0x375c79=0.5+(_0x2ce4f4-0.5)*0.4,_0x24ca2a=_0x375c79*Math[_0x742c42(0x12f)](_0x2cddc2-_0x2b7867)-(0x1-_0x375c79)*Math['abs'](_0x2b7867-_0x14b604);_0x24ed2c[_0x742c42(0x14d)]['lastUsedBarIndex']=_0x23ec82,_0x24ed2c['zone'][_0x742c42(0x158)]=!![],_0x24ed2c['zone']['sweptAt']=new Date(_0x5d3113['timestamp']),this[_0x742c42(0x13a)]=Date[_0x742c42(0xef)](),this[_0x742c42(0x108)][_0x742c42(0x11e)]++;const _0x39ac0e={'id':uuidv4(),'timestamp':Date['now'](),'symbol':_0x2dc239[_0x742c42(0xfc)]('.')[0x0]||_0x2dc239,'contractId':_0x2dc239,'side':_0x1496f5==='long'?OrderSide[_0x742c42(0x130)]:OrderSide['ASK'],'direction':_0x1496f5,'strategy':'HQX_2B_LIQUIDITY_SWEEP','strength':_0x4c5b55,'edge':_0x24ca2a,'confidence':_0x2ce4f4,'entry':_0x2b7867,'entryPrice':_0x2b7867,'stopLoss':_0x14b604,'takeProfit':_0x2cddc2,'riskReward':_0x1166da,'stopTicks':_0x5e6309[_0x742c42(0xf7)],'targetTicks':_0x5e6309[_0x742c42(0x129)],'breakevenTicks':_0x5e6309[_0x742c42(0x165)],'trailTriggerTicks':_0x5e6309[_0x742c42(0x11b)],'trailDistanceTicks':_0x5e6309[_0x742c42(0x139)],'beLevel':_0x3fe5fb,'trailTrigger':_0x1a30c2,'sweepType':_0x24ed2c[_0x742c42(0x157)],'penetrationTicks':_0x24ed2c['penetrationTicks'],'sweepDurationBars':_0x24ed2c['durationBars'],'sweepQuality':_0x24ed2c[_0x742c42(0x149)],'volumeRatio':_0x24ed2c['volumeRatio'],'zoneType':_0x24ed2c['zone'][_0x742c42(0x104)],'zoneLevel':_0x24ed2c[_0x742c42(0x14d)]['getLevel'](),'zoneTouches':_0x24ed2c[_0x742c42(0x14d)][_0x742c42(0xf9)],'zoneQuality':_0x24ed2c[_0x742c42(0x14d)]['qualityScore'],'expires':Date[_0x742c42(0xef)]()+0xea60};return this['emit'](_0x742c42(0x156),{'side':_0x1496f5===_0x742c42(0x14e)?_0x742c42(0xf1):'sell','action':_0x742c42(0x14a),'reason':'2B\x20'+_0x24ed2c[_0x742c42(0x157)]+_0x742c42(0x136)+_0x24ed2c['penetrationTicks']['toFixed'](0x1)+'t\x20|\x20Vol:'+_0x24ed2c['volumeRatio']['toFixed'](0x1)+'x\x20|\x20Q:'+(_0x24ed2c[_0x742c42(0x149)]*0x64)['toFixed'](0x0)+'%',..._0x39ac0e}),this['emit']('log',{'type':_0x742c42(0x160),'message':_0x742c42(0x10f)+_0x1496f5['toUpperCase']()+'\x20@\x20'+_0x2b7867[_0x742c42(0x152)](0x2)+'\x20|\x20'+_0x24ed2c['sweepType']+_0x742c42(0x136)+_0x24ed2c[_0x742c42(0x10a)][_0x742c42(0x152)](0x1)+_0x742c42(0x120)+_0x24ed2c['volumeRatio']['toFixed'](0x1)+_0x742c42(0x15b)+(_0x2ce4f4*0x64)[_0x742c42(0x152)](0x0)+'%'}),_0x39ac0e;}['getAnalysisState'](_0x2c8cbe,_0x250870){const _0x1ef392=_0x344fde,_0x78ce70=this[_0x1ef392(0x150)][_0x1ef392(0x102)](_0x2c8cbe)||[],_0x56b900=this[_0x1ef392(0xf4)]['get'](_0x2c8cbe)||[],_0x105f36=this[_0x1ef392(0xec)]['get'](_0x2c8cbe)||[];if(_0x78ce70['length']<0x14)return{'ready':![],'message':'Collecting\x20data...\x20'+_0x78ce70['length']+_0x1ef392(0xf6)};const _0x3bf479=_0x56b900[_0x1ef392(0x13e)](_0x612c64=>({'zone':_0x612c64,'distance':Math[_0x1ef392(0x12f)](_0x250870-_0x612c64['getLevel']())}))[_0x1ef392(0xe8)]((_0x3eab0d,_0x5c82a3)=>_0x3eab0d['distance']-_0x5c82a3['distance']),_0x6462a2=_0x3bf479['find'](_0x42a0d0=>_0x42a0d0['zone'][_0x1ef392(0x104)]===ZoneType['RESISTANCE']),_0x1d330e=_0x3bf479[_0x1ef392(0x125)](_0x22879a=>_0x22879a[_0x1ef392(0x14d)]['type']===ZoneType[_0x1ef392(0x15c)]);return{'ready':!![],'barsProcessed':_0x78ce70[_0x1ef392(0x148)],'swingsDetected':_0x105f36['length'],'activeZones':_0x56b900[_0x1ef392(0x148)],'nearestResistance':_0x6462a2?_0x6462a2[_0x1ef392(0x14d)][_0x1ef392(0xfd)]():null,'nearestSupport':_0x1d330e?_0x1d330e[_0x1ef392(0x14d)]['getLevel']():null,'stopTicks':this['config'][_0x1ef392(0x138)]['stopTicks'],'targetTicks':this['config'][_0x1ef392(0x138)]['targetTicks'],'strategy':_0x1ef392(0x123)};}[_0x344fde(0x159)](_0x5042ae){const _0x4156b0=_0x344fde;this[_0x4156b0(0x14b)][_0x4156b0(0xed)]({'netPnl':_0x5042ae,'timestamp':Date['now']()});if(this[_0x4156b0(0x14b)][_0x4156b0(0x148)]>0x64)this[_0x4156b0(0x14b)][_0x4156b0(0xf8)]();_0x5042ae>0x0?this[_0x4156b0(0x108)]['wins']++:this[_0x4156b0(0x108)][_0x4156b0(0x127)]++,this['stats']['trades']++,this[_0x4156b0(0x108)][_0x4156b0(0x168)]+=_0x5042ae,this['emit'](_0x4156b0(0x16a),{'type':_0x4156b0(0x12e),'message':_0x4156b0(0x13f)+(_0x5042ae>0x0?'WIN':_0x4156b0(0x161))+'\x20$'+_0x5042ae['toFixed'](0x2)});}[_0x344fde(0x11c)](_0x275010){const _0x51d5df=_0x344fde;return this[_0x51d5df(0x150)]['get'](_0x275010)||[];}['getStats'](){return this['stats'];}[_0x344fde(0x141)](_0x379e60){const _0x2ba6bb=_0x344fde;this[_0x2ba6bb(0x150)][_0x2ba6bb(0x114)](_0x379e60,[]),this[_0x2ba6bb(0xec)]['set'](_0x379e60,[]),this[_0x2ba6bb(0xf4)][_0x2ba6bb(0x114)](_0x379e60,[]),this[_0x2ba6bb(0x169)]['set'](_0x379e60,[]),this[_0x2ba6bb(0x134)](_0x2ba6bb(0x16a),{'type':'info','message':_0x2ba6bb(0x132)+_0x379e60});}}class HQX2BStrategy extends EventEmitter{constructor(_0x506c08={}){const _0x4e7b4c=_0x344fde;super(),this['config']=_0x506c08,this[_0x4e7b4c(0x143)]=new HQX2BLiquiditySweep(_0x506c08),this['strategy']['on']('signal',_0x2c7435=>this[_0x4e7b4c(0x134)](_0x4e7b4c(0x156),_0x2c7435)),this['strategy']['on']('log',_0x48ca94=>this[_0x4e7b4c(0x134)]('log',_0x48ca94));}[_0x344fde(0x116)](_0x5aaa50){return this['strategy']['processTick'](_0x5aaa50);}[_0x344fde(0x13d)](_0xdbe743){return this['strategy']['onTick'](_0xdbe743);}['onTrade'](_0x5334f0){const _0x2a4208=_0x344fde;return this['strategy'][_0x2a4208(0x128)](_0x5334f0);}[_0x344fde(0x119)](_0x514e07,_0x4d1ab6){const _0x4207a1=_0x344fde;return this[_0x4207a1(0x143)][_0x4207a1(0x119)](_0x514e07,_0x4d1ab6);}['initialize'](_0x57b0ba,_0x139161,_0x76515a){const _0x495bd0=_0x344fde;return this[_0x495bd0(0x143)][_0x495bd0(0x12b)](_0x57b0ba,_0x139161,_0x76515a);}[_0x344fde(0x154)](_0x478865,_0x1e51ed){const _0x25dc2d=_0x344fde;return this['strategy'][_0x25dc2d(0x154)](_0x478865,_0x1e51ed);}[_0x344fde(0x159)](_0x3fb341){const _0x44d0a6=_0x344fde;return this[_0x44d0a6(0x143)][_0x44d0a6(0x159)](_0x3fb341);}['reset'](_0x4b424e){const _0x2c60bd=_0x344fde;return this[_0x2c60bd(0x143)]['reset'](_0x4b424e);}[_0x344fde(0x126)](){const _0x4e147c=_0x344fde;return this[_0x4e147c(0x143)]['getStats']();}['getBarHistory'](_0x322616){const _0x5a2f94=_0x344fde;return this[_0x5a2f94(0x143)]['getBarHistory'](_0x322616);}['generateSignal'](_0x343b8a){return null;}}module[_0x344fde(0x10b)]={'HQX2BLiquiditySweep':HQX2BLiquiditySweep,'HQX2BStrategy':HQX2BStrategy,'M2':HQX2BStrategy,'S2':HQX2BLiquiditySweep,'OrderSide':OrderSide,'SignalStrength':SignalStrength,'SweepType':SweepType,'ZoneType':ZoneType,'DEFAULT_CONFIG':DEFAULT_CONFIG};function _0x31ab(){const _0x2068f5=['find','getStats','losses','onTrade','targetTicks','HIGH_SWEEP','initialize','STRONG','_detectSwings','debug','abs','BID','minVolumeRatio','[HQX-2B]\x20Reset\x20state\x20for\x20','cooldownMs','emit','t,\x20Target=','\x20|\x20Pen:','sweptAt','execution','trailDistanceTicks','lastSignalTime','volume','contractId','onTick','map','[HQX-2B]\x20Trade\x20result:\x20','452803FLuEym','reset','6360580TeFprc','strategy','1403666IRZbzt','maxZoneDistanceTicks','createdAt','t,\x20Trail=','length','qualityScore','open','recentTrades','9UMRmxi','zone','long','_getVolumeRatio','barHistory','lastUsedBarIndex','toFixed','LOW_SWEEP','getAnalysisState','swing','signal','sweepType','swept','recordTradeResult','minPenetrationTicks','x\x20|\x20Conf:','SUPPORT','volumeRatio','_updateZones','barIndex','info','LOSS','_scoreSweep','config','_detectSweep','breakevenTicks','durationBars','priceLow','pnl','activeSweeps','log','isValid','sort','short','priceHigh','size','swingPoints','push','price','now','isArray','buy','minQualityScore','timestamp','liquidityZones','minStrength','/20\x20bars','stopTicks','shift','touches','max','containsPrice','split','getLevel','extremeBarIndex','tickValue','low','11508580FNGdCh','get','clusterToleranceTicks','type','min','113766RvAvbN','strength','stats','[HQX-2B]\x20Initialized\x20for\x20','penetrationTicks','exports','uuid','lookbackBars','_generateSignal','[HQX-2B]\x20SIGNAL:\x20','close','4096960UugIad','tickSize','77AgvQkZ','set','entryBarIndex','processTick','5249656kdotoV','t,\x20BE=','processBar','3taXcSl','trailTriggerTicks','getBarHistory','high','signals','floor','t\x20Vol:','[HQX-2B]\x20Params:\x20Stop=','events','HQX-2B\x20Liquidity\x20Sweep\x20(Optimized)','splice'];_0x31ab=function(){return _0x2068f5;};return _0x31ab();}
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
+ // hqx-2b/config.js
7
+ var require_config = __commonJS({
8
+ "hqx-2b/config.js"(exports2, module2) {
9
+ var SweepType2 = { HIGH_SWEEP: "high", LOW_SWEEP: "low" };
10
+ var ZoneType2 = { RESISTANCE: "resistance", SUPPORT: "support" };
11
+ var DEFAULT_CONFIG2 = {
12
+ // Instrument
13
+ tickSize: 0.25,
14
+ tickValue: 5,
15
+ // Swing Detection (ULTRA AGGRESSIVE)
16
+ swing: {
17
+ lookbackBars: 2,
18
+ // Reduced for more swings
19
+ minStrength: 2,
20
+ // More permissive
21
+ confirmationBars: 1
22
+ // Faster confirmation
23
+ },
24
+ // Zone Detection (ULTRA AGGRESSIVE)
25
+ zone: {
26
+ clusterToleranceTicks: 4,
27
+ minTouches: 1,
28
+ // Allow single-touch zones
29
+ maxZoneAgeBars: 200,
30
+ // Fresher zones only
31
+ maxZoneDistanceTicks: 40,
32
+ cooldownBars: 10
33
+ // Bars before zone can be reused
34
+ },
35
+ // Sweep Detection (ULTRA AGGRESSIVE)
36
+ sweep: {
37
+ minPenetrationTicks: 1,
38
+ // Very permissive
39
+ maxPenetrationTicks: 12,
40
+ // Tighter range
41
+ maxDurationBars: 5,
42
+ minQualityScore: 0.4,
43
+ minVolumeRatio: 0.8,
44
+ // >= 0.8x median volume
45
+ minBodyRatio: 0.2
46
+ // Minimum body/range ratio
47
+ },
48
+ // Execution (OPTIMIZED 4:1 R:R)
49
+ execution: {
50
+ stopTicks: 10,
51
+ // $50 stop
52
+ targetTicks: 40,
53
+ // $200 target (4:1 R:R)
54
+ breakevenTicks: 4,
55
+ // Move to BE at +4 ticks
56
+ trailTriggerTicks: 8,
57
+ // Activate trailing at +8 ticks
58
+ trailDistanceTicks: 4,
59
+ // Trail by 4 ticks
60
+ cooldownMs: 3e4,
61
+ // 30 seconds between signals
62
+ minHoldTimeMs: 1e4,
63
+ // Minimum 10 seconds hold
64
+ slippageTicks: 1,
65
+ commissionPerSide: 2
66
+ // $4 round-trip
67
+ },
68
+ // Session (Futures Market Hours - Sunday 18:00 to Friday 17:00 EST)
69
+ session: {
70
+ enabled: false,
71
+ // Trade anytime markets are open
72
+ timezone: "America/New_York"
73
+ }
74
+ };
75
+ module2.exports = { DEFAULT_CONFIG: DEFAULT_CONFIG2, SweepType: SweepType2, ZoneType: ZoneType2 };
76
+ }
77
+ });
78
+
79
+ // common/types.js
80
+ var require_types = __commonJS({
81
+ "common/types.js"(exports2, module2) {
82
+ var OrderSide2 = { BID: 0, ASK: 1 };
83
+ var SignalStrength2 = { WEAK: 1, MODERATE: 2, STRONG: 3, VERY_STRONG: 4 };
84
+ module2.exports = { OrderSide: OrderSide2, SignalStrength: SignalStrength2 };
85
+ }
86
+ });
87
+
88
+ // hqx-2b/signal.js
89
+ var require_signal = __commonJS({
90
+ "hqx-2b/signal.js"(exports2, module2) {
91
+ var { v4: uuidv4 } = require("uuid");
92
+ var { OrderSide: OrderSide2, SignalStrength: SignalStrength2 } = require_types();
93
+ var { SweepType: SweepType2 } = require_config();
94
+ function generateSignal(params) {
95
+ const {
96
+ contractId,
97
+ currentBar,
98
+ currentIndex,
99
+ sweep,
100
+ config,
101
+ tickSize
102
+ } = params;
103
+ const exec = config.execution;
104
+ const currentPrice = currentBar.close;
105
+ const direction = sweep.sweepType === SweepType2.HIGH_SWEEP ? "short" : "long";
106
+ let stopLoss, takeProfit, beLevel, trailTrigger;
107
+ if (direction === "long") {
108
+ stopLoss = currentPrice - exec.stopTicks * tickSize;
109
+ takeProfit = currentPrice + exec.targetTicks * tickSize;
110
+ beLevel = currentPrice + exec.breakevenTicks * tickSize;
111
+ trailTrigger = currentPrice + exec.trailTriggerTicks * tickSize;
112
+ } else {
113
+ stopLoss = currentPrice + exec.stopTicks * tickSize;
114
+ takeProfit = currentPrice - exec.targetTicks * tickSize;
115
+ beLevel = currentPrice - exec.breakevenTicks * tickSize;
116
+ trailTrigger = currentPrice - exec.trailTriggerTicks * tickSize;
117
+ }
118
+ const riskReward = exec.targetTicks / exec.stopTicks;
119
+ const confidence = Math.min(
120
+ 1,
121
+ sweep.qualityScore * 0.5 + sweep.zone.qualityScore * 0.3 + (sweep.volumeRatio > 1.5 ? 0.2 : sweep.volumeRatio * 0.1)
122
+ );
123
+ let strength = SignalStrength2.MODERATE;
124
+ if (confidence >= 0.8) strength = SignalStrength2.VERY_STRONG;
125
+ else if (confidence >= 0.65) strength = SignalStrength2.STRONG;
126
+ else if (confidence < 0.5) strength = SignalStrength2.WEAK;
127
+ const winProb = 0.5 + (confidence - 0.5) * 0.4;
128
+ const edge = winProb * Math.abs(takeProfit - currentPrice) - (1 - winProb) * Math.abs(currentPrice - stopLoss);
129
+ sweep.zone.lastUsedBarIndex = currentIndex;
130
+ sweep.zone.swept = true;
131
+ sweep.zone.sweptAt = new Date(currentBar.timestamp);
132
+ return {
133
+ id: uuidv4(),
134
+ timestamp: Date.now(),
135
+ symbol: contractId.split(".")[0] || contractId,
136
+ contractId,
137
+ side: direction === "long" ? OrderSide2.BID : OrderSide2.ASK,
138
+ direction,
139
+ strategy: "HQX_2B_LIQUIDITY_SWEEP",
140
+ strength,
141
+ edge,
142
+ confidence,
143
+ entry: currentPrice,
144
+ entryPrice: currentPrice,
145
+ stopLoss,
146
+ takeProfit,
147
+ riskReward,
148
+ stopTicks: exec.stopTicks,
149
+ targetTicks: exec.targetTicks,
150
+ breakevenTicks: exec.breakevenTicks,
151
+ trailTriggerTicks: exec.trailTriggerTicks,
152
+ trailDistanceTicks: exec.trailDistanceTicks,
153
+ beLevel,
154
+ trailTrigger,
155
+ // Sweep details
156
+ sweepType: sweep.sweepType,
157
+ penetrationTicks: sweep.penetrationTicks,
158
+ sweepDurationBars: sweep.durationBars,
159
+ sweepQuality: sweep.qualityScore,
160
+ volumeRatio: sweep.volumeRatio,
161
+ // Zone details
162
+ zoneType: sweep.zone.type,
163
+ zoneLevel: sweep.zone.getLevel(),
164
+ zoneTouches: sweep.zone.touches,
165
+ zoneQuality: sweep.zone.qualityScore,
166
+ expires: Date.now() + 6e4
167
+ };
168
+ }
169
+ module2.exports = { generateSignal };
170
+ }
171
+ });
172
+
173
+ // hqx-2b/detection/swings.js
174
+ var require_swings = __commonJS({
175
+ "hqx-2b/detection/swings.js"(exports2, module2) {
176
+ var SwingPoint = class {
177
+ constructor(type, price, barIndex, timestamp, strength = 1) {
178
+ this.type = type;
179
+ this.price = price;
180
+ this.barIndex = barIndex;
181
+ this.timestamp = timestamp;
182
+ this.strength = strength;
183
+ }
184
+ };
185
+ function detectSwings(bars, currentIndex, existingSwings, config, maxAge) {
186
+ const { lookbackBars, minStrength } = config;
187
+ const swings = [...existingSwings];
188
+ if (currentIndex < lookbackBars * 2) return swings;
189
+ const pivotIndex = currentIndex - lookbackBars;
190
+ const pivotBar = bars[pivotIndex];
191
+ let isSwingHigh = true;
192
+ let highStrength = 0;
193
+ for (let i = pivotIndex - lookbackBars; i <= pivotIndex + lookbackBars; i++) {
194
+ if (i === pivotIndex || i < 0 || i >= bars.length) continue;
195
+ if (bars[i].high >= pivotBar.high) {
196
+ isSwingHigh = false;
197
+ break;
198
+ }
199
+ highStrength++;
200
+ }
201
+ if (isSwingHigh && highStrength >= minStrength) {
202
+ const existing = swings.find((s) => s.barIndex === pivotIndex && s.type === "high");
203
+ if (!existing) {
204
+ swings.push(new SwingPoint("high", pivotBar.high, pivotIndex, pivotBar.timestamp, highStrength));
205
+ }
206
+ }
207
+ let isSwingLow = true;
208
+ let lowStrength = 0;
209
+ for (let i = pivotIndex - lookbackBars; i <= pivotIndex + lookbackBars; i++) {
210
+ if (i === pivotIndex || i < 0 || i >= bars.length) continue;
211
+ if (bars[i].low <= pivotBar.low) {
212
+ isSwingLow = false;
213
+ break;
214
+ }
215
+ lowStrength++;
216
+ }
217
+ if (isSwingLow && lowStrength >= minStrength) {
218
+ const existing = swings.find((s) => s.barIndex === pivotIndex && s.type === "low");
219
+ if (!existing) {
220
+ swings.push(new SwingPoint("low", pivotBar.low, pivotIndex, pivotBar.timestamp, lowStrength));
221
+ }
222
+ }
223
+ while (swings.length > 0 && swings[0].barIndex < currentIndex - maxAge) {
224
+ swings.shift();
225
+ }
226
+ return swings;
227
+ }
228
+ module2.exports = { SwingPoint, detectSwings };
229
+ }
230
+ });
231
+
232
+ // hqx-2b/detection/zones.js
233
+ var require_zones = __commonJS({
234
+ "hqx-2b/detection/zones.js"(exports2, module2) {
235
+ var { v4: uuidv4 } = require("uuid");
236
+ var { ZoneType: ZoneType2 } = require_config();
237
+ var LiquidityZone = class {
238
+ constructor(type, priceHigh, priceLow, createdAt, barIndex) {
239
+ this.id = uuidv4();
240
+ this.type = type;
241
+ this.priceHigh = priceHigh;
242
+ this.priceLow = priceLow;
243
+ this.createdAt = createdAt;
244
+ this.barIndex = barIndex;
245
+ this.touches = 1;
246
+ this.swept = false;
247
+ this.sweptAt = null;
248
+ this.lastUsedBarIndex = -999;
249
+ this.qualityScore = 0.5;
250
+ }
251
+ containsPrice(price, toleranceTicks, tickSize) {
252
+ const tolerance = toleranceTicks * tickSize;
253
+ return price >= this.priceLow - tolerance && price <= this.priceHigh + tolerance;
254
+ }
255
+ getLevel() {
256
+ return (this.priceHigh + this.priceLow) / 2;
257
+ }
258
+ };
259
+ function updateZones(swings, existingZones, currentIndex, config, tickSize) {
260
+ const { clusterToleranceTicks, maxZoneAgeBars } = config;
261
+ const zones = [...existingZones];
262
+ const tolerance = clusterToleranceTicks * tickSize;
263
+ for (let i = zones.length - 1; i >= 0; i--) {
264
+ if (currentIndex - zones[i].barIndex > maxZoneAgeBars) {
265
+ zones.splice(i, 1);
266
+ }
267
+ }
268
+ for (const swing of swings) {
269
+ let foundZone = null;
270
+ for (const zone of zones) {
271
+ if (zone.containsPrice(swing.price, clusterToleranceTicks, tickSize)) {
272
+ foundZone = zone;
273
+ break;
274
+ }
275
+ }
276
+ if (foundZone) {
277
+ foundZone.touches++;
278
+ if (swing.price > foundZone.priceHigh) foundZone.priceHigh = swing.price;
279
+ if (swing.price < foundZone.priceLow) foundZone.priceLow = swing.price;
280
+ foundZone.qualityScore = Math.min(1, 0.3 + foundZone.touches * 0.15);
281
+ } else {
282
+ const zoneType = swing.type === "high" ? ZoneType2.RESISTANCE : ZoneType2.SUPPORT;
283
+ const newZone = new LiquidityZone(
284
+ zoneType,
285
+ swing.price + tolerance / 2,
286
+ swing.price - tolerance / 2,
287
+ swing.timestamp,
288
+ swing.barIndex
289
+ );
290
+ newZone.qualityScore = 0.3 + swing.strength * 0.1;
291
+ zones.push(newZone);
292
+ }
293
+ }
294
+ return zones;
295
+ }
296
+ module2.exports = { LiquidityZone, updateZones };
297
+ }
298
+ });
299
+
300
+ // hqx-2b/detection/sweeps.js
301
+ var require_sweeps = __commonJS({
302
+ "hqx-2b/detection/sweeps.js"(exports2, module2) {
303
+ var { SweepType: SweepType2, ZoneType: ZoneType2 } = require_config();
304
+ var SweepEvent = class {
305
+ constructor(sweepType, zone, entryBarIndex, extremeBarIndex, extremePrice) {
306
+ this.sweepType = sweepType;
307
+ this.zone = zone;
308
+ this.entryBarIndex = entryBarIndex;
309
+ this.extremeBarIndex = extremeBarIndex;
310
+ this.extremePrice = extremePrice;
311
+ this.exitBarIndex = null;
312
+ this.isValid = false;
313
+ this.qualityScore = 0;
314
+ this.penetrationTicks = 0;
315
+ this.durationBars = 0;
316
+ this.volumeRatio = 1;
317
+ }
318
+ };
319
+ function getVolumeRatio(bars, index, lookback) {
320
+ const start = Math.max(0, index - lookback);
321
+ const recentBars = bars.slice(start, index);
322
+ if (recentBars.length === 0) return 1;
323
+ const volumes = recentBars.map((b) => b.volume).sort((a, b) => a - b);
324
+ const medianIdx = Math.floor(volumes.length / 2);
325
+ const medianVolume = volumes[medianIdx] || 1;
326
+ return bars[index].volume / medianVolume;
327
+ }
328
+ function scoreSweep(sweep, bodyRatio) {
329
+ let score = 0;
330
+ const optimalPen = 4;
331
+ const penDiff = Math.abs(sweep.penetrationTicks - optimalPen);
332
+ score += Math.max(0, 0.3 - penDiff * 0.03);
333
+ score += Math.max(0, 0.25 - sweep.durationBars * 0.05);
334
+ score += Math.min(0.25, sweep.volumeRatio * 0.1);
335
+ score += Math.min(0.2, bodyRatio * 0.4);
336
+ return Math.min(1, score);
337
+ }
338
+ function detectSweep(zones, bars, currentIndex, sweepConfig, zoneConfig, tickSize) {
339
+ const currentBar = bars[currentIndex];
340
+ const currentPrice = currentBar.close;
341
+ const cfg = sweepConfig;
342
+ for (const zone of zones) {
343
+ if (zone.lastUsedBarIndex >= 0 && currentIndex - zone.lastUsedBarIndex < zoneConfig.cooldownBars) {
344
+ continue;
345
+ }
346
+ const zoneLevel = zone.getLevel();
347
+ const distanceTicks = Math.abs(currentPrice - zoneLevel) / tickSize;
348
+ if (distanceTicks > zoneConfig.maxZoneDistanceTicks) continue;
349
+ const lookbackStart = Math.max(0, currentIndex - cfg.maxDurationBars * 2);
350
+ for (let i = lookbackStart; i < currentIndex; i++) {
351
+ const bar = bars[i];
352
+ if (zone.type === ZoneType2.RESISTANCE) {
353
+ const penetration = (bar.high - zone.priceHigh) / tickSize;
354
+ if (penetration >= cfg.minPenetrationTicks && penetration <= cfg.maxPenetrationTicks) {
355
+ if (currentPrice < zone.priceHigh) {
356
+ const barRange = bar.high - bar.low;
357
+ const bodySize = Math.abs(bar.close - bar.open);
358
+ const bodyRatio = barRange > 0 ? bodySize / barRange : 0;
359
+ if (bodyRatio >= cfg.minBodyRatio) {
360
+ const volumeRatio = getVolumeRatio(bars, i, 20);
361
+ if (volumeRatio >= cfg.minVolumeRatio) {
362
+ const sweep = new SweepEvent(
363
+ SweepType2.HIGH_SWEEP,
364
+ zone,
365
+ i,
366
+ i,
367
+ bar.high
368
+ );
369
+ sweep.exitBarIndex = currentIndex;
370
+ sweep.penetrationTicks = penetration;
371
+ sweep.durationBars = currentIndex - i;
372
+ sweep.volumeRatio = volumeRatio;
373
+ sweep.qualityScore = scoreSweep(sweep, bodyRatio);
374
+ sweep.isValid = sweep.qualityScore >= cfg.minQualityScore;
375
+ if (sweep.isValid) {
376
+ return sweep;
377
+ }
378
+ }
379
+ }
380
+ }
381
+ }
382
+ }
383
+ if (zone.type === ZoneType2.SUPPORT) {
384
+ const penetration = (zone.priceLow - bar.low) / tickSize;
385
+ if (penetration >= cfg.minPenetrationTicks && penetration <= cfg.maxPenetrationTicks) {
386
+ if (currentPrice > zone.priceLow) {
387
+ const barRange = bar.high - bar.low;
388
+ const bodySize = Math.abs(bar.close - bar.open);
389
+ const bodyRatio = barRange > 0 ? bodySize / barRange : 0;
390
+ if (bodyRatio >= cfg.minBodyRatio) {
391
+ const volumeRatio = getVolumeRatio(bars, i, 20);
392
+ if (volumeRatio >= cfg.minVolumeRatio) {
393
+ const sweep = new SweepEvent(
394
+ SweepType2.LOW_SWEEP,
395
+ zone,
396
+ i,
397
+ i,
398
+ bar.low
399
+ );
400
+ sweep.exitBarIndex = currentIndex;
401
+ sweep.penetrationTicks = penetration;
402
+ sweep.durationBars = currentIndex - i;
403
+ sweep.volumeRatio = volumeRatio;
404
+ sweep.qualityScore = scoreSweep(sweep, bodyRatio);
405
+ sweep.isValid = sweep.qualityScore >= cfg.minQualityScore;
406
+ if (sweep.isValid) {
407
+ return sweep;
408
+ }
409
+ }
410
+ }
411
+ }
412
+ }
413
+ }
414
+ }
415
+ }
416
+ return null;
417
+ }
418
+ module2.exports = { SweepEvent, detectSweep, getVolumeRatio, scoreSweep };
419
+ }
420
+ });
421
+
422
+ // hqx-2b/detection/index.js
423
+ var require_detection = __commonJS({
424
+ "hqx-2b/detection/index.js"(exports2, module2) {
425
+ var { SwingPoint, detectSwings } = require_swings();
426
+ var { LiquidityZone, updateZones } = require_zones();
427
+ var { SweepEvent, detectSweep } = require_sweeps();
428
+ module2.exports = {
429
+ SwingPoint,
430
+ detectSwings,
431
+ LiquidityZone,
432
+ updateZones,
433
+ SweepEvent,
434
+ detectSweep
435
+ };
436
+ }
437
+ });
438
+
439
+ // hqx-2b/core.js
440
+ var require_core = __commonJS({
441
+ "hqx-2b/core.js"(exports2, module2) {
442
+ var EventEmitter2 = require("events");
443
+ var { DEFAULT_CONFIG: DEFAULT_CONFIG2, ZoneType: ZoneType2 } = require_config();
444
+ var { generateSignal } = require_signal();
445
+ var { detectSwings, updateZones, detectSweep } = require_detection();
446
+ function mergeConfig(defaults, custom) {
447
+ const result = { ...defaults };
448
+ for (const key in custom) {
449
+ if (typeof custom[key] === "object" && !Array.isArray(custom[key]) && custom[key] !== null) {
450
+ result[key] = { ...defaults[key], ...custom[key] };
451
+ } else {
452
+ result[key] = custom[key];
453
+ }
454
+ }
455
+ return result;
456
+ }
457
+ var HQX2BLiquiditySweep2 = class extends EventEmitter2 {
458
+ constructor(config = {}) {
459
+ super();
460
+ this.config = mergeConfig(DEFAULT_CONFIG2, config);
461
+ this.tickSize = this.config.tickSize;
462
+ this.tickValue = this.config.tickValue;
463
+ this.barHistory = /* @__PURE__ */ new Map();
464
+ this.swingPoints = /* @__PURE__ */ new Map();
465
+ this.liquidityZones = /* @__PURE__ */ new Map();
466
+ this.lastSignalTime = 0;
467
+ this.stats = { signals: 0, trades: 0, wins: 0, losses: 0, pnl: 0 };
468
+ this.recentTrades = [];
469
+ }
470
+ initialize(contractId, tickSize = 0.25, tickValue = 5) {
471
+ this.tickSize = tickSize;
472
+ this.tickValue = tickValue;
473
+ this.config.tickSize = tickSize;
474
+ this.config.tickValue = tickValue;
475
+ this.barHistory.set(contractId, []);
476
+ this.swingPoints.set(contractId, []);
477
+ this.liquidityZones.set(contractId, []);
478
+ this.emit("log", {
479
+ type: "info",
480
+ message: `[HQX-2B] Initialized for ${contractId}: tick=${tickSize}, value=${tickValue}`
481
+ });
482
+ this.emit("log", {
483
+ type: "info",
484
+ 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}`
485
+ });
486
+ }
487
+ processTick(tick) {
488
+ const { contractId, price, volume, timestamp } = tick;
489
+ const bar = {
490
+ timestamp: timestamp || Date.now(),
491
+ open: price,
492
+ high: price,
493
+ low: price,
494
+ close: price,
495
+ volume: volume || 1
496
+ };
497
+ return this.processBar(contractId, bar);
498
+ }
499
+ onTick(tick) {
500
+ return this.processTick(tick);
501
+ }
502
+ onTrade(trade) {
503
+ return this.processTick({
504
+ contractId: trade.contractId || trade.symbol,
505
+ price: trade.price,
506
+ volume: trade.size || trade.volume || 1,
507
+ timestamp: trade.timestamp || Date.now()
508
+ });
509
+ }
510
+ processBar(contractId, bar) {
511
+ let bars = this.barHistory.get(contractId);
512
+ if (!bars) {
513
+ this.initialize(contractId);
514
+ bars = this.barHistory.get(contractId);
515
+ }
516
+ bars.push(bar);
517
+ if (bars.length > 500) bars.shift();
518
+ const currentIndex = bars.length - 1;
519
+ if (bars.length < this.config.swing.lookbackBars * 3) {
520
+ return null;
521
+ }
522
+ const swings = this.swingPoints.get(contractId);
523
+ const updatedSwings = detectSwings(
524
+ bars,
525
+ currentIndex,
526
+ swings,
527
+ this.config.swing,
528
+ this.config.zone.maxZoneAgeBars
529
+ );
530
+ this.swingPoints.set(contractId, updatedSwings);
531
+ const zones = this.liquidityZones.get(contractId);
532
+ const updatedZones = updateZones(
533
+ updatedSwings,
534
+ zones,
535
+ currentIndex,
536
+ this.config.zone,
537
+ this.tickSize
538
+ );
539
+ this.liquidityZones.set(contractId, updatedZones);
540
+ const sweep = detectSweep(
541
+ updatedZones,
542
+ bars,
543
+ currentIndex,
544
+ this.config.sweep,
545
+ this.config.zone,
546
+ this.tickSize
547
+ );
548
+ if (sweep && sweep.isValid) {
549
+ if (Date.now() - this.lastSignalTime < this.config.execution.cooldownMs) {
550
+ return null;
551
+ }
552
+ const signal = generateSignal({
553
+ contractId,
554
+ currentBar: bar,
555
+ currentIndex,
556
+ sweep,
557
+ config: this.config,
558
+ tickSize: this.tickSize
559
+ });
560
+ if (signal) {
561
+ this.lastSignalTime = Date.now();
562
+ this.stats.signals++;
563
+ this.emit("signal", {
564
+ side: signal.direction === "long" ? "buy" : "sell",
565
+ action: "open",
566
+ reason: `2B ${sweep.sweepType} | Pen:${sweep.penetrationTicks.toFixed(1)}t | Vol:${sweep.volumeRatio.toFixed(1)}x | Q:${(sweep.qualityScore * 100).toFixed(0)}%`,
567
+ ...signal
568
+ });
569
+ this.emit("log", {
570
+ type: "info",
571
+ message: `[HQX-2B] SIGNAL: ${signal.direction.toUpperCase()} @ ${bar.close.toFixed(2)} | ${sweep.sweepType} | Pen:${sweep.penetrationTicks.toFixed(1)}t Vol:${sweep.volumeRatio.toFixed(1)}x | Conf:${(signal.confidence * 100).toFixed(0)}%`
572
+ });
573
+ return signal;
574
+ }
575
+ }
576
+ return null;
577
+ }
578
+ getAnalysisState(contractId, currentPrice) {
579
+ const bars = this.barHistory.get(contractId) || [];
580
+ const zones = this.liquidityZones.get(contractId) || [];
581
+ const swings = this.swingPoints.get(contractId) || [];
582
+ if (bars.length < 20) {
583
+ return { ready: false, message: `Collecting data... ${bars.length}/20 bars` };
584
+ }
585
+ const sortedZones = zones.map((z) => ({ zone: z, distance: Math.abs(currentPrice - z.getLevel()) })).sort((a, b) => a.distance - b.distance);
586
+ const nearestResistance = sortedZones.find((z) => z.zone.type === ZoneType2.RESISTANCE);
587
+ const nearestSupport = sortedZones.find((z) => z.zone.type === ZoneType2.SUPPORT);
588
+ return {
589
+ ready: true,
590
+ barsProcessed: bars.length,
591
+ swingsDetected: swings.length,
592
+ activeZones: zones.length,
593
+ nearestResistance: nearestResistance ? nearestResistance.zone.getLevel() : null,
594
+ nearestSupport: nearestSupport ? nearestSupport.zone.getLevel() : null,
595
+ stopTicks: this.config.execution.stopTicks,
596
+ targetTicks: this.config.execution.targetTicks,
597
+ strategy: "HQX-2B Liquidity Sweep (Optimized)"
598
+ };
599
+ }
600
+ recordTradeResult(pnl) {
601
+ this.recentTrades.push({ netPnl: pnl, timestamp: Date.now() });
602
+ if (this.recentTrades.length > 100) this.recentTrades.shift();
603
+ if (pnl > 0) {
604
+ this.stats.wins++;
605
+ } else {
606
+ this.stats.losses++;
607
+ }
608
+ this.stats.trades++;
609
+ this.stats.pnl += pnl;
610
+ this.emit("log", {
611
+ type: "debug",
612
+ message: `[HQX-2B] Trade result: ${pnl > 0 ? "WIN" : "LOSS"} $${pnl.toFixed(2)}`
613
+ });
614
+ }
615
+ getBarHistory(contractId) {
616
+ return this.barHistory.get(contractId) || [];
617
+ }
618
+ getStats() {
619
+ return this.stats;
620
+ }
621
+ reset(contractId) {
622
+ this.barHistory.set(contractId, []);
623
+ this.swingPoints.set(contractId, []);
624
+ this.liquidityZones.set(contractId, []);
625
+ this.emit("log", {
626
+ type: "info",
627
+ message: `[HQX-2B] Reset state for ${contractId}`
628
+ });
629
+ }
630
+ };
631
+ module2.exports = { HQX2BLiquiditySweep: HQX2BLiquiditySweep2 };
632
+ }
633
+ });
634
+
635
+ // hqx-2b/index.js
636
+ var EventEmitter = require("events");
637
+ var { HQX2BLiquiditySweep } = require_core();
638
+ var { OrderSide, SignalStrength } = require_types();
639
+ var { SweepType, ZoneType, DEFAULT_CONFIG } = require_config();
640
+ var HQX2BStrategy = class extends EventEmitter {
641
+ constructor(config = {}) {
642
+ super();
643
+ this.config = config;
644
+ this.strategy = new HQX2BLiquiditySweep(config);
645
+ this.strategy.on("signal", (sig) => this.emit("signal", sig));
646
+ this.strategy.on("log", (log) => this.emit("log", log));
647
+ }
648
+ // Interface methods (compatible with M1)
649
+ processTick(tick) {
650
+ return this.strategy.processTick(tick);
651
+ }
652
+ onTick(tick) {
653
+ return this.strategy.onTick(tick);
654
+ }
655
+ onTrade(trade) {
656
+ return this.strategy.onTrade(trade);
657
+ }
658
+ processBar(contractId, bar) {
659
+ return this.strategy.processBar(contractId, bar);
660
+ }
661
+ initialize(contractId, tickSize, tickValue) {
662
+ return this.strategy.initialize(contractId, tickSize, tickValue);
663
+ }
664
+ getAnalysisState(contractId, price) {
665
+ return this.strategy.getAnalysisState(contractId, price);
666
+ }
667
+ recordTradeResult(pnl) {
668
+ return this.strategy.recordTradeResult(pnl);
669
+ }
670
+ reset(contractId) {
671
+ return this.strategy.reset(contractId);
672
+ }
673
+ getStats() {
674
+ return this.strategy.getStats();
675
+ }
676
+ getBarHistory(contractId) {
677
+ return this.strategy.getBarHistory(contractId);
678
+ }
679
+ generateSignal(params) {
680
+ return null;
681
+ }
682
+ // Signals come from processBar
683
+ };
684
+ module.exports = {
685
+ HQX2BLiquiditySweep,
686
+ HQX2BStrategy,
687
+ // Aliases
688
+ M2: HQX2BStrategy,
689
+ S2: HQX2BLiquiditySweep,
690
+ OrderSide,
691
+ SignalStrength,
692
+ SweepType,
693
+ ZoneType,
694
+ DEFAULT_CONFIG
695
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "2.9.79",
3
+ "version": "2.9.81",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -124,7 +124,7 @@ class RithmicConnection extends EventEmitter {
124
124
  appVersion: this.config.appVersion || '1.0.0',
125
125
  systemName: this.config.systemName,
126
126
  infraType: INFRA_TYPE[infraType],
127
- macAddr: [getMacAddress()],
127
+ macAddr: ['00:00:00:00:00:00'],
128
128
  osVersion: os.release(),
129
129
  osPlatform: os.platform(),
130
130
  });
@@ -42,8 +42,8 @@ const PROPFIRM_CONFIGS = {
42
42
  lucidtrading: { name: 'Lucid Trading', systemName: RITHMIC_SYSTEMS.LUCID_TRADING, gateway: RITHMIC_ENDPOINTS.CHICAGO },
43
43
  thrivetrading: { name: 'Thrive Trading', systemName: RITHMIC_SYSTEMS.THRIVE_TRADING, gateway: RITHMIC_ENDPOINTS.CHICAGO },
44
44
  legendstrading: { name: 'Legends Trading', systemName: RITHMIC_SYSTEMS.LEGENDS_TRADING, gateway: RITHMIC_ENDPOINTS.CHICAGO },
45
- // Rithmic Paper Trading - uses dedicated PAPER endpoint
46
- rithmic_paper: { name: 'Rithmic Paper Trading', systemName: RITHMIC_SYSTEMS.PAPER, gateway: RITHMIC_ENDPOINTS.PAPER },
45
+ // Rithmic Paper Trading - uses CHICAGO endpoint (PAPER endpoint deprecated)
46
+ rithmic_paper: { name: 'Rithmic Paper Trading', systemName: RITHMIC_SYSTEMS.PAPER, gateway: RITHMIC_ENDPOINTS.CHICAGO },
47
47
  };
48
48
 
49
49
  /**