| | javascript:(function(){ |
| | var old=document.getElementById('qx-ai-root'); |
| | if(old)old.remove(); |
| | var SERVERS=[ |
| | 'http://127.0.0.1:5050', |
| | 'http://192.168.0.103:5050', |
| | 'http://10.254.60.18:5050', |
| | 'http://192.168.0.100:5050', |
| | 'http://192.168.0.117:5050', |
| | 'http://192.168.0.205:5050' |
| | ]; |
| | var serverIndex=0; |
| | var host=document.createElement('div'); |
| | host.id='qx-ai-root'; |
| | host.style.cssText='position:fixed;top:0;left:0;width:0;height:0;z-index:999999999'; |
| | document.documentElement.appendChild(host); |
| | var css=document.createElement('style'); |
| | css.textContent= | | | '#qx-ai-root *{box-sizing:border-box;font-family:system-ui,sans-serif;user-select:none;-webkit-tap-highlight-color:transparent}'+ | | | '.qx-i{position:fixed;top:70px;right:12px;width:54px;height:54px;border-radius:50%;background:#0f172a;border:2px solid #38bdf8;color:#38bdf8;font-weight:800;font-size:11px;display:flex;align-items:center;justify-content:center;cursor:grab;z-index:999999999;box-shadow:0 0 16px rgba(56,189,248,.45);touch-action:none}'+ | | | '.qx-p{position:fixed;top:80px;left:8px;width:min(420px,96vw);min-height:200px;background:rgba(7,18,36,.98);color:#e2e8f0;border:1px solid #334155;border-radius:16px;display:none;overflow:hidden;z-index:999999998;box-shadow:0 20px 50px #000;flex-direction:column}'+ | | | '.qx-p.show{display:flex}'+ | | | '.qx-h{background:linear-gradient(90deg,#0ea5e9,#6366f1);padding:12px 14px;font-weight:700;font-size:13px;display:flex;justify-content:space-between;align-items:center;cursor:move;touch-action:none}'+ |
| | '.qx-b{padding:12px;overflow-y:auto;flex:1;max-height:78vh}'+ |
| | '.qx-res{text-align:center;padding:12px;background:#1e293b;border-radius:12px;font-size:14px;font-weight:700;margin-bottom:8px;border:1px solid #334155}'+ |
| | '.qx-meta{font-size:11px;color:#94a3b8;line-height:1.45;margin-bottom:8px}'+ |
| | '.qx-row{display:flex;gap:6px;flex-wrap:wrap;margin:6px 0}'+ |
| | '.qx-row label{font-size:11px;color:#94a3b8;display:flex;flex-direction:column;gap:3px;flex:1;min-width:90px}'+ |
| | '.qx-row select,.qx-row input{background:#0f172a;border:1px solid #334155;color:#e2e8f0;border-radius:8px;padding:6px 8px;font-size:12px}'+ |
| | '.qx-btn{flex:1;padding:10px;border:0;border-radius:10px;font-weight:700;font-size:12px;cursor:pointer}'+ |
| | '.qx-scan{background:linear-gradient(90deg,#0ea5e9,#6366f1);color:#fff}'+ |
| | '.qx-stop{background:#7f1d1d;color:#fecaca}'+ |
| | '.qx-tog{background:#1e293b;color:#94a3b8;border:1px solid #334155}'+ |
| | '.qx-tog.on{background:#14532d;color:#86efac;border-color:#22c55e}'+ |
| | '.qx-ov{position:fixed;inset:0;background:rgba(15,23,42,.28);backdrop-filter:blur(2px);z-index:999999990;display:none;pointer-events:none}'+ |
| | '.qx-ov.on{display:block}'+ |
| | '.qx-laser{position:absolute;left:0;width:100%;height:3px;background:linear-gradient(90deg,transparent,#38bdf8,#818cf8,transparent);box-shadow:0 0 14px #38bdf8;animation:qxScan 1.1s ease-in-out infinite alternate}'+ |
| | '@keyframes qxScan{from{top:4%}to{top:96%}}'+ |
| | '.qx-rs{position:absolute;right:0;bottom:0;width:18px;height:18px;cursor:nwse-resize;background:linear-gradient(135deg,transparent 50%,#38bdf8 50%);opacity:.7}'; |
| | host.appendChild(css); |
| | var overlay=document.createElement('div'); |
| | overlay.className='qx-ov'; |
| | overlay.innerHTML='<div class="qx-laser"></div>'; |
| | host.appendChild(overlay); |
| | var icon=document.createElement('div'); |
| | icon.className='qx-i'; |
| | icon.textContent='QX'; |
| | host.appendChild(icon); |
| | var panel=document.createElement('div'); |
| | panel.className='qx-p'; |
| | panel.innerHTML= |
| | '<div class="qx-h"><span>QX AI V16.2</span><span id="qxSrv" style="font-size:10px;opacity:.85">...</span></div>'+ |
| | '<div class="qx-b">'+ |
| | '<div class="qx-res" id="qxResult">Ready</div>'+ |
| | '<div class="qx-meta" id="qxMeta">Connecting...</div>'+ |
| | '<div class="qx-row">'+ |
| | '<label>Candles<select id="qxCandles"><option>30</option><option selected>50</option><option>80</option><option>100</option><option>200</option><option>300</option><option value="all">ALL</option></select></label>'+ | | | '<label>Duration<select id="qxDur"><option value="5">5s</option><option value="10">10s</option><option value="15">15s</option><option value="30">30s</option><option value="60" selected>60s</option></select></label>'+ | | | '<label>Trades<input id="qxTrades" type="number" min="1" max="20" value="1"></label>'+ | | | '</div>'+ | | | '<div class="qx-row">'+ | | | '<label>Entry<select id="qxEntry"><option value="smart">Smart</option><option value="before_1s">Before 1s</option><option value="before_2s">Before 2s</option><option value="exact">Exact 00</option><option value="instant">Instant</option></select></label>'+ |
| | '<label>Mode<select id="qxMode"><option value="normal">Normal</option><option value="ultra">Ultra</option></select></label>'+ |
| | '<label>After<select id="qxAfter"><option value="2s">2s</option><option value="now">Now</option><option value="duration">Duration</option></select></label>'+ |
| | '</div>'+ |
| | '<div class="qx-row">'+ |
| | '<button class="qx-btn qx-scan" id="qxScan">SCAN / LOOP</button>'+ |
| | '<button class="qx-btn qx-stop" id="qxStop">STOP</button>'+ |
| | '</div>'+ |
| | '<div class="qx-row">'+ |
| | '<button class="qx-btn qx-tog" id="qxAnim">ANIM ON</button>'+ |
| | '<button class="qx-btn qx-tog" id="qxHunt">HUNT OFF</button>'+ |
| | '</div>'+ | | | '</div>'+ |
| | '<div class="qx-rs" id="qxRs"></div>'; |
| | host.appendChild(panel); |
| | function $(id){return panel.querySelector('#'+id)\|\|document.getElementById(id);} |
| | var STOP=false,BUSY=false,LOCK=false,HUNT=false,ANIM=true; |
| | var TIMERS=[]; |
| | function beep(){ |
| | try{ |
| | var a=new (window.AudioContext\|\|window.webkitAudioContext)(); |
| | var o=a.createOscillator();var g=a.createGain(); |
| | o.connect(g);g.connect(a.destination); |
| | o.frequency.value=880;g.gain.value=0.04;o.start(); |
| | setTimeout(function(){try{o.stop();a.close();}catch(e){}},120); |
| | }catch(e){} |
| | } |
| | function fetchJSON(path,opt,retry){ |
| | retry=retry\|\|3; |
| | opt=opt\|\|{}; |
| | return new Promise(function(resolve,reject){ |
| | var last=null; |
| | var attempt=0; |
| | function tryOnce(){ |
| | if(attempt>=retry){reject(last\|\|new Error('offline'));return;} |
| | attempt++; | | | var s; |
| | var chain=Promise.resolve(); |
| | for(s=0;s<SERVERS.length;s++){ |
| | (function(idx){ |
| | chain=chain.then(function(done){ |
| | if(done)return done; |
| | var base=SERVERS[(serverIndex+idx)%SERVERS.length]; |
| | var ctrl=typeof AbortController!=='undefined'?new AbortController():null; |
| | var to=ctrl?setTimeout(function(){ctrl.abort();},16000):null; |
| | var o2={}; |
| | for(var k in opt){if(Object.prototype.hasOwnProperty.call(opt,k))o2[k]=opt[k];} |
| | if(ctrl)o2.signal=ctrl.signal; |
| | return fetch(base+path,o2).then(function(r){ |
| | if(to)clearTimeout(to); |
| | if(!r.ok)throw new Error('HTTP '+r.status); |
| | serverIndex=(serverIndex+idx)%SERVERS.length; |
| | var el=$('qxSrv'); |
| | if(el)el.textContent=base.replace('http://',''); |
| | return r.json().then(function(j){return {ok:true,j:j};}); |
| | }).catch(function(e){last=e;if(to)clearTimeout(to);return null;}); |
| | }); |
| | })(s); |
| | } |
| | chain.then(function(done){ |
| | if(done&&done.ok)resolve(done.j); |
| | else setTimeout(tryOnce,400); |
| | }); |
| | } |
| | tryOnce(); |
| | }); |
| | } | | | function clickDir(dir){ | | | try{ |
| | document.querySelectorAll('[class*="close"],[aria-label="Close"]').forEach(function(b){try{b.click();}catch(e){}}); |
| | }catch(e){} |
| | var btns=[].slice.call(document.querySelectorAll('button,div[role="button"],[class*="btn"]')); |
| | var keys=dir==='UP'?['up','call','higher']:['down','put','lower']; |
| | for(var i=0;i<btns.length;i++){ |
| | var b=btns[i]; |
| | var t=((b.innerText\|\|b.textContent\|\|'')+'').toLowerCase().trim(); |
| | if(!t\|\|t.length>24)continue; |
| | var hit=false; |
| | for(var k=0;k<keys.length;k++){if(t.indexOf(keys[k])>=0)hit=true;} |
| | if(hit&&t.indexOf('support')<0&&t.indexOf('chat')<0&&t.indexOf('deposit')<0){ |
| | try{b.dispatchEvent(new PointerEvent('pointerdown',{bubbles:true}));}catch(e){} |
| | b.click(); |
| | return true; | | | } | | | } | | | return false; | | | } |
| | function doTrades(dir,num){ |
| | if(LOCK\|\|dir==='WAIT')return; |
| | LOCK=true; |
| | var max=Math.min(20,Math.max(1,parseInt(num,10)\|\|1)); |
| | var done=0; |
| | var iv=setInterval(function(){ |
| | if(done>=max){clearInterval(iv);LOCK=false;return;} |
| | clickDir(dir);done++; |
| | },280); |
| | } |
| | function isGoodSignal(g){ |
| | var dir=(g.direction\|\|'WAIT').toUpperCase(); |
| | if(dir==='CALL')dir='UP'; |
| | if(dir==='PUT')dir='DOWN'; |
| | if((g.status\|\|'')==='SIGNAL'&&(dir==='UP'\|\|dir==='DOWN')){ |
| | var z=g.zone\|\|{}; |
| | if(dir==='UP'&&z.chase_up)return{ok:false,dir:dir,why:'chase'}; |
| | if(dir==='DOWN'&&z.chase_dn)return{ok:false,dir:dir,why:'chase'}; |
| | return{ok:true,dir:dir,conf:parseInt(g.confidence,10)\|\|62,why:'server'}; |
| | } |
| | if(dir!=='UP'&&dir!=='DOWN'){ |
| | return{ok:false,dir:dir,why:String(g.wait_why\|\|g.reason\|\|'WAIT').slice(0,48)}; |
| | } |
| | var z2=g.zone\|\|{}; |
| | if(dir==='UP'&&z2.chase_up)return{ok:false,dir:dir,why:'chase'}; |
| | if(dir==='DOWN'&&z2.chase_dn)return{ok:false,dir:dir,why:'chase'}; |
| | return{ok:true,dir:dir,conf:parseInt(g.confidence,10)\|\|62,why:'ok'}; |
| | } |
| | function entryStillOk(dir){ |
| | return fetchJSON('/pressure?dir='+encodeURIComponent(dir),{method:'GET'},2).then(function(p){ |
| | if(p.block)return{ok:false,why:p.block_reason\|\|'block'}; |
| | return{ok:true,why:'ok'}; |
| | }).catch(function(){return{ok:true,why:'skip_check'};}); |
| | } |
| | function sleep(ms){ |
| | return new Promise(function(r){var t=setTimeout(r,ms);TIMERS.push(t);}); |
| | } |
| | function oneSignalCall(){ |
| | var body={ |
| | candle_limit:$('qxCandles').value, |
| | duration:parseInt($('qxDur').value,10)\|\|60, |
| | mode:$('qxMode').value\|\|'normal' |
| | }; |
| | return fetchJSON('/signal',{ |
| | method:'POST', |
| | headers:{'Content-Type':'application/json'}, |
| | body:JSON.stringify(body) |
| | }); |
| | } |
| | function paintMeta(g){ |
| | var L=g.learn\|\|{}; |
| | var z=g.zone\|\|{}; |
| | var txt= |
| | 'Mkt '+(g.market\|\|'-')+ |
| | ' \| C '+(g.candles_loaded\|\|0)+'/'+(g.candles_total\|\|0)+ |
| | ' \| T '+(g.ticks_loaded\|\|0)+'/'+(g.ticks_total\|\|0)+ |
| | ' \| Local '+(g.local_direction\|\|'-')+ |
| | ' Q'+Math.round(g.q||g.local_score||0)+ |
| | ' agree '+(g.agree\|\|0)+'/5'+ |
| | ' class '+(g.setup_class\|\|'-')+ |
| | ' \| closed '+(g.closed_bias\|\|'-')+ |
| | ' pd '+(z.pd\|\|'-')+ |
| | ' \| W/L '+(L.wins\|\|0)+'/'+(L.losses\|\|0)+ |
| | ' ('+(L.win_rate\|\|0)+'%)'+ |
| | ' \| '+(g.wait_why\|\|g.reason\|\|''); |
| | $('qxMeta').textContent=txt.slice(0,320); |
| | } |
| | function fireEntryAdaptive(dir,cnt,mode,delayMs){ |
| | if(mode==='instant'){ |
| | return entryStillOk(dir).then(function(chk){ |
| | if(!chk.ok)return{ok:false,why:chk.why}; |
| | doTrades(dir,cnt); |
| | return{ok:true,dir:dir}; |
| | }); |
| | } |
| | var wait=delayMs; |
| | if(mode==='before_1s')wait=Math.max(0,delayMs-1000); |
| | if(mode==='before_2s')wait=Math.max(0,delayMs-2000); |
| | if(mode==='exact')wait=delayMs; |
| | if(mode==='smart')wait=Math.max(200,delayMs-400); |
| | $('qxResult').textContent=dir+' in '+Math.round(wait/1000)+'s'; |
| | return sleep(wait).then(function(){ |
| | if(STOP)return{ok:false,why:'stop'}; |
| | return entryStillOk(dir).then(function(chk){ |
| | if(!chk.ok){ |
| | return oneSignalCall().then(function(g){ |
| | paintMeta(g); |
| | var sg=isGoodSignal(g); |
| | if(!sg.ok)return{ok:false,why:chk.why+'\|'+sg.why}; |
| | doTrades(sg.dir,cnt); |
| | return{ok:true,dir:sg.dir}; |
| | }); |
| | } |
| | doTrades(dir,cnt); |
| | return{ok:true,dir:dir}; |
| | }); |
| | }); |
| | } |
| | function runContinuousLoop(){ |
| | if(BUSY)return; |
| | BUSY=true;STOP=false; |
| | $('qxScan').disabled=true; |
| | function loop(){ |
| | if(STOP){ |
| | BUSY=false; |
| | $('qxScan').disabled=false; |
| | overlay.classList.remove('on'); |
| | return; | | | } |
| | if(ANIM)overlay.classList.add('on'); |
| | $('qxResult').textContent='Analyzing...'; |
| | $('qxResult').style.color='#94a3b8'; |
| | oneSignalCall().then(function(g){ |
| | paintMeta(g); |
| | var chk=isGoodSignal(g); |
| | if(!chk.ok){ |
| | $('qxResult').textContent='WAIT - '+chk.why; |
| | $('qxResult').style.color='#fbbf24'; |
| | overlay.classList.remove('on'); |
| | return sleep(HUNT?2500:3500).then(function(){ |
| | if(HUNT&&!STOP)loop(); |
| | else{BUSY=false;$('qxScan').disabled=false;} |
| | }); |
| | } |
| | beep(); |
| | var cnt=Math.max(1,parseInt($('qxTrades').value,10)\|\|1); |
| | var mode=$('qxEntry').value; |
| | var delayMs=parseInt(g.delay_ms,10); |
| | if(!delayMs\|\|isNaN(delayMs)){ |
| | delayMs=(60-new Date().getSeconds())*1000-new Date().getMilliseconds(); |
| | if(delayMs<200)delayMs+=60000; |
| | } |
| | return fireEntryAdaptive(chk.dir,cnt,mode,delayMs).then(function(res){ |
| | if(res.ok){ |
| | $('qxResult').textContent=(res.dir\|\|chk.dir)+' x'+cnt; |
| | $('qxResult').style.color=(res.dir\|\|chk.dir)==='UP'?'#38bdf8':'#f87171'; |
| | }else{ |
| | $('qxResult').textContent='Skip entry - '+(res.why\|\|''); |
| | $('qxResult').style.color='#fbbf24'; |
| | } |
| | overlay.classList.remove('on'); |
| | var after=$('qxAfter').value; |
| | var cool=2000; |
| | if(after==='now')cool=400; |
| | if(after==='duration')cool=(parseInt($('qxDur').value,10)\|\|60)*1000+500; |
| | return sleep(cool).then(function(){ |
| | if(HUNT&&!STOP)loop(); |
| | else{BUSY=false;$('qxScan').disabled=false;} |
| | }); |
| | }); |
| | }).catch(function(){ |
| | $('qxResult').textContent='SERVER OFF'; |
| | $('qxResult').style.color='#f87171'; |
| | overlay.classList.remove('on'); |
| | sleep(2000).then(function(){ |
| | if(HUNT&&!STOP)loop(); |
| | else{BUSY=false;$('qxScan').disabled=false;} |
| | }); |
| | }); |
| | } | | | loop(); | | | } | | | /* drag icon */ |
| | (function(){ |
| | var ox=0,oy=0,sx=0,sy=0,drag=false; |
| | function start(e){ |
| | drag=true; |
| | var p=e.touches?e.touches[0]:e; |
| | sx=p.clientX;sy=p.clientY; |
| | var r=icon.getBoundingClientRect();ox=r.left;oy=r.top; |
| | } |
| | function move(e){ |
| | if(!drag)return; |
| | e.preventDefault(); |
| | var p=e.touches?e.touches[0]:e; |
| | icon.style.left=(ox+p.clientX-sx)+'px'; |
| | icon.style.top=(oy+p.clientY-sy)+'px'; |
| | icon.style.right='auto'; |
| | } |
| | function end(){drag=false;} |
| | icon.addEventListener('mousedown',start); |
| | icon.addEventListener('touchstart',start,{passive:false}); |
| | window.addEventListener('mousemove',move,{passive:false}); |
| | window.addEventListener('touchmove',move,{passive:false}); |
| | window.addEventListener('mouseup',end); |
| | window.addEventListener('touchend',end); |
| | })(); |
| | /* drag panel + resize */ |
| | (function(){ |
| | var hd=panel.querySelector('.qx-h'); |
| | var ox=0,oy=0,sx=0,sy=0,drag=false; |
| | function start(e){ |
| | if(e.target&&e.target.id==='qxRs')return; |
| | drag=true; |
| | var p=e.touches?e.touches[0]:e; |
| | sx=p.clientX;sy=p.clientY; |
| | var r=panel.getBoundingClientRect();ox=r.left;oy=r.top; |
| | } |
| | function move(e){ |
| | if(!drag)return; |
| | e.preventDefault(); |
| | var p=e.touches?e.touches[0]:e; |
| | panel.style.left=(ox+p.clientX-sx)+'px'; |
| | panel.style.top=(oy+p.clientY-sy)+'px'; |
| | } |
| | function end(){drag=false;} |
| | hd.addEventListener('mousedown',start); |
| | hd.addEventListener('touchstart',start,{passive:false}); |
| | window.addEventListener('mousemove',move,{passive:false}); |
| | window.addEventListener('touchmove',move,{passive:false}); |
| | window.addEventListener('mouseup',end); |
| | window.addEventListener('touchend',end); |
| | var rs=$('qxRs'); |
| | var rw=false,bs=0,bh=0,bx=0,by=0; |
| | function rsStart(e){ |
| | rw=true; |
| | var p=e.touches?e.touches[0]:e; |
| | bx=p.clientX;by=p.clientY; |
| | var r=panel.getBoundingClientRect();bs=r.width;bh=r.height; |
| | e.preventDefault();e.stopPropagation(); |
| | } |
| | function rsMove(e){ |
| | if(!rw)return; |
| | var p=e.touches?e.touches[0]:e; |
| | panel.style.width=Math.max(280,bs+(p.clientX-bx))+'px'; |
| | panel.style.maxHeight='none'; |
| | panel.style.height=Math.max(180,bh+(p.clientY-by))+'px'; |
| | } |
| | function rsEnd(){rw=false;} |
| | rs.addEventListener('mousedown',rsStart); |
| | rs.addEventListener('touchstart',rsStart,{passive:false}); |
| | window.addEventListener('mousemove',rsMove); |
| | window.addEventListener('touchmove',rsMove,{passive:false}); |
| | window.addEventListener('mouseup',rsEnd); |
| | window.addEventListener('touchend',rsEnd); |
| | })(); |
| | icon.onclick=function(){panel.classList.toggle('show');}; |
| | $('qxAnim').onclick=function(){ |
| | ANIM=!ANIM; |
| | $('qxAnim').textContent=ANIM?'ANIM ON':'ANIM OFF'; |
| | if(ANIM)$('qxAnim').classList.add('on'); |
| | else $('qxAnim').classList.remove('on'); |
| | }; |
| | $('qxHunt').onclick=function(){ |
| | HUNT=!HUNT; |
| | $('qxHunt').textContent=HUNT?'HUNT ON':'HUNT OFF'; |
| | if(HUNT)$('qxHunt').classList.add('on'); |
| | else $('qxHunt').classList.remove('on'); |
| | }; |
| | $('qxScan').onclick=function(){ |
| | STOP=false;HUNT=true; |
| | $('qxHunt').classList.add('on'); |
| | $('qxHunt').textContent='HUNT ON'; |
| | runContinuousLoop(); |
| | }; |
| | $('qxStop').onclick=function(){ |
| | STOP=true;HUNT=false;BUSY=false;LOCK=false; |
| | TIMERS.forEach(clearTimeout);TIMERS=[]; |
| | $('qxHunt').classList.remove('on'); |
| | $('qxHunt').textContent='HUNT OFF'; |
| | overlay.classList.remove('on'); |
| | $('qxScan').disabled=false; |
| | $('qxResult').textContent='STOPPED'; |
| | $('qxResult').style.color='#f87171'; |
| | }; |
| | fetchJSON('/status',{method:'GET'}).then(function(s){ |
| | $('qxMeta').textContent= |
| | 'Online v'+(s.version\|\|'?')+ |
| | ' \| '+(s.market\|\|'')+ |
| | ' \| C'+(s.candles\|\|0)+ |
| | ' T'+(s.ticks\|\|0); |
| | }).catch(function(){ |
| | $('qxMeta').textContent='Server offline - check IP or tunnel'; |
| | }); |
| | })(); |