@oracle-agent/oracle 0.35.30 → 0.35.32

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.
Files changed (54) hide show
  1. package/README.md +19 -1
  2. package/dist/agent-lifecycle.mjs +3 -3
  3. package/dist/agent-sessions.mjs +9 -6
  4. package/dist/assets/skills/oracle-desk-product/SKILL.md +1 -1
  5. package/dist/bin/desk-server.mjs +37 -37
  6. package/dist/bin/oracle-data-mcp.mjs +17 -17
  7. package/dist/bin/oracle-gateway.mjs +14 -14
  8. package/dist/bin/oracle-investigate.mjs +11 -0
  9. package/dist/bin/oracle-launch-radar-shadow.mjs +6 -6
  10. package/dist/bin/oracle-mev-arb-shadow.mjs +6 -6
  11. package/dist/bin/oracle-mev-shadow.mjs +6 -6
  12. package/dist/bin/oracle-public-server.mjs +5 -5
  13. package/dist/bin/oracle-route.mjs +22 -22
  14. package/dist/bin/oracle-scan.mjs +15 -15
  15. package/dist/cli/commands/agent-session.mjs +11 -0
  16. package/dist/cli/commands/chat.mjs +202 -199
  17. package/dist/cli/commands/context.mjs +6 -6
  18. package/dist/cli/commands/doctor.mjs +9 -9
  19. package/dist/cli/commands/eval.mjs +50 -50
  20. package/dist/cli/commands/farm.mjs +22 -22
  21. package/dist/cli/commands/follow.mjs +16 -16
  22. package/dist/cli/commands/lifecycle.mjs +6 -6
  23. package/dist/cli/commands/model.mjs +206 -203
  24. package/dist/cli/commands/quickstart.mjs +7 -7
  25. package/dist/cli/commands/receipt.mjs +12 -12
  26. package/dist/cli/commands/resolve.mjs +12 -12
  27. package/dist/cli/commands/sign.mjs +21 -13
  28. package/dist/cli/commands/signer.mjs +19 -19
  29. package/dist/cli/commands/snipe.mjs +11 -11
  30. package/dist/cli/commands/strategy.mjs +5 -5
  31. package/dist/cli/commands/swap.mjs +31 -31
  32. package/dist/cli/commands/venues.mjs +2 -2
  33. package/dist/context-graph.mjs +3 -3
  34. package/dist/data/desk-data.mjs +35 -35
  35. package/dist/data/names.mjs +3 -3
  36. package/dist/data/providers/farming.mjs +2 -2
  37. package/dist/data/providers/lp-destination-discovery.mjs +4 -4
  38. package/dist/index.mjs +49 -49
  39. package/dist/investigator/index.mjs +2 -0
  40. package/dist/launch-radar/index.mjs +5 -5
  41. package/dist/local-signer/anvil-attestation-worker.mjs +1 -1
  42. package/dist/local-signer/index.mjs +3 -3
  43. package/dist/local-signer/runtime.mjs +19 -19
  44. package/dist/nft/universal-mint-router.mjs +4 -4
  45. package/dist/router/index.mjs +3 -3
  46. package/dist/router/prepare-bridge.mjs +2 -2
  47. package/dist/scanner/index.mjs +4 -4
  48. package/dist/strategy/index.mjs +3 -3
  49. package/dist/teams/index.mjs +1 -1
  50. package/dist/tui/standalone-client.mjs +44 -44
  51. package/package.json +3 -1
  52. package/public/eval-report.json +2 -2
  53. package/public/oracle-splash/index.html +2 -2
  54. package/server.json +2 -2
@@ -1,3 +1,3 @@
1
- import{createHash as No}from"node:crypto";import{createHash as nr}from"node:crypto";import fe from"node:net";import un from"node:dns";var fn=new Set(["localhost","metadata.google.internal","metadata.goog"]);function qe(e){let t=String(e).toLowerCase().split("%")[0];if((t.match(/::/g)||[]).length>1)return null;let r=d=>{if(!d)return[];let c=d.split(":"),f=c.at(-1);if(f?.includes(".")){let p=f.split(".").map(Number);if(p.length!==4||p.some(h=>!Number.isInteger(h)||h<0||h>255))return null;c.splice(c.length-1,1,(p[0]<<8|p[1]).toString(16),(p[2]<<8|p[3]).toString(16))}return c.some(p=>!/^[0-9a-f]{1,4}$/.test(p))?null:c.map(p=>Number.parseInt(p,16))},[n,o]=t.split("::"),s=r(n),i=r(o);if(!s||!i)return null;let a=t.includes("::"),l=8-s.length-i.length;if(!a&&l!==0||a&&l<1)return null;let u=[...s,...Array(Math.max(0,l)).fill(0),...i];return u.length!==8?null:Uint8Array.from(u.flatMap(d=>[d>>8,d&255]))}function ot(e,t,r){let n=Math.floor(r/8),o=r%8;for(let i=0;i<n;i+=1)if(e[i]!==t[i])return!1;if(!o)return!0;let s=255<<8-o;return(e[n]&s)===(t[n]&s)}function st(e){if(fe.isIPv4(e)){let t=e.split(".").map(Number);return!(t[0]===0||t[0]===10||t[0]===127||t[0]>=224||t[0]===100&&t[1]>=64&&t[1]<=127||t[0]===169&&t[1]===254||t[0]===172&&t[1]>=16&&t[1]<=31||t[0]===192&&(t[1]===0||t[1]===2||t[1]===168)||t[0]===192&&t[1]===88&&t[2]===99||t[0]===198&&(t[1]===18||t[1]===19||t[1]===51)||t[0]===203&&t[1]===0&&t[2]===113)}if(fe.isIPv6(e)){let t=qe(e);if(!t)return!1;let r=qe("::ffff:0:0");return ot(t,r,96)?st([...t.slice(12)].join(".")):ot(t,qe("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([o,s])=>ot(t,qe(o),s)):!1}return!1}function dn(e){let t;try{t=new URL(String(e))}catch{return{ok:!1,error:`not a valid URL: ${String(e).slice(0,120)}`}}if(t.protocol!=="http:"&&t.protocol!=="https:")return{ok:!1,error:`refused protocol ${t.protocol} (only http/https)`};let r=t.hostname.toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,"");if(fn.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=fe.isIP(r);return n!==0&&!st(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function it(e,{lookupFn:t=un.promises.lookup}={}){let r=dn(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:fe.isIPv6(r.host)?6:4}]};let n;try{n=await t(r.host,{all:!0,verbatim:!0})}catch{return{ok:!1,error:`refused: ${r.host} did not resolve`}}return!Array.isArray(n)||n.length===0||n.some(o=>!st(o.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}async function at({requireUndici:e=!1,importUndici:t=()=>import("undici")}={}){let r,n;try{let c=await t();r=c.Agent,n=c.fetch}catch(c){if(e)throw new Error(`egress-guard: untrustedUrl pinning requires the undici package, which failed to load: ${c?.message||c}`);return null}if(typeof r!="function"||typeof n!="function"){if(e)throw new Error("egress-guard: untrustedUrl pinning requires undici's Agent and fetch exports, which were not found on the imported module");return null}let o=c=>String(c).toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,""),s=new Map,i=c=>(Array.isArray(c)?c:[c]).map(f=>typeof f=="string"?{address:f}:f).filter(f=>f&&f.address).map(f=>({address:f.address,family:f.family||(fe.isIPv6(f.address)?6:4)})),a=(c,f,p)=>{s.set(o(c),i(typeof f=="string"?[{address:f,family:p}]:f))},l=c=>{let f=o(c);if(fe.isIP(f))return[{address:f,family:fe.isIPv6(f)?6:4}];let p=s.get(f);if(!p||!p.length)throw new Error(`refused: unpinned host ${c} during pinned fetch`);return p},u=new r({connect:{lookup(c,f,p){let h;try{h=l(c)}catch(w){return p(w)}return f?.all?p(null,h):p(null,h[0].address,h[0].family)}}}),d=pn((c,f={})=>n(c,{...f,dispatcher:u}),a);return{dispatcher:u,fetch:d,pin:a,resolve:l,async close(){try{await u.destroy()}catch{}}}}var ct=Symbol.for("oracle.egressGuard.pinCapableFetch");function pn(e,t){if(typeof e!="function")throw new Error("markPinCapableFetch: fetchImpl must be a function");if(typeof t!="function")throw new Error("markPinCapableFetch: pin must be a function");return e[ct]=Object.freeze({pin:t}),e}function lt(e){return typeof e=="function"&&typeof e[ct]?.pin=="function"}function rr(e,t,r){if(!lt(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[ct].pin(t,r)}var mn=new Set([408,425,429,500,502,503,504]),or=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),hn=2,sr=4e3,ur=["authorization","x-api-key","x-tensor-api-key","0x-api-key","api-key","cookie","proxy-authorization"],yn=new Set([301,302,303,307,308]),ir=3,wn=64*1024;function gn(e){let t=String(e||"").toLowerCase();return ur.includes(t)||/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(t)}function bn(e){let t={};for(let[r,n]of Object.entries(e||{}))gn(r)||(t[r]=n);return t}function En(e,t){if(!e)throw new Error(`HTTP redirect from ${t} missing Location`);let r=new URL(String(e),String(t));if(r.protocol!=="http:"&&r.protocol!=="https:")throw new Error(`HTTP redirect from ${t} used unsupported protocol ${r.protocol}`);return r.toString()}function kn(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}var ut=new Map,xn=/(?:^|_)(send|submit|broadcast|sign|requestAirdrop)(?=[A-Z_]|$)/i,Sn=new Set(["allMids","l2Book","outcomeMeta","spotClearinghouseState","userFills","meta","metaAndAssetCtxs","perpDexs","candleSnapshot","fundingHistory","openOrders","frontendOpenOrders","clearinghouseState","spotMeta","validatorSummaries","delegatorSummary","delegations","delegatorRewards","delegatorHistory","maxBuilderFee"]);function ar(e){let t=String(e?.method||"");return t?!xn.test(t):!1}function An(e,t){if(e==="GET"&&t==null)return!0;if(e!=="POST"||t==null)return!1;let r=t;if(typeof t=="string")try{r=JSON.parse(t)}catch{return!1}return Array.isArray(r)?r.length>0&&r.every(ar):!r||typeof r!="object"?!1:r.jsonrpc&&r.method?ar(r):typeof r.type=="string"&&Sn.has(r.type)&&r.action==null&&r.signature==null&&r.nonce==null}function $n(e,t,r,n={},o=null){let s={};for(let[f,p]of Object.entries(r||{}))s[f.toLowerCase()]=p;let i=Object.keys(s).filter(f=>/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(f)),l=[...new Set([...ur,...i])].sort().map(f=>`${f}=${s[f]??""}`).join(`
2
- `),u=nr("sha256").update(l).digest("hex").slice(0,32),d=`${n.untrustedUrl?"untrusted":"trusted"}:${n.maxResponseBytes??"unbounded"}`,c=o==null?"-":nr("sha256").update(String(o)).digest("hex").slice(0,32);return`${e} ${t} ${d} ${u} ${c}`}function Pn(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,sr):Math.min(250*2**e,sr)+Math.floor(Math.random()*100)}var Tn=e=>new Promise(t=>setTimeout(t,e));function Pe(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function ft(e,t,r){return Pe(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function Te(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function In(e){return e?e.byteLength??e.length??0:0}async function cr(e,t,{url:r,truncate:n=!1,onOversize:o}={}){if(t==null)return await e.text();let s=Number(e.headers?.get?.("content-length"));if(Number.isFinite(s)&&s>t&&(Te(e),!n))throw ft(r,`content-length ${s}`,t);let i=e.body?.getReader?.();if(!i){let c=await e.text(),f=Buffer.byteLength(c,"utf8");if(f>t){if(!n)throw ft(r,`body ${f} bytes`,t);return Buffer.from(c,"utf8").subarray(0,t).toString("utf8")}return c}let a=[],l=0,u=!1;try{for(;;){let{value:c,done:f}=await i.read();if(f)break;if(c&&(a.push(Buffer.from(c)),l+=In(c),l>t)){u=!0;break}}}finally{if(u)try{await i.cancel()}catch{}try{i.releaseLock?.()}catch{}}if(u&&(typeof o=="function"&&o(),!n))throw ft(r,`streamed ${l} bytes`,t);let d=Buffer.concat(a);return(u?d.subarray(0,t):d).toString("utf8")}function lr(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function _n(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:s,lookupFn:i,realFetch:a,untrustedUrl:l=!1,maxResponseBytes:u=null,importUndici:d,validateResponse:c,signal:f}){let p=new AbortController,h=setTimeout(()=>p.abort(),s),w=f?typeof AbortSignal.any=="function"?AbortSignal.any([f,p.signal]):f:p.signal,k=null,S=t,I=i?{lookupFn:i}:{};if(l&&!a&&!lt(S))throw Pe(`HTTP refused ${e}: untrustedUrl requires a pin-capable fetchImpl (see markPinCapableFetch in egress-guard.mjs) or no fetchImpl override so Oracle can pin the connection itself`);let _=async(g,{status:P=null}={})=>{let x=await it(g,I);if(!x.ok)throw Pe(P==null?`HTTP refused ${g}: ${x.error}`:`HTTP redirect to ${g} ${x.error}`,P==null?{}:{status:P});let m=new URL(g).hostname;if(a){if(k&&(await k.close(),k=null),!k)try{k=await at({requireUndici:!0,...d?{importUndici:d}:{}})}catch(M){throw Pe(P==null?`HTTP refused ${g}: ${M?.message||M}`:`HTTP redirect to ${g} refused: ${M?.message||M}`,P==null?{}:{status:P})}k.pin(m,x.addresses),S=k.fetch}else rr(S,m,x.addresses);return x};try{let g=String(e),P={...n||{}};l&&await _(g);for(let x=0;x<=ir;x+=1){let m=await S(g,{method:r,headers:P,body:o,signal:w,redirect:"manual"});if(yn.has(m.status)){if(r!=="GET"&&r!=="HEAD"){let $=await cr(m,u??wn,{url:g,truncate:!0}),T=new Error(`HTTP ${m.status} ${r} ${g} redirected non-idempotent request`);throw T.status=m.status,T.body=lr($)??$.slice(0,300),T}if(x===ir)throw Te(m),new Error(`HTTP redirect loop for ${e}`);let U=m.headers?.get?.("location"),z;try{z=En(U,g)}catch($){throw Te(m),$}let y=!kn(z,g);if(Te(m),y&&(P=bn(P)),l)await _(z,{status:m.status});else if(y){let $=await it(z,I);if(!$.ok){let T=new Error(`HTTP redirect from ${g} ${$.error}`);throw T.status=m.status,T.retryable=!1,T}a&&$.addresses?.length&&(k||(k=await at(d?{importUndici:d}:{})),k&&(k.pin(new URL(z).hostname,$.addresses),S=k.fetch))}g=z;continue}if(typeof c=="function")try{await c(m,{url:g})}catch(U){throw Te(m),Pe(U?.message||String(U))}let M=await cr(m,u,{url:g,onOversize:()=>p.abort()}),G=lr(M);if(!m.ok){let U=new Error(`HTTP ${m.status} ${r} ${g}`);throw U.status=m.status,U.retryAfter=m.headers?.get?.("retry-after")??null,U.body=G??M.slice(0,300),U}return G??M}throw new Error(`HTTP redirect loop for ${e}`)}finally{clearTimeout(h),k&&await k.close()}}async function fr(e,t={}){let r=t.fetchImpl||globalThis.fetch;if(typeof r!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let n=t.timeoutMs??12e3,o=(t.method||"GET").toUpperCase(),s={Accept:"application/json",...t.headers||{}},i=t.body;i!=null&&typeof i!="string"&&(s["Content-Type"]=s["Content-Type"]||"application/json",i=JSON.stringify(i));let a=Number.isInteger(t.retries)?Math.max(t.retries,0):hn,l=t.lookupFn,u=!t.fetchImpl,d=t.untrustedUrl===!0,c=t.importUndici,f=t.validateResponse,p=t.signal,h=Number(t.maxResponseBytes),w=Number.isFinite(h)&&h>0?Math.floor(h):null,k=async()=>{let P;for(let x=0;x<=a;x++){p?.throwIfAborted?.();try{return await _n(e,{fetchImpl:r,method:o,headers:s,body:i,timeoutMs:n,lookupFn:l,realFetch:u,untrustedUrl:d,maxResponseBytes:w,importUndici:c,validateResponse:f,signal:p})}catch(m){P=m;let M=m?.status,G=m?.name==="AbortError"||m?.name==="TimeoutError"||p?.aborted,U=new Set([408,425,429]),z=m?.retryable===!1?!1:M!=null?U.has(M)||mn.has(M)&&or.has(o):!G&&or.has(o);if(x===a||!z)throw m;let y=Pn(x,m?.retryAfter);p?await new Promise(($,T)=>{let L=setTimeout($,y);p.addEventListener("abort",()=>{clearTimeout(L),T(p.reason||new DOMException("Aborted","AbortError"))},{once:!0})}):await Tn(y)}}throw P};if(!(t.dedupe!==!1&&!p&&An(o,i)))return k();let I=$n(o,e,s,{untrustedUrl:d,maxResponseBytes:w},i),_=ut.get(I);if(_)return _;let g=k().finally(()=>ut.delete(I));return ut.set(I,g),g}var vn="https://api.hyperliquid.xyz/info",On="https://api.hyperliquid-testnet.xyz/info";function Nn({testnet:e,baseUrl:t}={}){if(t)return t.replace(/\/$/,"").endsWith("/info")?t:`${t.replace(/\/$/,"")}/info`;if(process.env.HL_INFO_URL)return process.env.HL_INFO_URL;if(process.env.HL_API_URL){let r=process.env.HL_API_URL.replace(/\/$/,"");return r.endsWith("/info")?r:`${r}/info`}return e||process.env.HL_TESTNET==="1"?On:vn}async function Ie(e,t={}){if(!e||!e.type)throw new Error("hlInfo requires body.type");let r=Nn(t);return fr(r,{method:"POST",body:e,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs})}async function dr(e,t={}){if(!e)throw new Error("hlL2Book requires coin");return Ie({type:"l2Book",coin:String(e)},t)}async function pr(e={}){return Ie({type:"meta"},e)}async function mr(e={}){let t={type:"metaAndAssetCtxs"};return e.dex&&(t.dex=e.dex),Ie(t,e)}async function hr({coin:e,interval:t="1h",startTime:r,endTime:n},o={}){if(!e)throw new Error("hlCandleSnapshot requires coin");let s={type:"candleSnapshot",req:{coin:String(e),interval:t,startTime:r??Date.now()-24*3600*1e3,endTime:n??Date.now()}};return Ie(s,o)}async function yr({coin:e,startTime:t,endTime:r},n={}){if(!e)throw new Error("hlFundingHistory requires coin");return Ie({type:"fundingHistory",coin:String(e),startTime:t??Date.now()-24*3600*1e3,endTime:r??Date.now()},n)}function ve(e){if(!Array.isArray(e))throw new TypeError("values must be an array");for(let t=0;t<e.length;t++){let r=e[t];if(typeof r!="number"||!Number.isFinite(r))throw new TypeError(`values[${t}] must be a finite number`)}}function ce(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("period must be a positive integer")}function Mn(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");for(let t=0;t<e.length;t++){let r=e[t];if(r==null||typeof r!="object")throw new TypeError(`bars[${t}] must be an object`);for(let n of["o","h","l","c"]){let o=r[n];if(typeof o!="number"||!Number.isFinite(o))throw new TypeError(`bars[${t}].${n} must be a finite number`)}if(r.h<r.l)throw new TypeError(`bars[${t}] high must be >= low`)}}function dt(e,t){ve(e),ce(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=0;for(let o=0;o<e.length;o++)n+=e[o],o>=t&&(n-=e[o-t]),o>=t-1&&(r[o]=n/t);return r}function _e(e,t){ve(e),ce(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=0;for(let i=0;i<t;i++)n+=e[i];let o=n/t;r[t-1]=o;let s=2/(t+1);for(let i=t;i<e.length;i++)o=s*e[i]+(1-s)*o,r[i]=o;return r}function pt(e,t){ve(e),ce(t);let r=new Array(e.length).fill(null);if(e.length<=t)return r;let n=0,o=0;for(let a=1;a<=t;a++){let l=e[a]-e[a-1];l>=0?n+=l:o-=l}let s=n/t,i=o/t;r[t]=wr(s,i);for(let a=t+1;a<e.length;a++){let l=e[a]-e[a-1],u=l>0?l:0,d=l<0?-l:0;s=(s*(t-1)+u)/t,i=(i*(t-1)+d)/t,r[a]=wr(s,i)}return r}function wr(e,t){return e===0&&t===0?50:t===0?100:e===0?0:100-100/(1+e/t)}function mt(e,t={}){ve(e);let r=t.fastPeriod,n=t.slowPeriod,o=t.signalPeriod;if(ce(r),ce(n),ce(o),r>=n)throw new TypeError("fastPeriod must be < slowPeriod");let s=_e(e,r),i=_e(e,n),a=new Array(e.length).fill(null);for(let c=0;c<e.length;c++)s[c]!=null&&i[c]!=null&&(a[c]=s[c]-i[c]);let l=new Array(e.length).fill(null),u=new Array(e.length).fill(null),d=[];for(let c=0;c<a.length;c++)a[c]!=null&&d.push(c);if(d.length>=o){let c=0;for(let w=0;w<o;w++)c+=a[d[w]];let f=c/o,p=d[o-1];l[p]=f,u[p]=a[p]-f;let h=2/(o+1);for(let w=o;w<d.length;w++){let k=d[w];f=h*a[k]+(1-h)*f,l[k]=f,u[k]=a[k]-f}}return{line:a,signal:l,histogram:u}}function ht(e,t={}){ve(e);let r=t.period,n=t.stdDev;if(ce(r),typeof n!="number"||!Number.isFinite(n)||n<=0)throw new TypeError("stdDev must be a finite number > 0");let o=new Array(e.length).fill(null),s=new Array(e.length).fill(null),i=new Array(e.length).fill(null);if(e.length<r)return{upper:s,middle:o,lower:i};let a=0,l=0;for(let u=0;u<e.length;u++){let d=e[u];if(a+=d,l+=d*d,u>=r){let c=e[u-r];a-=c,l-=c*c}if(u>=r-1){let c=a/r,f=l/r-c*c;f<0&&f>-1e-12&&(f=0);let p=Math.sqrt(f);o[u]=c,s[u]=c+n*p,i[u]=c-n*p}}return{upper:s,middle:o,lower:i}}function yt(e,t){Mn(e),ce(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=new Array(e.length);for(let i=0;i<e.length;i++){let a=e[i];if(i===0)n[i]=a.h-a.l;else{let l=e[i-1].c;n[i]=Math.max(a.h-a.l,Math.abs(a.h-l),Math.abs(a.l-l))}}let o=0;for(let i=0;i<t;i++)o+=n[i];let s=o/t;r[t-1]=s;for(let i=t;i<e.length;i++)s=(s*(t-1)+n[i])/t,r[i]=s;return r}import{createHash as Rn}from"node:crypto";var wt=3,Ln="7477966facc4ef928a94e6221c8fd238eef4fcbeec46b96ae1b89178e13c2d5f",Fn="68f5b412a9975f04024cf9b9b6209b4bccedd52f176e95f34f786b3f53479c6a",jn="967fd45ecddd0d59ac0f662fe92ea813c32620ba751f249b4ace6cb6b809fb5e",gr=Rn("sha256").update(JSON.stringify({version:wt,compilerSourceHash:Ln,indicatorsSourceHash:Fn,schemaSourceHash:jn})).digest("hex");var we=wt,le=gr,Hn=Object.freeze({open:"o",high:"h",low:"l",close:"c",volume:"v",fundingRate:"fundingRate",openInterest:"openInterest",premium:"premium",oiDelta:"oiDelta",bookImbalance:"bookImbalance"}),Cn=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5});function W(e){return typeof e=="number"&&Number.isFinite(e)}function qn(e){let t=new Map(e.map(a=>[a.id,a])),r=a=>{switch(a.type){case"indicator":return a.input?[a.input]:[];case"compare":case"cross":return[a.left,a.right];case"logic":return[...a.inputs];default:return[]}},n=new Map,o=new Map;for(let a of e)n.set(a.id,0),o.set(a.id,[]);for(let a of e)for(let l of r(a))t.has(l)&&(o.get(l).push(a.id),n.set(a.id,n.get(a.id)+1));let s=[];for(let[a,l]of n)l===0&&s.push(a);let i=[];for(;s.length;){let a=s.shift();i.push(a);for(let l of o.get(a))n.set(l,n.get(l)-1),n.get(l)===0&&s.push(l)}if(i.length!==e.length)throw new Error("strategy graph is cyclic");return i}function ye(e,t){return e!=null&&typeof e=="object"&&"param"in e?t[e.param].value:e}function Un(e,t,r){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");if(!Number.isInteger(t)||t<0||t>=e.length)throw new RangeError("index out of range");let n=null;for(let o=0;o<=t;o++){let s=e[o];if(s==null||typeof s!="object"||Array.isArray(s))throw new TypeError(`bars[${o}] must be an object`);let{t:i,o:a,h:l,l:u,c:d,v:c}=s;if(!W(i)&&(typeof i=="number"&&Number.isFinite(i)),!Number.isFinite(i))throw new TypeError(`bars[${o}].t must be finite`);for(let[f,p]of[["o",a],["h",l],["l",u],["c",d],["v",c]])if(!W(p))throw new TypeError(`bars[${o}].${f} must be a finite number`);for(let[f,p]of[["o",a],["h",l],["l",u],["c",d]])if(!(p>0))throw new TypeError(`bars[${o}].${f} price must be positive`);if(c<0)throw new TypeError(`bars[${o}].v volume must be non-negative`);if(l<Math.max(a,d,u))throw new TypeError(`bars[${o}] high must be >= max(open, close, low)`);if(u>Math.min(a,d,l))throw new TypeError(`bars[${o}] low must be <= min(open, close, high)`);if(n!=null){if(!(i>n))throw new TypeError("bars t must be strictly increasing");if(i-n!==Cn[r])throw new TypeError(`bars t must match ${r} cadence`)}if(n=i,"fundingRate"in s&&s.fundingRate!=null&&!W(s.fundingRate))throw new TypeError(`bars[${o}].fundingRate must be finite when present`);if("openInterest"in s&&s.openInterest!=null){if(!W(s.openInterest))throw new TypeError(`bars[${o}].openInterest must be finite when present`);if(s.openInterest<0)throw new TypeError(`bars[${o}].openInterest must be non-negative`)}for(let f of["premium","oiDelta"])if(f in s&&s[f]!=null&&!W(s[f]))throw new TypeError(`bars[${o}].${f} must be finite when present`);if("bookImbalance"in s&&s.bookImbalance!=null){if(!W(s.bookImbalance))throw new TypeError(`bars[${o}].bookImbalance must be finite when present`);if(s.bookImbalance<-1||s.bookImbalance>1)throw new TypeError(`bars[${o}].bookImbalance must be within [-1, 1]`)}}}function de(e,t,r,n,o,s){if(s.has(e))return s.get(e);let i=t.get(e),a;switch(i.type){case"input":{let l=Hn[i.field];a=new Array(o+1);for(let u=0;u<=o;u++){let d=n[u][l];a[u]=d===void 0?null:d}break}case"constant":{let l=ye(i.value,r);a=new Array(o+1).fill(l);break}case"indicator":{let l=i.period!=null?ye(i.period,r):void 0;if(i.indicator==="atr"){let c=[];for(let f=0;f<=o;f++){let p=n[f];c.push({o:p.o,h:p.h,l:p.l,c:p.c})}a=yt(c,l);break}let d=de(i.input,t,r,n,o,s).map((c,f)=>{if(c==null||!W(c))throw new TypeError(`indicator input ${i.input} has non-finite value at ${f}`);return c});if(i.indicator==="sma")a=dt(d,l);else if(i.indicator==="ema")a=_e(d,l);else if(i.indicator==="rsi")a=pt(d,l);else if(i.indicator==="macd")a=mt(d,{fastPeriod:ye(i.fastPeriod,r),slowPeriod:ye(i.slowPeriod,r),signalPeriod:ye(i.signalPeriod,r)})[i.output];else if(i.indicator==="bollinger")a=ht(d,{period:l,stdDev:ye(i.stdDev,r)})[i.output];else throw new Error(`unsupported indicator ${i.indicator}`);break}case"compare":{let l=de(i.left,t,r,n,o,s),u=de(i.right,t,r,n,o,s);a=new Array(o+1);for(let d=0;d<=o;d++){let c=l[d],f=u[d];if(c==null||f==null||!W(c)||!W(f)){a[d]=!1;continue}switch(i.op){case"gt":a[d]=c>f;break;case"gte":a[d]=c>=f;break;case"lt":a[d]=c<f;break;case"lte":a[d]=c<=f;break;case"eq":a[d]=c===f;break;default:a[d]=!1}}break}case"logic":{let l=i.inputs.map(u=>de(u,t,r,n,o,s));a=new Array(o+1);for(let u=0;u<=o;u++)if(i.op==="not"){let d=l[0][u];a[u]=d===!0?!1:d===!1}else if(i.op==="and"){let d=!0;for(let c of l)if(c[u]!==!0){d=!1;break}a[u]=d}else if(i.op==="or"){let d=!1;for(let c of l)if(c[u]===!0){d=!0;break}a[u]=d}else a[u]=!1;break}case"cross":{let l=de(i.left,t,r,n,o,s),u=de(i.right,t,r,n,o,s);a=new Array(o+1),a[0]=!1;for(let d=1;d<=o;d++){let c=l[d-1],f=u[d-1],p=l[d],h=u[d];if(c==null||f==null||p==null||h==null||!W(c)||!W(f)||!W(p)||!W(h)){a[d]=!1;continue}i.direction==="above"?a[d]=c<=f&&p>h:a[d]=c>=f&&p<h}break}default:throw new Error(`unknown node type ${i.type}`)}return s.set(e,a),a}function K(e,t={}){let r=Y(e);t&&Object.keys(t).length&&(r=ge(r,t));let n=new Map(r.nodes.map(p=>[p.id,p])),o=Object.freeze(qn(r.nodes)),s=r.parameters,i=new Set(r.nodes.filter(p=>p.type==="input").map(p=>p.field));if(r.nodes.some(p=>p.type==="indicator"&&p.indicator==="atr"))for(let p of["open","high","low","close"])i.add(p);let a=Object.freeze([...i].sort()),l=pe(r);function u(p,h){let w={};for(let S of o){let I=p.get(S);w[S]=I[h]}let k=S=>S!=null&&w[S]===!0;return{values:w,signals:{entryLong:k(r.rules.entryLong),entryShort:k(r.rules.entryShort),exitLong:k(r.rules.exitLong),exitShort:k(r.rules.exitShort)}}}function d(p,h){Un(p,h,r.market.interval);let w=new Map;for(let k of o)de(k,n,s,p,h,w);return w}function c(p,h){return u(d(p,h),h)}function f(p){if(!Array.isArray(p)||p.length===0)throw new TypeError("bars must be a non-empty array");let h=p.length-1,w=d(p,h);return Object.freeze(p.map((k,S)=>Object.freeze(u(w,S))))}return Object.freeze({strategy:r,strategyHash:l,compilerVersion:we,compilerHash:le,requiredSeries:a,nodeOrder:o,evaluate:c,evaluateAll:f})}import{createHash as oo}from"node:crypto";import{createHash as Dn}from"node:crypto";var Bn=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:100});function zn(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function te(e){return typeof e=="number"&&Number.isFinite(e)}function gt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)gt(t);return Object.freeze(e)}for(let t of Object.keys(e))gt(e[t]);return Object.freeze(e)}function Ue(e){if(Array.isArray(e))return e.map(Ue);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Ue(e[r]);return t}return e}function bt(e,t="result"){if(typeof e=="number"){if(!Number.isFinite(e))throw new Error(`non-finite backtest result at ${t}`);return}if(!(e==null||typeof e!="object")){if(Array.isArray(e)){e.forEach((r,n)=>bt(r,`${t}[${n}]`));return}for(let[r,n]of Object.entries(e))bt(n,`${t}.${r}`)}}function Er(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");let t=null;for(let r=0;r<e.length;r++){let n=e[r];if(n==null||typeof n!="object"||Array.isArray(n))throw new TypeError(`bars[${r}] must be an object`);let{t:o,o:s,h:i,l:a,c:l,v:u}=n;if(!te(o))throw new TypeError(`bars[${r}].t must be finite`);for(let[d,c]of[["o",s],["h",i],["l",a],["c",l],["v",u]])if(!te(c))throw new TypeError(`bars[${r}].${d} must be a finite number`);for(let[d,c]of[["o",s],["h",i],["l",a],["c",l]])if(!(c>0))throw new TypeError(`bars[${r}].${d} price must be positive`);if(u<0)throw new TypeError(`bars[${r}].v volume must be non-negative`);if(i<Math.max(s,l,a))throw new TypeError(`bars[${r}] high must be >= max(open, close, low)`);if(a>Math.min(s,l,i))throw new TypeError(`bars[${r}] low must be <= min(open, close, high)`);if(t!=null&&!(o>t))throw new TypeError("bars t must be strictly increasing");if(t=o,"fundingRate"in n&&n.fundingRate!=null&&!te(n.fundingRate))throw new TypeError(`bars[${r}].fundingRate must be finite when present`);if("fundingPaymentRate"in n&&n.fundingPaymentRate!=null&&!te(n.fundingPaymentRate))throw new TypeError(`bars[${r}].fundingPaymentRate must be finite when present`);if("openInterest"in n&&n.openInterest!=null&&!te(n.openInterest))throw new TypeError(`bars[${r}].openInterest must be finite when present`)}}function Oe(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");return e.length>0&&Er(e),Dn("sha256").update(JSON.stringify(Ue(e)),"utf8").digest("hex")}function Vn(e){if(e==null&&(e={}),!zn(e))throw new TypeError("options must be a plain object");let t={...Bn},r=new Set(["initialEquityUsd","takerFeeBps","builderFeeBps","slippageBps","latencyBars","maxVolumeParticipationPct","nowMs"]);for(let n of Object.keys(e))if(!r.has(n))throw new TypeError(`unknown option "${n}"`);if("initialEquityUsd"in e){if(!te(e.initialEquityUsd)||e.initialEquityUsd<=0)throw new TypeError("initialEquityUsd must be a positive finite number");t.initialEquityUsd=e.initialEquityUsd}for(let n of["takerFeeBps","builderFeeBps","slippageBps"])if(n in e){let o=e[n];if(!te(o)||o<0)throw new TypeError(`${n} must be a finite number >= 0`);if(n==="slippageBps"?o>=1e4:o>1e4)throw new TypeError(`${n} exceeds its safe basis-point bound`);t[n]=o}if("latencyBars"in e){let n=e.latencyBars;if(!Number.isInteger(n)||n<1)throw new TypeError("latencyBars must be an integer >= 1");t.latencyBars=n}if("maxVolumeParticipationPct"in e){let n=e.maxVolumeParticipationPct;if(!te(n)||n<=0||n>100)throw new TypeError("maxVolumeParticipationPct must be in (0,100]");t.maxVolumeParticipationPct=n}if("nowMs"in e){if(!Number.isInteger(e.nowMs))throw new TypeError("nowMs must be an integer epoch milliseconds");t.nowMs=e.nowMs}return t}function De(e){return e/1e4}function Jn(e,t,r){let n=De(r);return t==="long"?e*(1+n):e*(1-n)}function Kn(e,t,r){let n=De(r);return t==="long"?e*(1-n):e*(1+n)}function br(e,t,r){let n=Math.abs(e)*De(t),o=Math.abs(e)*De(r);return{taker:n,builder:o,total:n+o}}function Yn(e,t){let r=e*(t.positionSizePct/100)*t.maxLeverage;return Math.min(r,t.maxNotionalUsd)}function Gn(e,t,r){let n=r/100;return t==="long"?e*(1-n):e*(1+n)}function Wn(e,t,r){let n=r/100;return t==="long"?e*(1+n):e*(1-n)}function Xn(e,t,r,n){if(!(r>0))return t==="long"?0:Number.POSITIVE_INFINITY;let o=Math.min(.99,1/(2*r)+n/1e4);return t==="long"?e*(1-1/r)/(1-o):e*(1+1/r)/(1+o)}function Zn(e,t,r){return t==="long"?e.l<=r:e.h>=r}function Qn(e,t,r){return t==="long"?e.h>=r:e.l<=r}function eo(e,t,r){return t==="long"?e.l<=r:e.h>=r}var to=Object.freeze(["fundingRate","openInterest","premium","oiDelta","bookImbalance"]);function Ne(e,t){for(let r of e.requiredSeries)if(to.includes(r)&&!t.every(n=>te(n?.[r])))throw new Error(`strategy required series is absent: ${r}`)}function ro(e){if(e.length<3)return 0;let t=[];for(let i=1;i<e.length;i++){let a=e[i-1].equity,l=e[i].equity;a>0&&t.push((l-a)/a)}if(t.length<2)return 0;let r=0;for(let i of t)r+=i;let n=r/t.length,o=0;for(let i of t)o+=(i-n)**2;let s=Math.sqrt(o/(t.length-1));return s>0?n/s:0}function no(e){let t=-1/0,r=0;for(let n of e){let o=n.equity;if(o>t&&(t=o),t>0){let s=(t-o)/t*100;s>r&&(r=s)}}return r}function ie(e,t,r={}){let n=Vn(r);Er(t);let o=Oe(t);n.nowMs!==void 0&&Y(e,{nowMs:n.nowMs});let s=K(e);if(Ne(s,t),n.nowMs!==void 0&&s.strategy.risk.expiresAt<=n.nowMs)throw new Error("strategy is expired: risk.expiresAt must be strictly greater than nowMs");let i=s.strategy.risk,a=s.evaluateAll(t),l=n.latencyBars,u=n.slippageBps,d=n.takerFeeBps,c=n.builderFeeBps,f=n.initialEquityUsd,p=0,h=0,w=0,k=0,S=0,I=[],_=[],g=[],P=[],x=[],m=null,M=0,G=null,U=f,z=!1,y=0,$=0,T=[],L=new Array(t.length).fill(0);function j(E){T.push(E)}function O(E){let v=t[E].v*(n.maxVolumeParticipationPct/100);return Math.max(0,v-L[E])}function R(E){if(!m)return f;let v=m.side==="long"?(E-m.entryPrice)*m.qty:(m.entryPrice-E)*m.qty;return f+v}function J(E,v,A){let H=A.o,N=Yn(f,i);if(!(N>0)||!(H>0))return;let C=Jn(H,v,u),F=N/C,B=O(E),Ae=C*B;if(F>B){g.push({kind:"entry",barIndex:E,time:A.t,side:v,requestedNotionalUsd:N,maxFillNotionalUsd:Ae,reason:"volume_participation"});return}L[E]+=F;let ee=Math.abs(C-H)*F,se=br(N,d,c);f-=se.total,p+=se.taker,h+=se.builder,k+=ee,S+=N,m={lifecycleEpoch:++$,side:v,entryBarIndex:E,entryReferencePrice:H,entryPrice:C,qty:F,notionalUsd:N,stop:Gn(C,v,i.stopLossPct),take:Wn(C,v,i.takeProfitPct),liq:Xn(C,v,i.maxLeverage,d+c),entryFees:se.taker,entryBuilderFees:se.builder,entrySlippageUsd:ee,fundingAccrued:0}}function D(E,v,A,H){if(!m)return!1;let N=m.side,C=v,F=C;A!=="liquidation"&&H&&(F=Kn(C,N,u));let B=m.qty,Ae=B*F;if(A!=="liquidation"){let tr=O(E),ln=F*tr;if(B>tr)return g.push({kind:"exit",barIndex:E,time:t[E].t,side:N,requestedNotionalUsd:Ae,maxFillNotionalUsd:ln,reason:"volume_participation",triggerReason:A}),!1;L[E]+=B}let ee=br(Ae,d,c),se=A==="liquidation"?0:Math.abs(F-C)*B,$e,nt;N==="long"?($e=(C-m.entryReferencePrice)*B,nt=(F-m.entryPrice)*B):($e=(m.entryReferencePrice-C)*B,nt=(m.entryPrice-F)*B),f+=nt,f-=ee.total,p+=ee.taker,h+=ee.builder,k+=se,S+=Ae;let cn={side:N,entryBarIndex:m.entryBarIndex,entryTime:t[m.entryBarIndex].t,entryPrice:m.entryPrice,exitBarIndex:E,exitTime:t[E].t,exitPrice:F,exitReason:A,qty:B,notionalUsd:m.notionalUsd,grossPnlUsd:$e,feesUsd:m.entryFees+ee.taker,builderFeesUsd:m.entryBuilderFees+ee.builder,fundingUsd:m.fundingAccrued,slippageUsd:m.entrySlippageUsd+se,netPnlUsd:$e-(m.entryFees+ee.taker+m.entryBuilderFees+ee.builder)-m.fundingAccrued-(m.entrySlippageUsd+se)};return I.push(cn),A==="liquidation"&&_.push({barIndex:E,time:t[E].t,side:N,price:F,tradeIndex:I.length-1}),m=null,$+=1,y=E+1+(i.cooldownBars||0),!0}function Q(E,v,A,H){let N=E+1;if(N>=t.length)return;T.some(F=>F.kind==="exit"&&F.side===v&&F.fillBar===N&&F.epoch===H)||j({kind:"exit",side:v,signalBar:E,fillBar:N,reason:A,epoch:H})}function je(E){let v=T.filter(A=>A.fillBar===E);for(let A=T.length-1;A>=0;A--)T[A].fillBar===E&&T.splice(A,1);v.sort((A,H)=>{let N=C=>C.kind==="exit"?0:1;return N(A)-N(H)});for(let A of v)if(A.kind==="exit"){if(!m||m.side!==A.side||m.lifecycleEpoch!==A.epoch)continue;let H=A.reason||"rule";D(E,t[E].o,H,!0)||Q(E,A.side,H,A.epoch)}else if(A.kind==="entry"){if(m||A.epoch!==$||E<y)continue;J(E,A.side,t[E])}}function He(E){if(!m)return;let v=t[E],A=v.fundingPaymentRate;if(A==null||!te(A)||A===0)return;let H=Math.abs(m.qty*v.c),N=A*H;m.side==="long"?(f-=N,m.fundingAccrued+=N,w+=N):(f+=N,m.fundingAccrued-=N,w-=N)}function Ce(E){if(!m)return;let v=t[E].o;(m.side==="long"?v<=m.liq:v>=m.liq)&&D(E,v,"liquidation",!1)}function Wt(E){if(!m)return;let v=t[E],A=m.side,H=eo(v,A,m.liq),N=Zn(v,A,m.stop),C=Qn(v,A,m.take),F=B=>A==="long"?Math.min(B,v.o):Math.max(B,v.o);if(H){D(E,F(m.liq),"liquidation",!1);return}if(N&&C){D(E,F(m.stop),"stop_loss",!0)||Q(E,A,"stop_loss",m.lifecycleEpoch);return}if(N){D(E,F(m.stop),"stop_loss",!0)||Q(E,A,"stop_loss",m.lifecycleEpoch);return}C&&(D(E,m.take,"take_profit",!0)||Q(E,A,"take_profit",m.lifecycleEpoch))}for(let E=0;E<t.length;E++){let v=Math.floor(t[E].t/864e5);v!==G&&(G=v,U=R(t[E].o),z=!1),Ce(E),je(E),Wt(E),He(E),!z&&R(t[E].c)<=U*(1-i.maxDailyLossPct/100)&&(z=!0,P.push({type:"daily_loss_limit",barIndex:E,time:t[E].t,message:"daily loss limit reached; new entries blocked for UTC day"}));let A=a[E].signals,H=E+l;if(m)(m.side==="long"&&A.exitLong===!0||m.side==="short"&&A.exitShort===!0)&&H<t.length&&(T.some(B=>B.kind==="exit"&&B.side===m.side&&B.fillBar===H&&B.epoch===m.lifecycleEpoch)||j({kind:"exit",side:m.side,signalBar:E,fillBar:H,reason:"rule",epoch:m.lifecycleEpoch}));else{let C=A.entryLong===!0,F=A.entryShort===!0;C&&F?P.push({type:"conflicting_entry_signals",barIndex:E,time:t[E].t,message:"conflicting entry signals; no position opened"}):!z&&(C||F)&&H<t.length&&E>=y&&j({kind:"entry",side:C?"long":"short",signalBar:E,fillBar:H,epoch:$})}let N=f;m&&(M+=1,N=R(t[E].c)),x.push({barIndex:E,time:t[E].t,equity:N,positionSide:m?m.side:null})}let Xt=null;if(m){let E=t.length-1;if(D(E,t[E].c,"end_of_data",!0))x[E]={barIndex:E,time:t[E].t,equity:f,positionSide:null};else{let A=R(t[E].c);Xt={side:m.side,entryBarIndex:m.entryBarIndex,entryTime:t[m.entryBarIndex].t,entryPrice:m.entryPrice,qty:m.qty,notionalUsd:m.notionalUsd,markPrice:t[E].c,markedEquityUsd:A},P.push({type:"open_position_at_end",barIndex:E,time:t[E].t,message:"end-of-data exit missed; position remains open and marked"})}}let Zt=(m?R(t[t.length-1].c):f)-n.initialEquityUsd,nn=Zt/n.initialEquityUsd*100,Qt=0,Qe=0,et=0;for(let E of I)E.netPnlUsd>0?(Qt+=1,Qe+=E.netPnlUsd):E.netPnlUsd<0&&(et+=-E.netPnlUsd);let tt=I.length,on=tt===0?0:Qt/tt,rt=0;et>0?rt=Qe/et:Qe>0&&(rt=1e12);let sn={netPnlUsd:Zt,netPnlPct:nn,maxDrawdownPct:no(x),winRate:on,profitFactor:rt,tradeCount:tt,sharpe:ro(x),turnoverUsd:S,exposurePct:M/t.length*100},an={initialEquityUsd:n.initialEquityUsd,takerFeeBps:n.takerFeeBps,builderFeeBps:n.builderFeeBps,slippageBps:n.slippageBps,latencyBars:n.latencyBars,maxVolumeParticipationPct:n.maxVolumeParticipationPct},er={barsHash:o,strategyHash:s.strategyHash,compilerHash:le,compilerVersion:we,config:an,trades:I,equityCurve:x,metrics:sn,costs:{feesUsd:p,builderFeesUsd:h,fundingUsd:w,slippageUsd:k},liquidations:_,missedFills:g,openPositionAtEnd:Xt,flags:P};return bt(er),gt(Ue(er))}var Sr=Object.freeze(["fail","pass_paper_only","pass_live_eligible"]);function re(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function be(e){return typeof e=="number"&&Number.isFinite(e)}function xt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)xt(t);return Object.freeze(e)}for(let t of Object.keys(e))xt(e[t]);return Object.freeze(e)}function me(e){if(Array.isArray(e))return e.map(me);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=me(e[r]);return t}return e}function Et(e){return{netPnlUsd:e.metrics.netPnlUsd,netPnlPct:e.metrics.netPnlPct,maxDrawdownPct:e.metrics.maxDrawdownPct,winRate:e.metrics.winRate,profitFactor:e.metrics.profitFactor,tradeCount:e.metrics.tradeCount,sharpe:e.metrics.sharpe,turnoverUsd:e.metrics.turnoverUsd,exposurePct:e.metrics.exposurePct}}function kr(e){return{feesUsd:e.costs.feesUsd,builderFeesUsd:e.costs.builderFeesUsd,fundingUsd:e.costs.fundingUsd,slippageUsd:e.costs.slippageUsd}}function so(e){return(e.feesUsd||0)+(e.builderFeesUsd||0)+Math.max(0,e.fundingUsd||0)+(e.slippageUsd||0)}function io(e){let t=0;for(let r of e.trades)r.grossPnlUsd>0&&(t+=r.grossPnlUsd);return t}function ao(e,t,r){return!(!e||e.tradeCount<Math.max(1,Math.min(r,3))||!(e.netPnlUsd>0)||!(e.profitFactor>1)||!(e.maxDrawdownPct<=t.maxDailyLossPct))}function Ar(e){if(!re(e))throw new TypeError("evidence artifact must be a plain object");if(!Sr.includes(e.status))throw new TypeError("evidence artifact status is invalid");for(let t of["strategyHash","compilerHash","barsHash"])if(typeof e[t]!="string"||!/^[0-9a-f]{64}$/.test(e[t]))throw new TypeError(`evidence artifact ${t} must be a sha256 hash`);if(!re(e.split))throw new TypeError("evidence artifact split required");if(!Array.isArray(e.flags))throw new TypeError("evidence artifact flags must be an array");if(!re(e.walkForward)||!Array.isArray(e.walkForward.windows))throw new TypeError("evidence artifact walkForward windows required");if(e.status==="pass_live_eligible"&&(!re(e.train)||!re(e.holdout)))throw new TypeError("live-eligible evidence artifact requires train and holdout facts");return me({barsHash:e.barsHash,compilerHash:e.compilerHash,flags:e.flags.map(t=>me(t)),holdout:e.holdout??null,split:e.split,status:e.status,strategyHash:e.strategyHash,train:e.train??null,walkForward:{passRate:e.walkForward.passRate,windowsRun:e.walkForward.windowsRun??e.walkForward.windows.length,windows:e.walkForward.windows.map(t=>({index:t.index,trainStartIndex:t.trainStartIndex,trainEndIndex:t.trainEndIndex,passed:t.passed,reason:t.reason,evalStartIndex:t.evalStartIndex,evalEndIndex:t.evalEndIndex,metrics:t.metrics}))}})}function St(e){return oo("sha256").update(JSON.stringify(Ar(e)),"utf8").digest("hex")}function Z(e,t,r=0){if(!Number.isInteger(e)||e<r)throw new Error(`${t} must be an integer >= ${r}`);return e}function kt(e,t){if(!re(e)||!re(e.metrics))throw new Error(`${t} metrics required`);let r=Z(e.tradeCount,`${t}.tradeCount`);if(e.metrics.tradeCount!==r)throw new Error(`${t} tradeCount contradicts metrics.tradeCount`);for(let n of["netPnlUsd","profitFactor","maxDrawdownPct"])if(!be(e.metrics[n]))throw new Error(`${t}.metrics.${n} must be finite`);if(e.metrics.maxDrawdownPct<0)throw new Error(`${t}.metrics.maxDrawdownPct must be >= 0`);return e.metrics}function co(e,{maxDailyLossPct:t}={}){let r=e.split,n=Z(r.trainStartIndex,"split.trainStartIndex"),o=Z(r.trainEndIndex,"split.trainEndIndex"),s=Z(r.trainBarCount,"split.trainBarCount",1),i=Z(r.holdoutStartIndex,"split.holdoutStartIndex"),a=Z(r.holdoutEndIndex,"split.holdoutEndIndex"),l=Z(r.holdoutBarCount,"split.holdoutBarCount",1);if(n!==0||o-n+1!==s||i!==o+1||a-i+1!==l)throw new Error("evidence split must be contiguous, chronological, and count-consistent");if(!be(r.trainFraction)||r.trainFraction<=0||r.trainFraction>=1)throw new Error("split.trainFraction must be in (0,1)");kt(e.train,"train");let u=kt(e.holdout,"holdout");if(u.tradeCount<1||u.netPnlUsd<=0||u.profitFactor<=1)throw new Error("live-eligible holdout metrics do not pass");if(be(t)&&u.maxDrawdownPct>t)throw new Error("live-eligible holdout drawdown exceeds strategy risk");if(e.flags.length>0)throw new Error("live-eligible evidence cannot contain failure flags");let d=e.walkForward,c=d.windows;if(c.length<1||d.windowsRun!==c.length)throw new Error("live-eligible walk-forward windowsRun must match nonempty windows");let f=0,p=-1;for(let w=0;w<c.length;w++){let k=c[w];if(!re(k)||k.index!==w||typeof k.passed!="boolean")throw new Error("walk-forward windows must be ordered and structurally valid");let S=Z(k.trainStartIndex,`walkForward.windows[${w}].trainStartIndex`),I=Z(k.trainEndIndex,`walkForward.windows[${w}].trainEndIndex`),_=Z(k.evalStartIndex,`walkForward.windows[${w}].evalStartIndex`),g=Z(k.evalEndIndex,`walkForward.windows[${w}].evalEndIndex`);if(S!==0||I>=_||_>g||_<=p)throw new Error("walk-forward windows must be chronological and disjoint");if(p=g,k.passed){if(f+=1,k.reason!=="pass")throw new Error("passed walk-forward window reason must be pass");let P=kt({metrics:k.metrics,tradeCount:k.metrics?.tradeCount},`walkForward.windows[${w}]`);if(P.tradeCount<1||P.netPnlUsd<=0||P.profitFactor<=1)throw new Error("passed walk-forward window metrics do not pass");if(be(t)&&P.maxDrawdownPct>t)throw new Error("passed walk-forward drawdown exceeds strategy risk")}else if(k.reason==="pass")throw new Error("failed walk-forward window cannot have pass reason")}let h=f/c.length;if(!be(d.passRate)||Math.abs(d.passRate-h)>Number.EPSILON||h<.6)throw new Error("walk-forward passRate contradicts concrete windows or is below live threshold")}function At(e,t={}){if(typeof e?.id!="string"||!/^[0-9a-f]{64}$/.test(e.id))throw new Error("evidence.id must be a sha256 evidence artifact hash");let r=Ar(e),n=me({id:e.id,...r});if(JSON.stringify(me(e))!==JSON.stringify(n))throw new Error("evidence artifact contains fields unbound from its deterministic identity");let o=St(e);if(e.id!==o)throw new Error("evidence.id does not match its deterministic artifact facts digest");return e.status==="pass_live_eligible"&&co(e,t),e}function Be({strategy:e,bars:t,backtestOptions:r={},trainFraction:n=.7,walkForwardWindows:o=3,minTrades:s=10}={}){let i=[];if(!re(e))throw new TypeError("strategy must be a plain object");if(!Array.isArray(t))throw new TypeError("bars must be an array");if(!re(r))throw new TypeError("backtestOptions must be a plain object");if(!be(n)||n<=0||n>=1)throw new TypeError("trainFraction must be in (0,1)");if(!Number.isInteger(o)||o<1)throw new TypeError("walkForwardWindows must be a positive integer");if(!Number.isInteger(s)||s<0)throw new TypeError("minTrades must be an integer >= 0");let a=Y(e),l=pe(a),u=Oe(t),d=t.length,c=(O=[],R={})=>xr({status:"fail",strategy:a,sHash:l,barsHash:u,split:R.split||{trainStartIndex:0,trainEndIndex:-1,trainBarCount:0,holdoutStartIndex:0,holdoutEndIndex:-1,holdoutBarCount:0,trainFraction:n},train:R.train||null,holdout:R.holdout||null,walkForward:R.walkForward||{windows:[],passRate:0},flags:[...i,...O]});if(d<10)return c([{type:"insufficient_bars",message:"need at least 10 bars for evidence"}]);let f=Math.floor(d*n),p=f,h=d-p;if(f<5||h<3)return c([{type:"invalid_windowing",message:"train/holdout split too small",trainCount:f,holdoutCount:h}]);let w=t.slice(0,f),k=t.slice(p),S,I;try{S=ie(a,w,r),I=ie(a,k,r)}catch(O){return c([{type:"backtest_error",message:String(O.message||O)}])}let _={metrics:Et(S),costs:kr(S),tradeCount:S.metrics.tradeCount},g={metrics:Et(I),costs:kr(I),tradeCount:I.metrics.tradeCount},P={trainStartIndex:0,trainEndIndex:f-1,trainBarCount:f,holdoutStartIndex:p,holdoutEndIndex:d-1,holdoutBarCount:h,trainFraction:n},x=[],m=Math.floor(d/(o+1));if(m<3)i.push({type:"invalid_windowing",message:"walk-forward window size too small",wfSize:m});else for(let O=0;O<o;O++){let R=m*(O+1),J=R,D=Math.min(d,J+m);if(D-J<3||R<3){x.push({index:O,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:J,evalEndIndex:D-1,passed:!1,reason:"window_too_small",metrics:null});continue}let Q=t.slice(J,D),je;try{je=ie(a,Q,r)}catch{x.push({index:O,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:J,evalEndIndex:D-1,passed:!1,reason:"backtest_error",metrics:null});continue}let He=Et(je),Ce=ao(He,a.risk,s);x.push({index:O,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:J,evalEndIndex:D-1,passed:Ce,reason:Ce?"pass":"fail_metrics",metrics:He})}let M=x.filter(O=>O.passed).length,G=x.length===0?0:M/x.length,U={windows:x,passRate:G,windowsRun:x.length};g.metrics.tradeCount===0&&_.metrics.tradeCount===0&&i.push({type:"no_trades",message:"no trades in train or holdout"}),g.metrics.tradeCount===0&&i.push({type:"absent_oos_trades",message:"holdout produced no trades"}),g.metrics.netPnlUsd<0&&i.push({type:"holdout_loss",message:"holdout netPnlUsd is negative"}),_.metrics.netPnlUsd>0&&g.metrics.netPnlUsd<0&&_.metrics.netPnlUsd>Math.abs(g.metrics.netPnlUsd)*.25?i.push({type:"overfit",message:"profitable train with losing holdout (OOS collapse)"}):_.metrics.netPnlUsd>0&&g.metrics.netPnlUsd>0&&g.metrics.netPnlUsd<_.metrics.netPnlUsd*.1&&_.metrics.tradeCount>=s&&i.push({type:"severe_oos_collapse",message:"holdout pnl collapsed vs train"});let z=so(g.costs),y=io(I);y>0&&z>y&&i.push({type:"costs_exceed_gross",message:"holdout costs exceed gross gains"});let $=i.some(O=>["insufficient_bars","invalid_windowing","absent_oos_trades","holdout_loss","no_trades","severe_oos_collapse","backtest_error"].includes(O.type)),T=i.some(O=>O.type==="overfit"),L="fail";return g.metrics.tradeCount>=s&&g.metrics.netPnlUsd>0&&g.metrics.profitFactor>1&&g.metrics.maxDrawdownPct<=a.risk.maxDailyLossPct&&G>=.6&&!(y>0&&z>y)&&!T&&!i.some(O=>O.type==="severe_oos_collapse"||O.type==="invalid_windowing")?L="pass_live_eligible":!$&&g.metrics.tradeCount>0&&_.metrics.tradeCount>0&&Number.isFinite(g.metrics.netPnlUsd)?(L="pass_paper_only",g.metrics.tradeCount<s&&i.push({type:"undersampled",message:"holdout trades below minTrades"})):T&&g.metrics.tradeCount>0&&_.metrics.netPnlUsd>0?L="fail":g.metrics.tradeCount>0&&_.metrics.tradeCount>0&&!$?L="pass_paper_only":L="fail",g.metrics.netPnlUsd<0&&(L=L==="pass_live_eligible"?"fail":L==="pass_paper_only"?"pass_paper_only":"fail",L="fail"),xr({status:L,strategy:a,sHash:l,barsHash:u,split:P,train:_,holdout:g,walkForward:U,flags:i})}function xr({status:e,strategy:t,sHash:r,barsHash:n,split:o,train:s,holdout:i,walkForward:a,flags:l}){let u={status:e,strategyHash:r,compilerHash:le,barsHash:n,split:o,train:s,holdout:i,walkForward:a,flags:l};return u.id=St(u),xt(me(JSON.parse(JSON.stringify(u))))}import{createHash as lo,createHmac as uo,timingSafeEqual as hi}from"node:crypto";var fo=2,po=300*1e3,mo=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})();function $t(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map($t).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${$t(e[r])}`).join(",")}}`}function $r(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function Pr(e=process.env){return $r(process.env)||$r(e)}function ho(e){let{prepareHash:t,prepareMac:r,note:n,...o}=e||{};return o}function yo(e){let t=ho(e);return lo("sha256").update($t(t)).digest("hex")}function wo(e,t=Pr()){return t?uo("sha256",t).update(String(e)).digest("hex"):""}function Tr(e,{provider:t,kind:r,env:n=process.env,nowMs:o=Date.now(),expiresAtMs:s}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let i=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(i&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let a={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1,oraclePrepared:i?e.oraclePrepared:!0};if(!a.provider)throw new Error("stampPrepared: provider required");if(!a.kind)throw new Error("stampPrepared: kind required");let l=Number(o),u=s==null?l+po:Number(s),d=u-l;if(!Number.isSafeInteger(l)||!Number.isSafeInteger(u)||d<=0||d>mo)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let f={...a,preparedAt:l,expiresAt:u,prepareVersion:fo},p=yo(f),h=Pr(n),w=h?wo(p,h):void 0,k={...f,prepareHash:p};return w&&(k.prepareMac=w),k}var go=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Me(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function bo(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Tt(e,t="value"){if(Array.isArray(e)){e.forEach((r,n)=>Tt(r,`${t}[${n}]`));return}if(Me(e))for(let[r,n]of Object.entries(e)){let o=bo(r);if(go.some(s=>o.includes(s)))throw new Error(`handoff: forbidden secret-like field at ${t}.${r}`);Tt(n,`${t}.${r}`)}}function Pt(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function It({strategy:e,evidence:t,shadow:r,caps:n,nowMs:o=Date.now(),env:s=process.env}={}){if(Tt({strategy:e,evidence:t,shadow:r,caps:n},"handoff"),!Me(e))throw new Error("handoff: strategy required");if(!Me(t))throw new Error("handoff: evidence required");if(!Me(r))throw new Error("handoff: shadow required");if(!Me(n))throw new Error("handoff: caps required");if(typeof r.id!="string"||!r.id.trim())throw new Error("handoff: shadow.id required");if(typeof r.stateHash!="string"||!/^[0-9a-f]{64}$/.test(r.stateHash))throw new Error("handoff: shadow.stateHash must be a sha256 hash");if(r.status!=="running")throw new Error("handoff: shadow.status must be running");if(!Number.isInteger(r.cursor)||r.cursor<=0)throw new Error("handoff: shadow.cursor must be a positive integer");if(!Number.isInteger(r.updatedAt)||r.updatedAt<=0||r.updatedAt>o)throw new Error("handoff: shadow.updatedAt must be a positive integer <= nowMs");let i=Y(e,{nowMs:o}),a=K(i);if(At(t,{maxDailyLossPct:i.risk.maxDailyLossPct}),t.status!=="pass_live_eligible")throw new Error("handoff: evidence.status must be pass_live_eligible");if(t.strategyHash!==a.strategyHash)throw new Error("handoff: evidence.strategyHash mismatch");if(t.compilerHash!==a.compilerHash)throw new Error("handoff: evidence.compilerHash mismatch");let l=["perStrategyNotionalUsd","maxLeverage","dailyLossCapUsd","chainAllowlist","assetAllowlist","expiresAt","killSwitchRequired"];for(let f of l)if(!(f in n)||n[f]==null)throw new Error(`handoff: caps.${f} required`);if(!Pt(n.perStrategyNotionalUsd))throw new Error("handoff: caps.perStrategyNotionalUsd must be positive");if(n.perStrategyNotionalUsd>a.strategy.risk.maxNotionalUsd)throw new Error("handoff: caps.perStrategyNotionalUsd exceeds strategy.risk.maxNotionalUsd");if(!Pt(n.maxLeverage))throw new Error("handoff: caps.maxLeverage must be positive");if(n.maxLeverage>a.strategy.risk.maxLeverage)throw new Error("handoff: caps.maxLeverage exceeds strategy.risk.maxLeverage");if(!Pt(n.dailyLossCapUsd))throw new Error("handoff: caps.dailyLossCapUsd must be positive");let u=a.strategy.risk.maxNotionalUsd*(a.strategy.risk.maxDailyLossPct/100);if(n.dailyLossCapUsd>u)throw new Error("handoff: caps.dailyLossCapUsd exceeds strategy daily loss ceiling");if(!Array.isArray(n.chainAllowlist)||n.chainAllowlist.length===0)throw new Error("handoff: caps.chainAllowlist must be a non-empty array");if(!n.chainAllowlist.every(f=>f==="hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include only hyperliquid");if(!n.chainAllowlist.includes("hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include hyperliquid");if(!Array.isArray(n.assetAllowlist)||n.assetAllowlist.length===0)throw new Error("handoff: caps.assetAllowlist must be a non-empty array");if(n.assetAllowlist.length!==1||n.assetAllowlist[0]!==a.strategy.market.coin)throw new Error("handoff: caps.assetAllowlist must contain only the strategy market coin");if(!Number.isInteger(n.expiresAt)||!(n.expiresAt>o))throw new Error("handoff: caps.expiresAt must be an integer > nowMs");if(n.expiresAt>a.strategy.risk.expiresAt)throw new Error("handoff: caps.expiresAt exceeds strategy.risk.expiresAt");if(n.killSwitchRequired!==!0)throw new Error("handoff: caps.killSwitchRequired must be exactly true");let d={perStrategyNotionalUsd:n.perStrategyNotionalUsd,maxLeverage:n.maxLeverage,dailyLossCapUsd:n.dailyLossCapUsd,chainAllowlist:[...n.chainAllowlist],assetAllowlist:[...n.assetAllowlist],expiresAt:n.expiresAt,killSwitchRequired:!0},c={strategyHash:a.strategyHash,compilerHash:a.compilerHash,evidence:JSON.parse(JSON.stringify(t)),shadow:{id:r.id,stateHash:r.stateHash,status:r.status,cursor:r.cursor,updatedAt:r.updatedAt},compiled:{strategyHash:a.strategyHash,compilerHash:a.compilerHash,compilerVersion:we,venue:"hyperliquid",market:{coin:a.strategy.market.coin,kind:"perp",interval:a.strategy.market.interval},risk:{...a.strategy.risk},strategy:JSON.parse(JSON.stringify(a.strategy))},arming:{liveBroadcast:!1,requiresExplicitUserArm:!0,caps:d},requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,executionReady:!1};return Tr(c,{provider:"hl-strategy",kind:"strategy-live-handoff",env:s})}var Eo=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5});function Ee(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function ke(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be a non-negative safe integer`);return e}function Re(e){if(Array.isArray(e))for(let t of e)Re(t);else if(e&&typeof e=="object")for(let t of Object.values(e))Re(t);return Object.freeze(e)}function Ir(e){let t=Eo[e];if(!t)throw new TypeError(`unsupported strategy interval: ${e}`);return t}function _r(e,{endTime:t=Number.MAX_SAFE_INTEGER}={}){if(!Array.isArray(e))throw new TypeError("Hyperliquid candles must be an array");ke(t,"endTime");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`candles[${n}] must be an object`);let s=ke(Number(o.t),`candles[${n}].t`);if(ke(Number(o.T),`candles[${n}].T`)>t)continue;let a={t:s,o:Ee(o.o,`candles[${n}].o`),h:Ee(o.h,`candles[${n}].h`),l:Ee(o.l,`candles[${n}].l`),c:Ee(o.c,`candles[${n}].c`),v:Ee(o.v,`candles[${n}].v`)};if(a.h<Math.max(a.o,a.c,a.l))throw new TypeError(`candles[${n}].h is below another price`);if(a.l>Math.min(a.o,a.c,a.h))throw new TypeError(`candles[${n}].l is above another price`);if(a.v<0)throw new TypeError(`candles[${n}].v must be non-negative`);let l=r.get(s);if(l&&JSON.stringify(l)!==JSON.stringify(a))throw new TypeError(`conflicting duplicate candle at timestamp ${s}`);l||r.set(s,a)}return Re([...r.values()].sort((n,o)=>n.t-o.t))}function ko(e,t){if(!Array.isArray(e))throw new TypeError("Hyperliquid funding history must be an array");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`funding[${n}] must be an object`);let s=ke(Number(o.time),`funding[${n}].time`);s>t||r.set(s,{time:s,fundingRate:Ee(o.fundingRate,`funding[${n}].fundingRate`)})}return[...r.values()].sort((n,o)=>n.time-o.time)}async function xo({coin:e,startTime:t,endTime:r},n){let o=[],s=Math.max(0,t-288e5),i=!1;for(let a=0;a<16&&s<=r;a++){let l=await yr({coin:e,startTime:s,endTime:r},n);if(!Array.isArray(l))throw new TypeError("Hyperliquid funding history must be an array");o.push(...l);let u=s;for(let d of l){let c=Number(d?.time);Number.isSafeInteger(c)&&c>u&&(u=c)}if(l.length<500||u>=r){i=!0;break}if(u<=s)throw new Error("Hyperliquid funding history pagination did not advance");s=u+1}if(!i)throw new Error("strategy history exceeds the bounded funding history limit");return ko(o,r)}function So(e,t,r){let n=0,o=null;return e.map(s=>{let i=s.t+r,a=0;for(;n<t.length&&t[n].time<i;){let l=t[n];o=l.fundingRate,l.time>=s.t&&(a+=l.fundingRate),n+=1}return o==null?{...s,fundingPaymentRate:a}:{...s,fundingRate:o,fundingPaymentRate:a}})}async function _t(e,t={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("strategy history input must be an object");let r=String(e.coin||"").trim().toUpperCase();if(!/^[A-Z0-9][A-Z0-9._-]{0,11}$/.test(r))throw new TypeError("coin must be an uppercase Hyperliquid asset id");let n=String(e.interval||"15m"),o=Ir(n);if(e.endTime==null)throw new TypeError("endTime is required for deterministic history");let s=ke(e.endTime,"endTime"),i=e.count==null?1500:e.count;if(!Number.isInteger(i)||i<20||i>5e3)throw new TypeError("count must be an integer from 20 to 5000");let a=e.startTime==null?Math.max(0,s-i*o):ke(e.startTime,"startTime");if(a>=s)throw new TypeError("startTime must be before endTime");let[l,u]=await Promise.all([hr({coin:r,interval:n,startTime:a,endTime:s},t),xo({coin:r,startTime:a,endTime:s},t)]),d=_r(l,{endTime:s}),c=Re(So(d,u,o));return Re({coin:r,interval:n,range:{startTime:a,endTime:s},bars:c})}var Ao=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),$o=new Set(["coin","interval"]);function Po(e){let t=[];if(!e||typeof e!="object"||Array.isArray(e))return{ok:!1,errors:[{path:"market",message:"must be a plain object"}],market:null};for(let r of Object.keys(e))$o.has(r)||t.push({path:`market.${r}`,message:"unknown field is not allowed"});return(typeof e.coin!="string"||e.coin.length===0||e.coin.length>32)&&t.push({path:"market.coin",message:"must be a non-empty string max 32"}),(typeof e.interval!="string"||!Ao.has(e.interval))&&t.push({path:"market.interval",message:"must be a supported interval"}),t.length?{ok:!1,errors:t,market:null}:{ok:!0,errors:[],market:{coin:e.coin,interval:e.interval}}}async function To(e={}){let t=await pr(e);if(!t||!Array.isArray(t.universe))throw new TypeError("Hyperliquid market metadata must contain universe");return Object.freeze(t.universe.map((r,n)=>{if(!r||typeof r.name!="string"||!r.name)throw new TypeError(`Hyperliquid market metadata universe[${n}].name is invalid`);return r.name}))}var vr=Object.freeze({id:"hyperliquid",validateMarket:Po,fetchBars:_t,listMarkets:To,prepareIntent(e){return It(e)}});var Io=Object.freeze(["id","validateMarket","prepareIntent"]);function _o(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("strategy venue adapter must be an object");if(typeof e.id!="string"||!/^[a-z0-9][a-z0-9._-]{0,63}$/.test(e.id))throw new TypeError("strategy venue adapter id is malformed");for(let t of Io.slice(1))if(typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} requires ${t}()`);for(let t of["fetchBars","listMarkets"])if(e[t]!=null&&typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} ${t} must be a function`);return e}var Or=[vr].map(_o),vo=new Map(Or.map(e=>[e.id,e])),Oo=Object.freeze([...Or]);function ze(e){return typeof e!="string"?null:vo.get(e)??null}function Ve(e){let t=ze(e);if(!t)throw new Error(`unknown strategy venue: ${String(e)}`);return t}var Je=1,Ur=/^[a-z0-9][a-z0-9._-]{0,63}$/,Dr=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Mo=new Set(["open","high","low","close","volume","fundingRate","openInterest","premium","oiDelta","bookImbalance"]),Ro=new Set(["sma","ema","rsi","macd","bollinger","atr"]),Lo=new Set(["gt","gte","lt","lte","eq"]),Fo=new Set(["and","or","not"]),jo=new Set(["above","below"]),Ho=new Set(["line","signal","histogram"]),Co=new Set(["upper","middle","lower"]),vt=new Set(["compare","logic","cross"]),Nr=new Set(["version","id","name","venue","market","parameters","nodes","rules","risk"]),Mr=new Set(["value","min","max","step"]),Ot=new Set(["entryLong","entryShort","exitLong","exitShort"]),Rr=new Set(["maxLeverage","maxNotionalUsd","positionSizePct","stopLossPct","takeProfitPct","cooldownBars","maxDailyLossPct","expiresAt"]),qo=new Set(["id","type"]),Lr={input:new Set(["id","type","field"]),constant:new Set(["id","type","value"]),indicator:new Set(["id","type","indicator","input","period","fastPeriod","slowPeriod","signalPeriod","stdDev","output"]),compare:new Set(["id","type","op","left","right"]),logic:new Set(["id","type","op","inputs"]),cross:new Set(["id","type","direction","left","right"])},Fr=16,jr=128,Hr=100,he=class extends Error{constructor(t){let r=t.map(n=>`${n.path}: ${n.message}`);super(`invalid strategy (${t.length} error${t.length===1?"":"s"}): ${r.join("; ")}`),this.name="StrategyValidationError",this.errors=t}};function X(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function q(e){return typeof e=="number"&&Number.isFinite(e)}function Cr(e){return Number.isInteger(e)&&e>0}function Mt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Mt(t);return Object.freeze(e)}for(let t of Object.keys(e))Mt(e[t]);return Object.freeze(e)}function Rt(e){if(Array.isArray(e))return e.map(Rt);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Rt(e[r]);return t}return e}function b(e,t,r){e.push({path:t,message:r})}function ue(e,t,r,n){for(let o of Object.keys(e))t.has(o)||b(n,r?`${r}.${o}`:o,"unknown field is not allowed")}function Br(e,t,r,n){if(!q(e)||!q(t)||!q(r)||!q(n)||n<=0||e<t||e>r)return!1;let o=(e-t)/n;if(!Number.isFinite(o))return!1;let s=Math.round(o);return Math.abs(o-s)<=1e-9}function Nt(e,t,r,n){if(X(e)){if(ue(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param)return b(n,`${t}.param`,"must be a parameter name string"),null;if(!Object.prototype.hasOwnProperty.call(r,e.param))return b(n,`${t}.param`,`unknown parameter "${e.param}"`),null;let o=r[e.param];return!X(o)||![o.value,o.min,o.max,o.step].every(Cr)?(b(n,`${t}.param`,"referenced period parameter value min max and step must be positive integers"),null):{param:e.param}}return Cr(e)?e:(b(n,t,"must be a positive integer or {param}"),null)}function qr(e,t,r,n){return X(e)?(ue(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param?(b(n,`${t}.param`,"must be a parameter name string"),null):Object.prototype.hasOwnProperty.call(r,e.param)?{param:e.param}:(b(n,`${t}.param`,`unknown parameter "${e.param}"`),null)):q(e)?e:(b(n,t,"must be a finite number or {param}"),null)}function Ke(e){switch(e.type){case"input":case"constant":return[];case"indicator":return e.input?[e.input]:[];case"compare":case"cross":return[e.left,e.right].filter(Boolean);case"logic":return Array.isArray(e.inputs)?[...e.inputs]:[];default:return[]}}function Uo(e){let t=new Map,r=n=>{let o=t.get(n)||0;if(o===1)return!0;if(o===2)return!1;t.set(n,1);let s=e.get(n);if(s){for(let i of Ke(s))if(e.has(i)&&r(i))return!0}return t.set(n,2),!1};for(let n of e.keys())if(r(n))return!0;return!1}function Do(e,t){if(!X(e))return b(t,"parameters","must be a plain object"),null;let r=Object.keys(e);if(r.length>Fr)return b(t,"parameters",`too many parameters (max ${Fr})`),null;let n={};for(let o of r){if(!Ur.test(o)){b(t,`parameters.${o}`,"parameter name is malformed");continue}let s=e[o],i=`parameters.${o}`;if(!X(s)){b(t,i,"must be a plain object");continue}ue(s,Mr,i,t);for(let c of Mr)c in s||b(t,`${i}.${c}`,"required field is missing");let{value:a,min:l,max:u,step:d}=s;q(l)||b(t,`${i}.min`,"must be a finite number"),q(u)||b(t,`${i}.max`,"must be a finite number"),(!q(d)||d<=0)&&b(t,`${i}.step`,"must be a positive finite number"),q(a)||b(t,`${i}.value`,"must be a finite number"),q(l)&&q(u)&&l>u&&b(t,`${i}.min`,"min must be <= max"),q(a)&&q(l)&&q(u)&&q(d)&&d>0&&(Br(a,l,u,d)||b(t,`${i}.value`,"value must lie on the declared min/max/step grid")),n[o]={value:a,min:l,max:u,step:d}}return n}function Bo(e,t,r,n){let o=`nodes.${t}`;if(!X(e))return b(n,o,"must be a plain object"),null;if(typeof e.type!="string"||!Lr[e.type])return b(n,`${o}.type`,"unknown or missing node type"),ue(e,qo,o,n),null;switch(ue(e,Lr[e.type],o,n),(typeof e.id!="string"||!Dr.test(e.id))&&b(n,`${o}.id`,"must be a 1-64 char id starting with alphanumeric"),e.type){case"input":return(typeof e.field!="string"||!Mo.has(e.field))&&b(n,`${o}.field`,"must be one of open|high|low|close|volume|fundingRate|openInterest|premium|oiDelta|bookImbalance"),{id:e.id,type:"input",field:e.field};case"constant":{let s=qr(e.value,`${o}.value`,r,n);return{id:e.id,type:"constant",value:s}}case"indicator":{(typeof e.indicator!="string"||!Ro.has(e.indicator))&&b(n,`${o}.indicator`,"must be one of sma|ema|rsi|macd|bollinger|atr");let s=e.indicator,i={id:e.id,type:"indicator",indicator:s};if(s==="atr"){"input"in e&&(typeof e.input!="string"||!e.input?b(n,`${o}.input`,"must be a node id string when provided"):i.input=e.input);let a=Nt(e.period,`${o}.period`,r,n);a!=null&&(i.period=a)}else typeof e.input!="string"||!e.input?b(n,`${o}.input`,"must be a node id string"):i.input=e.input;if((s==="sma"||s==="ema"||s==="rsi"||s==="bollinger"||s==="atr")&&("period"in e,s!=="macd"))if(!("period"in e))b(n,`${o}.period`,"required field is missing");else{let a=Nt(e.period,`${o}.period`,r,n);a!=null&&(i.period=a)}if(s==="macd"){for(let a of["fastPeriod","slowPeriod","signalPeriod"])if(!(a in e))b(n,`${o}.${a}`,"required field is missing");else{let l=Nt(e[a],`${o}.${a}`,r,n);l!=null&&(i[a]=l)}"output"in e?Ho.has(e.output)?i.output=e.output:b(n,`${o}.output`,"must be line|signal|histogram"):b(n,`${o}.output`,"required field is missing"),"period"in e&&b(n,`${o}.period`,"forbidden for macd"),"stdDev"in e&&b(n,`${o}.stdDev`,"forbidden for macd")}else if(s==="bollinger"){if(!("stdDev"in e))b(n,`${o}.stdDev`,"required field is missing");else{let a=qr(e.stdDev,`${o}.stdDev`,r,n);a!=null&&(typeof a=="number"&&a<=0?b(n,`${o}.stdDev`,"must be > 0"):i.stdDev=a)}"output"in e?Co.has(e.output)?i.output=e.output:b(n,`${o}.output`,"must be upper|middle|lower"):b(n,`${o}.output`,"required field is missing");for(let a of["fastPeriod","slowPeriod","signalPeriod"])a in e&&b(n,`${o}.${a}`,`forbidden for ${s}`)}else{"output"in e&&b(n,`${o}.output`,`forbidden for ${s}`),"stdDev"in e&&s!=="bollinger"&&b(n,`${o}.stdDev`,`forbidden for ${s}`);for(let a of["fastPeriod","slowPeriod","signalPeriod"])a in e&&b(n,`${o}.${a}`,`forbidden for ${s}`)}return i}case"compare":return(typeof e.op!="string"||!Lo.has(e.op))&&b(n,`${o}.op`,"must be gt|gte|lt|lte|eq"),(typeof e.left!="string"||!e.left)&&b(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&b(n,`${o}.right`,"must be a node id"),{id:e.id,type:"compare",op:e.op,left:e.left,right:e.right};case"logic":{if((typeof e.op!="string"||!Fo.has(e.op))&&b(n,`${o}.op`,"must be and|or|not"),!Array.isArray(e.inputs))return b(n,`${o}.inputs`,"must be an array of node ids"),{id:e.id,type:"logic",op:e.op,inputs:[]};let s=[];for(let i=0;i<e.inputs.length;i++){let a=e.inputs[i];typeof a!="string"||!a?b(n,`${o}.inputs.${i}`,"must be a node id"):s.push(a)}return e.op==="not"?s.length!==1&&b(n,`${o}.inputs`,"not requires exactly one input"):(e.op==="and"||e.op==="or")&&s.length<2&&b(n,`${o}.inputs`,`${e.op} requires at least two inputs`),{id:e.id,type:"logic",op:e.op,inputs:s}}case"cross":return(typeof e.direction!="string"||!jo.has(e.direction))&&b(n,`${o}.direction`,"must be above|below"),(typeof e.left!="string"||!e.left)&&b(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&b(n,`${o}.right`,"must be a node id"),{id:e.id,type:"cross",direction:e.direction,left:e.left,right:e.right};default:return null}}function zo(e,t,r){if(!X(e))return b(t,"risk","must be a plain object"),null;ue(e,Rr,"risk",t);for(let f of Rr)(!(f in e)||e[f]==null)&&b(t,`risk.${f}`,"required field is missing");let n={},o=e.maxLeverage;!q(o)||o<=0||o>50?b(t,"risk.maxLeverage","must be a number > 0 and <= 50"):n.maxLeverage=o;let s=e.maxNotionalUsd;!q(s)||s<=0?b(t,"risk.maxNotionalUsd","must be a number > 0"):n.maxNotionalUsd=s;let i=e.positionSizePct;!q(i)||i<=0||i>100?b(t,"risk.positionSizePct","must be a number > 0 and <= 100"):n.positionSizePct=i;let a=e.stopLossPct;!q(a)||a<=0||a>100?b(t,"risk.stopLossPct","must be a number > 0 and <= 100"):n.stopLossPct=a;let l=e.takeProfitPct;!q(l)||l<=0||l>1e3?b(t,"risk.takeProfitPct","must be a number > 0 and <= 1000"):n.takeProfitPct=l;let u=e.cooldownBars;!Number.isInteger(u)||u<0||u>1e5?b(t,"risk.cooldownBars","must be an integer >= 0 and <= 100000"):n.cooldownBars=u;let d=e.maxDailyLossPct;!q(d)||d<=0||d>100?b(t,"risk.maxDailyLossPct","must be a number > 0 and <= 100"):n.maxDailyLossPct=d;let c=e.expiresAt;return!Number.isInteger(c)||c<=0?b(t,"risk.expiresAt","must be an integer epoch milliseconds > 0"):(r.nowMs!==void 0&&(Number.isInteger(r.nowMs)?c<=r.nowMs&&b(t,"risk.expiresAt","must be strictly greater than nowMs"):b(t,"nowMs","must be an integer epoch milliseconds")),n.expiresAt=c),n}function Ye(e,t={}){let r=[];if(!X(e))return b(r,"","strategy must be a plain object"),{ok:!1,errors:r,strategy:null};ue(e,Nr,"",r);for(let c of Nr)(!(c in e)||e[c]==null)&&b(r,c,"required field is missing");e.version!==Je&&b(r,"version",`must be ${Je}`),(typeof e.id!="string"||!Ur.test(e.id))&&b(r,"id","must match /^[a-z0-9][a-z0-9._-]{0,63}$/"),(typeof e.name!="string"||e.name.length===0||e.name.length>Hr)&&b(r,"name",`must be a non-empty string max ${Hr}`);let n=ze(e.venue);n||b(r,"venue",`unknown strategy venue "${String(e.venue)}"`);let o=null;if(!n)X(e.market)||b(r,"market","must be a plain object");else{let c=n.validateMarket(e.market);if(!c||typeof c.ok!="boolean"||!Array.isArray(c.errors))b(r,"market",`venue ${n.id} returned an invalid market validation result`);else if(c.ok)o=c.market;else for(let f of c.errors)b(r,f.path,f.message)}let s=Do(e.parameters,r),i=null,a=new Map;if(!Array.isArray(e.nodes))b(r,"nodes","must be an array");else if(e.nodes.length>jr)b(r,"nodes",`too many nodes (max ${jr})`);else{i=[];for(let c=0;c<e.nodes.length;c++){let f=Bo(e.nodes[c],c,s||{},r);f&&(typeof f.id=="string"&&Dr.test(f.id)&&(a.has(f.id)?b(r,`nodes.${c}.id`,`duplicate node id "${f.id}"`):a.set(f.id,f)),i.push(f))}for(let c=0;c<i.length;c++){let f=i[c],p=`nodes.${c}`;for(let h of Ke(f))a.has(h)||b(r,p,`unknown node ref "${h}"`);if(f.type==="indicator"||f.type==="compare"||f.type==="cross")for(let h of Ke(f)){let w=a.get(h);w&&vt.has(w.type)&&b(r,p,`node ref "${h}" must be numeric`)}if(f.type==="logic")for(let h of Ke(f)){let w=a.get(h);w&&!vt.has(w.type)&&b(r,p,`node ref "${h}" must be boolean`)}}Uo(a)&&b(r,"nodes","graph contains a cycle")}let l=null;if(!X(e.rules))b(r,"rules","must be a plain object");else{ue(e.rules,Ot,"rules",r);for(let c of Ot)c in e.rules||b(r,`rules.${c}`,"required field is missing");l={};for(let c of Ot){let f=e.rules[c];if(f===null){l[c]=null;continue}if(typeof f!="string"||!f){b(r,`rules.${c}`,"must be a node id or null"),l[c]=f;continue}if(!a.has(f)){b(r,`rules.${c}`,`unknown node ref "${f}"`),l[c]=f;continue}let p=a.get(f);vt.has(p.type)||b(r,`rules.${c}`,`rule must reference a boolean node, not ${p.type}`),l[c]=f}}let u=zo(e.risk,r,t);if(r.length)return{ok:!1,errors:r,strategy:null};let d=Mt({version:Je,id:e.id,name:e.name,venue:n.id,market:o,parameters:s,nodes:i,rules:l,risk:u});return{ok:!0,errors:[],strategy:d}}function Y(e,t={}){let r=Ye(e,t);if(!r.ok)throw new he(r.errors);return r.strategy}function zr(e){let t=Y(e);return JSON.stringify(Rt(t))}function pe(e){let t=zr(e);return No("sha256").update(t,"utf8").digest("hex")}function ge(e,t){if(!X(e))throw new he([{path:"",message:"strategy must be a plain object"}]);if(!X(t))throw new he([{path:"overrides",message:"must be a plain object"}]);let r=Y(e),n={};for(let[s,i]of Object.entries(r.parameters))n[s]={value:i.value,min:i.min,max:i.max,step:i.step};let o=[];for(let[s,i]of Object.entries(t)){if(!Object.prototype.hasOwnProperty.call(n,s)){b(o,s,`unknown parameter "${s}"`);continue}let a=n[s];if(!q(i)){b(o,s,"override must be a finite number");continue}if(!Br(i,a.min,a.max,a.step)){b(o,s,"override must lie on the declared min/max/step grid");continue}n[s]={...a,value:i}}if(o.length)throw new he(o);return Y({version:r.version,id:r.id,name:r.name,venue:r.venue,market:{coin:r.market.coin,interval:r.market.interval},parameters:n,nodes:r.nodes.map(s=>{let i={...s};return Array.isArray(s.inputs)&&(i.inputs=[...s.inputs]),i}),rules:{...r.rules},risk:{...r.risk}})}var Vo=50;function ne(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function Vr(e,t,r){if(!Array.isArray(e))throw new TypeError(`${r} must be an array`);let n=0;for(let o=0;o<e.length;o++){let s=ne(e[o]?.px,`${r}[${o}].px`),i=ne(e[o]?.sz,`${r}[${o}].sz`);if(i<0)throw new TypeError(`${r}[${o}].sz must be non-negative`);Math.abs((s-t)/t)*1e4<=Vo&&(n+=i)}return n}async function Jo(e,t={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("sampleLiveSeries input must be an object");let r=String(e.coin||"").trim().toUpperCase();if(!/^[A-Z0-9][A-Z0-9._-]{0,11}$/.test(r))throw new TypeError("coin must be an uppercase Hyperliquid asset id");if(!Number.isSafeInteger(e.nowMs)||e.nowMs<=0)throw new TypeError("nowMs is required integer epoch ms");let[n,o]=await Promise.all([mr(t),dr(r,t)]),s=n?.[0]?.universe,i=n?.[1];if(!Array.isArray(s)||!Array.isArray(i))throw new TypeError("metaAndAssetCtxs payload malformed");let a=s.findIndex(w=>w?.name===r);if(a<0)throw new Error(`unknown coin: ${r}`);let l=i[a];if(!l||typeof l!="object")throw new TypeError("asset ctx malformed");let u=ne(l.premium,"ctx.premium"),d=ne(l.openInterest,"ctx.openInterest");if(d<0)throw new TypeError("ctx.openInterest must be non-negative");let c=ne(l.midPx,"ctx.midPx"),f=o?.levels;if(!Array.isArray(f)||f.length!==2)throw new TypeError("l2Book levels malformed");let p=Vr(f[0],c,"book.bids"),h=Vr(f[1],c,"book.asks");if(p+h<=0)throw new TypeError("book depth near mid is empty");return Object.freeze({coin:r,t:e.nowMs,premium:u,openInterest:d,book:Object.freeze({bidDepth:p,askDepth:h})})}function Ko(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("snapshots must be a non-empty array");let t=e[0]?.coin,r=[],n=null;for(let o=0;o<e.length;o++){let s=e[o];if(!s||typeof s!="object")throw new TypeError(`snapshots[${o}] must be an object`);if(s.coin!==t)throw new TypeError("snapshots must be a single coin");let i=ne(s.t,`snapshots[${o}].t`);if(n!=null&&!(i>n.t))throw new TypeError("snapshot times must be strictly increasing");let a=ne(s.premium,`snapshots[${o}].premium`),l=ne(s.openInterest,`snapshots[${o}].openInterest`),u=ne(s.book?.bidDepth,`snapshots[${o}].book.bidDepth`),d=ne(s.book?.askDepth,`snapshots[${o}].book.askDepth`),c=u+d;if(!(c>0))throw new TypeError(`snapshots[${o}] book depth must be positive`);r.push({coin:t,t:i,premium:a,openInterest:l,oiDelta:n==null?null:l-n.openInterest,bookImbalance:(u-d)/c}),n={t:i,openInterest:l}}return r}function Yo(e,t,r){if(!Array.isArray(e))throw new TypeError("bars must be an array");if(!Array.isArray(t))throw new TypeError("rows must be an array");if(!Number.isSafeInteger(r)||r<=0)throw new TypeError("intervalMs must be a positive integer");let n=0;return e.map(o=>{let s=o.t+r,i=null;for(;n<t.length&&t[n].t<s;)t[n].t>=o.t&&(i=t[n]),n+=1;if(!i)return{...o};let a={...o};return i.premium!=null&&(a.premium=i.premium),i.openInterest!=null&&(a.openInterest=i.openInterest),i.oiDelta!=null&&(a.oiDelta=i.oiDelta),i.bookImbalance!=null&&(a.bookImbalance=i.bookImbalance),a})}import{createHash as Go}from"node:crypto";var Ft=256,Jr=new Set(["netPnlUsd","profitFactor","sharpe","maxDrawdownPct"]);function Kr(e){let t=String(e).toLowerCase();return t==="holdout"||t==="test"||t==="oos"||t.includes("holdout")||t.includes("oos")?!0:t==="testbars"||t.endsWith("testbars")||t.startsWith("test")||t.endsWith("test")?!t.includes("backtest"):!1}function Yr(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function jt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)jt(t);return Object.freeze(e)}for(let t of Object.keys(e))jt(e[t]);return Object.freeze(e)}function Le(e){if(Array.isArray(e))return e.map(Le);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Le(e[r]);return t}return e}function Ge(e){return JSON.stringify(Le(e))}function Wo(e){let{min:t,max:r,step:n}=e;if(!(n>0)||t>r)return[];let o=[],s=Math.floor((r-t)/n+1e-9);for(let a=0;a<=s;a++){let l=t+a*n;if(l>r+1e-9)break;let u=Math.abs(l-Math.round(l))<1e-9?Math.round(l):Number(l.toPrecision(12));u<t-1e-9||u>r+1e-9||o.push(u)}if(o.length===0)return[];let i=o[o.length-1];if(Math.abs(i-r)>1e-9){let a=(r-t)/n;Math.abs(a-Math.round(a))<=1e-9&&o.push(r)}return o}function Xo(e,t){if(e.length===0)return[];let r=[{}];for(let n of e){let o=t[n],s=[];for(let i of r)for(let a of o)s.push({...i,[n]:a});r=s}return r.sort((n,o)=>{let s=Ge(n),i=Ge(o);return s<i?-1:s>i?1:0}),r}function Lt(e,t,r,n,o){let s=0;if(e==="maxDrawdownPct"){if(s=t.maxDrawdownPct-n.maxDrawdownPct,s!==0)return s<0}else if(s=t[e]-n[e],s!==0)return s>0;let i=Ge(r),a=Ge(o);return i<a}function Ht(e,t,r={}){if(!Yr(r))throw new TypeError("options must be a plain object");for(let g of Object.keys(r))if(Kr(g))throw new TypeError(`options must not include holdout/test/oos key "${g}"`);let n=new Set(["maxTrials","objective","backtestOptions"]);for(let g of Object.keys(r))if(!n.has(g))throw new TypeError(`unknown option "${g}"`);let o=64;if("maxTrials"in r){let g=r.maxTrials;if(!Number.isInteger(g)||g<1||g>Ft)throw new TypeError(`maxTrials must be an integer 1..${Ft}`);o=g}let s=r.objective??"netPnlUsd";if(!Jr.has(s))throw new TypeError(`objective must be one of ${[...Jr].join("|")}`);let i=r.backtestOptions??{};if(!Yr(i))throw new TypeError("backtestOptions must be a plain object");for(let g of Object.keys(i))if(Kr(g))throw new TypeError(`backtestOptions must not include holdout/test/oos key "${g}"`);let a=Y(e),l=Object.keys(a.parameters).sort();if(l.length===0)throw new Error("optimizeStrategy requires at least one declared parameter");let u={},d=1;for(let g of l){let P=Wo(a.parameters[g]);if(P.length===0)throw new Error(`parameter "${g}" produces an empty grid`);u[g]=P,d*=P.length}let c=Xo(l,u);if(c.length===0)throw new Error("parameter grid is empty");let f=c.slice(0,o),p=[],h=null,w=null;for(let g of f){let P=ge(a,g),x=ie(P,t,i);w==null&&(w=x.config);let m={netPnlUsd:x.metrics.netPnlUsd,netPnlPct:x.metrics.netPnlPct,maxDrawdownPct:x.metrics.maxDrawdownPct,winRate:x.metrics.winRate,profitFactor:x.metrics.profitFactor,tradeCount:x.metrics.tradeCount,sharpe:x.metrics.sharpe,turnoverUsd:x.metrics.turnoverUsd},M={parameters:{...g},metrics:m};p.push(M),(!h||Lt(s,m,g,h.metrics,h.parameters))&&(h=M)}p.sort((g,P)=>Lt(s,g.metrics,g.parameters,P.metrics,P.parameters)?-1:Lt(s,P.metrics,P.parameters,g.metrics,g.parameters)?1:0);let k={...h.parameters},S=ge(a,k),I={strategyHash:pe(a),compilerHash:le,trainBarsHash:Oe(t),backtestConfig:w,objective:s,maxTrials:o,trialsRun:p.length,candidates:p,bestParameters:k,bestStrategy:S},_={id:Go("sha256").update(JSON.stringify(Le(I)),"utf8").digest("hex"),...I};return jt(Le(JSON.parse(JSON.stringify(_))))}import{createHash as Zo}from"node:crypto";var V=class extends Error{constructor(t){super(t),this.name="StrategyDraftError"}},Qo=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),es=new Set(["BTC","ETH","SOL","HYPE"]),ts=/\b(mnemonic|private\s*key|privkey|seed\s*phrase|seed\b|api[_-]?key|secret\s*key|wallet\s*key|passphrase)\b/i,xe="Supported grammar: (1) EMA cross: <long|short> <COIN> when EMA <n> crosses <above|below> EMA <m> [on <interval>] [, exit on reverse] [, risk knobs]; (2) RSI: <long|short> <COIN> when RSI <n> <above|below> <threshold> [on <interval>] [, risk knobs]; (3) funding: <long|short> <COIN> when funding rate <above|below> <decimal|percent%> [on <interval>] [, risk knobs]; (4) open interest: <long|short> <COIN> when open interest <above|below> <non-negative number> [on <interval>] [, risk knobs]; (5) premium: <long|short> <COIN> when premium <above|below> <decimal|percent%> [on <interval>] [, risk knobs]; (6) oi delta: <long|short> <COIN> when oi delta <above|below> <number> [on <interval>] [, risk knobs]; (7) book imbalance: <long|short> <COIN> when book imbalance <above|below> <-1..1> [on <interval>] [, risk knobs]. Risk knobs: stop loss %, take profit %, leverage, position size %, max notional USD. Coins: BTC ETH SOL HYPE or uppercase token <=12 chars. Intervals: 1m 3m 5m 15m 30m 1h 2h 4h 8h 12h 1d.",rs=Object.freeze({maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3}),ns=36e5,os=30*864e5,ss=864e5;function is(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Ct(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Ct(t);return Object.freeze(e)}for(let t of Object.keys(e))Ct(e[t]);return Object.freeze(e)}function as(e){return String(e).trim().replace(/\s+/g," ")}function cs(e){let t=e.match(/\b(long|short)\b/i);return t?t[1].toLowerCase():null}function ls(e){for(let r of es)if(new RegExp(`\\b${r}\\b`,"i").test(e))return r;let t=e.match(/\b([A-Z][A-Z0-9]{1,11})\b/);return t?t[1]:null}function us(e){let t=e.match(/\bon\s+(1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)\b/i);if(!t)return"15m";let r=t[1].toLowerCase();return Qo.has(r)?r:null}function fs(e){let t={...rs},r=e.match(/stop\s*loss\s*(\d+(?:\.\d+)?)\s*%?/i);r&&(t.stopLossPct=Number(r[1]));let n=e.match(/take\s*profit\s*(\d+(?:\.\d+)?)\s*%?/i);n&&(t.takeProfitPct=Number(n[1]));let o=e.match(/leverage\s*(\d+(?:\.\d+)?)/i);o&&(t.maxLeverage=Number(o[1]));let s=e.match(/position\s*size\s*(\d+(?:\.\d+)?)\s*%?/i);s&&(t.positionSizePct=Number(s[1]));let i=e.match(/max\s*notional\s*(?:usd\s*)?\$?\s*(\d+(?:\.\d+)?)/i);return i&&(t.maxNotionalUsd=Number(i[1])),t}function ds(e){return[/\bon\s+(?:1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)\b/gi,/\bstop\s*loss\s*\d+(?:\.\d+)?\s*%?/gi,/\btake\s*profit\s*\d+(?:\.\d+)?\s*%?/gi,/\bleverage\s*\d+(?:\.\d+)?/gi,/\bposition\s*size\s*\d+(?:\.\d+)?\s*%?/gi,/\bmax\s*notional\s*(?:usd\s*)?\$?\s*\d+(?:\.\d+)?/gi].some(r=>(e.match(r)??[]).length>1)}function ps(e){let t=Zo("sha256").update(e,"utf8").digest("hex").slice(0,10),r=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40),o=`${r.length?r:"draft"}-${t}`.replace(/[^a-z0-9._-]/g,"").slice(0,64);return/^[a-z0-9]/.test(o)?o:`d${o}`.slice(0,64)}function ms(e){let t=e.match(/\bema\s*(\d+)\s*cross(?:es)?\s*(above|below)\s*ema\s*(\d+)\b/i);if(!t)return null;let r=Number(t[1]),n=t[2].toLowerCase(),o=Number(t[3]);if(!(r>0)||!(o>0)||r===o)return null;let s=/\b(exit\s+on\s+reverse|reverse\s+exit)\b/i.test(e);return{kind:"ema_cross",fast:r,slow:o,direction:n,reverse:s}}function hs(e){let t=e.match(/\brsi\s*(\d+)\s*(above|below)\s*(-?\d+(?:\.\d+)?)/i);if(!t)return null;let r=Number(t[3]);return!Number.isFinite(r)||r<=0||r>=100?null:{kind:"rsi",period:Number(t[1]),op:t[2].toLowerCase(),threshold:r}}function ys(e){let t=e.match(/\bfunding\s*rate\s*(above|below)\s*(-?\d+(?:\.\d+)?)(%?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return t[3]==="%"&&(r=r/100),{kind:"funding",op:t[1].toLowerCase(),threshold:r}}function ws(e){let t=e.match(/\bopen\s*interest\s*(above|below)\s*(-?\d+(?:\.\d+)?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return!Number.isFinite(r)||r<0?null:{kind:"open_interest",op:t[1].toLowerCase(),threshold:r}}function gs(e){let t=e.match(/\bpremium\s*(above|below)\s*(-?\d+(?:\.\d+)?)(%?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return Number.isFinite(r)?(t[3]==="%"&&(r=r/100),{kind:"premium",op:t[1].toLowerCase(),threshold:r}):null}function bs(e){let t=e.match(/\boi\s*delta\s*(above|below)\s*(-?\d+(?:\.\d+)?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return Number.isFinite(r)?{kind:"oi_delta",op:t[1].toLowerCase(),threshold:r}:null}function Es(e){let t=e.match(/\bbook\s*imbalance\s*(above|below)\s*(-?\d+(?:\.\d+)?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return!Number.isFinite(r)||r<-1||r>1?null:{kind:"book_imbalance",op:t[1].toLowerCase(),threshold:r}}function ks(e,t){let r=e.replace(/^(long|short)\s+[A-Z][A-Z0-9]{1,11}\s+when\s+/i,"");if(r===e)return!1;t.kind==="ema_cross"?r=r.replace(/^ema\s*\d+\s*cross(?:es)?\s*(?:above|below)\s*ema\s*\d+\b/i,""):t.kind==="rsi"?r=r.replace(/^rsi\s*\d+\s*(?:above|below)\s*\d+(?:\.\d+)?\b/i,""):t.kind==="open_interest"?r=r.replace(/^open\s*interest\s*(?:above|below)\s*-?\d+(?:\.\d+)?(?=\s|,|$)/i,""):t.kind==="premium"?r=r.replace(/^premium\s*(?:above|below)\s*-?\d+(?:\.\d+)?%?(?=\s|,|$)/i,""):t.kind==="oi_delta"?r=r.replace(/^oi\s*delta\s*(?:above|below)\s*-?\d+(?:\.\d+)?(?=\s|,|$)/i,""):t.kind==="book_imbalance"?r=r.replace(/^book\s*imbalance\s*(?:above|below)\s*-?\d+(?:\.\d+)?(?=\s|,|$)/i,""):r=r.replace(/^funding\s*rate\s*(?:above|below)\s*-?\d+(?:\.\d+)?%?(?=\s|,|$)/i,"");let n=[/(?:,\s*)?\bon\s+(?:1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)\b/gi,/(?:,\s*)?\bstop\s*loss\s*\d+(?:\.\d+)?\s*%?/gi,/(?:,\s*)?\btake\s*profit\s*\d+(?:\.\d+)?\s*%?/gi,/(?:,\s*)?\bleverage\s*\d+(?:\.\d+)?/gi,/(?:,\s*)?\bposition\s*size\s*\d+(?:\.\d+)?\s*%?/gi,/(?:,\s*)?\bmax\s*notional\s*(?:usd\s*)?\$?\s*\d+(?:\.\d+)?/gi];t.kind==="ema_cross"&&n.push(/(?:,\s*)?\b(?:exit\s+on\s+reverse|reverse\s+exit)\b/gi);for(let o of n)r=r.replace(o,"");return r.replace(/[\s,;]+/g,"")===""}function Gr(e){let t=Math.max(2,Math.floor(e/2));return{value:e,min:Math.max(2,e-t),max:Math.min(500,e+t),step:1}}function xs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"c",type:"input",field:"close"},{id:"emaLeft",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_left_period"}},{id:"emaRight",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_right_period"}},{id:"cross",type:"cross",direction:a.direction,left:"emaLeft",right:"emaRight"}],u={entryLong:null,entryShort:null,exitLong:null,exitShort:null};if(e==="long"?u.entryLong="cross":u.entryShort="cross",a.reverse){let d=a.direction==="above"?"below":"above";l.push({id:"crossRev",type:"cross",direction:d,left:"emaLeft",right:"emaRight"}),e==="long"?u.exitLong="crossRev":u.exitShort="crossRev"}return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{ema_left_period:Gr(a.fast),ema_right_period:Gr(a.slow)},nodes:l,rules:u,risk:{...n,expiresAt:o}}}function Ss({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"c",type:"input",field:"close"},{id:"rsi",type:"indicator",indicator:"rsi",input:"c",period:a.period},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"rsi",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function As({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"fr",type:"input",field:"fundingRate"},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"fr",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function $s({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"oi",type:"input",field:"openInterest"},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"oi",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}var Ps=Object.freeze({funding:"fundingRate",open_interest:"openInterest",premium:"premium",oi_delta:"oiDelta",book_imbalance:"bookImbalance"});function Ts({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let u=[{id:"sig_input",type:"input",field:Ps[a.kind]},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"sig_input",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:u,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function qt(e,t={}){if(typeof e!="string")throw new V("prompt must be a string");if(e.length>1e3)throw new V("prompt length must be <= 1000");if(!is(t))throw new V("options must be a plain object");if(!Number.isInteger(t.nowMs))throw new V("options.nowMs is required integer epoch ms");let r=t.nowMs,n=ss;if("expiresInMs"in t){if(!Number.isInteger(t.expiresInMs))throw new V("expiresInMs must be an integer");if(n=t.expiresInMs,n<ns||n>os)throw new V("expiresInMs must be between 1h and 30d")}if(ts.test(e))throw new V(`prompt appears to contain secrets and is rejected. ${xe}`);let o=as(e);if(!o)throw new V(`empty prompt. ${xe}`);if(ds(o))throw new V(`duplicate interval or risk clause. ${xe}`);let s=cs(o),i=ls(o),a=us(o);if(!s||!i||!a)throw new V(`could not parse side/coin/interval. ${xe}`);let l=fs(o);if(!(l.maxLeverage>0)||l.maxLeverage>50)throw new V("leverage out of range");if(!(l.positionSizePct>0)||l.positionSizePct>100)throw new V("position size out of range");let u=r+n,d=ps(o),c=`Draft ${i} ${s}`.slice(0,100),f=ms(o),p=hs(o),h=ys(o),w=ws(o),k=gs(o),S=bs(o),I=Es(o),_=[f,p,h,w,k,S,I].filter(Boolean);if(_.length!==1)throw new V(`unsupported or ambiguous prompt. ${xe}`);if(!ks(o,_[0]))throw new V(`unsupported or ambiguous prompt. ${xe}`);let g,P=_[0],x={side:s,coin:i,interval:a,risk:l,expiresAt:u,id:d,name:c,spec:P};P.kind==="ema_cross"?g=xs(x):P.kind==="rsi"?g=Ss(x):P.kind==="open_interest"?g=$s(x):P.kind==="funding"?g=As(x):g=Ts(x);let m=Ye(g,{nowMs:r});if(!m.ok)throw new V(`draft failed validation: ${m.errors.map(M=>M.message).join("; ")}`);return Ct(Y(g,{nowMs:r}))}import ae from"node:fs";import We from"node:path";var Dt=1,Is=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Xe(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function oe(e){return e==null?e:JSON.parse(JSON.stringify(e))}function _s(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Se(e,t="record"){if(Array.isArray(e)){e.forEach((r,n)=>Se(r,`${t}[${n}]`));return}if(Xe(e))for(let[r,n]of Object.entries(e)){let o=_s(r);if(Is.some(s=>o.includes(s)))throw new Error(`shadow-store: forbidden secret-like field at ${t}.${r}`);Se(n,`${t}.${r}`)}}function vs(e){if(typeof e!="string"||!e||!We.isAbsolute(e))throw new Error("shadow-store: path must be an absolute path")}function Wr(e){let t;try{t=ae.lstatSync(e)}catch(n){if(n&&n.code==="ENOENT")return;throw n}if(t.isSymbolicLink())throw new Error("shadow-store: store path must not be a symlink");if(!t.isFile())throw new Error("shadow-store: store path must be a regular file");if(t.mode&511&18)throw new Error("shadow-store: store file must not be group or world writable")}function Os(){return{version:Dt,runners:[]}}function Xr(e,t){let r;try{r=JSON.parse(e)}catch{throw new Error("shadow-store: malformed JSON")}if(!Xe(r))throw new Error("shadow-store: malformed JSON root");if(r.version!==Dt)throw new Error(`shadow-store: unsupported version ${r.version}`);if(!Array.isArray(r.runners))throw new Error("shadow-store: runners must be an array");return Se(r,We.basename(t)),{version:Dt,runners:r.runners.map(n=>oe(n))}}function Zr(e,t){Se(t,"store");let r=We.dirname(e);ae.mkdirSync(r,{recursive:!0,mode:448});let n=We.join(r,`.shadow-store.${process.pid}.${Date.now()}.tmp`),o=`${JSON.stringify(t)}
3
- `;try{ae.writeFileSync(n,o,{mode:384,flag:"wx"}),ae.renameSync(n,e);try{ae.chmodSync(e,384)}catch{}}catch(s){try{ae.unlinkSync(n)}catch{}throw s}}var Ut=new Map;function Bt(e={}){let t=e.path;if(vs(t),Wr(t),ae.existsSync(t)?Xr(ae.readFileSync(t,"utf8"),t):Zr(t,Os()),Ut.has(t))return Ut.get(t);let r=!1,n=[];function o(){if(r)return;let h=n.shift();if(h){r=!0;try{let w=h.fn();r=!1,h.resolve(w),o()}catch(w){r=!1,h.reject(w),o()}}}function s(h){if(!r&&n.length===0){r=!0;try{return h()}finally{r=!1,queueMicrotask(o)}}return new Promise((w,k)=>{n.push({fn:h,resolve:w,reject:k}),queueMicrotask(o)})}function i(){return Wr(t),Xr(ae.readFileSync(t,"utf8"),t)}function a(h){Zr(t,h)}function l(h){if(!Xe(h)||typeof h.id!="string"||!h.id)throw new Error("shadow-store: create requires record with string id");Se(h,"record");let w=i();if(w.runners.some(S=>S.id===h.id))throw new Error(`shadow-store: runner id already exists: ${h.id}`);let k=oe(h);return w.runners.push(k),a(w),oe(k)}function u(h){let w=i().runners.find(k=>k.id===h);return w?oe(w):null}function d(){return i().runners.map(h=>oe(h))}function c(h,w){if(typeof w!="function")throw new Error("shadow-store: updater must be a function");let k=i(),S=k.runners.findIndex(g=>g.id===h);if(S<0)throw new Error(`shadow-store: runner not found: ${h}`);let I=oe(k.runners[S]),_=w(I);if(!Xe(_)||_.id!==h)throw new Error("shadow-store: updater must return record with same id");return Se(_,"record"),k.runners[S]=oe(_),a(k),oe(k.runners[S])}function f(h){let w=i(),k=w.runners.findIndex(I=>I.id===h);if(k<0)throw new Error(`shadow-store: runner not found: ${h}`);let S=oe(w.runners[k]);return S.status!=="stopped"&&(S.status="stopped",w.runners[k]=S,a(w)),oe(w.runners[k])}let p={create(h){return s(()=>l(h))},get(h){return u(h)},list(){return d()},update(h,w){return s(()=>c(h,w))},stop(h){return s(()=>f(h))}};return Ut.set(t,p),p}import{createHash as Jt}from"node:crypto";function zt(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Vt(e){return Array.isArray(e)?e.map(Vt):e&&typeof e=="object"?Object.fromEntries(Object.keys(e).sort().map(t=>[t,Vt(e[t])])):e}function en(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("shadow-runner: record must be an object");return Jt("sha256").update(JSON.stringify(Vt(e))).digest("hex")}function Ns(e,t,r,n,o){return Jt("sha256").update(`${e}|${t}|${r}|${n}|${o}`).digest("hex")}function Ms(e,t,r,n){return Jt("sha256").update(`shadow|${e}|${t}|${r}|${n??""}`).digest("hex")}function Rs(e){return e==="entryLong"||e==="exitShort"?"buy":e==="entryShort"||e==="exitLong"?"sell":e}function Qr(e){return e==="entryLong"||e==="entryShort"}function Ze({storePath:e,clock:t=Date.now}={}){if(typeof e!="string"||!e)throw new Error("shadow-runner: storePath required");let r=Bt({path:e});function n({strategy:l,evidenceId:u=null}={}){let d=K(l),c=u==null?null:String(u),f=r.list().filter(S=>S.status==="running"&&S.strategyHash===d.strategyHash&&S.compilerHash===d.compilerHash&&S.evidenceId===c).sort((S,I)=>S.createdAt-I.createdAt||S.id.localeCompare(I.id))[0];if(f)return zt(f);let p=t(),h=Ms(p,d.strategyHash,d.compilerHash,c),w=r.get(h);if(w)return zt(w);let k={id:h,strategy:zt(d.strategy),strategyHash:d.strategyHash,compilerHash:d.compilerHash,evidenceId:c,status:"running",cursor:null,intendedOrders:[],fills:[],missedFills:[],markouts:[],createdAt:p,updatedAt:p,position:null,cooldownBarsRemaining:0,cooldownStartT:null,lastProcessedBarIndex:-1};return r.create(k)}function o(l){return r.get(l)}function s(){return r.list()}function i(l){return r.stop(l)}function a(l,u,{markoutHorizons:d=[1,4,12]}={}){if(!Array.isArray(u))throw new TypeError("shadow-runner: bars must be an array");return r.update(l,c=>{if(c.status!=="running")throw new Error("shadow-runner: runner is stopped");if(u.length===0)return c;let p=K(c.strategy).evaluateAll(u),h=new Map;for(let y=0;y<u.length;y++)h.set(u[y].t,y);let w=c.cursor,k=[];for(let y=0;y<u.length;y++){let $=u[y].t;(w==null||$>w)&&k.push(y)}if(k.length===0)return c;let S=new Map(c.intendedOrders.map(y=>[y.id,y])),I=new Set(c.fills.map(y=>y.orderId)),_=new Map(c.missedFills.map(y=>[y.orderId,y])),g=(y,$)=>`${y}|${$}`,P=new Map(c.markouts.map(y=>[g(y.orderId,y.horizon),y])),x=c.position?{...c.position}:null,m=Number.isInteger(c.cooldownBarsRemaining)?Math.max(0,c.cooldownBarsRemaining):0,M=Number.isFinite(c.cooldownStartT)?c.cooldownStartT:null;function G({action:y,signalBarT:$,signalIndex:T}){let L=Rs(y),j=Ns(c.id,c.strategyHash,$,L,y);if(S.has(j))return S.get(j);let O=T+1,R=O<u.length,J={id:j,action:y,type:y,side:L,signalBarT:$,fillBarT:R?u[O].t:null,status:R?"open":"missed"};return S.set(j,J),c.intendedOrders.push(J),J}function U(y,$,T){if(I.has(y.id))return;let L={orderId:y.id,action:Qr(y.action)?"entry":"exit",side:y.side,price:$.o,barT:$.t,signalBarT:y.signalBarT,barIndex:T};if(c.fills.push(L),I.add(y.id),y.status="filled",y.fillBarT=$.t,_.has(y.id)&&(_.delete(y.id),c.missedFills=c.missedFills.filter(j=>j.orderId!==y.id)),Qr(y.action)){x={side:y.action==="entryLong"?"long":"short",entryOrderId:y.id,entryBarT:$.t,entryPrice:$.o,entryBarIndex:T};for(let j of d){let O=g(y.id,j);if(P.has(O))continue;let R={orderId:y.id,horizon:j,entryBarT:$.t,entryPrice:$.o,side:x.side,status:"pending",close:null,barT:null};P.set(O,R),c.markouts.push(R)}}else x=null,m=Number(c.strategy?.risk?.cooldownBars)||0,M=$.t}function z(y){if(I.has(y.id)||_.has(y.id))return;let $={orderId:y.id,action:y.action,side:y.side,signalBarT:y.signalBarT,status:"missed"};_.set(y.id,$),c.missedFills.push($),y.status="missed"}for(let y of c.intendedOrders){if(y.status==="filled"||I.has(y.id))continue;let $=h.get(y.signalBarT);if($==null)continue;let T=$+1;T<u.length&&(w==null||u[T].t>w)&&U(y,u[T],T)}for(let y of k){let $=u[y],T=p[y].signals,L=x,j=R=>{if(x||m>0&&(M==null||$.t>=M))return;let D=G({action:R,signalBarT:$.t,signalIndex:y}),Q=y+1;Q<u.length?U(D,u[Q],Q):z(D)},O=R=>{if(!x||x.side==="long"&&R!=="exitLong"||x.side==="short"&&R!=="exitShort")return;let J=G({action:R,signalBarT:$.t,signalIndex:y}),D=y+1;D<u.length?U(J,u[D],D):z(J)};L?(T.exitLong&&O("exitLong"),T.exitShort&&O("exitShort")):T.entryLong&&T.entryShort||(T.entryLong&&j("entryLong"),T.entryShort&&j("entryShort")),m>0&&M!=null&&$.t>=M&&(m-=1,m===0&&(M=null)),c.cursor=$.t,c.lastProcessedBarIndex=y}for(let y of c.markouts){if(y.status!=="pending")continue;let $=c.fills.find(j=>j.orderId===y.orderId&&j.action==="entry");if(!$)continue;let T=h.get($.barT);if(T==null)continue;let L=T+y.horizon;if(L<u.length){y.close=u[L].c,y.barT=u[L].t,y.status="filled";let j=y.entryPrice;y.markout=y.side==="long"?(y.close-j)/j:(j-y.close)/j}}return c.position=x,c.cooldownBarsRemaining=m,c.cooldownStartT=M,c.updatedAt=t(),c})}return{start:n,step:a,list:s,get:o,stop:i}}import Ls from"node:os";import Fs from"node:path";var js=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Fe(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Hs(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Yt(e){if(Array.isArray(e)){for(let t of e)Yt(t);return}if(Fe(e))for(let[t,r]of Object.entries(e)){if(js.some(n=>Hs(t).includes(n)))throw new Error(`strategy service: secret-like field "${t}" is forbidden`);Yt(r)}}function Cs(e){if(!Fe(e))throw new TypeError("strategy input must be a plain object");return Yt(e),e}function qs(e,t={}){if(t.nowMs!==void 0){if(!Number.isInteger(t.nowMs))throw new TypeError("nowMs must be an integer epoch milliseconds");return t.nowMs}let r=Date.now();if(e.nowMs===void 0||e.nowMs===null)return r;if(!Number.isInteger(e.nowMs))throw new TypeError("nowMs must be an integer epoch milliseconds");if(Math.abs(e.nowMs-r)>12e4)throw new Error("nowMs outside allowed wall-clock skew (120s); omit nowMs to use server time");return e.nowMs}async function Kt(e,t,r,n){if(Array.isArray(t.bars))return t.bars;let o=Ve(e.venue),s=r.fetchBars??o.fetchBars;if(typeof s!="function")throw new Error(`strategy venue ${o.id} does not support history`);r.signal?.throwIfAborted?.();let i=await s({coin:e.market.coin,interval:e.market.interval,count:t.count??1500,endTime:t.endTime??n},{signal:r.signal});r.signal?.throwIfAborted?.();let a=Array.isArray(i)?i:i?.bars;if(!Array.isArray(a))throw new Error("strategy history provider returned no bars");return a}function Gt(e,t){let r=e.backtestOptions??{};if(!Fe(r))throw new TypeError("backtestOptions must be a plain object");return{...r,nowMs:t}}function tn(e,t,r,n,o={}){let s=e.evidenceOptions??{};if(!Fe(s))throw new TypeError("evidenceOptions must be a plain object");return{...s,...o,strategy:t,bars:r,backtestOptions:Gt(e,n)}}function rn(){return Fs.join(Ls.homedir(),".oracle","strategy-shadow.json")}function Us(e,t){return{perStrategyNotionalUsd:e.risk.maxNotionalUsd,maxLeverage:e.risk.maxLeverage,dailyLossCapUsd:e.risk.maxNotionalUsd*(e.risk.maxDailyLossPct/100),chainAllowlist:[e.venue],assetAllowlist:[e.market.coin],expiresAt:Math.min(e.risk.expiresAt,t+864e5),killSwitchRequired:!0}}async function Ds(e,t={},r={}){r.signal?.throwIfAborted?.();let n=Cs(t),o=qs(n,r);if(e==="draft")return{strategy:qt(n.prompt,{nowMs:o})};if(e==="validate"){let s=K(n.strategy);if(s.strategy.risk.expiresAt<=o)throw new Error("strategy is expired");return{valid:!0,strategy:s.strategy,strategyHash:s.strategyHash,compilerHash:s.compilerHash,compilerVersion:s.compilerVersion,requiredSeries:s.requiredSeries}}if(e==="backtest"||e==="evidence"){let s=K(n.strategy),i=await Kt(s.strategy,n,r,o);Ne(s,i);let a=Be(tn(n,s.strategy,i,o));return e==="evidence"?a:{backtest:ie(s.strategy,i,Gt(n,o)),evidence:a}}if(e==="optimize"){let s=K(n.strategy),i=await Kt(s.strategy,n,r,o);Ne(s,i);let a=n.trainFraction,l=n.evidenceOptions?.trainFraction;if(a!=null&&l!=null&&a!==l)throw new TypeError("conflicting trainFraction controls are forbidden");let u=a??l??.7;if(typeof u!="number"||u<=0||u>=1)throw new TypeError("trainFraction must be in (0,1)");let d=i.slice(0,Math.floor(i.length*u)),c=n.options??{};if(!Fe(c))throw new TypeError("options must be a plain object");let f=Ht(s.strategy,d,{...c,...n.maxTrials==null?{}:{maxTrials:n.maxTrials},backtestOptions:Gt(n,o)}),p=f.bestStrategy;return{strategy:p,optimization:f,evidence:Be(tn(n,p,i,o,{trainFraction:u}))}}if(e==="shadow"){let s=Ze({storePath:r.storePath??rn(),clock:()=>o}),i=n.action;if(i==="start")return await s.start({strategy:n.strategy,evidenceId:n.evidenceId??n.evidence?.id??null});if(i==="list")return await s.list();if(i==="get")return await s.get(n.id);if(i==="stop")return await s.stop(n.id);if(i==="step"){let a=await s.get(n.id);if(!a)throw new Error(`shadow runner not found: ${n.id}`);let l=await Kt(a.strategy,n,r,o);return Ne(K(a.strategy),l),await s.step(n.id,l,n.stepOptions??{})}throw new Error(`unknown shadow action: ${i}`)}if(e==="prepare"){let s=K(n.strategy),i=Ve(s.strategy.venue);if(typeof n.shadowId!="string"||!n.shadowId)throw new Error("strategy prepare requires a matching shadow runner id");let l=await Ze({storePath:r.storePath??rn(),clock:()=>o}).get(n.shadowId);if(!l)throw new Error("strategy prepare shadow runner not found");if(l.status!=="running")throw new Error("strategy prepare requires an active shadow runner");if(!Number.isFinite(l.cursor))throw new Error("strategy prepare requires a stepped shadow runner");if(l.strategyHash!==s.strategyHash||l.compilerHash!==s.compilerHash)throw new Error("strategy prepare shadow runner does not match strategy artifacts");if(l.evidenceId!==n.evidence?.id)throw new Error("strategy prepare shadow runner does not match evidence artifact");let u=n.caps??Us(s.strategy,o);return i.prepareIntent({strategy:s.strategy,evidence:n.evidence,shadow:{id:l.id,stateHash:en(l),status:l.status,cursor:l.cursor,updatedAt:l.updatedAt},caps:u,nowMs:o,env:r.env??process.env})}throw new Error(`unknown strategy operation: ${e}`)}export{Sr as EVIDENCE_STATUSES,Ft as MAX_OPTIMIZER_TRIALS,le as STRATEGY_COMPILER_HASH,we as STRATEGY_COMPILER_VERSION,Je as STRATEGY_VERSION,V as StrategyDraftError,he as StrategyValidationError,ge as applyParameterOverrides,At as assertEvidenceArtifact,yt as atr,Yo as attachDerivedSeries,ie as backtestStrategy,ht as bollinger,zr as canonicalStrategyJson,K as compileStrategy,St as computeEvidenceArtifactId,Ze as createShadowRunner,Ko as deriveSeries,qt as draftStrategyFromPrompt,_e as ema,Be as evaluateEvidence,_t as fetchHyperliquidStrategyBars,Ir as intervalToMs,mt as macd,_r as normalizeHyperliquidCandles,Y as normalizeStrategy,Bt as openShadowStore,Ht as optimizeStrategy,It as prepareStrategyLiveHandoff,Ve as requireStrategyVenue,ze as resolveStrategyVenue,pt as rsi,Ds as runStrategyOperation,Jo as sampleLiveSeries,dt as sma,pe as strategyHash,Oo as strategyVenues,Ye as validateStrategy};
1
+ import{createHash as Yo}from"node:crypto";import{createHash as Sn}from"node:crypto";import{types as le}from"node:util";import ge from"node:net";import gn from"node:dns";var bn=new Set(["localhost","metadata.google.internal","metadata.goog"]);function Ke(e){let t=String(e).toLowerCase().split("%")[0];if((t.match(/::/g)||[]).length>1)return null;let r=u=>{if(!u)return[];let c=u.split(":"),d=c.at(-1);if(d?.includes(".")){let m=d.split(".").map(Number);if(m.length!==4||m.some(p=>!Number.isInteger(p)||p<0||p>255))return null;c.splice(c.length-1,1,(m[0]<<8|m[1]).toString(16),(m[2]<<8|m[3]).toString(16))}return c.some(m=>!/^[0-9a-f]{1,4}$/.test(m))?null:c.map(m=>Number.parseInt(m,16))},[n,o]=t.split("::"),s=r(n),i=r(o);if(!s||!i)return null;let a=t.includes("::"),l=8-s.length-i.length;if(!a&&l!==0||a&&l<1)return null;let f=[...s,...Array(Math.max(0,l)).fill(0),...i];return f.length!==8?null:Uint8Array.from(f.flatMap(u=>[u>>8,u&255]))}function yt(e,t,r){let n=Math.floor(r/8),o=r%8;for(let i=0;i<n;i+=1)if(e[i]!==t[i])return!1;if(!o)return!0;let s=255<<8-o;return(e[n]&s)===(t[n]&s)}function wt(e){if(ge.isIPv4(e)){let t=e.split(".").map(Number);return!(t[0]===0||t[0]===10||t[0]===127||t[0]>=224||t[0]===100&&t[1]>=64&&t[1]<=127||t[0]===169&&t[1]===254||t[0]===172&&t[1]>=16&&t[1]<=31||t[0]===192&&(t[1]===0||t[1]===2||t[1]===168)||t[0]===192&&t[1]===88&&t[2]===99||t[0]===198&&(t[1]===18||t[1]===19||t[1]===51)||t[0]===203&&t[1]===0&&t[2]===113)}if(ge.isIPv6(e)){let t=Ke(e);if(!t)return!1;let r=Ke("::ffff:0:0");return yt(t,r,96)?wt([...t.slice(12)].join(".")):yt(t,Ke("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([o,s])=>yt(t,Ke(o),s)):!1}return!1}function En(e){let t;try{t=new URL(String(e))}catch{return{ok:!1,error:`not a valid URL: ${String(e).slice(0,120)}`}}if(t.protocol!=="http:"&&t.protocol!=="https:")return{ok:!1,error:`refused protocol ${t.protocol} (only http/https)`};let r=t.hostname.toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,"");if(bn.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=ge.isIP(r);return n!==0&&!wt(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function gt(e,{lookupFn:t=gn.promises.lookup}={}){let r=En(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:ge.isIPv6(r.host)?6:4}]};let n;try{n=await t(r.host,{all:!0,verbatim:!0})}catch{return{ok:!1,error:`refused: ${r.host} did not resolve`}}return!Array.isArray(n)||n.length===0||n.some(o=>!wt(o.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}async function bt({requireUndici:e=!1,importUndici:t=()=>import("undici")}={}){let r,n;try{let c=await t();r=c.Agent,n=c.fetch}catch(c){if(e)throw new Error(`egress-guard: untrustedUrl pinning requires the undici package, which failed to load: ${c?.message||c}`);return null}if(typeof r!="function"||typeof n!="function"){if(e)throw new Error("egress-guard: untrustedUrl pinning requires undici's Agent and fetch exports, which were not found on the imported module");return null}let o=c=>String(c).toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,""),s=new Map,i=c=>(Array.isArray(c)?c:[c]).map(d=>typeof d=="string"?{address:d}:d).filter(d=>d&&d.address).map(d=>({address:d.address,family:d.family||(ge.isIPv6(d.address)?6:4)})),a=(c,d,m)=>{s.set(o(c),i(typeof d=="string"?[{address:d,family:m}]:d))},l=c=>{let d=o(c);if(ge.isIP(d))return[{address:d,family:ge.isIPv6(d)?6:4}];let m=s.get(d);if(!m||!m.length)throw new Error(`refused: unpinned host ${c} during pinned fetch`);return m},f=new r({connect:{lookup(c,d,m){let p;try{p=l(c)}catch(w){return m(w)}return d?.all?m(null,p):m(null,p[0].address,p[0].family)}}}),u=xn((c,d={})=>n(c,{...d,dispatcher:f}),a);return{dispatcher:f,fetch:u,pin:a,resolve:l,async close(){try{await f.destroy()}catch{}}}}var Et=Symbol.for("oracle.egressGuard.pinCapableFetch");function xn(e,t){if(typeof e!="function")throw new Error("markPinCapableFetch: fetchImpl must be a function");if(typeof t!="function")throw new Error("markPinCapableFetch: pin must be a function");return e[Et]=Object.freeze({pin:t}),e}function xt(e){return typeof e=="function"&&typeof e[Et]?.pin=="function"}function fr(e,t,r){if(!xt(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[Et].pin(t,r)}var kn=new Set([408,425,429,500,502,503,504]),dr=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),Tn=2,pr=4e3,An=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"aborted")?.get,On=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"reason")?.get,Pn=AbortSignal.prototype.throwIfAborted,$n=EventTarget.prototype.addEventListener,mr=typeof AbortSignal.any=="function"?AbortSignal.any.bind(AbortSignal):null,Tt=e=>e?An.call(e):!1,In=e=>e?On.call(e):void 0,_n=new Set([301,302,303,307,308]),We=3,di=64*1024,ce=Object.freeze({depth:32,nodes:1e4,fields:1e4,arrayLength:1e4,bytes:1024*1024});function V(e){return pe(`HTTP JSON body refused: ${e}`)}function vn(e){return["isArgumentsObject","isArrayBuffer","isAnyArrayBuffer","isArrayBufferView","isBoxedPrimitive","isDataView","isDate","isExternal","isGeneratorObject","isKeyObject","isCryptoKey","isMap","isMapIterator","isModuleNamespaceObject","isNativeError","isPromise","isRegExp","isSet","isSetIterator","isTypedArray","isWeakMap","isWeakSet"].some(t=>typeof le[t]=="function"&&le[t](e))}function jn(e){let t=[],r=0,n=0,o=0,s=0,i=new WeakSet,a=u=>{if(r+=Buffer.byteLength(u,"utf8"),r>ce.bytes)throw V("serialized byte limit exceeded");t.push(u)},l=u=>{if(Buffer.byteLength(u,"utf8")>ce.bytes)throw V("serialized byte limit exceeded");return JSON.stringify(u)},f=(u,c)=>{if(n+=1,n>ce.nodes)throw V("node limit exceeded");if(c>ce.depth)throw V("depth limit exceeded");if(u===null){a("null");return}if(typeof u=="string"){a(l(u));return}if(typeof u=="boolean"){a(u?"true":"false");return}if(typeof u=="number"){if(!Number.isFinite(u))throw V("non-finite number");a(Object.is(u,-0)?"0":String(u));return}if(typeof u!="object")throw V("unsupported non-JSON value");if(le.isProxy(u))throw V("proxy value");if(vn(u))throw V("unsupported exotic object");if(i.has(u))throw V("cyclic value");i.add(u);try{if(Object.getOwnPropertySymbols(u).length>0)throw V("symbol-keyed fields are unsupported");if(Array.isArray(u)){let p=Object.getPrototypeOf(u),w=0;for(;p!==null;){if(le.isProxy(p))throw V("proxy array prototype");if(w+=1,w>ce.depth)throw V("array prototype depth limit exceeded");p=Object.getPrototypeOf(p)}if(u.length>ce.arrayLength)throw V("array length limit exceeded");for(let S=0;S<u.length;S+=1){let v=Object.getOwnPropertyDescriptor(u,String(S));if(!v||!Object.hasOwn(v,"value")||v.enumerable!==!0)throw V("array entries must be dense enumerable own data")}let x=0;for(let S in u){if(s+=1,s>ce.fields)throw V("enumeration limit exceeded");if(Object.hasOwn(u,S)&&(x+=1,x>u.length))throw V("named array fields are unsupported")}if(x!==u.length)throw V("array entries must be dense enumerable own data");a("[");for(let S=0;S<u.length;S+=1)S&&a(","),f(Object.getOwnPropertyDescriptor(u,String(S)).value,c+1);a("]");return}let d=Object.getPrototypeOf(u);if(d!==Object.prototype&&d!==null)throw V("non-plain object");let m=[];for(let p in u){if(s+=1,s>ce.fields)throw V("enumeration limit exceeded");if(!Object.hasOwn(u,p))continue;if(o+=1,o>ce.fields)throw V("field limit exceeded");let w=Object.getOwnPropertyDescriptor(u,p);if(!w||!Object.hasOwn(w,"value")||w.enumerable!==!0)throw V("object fields must be enumerable own data");m.push([p,w.value])}a("{");for(let p=0;p<m.length;p+=1)p&&a(","),a(l(m[p][0])),a(":"),f(m[p][1],c+1);a("}")}finally{i.delete(u)}};return f(e,0),t.join("")}function Nn(e){let t=Object.create(null);if(e==null)return t;if(typeof e!="object"&&typeof e!="function")throw new TypeError("HTTP headers must be an object");if(le.isProxy(e))throw new TypeError("HTTP headers must not be a proxy");if(Object.getOwnPropertySymbols(e).length>0)throw new TypeError("HTTP headers must not contain symbol fields");let r=new Set;for(let n of Object.keys(e)){if(!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/u.test(n))throw new TypeError("HTTP header names must be valid tokens");let o=n.toLowerCase();if(r.has(o))throw new TypeError("HTTP headers contain a duplicate canonical name");r.add(o);let s=Object.getOwnPropertyDescriptor(e,n);if(!s||!Object.hasOwn(s,"value"))throw new TypeError("HTTP headers must contain own data properties");let i=s.value;if(i==null||["object","function","symbol"].includes(typeof i))throw new TypeError("HTTP header values must be scalar");t[n]=String(i)}return t}function Rn(){return Object.assign(Object.create(null),{Accept:"application/json"})}function Mn(e,t){if(!e)throw new Error(`HTTP redirect from ${t} missing Location`);let r=new URL(String(e),String(t));if(r.protocol!=="http:"&&r.protocol!=="https:")throw new Error(`HTTP redirect from ${t} used unsupported protocol ${r.protocol}`);return r.toString()}function Ln(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}var St=new Map,hr=new WeakMap,yr=1;function Ye(e){if((typeof e!="object"||e===null)&&typeof e!="function")return`${typeof e}:${String(e)}`;let t=hr.get(e);return t||(t=yr,yr+=1,hr.set(e,t)),`reference:${t}`}var Hn=new Set(["eth_blockNumber","eth_call","eth_chainId","eth_estimateGas","getHealth","minimumLedgerSlot","net_version","simulateTransaction","web3_clientVersion"]),Fn=new Set(["allMids","l2Book","outcomeMeta","spotClearinghouseState","userFills","meta","metaAndAssetCtxs","perpDexs","candleSnapshot","fundingHistory","openOrders","frontendOpenOrders","clearinghouseState","spotMeta","validatorSummaries","delegatorSummary","delegations","delegatorRewards","delegatorHistory","maxBuilderFee"]);function wr(e){if(!e||typeof e!="object"||Array.isArray(e)||!Object.hasOwn(e,"jsonrpc")||!Object.hasOwn(e,"method")||e.jsonrpc!=="2.0")return!1;let t=typeof e.method=="string"?e.method:"";return t?Hn.has(t)||/^get[A-Z0-9_]/u.test(t)||/^is[A-Z0-9_]/u.test(t)||/^eth_get[A-Z0-9_]/u.test(t):!1}function gr(e,t){if(e==="GET"&&t==null)return!0;if(e!=="POST"||t==null)return!1;let r=t;if(typeof t=="string")try{r=JSON.parse(t)}catch{return!1}if(Array.isArray(r))return r.length>0&&r.every(wr);if(!r||typeof r!="object")return!1;if(Object.hasOwn(r,"jsonrpc")||Object.hasOwn(r,"method"))return wr(r);let n=Object.hasOwn(r,"type")?r.type:null;return typeof n=="string"&&Fn.has(n)&&(!Object.hasOwn(r,"action")||r.action==null)&&(!Object.hasOwn(r,"signature")||r.signature==null)&&(!Object.hasOwn(r,"nonce")||r.nonce==null)}function Cn(e,t,r,n={},o=null){let s=Sn("sha256"),i=(l,f)=>{let u=String(f);s.update(String(Buffer.byteLength(l,"utf8"))).update(":").update(l),s.update("=").update(String(Buffer.byteLength(u,"utf8"))).update(":").update(u).update(`
2
+ `)};i("method",e),i("url",t),Object.keys(r||{}).map((l,f)=>({name:l.toLowerCase(),order:f,value:String(r[l])})).sort((l,f)=>l.name.localeCompare(f.name)||l.order-f.order).forEach((l,f)=>{i(`header-name-${f}`,l.name),i(`header-value-${f}`,l.value)}),i("body",o??"-");for(let l of["untrustedUrl","maxResponseBytes","sameOriginRedirectsOnly","redirectPolicy","maxRedirects","timeoutMs","retries","fetchImpl","realFetch","lookupFn","importUndici","validateResponse"])i(`context-${l}`,n[l]??"-");return s.digest("hex")}function Dn(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,pr):Math.min(250*2**e,pr)+Math.floor(Math.random()*100)}var Un=e=>new Promise(t=>setTimeout(t,e));function pe(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function kt(e,t,r){return pe(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function be(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function qn(e){return e?e.byteLength??e.length??0:0}async function Bn(e,t,{url:r,truncate:n=!1,onOversize:o}={}){if(t==null)return await e.text();let s=Number(e.headers?.get?.("content-length"));if(Number.isFinite(s)&&s>t&&(be(e),!n))throw kt(r,`content-length ${s}`,t);let i=e.body?.getReader?.();if(!i){let c=await e.text(),d=Buffer.byteLength(c,"utf8");if(d>t){if(!n)throw kt(r,`body ${d} bytes`,t);return Buffer.from(c,"utf8").subarray(0,t).toString("utf8")}return c}let a=[],l=0,f=!1;try{for(;;){let{value:c,done:d}=await i.read();if(d)break;if(c&&(a.push(Buffer.from(c)),l+=qn(c),l>t)){f=!0;break}}}finally{if(f)try{await i.cancel()}catch{}try{i.releaseLock?.()}catch{}}if(f&&(typeof o=="function"&&o(),!n))throw kt(r,`streamed ${l} bytes`,t);let u=Buffer.concat(a);return(f?u.subarray(0,t):u).toString("utf8")}function zn(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function Vn(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:s,lookupFn:i,realFetch:a,untrustedUrl:l=!1,maxResponseBytes:f=null,sameOriginRedirectsOnly:u=!1,importUndici:c,validateResponse:d,signal:m,redirectPolicy:p="follow",maxRedirects:w=We}){let x=new AbortController,S=setTimeout(()=>x.abort(),s),v=m?mr?mr([m,x.signal]):m:x.signal,k=null,E=t,R=i?{lookupFn:i}:{};if(l&&!a&&!xt(E))throw pe(`HTTP refused ${e}: untrustedUrl requires a pin-capable fetchImpl (see markPinCapableFetch in egress-guard.mjs) or no fetchImpl override so Oracle can pin the connection itself`);let P=async(h,{status:M=null}={})=>{let D=await gt(h,R);if(!D.ok)throw pe(M==null?`HTTP refused ${h}: ${D.error}`:`HTTP redirect to ${h} ${D.error}`,M==null?{}:{status:M});let Y=new URL(h).hostname;if(a){if(k&&(await k.close(),k=null),!k)try{k=await bt({requireUndici:!0,...c?{importUndici:c}:{}})}catch(T){throw pe(M==null?`HTTP refused ${h}: ${T?.message||T}`:`HTTP redirect to ${h} refused: ${T?.message||T}`,M==null?{}:{status:M})}k.pin(Y,D.addresses),E=k.fetch}else fr(E,Y,D.addresses);return D};try{let h=String(e),M=Object.assign(Object.create(null),n||{});l&&await P(h);for(let D=0;D<=w;D+=1){let Y=Object.assign(Object.create(null),{method:r,headers:M,body:o,signal:v,redirect:"manual",dispatcher:void 0}),T=await E(h,Y);if((p==="error"||w===0)&&T.status>=300&&T.status<400)throw be(T),pe(`HTTP ${T.status} ${r} redirect refused`,{status:T.status,redirectRefused:!0});if(_n.has(T.status)){let _=u===!0&&r==="POST"&&[307,308].includes(T.status)&&gr(r,o);if(r!=="GET"&&r!=="HEAD"&&!_){be(T);let O=new Error(`HTTP ${T.status} ${r} ${h} redirected non-idempotent request`);throw O.status=T.status,O}if(D===w)throw be(T),pe(`HTTP ${T.status} ${r} redirect budget exhausted`,{status:T.status,redirectRefused:!0});let C=T.headers?.get?.("location"),L;try{L=Mn(C,h)}catch(O){throw be(T),O}let j=!Ln(L,h);if(be(T),j&&r==="POST"){let O=new Error(`HTTP ${T.status} ${r} cross-origin redirect refused`);throw O.status=T.status,O}if(j&&u){let O=new Error(`HTTP ${T.status} ${r} cross-origin redirect refused`);throw O.status=T.status,O.retryable=!1,O}if(j&&(M=Rn(M)),l)await P(L,{status:T.status});else if(j){let O=await gt(L,R);if(!O.ok){let N=new Error(`HTTP redirect from ${h} ${O.error}`);throw N.status=T.status,N.retryable=!1,N}a&&O.addresses?.length&&(k||(k=await bt(c?{importUndici:c}:{})),k&&(k.pin(new URL(L).hostname,O.addresses),E=k.fetch))}h=L;continue}if(typeof d=="function")try{await d(T,{url:h})}catch(_){throw be(T),pe(_?.message||String(_))}let y=await Bn(T,f,{url:h,onOversize:()=>x.abort()}),$=zn(y);if(!T.ok){let _=new Error(`HTTP ${T.status} ${r} ${h}`);throw _.status=T.status,_.retryAfter=T.headers?.get?.("retry-after")??null,_.body=$??y.slice(0,300),_}return $??y}throw new Error(`HTTP redirect loop for ${e}`)}catch(h){if(x.signal.aborted&&!Tt(m)){let M=h&&(typeof h=="object"||typeof h=="function")&&!le.isProxy(h)?h:null,D=M?Object.getOwnPropertyDescriptor(M,"oversize"):null;if(!(D&&Object.hasOwn(D,"value")&&D.value===!0))try{if(!M)throw new TypeError("unsafe rejection");Object.defineProperties(M,{oracleTimeout:{value:!0,enumerable:!1},retryable:{value:!1,enumerable:!1}})}catch{let T=new Error("HTTP request timed out");throw Object.defineProperties(T,{oracleTimeout:{value:!0,enumerable:!1},retryable:{value:!1,enumerable:!1}}),T}}throw h}finally{clearTimeout(S),k&&await k.close()}}async function br(e,t={}){if(t!=null&&typeof t!="object"&&typeof t!="function")throw new TypeError("HTTP options must be an object");if(t!=null&&le.isProxy(t))throw new TypeError("HTTP options must not be a proxy");let r=new Set(["body","dedupe","fetchImpl","headers","importUndici","lookupFn","maxRedirects","maxResponseBytes","method","redirectPolicy","retries","sameOriginRedirectsOnly","signal","timeoutMs","untrustedUrl","validateResponse"]);if(t!=null){if(Object.getOwnPropertySymbols(t).length>0)throw new TypeError("HTTP options contain unknown fields");for(let N of Object.getOwnPropertyNames(t)){let I=Object.getOwnPropertyDescriptor(t,N);if(!(N==="toJSON"&&I&&Object.hasOwn(I,"value")&&I.value===void 0)){if(!r.has(N))throw new TypeError("HTTP options contain unknown fields");if(!I||!I.enumerable||!Object.hasOwn(I,"value"))throw new TypeError("HTTP options must contain enumerable own data properties")}}}let n=N=>{if(t==null||!Object.hasOwn(t,N))return;let I=Object.getOwnPropertyDescriptor(t,N);if(!I||!Object.hasOwn(I,"value"))throw new TypeError("HTTP options must contain own data properties");return I.value};if(typeof e!="string"||e.length===0||e.length>8192)throw new TypeError("HTTP URL must be a bounded string");let o=n("method");if(o!==void 0&&(typeof o!="string"||!/^[A-Za-z]+$/u.test(o)))throw new TypeError("HTTP method must be a string token");let s=n("timeoutMs");if(s!==void 0&&(!Number.isInteger(s)||s<1||s>12e4))throw new TypeError("HTTP timeoutMs must be a bounded integer");let i=n("retries");if(i!==void 0&&(!Number.isInteger(i)||i<0||i>10))throw new TypeError("HTTP retries must be a bounded integer");let a=n("redirectPolicy");if(a!==void 0&&a!=="follow"&&a!=="error")throw new TypeError('HTTP redirectPolicy must be "follow" or "error"');let l=n("maxRedirects");if(l!==void 0&&(!Number.isInteger(l)||l<0||l>We))throw new TypeError(`HTTP maxRedirects must be an integer from 0 through ${We}`);if(a==="error"&&l!==void 0&&l!==0)throw new TypeError('HTTP redirectPolicy "error" requires maxRedirects 0 when supplied');let f=a??"follow",u=f==="error"?0:l??We;for(let N of["dedupe","untrustedUrl","sameOriginRedirectsOnly"]){let I=n(N);if(I!==void 0&&typeof I!="boolean")throw new TypeError(`HTTP ${N} must be boolean`)}let c=n("maxResponseBytes");if(c!==void 0&&(!Number.isInteger(c)||c<1||c>64*1024*1024))throw new TypeError("HTTP maxResponseBytes must be a bounded integer");let d=n("signal");if(d!==void 0){if(le.isProxy(d)||!(d instanceof AbortSignal))throw new TypeError("HTTP signal must be a native AbortSignal");try{Tt(d)}catch{throw new TypeError("HTTP signal must be a native AbortSignal")}}for(let N of["importUndici","lookupFn","validateResponse"]){let I=n(N);if(I!==void 0&&typeof I!="function")throw new TypeError(`HTTP ${N} must be a function`)}let m=n("fetchImpl"),p=m||globalThis.fetch;if(typeof p!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let w=s??12e3,x=(o||"GET").toUpperCase(),S=n("headers"),v=Nn(S),k=Object.assign(Object.create(null),v);Object.keys(k).some(N=>N.toLowerCase()==="accept")||(k.Accept="application/json");let E=n("body");E!=null&&typeof E!="string"&&(Object.keys(k).find(I=>I.toLowerCase()==="content-type")||(k["Content-Type"]="application/json"),E=jn(E));let R=i??Tn,P=n("lookupFn"),h=!m,M=n("untrustedUrl")===!0,D=n("sameOriginRedirectsOnly")===!0,Y=n("importUndici"),T=n("validateResponse"),y=d,$=c??null,_=async()=>{let N;for(let I=0;I<=R;I++){y&&Pn.call(y);try{return await Vn(e,{fetchImpl:p,method:x,headers:k,body:E,timeoutMs:w,lookupFn:P,realFetch:h,untrustedUrl:M,maxResponseBytes:$,sameOriginRedirectsOnly:D,importUndici:Y,validateResponse:T,signal:y,redirectPolicy:f,maxRedirects:u})}catch(G){N=G;let ee=Ae=>{if(!G||typeof G!="object"&&typeof G!="function"||le.isProxy(G))return;let we=Object.getOwnPropertyDescriptor(G,Ae);return we&&Object.hasOwn(we,"value")?we.value:void 0},de=ee("status"),Te=ee("oracleTimeout")===!0||ee("name")==="AbortError"||ee("name")==="TimeoutError"||Tt(y),Ve=new Set([408,425,429]),Je=ee("retryable")===!1?!1:de!=null?Ve.has(de)||kn.has(de)&&dr.has(x):!Te&&dr.has(x);if(I===R||!Je)throw G;let ut=Dn(I,ee("retryAfter"));y?await new Promise((Ae,we)=>{let Ge=setTimeout(Ae,ut);$n.call(y,"abort",()=>{clearTimeout(Ge),we(In(y)||new DOMException("Aborted","AbortError"))},{once:!0})}):await Un(ut)}}throw N};if(!(n("dedupe")!==!1&&!y&&gr(x,E)))return _();let L=Cn(x,e,k,{untrustedUrl:M,maxResponseBytes:$,sameOriginRedirectsOnly:D,redirectPolicy:f,maxRedirects:u,timeoutMs:w,retries:R,fetchImpl:Ye(p),realFetch:h,lookupFn:Ye(P),importUndici:Ye(Y),validateResponse:Ye(T)},E),j=St.get(L);if(j)return j;let O=_().finally(()=>St.delete(L));return St.set(L,O),O}import{types as Er}from"node:util";function Jn(e){if(!e||typeof e!="object"||Er.isProxy(e)||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Ze(e,t="provider response",r=0){if(r>64)throw new Error(`${t} exceeds the JSON nesting bound`);if(e===null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))return e;if(Array.isArray(e)){if(Er.isProxy(e)||e.length>1e5)throw new Error(`${t} contains an invalid array`);let o=new Array(e.length);for(let s=0;s<e.length;s+=1){let i=Object.getOwnPropertyDescriptor(e,String(s));if(!i||!Object.hasOwn(i,"value"))throw new Error(`${t} arrays must contain dense own data`);o[s]=Ze(i.value,t,r+1)}return o}if(!Jn(e))throw new Error(`${t} contains a non-JSON value`);let n=Object.create(null);for(let o of Object.keys(e)){let s=Object.getOwnPropertyDescriptor(e,o);if(!s||!Object.hasOwn(s,"value"))throw new Error(`${t} objects must contain own data`);n[o]=Ze(s.value,t,r+1)}return n}var Gn="https://api.hyperliquid.xyz/info",Kn="https://api.hyperliquid-testnet.xyz/info";function Yn({testnet:e,baseUrl:t}={}){if(t)return t.replace(/\/$/,"").endsWith("/info")?t:`${t.replace(/\/$/,"")}/info`;if(process.env.HL_INFO_URL)return process.env.HL_INFO_URL;if(process.env.HL_API_URL){let r=process.env.HL_API_URL.replace(/\/$/,"");return r.endsWith("/info")?r:`${r}/info`}return e||process.env.HL_TESTNET==="1"?Kn:Gn}async function Le(e,t={}){if(!e||!e.type)throw new Error("hlInfo requires body.type");let r=Yn(t);return Ze(await br(r,{method:"POST",body:e,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs,maxResponseBytes:t.maxResponseBytes,sameOriginRedirectsOnly:t.sameOriginRedirectsOnly}),"hyperliquid info response")}async function xr(e,t={}){if(!e)throw new Error("hlL2Book requires coin");return Le({type:"l2Book",coin:String(e)},t)}async function Sr(e={}){return Le({type:"meta"},e)}async function kr(e={}){let t={type:"metaAndAssetCtxs"};return e.dex&&(t.dex=e.dex),Le(t,e)}async function Tr({coin:e,interval:t="1h",startTime:r,endTime:n},o={}){if(!e)throw new Error("hlCandleSnapshot requires coin");let s={type:"candleSnapshot",req:{coin:String(e),interval:t,startTime:r??Date.now()-24*3600*1e3,endTime:n??Date.now()}};return Le(s,o)}async function Ar({coin:e,startTime:t,endTime:r},n={}){if(!e)throw new Error("hlFundingHistory requires coin");return Le({type:"fundingHistory",coin:String(e),startTime:t??Date.now()-24*3600*1e3,endTime:r??Date.now()},n)}function Fe(e){if(!Array.isArray(e))throw new TypeError("values must be an array");for(let t=0;t<e.length;t++){let r=e[t];if(typeof r!="number"||!Number.isFinite(r))throw new TypeError(`values[${t}] must be a finite number`)}}function me(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("period must be a positive integer")}function Wn(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");for(let t=0;t<e.length;t++){let r=e[t];if(r==null||typeof r!="object")throw new TypeError(`bars[${t}] must be an object`);for(let n of["o","h","l","c"]){let o=r[n];if(typeof o!="number"||!Number.isFinite(o))throw new TypeError(`bars[${t}].${n} must be a finite number`)}if(r.h<r.l)throw new TypeError(`bars[${t}] high must be >= low`)}}function At(e,t){Fe(e),me(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=0;for(let o=0;o<e.length;o++)n+=e[o],o>=t&&(n-=e[o-t]),o>=t-1&&(r[o]=n/t);return r}function He(e,t){Fe(e),me(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=0;for(let i=0;i<t;i++)n+=e[i];let o=n/t;r[t-1]=o;let s=2/(t+1);for(let i=t;i<e.length;i++)o=s*e[i]+(1-s)*o,r[i]=o;return r}function Ot(e,t){Fe(e),me(t);let r=new Array(e.length).fill(null);if(e.length<=t)return r;let n=0,o=0;for(let a=1;a<=t;a++){let l=e[a]-e[a-1];l>=0?n+=l:o-=l}let s=n/t,i=o/t;r[t]=Or(s,i);for(let a=t+1;a<e.length;a++){let l=e[a]-e[a-1],f=l>0?l:0,u=l<0?-l:0;s=(s*(t-1)+f)/t,i=(i*(t-1)+u)/t,r[a]=Or(s,i)}return r}function Or(e,t){return e===0&&t===0?50:t===0?100:e===0?0:100-100/(1+e/t)}function Pt(e,t={}){Fe(e);let r=t.fastPeriod,n=t.slowPeriod,o=t.signalPeriod;if(me(r),me(n),me(o),r>=n)throw new TypeError("fastPeriod must be < slowPeriod");let s=He(e,r),i=He(e,n),a=new Array(e.length).fill(null);for(let c=0;c<e.length;c++)s[c]!=null&&i[c]!=null&&(a[c]=s[c]-i[c]);let l=new Array(e.length).fill(null),f=new Array(e.length).fill(null),u=[];for(let c=0;c<a.length;c++)a[c]!=null&&u.push(c);if(u.length>=o){let c=0;for(let w=0;w<o;w++)c+=a[u[w]];let d=c/o,m=u[o-1];l[m]=d,f[m]=a[m]-d;let p=2/(o+1);for(let w=o;w<u.length;w++){let x=u[w];d=p*a[x]+(1-p)*d,l[x]=d,f[x]=a[x]-d}}return{line:a,signal:l,histogram:f}}function $t(e,t={}){Fe(e);let r=t.period,n=t.stdDev;if(me(r),typeof n!="number"||!Number.isFinite(n)||n<=0)throw new TypeError("stdDev must be a finite number > 0");let o=new Array(e.length).fill(null),s=new Array(e.length).fill(null),i=new Array(e.length).fill(null);if(e.length<r)return{upper:s,middle:o,lower:i};let a=0,l=0;for(let f=0;f<e.length;f++){let u=e[f];if(a+=u,l+=u*u,f>=r){let c=e[f-r];a-=c,l-=c*c}if(f>=r-1){let c=a/r,d=l/r-c*c;d<0&&d>-1e-12&&(d=0);let m=Math.sqrt(d);o[f]=c,s[f]=c+n*m,i[f]=c-n*m}}return{upper:s,middle:o,lower:i}}function It(e,t){Wn(e),me(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=new Array(e.length);for(let i=0;i<e.length;i++){let a=e[i];if(i===0)n[i]=a.h-a.l;else{let l=e[i-1].c;n[i]=Math.max(a.h-a.l,Math.abs(a.h-l),Math.abs(a.l-l))}}let o=0;for(let i=0;i<t;i++)o+=n[i];let s=o/t;r[t-1]=s;for(let i=t;i<e.length;i++)s=(s*(t-1)+n[i])/t,r[i]=s;return r}import{createHash as Zn}from"node:crypto";var _t=3,Xn="7477966facc4ef928a94e6221c8fd238eef4fcbeec46b96ae1b89178e13c2d5f",Qn="68f5b412a9975f04024cf9b9b6209b4bccedd52f176e95f34f786b3f53479c6a",eo="967fd45ecddd0d59ac0f662fe92ea813c32620ba751f249b4ace6cb6b809fb5e",Pr=Zn("sha256").update(JSON.stringify({version:_t,compilerSourceHash:Xn,indicatorsSourceHash:Qn,schemaSourceHash:eo})).digest("hex");var Pe=_t,he=Pr,to=Object.freeze({open:"o",high:"h",low:"l",close:"c",volume:"v",fundingRate:"fundingRate",openInterest:"openInterest",premium:"premium",oiDelta:"oiDelta",bookImbalance:"bookImbalance"}),ro=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5});function X(e){return typeof e=="number"&&Number.isFinite(e)}function no(e){let t=new Map(e.map(a=>[a.id,a])),r=a=>{switch(a.type){case"indicator":return a.input?[a.input]:[];case"compare":case"cross":return[a.left,a.right];case"logic":return[...a.inputs];default:return[]}},n=new Map,o=new Map;for(let a of e)n.set(a.id,0),o.set(a.id,[]);for(let a of e)for(let l of r(a))t.has(l)&&(o.get(l).push(a.id),n.set(a.id,n.get(a.id)+1));let s=[];for(let[a,l]of n)l===0&&s.push(a);let i=[];for(;s.length;){let a=s.shift();i.push(a);for(let l of o.get(a))n.set(l,n.get(l)-1),n.get(l)===0&&s.push(l)}if(i.length!==e.length)throw new Error("strategy graph is cyclic");return i}function Oe(e,t){return e!=null&&typeof e=="object"&&"param"in e?t[e.param].value:e}function oo(e,t,r){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");if(!Number.isInteger(t)||t<0||t>=e.length)throw new RangeError("index out of range");let n=null;for(let o=0;o<=t;o++){let s=e[o];if(s==null||typeof s!="object"||Array.isArray(s))throw new TypeError(`bars[${o}] must be an object`);let{t:i,o:a,h:l,l:f,c:u,v:c}=s;if(!X(i)&&(typeof i=="number"&&Number.isFinite(i)),!Number.isFinite(i))throw new TypeError(`bars[${o}].t must be finite`);for(let[d,m]of[["o",a],["h",l],["l",f],["c",u],["v",c]])if(!X(m))throw new TypeError(`bars[${o}].${d} must be a finite number`);for(let[d,m]of[["o",a],["h",l],["l",f],["c",u]])if(!(m>0))throw new TypeError(`bars[${o}].${d} price must be positive`);if(c<0)throw new TypeError(`bars[${o}].v volume must be non-negative`);if(l<Math.max(a,u,f))throw new TypeError(`bars[${o}] high must be >= max(open, close, low)`);if(f>Math.min(a,u,l))throw new TypeError(`bars[${o}] low must be <= min(open, close, high)`);if(n!=null){if(!(i>n))throw new TypeError("bars t must be strictly increasing");if(i-n!==ro[r])throw new TypeError(`bars t must match ${r} cadence`)}if(n=i,"fundingRate"in s&&s.fundingRate!=null&&!X(s.fundingRate))throw new TypeError(`bars[${o}].fundingRate must be finite when present`);if("openInterest"in s&&s.openInterest!=null){if(!X(s.openInterest))throw new TypeError(`bars[${o}].openInterest must be finite when present`);if(s.openInterest<0)throw new TypeError(`bars[${o}].openInterest must be non-negative`)}for(let d of["premium","oiDelta"])if(d in s&&s[d]!=null&&!X(s[d]))throw new TypeError(`bars[${o}].${d} must be finite when present`);if("bookImbalance"in s&&s.bookImbalance!=null){if(!X(s.bookImbalance))throw new TypeError(`bars[${o}].bookImbalance must be finite when present`);if(s.bookImbalance<-1||s.bookImbalance>1)throw new TypeError(`bars[${o}].bookImbalance must be within [-1, 1]`)}}}function Ee(e,t,r,n,o,s){if(s.has(e))return s.get(e);let i=t.get(e),a;switch(i.type){case"input":{let l=to[i.field];a=new Array(o+1);for(let f=0;f<=o;f++){let u=n[f][l];a[f]=u===void 0?null:u}break}case"constant":{let l=Oe(i.value,r);a=new Array(o+1).fill(l);break}case"indicator":{let l=i.period!=null?Oe(i.period,r):void 0;if(i.indicator==="atr"){let c=[];for(let d=0;d<=o;d++){let m=n[d];c.push({o:m.o,h:m.h,l:m.l,c:m.c})}a=It(c,l);break}let u=Ee(i.input,t,r,n,o,s).map((c,d)=>{if(c==null||!X(c))throw new TypeError(`indicator input ${i.input} has non-finite value at ${d}`);return c});if(i.indicator==="sma")a=At(u,l);else if(i.indicator==="ema")a=He(u,l);else if(i.indicator==="rsi")a=Ot(u,l);else if(i.indicator==="macd")a=Pt(u,{fastPeriod:Oe(i.fastPeriod,r),slowPeriod:Oe(i.slowPeriod,r),signalPeriod:Oe(i.signalPeriod,r)})[i.output];else if(i.indicator==="bollinger")a=$t(u,{period:l,stdDev:Oe(i.stdDev,r)})[i.output];else throw new Error(`unsupported indicator ${i.indicator}`);break}case"compare":{let l=Ee(i.left,t,r,n,o,s),f=Ee(i.right,t,r,n,o,s);a=new Array(o+1);for(let u=0;u<=o;u++){let c=l[u],d=f[u];if(c==null||d==null||!X(c)||!X(d)){a[u]=!1;continue}switch(i.op){case"gt":a[u]=c>d;break;case"gte":a[u]=c>=d;break;case"lt":a[u]=c<d;break;case"lte":a[u]=c<=d;break;case"eq":a[u]=c===d;break;default:a[u]=!1}}break}case"logic":{let l=i.inputs.map(f=>Ee(f,t,r,n,o,s));a=new Array(o+1);for(let f=0;f<=o;f++)if(i.op==="not"){let u=l[0][f];a[f]=u===!0?!1:u===!1}else if(i.op==="and"){let u=!0;for(let c of l)if(c[f]!==!0){u=!1;break}a[f]=u}else if(i.op==="or"){let u=!1;for(let c of l)if(c[f]===!0){u=!0;break}a[f]=u}else a[f]=!1;break}case"cross":{let l=Ee(i.left,t,r,n,o,s),f=Ee(i.right,t,r,n,o,s);a=new Array(o+1),a[0]=!1;for(let u=1;u<=o;u++){let c=l[u-1],d=f[u-1],m=l[u],p=f[u];if(c==null||d==null||m==null||p==null||!X(c)||!X(d)||!X(m)||!X(p)){a[u]=!1;continue}i.direction==="above"?a[u]=c<=d&&m>p:a[u]=c>=d&&m<p}break}default:throw new Error(`unknown node type ${i.type}`)}return s.set(e,a),a}function W(e,t={}){let r=Z(e);t&&Object.keys(t).length&&(r=$e(r,t));let n=new Map(r.nodes.map(m=>[m.id,m])),o=Object.freeze(no(r.nodes)),s=r.parameters,i=new Set(r.nodes.filter(m=>m.type==="input").map(m=>m.field));if(r.nodes.some(m=>m.type==="indicator"&&m.indicator==="atr"))for(let m of["open","high","low","close"])i.add(m);let a=Object.freeze([...i].sort()),l=xe(r);function f(m,p){let w={};for(let S of o){let v=m.get(S);w[S]=v[p]}let x=S=>S!=null&&w[S]===!0;return{values:w,signals:{entryLong:x(r.rules.entryLong),entryShort:x(r.rules.entryShort),exitLong:x(r.rules.exitLong),exitShort:x(r.rules.exitShort)}}}function u(m,p){oo(m,p,r.market.interval);let w=new Map;for(let x of o)Ee(x,n,s,m,p,w);return w}function c(m,p){return f(u(m,p),p)}function d(m){if(!Array.isArray(m)||m.length===0)throw new TypeError("bars must be a non-empty array");let p=m.length-1,w=u(m,p);return Object.freeze(m.map((x,S)=>Object.freeze(f(w,S))))}return Object.freeze({strategy:r,strategyHash:l,compilerVersion:Pe,compilerHash:he,requiredSeries:a,nodeOrder:o,evaluate:c,evaluateAll:d})}import{createHash as So}from"node:crypto";import{createHash as so}from"node:crypto";var io=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:100});function ao(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ne(e){return typeof e=="number"&&Number.isFinite(e)}function vt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)vt(t);return Object.freeze(e)}for(let t of Object.keys(e))vt(e[t]);return Object.freeze(e)}function Xe(e){if(Array.isArray(e))return e.map(Xe);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Xe(e[r]);return t}return e}function jt(e,t="result"){if(typeof e=="number"){if(!Number.isFinite(e))throw new Error(`non-finite backtest result at ${t}`);return}if(!(e==null||typeof e!="object")){if(Array.isArray(e)){e.forEach((r,n)=>jt(r,`${t}[${n}]`));return}for(let[r,n]of Object.entries(e))jt(n,`${t}.${r}`)}}function Ir(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");let t=null;for(let r=0;r<e.length;r++){let n=e[r];if(n==null||typeof n!="object"||Array.isArray(n))throw new TypeError(`bars[${r}] must be an object`);let{t:o,o:s,h:i,l:a,c:l,v:f}=n;if(!ne(o))throw new TypeError(`bars[${r}].t must be finite`);for(let[u,c]of[["o",s],["h",i],["l",a],["c",l],["v",f]])if(!ne(c))throw new TypeError(`bars[${r}].${u} must be a finite number`);for(let[u,c]of[["o",s],["h",i],["l",a],["c",l]])if(!(c>0))throw new TypeError(`bars[${r}].${u} price must be positive`);if(f<0)throw new TypeError(`bars[${r}].v volume must be non-negative`);if(i<Math.max(s,l,a))throw new TypeError(`bars[${r}] high must be >= max(open, close, low)`);if(a>Math.min(s,l,i))throw new TypeError(`bars[${r}] low must be <= min(open, close, high)`);if(t!=null&&!(o>t))throw new TypeError("bars t must be strictly increasing");if(t=o,"fundingRate"in n&&n.fundingRate!=null&&!ne(n.fundingRate))throw new TypeError(`bars[${r}].fundingRate must be finite when present`);if("fundingPaymentRate"in n&&n.fundingPaymentRate!=null&&!ne(n.fundingPaymentRate))throw new TypeError(`bars[${r}].fundingPaymentRate must be finite when present`);if("openInterest"in n&&n.openInterest!=null&&!ne(n.openInterest))throw new TypeError(`bars[${r}].openInterest must be finite when present`)}}function Ce(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");return e.length>0&&Ir(e),so("sha256").update(JSON.stringify(Xe(e)),"utf8").digest("hex")}function co(e){if(e==null&&(e={}),!ao(e))throw new TypeError("options must be a plain object");let t={...io},r=new Set(["initialEquityUsd","takerFeeBps","builderFeeBps","slippageBps","latencyBars","maxVolumeParticipationPct","nowMs"]);for(let n of Object.keys(e))if(!r.has(n))throw new TypeError(`unknown option "${n}"`);if("initialEquityUsd"in e){if(!ne(e.initialEquityUsd)||e.initialEquityUsd<=0)throw new TypeError("initialEquityUsd must be a positive finite number");t.initialEquityUsd=e.initialEquityUsd}for(let n of["takerFeeBps","builderFeeBps","slippageBps"])if(n in e){let o=e[n];if(!ne(o)||o<0)throw new TypeError(`${n} must be a finite number >= 0`);if(n==="slippageBps"?o>=1e4:o>1e4)throw new TypeError(`${n} exceeds its safe basis-point bound`);t[n]=o}if("latencyBars"in e){let n=e.latencyBars;if(!Number.isInteger(n)||n<1)throw new TypeError("latencyBars must be an integer >= 1");t.latencyBars=n}if("maxVolumeParticipationPct"in e){let n=e.maxVolumeParticipationPct;if(!ne(n)||n<=0||n>100)throw new TypeError("maxVolumeParticipationPct must be in (0,100]");t.maxVolumeParticipationPct=n}if("nowMs"in e){if(!Number.isInteger(e.nowMs))throw new TypeError("nowMs must be an integer epoch milliseconds");t.nowMs=e.nowMs}return t}function Qe(e){return e/1e4}function lo(e,t,r){let n=Qe(r);return t==="long"?e*(1+n):e*(1-n)}function uo(e,t,r){let n=Qe(r);return t==="long"?e*(1-n):e*(1+n)}function $r(e,t,r){let n=Math.abs(e)*Qe(t),o=Math.abs(e)*Qe(r);return{taker:n,builder:o,total:n+o}}function fo(e,t){let r=e*(t.positionSizePct/100)*t.maxLeverage;return Math.min(r,t.maxNotionalUsd)}function po(e,t,r){let n=r/100;return t==="long"?e*(1-n):e*(1+n)}function mo(e,t,r){let n=r/100;return t==="long"?e*(1+n):e*(1-n)}function ho(e,t,r,n){if(!(r>0))return t==="long"?0:Number.POSITIVE_INFINITY;let o=Math.min(.99,1/(2*r)+n/1e4);return t==="long"?e*(1-1/r)/(1-o):e*(1+1/r)/(1+o)}function yo(e,t,r){return t==="long"?e.l<=r:e.h>=r}function wo(e,t,r){return t==="long"?e.h>=r:e.l<=r}function go(e,t,r){return t==="long"?e.l<=r:e.h>=r}var bo=Object.freeze(["fundingRate","openInterest","premium","oiDelta","bookImbalance"]);function De(e,t){for(let r of e.requiredSeries)if(bo.includes(r)&&!t.every(n=>ne(n?.[r])))throw new Error(`strategy required series is absent: ${r}`)}function Eo(e){if(e.length<3)return 0;let t=[];for(let i=1;i<e.length;i++){let a=e[i-1].equity,l=e[i].equity;a>0&&t.push((l-a)/a)}if(t.length<2)return 0;let r=0;for(let i of t)r+=i;let n=r/t.length,o=0;for(let i of t)o+=(i-n)**2;let s=Math.sqrt(o/(t.length-1));return s>0?n/s:0}function xo(e){let t=-1/0,r=0;for(let n of e){let o=n.equity;if(o>t&&(t=o),t>0){let s=(t-o)/t*100;s>r&&(r=s)}}return r}function ue(e,t,r={}){let n=co(r);Ir(t);let o=Ce(t);n.nowMs!==void 0&&Z(e,{nowMs:n.nowMs});let s=W(e);if(De(s,t),n.nowMs!==void 0&&s.strategy.risk.expiresAt<=n.nowMs)throw new Error("strategy is expired: risk.expiresAt must be strictly greater than nowMs");let i=s.strategy.risk,a=s.evaluateAll(t),l=n.latencyBars,f=n.slippageBps,u=n.takerFeeBps,c=n.builderFeeBps,d=n.initialEquityUsd,m=0,p=0,w=0,x=0,S=0,v=[],k=[],E=[],R=[],P=[],h=null,M=0,D=null,Y=d,T=!1,y=0,$=0,_=[],C=new Array(t.length).fill(0);function L(b){_.push(b)}function j(b){let H=t[b].v*(n.maxVolumeParticipationPct/100);return Math.max(0,H-C[b])}function O(b){if(!h)return d;let H=h.side==="long"?(b-h.entryPrice)*h.qty:(h.entryPrice-b)*h.qty;return d+H}function N(b,H,A){let q=A.o,F=fo(d,i);if(!(F>0)||!(q>0))return;let B=lo(q,H,f),U=F/B,J=j(b),Re=B*J;if(U>J){E.push({kind:"entry",barIndex:b,time:A.t,side:H,requestedNotionalUsd:F,maxFillNotionalUsd:Re,reason:"volume_participation"});return}C[b]+=U;let re=Math.abs(B-q)*U,ae=$r(F,u,c);d-=ae.total,m+=ae.taker,p+=ae.builder,x+=re,S+=F,h={lifecycleEpoch:++$,side:H,entryBarIndex:b,entryReferencePrice:q,entryPrice:B,qty:U,notionalUsd:F,stop:po(B,H,i.stopLossPct),take:mo(B,H,i.takeProfitPct),liq:ho(B,H,i.maxLeverage,u+c),entryFees:ae.taker,entryBuilderFees:ae.builder,entrySlippageUsd:re,fundingAccrued:0}}function I(b,H,A,q){if(!h)return!1;let F=h.side,B=H,U=B;A!=="liquidation"&&q&&(U=uo(B,F,f));let J=h.qty,Re=J*U;if(A!=="liquidation"){let ur=j(b),wn=U*ur;if(J>ur)return E.push({kind:"exit",barIndex:b,time:t[b].t,side:F,requestedNotionalUsd:Re,maxFillNotionalUsd:wn,reason:"volume_participation",triggerReason:A}),!1;C[b]+=J}let re=$r(Re,u,c),ae=A==="liquidation"?0:Math.abs(U-B)*J,Me,ht;F==="long"?(Me=(B-h.entryReferencePrice)*J,ht=(U-h.entryPrice)*J):(Me=(h.entryReferencePrice-B)*J,ht=(h.entryPrice-U)*J),d+=ht,d-=re.total,m+=re.taker,p+=re.builder,x+=ae,S+=Re;let yn={side:F,entryBarIndex:h.entryBarIndex,entryTime:t[h.entryBarIndex].t,entryPrice:h.entryPrice,exitBarIndex:b,exitTime:t[b].t,exitPrice:U,exitReason:A,qty:J,notionalUsd:h.notionalUsd,grossPnlUsd:Me,feesUsd:h.entryFees+re.taker,builderFeesUsd:h.entryBuilderFees+re.builder,fundingUsd:h.fundingAccrued,slippageUsd:h.entrySlippageUsd+ae,netPnlUsd:Me-(h.entryFees+re.taker+h.entryBuilderFees+re.builder)-h.fundingAccrued-(h.entrySlippageUsd+ae)};return v.push(yn),A==="liquidation"&&k.push({barIndex:b,time:t[b].t,side:F,price:U,tradeIndex:v.length-1}),h=null,$+=1,y=b+1+(i.cooldownBars||0),!0}function G(b,H,A,q){let F=b+1;if(F>=t.length)return;_.some(U=>U.kind==="exit"&&U.side===H&&U.fillBar===F&&U.epoch===q)||L({kind:"exit",side:H,signalBar:b,fillBar:F,reason:A,epoch:q})}function ee(b){let H=_.filter(A=>A.fillBar===b);for(let A=_.length-1;A>=0;A--)_[A].fillBar===b&&_.splice(A,1);H.sort((A,q)=>{let F=B=>B.kind==="exit"?0:1;return F(A)-F(q)});for(let A of H)if(A.kind==="exit"){if(!h||h.side!==A.side||h.lifecycleEpoch!==A.epoch)continue;let q=A.reason||"rule";I(b,t[b].o,q,!0)||G(b,A.side,q,A.epoch)}else if(A.kind==="entry"){if(h||A.epoch!==$||b<y)continue;N(b,A.side,t[b])}}function de(b){if(!h)return;let H=t[b],A=H.fundingPaymentRate;if(A==null||!ne(A)||A===0)return;let q=Math.abs(h.qty*H.c),F=A*q;h.side==="long"?(d-=F,h.fundingAccrued+=F,w+=F):(d+=F,h.fundingAccrued-=F,w-=F)}function Te(b){if(!h)return;let H=t[b].o;(h.side==="long"?H<=h.liq:H>=h.liq)&&I(b,H,"liquidation",!1)}function Ve(b){if(!h)return;let H=t[b],A=h.side,q=go(H,A,h.liq),F=yo(H,A,h.stop),B=wo(H,A,h.take),U=J=>A==="long"?Math.min(J,H.o):Math.max(J,H.o);if(q){I(b,U(h.liq),"liquidation",!1);return}if(F&&B){I(b,U(h.stop),"stop_loss",!0)||G(b,A,"stop_loss",h.lifecycleEpoch);return}if(F){I(b,U(h.stop),"stop_loss",!0)||G(b,A,"stop_loss",h.lifecycleEpoch);return}B&&(I(b,h.take,"take_profit",!0)||G(b,A,"take_profit",h.lifecycleEpoch))}for(let b=0;b<t.length;b++){let H=Math.floor(t[b].t/864e5);H!==D&&(D=H,Y=O(t[b].o),T=!1),Te(b),ee(b),Ve(b),de(b),!T&&O(t[b].c)<=Y*(1-i.maxDailyLossPct/100)&&(T=!0,R.push({type:"daily_loss_limit",barIndex:b,time:t[b].t,message:"daily loss limit reached; new entries blocked for UTC day"}));let A=a[b].signals,q=b+l;if(h)(h.side==="long"&&A.exitLong===!0||h.side==="short"&&A.exitShort===!0)&&q<t.length&&(_.some(J=>J.kind==="exit"&&J.side===h.side&&J.fillBar===q&&J.epoch===h.lifecycleEpoch)||L({kind:"exit",side:h.side,signalBar:b,fillBar:q,reason:"rule",epoch:h.lifecycleEpoch}));else{let B=A.entryLong===!0,U=A.entryShort===!0;B&&U?R.push({type:"conflicting_entry_signals",barIndex:b,time:t[b].t,message:"conflicting entry signals; no position opened"}):!T&&(B||U)&&q<t.length&&b>=y&&L({kind:"entry",side:B?"long":"short",signalBar:b,fillBar:q,epoch:$})}let F=d;h&&(M+=1,F=O(t[b].c)),P.push({barIndex:b,time:t[b].t,equity:F,positionSide:h?h.side:null})}let Je=null;if(h){let b=t.length-1;if(I(b,t[b].c,"end_of_data",!0))P[b]={barIndex:b,time:t[b].t,equity:d,positionSide:null};else{let A=O(t[b].c);Je={side:h.side,entryBarIndex:h.entryBarIndex,entryTime:t[h.entryBarIndex].t,entryPrice:h.entryPrice,qty:h.qty,notionalUsd:h.notionalUsd,markPrice:t[b].c,markedEquityUsd:A},R.push({type:"open_position_at_end",barIndex:b,time:t[b].t,message:"end-of-data exit missed; position remains open and marked"})}}let Ae=(h?O(t[t.length-1].c):d)-n.initialEquityUsd,we=Ae/n.initialEquityUsd*100,Ge=0,ft=0,dt=0;for(let b of v)b.netPnlUsd>0?(Ge+=1,ft+=b.netPnlUsd):b.netPnlUsd<0&&(dt+=-b.netPnlUsd);let pt=v.length,pn=pt===0?0:Ge/pt,mt=0;dt>0?mt=ft/dt:ft>0&&(mt=1e12);let mn={netPnlUsd:Ae,netPnlPct:we,maxDrawdownPct:xo(P),winRate:pn,profitFactor:mt,tradeCount:pt,sharpe:Eo(P),turnoverUsd:S,exposurePct:M/t.length*100},hn={initialEquityUsd:n.initialEquityUsd,takerFeeBps:n.takerFeeBps,builderFeeBps:n.builderFeeBps,slippageBps:n.slippageBps,latencyBars:n.latencyBars,maxVolumeParticipationPct:n.maxVolumeParticipationPct},lr={barsHash:o,strategyHash:s.strategyHash,compilerHash:he,compilerVersion:Pe,config:hn,trades:v,equityCurve:P,metrics:mn,costs:{feesUsd:m,builderFeesUsd:p,fundingUsd:w,slippageUsd:x},liquidations:k,missedFills:E,openPositionAtEnd:Je,flags:R};return jt(lr),vt(Xe(lr))}var jr=Object.freeze(["fail","pass_paper_only","pass_live_eligible"]);function oe(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Ie(e){return typeof e=="number"&&Number.isFinite(e)}function Mt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Mt(t);return Object.freeze(e)}for(let t of Object.keys(e))Mt(e[t]);return Object.freeze(e)}function Se(e){if(Array.isArray(e))return e.map(Se);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Se(e[r]);return t}return e}function Nt(e){return{netPnlUsd:e.metrics.netPnlUsd,netPnlPct:e.metrics.netPnlPct,maxDrawdownPct:e.metrics.maxDrawdownPct,winRate:e.metrics.winRate,profitFactor:e.metrics.profitFactor,tradeCount:e.metrics.tradeCount,sharpe:e.metrics.sharpe,turnoverUsd:e.metrics.turnoverUsd,exposurePct:e.metrics.exposurePct}}function _r(e){return{feesUsd:e.costs.feesUsd,builderFeesUsd:e.costs.builderFeesUsd,fundingUsd:e.costs.fundingUsd,slippageUsd:e.costs.slippageUsd}}function ko(e){return(e.feesUsd||0)+(e.builderFeesUsd||0)+Math.max(0,e.fundingUsd||0)+(e.slippageUsd||0)}function To(e){let t=0;for(let r of e.trades)r.grossPnlUsd>0&&(t+=r.grossPnlUsd);return t}function Ao(e,t,r){return!(!e||e.tradeCount<Math.max(1,Math.min(r,3))||!(e.netPnlUsd>0)||!(e.profitFactor>1)||!(e.maxDrawdownPct<=t.maxDailyLossPct))}function Nr(e){if(!oe(e))throw new TypeError("evidence artifact must be a plain object");if(!jr.includes(e.status))throw new TypeError("evidence artifact status is invalid");for(let t of["strategyHash","compilerHash","barsHash"])if(typeof e[t]!="string"||!/^[0-9a-f]{64}$/.test(e[t]))throw new TypeError(`evidence artifact ${t} must be a sha256 hash`);if(!oe(e.split))throw new TypeError("evidence artifact split required");if(!Array.isArray(e.flags))throw new TypeError("evidence artifact flags must be an array");if(!oe(e.walkForward)||!Array.isArray(e.walkForward.windows))throw new TypeError("evidence artifact walkForward windows required");if(e.status==="pass_live_eligible"&&(!oe(e.train)||!oe(e.holdout)))throw new TypeError("live-eligible evidence artifact requires train and holdout facts");return Se({barsHash:e.barsHash,compilerHash:e.compilerHash,flags:e.flags.map(t=>Se(t)),holdout:e.holdout??null,split:e.split,status:e.status,strategyHash:e.strategyHash,train:e.train??null,walkForward:{passRate:e.walkForward.passRate,windowsRun:e.walkForward.windowsRun??e.walkForward.windows.length,windows:e.walkForward.windows.map(t=>({index:t.index,trainStartIndex:t.trainStartIndex,trainEndIndex:t.trainEndIndex,passed:t.passed,reason:t.reason,evalStartIndex:t.evalStartIndex,evalEndIndex:t.evalEndIndex,metrics:t.metrics}))}})}function Lt(e){return So("sha256").update(JSON.stringify(Nr(e)),"utf8").digest("hex")}function te(e,t,r=0){if(!Number.isInteger(e)||e<r)throw new Error(`${t} must be an integer >= ${r}`);return e}function Rt(e,t){if(!oe(e)||!oe(e.metrics))throw new Error(`${t} metrics required`);let r=te(e.tradeCount,`${t}.tradeCount`);if(e.metrics.tradeCount!==r)throw new Error(`${t} tradeCount contradicts metrics.tradeCount`);for(let n of["netPnlUsd","profitFactor","maxDrawdownPct"])if(!Ie(e.metrics[n]))throw new Error(`${t}.metrics.${n} must be finite`);if(e.metrics.maxDrawdownPct<0)throw new Error(`${t}.metrics.maxDrawdownPct must be >= 0`);return e.metrics}function Oo(e,{maxDailyLossPct:t}={}){let r=e.split,n=te(r.trainStartIndex,"split.trainStartIndex"),o=te(r.trainEndIndex,"split.trainEndIndex"),s=te(r.trainBarCount,"split.trainBarCount",1),i=te(r.holdoutStartIndex,"split.holdoutStartIndex"),a=te(r.holdoutEndIndex,"split.holdoutEndIndex"),l=te(r.holdoutBarCount,"split.holdoutBarCount",1);if(n!==0||o-n+1!==s||i!==o+1||a-i+1!==l)throw new Error("evidence split must be contiguous, chronological, and count-consistent");if(!Ie(r.trainFraction)||r.trainFraction<=0||r.trainFraction>=1)throw new Error("split.trainFraction must be in (0,1)");Rt(e.train,"train");let f=Rt(e.holdout,"holdout");if(f.tradeCount<1||f.netPnlUsd<=0||f.profitFactor<=1)throw new Error("live-eligible holdout metrics do not pass");if(Ie(t)&&f.maxDrawdownPct>t)throw new Error("live-eligible holdout drawdown exceeds strategy risk");if(e.flags.length>0)throw new Error("live-eligible evidence cannot contain failure flags");let u=e.walkForward,c=u.windows;if(c.length<1||u.windowsRun!==c.length)throw new Error("live-eligible walk-forward windowsRun must match nonempty windows");let d=0,m=-1;for(let w=0;w<c.length;w++){let x=c[w];if(!oe(x)||x.index!==w||typeof x.passed!="boolean")throw new Error("walk-forward windows must be ordered and structurally valid");let S=te(x.trainStartIndex,`walkForward.windows[${w}].trainStartIndex`),v=te(x.trainEndIndex,`walkForward.windows[${w}].trainEndIndex`),k=te(x.evalStartIndex,`walkForward.windows[${w}].evalStartIndex`),E=te(x.evalEndIndex,`walkForward.windows[${w}].evalEndIndex`);if(S!==0||v>=k||k>E||k<=m)throw new Error("walk-forward windows must be chronological and disjoint");if(m=E,x.passed){if(d+=1,x.reason!=="pass")throw new Error("passed walk-forward window reason must be pass");let R=Rt({metrics:x.metrics,tradeCount:x.metrics?.tradeCount},`walkForward.windows[${w}]`);if(R.tradeCount<1||R.netPnlUsd<=0||R.profitFactor<=1)throw new Error("passed walk-forward window metrics do not pass");if(Ie(t)&&R.maxDrawdownPct>t)throw new Error("passed walk-forward drawdown exceeds strategy risk")}else if(x.reason==="pass")throw new Error("failed walk-forward window cannot have pass reason")}let p=d/c.length;if(!Ie(u.passRate)||Math.abs(u.passRate-p)>Number.EPSILON||p<.6)throw new Error("walk-forward passRate contradicts concrete windows or is below live threshold")}function Ht(e,t={}){if(typeof e?.id!="string"||!/^[0-9a-f]{64}$/.test(e.id))throw new Error("evidence.id must be a sha256 evidence artifact hash");let r=Nr(e),n=Se({id:e.id,...r});if(JSON.stringify(Se(e))!==JSON.stringify(n))throw new Error("evidence artifact contains fields unbound from its deterministic identity");let o=Lt(e);if(e.id!==o)throw new Error("evidence.id does not match its deterministic artifact facts digest");return e.status==="pass_live_eligible"&&Oo(e,t),e}function et({strategy:e,bars:t,backtestOptions:r={},trainFraction:n=.7,walkForwardWindows:o=3,minTrades:s=10}={}){let i=[];if(!oe(e))throw new TypeError("strategy must be a plain object");if(!Array.isArray(t))throw new TypeError("bars must be an array");if(!oe(r))throw new TypeError("backtestOptions must be a plain object");if(!Ie(n)||n<=0||n>=1)throw new TypeError("trainFraction must be in (0,1)");if(!Number.isInteger(o)||o<1)throw new TypeError("walkForwardWindows must be a positive integer");if(!Number.isInteger(s)||s<0)throw new TypeError("minTrades must be an integer >= 0");let a=Z(e),l=xe(a),f=Ce(t),u=t.length,c=(j=[],O={})=>vr({status:"fail",strategy:a,sHash:l,barsHash:f,split:O.split||{trainStartIndex:0,trainEndIndex:-1,trainBarCount:0,holdoutStartIndex:0,holdoutEndIndex:-1,holdoutBarCount:0,trainFraction:n},train:O.train||null,holdout:O.holdout||null,walkForward:O.walkForward||{windows:[],passRate:0},flags:[...i,...j]});if(u<10)return c([{type:"insufficient_bars",message:"need at least 10 bars for evidence"}]);let d=Math.floor(u*n),m=d,p=u-m;if(d<5||p<3)return c([{type:"invalid_windowing",message:"train/holdout split too small",trainCount:d,holdoutCount:p}]);let w=t.slice(0,d),x=t.slice(m),S,v;try{S=ue(a,w,r),v=ue(a,x,r)}catch(j){return c([{type:"backtest_error",message:String(j.message||j)}])}let k={metrics:Nt(S),costs:_r(S),tradeCount:S.metrics.tradeCount},E={metrics:Nt(v),costs:_r(v),tradeCount:v.metrics.tradeCount},R={trainStartIndex:0,trainEndIndex:d-1,trainBarCount:d,holdoutStartIndex:m,holdoutEndIndex:u-1,holdoutBarCount:p,trainFraction:n},P=[],h=Math.floor(u/(o+1));if(h<3)i.push({type:"invalid_windowing",message:"walk-forward window size too small",wfSize:h});else for(let j=0;j<o;j++){let O=h*(j+1),N=O,I=Math.min(u,N+h);if(I-N<3||O<3){P.push({index:j,trainStartIndex:0,trainEndIndex:O-1,evalStartIndex:N,evalEndIndex:I-1,passed:!1,reason:"window_too_small",metrics:null});continue}let G=t.slice(N,I),ee;try{ee=ue(a,G,r)}catch{P.push({index:j,trainStartIndex:0,trainEndIndex:O-1,evalStartIndex:N,evalEndIndex:I-1,passed:!1,reason:"backtest_error",metrics:null});continue}let de=Nt(ee),Te=Ao(de,a.risk,s);P.push({index:j,trainStartIndex:0,trainEndIndex:O-1,evalStartIndex:N,evalEndIndex:I-1,passed:Te,reason:Te?"pass":"fail_metrics",metrics:de})}let M=P.filter(j=>j.passed).length,D=P.length===0?0:M/P.length,Y={windows:P,passRate:D,windowsRun:P.length};E.metrics.tradeCount===0&&k.metrics.tradeCount===0&&i.push({type:"no_trades",message:"no trades in train or holdout"}),E.metrics.tradeCount===0&&i.push({type:"absent_oos_trades",message:"holdout produced no trades"}),E.metrics.netPnlUsd<0&&i.push({type:"holdout_loss",message:"holdout netPnlUsd is negative"}),k.metrics.netPnlUsd>0&&E.metrics.netPnlUsd<0&&k.metrics.netPnlUsd>Math.abs(E.metrics.netPnlUsd)*.25?i.push({type:"overfit",message:"profitable train with losing holdout (OOS collapse)"}):k.metrics.netPnlUsd>0&&E.metrics.netPnlUsd>0&&E.metrics.netPnlUsd<k.metrics.netPnlUsd*.1&&k.metrics.tradeCount>=s&&i.push({type:"severe_oos_collapse",message:"holdout pnl collapsed vs train"});let T=ko(E.costs),y=To(v);y>0&&T>y&&i.push({type:"costs_exceed_gross",message:"holdout costs exceed gross gains"});let $=i.some(j=>["insufficient_bars","invalid_windowing","absent_oos_trades","holdout_loss","no_trades","severe_oos_collapse","backtest_error"].includes(j.type)),_=i.some(j=>j.type==="overfit"),C="fail";return E.metrics.tradeCount>=s&&E.metrics.netPnlUsd>0&&E.metrics.profitFactor>1&&E.metrics.maxDrawdownPct<=a.risk.maxDailyLossPct&&D>=.6&&!(y>0&&T>y)&&!_&&!i.some(j=>j.type==="severe_oos_collapse"||j.type==="invalid_windowing")?C="pass_live_eligible":!$&&E.metrics.tradeCount>0&&k.metrics.tradeCount>0&&Number.isFinite(E.metrics.netPnlUsd)?(C="pass_paper_only",E.metrics.tradeCount<s&&i.push({type:"undersampled",message:"holdout trades below minTrades"})):_&&E.metrics.tradeCount>0&&k.metrics.netPnlUsd>0?C="fail":E.metrics.tradeCount>0&&k.metrics.tradeCount>0&&!$?C="pass_paper_only":C="fail",E.metrics.netPnlUsd<0&&(C=C==="pass_live_eligible"?"fail":C==="pass_paper_only"?"pass_paper_only":"fail",C="fail"),vr({status:C,strategy:a,sHash:l,barsHash:f,split:R,train:k,holdout:E,walkForward:Y,flags:i})}function vr({status:e,strategy:t,sHash:r,barsHash:n,split:o,train:s,holdout:i,walkForward:a,flags:l}){let f={status:e,strategyHash:r,compilerHash:he,barsHash:n,split:o,train:s,holdout:i,walkForward:a,flags:l};return f.id=Lt(f),Mt(Se(JSON.parse(JSON.stringify(f))))}import{createHash as Po,createHmac as $o,timingSafeEqual as Li}from"node:crypto";var Io=2,_o=300*1e3,vo=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})();function Ft(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(Ft).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${Ft(e[r])}`).join(",")}}`}function Rr(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function Mr(e=process.env){return Rr(process.env)||Rr(e)}function jo(e){let{prepareHash:t,prepareMac:r,note:n,...o}=e||{};return o}function No(e){let t=jo(e);return Po("sha256").update(Ft(t)).digest("hex")}function Ro(e,t=Mr()){return t?$o("sha256",t).update(String(e)).digest("hex"):""}function Lr(e,{provider:t,kind:r,env:n=process.env,nowMs:o=Date.now(),expiresAtMs:s}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let i=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(i&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let a={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1,oraclePrepared:i?e.oraclePrepared:!0};if(!a.provider)throw new Error("stampPrepared: provider required");if(!a.kind)throw new Error("stampPrepared: kind required");let l=Number(o),f=s==null?l+_o:Number(s),u=f-l;if(!Number.isSafeInteger(l)||!Number.isSafeInteger(f)||u<=0||u>vo)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let d={...a,preparedAt:l,expiresAt:f,prepareVersion:Io},m=No(d),p=Mr(n),w=p?Ro(m,p):void 0,x={...d,prepareHash:m};return w&&(x.prepareMac=w),x}var Mo=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Ue(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Lo(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Dt(e,t="value"){if(Array.isArray(e)){e.forEach((r,n)=>Dt(r,`${t}[${n}]`));return}if(Ue(e))for(let[r,n]of Object.entries(e)){let o=Lo(r);if(Mo.some(s=>o.includes(s)))throw new Error(`handoff: forbidden secret-like field at ${t}.${r}`);Dt(n,`${t}.${r}`)}}function Ct(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function Ut({strategy:e,evidence:t,shadow:r,caps:n,nowMs:o=Date.now(),env:s=process.env}={}){if(Dt({strategy:e,evidence:t,shadow:r,caps:n},"handoff"),!Ue(e))throw new Error("handoff: strategy required");if(!Ue(t))throw new Error("handoff: evidence required");if(!Ue(r))throw new Error("handoff: shadow required");if(!Ue(n))throw new Error("handoff: caps required");if(typeof r.id!="string"||!r.id.trim())throw new Error("handoff: shadow.id required");if(typeof r.stateHash!="string"||!/^[0-9a-f]{64}$/.test(r.stateHash))throw new Error("handoff: shadow.stateHash must be a sha256 hash");if(r.status!=="running")throw new Error("handoff: shadow.status must be running");if(!Number.isInteger(r.cursor)||r.cursor<=0)throw new Error("handoff: shadow.cursor must be a positive integer");if(!Number.isInteger(r.updatedAt)||r.updatedAt<=0||r.updatedAt>o)throw new Error("handoff: shadow.updatedAt must be a positive integer <= nowMs");let i=Z(e,{nowMs:o}),a=W(i);if(Ht(t,{maxDailyLossPct:i.risk.maxDailyLossPct}),t.status!=="pass_live_eligible")throw new Error("handoff: evidence.status must be pass_live_eligible");if(t.strategyHash!==a.strategyHash)throw new Error("handoff: evidence.strategyHash mismatch");if(t.compilerHash!==a.compilerHash)throw new Error("handoff: evidence.compilerHash mismatch");let l=["perStrategyNotionalUsd","maxLeverage","dailyLossCapUsd","chainAllowlist","assetAllowlist","expiresAt","killSwitchRequired"];for(let d of l)if(!(d in n)||n[d]==null)throw new Error(`handoff: caps.${d} required`);if(!Ct(n.perStrategyNotionalUsd))throw new Error("handoff: caps.perStrategyNotionalUsd must be positive");if(n.perStrategyNotionalUsd>a.strategy.risk.maxNotionalUsd)throw new Error("handoff: caps.perStrategyNotionalUsd exceeds strategy.risk.maxNotionalUsd");if(!Ct(n.maxLeverage))throw new Error("handoff: caps.maxLeverage must be positive");if(n.maxLeverage>a.strategy.risk.maxLeverage)throw new Error("handoff: caps.maxLeverage exceeds strategy.risk.maxLeverage");if(!Ct(n.dailyLossCapUsd))throw new Error("handoff: caps.dailyLossCapUsd must be positive");let f=a.strategy.risk.maxNotionalUsd*(a.strategy.risk.maxDailyLossPct/100);if(n.dailyLossCapUsd>f)throw new Error("handoff: caps.dailyLossCapUsd exceeds strategy daily loss ceiling");if(!Array.isArray(n.chainAllowlist)||n.chainAllowlist.length===0)throw new Error("handoff: caps.chainAllowlist must be a non-empty array");if(!n.chainAllowlist.every(d=>d==="hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include only hyperliquid");if(!n.chainAllowlist.includes("hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include hyperliquid");if(!Array.isArray(n.assetAllowlist)||n.assetAllowlist.length===0)throw new Error("handoff: caps.assetAllowlist must be a non-empty array");if(n.assetAllowlist.length!==1||n.assetAllowlist[0]!==a.strategy.market.coin)throw new Error("handoff: caps.assetAllowlist must contain only the strategy market coin");if(!Number.isInteger(n.expiresAt)||!(n.expiresAt>o))throw new Error("handoff: caps.expiresAt must be an integer > nowMs");if(n.expiresAt>a.strategy.risk.expiresAt)throw new Error("handoff: caps.expiresAt exceeds strategy.risk.expiresAt");if(n.killSwitchRequired!==!0)throw new Error("handoff: caps.killSwitchRequired must be exactly true");let u={perStrategyNotionalUsd:n.perStrategyNotionalUsd,maxLeverage:n.maxLeverage,dailyLossCapUsd:n.dailyLossCapUsd,chainAllowlist:[...n.chainAllowlist],assetAllowlist:[...n.assetAllowlist],expiresAt:n.expiresAt,killSwitchRequired:!0},c={strategyHash:a.strategyHash,compilerHash:a.compilerHash,evidence:JSON.parse(JSON.stringify(t)),shadow:{id:r.id,stateHash:r.stateHash,status:r.status,cursor:r.cursor,updatedAt:r.updatedAt},compiled:{strategyHash:a.strategyHash,compilerHash:a.compilerHash,compilerVersion:Pe,venue:"hyperliquid",market:{coin:a.strategy.market.coin,kind:"perp",interval:a.strategy.market.interval},risk:{...a.strategy.risk},strategy:JSON.parse(JSON.stringify(a.strategy))},arming:{liveBroadcast:!1,requiresExplicitUserArm:!0,caps:u},requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,executionReady:!1};return Lr(c,{provider:"hl-strategy",kind:"strategy-live-handoff",env:s})}var Ho=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5});function _e(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function ve(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be a non-negative safe integer`);return e}function qe(e){if(Array.isArray(e))for(let t of e)qe(t);else if(e&&typeof e=="object")for(let t of Object.values(e))qe(t);return Object.freeze(e)}function Hr(e){let t=Ho[e];if(!t)throw new TypeError(`unsupported strategy interval: ${e}`);return t}function Fr(e,{endTime:t=Number.MAX_SAFE_INTEGER}={}){if(!Array.isArray(e))throw new TypeError("Hyperliquid candles must be an array");ve(t,"endTime");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`candles[${n}] must be an object`);let s=ve(Number(o.t),`candles[${n}].t`);if(ve(Number(o.T),`candles[${n}].T`)>t)continue;let a={t:s,o:_e(o.o,`candles[${n}].o`),h:_e(o.h,`candles[${n}].h`),l:_e(o.l,`candles[${n}].l`),c:_e(o.c,`candles[${n}].c`),v:_e(o.v,`candles[${n}].v`)};if(a.h<Math.max(a.o,a.c,a.l))throw new TypeError(`candles[${n}].h is below another price`);if(a.l>Math.min(a.o,a.c,a.h))throw new TypeError(`candles[${n}].l is above another price`);if(a.v<0)throw new TypeError(`candles[${n}].v must be non-negative`);let l=r.get(s);if(l&&JSON.stringify(l)!==JSON.stringify(a))throw new TypeError(`conflicting duplicate candle at timestamp ${s}`);l||r.set(s,a)}return qe([...r.values()].sort((n,o)=>n.t-o.t))}function Fo(e,t){if(!Array.isArray(e))throw new TypeError("Hyperliquid funding history must be an array");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`funding[${n}] must be an object`);let s=ve(Number(o.time),`funding[${n}].time`);s>t||r.set(s,{time:s,fundingRate:_e(o.fundingRate,`funding[${n}].fundingRate`)})}return[...r.values()].sort((n,o)=>n.time-o.time)}async function Co({coin:e,startTime:t,endTime:r},n){let o=[],s=Math.max(0,t-288e5),i=!1;for(let a=0;a<16&&s<=r;a++){let l=await Ar({coin:e,startTime:s,endTime:r},n);if(!Array.isArray(l))throw new TypeError("Hyperliquid funding history must be an array");o.push(...l);let f=s;for(let u of l){let c=Number(u?.time);Number.isSafeInteger(c)&&c>f&&(f=c)}if(l.length<500||f>=r){i=!0;break}if(f<=s)throw new Error("Hyperliquid funding history pagination did not advance");s=f+1}if(!i)throw new Error("strategy history exceeds the bounded funding history limit");return Fo(o,r)}function Do(e,t,r){let n=0,o=null;return e.map(s=>{let i=s.t+r,a=0;for(;n<t.length&&t[n].time<i;){let l=t[n];o=l.fundingRate,l.time>=s.t&&(a+=l.fundingRate),n+=1}return o==null?{...s,fundingPaymentRate:a}:{...s,fundingRate:o,fundingPaymentRate:a}})}async function qt(e,t={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("strategy history input must be an object");let r=String(e.coin||"").trim().toUpperCase();if(!/^[A-Z0-9][A-Z0-9._-]{0,11}$/.test(r))throw new TypeError("coin must be an uppercase Hyperliquid asset id");let n=String(e.interval||"15m"),o=Hr(n);if(e.endTime==null)throw new TypeError("endTime is required for deterministic history");let s=ve(e.endTime,"endTime"),i=e.count==null?1500:e.count;if(!Number.isInteger(i)||i<20||i>5e3)throw new TypeError("count must be an integer from 20 to 5000");let a=e.startTime==null?Math.max(0,s-i*o):ve(e.startTime,"startTime");if(a>=s)throw new TypeError("startTime must be before endTime");let[l,f]=await Promise.all([Tr({coin:r,interval:n,startTime:a,endTime:s},t),Co({coin:r,startTime:a,endTime:s},t)]),u=Fr(l,{endTime:s}),c=qe(Do(u,f,o));return qe({coin:r,interval:n,range:{startTime:a,endTime:s},bars:c})}var Uo=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),qo=new Set(["coin","interval"]);function Bo(e){let t=[];if(!e||typeof e!="object"||Array.isArray(e))return{ok:!1,errors:[{path:"market",message:"must be a plain object"}],market:null};for(let r of Object.keys(e))qo.has(r)||t.push({path:`market.${r}`,message:"unknown field is not allowed"});return(typeof e.coin!="string"||e.coin.length===0||e.coin.length>32)&&t.push({path:"market.coin",message:"must be a non-empty string max 32"}),(typeof e.interval!="string"||!Uo.has(e.interval))&&t.push({path:"market.interval",message:"must be a supported interval"}),t.length?{ok:!1,errors:t,market:null}:{ok:!0,errors:[],market:{coin:e.coin,interval:e.interval}}}async function zo(e={}){let t=await Sr(e);if(!t||!Array.isArray(t.universe))throw new TypeError("Hyperliquid market metadata must contain universe");return Object.freeze(t.universe.map((r,n)=>{if(!r||typeof r.name!="string"||!r.name)throw new TypeError(`Hyperliquid market metadata universe[${n}].name is invalid`);return r.name}))}var Cr=Object.freeze({id:"hyperliquid",validateMarket:Bo,fetchBars:qt,listMarkets:zo,prepareIntent(e){return Ut(e)}});var Vo=Object.freeze(["id","validateMarket","prepareIntent"]);function Jo(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("strategy venue adapter must be an object");if(typeof e.id!="string"||!/^[a-z0-9][a-z0-9._-]{0,63}$/.test(e.id))throw new TypeError("strategy venue adapter id is malformed");for(let t of Vo.slice(1))if(typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} requires ${t}()`);for(let t of["fetchBars","listMarkets"])if(e[t]!=null&&typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} ${t} must be a function`);return e}var Dr=[Cr].map(Jo),Go=new Map(Dr.map(e=>[e.id,e])),Ko=Object.freeze([...Dr]);function tt(e){return typeof e!="string"?null:Go.get(e)??null}function rt(e){let t=tt(e);if(!t)throw new Error(`unknown strategy venue: ${String(e)}`);return t}var nt=1,Wr=/^[a-z0-9][a-z0-9._-]{0,63}$/,Zr=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Wo=new Set(["open","high","low","close","volume","fundingRate","openInterest","premium","oiDelta","bookImbalance"]),Zo=new Set(["sma","ema","rsi","macd","bollinger","atr"]),Xo=new Set(["gt","gte","lt","lte","eq"]),Qo=new Set(["and","or","not"]),es=new Set(["above","below"]),ts=new Set(["line","signal","histogram"]),rs=new Set(["upper","middle","lower"]),Bt=new Set(["compare","logic","cross"]),Ur=new Set(["version","id","name","venue","market","parameters","nodes","rules","risk"]),qr=new Set(["value","min","max","step"]),zt=new Set(["entryLong","entryShort","exitLong","exitShort"]),Br=new Set(["maxLeverage","maxNotionalUsd","positionSizePct","stopLossPct","takeProfitPct","cooldownBars","maxDailyLossPct","expiresAt"]),ns=new Set(["id","type"]),zr={input:new Set(["id","type","field"]),constant:new Set(["id","type","value"]),indicator:new Set(["id","type","indicator","input","period","fastPeriod","slowPeriod","signalPeriod","stdDev","output"]),compare:new Set(["id","type","op","left","right"]),logic:new Set(["id","type","op","inputs"]),cross:new Set(["id","type","direction","left","right"])},Vr=16,Jr=128,Gr=100,ke=class extends Error{constructor(t){let r=t.map(n=>`${n.path}: ${n.message}`);super(`invalid strategy (${t.length} error${t.length===1?"":"s"}): ${r.join("; ")}`),this.name="StrategyValidationError",this.errors=t}};function Q(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function z(e){return typeof e=="number"&&Number.isFinite(e)}function Kr(e){return Number.isInteger(e)&&e>0}function Jt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Jt(t);return Object.freeze(e)}for(let t of Object.keys(e))Jt(e[t]);return Object.freeze(e)}function Gt(e){if(Array.isArray(e))return e.map(Gt);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Gt(e[r]);return t}return e}function g(e,t,r){e.push({path:t,message:r})}function ye(e,t,r,n){for(let o of Object.keys(e))t.has(o)||g(n,r?`${r}.${o}`:o,"unknown field is not allowed")}function Xr(e,t,r,n){if(!z(e)||!z(t)||!z(r)||!z(n)||n<=0||e<t||e>r)return!1;let o=(e-t)/n;if(!Number.isFinite(o))return!1;let s=Math.round(o);return Math.abs(o-s)<=1e-9}function Vt(e,t,r,n){if(Q(e)){if(ye(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param)return g(n,`${t}.param`,"must be a parameter name string"),null;if(!Object.prototype.hasOwnProperty.call(r,e.param))return g(n,`${t}.param`,`unknown parameter "${e.param}"`),null;let o=r[e.param];return!Q(o)||![o.value,o.min,o.max,o.step].every(Kr)?(g(n,`${t}.param`,"referenced period parameter value min max and step must be positive integers"),null):{param:e.param}}return Kr(e)?e:(g(n,t,"must be a positive integer or {param}"),null)}function Yr(e,t,r,n){return Q(e)?(ye(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param?(g(n,`${t}.param`,"must be a parameter name string"),null):Object.prototype.hasOwnProperty.call(r,e.param)?{param:e.param}:(g(n,`${t}.param`,`unknown parameter "${e.param}"`),null)):z(e)?e:(g(n,t,"must be a finite number or {param}"),null)}function ot(e){switch(e.type){case"input":case"constant":return[];case"indicator":return e.input?[e.input]:[];case"compare":case"cross":return[e.left,e.right].filter(Boolean);case"logic":return Array.isArray(e.inputs)?[...e.inputs]:[];default:return[]}}function os(e){let t=new Map,r=n=>{let o=t.get(n)||0;if(o===1)return!0;if(o===2)return!1;t.set(n,1);let s=e.get(n);if(s){for(let i of ot(s))if(e.has(i)&&r(i))return!0}return t.set(n,2),!1};for(let n of e.keys())if(r(n))return!0;return!1}function ss(e,t){if(!Q(e))return g(t,"parameters","must be a plain object"),null;let r=Object.keys(e);if(r.length>Vr)return g(t,"parameters",`too many parameters (max ${Vr})`),null;let n={};for(let o of r){if(!Wr.test(o)){g(t,`parameters.${o}`,"parameter name is malformed");continue}let s=e[o],i=`parameters.${o}`;if(!Q(s)){g(t,i,"must be a plain object");continue}ye(s,qr,i,t);for(let c of qr)c in s||g(t,`${i}.${c}`,"required field is missing");let{value:a,min:l,max:f,step:u}=s;z(l)||g(t,`${i}.min`,"must be a finite number"),z(f)||g(t,`${i}.max`,"must be a finite number"),(!z(u)||u<=0)&&g(t,`${i}.step`,"must be a positive finite number"),z(a)||g(t,`${i}.value`,"must be a finite number"),z(l)&&z(f)&&l>f&&g(t,`${i}.min`,"min must be <= max"),z(a)&&z(l)&&z(f)&&z(u)&&u>0&&(Xr(a,l,f,u)||g(t,`${i}.value`,"value must lie on the declared min/max/step grid")),n[o]={value:a,min:l,max:f,step:u}}return n}function is(e,t,r,n){let o=`nodes.${t}`;if(!Q(e))return g(n,o,"must be a plain object"),null;if(typeof e.type!="string"||!zr[e.type])return g(n,`${o}.type`,"unknown or missing node type"),ye(e,ns,o,n),null;switch(ye(e,zr[e.type],o,n),(typeof e.id!="string"||!Zr.test(e.id))&&g(n,`${o}.id`,"must be a 1-64 char id starting with alphanumeric"),e.type){case"input":return(typeof e.field!="string"||!Wo.has(e.field))&&g(n,`${o}.field`,"must be one of open|high|low|close|volume|fundingRate|openInterest|premium|oiDelta|bookImbalance"),{id:e.id,type:"input",field:e.field};case"constant":{let s=Yr(e.value,`${o}.value`,r,n);return{id:e.id,type:"constant",value:s}}case"indicator":{(typeof e.indicator!="string"||!Zo.has(e.indicator))&&g(n,`${o}.indicator`,"must be one of sma|ema|rsi|macd|bollinger|atr");let s=e.indicator,i={id:e.id,type:"indicator",indicator:s};if(s==="atr"){"input"in e&&(typeof e.input!="string"||!e.input?g(n,`${o}.input`,"must be a node id string when provided"):i.input=e.input);let a=Vt(e.period,`${o}.period`,r,n);a!=null&&(i.period=a)}else typeof e.input!="string"||!e.input?g(n,`${o}.input`,"must be a node id string"):i.input=e.input;if((s==="sma"||s==="ema"||s==="rsi"||s==="bollinger"||s==="atr")&&("period"in e,s!=="macd"))if(!("period"in e))g(n,`${o}.period`,"required field is missing");else{let a=Vt(e.period,`${o}.period`,r,n);a!=null&&(i.period=a)}if(s==="macd"){for(let a of["fastPeriod","slowPeriod","signalPeriod"])if(!(a in e))g(n,`${o}.${a}`,"required field is missing");else{let l=Vt(e[a],`${o}.${a}`,r,n);l!=null&&(i[a]=l)}"output"in e?ts.has(e.output)?i.output=e.output:g(n,`${o}.output`,"must be line|signal|histogram"):g(n,`${o}.output`,"required field is missing"),"period"in e&&g(n,`${o}.period`,"forbidden for macd"),"stdDev"in e&&g(n,`${o}.stdDev`,"forbidden for macd")}else if(s==="bollinger"){if(!("stdDev"in e))g(n,`${o}.stdDev`,"required field is missing");else{let a=Yr(e.stdDev,`${o}.stdDev`,r,n);a!=null&&(typeof a=="number"&&a<=0?g(n,`${o}.stdDev`,"must be > 0"):i.stdDev=a)}"output"in e?rs.has(e.output)?i.output=e.output:g(n,`${o}.output`,"must be upper|middle|lower"):g(n,`${o}.output`,"required field is missing");for(let a of["fastPeriod","slowPeriod","signalPeriod"])a in e&&g(n,`${o}.${a}`,`forbidden for ${s}`)}else{"output"in e&&g(n,`${o}.output`,`forbidden for ${s}`),"stdDev"in e&&s!=="bollinger"&&g(n,`${o}.stdDev`,`forbidden for ${s}`);for(let a of["fastPeriod","slowPeriod","signalPeriod"])a in e&&g(n,`${o}.${a}`,`forbidden for ${s}`)}return i}case"compare":return(typeof e.op!="string"||!Xo.has(e.op))&&g(n,`${o}.op`,"must be gt|gte|lt|lte|eq"),(typeof e.left!="string"||!e.left)&&g(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&g(n,`${o}.right`,"must be a node id"),{id:e.id,type:"compare",op:e.op,left:e.left,right:e.right};case"logic":{if((typeof e.op!="string"||!Qo.has(e.op))&&g(n,`${o}.op`,"must be and|or|not"),!Array.isArray(e.inputs))return g(n,`${o}.inputs`,"must be an array of node ids"),{id:e.id,type:"logic",op:e.op,inputs:[]};let s=[];for(let i=0;i<e.inputs.length;i++){let a=e.inputs[i];typeof a!="string"||!a?g(n,`${o}.inputs.${i}`,"must be a node id"):s.push(a)}return e.op==="not"?s.length!==1&&g(n,`${o}.inputs`,"not requires exactly one input"):(e.op==="and"||e.op==="or")&&s.length<2&&g(n,`${o}.inputs`,`${e.op} requires at least two inputs`),{id:e.id,type:"logic",op:e.op,inputs:s}}case"cross":return(typeof e.direction!="string"||!es.has(e.direction))&&g(n,`${o}.direction`,"must be above|below"),(typeof e.left!="string"||!e.left)&&g(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&g(n,`${o}.right`,"must be a node id"),{id:e.id,type:"cross",direction:e.direction,left:e.left,right:e.right};default:return null}}function as(e,t,r){if(!Q(e))return g(t,"risk","must be a plain object"),null;ye(e,Br,"risk",t);for(let d of Br)(!(d in e)||e[d]==null)&&g(t,`risk.${d}`,"required field is missing");let n={},o=e.maxLeverage;!z(o)||o<=0||o>50?g(t,"risk.maxLeverage","must be a number > 0 and <= 50"):n.maxLeverage=o;let s=e.maxNotionalUsd;!z(s)||s<=0?g(t,"risk.maxNotionalUsd","must be a number > 0"):n.maxNotionalUsd=s;let i=e.positionSizePct;!z(i)||i<=0||i>100?g(t,"risk.positionSizePct","must be a number > 0 and <= 100"):n.positionSizePct=i;let a=e.stopLossPct;!z(a)||a<=0||a>100?g(t,"risk.stopLossPct","must be a number > 0 and <= 100"):n.stopLossPct=a;let l=e.takeProfitPct;!z(l)||l<=0||l>1e3?g(t,"risk.takeProfitPct","must be a number > 0 and <= 1000"):n.takeProfitPct=l;let f=e.cooldownBars;!Number.isInteger(f)||f<0||f>1e5?g(t,"risk.cooldownBars","must be an integer >= 0 and <= 100000"):n.cooldownBars=f;let u=e.maxDailyLossPct;!z(u)||u<=0||u>100?g(t,"risk.maxDailyLossPct","must be a number > 0 and <= 100"):n.maxDailyLossPct=u;let c=e.expiresAt;return!Number.isInteger(c)||c<=0?g(t,"risk.expiresAt","must be an integer epoch milliseconds > 0"):(r.nowMs!==void 0&&(Number.isInteger(r.nowMs)?c<=r.nowMs&&g(t,"risk.expiresAt","must be strictly greater than nowMs"):g(t,"nowMs","must be an integer epoch milliseconds")),n.expiresAt=c),n}function st(e,t={}){let r=[];if(!Q(e))return g(r,"","strategy must be a plain object"),{ok:!1,errors:r,strategy:null};ye(e,Ur,"",r);for(let c of Ur)(!(c in e)||e[c]==null)&&g(r,c,"required field is missing");e.version!==nt&&g(r,"version",`must be ${nt}`),(typeof e.id!="string"||!Wr.test(e.id))&&g(r,"id","must match /^[a-z0-9][a-z0-9._-]{0,63}$/"),(typeof e.name!="string"||e.name.length===0||e.name.length>Gr)&&g(r,"name",`must be a non-empty string max ${Gr}`);let n=tt(e.venue);n||g(r,"venue",`unknown strategy venue "${String(e.venue)}"`);let o=null;if(!n)Q(e.market)||g(r,"market","must be a plain object");else{let c=n.validateMarket(e.market);if(!c||typeof c.ok!="boolean"||!Array.isArray(c.errors))g(r,"market",`venue ${n.id} returned an invalid market validation result`);else if(c.ok)o=c.market;else for(let d of c.errors)g(r,d.path,d.message)}let s=ss(e.parameters,r),i=null,a=new Map;if(!Array.isArray(e.nodes))g(r,"nodes","must be an array");else if(e.nodes.length>Jr)g(r,"nodes",`too many nodes (max ${Jr})`);else{i=[];for(let c=0;c<e.nodes.length;c++){let d=is(e.nodes[c],c,s||{},r);d&&(typeof d.id=="string"&&Zr.test(d.id)&&(a.has(d.id)?g(r,`nodes.${c}.id`,`duplicate node id "${d.id}"`):a.set(d.id,d)),i.push(d))}for(let c=0;c<i.length;c++){let d=i[c],m=`nodes.${c}`;for(let p of ot(d))a.has(p)||g(r,m,`unknown node ref "${p}"`);if(d.type==="indicator"||d.type==="compare"||d.type==="cross")for(let p of ot(d)){let w=a.get(p);w&&Bt.has(w.type)&&g(r,m,`node ref "${p}" must be numeric`)}if(d.type==="logic")for(let p of ot(d)){let w=a.get(p);w&&!Bt.has(w.type)&&g(r,m,`node ref "${p}" must be boolean`)}}os(a)&&g(r,"nodes","graph contains a cycle")}let l=null;if(!Q(e.rules))g(r,"rules","must be a plain object");else{ye(e.rules,zt,"rules",r);for(let c of zt)c in e.rules||g(r,`rules.${c}`,"required field is missing");l={};for(let c of zt){let d=e.rules[c];if(d===null){l[c]=null;continue}if(typeof d!="string"||!d){g(r,`rules.${c}`,"must be a node id or null"),l[c]=d;continue}if(!a.has(d)){g(r,`rules.${c}`,`unknown node ref "${d}"`),l[c]=d;continue}let m=a.get(d);Bt.has(m.type)||g(r,`rules.${c}`,`rule must reference a boolean node, not ${m.type}`),l[c]=d}}let f=as(e.risk,r,t);if(r.length)return{ok:!1,errors:r,strategy:null};let u=Jt({version:nt,id:e.id,name:e.name,venue:n.id,market:o,parameters:s,nodes:i,rules:l,risk:f});return{ok:!0,errors:[],strategy:u}}function Z(e,t={}){let r=st(e,t);if(!r.ok)throw new ke(r.errors);return r.strategy}function Qr(e){let t=Z(e);return JSON.stringify(Gt(t))}function xe(e){let t=Qr(e);return Yo("sha256").update(t,"utf8").digest("hex")}function $e(e,t){if(!Q(e))throw new ke([{path:"",message:"strategy must be a plain object"}]);if(!Q(t))throw new ke([{path:"overrides",message:"must be a plain object"}]);let r=Z(e),n={};for(let[s,i]of Object.entries(r.parameters))n[s]={value:i.value,min:i.min,max:i.max,step:i.step};let o=[];for(let[s,i]of Object.entries(t)){if(!Object.prototype.hasOwnProperty.call(n,s)){g(o,s,`unknown parameter "${s}"`);continue}let a=n[s];if(!z(i)){g(o,s,"override must be a finite number");continue}if(!Xr(i,a.min,a.max,a.step)){g(o,s,"override must lie on the declared min/max/step grid");continue}n[s]={...a,value:i}}if(o.length)throw new ke(o);return Z({version:r.version,id:r.id,name:r.name,venue:r.venue,market:{coin:r.market.coin,interval:r.market.interval},parameters:n,nodes:r.nodes.map(s=>{let i={...s};return Array.isArray(s.inputs)&&(i.inputs=[...s.inputs]),i}),rules:{...r.rules},risk:{...r.risk}})}var cs=50;function se(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function en(e,t,r){if(!Array.isArray(e))throw new TypeError(`${r} must be an array`);let n=0;for(let o=0;o<e.length;o++){let s=se(e[o]?.px,`${r}[${o}].px`),i=se(e[o]?.sz,`${r}[${o}].sz`);if(i<0)throw new TypeError(`${r}[${o}].sz must be non-negative`);Math.abs((s-t)/t)*1e4<=cs&&(n+=i)}return n}async function ls(e,t={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("sampleLiveSeries input must be an object");let r=String(e.coin||"").trim().toUpperCase();if(!/^[A-Z0-9][A-Z0-9._-]{0,11}$/.test(r))throw new TypeError("coin must be an uppercase Hyperliquid asset id");if(!Number.isSafeInteger(e.nowMs)||e.nowMs<=0)throw new TypeError("nowMs is required integer epoch ms");let[n,o]=await Promise.all([kr(t),xr(r,t)]),s=n?.[0]?.universe,i=n?.[1];if(!Array.isArray(s)||!Array.isArray(i))throw new TypeError("metaAndAssetCtxs payload malformed");let a=s.findIndex(w=>w?.name===r);if(a<0)throw new Error(`unknown coin: ${r}`);let l=i[a];if(!l||typeof l!="object")throw new TypeError("asset ctx malformed");let f=se(l.premium,"ctx.premium"),u=se(l.openInterest,"ctx.openInterest");if(u<0)throw new TypeError("ctx.openInterest must be non-negative");let c=se(l.midPx,"ctx.midPx"),d=o?.levels;if(!Array.isArray(d)||d.length!==2)throw new TypeError("l2Book levels malformed");let m=en(d[0],c,"book.bids"),p=en(d[1],c,"book.asks");if(m+p<=0)throw new TypeError("book depth near mid is empty");return Object.freeze({coin:r,t:e.nowMs,premium:f,openInterest:u,book:Object.freeze({bidDepth:m,askDepth:p})})}function us(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("snapshots must be a non-empty array");let t=e[0]?.coin,r=[],n=null;for(let o=0;o<e.length;o++){let s=e[o];if(!s||typeof s!="object")throw new TypeError(`snapshots[${o}] must be an object`);if(s.coin!==t)throw new TypeError("snapshots must be a single coin");let i=se(s.t,`snapshots[${o}].t`);if(n!=null&&!(i>n.t))throw new TypeError("snapshot times must be strictly increasing");let a=se(s.premium,`snapshots[${o}].premium`),l=se(s.openInterest,`snapshots[${o}].openInterest`),f=se(s.book?.bidDepth,`snapshots[${o}].book.bidDepth`),u=se(s.book?.askDepth,`snapshots[${o}].book.askDepth`),c=f+u;if(!(c>0))throw new TypeError(`snapshots[${o}] book depth must be positive`);r.push({coin:t,t:i,premium:a,openInterest:l,oiDelta:n==null?null:l-n.openInterest,bookImbalance:(f-u)/c}),n={t:i,openInterest:l}}return r}function fs(e,t,r){if(!Array.isArray(e))throw new TypeError("bars must be an array");if(!Array.isArray(t))throw new TypeError("rows must be an array");if(!Number.isSafeInteger(r)||r<=0)throw new TypeError("intervalMs must be a positive integer");let n=0;return e.map(o=>{let s=o.t+r,i=null;for(;n<t.length&&t[n].t<s;)t[n].t>=o.t&&(i=t[n]),n+=1;if(!i)return{...o};let a={...o};return i.premium!=null&&(a.premium=i.premium),i.openInterest!=null&&(a.openInterest=i.openInterest),i.oiDelta!=null&&(a.oiDelta=i.oiDelta),i.bookImbalance!=null&&(a.bookImbalance=i.bookImbalance),a})}import{createHash as ds}from"node:crypto";var Yt=256,tn=new Set(["netPnlUsd","profitFactor","sharpe","maxDrawdownPct"]);function rn(e){let t=String(e).toLowerCase();return t==="holdout"||t==="test"||t==="oos"||t.includes("holdout")||t.includes("oos")?!0:t==="testbars"||t.endsWith("testbars")||t.startsWith("test")||t.endsWith("test")?!t.includes("backtest"):!1}function nn(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Wt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Wt(t);return Object.freeze(e)}for(let t of Object.keys(e))Wt(e[t]);return Object.freeze(e)}function Be(e){if(Array.isArray(e))return e.map(Be);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Be(e[r]);return t}return e}function it(e){return JSON.stringify(Be(e))}function ps(e){let{min:t,max:r,step:n}=e;if(!(n>0)||t>r)return[];let o=[],s=Math.floor((r-t)/n+1e-9);for(let a=0;a<=s;a++){let l=t+a*n;if(l>r+1e-9)break;let f=Math.abs(l-Math.round(l))<1e-9?Math.round(l):Number(l.toPrecision(12));f<t-1e-9||f>r+1e-9||o.push(f)}if(o.length===0)return[];let i=o[o.length-1];if(Math.abs(i-r)>1e-9){let a=(r-t)/n;Math.abs(a-Math.round(a))<=1e-9&&o.push(r)}return o}function ms(e,t){if(e.length===0)return[];let r=[{}];for(let n of e){let o=t[n],s=[];for(let i of r)for(let a of o)s.push({...i,[n]:a});r=s}return r.sort((n,o)=>{let s=it(n),i=it(o);return s<i?-1:s>i?1:0}),r}function Kt(e,t,r,n,o){let s=0;if(e==="maxDrawdownPct"){if(s=t.maxDrawdownPct-n.maxDrawdownPct,s!==0)return s<0}else if(s=t[e]-n[e],s!==0)return s>0;let i=it(r),a=it(o);return i<a}function Zt(e,t,r={}){if(!nn(r))throw new TypeError("options must be a plain object");for(let E of Object.keys(r))if(rn(E))throw new TypeError(`options must not include holdout/test/oos key "${E}"`);let n=new Set(["maxTrials","objective","backtestOptions"]);for(let E of Object.keys(r))if(!n.has(E))throw new TypeError(`unknown option "${E}"`);let o=64;if("maxTrials"in r){let E=r.maxTrials;if(!Number.isInteger(E)||E<1||E>Yt)throw new TypeError(`maxTrials must be an integer 1..${Yt}`);o=E}let s=r.objective??"netPnlUsd";if(!tn.has(s))throw new TypeError(`objective must be one of ${[...tn].join("|")}`);let i=r.backtestOptions??{};if(!nn(i))throw new TypeError("backtestOptions must be a plain object");for(let E of Object.keys(i))if(rn(E))throw new TypeError(`backtestOptions must not include holdout/test/oos key "${E}"`);let a=Z(e),l=Object.keys(a.parameters).sort();if(l.length===0)throw new Error("optimizeStrategy requires at least one declared parameter");let f={},u=1;for(let E of l){let R=ps(a.parameters[E]);if(R.length===0)throw new Error(`parameter "${E}" produces an empty grid`);f[E]=R,u*=R.length}let c=ms(l,f);if(c.length===0)throw new Error("parameter grid is empty");let d=c.slice(0,o),m=[],p=null,w=null;for(let E of d){let R=$e(a,E),P=ue(R,t,i);w==null&&(w=P.config);let h={netPnlUsd:P.metrics.netPnlUsd,netPnlPct:P.metrics.netPnlPct,maxDrawdownPct:P.metrics.maxDrawdownPct,winRate:P.metrics.winRate,profitFactor:P.metrics.profitFactor,tradeCount:P.metrics.tradeCount,sharpe:P.metrics.sharpe,turnoverUsd:P.metrics.turnoverUsd},M={parameters:{...E},metrics:h};m.push(M),(!p||Kt(s,h,E,p.metrics,p.parameters))&&(p=M)}m.sort((E,R)=>Kt(s,E.metrics,E.parameters,R.metrics,R.parameters)?-1:Kt(s,R.metrics,R.parameters,E.metrics,E.parameters)?1:0);let x={...p.parameters},S=$e(a,x),v={strategyHash:xe(a),compilerHash:he,trainBarsHash:Ce(t),backtestConfig:w,objective:s,maxTrials:o,trialsRun:m.length,candidates:m,bestParameters:x,bestStrategy:S},k={id:ds("sha256").update(JSON.stringify(Be(v)),"utf8").digest("hex"),...v};return Wt(Be(JSON.parse(JSON.stringify(k))))}import{createHash as hs}from"node:crypto";var K=class extends Error{constructor(t){super(t),this.name="StrategyDraftError"}},ys=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),ws=new Set(["BTC","ETH","SOL","HYPE"]),gs=/\b(mnemonic|private\s*key|privkey|seed\s*phrase|seed\b|api[_-]?key|secret\s*key|wallet\s*key|passphrase)\b/i,je="Supported grammar: (1) EMA cross: <long|short> <COIN> when EMA <n> crosses <above|below> EMA <m> [on <interval>] [, exit on reverse] [, risk knobs]; (2) RSI: <long|short> <COIN> when RSI <n> <above|below> <threshold> [on <interval>] [, risk knobs]; (3) funding: <long|short> <COIN> when funding rate <above|below> <decimal|percent%> [on <interval>] [, risk knobs]; (4) open interest: <long|short> <COIN> when open interest <above|below> <non-negative number> [on <interval>] [, risk knobs]; (5) premium: <long|short> <COIN> when premium <above|below> <decimal|percent%> [on <interval>] [, risk knobs]; (6) oi delta: <long|short> <COIN> when oi delta <above|below> <number> [on <interval>] [, risk knobs]; (7) book imbalance: <long|short> <COIN> when book imbalance <above|below> <-1..1> [on <interval>] [, risk knobs]. Risk knobs: stop loss %, take profit %, leverage, position size %, max notional USD. Coins: BTC ETH SOL HYPE or uppercase token <=12 chars. Intervals: 1m 3m 5m 15m 30m 1h 2h 4h 8h 12h 1d.",bs=Object.freeze({maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3}),Es=36e5,xs=30*864e5,Ss=864e5;function ks(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Xt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Xt(t);return Object.freeze(e)}for(let t of Object.keys(e))Xt(e[t]);return Object.freeze(e)}function Ts(e){return String(e).trim().replace(/\s+/g," ")}function As(e){let t=e.match(/\b(long|short)\b/i);return t?t[1].toLowerCase():null}function Os(e){for(let r of ws)if(new RegExp(`\\b${r}\\b`,"i").test(e))return r;let t=e.match(/\b([A-Z][A-Z0-9]{1,11})\b/);return t?t[1]:null}function Ps(e){let t=e.match(/\bon\s+(1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)\b/i);if(!t)return"15m";let r=t[1].toLowerCase();return ys.has(r)?r:null}function $s(e){let t={...bs},r=e.match(/stop\s*loss\s*(\d+(?:\.\d+)?)\s*%?/i);r&&(t.stopLossPct=Number(r[1]));let n=e.match(/take\s*profit\s*(\d+(?:\.\d+)?)\s*%?/i);n&&(t.takeProfitPct=Number(n[1]));let o=e.match(/leverage\s*(\d+(?:\.\d+)?)/i);o&&(t.maxLeverage=Number(o[1]));let s=e.match(/position\s*size\s*(\d+(?:\.\d+)?)\s*%?/i);s&&(t.positionSizePct=Number(s[1]));let i=e.match(/max\s*notional\s*(?:usd\s*)?\$?\s*(\d+(?:\.\d+)?)/i);return i&&(t.maxNotionalUsd=Number(i[1])),t}function Is(e){return[/\bon\s+(?:1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)\b/gi,/\bstop\s*loss\s*\d+(?:\.\d+)?\s*%?/gi,/\btake\s*profit\s*\d+(?:\.\d+)?\s*%?/gi,/\bleverage\s*\d+(?:\.\d+)?/gi,/\bposition\s*size\s*\d+(?:\.\d+)?\s*%?/gi,/\bmax\s*notional\s*(?:usd\s*)?\$?\s*\d+(?:\.\d+)?/gi].some(r=>(e.match(r)??[]).length>1)}function _s(e){let t=hs("sha256").update(e,"utf8").digest("hex").slice(0,10),r=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40),o=`${r.length?r:"draft"}-${t}`.replace(/[^a-z0-9._-]/g,"").slice(0,64);return/^[a-z0-9]/.test(o)?o:`d${o}`.slice(0,64)}function vs(e){let t=e.match(/\bema\s*(\d+)\s*cross(?:es)?\s*(above|below)\s*ema\s*(\d+)\b/i);if(!t)return null;let r=Number(t[1]),n=t[2].toLowerCase(),o=Number(t[3]);if(!(r>0)||!(o>0)||r===o)return null;let s=/\b(exit\s+on\s+reverse|reverse\s+exit)\b/i.test(e);return{kind:"ema_cross",fast:r,slow:o,direction:n,reverse:s}}function js(e){let t=e.match(/\brsi\s*(\d+)\s*(above|below)\s*(-?\d+(?:\.\d+)?)/i);if(!t)return null;let r=Number(t[3]);return!Number.isFinite(r)||r<=0||r>=100?null:{kind:"rsi",period:Number(t[1]),op:t[2].toLowerCase(),threshold:r}}function Ns(e){let t=e.match(/\bfunding\s*rate\s*(above|below)\s*(-?\d+(?:\.\d+)?)(%?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return t[3]==="%"&&(r=r/100),{kind:"funding",op:t[1].toLowerCase(),threshold:r}}function Rs(e){let t=e.match(/\bopen\s*interest\s*(above|below)\s*(-?\d+(?:\.\d+)?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return!Number.isFinite(r)||r<0?null:{kind:"open_interest",op:t[1].toLowerCase(),threshold:r}}function Ms(e){let t=e.match(/\bpremium\s*(above|below)\s*(-?\d+(?:\.\d+)?)(%?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return Number.isFinite(r)?(t[3]==="%"&&(r=r/100),{kind:"premium",op:t[1].toLowerCase(),threshold:r}):null}function Ls(e){let t=e.match(/\boi\s*delta\s*(above|below)\s*(-?\d+(?:\.\d+)?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return Number.isFinite(r)?{kind:"oi_delta",op:t[1].toLowerCase(),threshold:r}:null}function Hs(e){let t=e.match(/\bbook\s*imbalance\s*(above|below)\s*(-?\d+(?:\.\d+)?)(?=\s|,|$)/i);if(!t)return null;let r=Number(t[2]);return!Number.isFinite(r)||r<-1||r>1?null:{kind:"book_imbalance",op:t[1].toLowerCase(),threshold:r}}function Fs(e,t){let r=e.replace(/^(long|short)\s+[A-Z][A-Z0-9]{1,11}\s+when\s+/i,"");if(r===e)return!1;t.kind==="ema_cross"?r=r.replace(/^ema\s*\d+\s*cross(?:es)?\s*(?:above|below)\s*ema\s*\d+\b/i,""):t.kind==="rsi"?r=r.replace(/^rsi\s*\d+\s*(?:above|below)\s*\d+(?:\.\d+)?\b/i,""):t.kind==="open_interest"?r=r.replace(/^open\s*interest\s*(?:above|below)\s*-?\d+(?:\.\d+)?(?=\s|,|$)/i,""):t.kind==="premium"?r=r.replace(/^premium\s*(?:above|below)\s*-?\d+(?:\.\d+)?%?(?=\s|,|$)/i,""):t.kind==="oi_delta"?r=r.replace(/^oi\s*delta\s*(?:above|below)\s*-?\d+(?:\.\d+)?(?=\s|,|$)/i,""):t.kind==="book_imbalance"?r=r.replace(/^book\s*imbalance\s*(?:above|below)\s*-?\d+(?:\.\d+)?(?=\s|,|$)/i,""):r=r.replace(/^funding\s*rate\s*(?:above|below)\s*-?\d+(?:\.\d+)?%?(?=\s|,|$)/i,"");let n=[/(?:,\s*)?\bon\s+(?:1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)\b/gi,/(?:,\s*)?\bstop\s*loss\s*\d+(?:\.\d+)?\s*%?/gi,/(?:,\s*)?\btake\s*profit\s*\d+(?:\.\d+)?\s*%?/gi,/(?:,\s*)?\bleverage\s*\d+(?:\.\d+)?/gi,/(?:,\s*)?\bposition\s*size\s*\d+(?:\.\d+)?\s*%?/gi,/(?:,\s*)?\bmax\s*notional\s*(?:usd\s*)?\$?\s*\d+(?:\.\d+)?/gi];t.kind==="ema_cross"&&n.push(/(?:,\s*)?\b(?:exit\s+on\s+reverse|reverse\s+exit)\b/gi);for(let o of n)r=r.replace(o,"");return r.replace(/[\s,;]+/g,"")===""}function on(e){let t=Math.max(2,Math.floor(e/2));return{value:e,min:Math.max(2,e-t),max:Math.min(500,e+t),step:1}}function Cs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"c",type:"input",field:"close"},{id:"emaLeft",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_left_period"}},{id:"emaRight",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_right_period"}},{id:"cross",type:"cross",direction:a.direction,left:"emaLeft",right:"emaRight"}],f={entryLong:null,entryShort:null,exitLong:null,exitShort:null};if(e==="long"?f.entryLong="cross":f.entryShort="cross",a.reverse){let u=a.direction==="above"?"below":"above";l.push({id:"crossRev",type:"cross",direction:u,left:"emaLeft",right:"emaRight"}),e==="long"?f.exitLong="crossRev":f.exitShort="crossRev"}return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{ema_left_period:on(a.fast),ema_right_period:on(a.slow)},nodes:l,rules:f,risk:{...n,expiresAt:o}}}function Ds({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"c",type:"input",field:"close"},{id:"rsi",type:"indicator",indicator:"rsi",input:"c",period:a.period},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"rsi",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function Us({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"fr",type:"input",field:"fundingRate"},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"fr",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function qs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"oi",type:"input",field:"openInterest"},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"oi",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}var Bs=Object.freeze({funding:"fundingRate",open_interest:"openInterest",premium:"premium",oi_delta:"oiDelta",book_imbalance:"bookImbalance"});function zs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let f=[{id:"sig_input",type:"input",field:Bs[a.kind]},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"sig_input",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:f,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function Qt(e,t={}){if(typeof e!="string")throw new K("prompt must be a string");if(e.length>1e3)throw new K("prompt length must be <= 1000");if(!ks(t))throw new K("options must be a plain object");if(!Number.isInteger(t.nowMs))throw new K("options.nowMs is required integer epoch ms");let r=t.nowMs,n=Ss;if("expiresInMs"in t){if(!Number.isInteger(t.expiresInMs))throw new K("expiresInMs must be an integer");if(n=t.expiresInMs,n<Es||n>xs)throw new K("expiresInMs must be between 1h and 30d")}if(gs.test(e))throw new K(`prompt appears to contain secrets and is rejected. ${je}`);let o=Ts(e);if(!o)throw new K(`empty prompt. ${je}`);if(Is(o))throw new K(`duplicate interval or risk clause. ${je}`);let s=As(o),i=Os(o),a=Ps(o);if(!s||!i||!a)throw new K(`could not parse side/coin/interval. ${je}`);let l=$s(o);if(!(l.maxLeverage>0)||l.maxLeverage>50)throw new K("leverage out of range");if(!(l.positionSizePct>0)||l.positionSizePct>100)throw new K("position size out of range");let f=r+n,u=_s(o),c=`Draft ${i} ${s}`.slice(0,100),d=vs(o),m=js(o),p=Ns(o),w=Rs(o),x=Ms(o),S=Ls(o),v=Hs(o),k=[d,m,p,w,x,S,v].filter(Boolean);if(k.length!==1)throw new K(`unsupported or ambiguous prompt. ${je}`);if(!Fs(o,k[0]))throw new K(`unsupported or ambiguous prompt. ${je}`);let E,R=k[0],P={side:s,coin:i,interval:a,risk:l,expiresAt:f,id:u,name:c,spec:R};R.kind==="ema_cross"?E=Cs(P):R.kind==="rsi"?E=Ds(P):R.kind==="open_interest"?E=qs(P):R.kind==="funding"?E=Us(P):E=zs(P);let h=st(E,{nowMs:r});if(!h.ok)throw new K(`draft failed validation: ${h.errors.map(M=>M.message).join("; ")}`);return Xt(Z(E,{nowMs:r}))}import fe from"node:fs";import at from"node:path";var tr=1,Vs=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function ct(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ie(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Js(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Ne(e,t="record"){if(Array.isArray(e)){e.forEach((r,n)=>Ne(r,`${t}[${n}]`));return}if(ct(e))for(let[r,n]of Object.entries(e)){let o=Js(r);if(Vs.some(s=>o.includes(s)))throw new Error(`shadow-store: forbidden secret-like field at ${t}.${r}`);Ne(n,`${t}.${r}`)}}function Gs(e){if(typeof e!="string"||!e||!at.isAbsolute(e))throw new Error("shadow-store: path must be an absolute path")}function sn(e){let t;try{t=fe.lstatSync(e)}catch(n){if(n&&n.code==="ENOENT")return;throw n}if(t.isSymbolicLink())throw new Error("shadow-store: store path must not be a symlink");if(!t.isFile())throw new Error("shadow-store: store path must be a regular file");if(t.mode&511&18)throw new Error("shadow-store: store file must not be group or world writable")}function Ks(){return{version:tr,runners:[]}}function an(e,t){let r;try{r=JSON.parse(e)}catch{throw new Error("shadow-store: malformed JSON")}if(!ct(r))throw new Error("shadow-store: malformed JSON root");if(r.version!==tr)throw new Error(`shadow-store: unsupported version ${r.version}`);if(!Array.isArray(r.runners))throw new Error("shadow-store: runners must be an array");return Ne(r,at.basename(t)),{version:tr,runners:r.runners.map(n=>ie(n))}}function cn(e,t){Ne(t,"store");let r=at.dirname(e);fe.mkdirSync(r,{recursive:!0,mode:448});let n=at.join(r,`.shadow-store.${process.pid}.${Date.now()}.tmp`),o=`${JSON.stringify(t)}
3
+ `;try{fe.writeFileSync(n,o,{mode:384,flag:"wx"}),fe.renameSync(n,e);try{fe.chmodSync(e,384)}catch{}}catch(s){try{fe.unlinkSync(n)}catch{}throw s}}var er=new Map;function rr(e={}){let t=e.path;if(Gs(t),sn(t),fe.existsSync(t)?an(fe.readFileSync(t,"utf8"),t):cn(t,Ks()),er.has(t))return er.get(t);let r=!1,n=[];function o(){if(r)return;let p=n.shift();if(p){r=!0;try{let w=p.fn();r=!1,p.resolve(w),o()}catch(w){r=!1,p.reject(w),o()}}}function s(p){if(!r&&n.length===0){r=!0;try{return p()}finally{r=!1,queueMicrotask(o)}}return new Promise((w,x)=>{n.push({fn:p,resolve:w,reject:x}),queueMicrotask(o)})}function i(){return sn(t),an(fe.readFileSync(t,"utf8"),t)}function a(p){cn(t,p)}function l(p){if(!ct(p)||typeof p.id!="string"||!p.id)throw new Error("shadow-store: create requires record with string id");Ne(p,"record");let w=i();if(w.runners.some(S=>S.id===p.id))throw new Error(`shadow-store: runner id already exists: ${p.id}`);let x=ie(p);return w.runners.push(x),a(w),ie(x)}function f(p){let w=i().runners.find(x=>x.id===p);return w?ie(w):null}function u(){return i().runners.map(p=>ie(p))}function c(p,w){if(typeof w!="function")throw new Error("shadow-store: updater must be a function");let x=i(),S=x.runners.findIndex(E=>E.id===p);if(S<0)throw new Error(`shadow-store: runner not found: ${p}`);let v=ie(x.runners[S]),k=w(v);if(!ct(k)||k.id!==p)throw new Error("shadow-store: updater must return record with same id");return Ne(k,"record"),x.runners[S]=ie(k),a(x),ie(x.runners[S])}function d(p){let w=i(),x=w.runners.findIndex(v=>v.id===p);if(x<0)throw new Error(`shadow-store: runner not found: ${p}`);let S=ie(w.runners[x]);return S.status!=="stopped"&&(S.status="stopped",w.runners[x]=S,a(w)),ie(w.runners[x])}let m={create(p){return s(()=>l(p))},get(p){return f(p)},list(){return u()},update(p,w){return s(()=>c(p,w))},stop(p){return s(()=>d(p))}};return er.set(t,m),m}import{createHash as sr}from"node:crypto";function nr(e){return e==null?e:JSON.parse(JSON.stringify(e))}function or(e){return Array.isArray(e)?e.map(or):e&&typeof e=="object"?Object.fromEntries(Object.keys(e).sort().map(t=>[t,or(e[t])])):e}function un(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("shadow-runner: record must be an object");return sr("sha256").update(JSON.stringify(or(e))).digest("hex")}function Ys(e,t,r,n,o){return sr("sha256").update(`${e}|${t}|${r}|${n}|${o}`).digest("hex")}function Ws(e,t,r,n){return sr("sha256").update(`shadow|${e}|${t}|${r}|${n??""}`).digest("hex")}function Zs(e){return e==="entryLong"||e==="exitShort"?"buy":e==="entryShort"||e==="exitLong"?"sell":e}function ln(e){return e==="entryLong"||e==="entryShort"}function lt({storePath:e,clock:t=Date.now}={}){if(typeof e!="string"||!e)throw new Error("shadow-runner: storePath required");let r=rr({path:e});function n({strategy:l,evidenceId:f=null}={}){let u=W(l),c=f==null?null:String(f),d=r.list().filter(S=>S.status==="running"&&S.strategyHash===u.strategyHash&&S.compilerHash===u.compilerHash&&S.evidenceId===c).sort((S,v)=>S.createdAt-v.createdAt||S.id.localeCompare(v.id))[0];if(d)return nr(d);let m=t(),p=Ws(m,u.strategyHash,u.compilerHash,c),w=r.get(p);if(w)return nr(w);let x={id:p,strategy:nr(u.strategy),strategyHash:u.strategyHash,compilerHash:u.compilerHash,evidenceId:c,status:"running",cursor:null,intendedOrders:[],fills:[],missedFills:[],markouts:[],createdAt:m,updatedAt:m,position:null,cooldownBarsRemaining:0,cooldownStartT:null,lastProcessedBarIndex:-1};return r.create(x)}function o(l){return r.get(l)}function s(){return r.list()}function i(l){return r.stop(l)}function a(l,f,{markoutHorizons:u=[1,4,12]}={}){if(!Array.isArray(f))throw new TypeError("shadow-runner: bars must be an array");return r.update(l,c=>{if(c.status!=="running")throw new Error("shadow-runner: runner is stopped");if(f.length===0)return c;let m=W(c.strategy).evaluateAll(f),p=new Map;for(let y=0;y<f.length;y++)p.set(f[y].t,y);let w=c.cursor,x=[];for(let y=0;y<f.length;y++){let $=f[y].t;(w==null||$>w)&&x.push(y)}if(x.length===0)return c;let S=new Map(c.intendedOrders.map(y=>[y.id,y])),v=new Set(c.fills.map(y=>y.orderId)),k=new Map(c.missedFills.map(y=>[y.orderId,y])),E=(y,$)=>`${y}|${$}`,R=new Map(c.markouts.map(y=>[E(y.orderId,y.horizon),y])),P=c.position?{...c.position}:null,h=Number.isInteger(c.cooldownBarsRemaining)?Math.max(0,c.cooldownBarsRemaining):0,M=Number.isFinite(c.cooldownStartT)?c.cooldownStartT:null;function D({action:y,signalBarT:$,signalIndex:_}){let C=Zs(y),L=Ys(c.id,c.strategyHash,$,C,y);if(S.has(L))return S.get(L);let j=_+1,O=j<f.length,N={id:L,action:y,type:y,side:C,signalBarT:$,fillBarT:O?f[j].t:null,status:O?"open":"missed"};return S.set(L,N),c.intendedOrders.push(N),N}function Y(y,$,_){if(v.has(y.id))return;let C={orderId:y.id,action:ln(y.action)?"entry":"exit",side:y.side,price:$.o,barT:$.t,signalBarT:y.signalBarT,barIndex:_};if(c.fills.push(C),v.add(y.id),y.status="filled",y.fillBarT=$.t,k.has(y.id)&&(k.delete(y.id),c.missedFills=c.missedFills.filter(L=>L.orderId!==y.id)),ln(y.action)){P={side:y.action==="entryLong"?"long":"short",entryOrderId:y.id,entryBarT:$.t,entryPrice:$.o,entryBarIndex:_};for(let L of u){let j=E(y.id,L);if(R.has(j))continue;let O={orderId:y.id,horizon:L,entryBarT:$.t,entryPrice:$.o,side:P.side,status:"pending",close:null,barT:null};R.set(j,O),c.markouts.push(O)}}else P=null,h=Number(c.strategy?.risk?.cooldownBars)||0,M=$.t}function T(y){if(v.has(y.id)||k.has(y.id))return;let $={orderId:y.id,action:y.action,side:y.side,signalBarT:y.signalBarT,status:"missed"};k.set(y.id,$),c.missedFills.push($),y.status="missed"}for(let y of c.intendedOrders){if(y.status==="filled"||v.has(y.id))continue;let $=p.get(y.signalBarT);if($==null)continue;let _=$+1;_<f.length&&(w==null||f[_].t>w)&&Y(y,f[_],_)}for(let y of x){let $=f[y],_=m[y].signals,C=P,L=O=>{if(P||h>0&&(M==null||$.t>=M))return;let I=D({action:O,signalBarT:$.t,signalIndex:y}),G=y+1;G<f.length?Y(I,f[G],G):T(I)},j=O=>{if(!P||P.side==="long"&&O!=="exitLong"||P.side==="short"&&O!=="exitShort")return;let N=D({action:O,signalBarT:$.t,signalIndex:y}),I=y+1;I<f.length?Y(N,f[I],I):T(N)};C?(_.exitLong&&j("exitLong"),_.exitShort&&j("exitShort")):_.entryLong&&_.entryShort||(_.entryLong&&L("entryLong"),_.entryShort&&L("entryShort")),h>0&&M!=null&&$.t>=M&&(h-=1,h===0&&(M=null)),c.cursor=$.t,c.lastProcessedBarIndex=y}for(let y of c.markouts){if(y.status!=="pending")continue;let $=c.fills.find(L=>L.orderId===y.orderId&&L.action==="entry");if(!$)continue;let _=p.get($.barT);if(_==null)continue;let C=_+y.horizon;if(C<f.length){y.close=f[C].c,y.barT=f[C].t,y.status="filled";let L=y.entryPrice;y.markout=y.side==="long"?(y.close-L)/L:(L-y.close)/L}}return c.position=P,c.cooldownBarsRemaining=h,c.cooldownStartT=M,c.updatedAt=t(),c})}return{start:n,step:a,list:s,get:o,stop:i}}import Xs from"node:os";import Qs from"node:path";var ei=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function ze(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ti(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function ar(e){if(Array.isArray(e)){for(let t of e)ar(t);return}if(ze(e))for(let[t,r]of Object.entries(e)){if(ei.some(n=>ti(t).includes(n)))throw new Error(`strategy service: secret-like field "${t}" is forbidden`);ar(r)}}function ri(e){if(!ze(e))throw new TypeError("strategy input must be a plain object");return ar(e),e}function ni(e,t={}){if(t.nowMs!==void 0){if(!Number.isInteger(t.nowMs))throw new TypeError("nowMs must be an integer epoch milliseconds");return t.nowMs}let r=Date.now();if(e.nowMs===void 0||e.nowMs===null)return r;if(!Number.isInteger(e.nowMs))throw new TypeError("nowMs must be an integer epoch milliseconds");if(Math.abs(e.nowMs-r)>12e4)throw new Error("nowMs outside allowed wall-clock skew (120s); omit nowMs to use server time");return e.nowMs}async function ir(e,t,r,n){if(Array.isArray(t.bars))return t.bars;let o=rt(e.venue),s=r.fetchBars??o.fetchBars;if(typeof s!="function")throw new Error(`strategy venue ${o.id} does not support history`);r.signal?.throwIfAborted?.();let i=await s({coin:e.market.coin,interval:e.market.interval,count:t.count??1500,endTime:t.endTime??n},{signal:r.signal});r.signal?.throwIfAborted?.();let a=Array.isArray(i)?i:i?.bars;if(!Array.isArray(a))throw new Error("strategy history provider returned no bars");return a}function cr(e,t){let r=e.backtestOptions??{};if(!ze(r))throw new TypeError("backtestOptions must be a plain object");return{...r,nowMs:t}}function fn(e,t,r,n,o={}){let s=e.evidenceOptions??{};if(!ze(s))throw new TypeError("evidenceOptions must be a plain object");return{...s,...o,strategy:t,bars:r,backtestOptions:cr(e,n)}}function dn(){return Qs.join(Xs.homedir(),".oracle","strategy-shadow.json")}function oi(e,t){return{perStrategyNotionalUsd:e.risk.maxNotionalUsd,maxLeverage:e.risk.maxLeverage,dailyLossCapUsd:e.risk.maxNotionalUsd*(e.risk.maxDailyLossPct/100),chainAllowlist:[e.venue],assetAllowlist:[e.market.coin],expiresAt:Math.min(e.risk.expiresAt,t+864e5),killSwitchRequired:!0}}async function si(e,t={},r={}){r.signal?.throwIfAborted?.();let n=ri(t),o=ni(n,r);if(e==="draft")return{strategy:Qt(n.prompt,{nowMs:o})};if(e==="validate"){let s=W(n.strategy);if(s.strategy.risk.expiresAt<=o)throw new Error("strategy is expired");return{valid:!0,strategy:s.strategy,strategyHash:s.strategyHash,compilerHash:s.compilerHash,compilerVersion:s.compilerVersion,requiredSeries:s.requiredSeries}}if(e==="backtest"||e==="evidence"){let s=W(n.strategy),i=await ir(s.strategy,n,r,o);De(s,i);let a=et(fn(n,s.strategy,i,o));return e==="evidence"?a:{backtest:ue(s.strategy,i,cr(n,o)),evidence:a}}if(e==="optimize"){let s=W(n.strategy),i=await ir(s.strategy,n,r,o);De(s,i);let a=n.trainFraction,l=n.evidenceOptions?.trainFraction;if(a!=null&&l!=null&&a!==l)throw new TypeError("conflicting trainFraction controls are forbidden");let f=a??l??.7;if(typeof f!="number"||f<=0||f>=1)throw new TypeError("trainFraction must be in (0,1)");let u=i.slice(0,Math.floor(i.length*f)),c=n.options??{};if(!ze(c))throw new TypeError("options must be a plain object");let d=Zt(s.strategy,u,{...c,...n.maxTrials==null?{}:{maxTrials:n.maxTrials},backtestOptions:cr(n,o)}),m=d.bestStrategy;return{strategy:m,optimization:d,evidence:et(fn(n,m,i,o,{trainFraction:f}))}}if(e==="shadow"){let s=lt({storePath:r.storePath??dn(),clock:()=>o}),i=n.action;if(i==="start")return await s.start({strategy:n.strategy,evidenceId:n.evidenceId??n.evidence?.id??null});if(i==="list")return await s.list();if(i==="get")return await s.get(n.id);if(i==="stop")return await s.stop(n.id);if(i==="step"){let a=await s.get(n.id);if(!a)throw new Error(`shadow runner not found: ${n.id}`);let l=await ir(a.strategy,n,r,o);return De(W(a.strategy),l),await s.step(n.id,l,n.stepOptions??{})}throw new Error(`unknown shadow action: ${i}`)}if(e==="prepare"){let s=W(n.strategy),i=rt(s.strategy.venue);if(typeof n.shadowId!="string"||!n.shadowId)throw new Error("strategy prepare requires a matching shadow runner id");let l=await lt({storePath:r.storePath??dn(),clock:()=>o}).get(n.shadowId);if(!l)throw new Error("strategy prepare shadow runner not found");if(l.status!=="running")throw new Error("strategy prepare requires an active shadow runner");if(!Number.isFinite(l.cursor))throw new Error("strategy prepare requires a stepped shadow runner");if(l.strategyHash!==s.strategyHash||l.compilerHash!==s.compilerHash)throw new Error("strategy prepare shadow runner does not match strategy artifacts");if(l.evidenceId!==n.evidence?.id)throw new Error("strategy prepare shadow runner does not match evidence artifact");let f=n.caps??oi(s.strategy,o);return i.prepareIntent({strategy:s.strategy,evidence:n.evidence,shadow:{id:l.id,stateHash:un(l),status:l.status,cursor:l.cursor,updatedAt:l.updatedAt},caps:f,nowMs:o,env:r.env??process.env})}throw new Error(`unknown strategy operation: ${e}`)}export{jr as EVIDENCE_STATUSES,Yt as MAX_OPTIMIZER_TRIALS,he as STRATEGY_COMPILER_HASH,Pe as STRATEGY_COMPILER_VERSION,nt as STRATEGY_VERSION,K as StrategyDraftError,ke as StrategyValidationError,$e as applyParameterOverrides,Ht as assertEvidenceArtifact,It as atr,fs as attachDerivedSeries,ue as backtestStrategy,$t as bollinger,Qr as canonicalStrategyJson,W as compileStrategy,Lt as computeEvidenceArtifactId,lt as createShadowRunner,us as deriveSeries,Qt as draftStrategyFromPrompt,He as ema,et as evaluateEvidence,qt as fetchHyperliquidStrategyBars,Hr as intervalToMs,Pt as macd,Fr as normalizeHyperliquidCandles,Z as normalizeStrategy,rr as openShadowStore,Zt as optimizeStrategy,Ut as prepareStrategyLiveHandoff,rt as requireStrategyVenue,tt as resolveStrategyVenue,Ot as rsi,si as runStrategyOperation,ls as sampleLiveSeries,At as sma,xe as strategyHash,Ko as strategyVenues,st as validateStrategy};