Video 8: Polymarket 15-Minute Crypto Trading Bot
Automated trading bot for Polymarket's 15-minute crypto up/down markets. Features built-in stop loss for risk management, time delay restrictions for smarter entry timing, and wallet response time handling to account for on-chain confirmation delays. Designed to monitor price action, place trades at high-probability trigger points, and manage positions across sessions.
YouTube Video
Screen Map

HUD Code
Script =
(%
(()=>{const t=document.getElementById("POLY_HUD");t&&t.remove(),window.__POLY_HUD_STATE__||(window.__POLY_HUD_STATE__={});const e=window.__POLY_HUD_STATE__;try{(e.observers||[]).forEach(t=>t.disconnect())}catch{}if(e.observers=[],e.abortController)try{e.abortController.abort()}catch{}e.abortController=new AbortController;const n=e.abortController.signal,o="#00ff66",i="__POLY_DOLLARS__",r="__POLY_HUD_POS__",l="__POLY_HUD_ZOOM__";let c=parseInt(localStorage.getItem(l),10)||16;let a=null,u=0;const s=(...t)=>t.forEach(t=>{try{t()}catch{}}),d=()=>{if(a)return;const t=Date.now()-u;t>=300?(u=Date.now(),s(Y,R)):a=setTimeout(()=>{a=null,u=Date.now(),s(Y,R)},300-t)},f=document.createElement("div");f.id="POLY_HUD",f.style.cssText=``\n position: fixed;\n top: 90px;\n left: 90px;\n z-index: 2147483647;\n background: black;\n border: 2px solid ${o};\n border-radius: 12px;\n padding: 12px;\n font-family: monospace;\n color: ${o};\n user-select: none;\n min-width: 391px;\n ``;try{const t=JSON.parse(localStorage.getItem(r)||"null");t&&Number.isFinite(t.left)&&Number.isFinite(t.top)&&(f.style.left=``${t.left}px``,f.style.top=``${t.top}px``)}catch{}const p=localStorage.getItem(i)||"";f.innerHTML=``\n <div id="hudHeader" style="display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px;cursor:move">\n <div style="opacity:.9;font-weight:700">POLY HUD</div>\n <div style="display:flex;gap:10px">\n <button id="dec">−</button>\n <button id="inc">+</button>\n <button id="copyPrice">COPY</button>\n <button id="liveSession">LIVE SESSION</button>\n </div>\n </div>\n\n <table id="tbl" style="border-collapse:collapse;font-size:${c}px;width:100%;text-align:center">\n <tr>\n <td style="border:1px solid ${o};padding:18px" id="aLabel">UP</td>\n <td style="border:1px solid ${o};padding:18px" id="aPrice">--</td>\n </tr>\n <tr>\n <td style="border:1px solid ${o};padding:18px" id="bLabel">DOWN</td>\n <td style="border:1px solid ${o};padding:18px" id="bPrice">--</td>\n </tr>\n </table>\n\n <div style="display:flex;gap:12px;margin-top:14px">\n <button id="buyA" class="bigBuy">BUY UP</button>\n <button id="buyB" class="bigBuy">BUY DOWN</button>\n </div>\n\n <div style="display:flex;gap:12px;margin-top:14px">\n <button id="redeemBtn" class="bigBuy">REDEEM</button>\n </div>\n\n <div style="display:flex;gap:12px;margin-top:14px;align-items:center">\n <input id="dollarsBox" placeholder="DOLLARS" value="${p.replace(/"/g,""")}"\n style="\n flex:1;\n background:black;\n color:${o};\n border:1px solid ${o};\n padding:12px 14px;\n font-family:monospace;\n outline:none;\n font-size:16px;\n "/>\n <button id="fillDollars" class="fillBtn">FILL DOLLARS</button>\n </div>\n\n <div style="display:flex;gap:12px;margin-top:14px;align-items:center">\n <div style="min-width:98px;opacity:0.9;font-weight:800">POSITION</div>\n <div id="posBox" style="\n flex:1;\n border:2px solid ${o};\n padding:18px 22px;\n text-align:center;\n letter-spacing:2px;\n font-weight:900;\n font-size: 20px;\n ">0</div>\n </div>\n\n <div id="dbg" style="margin-top:12px;font-size:12px;opacity:0.85;text-align:left"></div>\n ``,f.querySelectorAll("button").forEach(t=>{t.style.cssText=``\n background:black;\n color:${o};\n border:1px solid ${o};\n cursor:pointer;\n font-family:monospace;\n white-space:nowrap;\n ``}),f.querySelector("#dec").style.padding="10px 14px",f.querySelector("#inc").style.padding="10px 14px",f.querySelector("#copyPrice").style.padding="10px 16px",f.querySelector("#liveSession").style.padding="10px 16px",f.querySelectorAll(".bigBuy").forEach(t=>{t.style.flex="1",t.style.padding="22px 18px",t.style.fontSize="20px",t.style.fontWeight="900",t.style.letterSpacing="1px"});const b=f.querySelector("#fillDollars");b.style.padding="12px 16px",b.style.fontSize="16px",b.style.fontWeight="800",document.body.appendChild(f);const y=f.querySelector("#dbg"),x=f.querySelector("#posBox"),g=f.querySelector("#tbl"),m=f.querySelector("#hudHeader"),E=f.querySelector("#aLabel"),S=f.querySelector("#bLabel"),w=f.querySelector("#aPrice"),v=f.querySelector("#bPrice"),L=t=>y.textContent=t;e.noBalanceUntil=e.noBalanceUntil||0;let h=!1,D=0,C=0;const O=()=>{try{localStorage.setItem(r,JSON.stringify({left:f.offsetLeft,top:f.offsetTop}))}catch{}};m.addEventListener("mousedown",t=>{t.target.closest("button")||t.target.closest("input")||(h=!0,D=t.clientX-f.offsetLeft,C=t.clientY-f.offsetTop,t.preventDefault())}),document.addEventListener("mousemove",t=>{h&&(f.style.left=t.clientX-D+"px",f.style.top=t.clientY-C+"px")},{signal:n}),document.addEventListener("mouseup",()=>{h&&(h=!1,O())},{signal:n}),window.addEventListener("blur",()=>{h&&(h=!1,O())},{signal:n}),f.querySelector("#inc").onclick=()=>{c+=2,g.style.fontSize=c+"px",localStorage.setItem(l,c)},f.querySelector("#dec").onclick=()=>{c=Math.max(10,c-2),g.style.fontSize=c+"px",localStorage.setItem(l,c)};const q=t=>new Promise(e=>setTimeout(e,t)),N=t=>(t||"").replace(/\s+/g," ").trim().toLowerCase();function $(t){if(!t)return!1;try{t.scrollIntoView({block:"center",inline:"center"})}catch{}const e=t.getBoundingClientRect(),n=Math.floor(e.left+e.width/2),o=Math.floor(e.top+e.height/2),i={bubbles:!0,cancelable:!0,composed:!0,view:window,clientX:n,clientY:o,screenX:n,screenY:o,button:0,buttons:1};try{return t.focus?.(),t.dispatchEvent(new PointerEvent("pointerdown",{...i,pointerId:1,pointerType:"mouse",isPrimary:!0})),t.dispatchEvent(new MouseEvent("mousedown",i)),t.dispatchEvent(new PointerEvent("pointerup",{...i,pointerId:1,pointerType:"mouse",isPrimary:!0})),t.dispatchEvent(new MouseEvent("mouseup",i)),t.dispatchEvent(new MouseEvent("click",i)),!0}catch{try{return t.click?.(),!0}catch{}return!1}}function P(t){if(null==t||""===t)return null;const e="number"==typeof t?t:parseFloat(String(t).replace(/,/g,""));return!Number.isFinite(e)||e<0||e>1e3?null:String(Math.floor(e))}function _(t,e=!1){const n=(t||"").replace(/\s+/g," ").trim();if(!n)return null;const o=n.match(/([\d,.]+)\s*¢/);return o?P(o[1]):e&&/^[\d,.]+$/.test(n)?P(n):null}function B(t,e=[]){if(!t)return e.join("");if(t.nodeType===Node.TEXT_NODE)return e.push(t.nodeValue||""),e.join("");if(t.nodeType!==Node.ELEMENT_NODE&&t.nodeType!==Node.DOCUMENT_FRAGMENT_NODE)return e.join("");if(t.nodeType===Node.ELEMENT_NODE){const n=t;if(n.hasAttribute("inert")||"true"===n.getAttribute("aria-hidden"))return e.join("");n.shadowRoot&&B(n.shadowRoot,e)}return t.childNodes.forEach(t=>B(t,e)),e.join("")}function U(t){let e=null;try{const n=t.getAttribute("data");n&&(e=JSON.parse(n))}catch{}const n=t._data||t.data||e,o=[n?.valueAsString,n?.value,t.value,t.getAttribute("aria-label"),t.getAttribute("aria-valuetext"),t.getAttribute("aria-valuenow"),t.getAttribute("title"),t.getAttribute("data-value"),t.getAttribute("value")];for(const t of o){const e=_(t,!1);if(null!=e)return e;const n=_(t,!0);if(null!=n)return n}return _(B(t).replace(/\s+/g,""),!0)}function A(){const t=[...document.querySelectorAll("#outcome-buttons button.trading-button")],e=t.length?t:[...document.querySelectorAll("button.trading-button")];let n=null,o=null;for(const t of e){if(f.contains(t))continue;if("blue"===t.dataset.color)continue;const e=N(t.textContent);!n&&/\bup/.test(e)&&(n=t),!o&&/\bdown/.test(e)&&(o=t)}return{aLabel:"UP",bLabel:"DOWN",aEl:n,bEl:o}}function I(t){if(!t)return null;const e=_(t.textContent,!1);if(null!=e)return e;const n=t.querySelectorAll("number-flow-react, number-flow");for(const t of n){const e=U(t);if(null!=e)return e}return null}function Y(){const{aLabel:t,bLabel:n,aEl:o,bEl:i}=A();if(E.textContent=t,S.textContent=n,e.aEl=o,e.bEl=i,Date.now()<e.noBalanceUntil)return w.textContent="NB",v.textContent="NB",void L("Prices: NB (no balance)");w.textContent=I(o)??"--",v.textContent=I(i)??"--",L(``Prices: Up=${w.textContent} Down=${v.textContent}``)}let T=null;const k=f.querySelector("#buyA"),M=f.querySelector("#buyB");function R(){let t=function(){const t=document.querySelectorAll("h3");for(const e of t){if(f.contains(e))continue;if("Positions"!==(e.textContent||"").trim())continue;const t=e.closest("div");if(!t)continue;const n=t.querySelectorAll("div.whitespace-nowrap.text-sm");for(let t=0;t<n.length;t++){const e=(n[t].textContent||"").trim();if(/^up$/i.test(e)&&t+1<n.length){const e=(n[t+1].textContent||"").trim(),o=parseInt(e,10);if(!isNaN(o)&&o>0)return{qty:o,side:"up"}}if(/^down$/i.test(e)&&t+1<n.length){const e=(n[t+1].textContent||"").trim(),o=parseInt(e,10);if(!isNaN(o)&&o>0)return{qty:o,side:"down"}}}}return{qty:0,side:null}}();0===t.qty&&(t=function(){const t=document.querySelectorAll("span");for(const e of t){if(f.contains(e))continue;const t=(e.textContent||"").trim().match(/([\d.]+)\s+shares?/i);if(t){const n=Math.floor(parseFloat(t[1]));if(n<=0)continue;let o=null,i=e.parentElement;for(;i;){if(i.classList.contains("flex-1")){const t=i.parentElement;if(t){const e=[...t.children].filter(t=>t.classList.contains("flex-1"));2===e.length&&(o=0===e.indexOf(i)?"up":"down")}break}i=i.parentElement}return{qty:n,side:o}}}return{qty:0,side:null}}()),x.textContent=t.qty,T=t.side,"up"===t.side?(k.textContent="SELL UP",M.textContent="BUY DOWN"):"down"===t.side?(k.textContent="BUY UP",M.textContent="SELL DOWN"):(k.textContent="BUY UP",M.textContent="BUY DOWN")}const H=f.querySelector("#dollarsBox");function F(t,e){const n=document.querySelector("#market-order-amount-input")||null;if(!n)return L(``${e}: amount input not found``);n.focus(),$(n),function(t,e){const n=Object.getPrototypeOf(t),o=Object.getOwnPropertyDescriptor(n,"value");o&&o.set?o.set.call(t,e):t.value=e}(n,t),n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0})),n.blur(),L(``${e}: ${t}``)}function W(){const t=(H.value||"").trim();if(!t)return L("FILL DOLLARS: empty");const e=t.replace(/[^\d.]/g,"");if(!e)return L("FILL DOLLARS: invalid");F(e,"FILL DOLLARS")}function z(){const t=document.querySelectorAll('button[role="radio"]');for(const e of t)if(!f.contains(e)&&("SELL"===e.value||"sell"===N(e.textContent)))return e;return null}function j(){const t=document.querySelectorAll("button.trading-button");for(const e of t)if(!f.contains(e)&&"blue"===e.dataset.color)return e;return null}async function V(t,e=6e4){const n=Date.now();let o=100;for(;Date.now()-n<e;){const e=t();if(e)return e;await q(o),o=Math.min(1.5*o,1e3)}return null}async function X(t){const{aEl:n,bEl:o}=A(),i="UP"===t?n:o;if(!i)return L(``BUY ${t}: pill not found``);const r=function(){const t=document.querySelectorAll('button[role="radio"]');for(const e of t)if(!f.contains(e)&&("BUY"===e.value||"buy"===N(e.textContent)))return e;return null}();r&&"checked"!==r.dataset.state&&(L(``BUY ${t}: switching to Buy tab``),$(r),await q(300)),L(``BUY ${t}: select``),$(i),await q(200),L(``BUY ${t}: fill dollars``),W(),await q(300),L(``BUY ${t}: waiting for action button``);const l=await V(j);if(!l)return L(``BUY ${t}: action button not found``);if(function(t){const e=N(t);return e.includes("deposit")||e.includes("deposite")}(l.textContent||""))return function(t=5e3){e.noBalanceUntil=Date.now()+t,w.textContent="NB",v.textContent="NB"}(5e3),L(``BUY ${t}: insufficient balance (NB 5s)``);L(``BUY ${t}: click action``),$(l),await q(500);const c=z();c&&$(c),L(``BUY ${t}: DONE``)}async function J(t){const{aEl:e,bEl:n}=A(),o="UP"===t?e:n;if(!o)return L(``SELL ${t}: pill not found``);const i=z();if(!i)return L(``SELL ${t}: Sell tab not found``);L(``SELL ${t}: switching to Sell tab``),$(i),await q(300),L(``SELL ${t}: select pill``),$(o),await q(300),L(``SELL ${t}: clicking Max``);const r=await V(()=>{const t=document.querySelectorAll("button");for(const e of t)if(!f.contains(e)&&/^max$/i.test((e.textContent||"").trim()))return e;return null},5e3);if(!r)return L(``SELL ${t}: Max button not found``);$(r),await q(300),L(``SELL ${t}: waiting for action button``);const l=await V(j);if(!l)return L(``SELL ${t}: action button not found``);L(``SELL ${t}: click action``),$(l),L(``SELL ${t}: DONE``)}function G(){const t=document.querySelectorAll("button");for(const e of t){if(f.contains(e))continue;const t=(e.textContent||"").trim();if(/\bcash\b/i.test(t))return e}return null}function Z(t){return t.disabled||"true"===t.getAttribute("aria-disabled")}function K(t){const e=N(t);return/^claim\b/.test(e)||/^redeem\b/.test(e)}function Q(){const t=document.querySelectorAll("button");for(const e of t){if(f.contains(e))continue;if(e.closest('[role="dialog"]'))continue;if(Z(e))continue;if(K((e.textContent||"").trim()))return e}return null}function tt(){const t=document.querySelector('[role="dialog"]');if(!t)return null;const e=t.querySelectorAll("button");for(const t of e)if(!Z(t)&&K(t.textContent||""))return t;return null}function et(){const t=function(){const t=document.querySelector('button[aria-label="Go to live market"]');return t&&!f.contains(t)?t:null}();if(!t)return L("LIVE SESSION: no live session found");L("LIVE SESSION: clicking "+(t.textContent||"").trim()),$(t)}function nt(){const t=document.querySelectorAll("button");for(const e of t)if(!f.contains(e)&&"done"===N(e.textContent))return L("AUTO-DISMISS: clicking Done"),void $(e)}H.addEventListener("input",()=>localStorage.setItem(i,H.value)),f.querySelector("#fillDollars").onclick=()=>W(),k.onclick=()=>"up"===T?J("UP"):X("UP"),M.onclick=()=>"down"===T?J("DOWN"):X("DOWN"),f.querySelector("#redeemBtn").onclick=()=>async function(){L("REDEEM: clicking Cash button");const t=await V(G,5e3);if(!t)return L("REDEEM: Cash button not found");$(t),await q(500),L("REDEEM: waiting for Redeem/Claim button");const e=await V(Q,1e4);if(!e)return L("REDEEM: no claimable position found");$(e),await q(500),L("REDEEM: waiting for Claim dialog");const n=await V(tt,1e4);if(!n)return L("REDEEM: Claim dialog not found");$(n),L("REDEEM: DONE")}(),f.querySelector("#copyPrice").onclick=()=>{let t=null;if("up"===T){const e=w.textContent.trim();"--"!==e&&(t=e)}else if("down"===T){const e=v.textContent.trim();"--"!==e&&(t=e)}if(null===t)return L("COPY: no position to copy");navigator.clipboard.writeText(t).then(()=>L(``COPIED: ${t}``),()=>L("COPY: clipboard failed"))},f.querySelector("#liveSession").onclick=()=>et();const ot=new MutationObserver(t=>{for(const e of t)if(!f.contains(e.target))return void d()});ot.observe(document.body,{childList:!0,subtree:!0,characterData:!0}),e.observers.push(ot),e.timerInterval&&clearInterval(e.timerInterval),e.timerInterval=setInterval(()=>{s(Y,R,nt)},1e3),d(),L("Poly HUD: ON")})();
)
LoadIndicator() {
global Script
Clipboard :=
Clipboard := Script
ClipWait, 1
SendInput, ^+j
Sleep 1200
SendInput, ^v
Sleep 1200
SendInput, allow pasting
Sleep 4000
SendInput, {Enter}
Sleep 2000
SendInput, ^v
SendInput, {Enter}
sleep 2000
SendInput, ^+j
}
click(point.a)
LoadIndicator()
Nightshark TradingBot Code
;=== THIS IS FOR POLYMARKET 15-MINUTE CRYPTO MARKET ONLY ====
triggerPoint := 75 ; BUY Price Point
exitPoint := 40 ; Stop Loss price point
triggerMinute := 8 ; remaining minutes
walletDelay := 3500 ; 3.5 seconds, you can adjust this based on your wallet response time
Log("Application Started !!")
loop {
click(point.c)
sleep 2000
exitCode := ""
if (Mod(A_Index, 2) = 0) {
Log("===REDEEMING REWARDS===")
redeem()
}
Log("Waiting for trade window last " . triggerMinute . " Minutes")
loop {
if (isXMinRemaining(triggerMinute))
break
sleep 500
}
Log("Monitoring UP & Down to hit Trigger Price > " . triggerPoint )
loop{
read_areas()
sleep 50 ; Adding a small sleep to prevent excessive CPU usage
} until (toNumber(area[1]) > triggerPoint || toNumber(area[2]) > triggerPoint || is5SecBeforeQuarter() )
if (toNumber(area[1]) > triggerPoint && toNumber(area[3]) = 0) {
Log("UP triggered !! Placing Up Order")
loop, 4{
click(point.a)
sleep 500
read_area(1)
if(area[1]~="NB"){
Log(" ====NOT ENOUGH BALANCE==")
Log("Skipping to Next Session")
exitCode = "NB"
break
}
sleep walletDelay
click(point.f) ; Wallet signature
sleep 4000
read_areas()
if (toNumber(area[3]) > 0) {
Log("UP position confirmed")
break
}
else {
Log("Position not confirmed ! Retrying ...")
sleep 1000
}
}
if(toNumber(area[3]) > 0) {
Log("Monitoring StopLoss @" . exitPoint . " or Resolution")
loop {
read_areas()
if (toNumber(area[1]) < exitPoint) {
if(DoubleExitCheck() < exitPoint) {
break
}
}
sleep 50 ; Adding a small sleep to prevent excessive CPU usage
} until (is5SecBeforeQuarter())
if (toNumber(area[1]) < exitPoint && DoubleExitCheck() < exitPoint && toNumber(area[1]) > 2) {
Log("Stop Loss Triggered !! Closing UP Position")
loop, 4 {
click(point.a)
sleep walletDelay
click(point.f)
sleep 4000
read_areas()
if (toNumber(area[3]) = 0) {
Log("UP Position closed ")
break
}
else {
Log("Position not confirmed ! Retrying ...")
sleep 1000
}
}
}
}
else if (exitCode != "NB") {
Log("Position did not filled on 4 retries ! Skipping to next session")
}
}
else if (toNumber(area[2]) > triggerPoint && toNumber(area[3]) = 0) {
Log("Down triggered !! Placing Down Order")
loop, 4 {
click(point.b)
sleep 500
read_area(1)
if(area[1]~="NB"){
Log(" ====NOT ENOUGH BALANCE==")
Log("Skipping to Next Session")
exitCode := "NB"
break
}
sleep walletDelay
click(point.f)
sleep 4000
read_areas()
if (toNumber(area[3]) > 0) {
Log("Down position confirmed")
break
}
else {
Log("Position not confirmed ! Retrying ...")
sleep 1000
}
}
if(toNumber(area[3]) > 0) {
Log("Monitoring StopLoss @" . exitPoint . " or Resolution")
loop {
read_areas()
if (toNumber(area[2]) < exitPoint) {
if(DoubleExitCheck() < exitPoint) {
break
}
}
sleep 50 ; Adding a small sleep to prevent excessive CPU usage
} until (is5SecBeforeQuarter())
if (toNumber(area[2]) < exitPoint && DoubleExitCheck() < exitPoint && toNumber(area[2]) > 2) {
Log("Stop Loss Triggered !! Closing Down Position")
loop, 4 {
click(point.b)
sleep walletDelay
click(point.f)
sleep 4000
read_areas()
if (toNumber(area[3]) = 0) {
Log("Down Position closed ")
break
}
else {
Log("Position not confirmed ! Retrying ...")
sleep 1000
}
}
}
}
else if (exitCode != "NB") {
Log("Position did not filled on 4 retries ! Skipping to next session")
}
}
else if (toNumber(area[3]) > 0) {
Log("Position already exists , skipping this session")
}
Log("Waiting for end of Session")
loop {
sleep 100
} until (is5SecBeforeQuarter())
sleep 6000
click(point.c)
sleep 1000
if (Mod(A_Index, 5) = 0) {
resetHUD()
}
}
isXMinRemaining(x) {
currentMinute := A_Min + 0
remaining := 15 - Mod(currentMinute, 15)
if (remaining <= x)
return true
else
return false
}
is5SecBeforeQuarter() {
minute := A_Min + 0
second := A_Sec + 0
if (Mod(minute, 15) = 14 && second >= 55) {
Log("Last 5 second. launching for new session")
return true
}
else {
return false
}
}
DoubleExitCheck() {
click(point.d)
sleep 1000
value := Clipboard
return value
}
redeem() {
click(point.e)
sleep 500
click(point.e)
sleep 8000
click(point.f)
Send, !{Left}
sleep 2000
click(point.c)
}
resetHUD() {
Log("Refreshing the Page, 20 seconds delay")
SendInput, {F5}
sleep 20000
Log("Resetting HUD")
SendInput, ^+j
sleep 2500
SendInput,{Up}
sleep 2500
SendInput, {Enter}
sleep 2500
SendInput, ^+j
}