@oracle-agent/oracle 0.30.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- var An=Object.defineProperty;var V=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var Pn=(e,t)=>{for(var r in t)An(e,r,{get:t[r],enumerable:!0})};import ue from"node:net";import $n from"node:dns";function Ue(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("::"),a=r(n),s=r(o);if(!a||!s)return null;let i=t.includes("::"),l=8-a.length-s.length;if(!i&&l!==0||i&&l<1)return null;let u=[...a,...Array(Math.max(0,l)).fill(0),...s];return u.length!==8?null:Uint8Array.from(u.flatMap(d=>[d>>8,d&255]))}function tt(e,t,r){let n=Math.floor(r/8),o=r%8;for(let s=0;s<n;s+=1)if(e[s]!==t[s])return!1;if(!o)return!0;let a=255<<8-o;return(e[n]&a)===(t[n]&a)}function rt(e){if(ue.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(ue.isIPv6(e)){let t=Ue(e);if(!t)return!1;let r=Ue("::ffff:0:0");return tt(t,r,96)?rt([...t.slice(12)].join(".")):tt(t,Ue("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([o,a])=>tt(t,Ue(o),a)):!1}return!1}function _n(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(Tn.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=ue.isIP(r);return n!==0&&!rt(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function nt(e,{lookupFn:t=$n.promises.lookup}={}){let r=_n(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:ue.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=>!rt(o.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}async function ot({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(/\.+$/,""),a=new Map,s=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||(ue.isIPv6(f.address)?6:4)})),i=(c,f,p)=>{a.set(o(c),s(typeof f=="string"?[{address:f,family:p}]:f))},l=c=>{let f=o(c);if(ue.isIP(f))return[{address:f,family:ue.isIPv6(f)?6:4}];let p=a.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=In((c,f={})=>n(c,{...f,dispatcher:u}),i);return{dispatcher:u,fetch:d,pin:i,resolve:l,async close(){try{await u.destroy()}catch{}}}}function In(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[st]=Object.freeze({pin:t}),e}function it(e){return typeof e=="function"&&typeof e[st]?.pin=="function"}function Wt(e,t,r){if(!it(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[st].pin(t,r)}var Tn,st,Xt=V(()=>{Tn=new Set(["localhost","metadata.google.internal","metadata.goog"]);st=Symbol.for("oracle.egressGuard.pinCapableFetch")});import{createHash as vn}from"node:crypto";function jn(e){let t=String(e||"").toLowerCase();return nr.includes(t)||/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(t)}function Fn(e){let t={};for(let[r,n]of Object.entries(e||{}))jn(r)||(t[r]=n);return t}function Ln(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 Hn(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}function Cn(e,t,r,n={}){let o={};for(let[d,c]of Object.entries(r||{}))o[d.toLowerCase()]=c;let a=Object.keys(o).filter(d=>/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(d)),i=[...new Set([...nr,...a])].sort().map(d=>`${d}=${o[d]??""}`).join(`
2
- `),l=vn("sha256").update(i).digest("hex").slice(0,32),u=`${n.untrustedUrl?"untrusted":"trusted"}:${n.maxResponseBytes??"unbounded"}`;return`${e} ${t} ${u} ${l}`}function qn(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,Qt):Math.min(250*2**e,Qt)+Math.floor(Math.random()*100)}function Te(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function ct(e,t,r){return Te(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function _e(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function Bn(e){return e?e.byteLength??e.length??0:0}async function tr(e,t,{url:r,truncate:n=!1,onOversize:o}={}){if(t==null)return await e.text();let a=Number(e.headers?.get?.("content-length"));if(Number.isFinite(a)&&a>t&&(_e(e),!n))throw ct(r,`content-length ${a}`,t);let s=e.body?.getReader?.();if(!s){let c=await e.text(),f=Buffer.byteLength(c,"utf8");if(f>t){if(!n)throw ct(r,`body ${f} bytes`,t);return Buffer.from(c,"utf8").subarray(0,t).toString("utf8")}return c}let i=[],l=0,u=!1;try{for(;;){let{value:c,done:f}=await s.read();if(f)break;if(c&&(i.push(Buffer.from(c)),l+=Bn(c),l>t)){u=!0;break}}}finally{if(u)try{await s.cancel()}catch{}try{s.releaseLock?.()}catch{}}if(u&&(typeof o=="function"&&o(),!n))throw ct(r,`streamed ${l} bytes`,t);let d=Buffer.concat(i);return(u?d.subarray(0,t):d).toString("utf8")}function rr(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function zn(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:a,lookupFn:s,realFetch:i,untrustedUrl:l=!1,maxResponseBytes:u=null,importUndici:d,validateResponse:c,signal:f}){let p=new AbortController,h=setTimeout(()=>p.abort(),a),w=f?typeof AbortSignal.any=="function"?AbortSignal.any([f,p.signal]):f:p.signal,b=null,k=t,$=s?{lookupFn:s}:{};if(l&&!i&&!it(k))throw Te(`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 I=async(x,{status:_=null}={})=>{let A=await nt(x,$);if(!A.ok)throw Te(_==null?`HTTP refused ${x}: ${A.error}`:`HTTP redirect to ${x} ${A.error}`,_==null?{}:{status:_});let m=new URL(x).hostname;if(i){if(b&&(await b.close(),b=null),!b)try{b=await ot({requireUndici:!0,...d?{importUndici:d}:{}})}catch(M){throw Te(_==null?`HTTP refused ${x}: ${M?.message||M}`:`HTTP redirect to ${x} refused: ${M?.message||M}`,_==null?{}:{status:_})}b.pin(m,A.addresses),k=b.fetch}else Wt(k,m,A.addresses);return A};try{let x=String(e),_={...n||{}};l&&await I(x);for(let A=0;A<=er;A+=1){let m=await k(x,{method:r,headers:_,body:o,signal:w,redirect:"manual"});if(Mn.has(m.status)){if(r!=="GET"&&r!=="HEAD"){let P=await tr(m,u??Rn,{url:x,truncate:!0}),T=new Error(`HTTP ${m.status} ${r} ${x} redirected non-idempotent request`);throw T.status=m.status,T.body=rr(P)??P.slice(0,300),T}if(A===er)throw _e(m),new Error(`HTTP redirect loop for ${e}`);let U=m.headers?.get?.("location"),D;try{D=Ln(U,x)}catch(P){throw _e(m),P}let y=!Hn(D,x);if(_e(m),y&&(_=Fn(_)),l)await I(D,{status:m.status});else if(y){let P=await nt(D,$);if(!P.ok){let T=new Error(`HTTP redirect from ${x} ${P.error}`);throw T.status=m.status,T.retryable=!1,T}i&&P.addresses?.length&&(b||(b=await ot(d?{importUndici:d}:{})),b&&(b.pin(new URL(D).hostname,P.addresses),k=b.fetch))}x=D;continue}if(typeof c=="function")try{await c(m,{url:x})}catch(U){throw _e(m),Te(U?.message||String(U))}let M=await tr(m,u,{url:x,onOversize:()=>p.abort()}),W=rr(M);if(!m.ok){let U=new Error(`HTTP ${m.status} ${r} ${x}`);throw U.status=m.status,U.retryAfter=m.headers?.get?.("retry-after")??null,U.body=W??M.slice(0,300),U}return W??M}throw new Error(`HTTP redirect loop for ${e}`)}finally{clearTimeout(h),b&&await b.close()}}async function or(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(),a={Accept:"application/json",...t.headers||{}},s=t.body;s!=null&&typeof s!="string"&&(a["Content-Type"]=a["Content-Type"]||"application/json",s=JSON.stringify(s));let i=Number.isInteger(t.retries)?Math.max(t.retries,0):Nn,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,b=async()=>{let _;for(let A=0;A<=i;A++){p?.throwIfAborted?.();try{return await zn(e,{fetchImpl:r,method:o,headers:a,body:s,timeoutMs:n,lookupFn:l,realFetch:u,untrustedUrl:d,maxResponseBytes:w,importUndici:c,validateResponse:f,signal:p})}catch(m){_=m;let M=m?.status,W=m?.name==="AbortError"||m?.name==="TimeoutError"||p?.aborted,U=new Set([408,425,429]),D=m?.retryable===!1?!1:M!=null?U.has(M)||On.has(M)&&Zt.has(o):!W&&Zt.has(o);if(A===i||!D)throw m;let y=qn(A,m?.retryAfter);p?await new Promise((P,T)=>{let j=setTimeout(P,y);p.addEventListener("abort",()=>{clearTimeout(j),T(p.reason||new DOMException("Aborted","AbortError"))},{once:!0})}):await Un(y)}}throw _};if(!(t.dedupe!==!1&&!p&&o==="GET"&&s==null))return b();let $=Cn(o,e,a,{untrustedUrl:d,maxResponseBytes:w}),I=at.get($);if(I)return I;let x=b().finally(()=>at.delete($));return at.set($,x),x}var On,Zt,Nn,Qt,nr,Mn,er,Rn,at,Un,sr=V(()=>{Xt();On=new Set([408,425,429,500,502,503,504]),Zt=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),Nn=2,Qt=4e3,nr=["authorization","x-api-key","x-tensor-api-key","0x-api-key","api-key","cookie","proxy-authorization"],Mn=new Set([301,302,303,307,308]),er=3,Rn=64*1024;at=new Map;Un=e=>new Promise(t=>setTimeout(t,e))});function Jn({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"?Vn:Dn}async function lt(e,t={}){if(!e||!e.type)throw new Error("hlInfo requires body.type");let r=Jn(t);return or(r,{method:"POST",body:e,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs})}async function ir(e={}){return lt({type:"meta"},e)}async function ar({coin:e,interval:t="1h",startTime:r,endTime:n},o={}){if(!e)throw new Error("hlCandleSnapshot requires coin");let a={type:"candleSnapshot",req:{coin:String(e),interval:t,startTime:r??Date.now()-24*3600*1e3,endTime:n??Date.now()}};return lt(a,o)}async function cr({coin:e,startTime:t,endTime:r},n={}){if(!e)throw new Error("hlFundingHistory requires coin");return lt({type:"fundingHistory",coin:String(e),startTime:t??Date.now()-24*3600*1e3,endTime:r??Date.now()},n)}var Dn,Vn,ut=V(()=>{sr();Dn="https://api.hyperliquid.xyz/info",Vn="https://api.hyperliquid-testnet.xyz/info"});import{createHash as Kn}from"node:crypto";function re(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function we(e){return typeof e=="number"&&Number.isFinite(e)}function pt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)pt(t);return Object.freeze(e)}for(let t of Object.keys(e))pt(e[t]);return Object.freeze(e)}function fe(e){if(Array.isArray(e))return e.map(fe);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=fe(e[r]);return t}return e}function ft(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 lr(e){return{feesUsd:e.costs.feesUsd,builderFeesUsd:e.costs.builderFeesUsd,fundingUsd:e.costs.fundingUsd,slippageUsd:e.costs.slippageUsd}}function Gn(e){return(e.feesUsd||0)+(e.builderFeesUsd||0)+Math.max(0,e.fundingUsd||0)+(e.slippageUsd||0)}function Wn(e){let t=0;for(let r of e.trades)r.grossPnlUsd>0&&(t+=r.grossPnlUsd);return t}function Xn(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 fr(e){if(!re(e))throw new TypeError("evidence artifact must be a plain object");if(!Yn.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 fe({barsHash:e.barsHash,compilerHash:e.compilerHash,flags:e.flags.map(t=>fe(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 dr(e){return Kn("sha256").update(JSON.stringify(fr(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 dt(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(!we(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 Zn(e,{maxDailyLossPct:t}={}){let r=e.split,n=Z(r.trainStartIndex,"split.trainStartIndex"),o=Z(r.trainEndIndex,"split.trainEndIndex"),a=Z(r.trainBarCount,"split.trainBarCount",1),s=Z(r.holdoutStartIndex,"split.holdoutStartIndex"),i=Z(r.holdoutEndIndex,"split.holdoutEndIndex"),l=Z(r.holdoutBarCount,"split.holdoutBarCount",1);if(n!==0||o-n+1!==a||s!==o+1||i-s+1!==l)throw new Error("evidence split must be contiguous, chronological, and count-consistent");if(!we(r.trainFraction)||r.trainFraction<=0||r.trainFraction>=1)throw new Error("split.trainFraction must be in (0,1)");dt(e.train,"train");let u=dt(e.holdout,"holdout");if(u.tradeCount<1||u.netPnlUsd<=0||u.profitFactor<=1)throw new Error("live-eligible holdout metrics do not pass");if(we(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 b=c[w];if(!re(b)||b.index!==w||typeof b.passed!="boolean")throw new Error("walk-forward windows must be ordered and structurally valid");let k=Z(b.trainStartIndex,`walkForward.windows[${w}].trainStartIndex`),$=Z(b.trainEndIndex,`walkForward.windows[${w}].trainEndIndex`),I=Z(b.evalStartIndex,`walkForward.windows[${w}].evalStartIndex`),x=Z(b.evalEndIndex,`walkForward.windows[${w}].evalEndIndex`);if(k!==0||$>=I||I>x||I<=p)throw new Error("walk-forward windows must be chronological and disjoint");if(p=x,b.passed){if(f+=1,b.reason!=="pass")throw new Error("passed walk-forward window reason must be pass");let _=dt({metrics:b.metrics,tradeCount:b.metrics?.tradeCount},`walkForward.windows[${w}]`);if(_.tradeCount<1||_.netPnlUsd<=0||_.profitFactor<=1)throw new Error("passed walk-forward window metrics do not pass");if(we(t)&&_.maxDrawdownPct>t)throw new Error("passed walk-forward drawdown exceeds strategy risk")}else if(b.reason==="pass")throw new Error("failed walk-forward window cannot have pass reason")}let h=f/c.length;if(!we(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 pr(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=fr(e),n=fe({id:e.id,...r});if(JSON.stringify(fe(e))!==JSON.stringify(n))throw new Error("evidence artifact contains fields unbound from its deterministic identity");let o=dr(e);if(e.id!==o)throw new Error("evidence.id does not match its deterministic artifact facts digest");return e.status==="pass_live_eligible"&&Zn(e,t),e}function mt({strategy:e,bars:t,backtestOptions:r={},trainFraction:n=.7,walkForwardWindows:o=3,minTrades:a=10}={}){let s=[];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(!we(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(a)||a<0)throw new TypeError("minTrades must be an integer >= 0");let i=Y(e),l=ge(i),u=Ie(t),d=t.length,c=(O=[],R={})=>ur({status:"fail",strategy:i,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:[...s,...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),b=t.slice(p),k,$;try{k=ae(i,w,r),$=ae(i,b,r)}catch(O){return c([{type:"backtest_error",message:String(O.message||O)}])}let I={metrics:ft(k),costs:lr(k),tradeCount:k.metrics.tradeCount},x={metrics:ft($),costs:lr($),tradeCount:$.metrics.tradeCount},_={trainStartIndex:0,trainEndIndex:f-1,trainBarCount:f,holdoutStartIndex:p,holdoutEndIndex:d-1,holdoutBarCount:h,trainFraction:n},A=[],m=Math.floor(d/(o+1));if(m<3)s.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,B=Math.min(d,J+m);if(B-J<3||R<3){A.push({index:O,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:J,evalEndIndex:B-1,passed:!1,reason:"window_too_small",metrics:null});continue}let ee=t.slice(J,B),He;try{He=ae(i,ee,r)}catch{A.push({index:O,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:J,evalEndIndex:B-1,passed:!1,reason:"backtest_error",metrics:null});continue}let Ce=ft(He),qe=Xn(Ce,i.risk,a);A.push({index:O,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:J,evalEndIndex:B-1,passed:qe,reason:qe?"pass":"fail_metrics",metrics:Ce})}let M=A.filter(O=>O.passed).length,W=A.length===0?0:M/A.length,U={windows:A,passRate:W,windowsRun:A.length};x.metrics.tradeCount===0&&I.metrics.tradeCount===0&&s.push({type:"no_trades",message:"no trades in train or holdout"}),x.metrics.tradeCount===0&&s.push({type:"absent_oos_trades",message:"holdout produced no trades"}),x.metrics.netPnlUsd<0&&s.push({type:"holdout_loss",message:"holdout netPnlUsd is negative"}),I.metrics.netPnlUsd>0&&x.metrics.netPnlUsd<0&&I.metrics.netPnlUsd>Math.abs(x.metrics.netPnlUsd)*.25?s.push({type:"overfit",message:"profitable train with losing holdout (OOS collapse)"}):I.metrics.netPnlUsd>0&&x.metrics.netPnlUsd>0&&x.metrics.netPnlUsd<I.metrics.netPnlUsd*.1&&I.metrics.tradeCount>=a&&s.push({type:"severe_oos_collapse",message:"holdout pnl collapsed vs train"});let D=Gn(x.costs),y=Wn($);y>0&&D>y&&s.push({type:"costs_exceed_gross",message:"holdout costs exceed gross gains"});let P=s.some(O=>["insufficient_bars","invalid_windowing","absent_oos_trades","holdout_loss","no_trades","severe_oos_collapse","backtest_error"].includes(O.type)),T=s.some(O=>O.type==="overfit"),j="fail";return x.metrics.tradeCount>=a&&x.metrics.netPnlUsd>0&&x.metrics.profitFactor>1&&x.metrics.maxDrawdownPct<=i.risk.maxDailyLossPct&&W>=.6&&!(y>0&&D>y)&&!T&&!s.some(O=>O.type==="severe_oos_collapse"||O.type==="invalid_windowing")?j="pass_live_eligible":!P&&x.metrics.tradeCount>0&&I.metrics.tradeCount>0&&Number.isFinite(x.metrics.netPnlUsd)?(j="pass_paper_only",x.metrics.tradeCount<a&&s.push({type:"undersampled",message:"holdout trades below minTrades"})):T&&x.metrics.tradeCount>0&&I.metrics.netPnlUsd>0?j="fail":x.metrics.tradeCount>0&&I.metrics.tradeCount>0&&!P?j="pass_paper_only":j="fail",x.metrics.netPnlUsd<0&&(j=j==="pass_live_eligible"?"fail":j==="pass_paper_only"?"pass_paper_only":"fail",j="fail"),ur({status:j,strategy:i,sHash:l,barsHash:u,split:_,train:I,holdout:x,walkForward:U,flags:s})}function ur({status:e,strategy:t,sHash:r,barsHash:n,split:o,train:a,holdout:s,walkForward:i,flags:l}){let u={status:e,strategyHash:r,compilerHash:pe,barsHash:n,split:o,train:a,holdout:s,walkForward:i,flags:l};return u.id=dr(u),pt(fe(JSON.parse(JSON.stringify(u))))}var Yn,ht=V(()=>{me();de();Be();Yn=Object.freeze(["fail","pass_paper_only","pass_live_eligible"])});import{createHash as Qn,createHmac as eo,timingSafeEqual as di}from"node:crypto";function yt(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(yt).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${yt(e[r])}`).join(",")}}`}function mr(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function hr(e=process.env){return mr(process.env)||mr(e)}function oo(e){let{prepareHash:t,prepareMac:r,note:n,...o}=e||{};return o}function so(e){let t=oo(e);return Qn("sha256").update(yt(t)).digest("hex")}function io(e,t=hr()){return t?eo("sha256",t).update(String(e)).digest("hex"):""}function yr(e,{provider:t,kind:r,env:n=process.env,nowMs:o=Date.now(),expiresAtMs:a}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let s=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(s&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let i={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1,oraclePrepared:s?e.oraclePrepared:!0};if(!i.provider)throw new Error("stampPrepared: provider required");if(!i.kind)throw new Error("stampPrepared: kind required");let l=Number(o),u=a==null?l+ro:Number(a),d=u-l;if(!Number.isSafeInteger(l)||!Number.isSafeInteger(u)||d<=0||d>no)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let f={...i,preparedAt:l,expiresAt:u,prepareVersion:to},p=so(f),h=hr(n),w=h?io(p,h):void 0,b={...f,prepareHash:p};return w&&(b.prepareMac=w),b}var to,ro,no,wr=V(()=>{to=2,ro=300*1e3,no=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})()});function ve(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function co(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function gt(e,t="value"){if(Array.isArray(e)){e.forEach((r,n)=>gt(r,`${t}[${n}]`));return}if(ve(e))for(let[r,n]of Object.entries(e)){let o=co(r);if(ao.some(a=>o.includes(a)))throw new Error(`handoff: forbidden secret-like field at ${t}.${r}`);gt(n,`${t}.${r}`)}}function wt(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function gr({strategy:e,evidence:t,shadow:r,caps:n,nowMs:o=Date.now(),env:a=process.env}={}){if(gt({strategy:e,evidence:t,shadow:r,caps:n},"handoff"),!ve(e))throw new Error("handoff: strategy required");if(!ve(t))throw new Error("handoff: evidence required");if(!ve(r))throw new Error("handoff: shadow required");if(!ve(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 s=Y(e,{nowMs:o}),i=G(s);if(pr(t,{maxDailyLossPct:s.risk.maxDailyLossPct}),t.status!=="pass_live_eligible")throw new Error("handoff: evidence.status must be pass_live_eligible");if(t.strategyHash!==i.strategyHash)throw new Error("handoff: evidence.strategyHash mismatch");if(t.compilerHash!==i.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(!wt(n.perStrategyNotionalUsd))throw new Error("handoff: caps.perStrategyNotionalUsd must be positive");if(n.perStrategyNotionalUsd>i.strategy.risk.maxNotionalUsd)throw new Error("handoff: caps.perStrategyNotionalUsd exceeds strategy.risk.maxNotionalUsd");if(!wt(n.maxLeverage))throw new Error("handoff: caps.maxLeverage must be positive");if(n.maxLeverage>i.strategy.risk.maxLeverage)throw new Error("handoff: caps.maxLeverage exceeds strategy.risk.maxLeverage");if(!wt(n.dailyLossCapUsd))throw new Error("handoff: caps.dailyLossCapUsd must be positive");let u=i.strategy.risk.maxNotionalUsd*(i.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]!==i.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>i.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:i.strategyHash,compilerHash:i.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:i.strategyHash,compilerHash:i.compilerHash,compilerVersion:Oe,venue:"hyperliquid",market:{coin:i.strategy.market.coin,kind:"perp",interval:i.strategy.market.interval},risk:{...i.strategy.risk},strategy:JSON.parse(JSON.stringify(i.strategy))},arming:{liveBroadcast:!1,requiresExplicitUserArm:!0,caps:d},requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,executionReady:!1};return yr(c,{provider:"hl-strategy",kind:"strategy-live-handoff",env:a})}var ao,br=V(()=>{me();ht();de();wr();ao=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"]});function be(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function Ee(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be a non-negative safe integer`);return e}function Ne(e){if(Array.isArray(e))for(let t of e)Ne(t);else if(e&&typeof e=="object")for(let t of Object.values(e))Ne(t);return Object.freeze(e)}function uo(e){let t=lo[e];if(!t)throw new TypeError(`unsupported strategy interval: ${e}`);return t}function fo(e,{endTime:t=Number.MAX_SAFE_INTEGER}={}){if(!Array.isArray(e))throw new TypeError("Hyperliquid candles must be an array");Ee(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 a=Ee(Number(o.t),`candles[${n}].t`);if(Ee(Number(o.T),`candles[${n}].T`)>t)continue;let i={t:a,o:be(o.o,`candles[${n}].o`),h:be(o.h,`candles[${n}].h`),l:be(o.l,`candles[${n}].l`),c:be(o.c,`candles[${n}].c`),v:be(o.v,`candles[${n}].v`)};if(i.h<Math.max(i.o,i.c,i.l))throw new TypeError(`candles[${n}].h is below another price`);if(i.l>Math.min(i.o,i.c,i.h))throw new TypeError(`candles[${n}].l is above another price`);if(i.v<0)throw new TypeError(`candles[${n}].v must be non-negative`);let l=r.get(a);if(l&&JSON.stringify(l)!==JSON.stringify(i))throw new TypeError(`conflicting duplicate candle at timestamp ${a}`);l||r.set(a,i)}return Ne([...r.values()].sort((n,o)=>n.t-o.t))}function po(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 a=Ee(Number(o.time),`funding[${n}].time`);a>t||r.set(a,{time:a,fundingRate:be(o.fundingRate,`funding[${n}].fundingRate`)})}return[...r.values()].sort((n,o)=>n.time-o.time)}async function mo({coin:e,startTime:t,endTime:r},n){let o=[],a=Math.max(0,t-288e5),s=!1;for(let i=0;i<16&&a<=r;i++){let l=await cr({coin:e,startTime:a,endTime:r},n);if(!Array.isArray(l))throw new TypeError("Hyperliquid funding history must be an array");o.push(...l);let u=a;for(let d of l){let c=Number(d?.time);Number.isSafeInteger(c)&&c>u&&(u=c)}if(l.length<500||u>=r){s=!0;break}if(u<=a)throw new Error("Hyperliquid funding history pagination did not advance");a=u+1}if(!s)throw new Error("strategy history exceeds the bounded funding history limit");return po(o,r)}function ho(e,t,r){let n=0,o=null;return e.map(a=>{let s=a.t+r,i=0;for(;n<t.length&&t[n].time<s;){let l=t[n];o=l.fundingRate,l.time>=a.t&&(i+=l.fundingRate),n+=1}return o==null?{...a,fundingPaymentRate:i}:{...a,fundingRate:o,fundingPaymentRate:i}})}async function Er(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=uo(n);if(e.endTime==null)throw new TypeError("endTime is required for deterministic history");let a=Ee(e.endTime,"endTime"),s=e.count==null?1500:e.count;if(!Number.isInteger(s)||s<20||s>5e3)throw new TypeError("count must be an integer from 20 to 5000");let i=e.startTime==null?Math.max(0,a-s*o):Ee(e.startTime,"startTime");if(i>=a)throw new TypeError("startTime must be before endTime");let[l,u]=await Promise.all([ar({coin:r,interval:n,startTime:i,endTime:a},t),mo({coin:r,startTime:i,endTime:a},t)]),d=fo(l,{endTime:a}),c=Ne(ho(d,u,o));return Ne({coin:r,interval:n,range:{startTime:i,endTime:a},bars:c})}var lo,xr=V(()=>{ut();lo=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 go(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))wo.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"||!yo.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 bo(e={}){let t=await ir(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 yo,wo,kr,Sr=V(()=>{ut();br();xr();yo=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),wo=new Set(["coin","interval"]);kr=Object.freeze({id:"hyperliquid",validateMarket:go,fetchBars:Er,listMarkets:bo,prepareIntent(e){return gr(e)}})});function xo(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 Eo.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}function bt(e){return typeof e!="string"?null:ko.get(e)??null}function Et(e){let t=bt(e);if(!t)throw new Error(`unknown strategy venue: ${String(e)}`);return t}var Eo,Ar,ko,$i,xt=V(()=>{Sr();Eo=Object.freeze(["id","validateMarket","prepareIntent"]);Ar=[kr].map(xo),ko=new Map(Ar.map(e=>[e.id,e])),$i=Object.freeze([...Ar])});import{createHash as So}from"node:crypto";function X(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function q(e){return typeof e=="number"&&Number.isFinite(e)}function Nr(e){return Number.isInteger(e)&&e>0}function $t(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)$t(t);return Object.freeze(e)}for(let t of Object.keys(e))$t(e[t]);return Object.freeze(e)}function Tt(e){if(Array.isArray(e))return e.map(Tt);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Tt(e[r]);return t}return e}function g(e,t,r){e.push({path:t,message:r})}function ce(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 Fr(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 a=Math.round(o);return Math.abs(o-a)<=1e-9}function Pt(e,t,r,n){if(X(e)){if(ce(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!X(o)||![o.value,o.min,o.max,o.step].every(Nr)?(g(n,`${t}.param`,"referenced period parameter value min max and step must be positive integers"),null):{param:e.param}}return Nr(e)?e:(g(n,t,"must be a positive integer or {param}"),null)}function Mr(e,t,r,n){return X(e)?(ce(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)):q(e)?e:(g(n,t,"must be a finite number or {param}"),null)}function ze(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 No(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 a=e.get(n);if(a){for(let s of ze(a))if(e.has(s)&&r(s))return!0}return t.set(n,2),!1};for(let n of e.keys())if(r(n))return!0;return!1}function Mo(e,t){if(!X(e))return g(t,"parameters","must be a plain object"),null;let r=Object.keys(e);if(r.length>Ir)return g(t,"parameters",`too many parameters (max ${Ir})`),null;let n={};for(let o of r){if(!Rr.test(o)){g(t,`parameters.${o}`,"parameter name is malformed");continue}let a=e[o],s=`parameters.${o}`;if(!X(a)){g(t,s,"must be a plain object");continue}ce(a,$r,s,t);for(let c of $r)c in a||g(t,`${s}.${c}`,"required field is missing");let{value:i,min:l,max:u,step:d}=a;q(l)||g(t,`${s}.min`,"must be a finite number"),q(u)||g(t,`${s}.max`,"must be a finite number"),(!q(d)||d<=0)&&g(t,`${s}.step`,"must be a positive finite number"),q(i)||g(t,`${s}.value`,"must be a finite number"),q(l)&&q(u)&&l>u&&g(t,`${s}.min`,"min must be <= max"),q(i)&&q(l)&&q(u)&&q(d)&&d>0&&(Fr(i,l,u,d)||g(t,`${s}.value`,"value must lie on the declared min/max/step grid")),n[o]={value:i,min:l,max:u,step:d}}return n}function Ro(e,t,r,n){let o=`nodes.${t}`;if(!X(e))return g(n,o,"must be a plain object"),null;if(typeof e.type!="string"||!_r[e.type])return g(n,`${o}.type`,"unknown or missing node type"),ce(e,Oo,o,n),null;switch(ce(e,_r[e.type],o,n),(typeof e.id!="string"||!jr.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"||!Ao.has(e.field))&&g(n,`${o}.field`,"must be one of open|high|low|close|volume|fundingRate|openInterest"),{id:e.id,type:"input",field:e.field};case"constant":{let a=Mr(e.value,`${o}.value`,r,n);return{id:e.id,type:"constant",value:a}}case"indicator":{(typeof e.indicator!="string"||!Po.has(e.indicator))&&g(n,`${o}.indicator`,"must be one of sma|ema|rsi|macd|bollinger|atr");let a=e.indicator,s={id:e.id,type:"indicator",indicator:a};if(a==="atr"){"input"in e&&(typeof e.input!="string"||!e.input?g(n,`${o}.input`,"must be a node id string when provided"):s.input=e.input);let i=Pt(e.period,`${o}.period`,r,n);i!=null&&(s.period=i)}else typeof e.input!="string"||!e.input?g(n,`${o}.input`,"must be a node id string"):s.input=e.input;if((a==="sma"||a==="ema"||a==="rsi"||a==="bollinger"||a==="atr")&&("period"in e,a!=="macd"))if(!("period"in e))g(n,`${o}.period`,"required field is missing");else{let i=Pt(e.period,`${o}.period`,r,n);i!=null&&(s.period=i)}if(a==="macd"){for(let i of["fastPeriod","slowPeriod","signalPeriod"])if(!(i in e))g(n,`${o}.${i}`,"required field is missing");else{let l=Pt(e[i],`${o}.${i}`,r,n);l!=null&&(s[i]=l)}"output"in e?Io.has(e.output)?s.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(a==="bollinger"){if(!("stdDev"in e))g(n,`${o}.stdDev`,"required field is missing");else{let i=Mr(e.stdDev,`${o}.stdDev`,r,n);i!=null&&(typeof i=="number"&&i<=0?g(n,`${o}.stdDev`,"must be > 0"):s.stdDev=i)}"output"in e?vo.has(e.output)?s.output=e.output:g(n,`${o}.output`,"must be upper|middle|lower"):g(n,`${o}.output`,"required field is missing");for(let i of["fastPeriod","slowPeriod","signalPeriod"])i in e&&g(n,`${o}.${i}`,`forbidden for ${a}`)}else{"output"in e&&g(n,`${o}.output`,`forbidden for ${a}`),"stdDev"in e&&a!=="bollinger"&&g(n,`${o}.stdDev`,`forbidden for ${a}`);for(let i of["fastPeriod","slowPeriod","signalPeriod"])i in e&&g(n,`${o}.${i}`,`forbidden for ${a}`)}return s}case"compare":return(typeof e.op!="string"||!$o.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"||!To.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 a=[];for(let s=0;s<e.inputs.length;s++){let i=e.inputs[s];typeof i!="string"||!i?g(n,`${o}.inputs.${s}`,"must be a node id"):a.push(i)}return e.op==="not"?a.length!==1&&g(n,`${o}.inputs`,"not requires exactly one input"):(e.op==="and"||e.op==="or")&&a.length<2&&g(n,`${o}.inputs`,`${e.op} requires at least two inputs`),{id:e.id,type:"logic",op:e.op,inputs:a}}case"cross":return(typeof e.direction!="string"||!_o.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 jo(e,t,r){if(!X(e))return g(t,"risk","must be a plain object"),null;ce(e,Tr,"risk",t);for(let f of Tr)(!(f in e)||e[f]==null)&&g(t,`risk.${f}`,"required field is missing");let n={},o=e.maxLeverage;!q(o)||o<=0||o>50?g(t,"risk.maxLeverage","must be a number > 0 and <= 50"):n.maxLeverage=o;let a=e.maxNotionalUsd;!q(a)||a<=0?g(t,"risk.maxNotionalUsd","must be a number > 0"):n.maxNotionalUsd=a;let s=e.positionSizePct;!q(s)||s<=0||s>100?g(t,"risk.positionSizePct","must be a number > 0 and <= 100"):n.positionSizePct=s;let i=e.stopLossPct;!q(i)||i<=0||i>100?g(t,"risk.stopLossPct","must be a number > 0 and <= 100"):n.stopLossPct=i;let l=e.takeProfitPct;!q(l)||l<=0||l>1e3?g(t,"risk.takeProfitPct","must be a number > 0 and <= 1000"):n.takeProfitPct=l;let u=e.cooldownBars;!Number.isInteger(u)||u<0||u>1e5?g(t,"risk.cooldownBars","must be an integer >= 0 and <= 100000"):n.cooldownBars=u;let d=e.maxDailyLossPct;!q(d)||d<=0||d>100?g(t,"risk.maxDailyLossPct","must be a number > 0 and <= 100"):n.maxDailyLossPct=d;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 _t(e,t={}){let r=[];if(!X(e))return g(r,"","strategy must be a plain object"),{ok:!1,errors:r,strategy:null};ce(e,Pr,"",r);for(let c of Pr)(!(c in e)||e[c]==null)&&g(r,c,"required field is missing");e.version!==kt&&g(r,"version",`must be ${kt}`),(typeof e.id!="string"||!Rr.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>Or)&&g(r,"name",`must be a non-empty string max ${Or}`);let n=bt(e.venue);n||g(r,"venue",`unknown strategy venue "${String(e.venue)}"`);let o=null;if(!n)X(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 f of c.errors)g(r,f.path,f.message)}let a=Mo(e.parameters,r),s=null,i=new Map;if(!Array.isArray(e.nodes))g(r,"nodes","must be an array");else if(e.nodes.length>vr)g(r,"nodes",`too many nodes (max ${vr})`);else{s=[];for(let c=0;c<e.nodes.length;c++){let f=Ro(e.nodes[c],c,a||{},r);f&&(typeof f.id=="string"&&jr.test(f.id)&&(i.has(f.id)?g(r,`nodes.${c}.id`,`duplicate node id "${f.id}"`):i.set(f.id,f)),s.push(f))}for(let c=0;c<s.length;c++){let f=s[c],p=`nodes.${c}`;for(let h of ze(f))i.has(h)||g(r,p,`unknown node ref "${h}"`);if(f.type==="indicator"||f.type==="compare"||f.type==="cross")for(let h of ze(f)){let w=i.get(h);w&&St.has(w.type)&&g(r,p,`node ref "${h}" must be numeric`)}if(f.type==="logic")for(let h of ze(f)){let w=i.get(h);w&&!St.has(w.type)&&g(r,p,`node ref "${h}" must be boolean`)}}No(i)&&g(r,"nodes","graph contains a cycle")}let l=null;if(!X(e.rules))g(r,"rules","must be a plain object");else{ce(e.rules,At,"rules",r);for(let c of At)c in e.rules||g(r,`rules.${c}`,"required field is missing");l={};for(let c of At){let f=e.rules[c];if(f===null){l[c]=null;continue}if(typeof f!="string"||!f){g(r,`rules.${c}`,"must be a node id or null"),l[c]=f;continue}if(!i.has(f)){g(r,`rules.${c}`,`unknown node ref "${f}"`),l[c]=f;continue}let p=i.get(f);St.has(p.type)||g(r,`rules.${c}`,`rule must reference a boolean node, not ${p.type}`),l[c]=f}}let u=jo(e.risk,r,t);if(r.length)return{ok:!1,errors:r,strategy:null};let d=$t({version:kt,id:e.id,name:e.name,venue:n.id,market:o,parameters:a,nodes:s,rules:l,risk:u});return{ok:!0,errors:[],strategy:d}}function Y(e,t={}){let r=_t(e,t);if(!r.ok)throw new xe(r.errors);return r.strategy}function Fo(e){let t=Y(e);return JSON.stringify(Tt(t))}function ge(e){let t=Fo(e);return So("sha256").update(t,"utf8").digest("hex")}function Me(e,t){if(!X(e))throw new xe([{path:"",message:"strategy must be a plain object"}]);if(!X(t))throw new xe([{path:"overrides",message:"must be a plain object"}]);let r=Y(e),n={};for(let[a,s]of Object.entries(r.parameters))n[a]={value:s.value,min:s.min,max:s.max,step:s.step};let o=[];for(let[a,s]of Object.entries(t)){if(!Object.prototype.hasOwnProperty.call(n,a)){g(o,a,`unknown parameter "${a}"`);continue}let i=n[a];if(!q(s)){g(o,a,"override must be a finite number");continue}if(!Fr(s,i.min,i.max,i.step)){g(o,a,"override must lie on the declared min/max/step grid");continue}n[a]={...i,value:s}}if(o.length)throw new xe(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(a=>{let s={...a};return Array.isArray(a.inputs)&&(s.inputs=[...a.inputs]),s}),rules:{...r.rules},risk:{...r.risk}})}var kt,Rr,jr,Ao,Po,$o,To,_o,Io,vo,St,Pr,$r,At,Tr,Oo,_r,Ir,vr,Or,xe,de=V(()=>{xt();kt=1,Rr=/^[a-z0-9][a-z0-9._-]{0,63}$/,jr=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Ao=new Set(["open","high","low","close","volume","fundingRate","openInterest"]),Po=new Set(["sma","ema","rsi","macd","bollinger","atr"]),$o=new Set(["gt","gte","lt","lte","eq"]),To=new Set(["and","or","not"]),_o=new Set(["above","below"]),Io=new Set(["line","signal","histogram"]),vo=new Set(["upper","middle","lower"]),St=new Set(["compare","logic","cross"]),Pr=new Set(["version","id","name","venue","market","parameters","nodes","rules","risk"]),$r=new Set(["value","min","max","step"]),At=new Set(["entryLong","entryShort","exitLong","exitShort"]),Tr=new Set(["maxLeverage","maxNotionalUsd","positionSizePct","stopLossPct","takeProfitPct","cooldownBars","maxDailyLossPct","expiresAt"]),Oo=new Set(["id","type"]),_r={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"])},Ir=16,vr=128,Or=100,xe=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 Re(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 le(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("period must be a positive integer")}function Lo(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 Hr(e,t){Re(e),le(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 De(e,t){Re(e),le(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=0;for(let s=0;s<t;s++)n+=e[s];let o=n/t;r[t-1]=o;let a=2/(t+1);for(let s=t;s<e.length;s++)o=a*e[s]+(1-a)*o,r[s]=o;return r}function Cr(e,t){Re(e),le(t);let r=new Array(e.length).fill(null);if(e.length<=t)return r;let n=0,o=0;for(let i=1;i<=t;i++){let l=e[i]-e[i-1];l>=0?n+=l:o-=l}let a=n/t,s=o/t;r[t]=Lr(a,s);for(let i=t+1;i<e.length;i++){let l=e[i]-e[i-1],u=l>0?l:0,d=l<0?-l:0;a=(a*(t-1)+u)/t,s=(s*(t-1)+d)/t,r[i]=Lr(a,s)}return r}function Lr(e,t){return e===0&&t===0?50:t===0?100:e===0?0:100-100/(1+e/t)}function qr(e,t={}){Re(e);let r=t.fastPeriod,n=t.slowPeriod,o=t.signalPeriod;if(le(r),le(n),le(o),r>=n)throw new TypeError("fastPeriod must be < slowPeriod");let a=De(e,r),s=De(e,n),i=new Array(e.length).fill(null);for(let c=0;c<e.length;c++)a[c]!=null&&s[c]!=null&&(i[c]=a[c]-s[c]);let l=new Array(e.length).fill(null),u=new Array(e.length).fill(null),d=[];for(let c=0;c<i.length;c++)i[c]!=null&&d.push(c);if(d.length>=o){let c=0;for(let w=0;w<o;w++)c+=i[d[w]];let f=c/o,p=d[o-1];l[p]=f,u[p]=i[p]-f;let h=2/(o+1);for(let w=o;w<d.length;w++){let b=d[w];f=h*i[b]+(1-h)*f,l[b]=f,u[b]=i[b]-f}}return{line:i,signal:l,histogram:u}}function Ur(e,t={}){Re(e);let r=t.period,n=t.stdDev;if(le(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),a=new Array(e.length).fill(null),s=new Array(e.length).fill(null);if(e.length<r)return{upper:a,middle:o,lower:s};let i=0,l=0;for(let u=0;u<e.length;u++){let d=e[u];if(i+=d,l+=d*d,u>=r){let c=e[u-r];i-=c,l-=c*c}if(u>=r-1){let c=i/r,f=l/r-c*c;f<0&&f>-1e-12&&(f=0);let p=Math.sqrt(f);o[u]=c,a[u]=c+n*p,s[u]=c-n*p}}return{upper:a,middle:o,lower:s}}function Br(e,t){Lo(e),le(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=new Array(e.length);for(let s=0;s<e.length;s++){let i=e[s];if(s===0)n[s]=i.h-i.l;else{let l=e[s-1].c;n[s]=Math.max(i.h-i.l,Math.abs(i.h-l),Math.abs(i.l-l))}}let o=0;for(let s=0;s<t;s++)o+=n[s];let a=o/t;r[t-1]=a;for(let s=t;s<e.length;s++)a=(a*(t-1)+n[s])/t,r[s]=a;return r}var zr=V(()=>{});import{createHash as Ho}from"node:crypto";var It,Co,qo,Uo,Dr,Vr=V(()=>{It=2,Co="93f9c998260e73756c13871dc1a84dd6cdb26ec6113bd1941f023519939db440",qo="68f5b412a9975f04024cf9b9b6209b4bccedd52f176e95f34f786b3f53479c6a",Uo="f197a38ff1c0f4ebe13326db8cbb8167ea3dd5d62e6033fe97c2fee8d23d96b5",Dr=Ho("sha256").update(JSON.stringify({version:It,compilerSourceHash:Co,indicatorsSourceHash:qo,schemaSourceHash:Uo})).digest("hex")});function Q(e){return typeof e=="number"&&Number.isFinite(e)}function Do(e){let t=new Map(e.map(i=>[i.id,i])),r=i=>{switch(i.type){case"indicator":return i.input?[i.input]:[];case"compare":case"cross":return[i.left,i.right];case"logic":return[...i.inputs];default:return[]}},n=new Map,o=new Map;for(let i of e)n.set(i.id,0),o.set(i.id,[]);for(let i of e)for(let l of r(i))t.has(l)&&(o.get(l).push(i.id),n.set(i.id,n.get(i.id)+1));let a=[];for(let[i,l]of n)l===0&&a.push(i);let s=[];for(;a.length;){let i=a.shift();s.push(i);for(let l of o.get(i))n.set(l,n.get(l)-1),n.get(l)===0&&a.push(l)}if(s.length!==e.length)throw new Error("strategy graph is cyclic");return s}function ke(e,t){return e!=null&&typeof e=="object"&&"param"in e?t[e.param].value:e}function Vo(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 a=e[o];if(a==null||typeof a!="object"||Array.isArray(a))throw new TypeError(`bars[${o}] must be an object`);let{t:s,o:i,h:l,l:u,c:d,v:c}=a;if(!Q(s)&&(typeof s=="number"&&Number.isFinite(s)),!Number.isFinite(s))throw new TypeError(`bars[${o}].t must be finite`);for(let[f,p]of[["o",i],["h",l],["l",u],["c",d],["v",c]])if(!Q(p))throw new TypeError(`bars[${o}].${f} must be a finite number`);for(let[f,p]of[["o",i],["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(i,d,u))throw new TypeError(`bars[${o}] high must be >= max(open, close, low)`);if(u>Math.min(i,d,l))throw new TypeError(`bars[${o}] low must be <= min(open, close, high)`);if(n!=null){if(!(s>n))throw new TypeError("bars t must be strictly increasing");if(s-n!==zo[r])throw new TypeError(`bars t must match ${r} cadence`)}if(n=s,"fundingRate"in a&&a.fundingRate!=null&&!Q(a.fundingRate))throw new TypeError(`bars[${o}].fundingRate must be finite when present`);if("openInterest"in a&&a.openInterest!=null){if(!Q(a.openInterest))throw new TypeError(`bars[${o}].openInterest must be finite when present`);if(a.openInterest<0)throw new TypeError(`bars[${o}].openInterest must be non-negative`)}}}function he(e,t,r,n,o,a){if(a.has(e))return a.get(e);let s=t.get(e),i;switch(s.type){case"input":{let l=Bo[s.field];i=new Array(o+1);for(let u=0;u<=o;u++){let d=n[u][l];i[u]=d===void 0?null:d}break}case"constant":{let l=ke(s.value,r);i=new Array(o+1).fill(l);break}case"indicator":{let l=s.period!=null?ke(s.period,r):void 0;if(s.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})}i=Br(c,l);break}let d=he(s.input,t,r,n,o,a).map((c,f)=>{if(c==null||!Q(c))throw new TypeError(`indicator input ${s.input} has non-finite value at ${f}`);return c});if(s.indicator==="sma")i=Hr(d,l);else if(s.indicator==="ema")i=De(d,l);else if(s.indicator==="rsi")i=Cr(d,l);else if(s.indicator==="macd")i=qr(d,{fastPeriod:ke(s.fastPeriod,r),slowPeriod:ke(s.slowPeriod,r),signalPeriod:ke(s.signalPeriod,r)})[s.output];else if(s.indicator==="bollinger")i=Ur(d,{period:l,stdDev:ke(s.stdDev,r)})[s.output];else throw new Error(`unsupported indicator ${s.indicator}`);break}case"compare":{let l=he(s.left,t,r,n,o,a),u=he(s.right,t,r,n,o,a);i=new Array(o+1);for(let d=0;d<=o;d++){let c=l[d],f=u[d];if(c==null||f==null||!Q(c)||!Q(f)){i[d]=!1;continue}switch(s.op){case"gt":i[d]=c>f;break;case"gte":i[d]=c>=f;break;case"lt":i[d]=c<f;break;case"lte":i[d]=c<=f;break;case"eq":i[d]=c===f;break;default:i[d]=!1}}break}case"logic":{let l=s.inputs.map(u=>he(u,t,r,n,o,a));i=new Array(o+1);for(let u=0;u<=o;u++)if(s.op==="not"){let d=l[0][u];i[u]=d===!0?!1:d===!1}else if(s.op==="and"){let d=!0;for(let c of l)if(c[u]!==!0){d=!1;break}i[u]=d}else if(s.op==="or"){let d=!1;for(let c of l)if(c[u]===!0){d=!0;break}i[u]=d}else i[u]=!1;break}case"cross":{let l=he(s.left,t,r,n,o,a),u=he(s.right,t,r,n,o,a);i=new Array(o+1),i[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||!Q(c)||!Q(f)||!Q(p)||!Q(h)){i[d]=!1;continue}s.direction==="above"?i[d]=c<=f&&p>h:i[d]=c>=f&&p<h}break}default:throw new Error(`unknown node type ${s.type}`)}return a.set(e,i),i}function G(e,t={}){let r=Y(e);t&&Object.keys(t).length&&(r=Me(r,t));let n=new Map(r.nodes.map(p=>[p.id,p])),o=Object.freeze(Do(r.nodes)),a=r.parameters,s=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"])s.add(p);let i=Object.freeze([...s].sort()),l=ge(r);function u(p,h){let w={};for(let k of o){let $=p.get(k);w[k]=$[h]}let b=k=>k!=null&&w[k]===!0;return{values:w,signals:{entryLong:b(r.rules.entryLong),entryShort:b(r.rules.entryShort),exitLong:b(r.rules.exitLong),exitShort:b(r.rules.exitShort)}}}function d(p,h){Vo(p,h,r.market.interval);let w=new Map;for(let b of o)he(b,n,a,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((b,k)=>Object.freeze(u(w,k))))}return Object.freeze({strategy:r,strategyHash:l,compilerVersion:Oe,compilerHash:pe,requiredSeries:i,nodeOrder:o,evaluate:c,evaluateAll:f})}var Oe,pe,Bo,zo,me=V(()=>{de();zr();Vr();Oe=It,pe=Dr,Bo=Object.freeze({open:"o",high:"h",low:"l",close:"c",volume:"v",fundingRate:"fundingRate",openInterest:"openInterest"}),zo=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5})});import{createHash as Jo}from"node:crypto";function Yo(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 Ve(e){if(Array.isArray(e))return e.map(Ve);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Ve(e[r]);return t}return e}function Ot(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)=>Ot(r,`${t}[${n}]`));return}for(let[r,n]of Object.entries(e))Ot(n,`${t}.${r}`)}}function Kr(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:a,h:s,l:i,c:l,v:u}=n;if(!ne(o))throw new TypeError(`bars[${r}].t must be finite`);for(let[d,c]of[["o",a],["h",s],["l",i],["c",l],["v",u]])if(!ne(c))throw new TypeError(`bars[${r}].${d} must be a finite number`);for(let[d,c]of[["o",a],["h",s],["l",i],["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(s<Math.max(a,l,i))throw new TypeError(`bars[${r}] high must be >= max(open, close, low)`);if(i>Math.min(a,l,s))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 Ie(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");return e.length>0&&Kr(e),Jo("sha256").update(JSON.stringify(Ve(e)),"utf8").digest("hex")}function Go(e){if(e==null&&(e={}),!Yo(e))throw new TypeError("options must be a plain object");let t={...Ko},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 Je(e){return e/1e4}function Wo(e,t,r){let n=Je(r);return t==="long"?e*(1+n):e*(1-n)}function Xo(e,t,r){let n=Je(r);return t==="long"?e*(1-n):e*(1+n)}function Jr(e,t,r){let n=Math.abs(e)*Je(t),o=Math.abs(e)*Je(r);return{taker:n,builder:o,total:n+o}}function Zo(e,t){let r=e*(t.positionSizePct/100)*t.maxLeverage;return Math.min(r,t.maxNotionalUsd)}function Qo(e,t,r){let n=r/100;return t==="long"?e*(1-n):e*(1+n)}function es(e,t,r){let n=r/100;return t==="long"?e*(1+n):e*(1-n)}function ts(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 rs(e,t,r){return t==="long"?e.l<=r:e.h>=r}function ns(e,t,r){return t==="long"?e.h>=r:e.l<=r}function os(e,t,r){return t==="long"?e.l<=r:e.h>=r}function je(e,t){for(let r of e.requiredSeries)if(["fundingRate","openInterest"].includes(r)&&!t.every(n=>ne(n?.[r])))throw new Error(`strategy required series is absent: ${r}`)}function ss(e){if(e.length<3)return 0;let t=[];for(let s=1;s<e.length;s++){let i=e[s-1].equity,l=e[s].equity;i>0&&t.push((l-i)/i)}if(t.length<2)return 0;let r=0;for(let s of t)r+=s;let n=r/t.length,o=0;for(let s of t)o+=(s-n)**2;let a=Math.sqrt(o/(t.length-1));return a>0?n/a:0}function is(e){let t=-1/0,r=0;for(let n of e){let o=n.equity;if(o>t&&(t=o),t>0){let a=(t-o)/t*100;a>r&&(r=a)}}return r}function ae(e,t,r={}){let n=Go(r);Kr(t);let o=Ie(t);n.nowMs!==void 0&&Y(e,{nowMs:n.nowMs});let a=G(e);if(je(a,t),n.nowMs!==void 0&&a.strategy.risk.expiresAt<=n.nowMs)throw new Error("strategy is expired: risk.expiresAt must be strictly greater than nowMs");let s=a.strategy.risk,i=a.evaluateAll(t),l=n.latencyBars,u=n.slippageBps,d=n.takerFeeBps,c=n.builderFeeBps,f=n.initialEquityUsd,p=0,h=0,w=0,b=0,k=0,$=[],I=[],x=[],_=[],A=[],m=null,M=0,W=null,U=f,D=!1,y=0,P=0,T=[],j=new Array(t.length).fill(0);function L(E){T.push(E)}function O(E){let v=t[E].v*(n.maxVolumeParticipationPct/100);return Math.max(0,v-j[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,S){let H=S.o,N=Zo(f,s);if(!(N>0)||!(H>0))return;let C=Wo(H,v,u),F=N/C,z=O(E),Pe=C*z;if(F>z){x.push({kind:"entry",barIndex:E,time:S.t,side:v,requestedNotionalUsd:N,maxFillNotionalUsd:Pe,reason:"volume_participation"});return}j[E]+=F;let te=Math.abs(C-H)*F,se=Jr(N,d,c);f-=se.total,p+=se.taker,h+=se.builder,b+=te,k+=N,m={lifecycleEpoch:++P,side:v,entryBarIndex:E,entryReferencePrice:H,entryPrice:C,qty:F,notionalUsd:N,stop:Qo(C,v,s.stopLossPct),take:es(C,v,s.takeProfitPct),liq:ts(C,v,s.maxLeverage,d+c),entryFees:se.taker,entryBuilderFees:se.builder,entrySlippageUsd:te,fundingAccrued:0}}function B(E,v,S,H){if(!m)return!1;let N=m.side,C=v,F=C;S!=="liquidation"&&H&&(F=Xo(C,N,u));let z=m.qty,Pe=z*F;if(S!=="liquidation"){let Gt=O(E),Sn=F*Gt;if(z>Gt)return x.push({kind:"exit",barIndex:E,time:t[E].t,side:N,requestedNotionalUsd:Pe,maxFillNotionalUsd:Sn,reason:"volume_participation",triggerReason:S}),!1;j[E]+=z}let te=Jr(Pe,d,c),se=S==="liquidation"?0:Math.abs(F-C)*z,$e,et;N==="long"?($e=(C-m.entryReferencePrice)*z,et=(F-m.entryPrice)*z):($e=(m.entryReferencePrice-C)*z,et=(m.entryPrice-F)*z),f+=et,f-=te.total,p+=te.taker,h+=te.builder,b+=se,k+=Pe;let kn={side:N,entryBarIndex:m.entryBarIndex,entryTime:t[m.entryBarIndex].t,entryPrice:m.entryPrice,exitBarIndex:E,exitTime:t[E].t,exitPrice:F,exitReason:S,qty:z,notionalUsd:m.notionalUsd,grossPnlUsd:$e,feesUsd:m.entryFees+te.taker,builderFeesUsd:m.entryBuilderFees+te.builder,fundingUsd:m.fundingAccrued,slippageUsd:m.entrySlippageUsd+se,netPnlUsd:$e-(m.entryFees+te.taker+m.entryBuilderFees+te.builder)-m.fundingAccrued-(m.entrySlippageUsd+se)};return $.push(kn),S==="liquidation"&&I.push({barIndex:E,time:t[E].t,side:N,price:F,tradeIndex:$.length-1}),m=null,P+=1,y=E+1+(s.cooldownBars||0),!0}function ee(E,v,S,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)||L({kind:"exit",side:v,signalBar:E,fillBar:N,reason:S,epoch:H})}function He(E){let v=T.filter(S=>S.fillBar===E);for(let S=T.length-1;S>=0;S--)T[S].fillBar===E&&T.splice(S,1);v.sort((S,H)=>{let N=C=>C.kind==="exit"?0:1;return N(S)-N(H)});for(let S of v)if(S.kind==="exit"){if(!m||m.side!==S.side||m.lifecycleEpoch!==S.epoch)continue;let H=S.reason||"rule";B(E,t[E].o,H,!0)||ee(E,S.side,H,S.epoch)}else if(S.kind==="entry"){if(m||S.epoch!==P||E<y)continue;J(E,S.side,t[E])}}function Ce(E){if(!m)return;let v=t[E],S=v.fundingPaymentRate;if(S==null||!ne(S)||S===0)return;let H=Math.abs(m.qty*v.c),N=S*H;m.side==="long"?(f-=N,m.fundingAccrued+=N,w+=N):(f+=N,m.fundingAccrued-=N,w-=N)}function qe(E){if(!m)return;let v=t[E].o;(m.side==="long"?v<=m.liq:v>=m.liq)&&B(E,v,"liquidation",!1)}function Dt(E){if(!m)return;let v=t[E],S=m.side,H=os(v,S,m.liq),N=rs(v,S,m.stop),C=ns(v,S,m.take),F=z=>S==="long"?Math.min(z,v.o):Math.max(z,v.o);if(H){B(E,F(m.liq),"liquidation",!1);return}if(N&&C){B(E,F(m.stop),"stop_loss",!0)||ee(E,S,"stop_loss",m.lifecycleEpoch);return}if(N){B(E,F(m.stop),"stop_loss",!0)||ee(E,S,"stop_loss",m.lifecycleEpoch);return}C&&(B(E,m.take,"take_profit",!0)||ee(E,S,"take_profit",m.lifecycleEpoch))}for(let E=0;E<t.length;E++){let v=Math.floor(t[E].t/864e5);v!==W&&(W=v,U=R(t[E].o),D=!1),qe(E),He(E),Dt(E),Ce(E),!D&&R(t[E].c)<=U*(1-s.maxDailyLossPct/100)&&(D=!0,_.push({type:"daily_loss_limit",barIndex:E,time:t[E].t,message:"daily loss limit reached; new entries blocked for UTC day"}));let S=i[E].signals,H=E+l;if(m)(m.side==="long"&&S.exitLong===!0||m.side==="short"&&S.exitShort===!0)&&H<t.length&&(T.some(z=>z.kind==="exit"&&z.side===m.side&&z.fillBar===H&&z.epoch===m.lifecycleEpoch)||L({kind:"exit",side:m.side,signalBar:E,fillBar:H,reason:"rule",epoch:m.lifecycleEpoch}));else{let C=S.entryLong===!0,F=S.entryShort===!0;C&&F?_.push({type:"conflicting_entry_signals",barIndex:E,time:t[E].t,message:"conflicting entry signals; no position opened"}):!D&&(C||F)&&H<t.length&&E>=y&&L({kind:"entry",side:C?"long":"short",signalBar:E,fillBar:H,epoch:P})}let N=f;m&&(M+=1,N=R(t[E].c)),A.push({barIndex:E,time:t[E].t,equity:N,positionSide:m?m.side:null})}let Vt=null;if(m){let E=t.length-1;if(B(E,t[E].c,"end_of_data",!0))A[E]={barIndex:E,time:t[E].t,equity:f,positionSide:null};else{let S=R(t[E].c);Vt={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:S},_.push({type:"open_position_at_end",barIndex:E,time:t[E].t,message:"end-of-data exit missed; position remains open and marked"})}}let Jt=(m?R(t[t.length-1].c):f)-n.initialEquityUsd,gn=Jt/n.initialEquityUsd*100,Kt=0,We=0,Xe=0;for(let E of $)E.netPnlUsd>0?(Kt+=1,We+=E.netPnlUsd):E.netPnlUsd<0&&(Xe+=-E.netPnlUsd);let Ze=$.length,bn=Ze===0?0:Kt/Ze,Qe=0;Xe>0?Qe=We/Xe:We>0&&(Qe=1e12);let En={netPnlUsd:Jt,netPnlPct:gn,maxDrawdownPct:is(A),winRate:bn,profitFactor:Qe,tradeCount:Ze,sharpe:ss(A),turnoverUsd:k,exposurePct:M/t.length*100},xn={initialEquityUsd:n.initialEquityUsd,takerFeeBps:n.takerFeeBps,builderFeeBps:n.builderFeeBps,slippageBps:n.slippageBps,latencyBars:n.latencyBars,maxVolumeParticipationPct:n.maxVolumeParticipationPct},Yt={barsHash:o,strategyHash:a.strategyHash,compilerHash:pe,compilerVersion:Oe,config:xn,trades:$,equityCurve:A,metrics:En,costs:{feesUsd:p,builderFeesUsd:h,fundingUsd:w,slippageUsd:b},liquidations:I,missedFills:x,openPositionAtEnd:Vt,flags:_};return Ot(Yt),vt(Ve(Yt))}var Ko,Be=V(()=>{me();de();Ko=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:100})});import{createHash as as}from"node:crypto";function hs(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Nt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Nt(t);return Object.freeze(e)}for(let t of Object.keys(e))Nt(e[t]);return Object.freeze(e)}function ys(e){return String(e).trim().replace(/\s+/g," ")}function ws(e){let t=e.match(/\b(long|short)\b/i);return t?t[1].toLowerCase():null}function gs(e){for(let r of ls)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 bs(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 cs.has(r)?r:null}function Es(e){let t={...fs},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 a=e.match(/position\s*size\s*(\d+(?:\.\d+)?)\s*%?/i);a&&(t.positionSizePct=Number(a[1]));let s=e.match(/max\s*notional\s*(?:usd\s*)?\$?\s*(\d+(?:\.\d+)?)/i);return s&&(t.maxNotionalUsd=Number(s[1])),t}function xs(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 ks(e){let t=as("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 Ss(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 a=/\b(exit\s+on\s+reverse|reverse\s+exit)\b/i.test(e);return{kind:"ema_cross",fast:r,slow:o,direction:n,reverse:a}}function As(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 Ps(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 $s(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,""):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 Yr(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 Ts({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:s,spec:i}){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:i.direction,left:"emaLeft",right:"emaRight"}],u={entryLong:null,entryShort:null,exitLong:null,exitShort:null};if(e==="long"?u.entryLong="cross":u.entryShort="cross",i.reverse){let d=i.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:a,name:s,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{ema_left_period:Yr(i.fast),ema_right_period:Yr(i.slow)},nodes:l,rules:u,risk:{...n,expiresAt:o}}}function _s({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:s,spec:i}){let l=[{id:"c",type:"input",field:"close"},{id:"rsi",type:"indicator",indicator:"rsi",input:"c",period:i.period},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"rsi",right:"thr"}];return{version:1,id:a,name:s,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 Is({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:s,spec:i}){let l=[{id:"fr",type:"input",field:"fundingRate"},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"fr",right:"thr"}];return{version:1,id:a,name:s,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 Gr(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(!hs(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=ms;if("expiresInMs"in t){if(!Number.isInteger(t.expiresInMs))throw new K("expiresInMs must be an integer");if(n=t.expiresInMs,n<ds||n>ps)throw new K("expiresInMs must be between 1h and 30d")}if(us.test(e))throw new K(`prompt appears to contain secrets and is rejected. ${Se}`);let o=ys(e);if(!o)throw new K(`empty prompt. ${Se}`);if(xs(o))throw new K(`duplicate interval or risk clause. ${Se}`);let a=ws(o),s=gs(o),i=bs(o);if(!a||!s||!i)throw new K(`could not parse side/coin/interval. ${Se}`);let l=Es(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 u=r+n,d=ks(o),c=`Draft ${s} ${a}`.slice(0,100),f=Ss(o),p=As(o),h=Ps(o),w=[f,p,h].filter(Boolean);if(w.length!==1)throw new K(`unsupported or ambiguous prompt. ${Se}`);if(!$s(o,w[0]))throw new K(`unsupported or ambiguous prompt. ${Se}`);let b,k=w[0],$={side:a,coin:s,interval:i,risk:l,expiresAt:u,id:d,name:c,spec:k};k.kind==="ema_cross"?b=Ts($):k.kind==="rsi"?b=_s($):b=Is($);let I=_t(b,{nowMs:r});if(!I.ok)throw new K(`draft failed validation: ${I.errors.map(x=>x.message).join("; ")}`);return Nt(Y(b,{nowMs:r}))}var K,cs,ls,us,Se,fs,ds,ps,ms,Wr=V(()=>{de();K=class extends Error{constructor(t){super(t),this.name="StrategyDraftError"}},cs=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),ls=new Set(["BTC","ETH","SOL","HYPE"]),us=/\b(mnemonic|private\s*key|privkey|seed\s*phrase|seed\b|api[_-]?key|secret\s*key|wallet\s*key|passphrase)\b/i,Se="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]. 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.",fs=Object.freeze({maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3}),ds=36e5,ps=30*864e5,ms=864e5});import{createHash as vs}from"node:crypto";function Qr(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 en(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Rt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Rt(t);return Object.freeze(e)}for(let t of Object.keys(e))Rt(e[t]);return Object.freeze(e)}function Fe(e){if(Array.isArray(e))return e.map(Fe);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Fe(e[r]);return t}return e}function Ke(e){return JSON.stringify(Fe(e))}function Os(e){let{min:t,max:r,step:n}=e;if(!(n>0)||t>r)return[];let o=[],a=Math.floor((r-t)/n+1e-9);for(let i=0;i<=a;i++){let l=t+i*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 s=o[o.length-1];if(Math.abs(s-r)>1e-9){let i=(r-t)/n;Math.abs(i-Math.round(i))<=1e-9&&o.push(r)}return o}function Ns(e,t){if(e.length===0)return[];let r=[{}];for(let n of e){let o=t[n],a=[];for(let s of r)for(let i of o)a.push({...s,[n]:i});r=a}return r.sort((n,o)=>{let a=Ke(n),s=Ke(o);return a<s?-1:a>s?1:0}),r}function Mt(e,t,r,n,o){let a=0;if(e==="maxDrawdownPct"){if(a=t.maxDrawdownPct-n.maxDrawdownPct,a!==0)return a<0}else if(a=t[e]-n[e],a!==0)return a>0;let s=Ke(r),i=Ke(o);return s<i}function tn(e,t,r={}){if(!en(r))throw new TypeError("options must be a plain object");for(let x of Object.keys(r))if(Qr(x))throw new TypeError(`options must not include holdout/test/oos key "${x}"`);let n=new Set(["maxTrials","objective","backtestOptions"]);for(let x of Object.keys(r))if(!n.has(x))throw new TypeError(`unknown option "${x}"`);let o=64;if("maxTrials"in r){let x=r.maxTrials;if(!Number.isInteger(x)||x<1||x>Xr)throw new TypeError(`maxTrials must be an integer 1..${Xr}`);o=x}let a=r.objective??"netPnlUsd";if(!Zr.has(a))throw new TypeError(`objective must be one of ${[...Zr].join("|")}`);let s=r.backtestOptions??{};if(!en(s))throw new TypeError("backtestOptions must be a plain object");for(let x of Object.keys(s))if(Qr(x))throw new TypeError(`backtestOptions must not include holdout/test/oos key "${x}"`);let i=Y(e),l=Object.keys(i.parameters).sort();if(l.length===0)throw new Error("optimizeStrategy requires at least one declared parameter");let u={},d=1;for(let x of l){let _=Os(i.parameters[x]);if(_.length===0)throw new Error(`parameter "${x}" produces an empty grid`);u[x]=_,d*=_.length}let c=Ns(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 x of f){let _=Me(i,x),A=ae(_,t,s);w==null&&(w=A.config);let m={netPnlUsd:A.metrics.netPnlUsd,netPnlPct:A.metrics.netPnlPct,maxDrawdownPct:A.metrics.maxDrawdownPct,winRate:A.metrics.winRate,profitFactor:A.metrics.profitFactor,tradeCount:A.metrics.tradeCount,sharpe:A.metrics.sharpe,turnoverUsd:A.metrics.turnoverUsd},M={parameters:{...x},metrics:m};p.push(M),(!h||Mt(a,m,x,h.metrics,h.parameters))&&(h=M)}p.sort((x,_)=>Mt(a,x.metrics,x.parameters,_.metrics,_.parameters)?-1:Mt(a,_.metrics,_.parameters,x.metrics,x.parameters)?1:0);let b={...h.parameters},k=Me(i,b),$={strategyHash:ge(i),compilerHash:pe,trainBarsHash:Ie(t),backtestConfig:w,objective:a,maxTrials:o,trialsRun:p.length,candidates:p,bestParameters:b,bestStrategy:k},I={id:vs("sha256").update(JSON.stringify(Fe($)),"utf8").digest("hex"),...$};return Rt(Fe(JSON.parse(JSON.stringify(I))))}var Xr,Zr,rn=V(()=>{me();de();Be();Xr=256,Zr=new Set(["netPnlUsd","profitFactor","sharpe","maxDrawdownPct"])});import ie from"node:fs";import Ye from"node:path";function Ge(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function oe(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Rs(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Ae(e,t="record"){if(Array.isArray(e)){e.forEach((r,n)=>Ae(r,`${t}[${n}]`));return}if(Ge(e))for(let[r,n]of Object.entries(e)){let o=Rs(r);if(Ms.some(a=>o.includes(a)))throw new Error(`shadow-store: forbidden secret-like field at ${t}.${r}`);Ae(n,`${t}.${r}`)}}function js(e){if(typeof e!="string"||!e||!Ye.isAbsolute(e))throw new Error("shadow-store: path must be an absolute path")}function nn(e){let t;try{t=ie.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 Fs(){return{version:Ft,runners:[]}}function on(e,t){let r;try{r=JSON.parse(e)}catch{throw new Error("shadow-store: malformed JSON")}if(!Ge(r))throw new Error("shadow-store: malformed JSON root");if(r.version!==Ft)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 Ae(r,Ye.basename(t)),{version:Ft,runners:r.runners.map(n=>oe(n))}}function sn(e,t){Ae(t,"store");let r=Ye.dirname(e);ie.mkdirSync(r,{recursive:!0,mode:448});let n=Ye.join(r,`.shadow-store.${process.pid}.${Date.now()}.tmp`),o=`${JSON.stringify(t)}
3
- `;try{ie.writeFileSync(n,o,{mode:384,flag:"wx"}),ie.renameSync(n,e);try{ie.chmodSync(e,384)}catch{}}catch(a){try{ie.unlinkSync(n)}catch{}throw a}}function an(e={}){let t=e.path;if(js(t),nn(t),ie.existsSync(t)?on(ie.readFileSync(t,"utf8"),t):sn(t,Fs()),jt.has(t))return jt.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 a(h){if(!r&&n.length===0){r=!0;try{return h()}finally{r=!1,queueMicrotask(o)}}return new Promise((w,b)=>{n.push({fn:h,resolve:w,reject:b}),queueMicrotask(o)})}function s(){return nn(t),on(ie.readFileSync(t,"utf8"),t)}function i(h){sn(t,h)}function l(h){if(!Ge(h)||typeof h.id!="string"||!h.id)throw new Error("shadow-store: create requires record with string id");Ae(h,"record");let w=s();if(w.runners.some(k=>k.id===h.id))throw new Error(`shadow-store: runner id already exists: ${h.id}`);let b=oe(h);return w.runners.push(b),i(w),oe(b)}function u(h){let w=s().runners.find(b=>b.id===h);return w?oe(w):null}function d(){return s().runners.map(h=>oe(h))}function c(h,w){if(typeof w!="function")throw new Error("shadow-store: updater must be a function");let b=s(),k=b.runners.findIndex(x=>x.id===h);if(k<0)throw new Error(`shadow-store: runner not found: ${h}`);let $=oe(b.runners[k]),I=w($);if(!Ge(I)||I.id!==h)throw new Error("shadow-store: updater must return record with same id");return Ae(I,"record"),b.runners[k]=oe(I),i(b),oe(b.runners[k])}function f(h){let w=s(),b=w.runners.findIndex($=>$.id===h);if(b<0)throw new Error(`shadow-store: runner not found: ${h}`);let k=oe(w.runners[b]);return k.status!=="stopped"&&(k.status="stopped",w.runners[b]=k,i(w)),oe(w.runners[b])}let p={create(h){return a(()=>l(h))},get(h){return u(h)},list(){return d()},update(h,w){return a(()=>c(h,w))},stop(h){return a(()=>f(h))}};return jt.set(t,p),p}var Ft,Ms,jt,cn=V(()=>{Ft=1,Ms=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];jt=new Map});import{createHash as Ct}from"node:crypto";function Lt(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Ht(e){return Array.isArray(e)?e.map(Ht):e&&typeof e=="object"?Object.fromEntries(Object.keys(e).sort().map(t=>[t,Ht(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 Ct("sha256").update(JSON.stringify(Ht(e))).digest("hex")}function Ls(e,t,r,n,o){return Ct("sha256").update(`${e}|${t}|${r}|${n}|${o}`).digest("hex")}function Hs(e,t,r,n){return Ct("sha256").update(`shadow|${e}|${t}|${r}|${n??""}`).digest("hex")}function Cs(e){return e==="entryLong"||e==="exitShort"?"buy":e==="entryShort"||e==="exitLong"?"sell":e}function ln(e){return e==="entryLong"||e==="entryShort"}function qt({storePath:e,clock:t=Date.now}={}){if(typeof e!="string"||!e)throw new Error("shadow-runner: storePath required");let r=an({path:e});function n({strategy:l,evidenceId:u=null}={}){let d=G(l),c=u==null?null:String(u),f=r.list().filter(k=>k.status==="running"&&k.strategyHash===d.strategyHash&&k.compilerHash===d.compilerHash&&k.evidenceId===c).sort((k,$)=>k.createdAt-$.createdAt||k.id.localeCompare($.id))[0];if(f)return Lt(f);let p=t(),h=Hs(p,d.strategyHash,d.compilerHash,c),w=r.get(h);if(w)return Lt(w);let b={id:h,strategy:Lt(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(b)}function o(l){return r.get(l)}function a(){return r.list()}function s(l){return r.stop(l)}function i(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=G(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,b=[];for(let y=0;y<u.length;y++){let P=u[y].t;(w==null||P>w)&&b.push(y)}if(b.length===0)return c;let k=new Map(c.intendedOrders.map(y=>[y.id,y])),$=new Set(c.fills.map(y=>y.orderId)),I=new Map(c.missedFills.map(y=>[y.orderId,y])),x=(y,P)=>`${y}|${P}`,_=new Map(c.markouts.map(y=>[x(y.orderId,y.horizon),y])),A=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 W({action:y,signalBarT:P,signalIndex:T}){let j=Cs(y),L=Ls(c.id,c.strategyHash,P,j,y);if(k.has(L))return k.get(L);let O=T+1,R=O<u.length,J={id:L,action:y,type:y,side:j,signalBarT:P,fillBarT:R?u[O].t:null,status:R?"open":"missed"};return k.set(L,J),c.intendedOrders.push(J),J}function U(y,P,T){if($.has(y.id))return;let j={orderId:y.id,action:ln(y.action)?"entry":"exit",side:y.side,price:P.o,barT:P.t,signalBarT:y.signalBarT,barIndex:T};if(c.fills.push(j),$.add(y.id),y.status="filled",y.fillBarT=P.t,I.has(y.id)&&(I.delete(y.id),c.missedFills=c.missedFills.filter(L=>L.orderId!==y.id)),ln(y.action)){A={side:y.action==="entryLong"?"long":"short",entryOrderId:y.id,entryBarT:P.t,entryPrice:P.o,entryBarIndex:T};for(let L of d){let O=x(y.id,L);if(_.has(O))continue;let R={orderId:y.id,horizon:L,entryBarT:P.t,entryPrice:P.o,side:A.side,status:"pending",close:null,barT:null};_.set(O,R),c.markouts.push(R)}}else A=null,m=Number(c.strategy?.risk?.cooldownBars)||0,M=P.t}function D(y){if($.has(y.id)||I.has(y.id))return;let P={orderId:y.id,action:y.action,side:y.side,signalBarT:y.signalBarT,status:"missed"};I.set(y.id,P),c.missedFills.push(P),y.status="missed"}for(let y of c.intendedOrders){if(y.status==="filled"||$.has(y.id))continue;let P=h.get(y.signalBarT);if(P==null)continue;let T=P+1;T<u.length&&(w==null||u[T].t>w)&&U(y,u[T],T)}for(let y of b){let P=u[y],T=p[y].signals,j=A,L=R=>{if(A||m>0&&(M==null||P.t>=M))return;let B=W({action:R,signalBarT:P.t,signalIndex:y}),ee=y+1;ee<u.length?U(B,u[ee],ee):D(B)},O=R=>{if(!A||A.side==="long"&&R!=="exitLong"||A.side==="short"&&R!=="exitShort")return;let J=W({action:R,signalBarT:P.t,signalIndex:y}),B=y+1;B<u.length?U(J,u[B],B):D(J)};j?(T.exitLong&&O("exitLong"),T.exitShort&&O("exitShort")):T.entryLong&&T.entryShort||(T.entryLong&&L("entryLong"),T.entryShort&&L("entryShort")),m>0&&M!=null&&P.t>=M&&(m-=1,m===0&&(M=null)),c.cursor=P.t,c.lastProcessedBarIndex=y}for(let y of c.markouts){if(y.status!=="pending")continue;let P=c.fills.find(L=>L.orderId===y.orderId&&L.action==="entry");if(!P)continue;let T=h.get(P.barT);if(T==null)continue;let j=T+y.horizon;if(j<u.length){y.close=u[j].c,y.barT=u[j].t,y.status="filled";let L=y.entryPrice;y.markout=y.side==="long"?(y.close-L)/L:(L-y.close)/L}}return c.position=A,c.cooldownBarsRemaining=m,c.cooldownStartT=M,c.updatedAt=t(),c})}return{start:n,step:i,list:a,get:o,stop:s}}var fn=V(()=>{me();cn()});var mn={};Pn(mn,{runStrategyOperation:()=>Ks});import qs from"node:os";import Us from"node:path";function Le(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function zs(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Bt(e){if(Array.isArray(e)){for(let t of e)Bt(t);return}if(Le(e))for(let[t,r]of Object.entries(e)){if(Bs.some(n=>zs(t).includes(n)))throw new Error(`strategy service: secret-like field "${t}" is forbidden`);Bt(r)}}function Ds(e){if(!Le(e))throw new TypeError("strategy input must be a plain object");return Bt(e),e}function Vs(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 Ut(e,t,r,n){if(Array.isArray(t.bars))return t.bars;let o=Et(e.venue),a=r.fetchBars??o.fetchBars;if(typeof a!="function")throw new Error(`strategy venue ${o.id} does not support history`);r.signal?.throwIfAborted?.();let s=await a({coin:e.market.coin,interval:e.market.interval,count:t.count??1500,endTime:t.endTime??n},{signal:r.signal});r.signal?.throwIfAborted?.();let i=Array.isArray(s)?s:s?.bars;if(!Array.isArray(i))throw new Error("strategy history provider returned no bars");return i}function zt(e,t){let r=e.backtestOptions??{};if(!Le(r))throw new TypeError("backtestOptions must be a plain object");return{...r,nowMs:t}}function dn(e,t,r,n,o={}){let a=e.evidenceOptions??{};if(!Le(a))throw new TypeError("evidenceOptions must be a plain object");return{...a,...o,strategy:t,bars:r,backtestOptions:zt(e,n)}}function pn(){return Us.join(qs.homedir(),".oracle","strategy-shadow.json")}function Js(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 Ks(e,t={},r={}){r.signal?.throwIfAborted?.();let n=Ds(t),o=Vs(n,r);if(e==="draft")return{strategy:Gr(n.prompt,{nowMs:o})};if(e==="validate"){let a=G(n.strategy);if(a.strategy.risk.expiresAt<=o)throw new Error("strategy is expired");return{valid:!0,strategy:a.strategy,strategyHash:a.strategyHash,compilerHash:a.compilerHash,compilerVersion:a.compilerVersion,requiredSeries:a.requiredSeries}}if(e==="backtest"||e==="evidence"){let a=G(n.strategy),s=await Ut(a.strategy,n,r,o);je(a,s);let i=mt(dn(n,a.strategy,s,o));return e==="evidence"?i:{backtest:ae(a.strategy,s,zt(n,o)),evidence:i}}if(e==="optimize"){let a=G(n.strategy),s=await Ut(a.strategy,n,r,o);je(a,s);let i=n.trainFraction,l=n.evidenceOptions?.trainFraction;if(i!=null&&l!=null&&i!==l)throw new TypeError("conflicting trainFraction controls are forbidden");let u=i??l??.7;if(typeof u!="number"||u<=0||u>=1)throw new TypeError("trainFraction must be in (0,1)");let d=s.slice(0,Math.floor(s.length*u)),c=n.options??{};if(!Le(c))throw new TypeError("options must be a plain object");let f=tn(a.strategy,d,{...c,...n.maxTrials==null?{}:{maxTrials:n.maxTrials},backtestOptions:zt(n,o)}),p=f.bestStrategy;return{strategy:p,optimization:f,evidence:mt(dn(n,p,s,o,{trainFraction:u}))}}if(e==="shadow"){let a=qt({storePath:r.storePath??pn(),clock:()=>o}),s=n.action;if(s==="start")return await a.start({strategy:n.strategy,evidenceId:n.evidenceId??n.evidence?.id??null});if(s==="list")return await a.list();if(s==="get")return await a.get(n.id);if(s==="stop")return await a.stop(n.id);if(s==="step"){let i=await a.get(n.id);if(!i)throw new Error(`shadow runner not found: ${n.id}`);let l=await Ut(i.strategy,n,r,o);return je(G(i.strategy),l),await a.step(n.id,l,n.stepOptions??{})}throw new Error(`unknown shadow action: ${s}`)}if(e==="prepare"){let a=G(n.strategy),s=Et(a.strategy.venue);if(typeof n.shadowId!="string"||!n.shadowId)throw new Error("strategy prepare requires a matching shadow runner id");let l=await qt({storePath:r.storePath??pn(),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!==a.strategyHash||l.compilerHash!==a.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??Js(a.strategy,o);return s.prepareIntent({strategy:a.strategy,evidence:n.evidence,shadow:{id:l.id,stateHash:un(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}`)}var Bs,hn=V(()=>{Be();me();ht();Wr();rn();fn();xt();Bs=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"]});import yn from"node:fs";function Ys(e){let t={},r=[];for(let n=0;n<e.length;n++){let o=e[n];if(!o.startsWith("--")){r.push(o);continue}let a=o.slice(2),s=e[n+1];s!=null&&!s.startsWith("--")?(t[a]=s,n++):t[a]=!0}return{flags:t,positional:r}}function ye(e,t){if(!e)throw new Error(`${t} path required`);let r=e==="-"?yn.readFileSync(0,"utf8"):yn.readFileSync(e,"utf8");try{return JSON.parse(r)}catch{throw new Error(`${t} must contain valid JSON`)}}function wn(e,t){if(e==null)return;let r=Number(e);if(!Number.isFinite(r))throw new Error(`${t} must be a finite number`);return r}var Gs=`oracle strategy <draft|validate|backtest|optimize|evidence|shadow|prepare> [args]
1
+ var An=Object.defineProperty;var V=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var $n=(e,t)=>{for(var r in t)An(e,r,{get:t[r],enumerable:!0})};import ue from"node:net";import Pn from"node:dns";function Ue(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("::"),a=r(n),s=r(o);if(!a||!s)return null;let i=t.includes("::"),l=8-a.length-s.length;if(!i&&l!==0||i&&l<1)return null;let u=[...a,...Array(Math.max(0,l)).fill(0),...s];return u.length!==8?null:Uint8Array.from(u.flatMap(d=>[d>>8,d&255]))}function tt(e,t,r){let n=Math.floor(r/8),o=r%8;for(let s=0;s<n;s+=1)if(e[s]!==t[s])return!1;if(!o)return!0;let a=255<<8-o;return(e[n]&a)===(t[n]&a)}function rt(e){if(ue.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(ue.isIPv6(e)){let t=Ue(e);if(!t)return!1;let r=Ue("::ffff:0:0");return tt(t,r,96)?rt([...t.slice(12)].join(".")):tt(t,Ue("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([o,a])=>tt(t,Ue(o),a)):!1}return!1}function In(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(Tn.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=ue.isIP(r);return n!==0&&!rt(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function nt(e,{lookupFn:t=Pn.promises.lookup}={}){let r=In(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:ue.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=>!rt(o.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}async function ot({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(/\.+$/,""),a=new Map,s=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||(ue.isIPv6(f.address)?6:4)})),i=(c,f,p)=>{a.set(o(c),s(typeof f=="string"?[{address:f,family:p}]:f))},l=c=>{let f=o(c);if(ue.isIP(f))return[{address:f,family:ue.isIPv6(f)?6:4}];let p=a.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(b){return p(b)}return f?.all?p(null,h):p(null,h[0].address,h[0].family)}}}),d=_n((c,f={})=>n(c,{...f,dispatcher:u}),i);return{dispatcher:u,fetch:d,pin:i,resolve:l,async close(){try{await u.destroy()}catch{}}}}function _n(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[st]=Object.freeze({pin:t}),e}function it(e){return typeof e=="function"&&typeof e[st]?.pin=="function"}function Xt(e,t,r){if(!it(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[st].pin(t,r)}var Tn,st,Wt=V(()=>{Tn=new Set(["localhost","metadata.google.internal","metadata.goog"]);st=Symbol.for("oracle.egressGuard.pinCapableFetch")});import{createHash as vn}from"node:crypto";function Ln(e){let t=String(e||"").toLowerCase();return nr.includes(t)||/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(t)}function Fn(e){let t={};for(let[r,n]of Object.entries(e||{}))Ln(r)||(t[r]=n);return t}function jn(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 Hn(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}function Cn(e,t,r,n={}){let o={};for(let[d,c]of Object.entries(r||{}))o[d.toLowerCase()]=c;let a=Object.keys(o).filter(d=>/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(d)),i=[...new Set([...nr,...a])].sort().map(d=>`${d}=${o[d]??""}`).join(`
2
+ `),l=vn("sha256").update(i).digest("hex").slice(0,32),u=`${n.untrustedUrl?"untrusted":"trusted"}:${n.maxResponseBytes??"unbounded"}`;return`${e} ${t} ${u} ${l}`}function qn(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,Qt):Math.min(250*2**e,Qt)+Math.floor(Math.random()*100)}function Te(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function ct(e,t,r){return Te(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function Ie(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function Bn(e){return e?e.byteLength??e.length??0:0}async function tr(e,t,{url:r,truncate:n=!1,onOversize:o}={}){if(t==null)return await e.text();let a=Number(e.headers?.get?.("content-length"));if(Number.isFinite(a)&&a>t&&(Ie(e),!n))throw ct(r,`content-length ${a}`,t);let s=e.body?.getReader?.();if(!s){let c=await e.text(),f=Buffer.byteLength(c,"utf8");if(f>t){if(!n)throw ct(r,`body ${f} bytes`,t);return Buffer.from(c,"utf8").subarray(0,t).toString("utf8")}return c}let i=[],l=0,u=!1;try{for(;;){let{value:c,done:f}=await s.read();if(f)break;if(c&&(i.push(Buffer.from(c)),l+=Bn(c),l>t)){u=!0;break}}}finally{if(u)try{await s.cancel()}catch{}try{s.releaseLock?.()}catch{}}if(u&&(typeof o=="function"&&o(),!n))throw ct(r,`streamed ${l} bytes`,t);let d=Buffer.concat(i);return(u?d.subarray(0,t):d).toString("utf8")}function rr(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function Dn(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:a,lookupFn:s,realFetch:i,untrustedUrl:l=!1,maxResponseBytes:u=null,importUndici:d,validateResponse:c,signal:f}){let p=new AbortController,h=setTimeout(()=>p.abort(),a),b=f?typeof AbortSignal.any=="function"?AbortSignal.any([f,p.signal]):f:p.signal,k=null,S=t,I=s?{lookupFn:s}:{};if(l&&!i&&!it(S))throw Te(`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(w,{status:P=null}={})=>{let x=await nt(w,I);if(!x.ok)throw Te(P==null?`HTTP refused ${w}: ${x.error}`:`HTTP redirect to ${w} ${x.error}`,P==null?{}:{status:P});let m=new URL(w).hostname;if(i){if(k&&(await k.close(),k=null),!k)try{k=await ot({requireUndici:!0,...d?{importUndici:d}:{}})}catch(M){throw Te(P==null?`HTTP refused ${w}: ${M?.message||M}`:`HTTP redirect to ${w} refused: ${M?.message||M}`,P==null?{}:{status:P})}k.pin(m,x.addresses),S=k.fetch}else Xt(S,m,x.addresses);return x};try{let w=String(e),P={...n||{}};l&&await _(w);for(let x=0;x<=er;x+=1){let m=await S(w,{method:r,headers:P,body:o,signal:b,redirect:"manual"});if(Mn.has(m.status)){if(r!=="GET"&&r!=="HEAD"){let $=await tr(m,u??Rn,{url:w,truncate:!0}),T=new Error(`HTTP ${m.status} ${r} ${w} redirected non-idempotent request`);throw T.status=m.status,T.body=rr($)??$.slice(0,300),T}if(x===er)throw Ie(m),new Error(`HTTP redirect loop for ${e}`);let U=m.headers?.get?.("location"),z;try{z=jn(U,w)}catch($){throw Ie(m),$}let y=!Hn(z,w);if(Ie(m),y&&(P=Fn(P)),l)await _(z,{status:m.status});else if(y){let $=await nt(z,I);if(!$.ok){let T=new Error(`HTTP redirect from ${w} ${$.error}`);throw T.status=m.status,T.retryable=!1,T}i&&$.addresses?.length&&(k||(k=await ot(d?{importUndici:d}:{})),k&&(k.pin(new URL(z).hostname,$.addresses),S=k.fetch))}w=z;continue}if(typeof c=="function")try{await c(m,{url:w})}catch(U){throw Ie(m),Te(U?.message||String(U))}let M=await tr(m,u,{url:w,onOversize:()=>p.abort()}),X=rr(M);if(!m.ok){let U=new Error(`HTTP ${m.status} ${r} ${w}`);throw U.status=m.status,U.retryAfter=m.headers?.get?.("retry-after")??null,U.body=X??M.slice(0,300),U}return X??M}throw new Error(`HTTP redirect loop for ${e}`)}finally{clearTimeout(h),k&&await k.close()}}async function or(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(),a={Accept:"application/json",...t.headers||{}},s=t.body;s!=null&&typeof s!="string"&&(a["Content-Type"]=a["Content-Type"]||"application/json",s=JSON.stringify(s));let i=Number.isInteger(t.retries)?Math.max(t.retries,0):Nn,l=t.lookupFn,u=!t.fetchImpl,d=t.untrustedUrl===!0,c=t.importUndici,f=t.validateResponse,p=t.signal,h=Number(t.maxResponseBytes),b=Number.isFinite(h)&&h>0?Math.floor(h):null,k=async()=>{let P;for(let x=0;x<=i;x++){p?.throwIfAborted?.();try{return await Dn(e,{fetchImpl:r,method:o,headers:a,body:s,timeoutMs:n,lookupFn:l,realFetch:u,untrustedUrl:d,maxResponseBytes:b,importUndici:c,validateResponse:f,signal:p})}catch(m){P=m;let M=m?.status,X=m?.name==="AbortError"||m?.name==="TimeoutError"||p?.aborted,U=new Set([408,425,429]),z=m?.retryable===!1?!1:M!=null?U.has(M)||On.has(M)&&Zt.has(o):!X&&Zt.has(o);if(x===i||!z)throw m;let y=qn(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 Un(y)}}throw P};if(!(t.dedupe!==!1&&!p&&o==="GET"&&s==null))return k();let I=Cn(o,e,a,{untrustedUrl:d,maxResponseBytes:b}),_=at.get(I);if(_)return _;let w=k().finally(()=>at.delete(I));return at.set(I,w),w}var On,Zt,Nn,Qt,nr,Mn,er,Rn,at,Un,sr=V(()=>{Wt();On=new Set([408,425,429,500,502,503,504]),Zt=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),Nn=2,Qt=4e3,nr=["authorization","x-api-key","x-tensor-api-key","0x-api-key","api-key","cookie","proxy-authorization"],Mn=new Set([301,302,303,307,308]),er=3,Rn=64*1024;at=new Map;Un=e=>new Promise(t=>setTimeout(t,e))});function Jn({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"?Vn:zn}async function lt(e,t={}){if(!e||!e.type)throw new Error("hlInfo requires body.type");let r=Jn(t);return or(r,{method:"POST",body:e,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs})}async function ir(e={}){return lt({type:"meta"},e)}async function ar({coin:e,interval:t="1h",startTime:r,endTime:n},o={}){if(!e)throw new Error("hlCandleSnapshot requires coin");let a={type:"candleSnapshot",req:{coin:String(e),interval:t,startTime:r??Date.now()-24*3600*1e3,endTime:n??Date.now()}};return lt(a,o)}async function cr({coin:e,startTime:t,endTime:r},n={}){if(!e)throw new Error("hlFundingHistory requires coin");return lt({type:"fundingHistory",coin:String(e),startTime:t??Date.now()-24*3600*1e3,endTime:r??Date.now()},n)}var zn,Vn,ut=V(()=>{sr();zn="https://api.hyperliquid.xyz/info",Vn="https://api.hyperliquid-testnet.xyz/info"});import{createHash as Kn}from"node:crypto";function re(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function we(e){return typeof e=="number"&&Number.isFinite(e)}function pt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)pt(t);return Object.freeze(e)}for(let t of Object.keys(e))pt(e[t]);return Object.freeze(e)}function fe(e){if(Array.isArray(e))return e.map(fe);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=fe(e[r]);return t}return e}function ft(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 lr(e){return{feesUsd:e.costs.feesUsd,builderFeesUsd:e.costs.builderFeesUsd,fundingUsd:e.costs.fundingUsd,slippageUsd:e.costs.slippageUsd}}function Gn(e){return(e.feesUsd||0)+(e.builderFeesUsd||0)+Math.max(0,e.fundingUsd||0)+(e.slippageUsd||0)}function Xn(e){let t=0;for(let r of e.trades)r.grossPnlUsd>0&&(t+=r.grossPnlUsd);return t}function Wn(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 fr(e){if(!re(e))throw new TypeError("evidence artifact must be a plain object");if(!Yn.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 fe({barsHash:e.barsHash,compilerHash:e.compilerHash,flags:e.flags.map(t=>fe(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 dr(e){return Kn("sha256").update(JSON.stringify(fr(e)),"utf8").digest("hex")}function Q(e,t,r=0){if(!Number.isInteger(e)||e<r)throw new Error(`${t} must be an integer >= ${r}`);return e}function dt(e,t){if(!re(e)||!re(e.metrics))throw new Error(`${t} metrics required`);let r=Q(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(!we(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 Zn(e,{maxDailyLossPct:t}={}){let r=e.split,n=Q(r.trainStartIndex,"split.trainStartIndex"),o=Q(r.trainEndIndex,"split.trainEndIndex"),a=Q(r.trainBarCount,"split.trainBarCount",1),s=Q(r.holdoutStartIndex,"split.holdoutStartIndex"),i=Q(r.holdoutEndIndex,"split.holdoutEndIndex"),l=Q(r.holdoutBarCount,"split.holdoutBarCount",1);if(n!==0||o-n+1!==a||s!==o+1||i-s+1!==l)throw new Error("evidence split must be contiguous, chronological, and count-consistent");if(!we(r.trainFraction)||r.trainFraction<=0||r.trainFraction>=1)throw new Error("split.trainFraction must be in (0,1)");dt(e.train,"train");let u=dt(e.holdout,"holdout");if(u.tradeCount<1||u.netPnlUsd<=0||u.profitFactor<=1)throw new Error("live-eligible holdout metrics do not pass");if(we(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 b=0;b<c.length;b++){let k=c[b];if(!re(k)||k.index!==b||typeof k.passed!="boolean")throw new Error("walk-forward windows must be ordered and structurally valid");let S=Q(k.trainStartIndex,`walkForward.windows[${b}].trainStartIndex`),I=Q(k.trainEndIndex,`walkForward.windows[${b}].trainEndIndex`),_=Q(k.evalStartIndex,`walkForward.windows[${b}].evalStartIndex`),w=Q(k.evalEndIndex,`walkForward.windows[${b}].evalEndIndex`);if(S!==0||I>=_||_>w||_<=p)throw new Error("walk-forward windows must be chronological and disjoint");if(p=w,k.passed){if(f+=1,k.reason!=="pass")throw new Error("passed walk-forward window reason must be pass");let P=dt({metrics:k.metrics,tradeCount:k.metrics?.tradeCount},`walkForward.windows[${b}]`);if(P.tradeCount<1||P.netPnlUsd<=0||P.profitFactor<=1)throw new Error("passed walk-forward window metrics do not pass");if(we(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(!we(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 pr(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=fr(e),n=fe({id:e.id,...r});if(JSON.stringify(fe(e))!==JSON.stringify(n))throw new Error("evidence artifact contains fields unbound from its deterministic identity");let o=dr(e);if(e.id!==o)throw new Error("evidence.id does not match its deterministic artifact facts digest");return e.status==="pass_live_eligible"&&Zn(e,t),e}function mt({strategy:e,bars:t,backtestOptions:r={},trainFraction:n=.7,walkForwardWindows:o=3,minTrades:a=10}={}){let s=[];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(!we(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(a)||a<0)throw new TypeError("minTrades must be an integer >= 0");let i=Y(e),l=ge(i),u=_e(t),d=t.length,c=(O=[],R={})=>ur({status:"fail",strategy:i,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:[...s,...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 b=t.slice(0,f),k=t.slice(p),S,I;try{S=ae(i,b,r),I=ae(i,k,r)}catch(O){return c([{type:"backtest_error",message:String(O.message||O)}])}let _={metrics:ft(S),costs:lr(S),tradeCount:S.metrics.tradeCount},w={metrics:ft(I),costs:lr(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)s.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,B=Math.min(d,J+m);if(B-J<3||R<3){x.push({index:O,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:J,evalEndIndex:B-1,passed:!1,reason:"window_too_small",metrics:null});continue}let ee=t.slice(J,B),He;try{He=ae(i,ee,r)}catch{x.push({index:O,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:J,evalEndIndex:B-1,passed:!1,reason:"backtest_error",metrics:null});continue}let Ce=ft(He),qe=Wn(Ce,i.risk,a);x.push({index:O,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:J,evalEndIndex:B-1,passed:qe,reason:qe?"pass":"fail_metrics",metrics:Ce})}let M=x.filter(O=>O.passed).length,X=x.length===0?0:M/x.length,U={windows:x,passRate:X,windowsRun:x.length};w.metrics.tradeCount===0&&_.metrics.tradeCount===0&&s.push({type:"no_trades",message:"no trades in train or holdout"}),w.metrics.tradeCount===0&&s.push({type:"absent_oos_trades",message:"holdout produced no trades"}),w.metrics.netPnlUsd<0&&s.push({type:"holdout_loss",message:"holdout netPnlUsd is negative"}),_.metrics.netPnlUsd>0&&w.metrics.netPnlUsd<0&&_.metrics.netPnlUsd>Math.abs(w.metrics.netPnlUsd)*.25?s.push({type:"overfit",message:"profitable train with losing holdout (OOS collapse)"}):_.metrics.netPnlUsd>0&&w.metrics.netPnlUsd>0&&w.metrics.netPnlUsd<_.metrics.netPnlUsd*.1&&_.metrics.tradeCount>=a&&s.push({type:"severe_oos_collapse",message:"holdout pnl collapsed vs train"});let z=Gn(w.costs),y=Xn(I);y>0&&z>y&&s.push({type:"costs_exceed_gross",message:"holdout costs exceed gross gains"});let $=s.some(O=>["insufficient_bars","invalid_windowing","absent_oos_trades","holdout_loss","no_trades","severe_oos_collapse","backtest_error"].includes(O.type)),T=s.some(O=>O.type==="overfit"),L="fail";return w.metrics.tradeCount>=a&&w.metrics.netPnlUsd>0&&w.metrics.profitFactor>1&&w.metrics.maxDrawdownPct<=i.risk.maxDailyLossPct&&X>=.6&&!(y>0&&z>y)&&!T&&!s.some(O=>O.type==="severe_oos_collapse"||O.type==="invalid_windowing")?L="pass_live_eligible":!$&&w.metrics.tradeCount>0&&_.metrics.tradeCount>0&&Number.isFinite(w.metrics.netPnlUsd)?(L="pass_paper_only",w.metrics.tradeCount<a&&s.push({type:"undersampled",message:"holdout trades below minTrades"})):T&&w.metrics.tradeCount>0&&_.metrics.netPnlUsd>0?L="fail":w.metrics.tradeCount>0&&_.metrics.tradeCount>0&&!$?L="pass_paper_only":L="fail",w.metrics.netPnlUsd<0&&(L=L==="pass_live_eligible"?"fail":L==="pass_paper_only"?"pass_paper_only":"fail",L="fail"),ur({status:L,strategy:i,sHash:l,barsHash:u,split:P,train:_,holdout:w,walkForward:U,flags:s})}function ur({status:e,strategy:t,sHash:r,barsHash:n,split:o,train:a,holdout:s,walkForward:i,flags:l}){let u={status:e,strategyHash:r,compilerHash:pe,barsHash:n,split:o,train:a,holdout:s,walkForward:i,flags:l};return u.id=dr(u),pt(fe(JSON.parse(JSON.stringify(u))))}var Yn,ht=V(()=>{me();de();Be();Yn=Object.freeze(["fail","pass_paper_only","pass_live_eligible"])});import{createHash as Qn,createHmac as eo,timingSafeEqual as Ei}from"node:crypto";function yt(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(yt).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${yt(e[r])}`).join(",")}}`}function mr(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function hr(e=process.env){return mr(process.env)||mr(e)}function oo(e){let{prepareHash:t,prepareMac:r,note:n,...o}=e||{};return o}function so(e){let t=oo(e);return Qn("sha256").update(yt(t)).digest("hex")}function io(e,t=hr()){return t?eo("sha256",t).update(String(e)).digest("hex"):""}function yr(e,{provider:t,kind:r,env:n=process.env,nowMs:o=Date.now(),expiresAtMs:a}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let s=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(s&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let i={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1,oraclePrepared:s?e.oraclePrepared:!0};if(!i.provider)throw new Error("stampPrepared: provider required");if(!i.kind)throw new Error("stampPrepared: kind required");let l=Number(o),u=a==null?l+ro:Number(a),d=u-l;if(!Number.isSafeInteger(l)||!Number.isSafeInteger(u)||d<=0||d>no)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let f={...i,preparedAt:l,expiresAt:u,prepareVersion:to},p=so(f),h=hr(n),b=h?io(p,h):void 0,k={...f,prepareHash:p};return b&&(k.prepareMac=b),k}var to,ro,no,wr=V(()=>{to=2,ro=300*1e3,no=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})()});function ve(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function co(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function gt(e,t="value"){if(Array.isArray(e)){e.forEach((r,n)=>gt(r,`${t}[${n}]`));return}if(ve(e))for(let[r,n]of Object.entries(e)){let o=co(r);if(ao.some(a=>o.includes(a)))throw new Error(`handoff: forbidden secret-like field at ${t}.${r}`);gt(n,`${t}.${r}`)}}function wt(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function gr({strategy:e,evidence:t,shadow:r,caps:n,nowMs:o=Date.now(),env:a=process.env}={}){if(gt({strategy:e,evidence:t,shadow:r,caps:n},"handoff"),!ve(e))throw new Error("handoff: strategy required");if(!ve(t))throw new Error("handoff: evidence required");if(!ve(r))throw new Error("handoff: shadow required");if(!ve(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 s=Y(e,{nowMs:o}),i=G(s);if(pr(t,{maxDailyLossPct:s.risk.maxDailyLossPct}),t.status!=="pass_live_eligible")throw new Error("handoff: evidence.status must be pass_live_eligible");if(t.strategyHash!==i.strategyHash)throw new Error("handoff: evidence.strategyHash mismatch");if(t.compilerHash!==i.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(!wt(n.perStrategyNotionalUsd))throw new Error("handoff: caps.perStrategyNotionalUsd must be positive");if(n.perStrategyNotionalUsd>i.strategy.risk.maxNotionalUsd)throw new Error("handoff: caps.perStrategyNotionalUsd exceeds strategy.risk.maxNotionalUsd");if(!wt(n.maxLeverage))throw new Error("handoff: caps.maxLeverage must be positive");if(n.maxLeverage>i.strategy.risk.maxLeverage)throw new Error("handoff: caps.maxLeverage exceeds strategy.risk.maxLeverage");if(!wt(n.dailyLossCapUsd))throw new Error("handoff: caps.dailyLossCapUsd must be positive");let u=i.strategy.risk.maxNotionalUsd*(i.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]!==i.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>i.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:i.strategyHash,compilerHash:i.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:i.strategyHash,compilerHash:i.compilerHash,compilerVersion:Oe,venue:"hyperliquid",market:{coin:i.strategy.market.coin,kind:"perp",interval:i.strategy.market.interval},risk:{...i.strategy.risk},strategy:JSON.parse(JSON.stringify(i.strategy))},arming:{liveBroadcast:!1,requiresExplicitUserArm:!0,caps:d},requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,executionReady:!1};return yr(c,{provider:"hl-strategy",kind:"strategy-live-handoff",env:a})}var ao,br=V(()=>{me();ht();de();wr();ao=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"]});function be(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function Ee(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be a non-negative safe integer`);return e}function Ne(e){if(Array.isArray(e))for(let t of e)Ne(t);else if(e&&typeof e=="object")for(let t of Object.values(e))Ne(t);return Object.freeze(e)}function uo(e){let t=lo[e];if(!t)throw new TypeError(`unsupported strategy interval: ${e}`);return t}function fo(e,{endTime:t=Number.MAX_SAFE_INTEGER}={}){if(!Array.isArray(e))throw new TypeError("Hyperliquid candles must be an array");Ee(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 a=Ee(Number(o.t),`candles[${n}].t`);if(Ee(Number(o.T),`candles[${n}].T`)>t)continue;let i={t:a,o:be(o.o,`candles[${n}].o`),h:be(o.h,`candles[${n}].h`),l:be(o.l,`candles[${n}].l`),c:be(o.c,`candles[${n}].c`),v:be(o.v,`candles[${n}].v`)};if(i.h<Math.max(i.o,i.c,i.l))throw new TypeError(`candles[${n}].h is below another price`);if(i.l>Math.min(i.o,i.c,i.h))throw new TypeError(`candles[${n}].l is above another price`);if(i.v<0)throw new TypeError(`candles[${n}].v must be non-negative`);let l=r.get(a);if(l&&JSON.stringify(l)!==JSON.stringify(i))throw new TypeError(`conflicting duplicate candle at timestamp ${a}`);l||r.set(a,i)}return Ne([...r.values()].sort((n,o)=>n.t-o.t))}function po(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 a=Ee(Number(o.time),`funding[${n}].time`);a>t||r.set(a,{time:a,fundingRate:be(o.fundingRate,`funding[${n}].fundingRate`)})}return[...r.values()].sort((n,o)=>n.time-o.time)}async function mo({coin:e,startTime:t,endTime:r},n){let o=[],a=Math.max(0,t-288e5),s=!1;for(let i=0;i<16&&a<=r;i++){let l=await cr({coin:e,startTime:a,endTime:r},n);if(!Array.isArray(l))throw new TypeError("Hyperliquid funding history must be an array");o.push(...l);let u=a;for(let d of l){let c=Number(d?.time);Number.isSafeInteger(c)&&c>u&&(u=c)}if(l.length<500||u>=r){s=!0;break}if(u<=a)throw new Error("Hyperliquid funding history pagination did not advance");a=u+1}if(!s)throw new Error("strategy history exceeds the bounded funding history limit");return po(o,r)}function ho(e,t,r){let n=0,o=null;return e.map(a=>{let s=a.t+r,i=0;for(;n<t.length&&t[n].time<s;){let l=t[n];o=l.fundingRate,l.time>=a.t&&(i+=l.fundingRate),n+=1}return o==null?{...a,fundingPaymentRate:i}:{...a,fundingRate:o,fundingPaymentRate:i}})}async function Er(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=uo(n);if(e.endTime==null)throw new TypeError("endTime is required for deterministic history");let a=Ee(e.endTime,"endTime"),s=e.count==null?1500:e.count;if(!Number.isInteger(s)||s<20||s>5e3)throw new TypeError("count must be an integer from 20 to 5000");let i=e.startTime==null?Math.max(0,a-s*o):Ee(e.startTime,"startTime");if(i>=a)throw new TypeError("startTime must be before endTime");let[l,u]=await Promise.all([ar({coin:r,interval:n,startTime:i,endTime:a},t),mo({coin:r,startTime:i,endTime:a},t)]),d=fo(l,{endTime:a}),c=Ne(ho(d,u,o));return Ne({coin:r,interval:n,range:{startTime:i,endTime:a},bars:c})}var lo,kr=V(()=>{ut();lo=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 go(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))wo.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"||!yo.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 bo(e={}){let t=await ir(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 yo,wo,xr,Sr=V(()=>{ut();br();kr();yo=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),wo=new Set(["coin","interval"]);xr=Object.freeze({id:"hyperliquid",validateMarket:go,fetchBars:Er,listMarkets:bo,prepareIntent(e){return gr(e)}})});function ko(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 Eo.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}function bt(e){return typeof e!="string"?null:xo.get(e)??null}function Et(e){let t=bt(e);if(!t)throw new Error(`unknown strategy venue: ${String(e)}`);return t}var Eo,Ar,xo,Ri,kt=V(()=>{Sr();Eo=Object.freeze(["id","validateMarket","prepareIntent"]);Ar=[xr].map(ko),xo=new Map(Ar.map(e=>[e.id,e])),Ri=Object.freeze([...Ar])});import{createHash as So}from"node:crypto";function Z(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function q(e){return typeof e=="number"&&Number.isFinite(e)}function Nr(e){return Number.isInteger(e)&&e>0}function Pt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Pt(t);return Object.freeze(e)}for(let t of Object.keys(e))Pt(e[t]);return Object.freeze(e)}function Tt(e){if(Array.isArray(e))return e.map(Tt);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Tt(e[r]);return t}return e}function g(e,t,r){e.push({path:t,message:r})}function ce(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 Fr(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 a=Math.round(o);return Math.abs(o-a)<=1e-9}function $t(e,t,r,n){if(Z(e)){if(ce(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!Z(o)||![o.value,o.min,o.max,o.step].every(Nr)?(g(n,`${t}.param`,"referenced period parameter value min max and step must be positive integers"),null):{param:e.param}}return Nr(e)?e:(g(n,t,"must be a positive integer or {param}"),null)}function Mr(e,t,r,n){return Z(e)?(ce(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)):q(e)?e:(g(n,t,"must be a finite number or {param}"),null)}function De(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 No(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 a=e.get(n);if(a){for(let s of De(a))if(e.has(s)&&r(s))return!0}return t.set(n,2),!1};for(let n of e.keys())if(r(n))return!0;return!1}function Mo(e,t){if(!Z(e))return g(t,"parameters","must be a plain object"),null;let r=Object.keys(e);if(r.length>_r)return g(t,"parameters",`too many parameters (max ${_r})`),null;let n={};for(let o of r){if(!Rr.test(o)){g(t,`parameters.${o}`,"parameter name is malformed");continue}let a=e[o],s=`parameters.${o}`;if(!Z(a)){g(t,s,"must be a plain object");continue}ce(a,Pr,s,t);for(let c of Pr)c in a||g(t,`${s}.${c}`,"required field is missing");let{value:i,min:l,max:u,step:d}=a;q(l)||g(t,`${s}.min`,"must be a finite number"),q(u)||g(t,`${s}.max`,"must be a finite number"),(!q(d)||d<=0)&&g(t,`${s}.step`,"must be a positive finite number"),q(i)||g(t,`${s}.value`,"must be a finite number"),q(l)&&q(u)&&l>u&&g(t,`${s}.min`,"min must be <= max"),q(i)&&q(l)&&q(u)&&q(d)&&d>0&&(Fr(i,l,u,d)||g(t,`${s}.value`,"value must lie on the declared min/max/step grid")),n[o]={value:i,min:l,max:u,step:d}}return n}function Ro(e,t,r,n){let o=`nodes.${t}`;if(!Z(e))return g(n,o,"must be a plain object"),null;if(typeof e.type!="string"||!Ir[e.type])return g(n,`${o}.type`,"unknown or missing node type"),ce(e,Oo,o,n),null;switch(ce(e,Ir[e.type],o,n),(typeof e.id!="string"||!Lr.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"||!Ao.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 a=Mr(e.value,`${o}.value`,r,n);return{id:e.id,type:"constant",value:a}}case"indicator":{(typeof e.indicator!="string"||!$o.has(e.indicator))&&g(n,`${o}.indicator`,"must be one of sma|ema|rsi|macd|bollinger|atr");let a=e.indicator,s={id:e.id,type:"indicator",indicator:a};if(a==="atr"){"input"in e&&(typeof e.input!="string"||!e.input?g(n,`${o}.input`,"must be a node id string when provided"):s.input=e.input);let i=$t(e.period,`${o}.period`,r,n);i!=null&&(s.period=i)}else typeof e.input!="string"||!e.input?g(n,`${o}.input`,"must be a node id string"):s.input=e.input;if((a==="sma"||a==="ema"||a==="rsi"||a==="bollinger"||a==="atr")&&("period"in e,a!=="macd"))if(!("period"in e))g(n,`${o}.period`,"required field is missing");else{let i=$t(e.period,`${o}.period`,r,n);i!=null&&(s.period=i)}if(a==="macd"){for(let i of["fastPeriod","slowPeriod","signalPeriod"])if(!(i in e))g(n,`${o}.${i}`,"required field is missing");else{let l=$t(e[i],`${o}.${i}`,r,n);l!=null&&(s[i]=l)}"output"in e?_o.has(e.output)?s.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(a==="bollinger"){if(!("stdDev"in e))g(n,`${o}.stdDev`,"required field is missing");else{let i=Mr(e.stdDev,`${o}.stdDev`,r,n);i!=null&&(typeof i=="number"&&i<=0?g(n,`${o}.stdDev`,"must be > 0"):s.stdDev=i)}"output"in e?vo.has(e.output)?s.output=e.output:g(n,`${o}.output`,"must be upper|middle|lower"):g(n,`${o}.output`,"required field is missing");for(let i of["fastPeriod","slowPeriod","signalPeriod"])i in e&&g(n,`${o}.${i}`,`forbidden for ${a}`)}else{"output"in e&&g(n,`${o}.output`,`forbidden for ${a}`),"stdDev"in e&&a!=="bollinger"&&g(n,`${o}.stdDev`,`forbidden for ${a}`);for(let i of["fastPeriod","slowPeriod","signalPeriod"])i in e&&g(n,`${o}.${i}`,`forbidden for ${a}`)}return s}case"compare":return(typeof e.op!="string"||!Po.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"||!To.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 a=[];for(let s=0;s<e.inputs.length;s++){let i=e.inputs[s];typeof i!="string"||!i?g(n,`${o}.inputs.${s}`,"must be a node id"):a.push(i)}return e.op==="not"?a.length!==1&&g(n,`${o}.inputs`,"not requires exactly one input"):(e.op==="and"||e.op==="or")&&a.length<2&&g(n,`${o}.inputs`,`${e.op} requires at least two inputs`),{id:e.id,type:"logic",op:e.op,inputs:a}}case"cross":return(typeof e.direction!="string"||!Io.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 Lo(e,t,r){if(!Z(e))return g(t,"risk","must be a plain object"),null;ce(e,Tr,"risk",t);for(let f of Tr)(!(f in e)||e[f]==null)&&g(t,`risk.${f}`,"required field is missing");let n={},o=e.maxLeverage;!q(o)||o<=0||o>50?g(t,"risk.maxLeverage","must be a number > 0 and <= 50"):n.maxLeverage=o;let a=e.maxNotionalUsd;!q(a)||a<=0?g(t,"risk.maxNotionalUsd","must be a number > 0"):n.maxNotionalUsd=a;let s=e.positionSizePct;!q(s)||s<=0||s>100?g(t,"risk.positionSizePct","must be a number > 0 and <= 100"):n.positionSizePct=s;let i=e.stopLossPct;!q(i)||i<=0||i>100?g(t,"risk.stopLossPct","must be a number > 0 and <= 100"):n.stopLossPct=i;let l=e.takeProfitPct;!q(l)||l<=0||l>1e3?g(t,"risk.takeProfitPct","must be a number > 0 and <= 1000"):n.takeProfitPct=l;let u=e.cooldownBars;!Number.isInteger(u)||u<0||u>1e5?g(t,"risk.cooldownBars","must be an integer >= 0 and <= 100000"):n.cooldownBars=u;let d=e.maxDailyLossPct;!q(d)||d<=0||d>100?g(t,"risk.maxDailyLossPct","must be a number > 0 and <= 100"):n.maxDailyLossPct=d;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 It(e,t={}){let r=[];if(!Z(e))return g(r,"","strategy must be a plain object"),{ok:!1,errors:r,strategy:null};ce(e,$r,"",r);for(let c of $r)(!(c in e)||e[c]==null)&&g(r,c,"required field is missing");e.version!==xt&&g(r,"version",`must be ${xt}`),(typeof e.id!="string"||!Rr.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>Or)&&g(r,"name",`must be a non-empty string max ${Or}`);let n=bt(e.venue);n||g(r,"venue",`unknown strategy venue "${String(e.venue)}"`);let o=null;if(!n)Z(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 f of c.errors)g(r,f.path,f.message)}let a=Mo(e.parameters,r),s=null,i=new Map;if(!Array.isArray(e.nodes))g(r,"nodes","must be an array");else if(e.nodes.length>vr)g(r,"nodes",`too many nodes (max ${vr})`);else{s=[];for(let c=0;c<e.nodes.length;c++){let f=Ro(e.nodes[c],c,a||{},r);f&&(typeof f.id=="string"&&Lr.test(f.id)&&(i.has(f.id)?g(r,`nodes.${c}.id`,`duplicate node id "${f.id}"`):i.set(f.id,f)),s.push(f))}for(let c=0;c<s.length;c++){let f=s[c],p=`nodes.${c}`;for(let h of De(f))i.has(h)||g(r,p,`unknown node ref "${h}"`);if(f.type==="indicator"||f.type==="compare"||f.type==="cross")for(let h of De(f)){let b=i.get(h);b&&St.has(b.type)&&g(r,p,`node ref "${h}" must be numeric`)}if(f.type==="logic")for(let h of De(f)){let b=i.get(h);b&&!St.has(b.type)&&g(r,p,`node ref "${h}" must be boolean`)}}No(i)&&g(r,"nodes","graph contains a cycle")}let l=null;if(!Z(e.rules))g(r,"rules","must be a plain object");else{ce(e.rules,At,"rules",r);for(let c of At)c in e.rules||g(r,`rules.${c}`,"required field is missing");l={};for(let c of At){let f=e.rules[c];if(f===null){l[c]=null;continue}if(typeof f!="string"||!f){g(r,`rules.${c}`,"must be a node id or null"),l[c]=f;continue}if(!i.has(f)){g(r,`rules.${c}`,`unknown node ref "${f}"`),l[c]=f;continue}let p=i.get(f);St.has(p.type)||g(r,`rules.${c}`,`rule must reference a boolean node, not ${p.type}`),l[c]=f}}let u=Lo(e.risk,r,t);if(r.length)return{ok:!1,errors:r,strategy:null};let d=Pt({version:xt,id:e.id,name:e.name,venue:n.id,market:o,parameters:a,nodes:s,rules:l,risk:u});return{ok:!0,errors:[],strategy:d}}function Y(e,t={}){let r=It(e,t);if(!r.ok)throw new ke(r.errors);return r.strategy}function Fo(e){let t=Y(e);return JSON.stringify(Tt(t))}function ge(e){let t=Fo(e);return So("sha256").update(t,"utf8").digest("hex")}function Me(e,t){if(!Z(e))throw new ke([{path:"",message:"strategy must be a plain object"}]);if(!Z(t))throw new ke([{path:"overrides",message:"must be a plain object"}]);let r=Y(e),n={};for(let[a,s]of Object.entries(r.parameters))n[a]={value:s.value,min:s.min,max:s.max,step:s.step};let o=[];for(let[a,s]of Object.entries(t)){if(!Object.prototype.hasOwnProperty.call(n,a)){g(o,a,`unknown parameter "${a}"`);continue}let i=n[a];if(!q(s)){g(o,a,"override must be a finite number");continue}if(!Fr(s,i.min,i.max,i.step)){g(o,a,"override must lie on the declared min/max/step grid");continue}n[a]={...i,value:s}}if(o.length)throw new ke(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(a=>{let s={...a};return Array.isArray(a.inputs)&&(s.inputs=[...a.inputs]),s}),rules:{...r.rules},risk:{...r.risk}})}var xt,Rr,Lr,Ao,$o,Po,To,Io,_o,vo,St,$r,Pr,At,Tr,Oo,Ir,_r,vr,Or,ke,de=V(()=>{kt();xt=1,Rr=/^[a-z0-9][a-z0-9._-]{0,63}$/,Lr=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Ao=new Set(["open","high","low","close","volume","fundingRate","openInterest","premium","oiDelta","bookImbalance"]),$o=new Set(["sma","ema","rsi","macd","bollinger","atr"]),Po=new Set(["gt","gte","lt","lte","eq"]),To=new Set(["and","or","not"]),Io=new Set(["above","below"]),_o=new Set(["line","signal","histogram"]),vo=new Set(["upper","middle","lower"]),St=new Set(["compare","logic","cross"]),$r=new Set(["version","id","name","venue","market","parameters","nodes","rules","risk"]),Pr=new Set(["value","min","max","step"]),At=new Set(["entryLong","entryShort","exitLong","exitShort"]),Tr=new Set(["maxLeverage","maxNotionalUsd","positionSizePct","stopLossPct","takeProfitPct","cooldownBars","maxDailyLossPct","expiresAt"]),Oo=new Set(["id","type"]),Ir={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"])},_r=16,vr=128,Or=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 Re(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 le(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("period must be a positive integer")}function jo(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 Hr(e,t){Re(e),le(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 ze(e,t){Re(e),le(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=0;for(let s=0;s<t;s++)n+=e[s];let o=n/t;r[t-1]=o;let a=2/(t+1);for(let s=t;s<e.length;s++)o=a*e[s]+(1-a)*o,r[s]=o;return r}function Cr(e,t){Re(e),le(t);let r=new Array(e.length).fill(null);if(e.length<=t)return r;let n=0,o=0;for(let i=1;i<=t;i++){let l=e[i]-e[i-1];l>=0?n+=l:o-=l}let a=n/t,s=o/t;r[t]=jr(a,s);for(let i=t+1;i<e.length;i++){let l=e[i]-e[i-1],u=l>0?l:0,d=l<0?-l:0;a=(a*(t-1)+u)/t,s=(s*(t-1)+d)/t,r[i]=jr(a,s)}return r}function jr(e,t){return e===0&&t===0?50:t===0?100:e===0?0:100-100/(1+e/t)}function qr(e,t={}){Re(e);let r=t.fastPeriod,n=t.slowPeriod,o=t.signalPeriod;if(le(r),le(n),le(o),r>=n)throw new TypeError("fastPeriod must be < slowPeriod");let a=ze(e,r),s=ze(e,n),i=new Array(e.length).fill(null);for(let c=0;c<e.length;c++)a[c]!=null&&s[c]!=null&&(i[c]=a[c]-s[c]);let l=new Array(e.length).fill(null),u=new Array(e.length).fill(null),d=[];for(let c=0;c<i.length;c++)i[c]!=null&&d.push(c);if(d.length>=o){let c=0;for(let b=0;b<o;b++)c+=i[d[b]];let f=c/o,p=d[o-1];l[p]=f,u[p]=i[p]-f;let h=2/(o+1);for(let b=o;b<d.length;b++){let k=d[b];f=h*i[k]+(1-h)*f,l[k]=f,u[k]=i[k]-f}}return{line:i,signal:l,histogram:u}}function Ur(e,t={}){Re(e);let r=t.period,n=t.stdDev;if(le(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),a=new Array(e.length).fill(null),s=new Array(e.length).fill(null);if(e.length<r)return{upper:a,middle:o,lower:s};let i=0,l=0;for(let u=0;u<e.length;u++){let d=e[u];if(i+=d,l+=d*d,u>=r){let c=e[u-r];i-=c,l-=c*c}if(u>=r-1){let c=i/r,f=l/r-c*c;f<0&&f>-1e-12&&(f=0);let p=Math.sqrt(f);o[u]=c,a[u]=c+n*p,s[u]=c-n*p}}return{upper:a,middle:o,lower:s}}function Br(e,t){jo(e),le(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=new Array(e.length);for(let s=0;s<e.length;s++){let i=e[s];if(s===0)n[s]=i.h-i.l;else{let l=e[s-1].c;n[s]=Math.max(i.h-i.l,Math.abs(i.h-l),Math.abs(i.l-l))}}let o=0;for(let s=0;s<t;s++)o+=n[s];let a=o/t;r[t-1]=a;for(let s=t;s<e.length;s++)a=(a*(t-1)+n[s])/t,r[s]=a;return r}var Dr=V(()=>{});import{createHash as Ho}from"node:crypto";var _t,Co,qo,Uo,zr,Vr=V(()=>{_t=3,Co="7477966facc4ef928a94e6221c8fd238eef4fcbeec46b96ae1b89178e13c2d5f",qo="68f5b412a9975f04024cf9b9b6209b4bccedd52f176e95f34f786b3f53479c6a",Uo="967fd45ecddd0d59ac0f662fe92ea813c32620ba751f249b4ace6cb6b809fb5e",zr=Ho("sha256").update(JSON.stringify({version:_t,compilerSourceHash:Co,indicatorsSourceHash:qo,schemaSourceHash:Uo})).digest("hex")});function W(e){return typeof e=="number"&&Number.isFinite(e)}function zo(e){let t=new Map(e.map(i=>[i.id,i])),r=i=>{switch(i.type){case"indicator":return i.input?[i.input]:[];case"compare":case"cross":return[i.left,i.right];case"logic":return[...i.inputs];default:return[]}},n=new Map,o=new Map;for(let i of e)n.set(i.id,0),o.set(i.id,[]);for(let i of e)for(let l of r(i))t.has(l)&&(o.get(l).push(i.id),n.set(i.id,n.get(i.id)+1));let a=[];for(let[i,l]of n)l===0&&a.push(i);let s=[];for(;a.length;){let i=a.shift();s.push(i);for(let l of o.get(i))n.set(l,n.get(l)-1),n.get(l)===0&&a.push(l)}if(s.length!==e.length)throw new Error("strategy graph is cyclic");return s}function xe(e,t){return e!=null&&typeof e=="object"&&"param"in e?t[e.param].value:e}function Vo(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 a=e[o];if(a==null||typeof a!="object"||Array.isArray(a))throw new TypeError(`bars[${o}] must be an object`);let{t:s,o:i,h:l,l:u,c:d,v:c}=a;if(!W(s)&&(typeof s=="number"&&Number.isFinite(s)),!Number.isFinite(s))throw new TypeError(`bars[${o}].t must be finite`);for(let[f,p]of[["o",i],["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",i],["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(i,d,u))throw new TypeError(`bars[${o}] high must be >= max(open, close, low)`);if(u>Math.min(i,d,l))throw new TypeError(`bars[${o}] low must be <= min(open, close, high)`);if(n!=null){if(!(s>n))throw new TypeError("bars t must be strictly increasing");if(s-n!==Do[r])throw new TypeError(`bars t must match ${r} cadence`)}if(n=s,"fundingRate"in a&&a.fundingRate!=null&&!W(a.fundingRate))throw new TypeError(`bars[${o}].fundingRate must be finite when present`);if("openInterest"in a&&a.openInterest!=null){if(!W(a.openInterest))throw new TypeError(`bars[${o}].openInterest must be finite when present`);if(a.openInterest<0)throw new TypeError(`bars[${o}].openInterest must be non-negative`)}for(let f of["premium","oiDelta"])if(f in a&&a[f]!=null&&!W(a[f]))throw new TypeError(`bars[${o}].${f} must be finite when present`);if("bookImbalance"in a&&a.bookImbalance!=null){if(!W(a.bookImbalance))throw new TypeError(`bars[${o}].bookImbalance must be finite when present`);if(a.bookImbalance<-1||a.bookImbalance>1)throw new TypeError(`bars[${o}].bookImbalance must be within [-1, 1]`)}}}function he(e,t,r,n,o,a){if(a.has(e))return a.get(e);let s=t.get(e),i;switch(s.type){case"input":{let l=Bo[s.field];i=new Array(o+1);for(let u=0;u<=o;u++){let d=n[u][l];i[u]=d===void 0?null:d}break}case"constant":{let l=xe(s.value,r);i=new Array(o+1).fill(l);break}case"indicator":{let l=s.period!=null?xe(s.period,r):void 0;if(s.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})}i=Br(c,l);break}let d=he(s.input,t,r,n,o,a).map((c,f)=>{if(c==null||!W(c))throw new TypeError(`indicator input ${s.input} has non-finite value at ${f}`);return c});if(s.indicator==="sma")i=Hr(d,l);else if(s.indicator==="ema")i=ze(d,l);else if(s.indicator==="rsi")i=Cr(d,l);else if(s.indicator==="macd")i=qr(d,{fastPeriod:xe(s.fastPeriod,r),slowPeriod:xe(s.slowPeriod,r),signalPeriod:xe(s.signalPeriod,r)})[s.output];else if(s.indicator==="bollinger")i=Ur(d,{period:l,stdDev:xe(s.stdDev,r)})[s.output];else throw new Error(`unsupported indicator ${s.indicator}`);break}case"compare":{let l=he(s.left,t,r,n,o,a),u=he(s.right,t,r,n,o,a);i=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)){i[d]=!1;continue}switch(s.op){case"gt":i[d]=c>f;break;case"gte":i[d]=c>=f;break;case"lt":i[d]=c<f;break;case"lte":i[d]=c<=f;break;case"eq":i[d]=c===f;break;default:i[d]=!1}}break}case"logic":{let l=s.inputs.map(u=>he(u,t,r,n,o,a));i=new Array(o+1);for(let u=0;u<=o;u++)if(s.op==="not"){let d=l[0][u];i[u]=d===!0?!1:d===!1}else if(s.op==="and"){let d=!0;for(let c of l)if(c[u]!==!0){d=!1;break}i[u]=d}else if(s.op==="or"){let d=!1;for(let c of l)if(c[u]===!0){d=!0;break}i[u]=d}else i[u]=!1;break}case"cross":{let l=he(s.left,t,r,n,o,a),u=he(s.right,t,r,n,o,a);i=new Array(o+1),i[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)){i[d]=!1;continue}s.direction==="above"?i[d]=c<=f&&p>h:i[d]=c>=f&&p<h}break}default:throw new Error(`unknown node type ${s.type}`)}return a.set(e,i),i}function G(e,t={}){let r=Y(e);t&&Object.keys(t).length&&(r=Me(r,t));let n=new Map(r.nodes.map(p=>[p.id,p])),o=Object.freeze(zo(r.nodes)),a=r.parameters,s=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"])s.add(p);let i=Object.freeze([...s].sort()),l=ge(r);function u(p,h){let b={};for(let S of o){let I=p.get(S);b[S]=I[h]}let k=S=>S!=null&&b[S]===!0;return{values:b,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){Vo(p,h,r.market.interval);let b=new Map;for(let k of o)he(k,n,a,p,h,b);return b}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,b=d(p,h);return Object.freeze(p.map((k,S)=>Object.freeze(u(b,S))))}return Object.freeze({strategy:r,strategyHash:l,compilerVersion:Oe,compilerHash:pe,requiredSeries:i,nodeOrder:o,evaluate:c,evaluateAll:f})}var Oe,pe,Bo,Do,me=V(()=>{de();Dr();Vr();Oe=_t,pe=zr,Bo=Object.freeze({open:"o",high:"h",low:"l",close:"c",volume:"v",fundingRate:"fundingRate",openInterest:"openInterest",premium:"premium",oiDelta:"oiDelta",bookImbalance:"bookImbalance"}),Do=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5})});import{createHash as Jo}from"node:crypto";function Yo(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 Ve(e){if(Array.isArray(e))return e.map(Ve);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Ve(e[r]);return t}return e}function Ot(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)=>Ot(r,`${t}[${n}]`));return}for(let[r,n]of Object.entries(e))Ot(n,`${t}.${r}`)}}function Kr(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:a,h:s,l:i,c:l,v:u}=n;if(!ne(o))throw new TypeError(`bars[${r}].t must be finite`);for(let[d,c]of[["o",a],["h",s],["l",i],["c",l],["v",u]])if(!ne(c))throw new TypeError(`bars[${r}].${d} must be a finite number`);for(let[d,c]of[["o",a],["h",s],["l",i],["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(s<Math.max(a,l,i))throw new TypeError(`bars[${r}] high must be >= max(open, close, low)`);if(i>Math.min(a,l,s))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 _e(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");return e.length>0&&Kr(e),Jo("sha256").update(JSON.stringify(Ve(e)),"utf8").digest("hex")}function Go(e){if(e==null&&(e={}),!Yo(e))throw new TypeError("options must be a plain object");let t={...Ko},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 Je(e){return e/1e4}function Xo(e,t,r){let n=Je(r);return t==="long"?e*(1+n):e*(1-n)}function Wo(e,t,r){let n=Je(r);return t==="long"?e*(1-n):e*(1+n)}function Jr(e,t,r){let n=Math.abs(e)*Je(t),o=Math.abs(e)*Je(r);return{taker:n,builder:o,total:n+o}}function Zo(e,t){let r=e*(t.positionSizePct/100)*t.maxLeverage;return Math.min(r,t.maxNotionalUsd)}function Qo(e,t,r){let n=r/100;return t==="long"?e*(1-n):e*(1+n)}function es(e,t,r){let n=r/100;return t==="long"?e*(1+n):e*(1-n)}function ts(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 rs(e,t,r){return t==="long"?e.l<=r:e.h>=r}function ns(e,t,r){return t==="long"?e.h>=r:e.l<=r}function os(e,t,r){return t==="long"?e.l<=r:e.h>=r}function Le(e,t){for(let r of e.requiredSeries)if(ss.includes(r)&&!t.every(n=>ne(n?.[r])))throw new Error(`strategy required series is absent: ${r}`)}function is(e){if(e.length<3)return 0;let t=[];for(let s=1;s<e.length;s++){let i=e[s-1].equity,l=e[s].equity;i>0&&t.push((l-i)/i)}if(t.length<2)return 0;let r=0;for(let s of t)r+=s;let n=r/t.length,o=0;for(let s of t)o+=(s-n)**2;let a=Math.sqrt(o/(t.length-1));return a>0?n/a:0}function as(e){let t=-1/0,r=0;for(let n of e){let o=n.equity;if(o>t&&(t=o),t>0){let a=(t-o)/t*100;a>r&&(r=a)}}return r}function ae(e,t,r={}){let n=Go(r);Kr(t);let o=_e(t);n.nowMs!==void 0&&Y(e,{nowMs:n.nowMs});let a=G(e);if(Le(a,t),n.nowMs!==void 0&&a.strategy.risk.expiresAt<=n.nowMs)throw new Error("strategy is expired: risk.expiresAt must be strictly greater than nowMs");let s=a.strategy.risk,i=a.evaluateAll(t),l=n.latencyBars,u=n.slippageBps,d=n.takerFeeBps,c=n.builderFeeBps,f=n.initialEquityUsd,p=0,h=0,b=0,k=0,S=0,I=[],_=[],w=[],P=[],x=[],m=null,M=0,X=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=Zo(f,s);if(!(N>0)||!(H>0))return;let C=Xo(H,v,u),F=N/C,D=O(E),$e=C*D;if(F>D){w.push({kind:"entry",barIndex:E,time:A.t,side:v,requestedNotionalUsd:N,maxFillNotionalUsd:$e,reason:"volume_participation"});return}L[E]+=F;let te=Math.abs(C-H)*F,se=Jr(N,d,c);f-=se.total,p+=se.taker,h+=se.builder,k+=te,S+=N,m={lifecycleEpoch:++$,side:v,entryBarIndex:E,entryReferencePrice:H,entryPrice:C,qty:F,notionalUsd:N,stop:Qo(C,v,s.stopLossPct),take:es(C,v,s.takeProfitPct),liq:ts(C,v,s.maxLeverage,d+c),entryFees:se.taker,entryBuilderFees:se.builder,entrySlippageUsd:te,fundingAccrued:0}}function B(E,v,A,H){if(!m)return!1;let N=m.side,C=v,F=C;A!=="liquidation"&&H&&(F=Wo(C,N,u));let D=m.qty,$e=D*F;if(A!=="liquidation"){let Gt=O(E),Sn=F*Gt;if(D>Gt)return w.push({kind:"exit",barIndex:E,time:t[E].t,side:N,requestedNotionalUsd:$e,maxFillNotionalUsd:Sn,reason:"volume_participation",triggerReason:A}),!1;L[E]+=D}let te=Jr($e,d,c),se=A==="liquidation"?0:Math.abs(F-C)*D,Pe,et;N==="long"?(Pe=(C-m.entryReferencePrice)*D,et=(F-m.entryPrice)*D):(Pe=(m.entryReferencePrice-C)*D,et=(m.entryPrice-F)*D),f+=et,f-=te.total,p+=te.taker,h+=te.builder,k+=se,S+=$e;let xn={side:N,entryBarIndex:m.entryBarIndex,entryTime:t[m.entryBarIndex].t,entryPrice:m.entryPrice,exitBarIndex:E,exitTime:t[E].t,exitPrice:F,exitReason:A,qty:D,notionalUsd:m.notionalUsd,grossPnlUsd:Pe,feesUsd:m.entryFees+te.taker,builderFeesUsd:m.entryBuilderFees+te.builder,fundingUsd:m.fundingAccrued,slippageUsd:m.entrySlippageUsd+se,netPnlUsd:Pe-(m.entryFees+te.taker+m.entryBuilderFees+te.builder)-m.fundingAccrued-(m.entrySlippageUsd+se)};return I.push(xn),A==="liquidation"&&_.push({barIndex:E,time:t[E].t,side:N,price:F,tradeIndex:I.length-1}),m=null,$+=1,y=E+1+(s.cooldownBars||0),!0}function ee(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 He(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";B(E,t[E].o,H,!0)||ee(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 Ce(E){if(!m)return;let v=t[E],A=v.fundingPaymentRate;if(A==null||!ne(A)||A===0)return;let H=Math.abs(m.qty*v.c),N=A*H;m.side==="long"?(f-=N,m.fundingAccrued+=N,b+=N):(f+=N,m.fundingAccrued-=N,b-=N)}function qe(E){if(!m)return;let v=t[E].o;(m.side==="long"?v<=m.liq:v>=m.liq)&&B(E,v,"liquidation",!1)}function zt(E){if(!m)return;let v=t[E],A=m.side,H=os(v,A,m.liq),N=rs(v,A,m.stop),C=ns(v,A,m.take),F=D=>A==="long"?Math.min(D,v.o):Math.max(D,v.o);if(H){B(E,F(m.liq),"liquidation",!1);return}if(N&&C){B(E,F(m.stop),"stop_loss",!0)||ee(E,A,"stop_loss",m.lifecycleEpoch);return}if(N){B(E,F(m.stop),"stop_loss",!0)||ee(E,A,"stop_loss",m.lifecycleEpoch);return}C&&(B(E,m.take,"take_profit",!0)||ee(E,A,"take_profit",m.lifecycleEpoch))}for(let E=0;E<t.length;E++){let v=Math.floor(t[E].t/864e5);v!==X&&(X=v,U=R(t[E].o),z=!1),qe(E),He(E),zt(E),Ce(E),!z&&R(t[E].c)<=U*(1-s.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=i[E].signals,H=E+l;if(m)(m.side==="long"&&A.exitLong===!0||m.side==="short"&&A.exitShort===!0)&&H<t.length&&(T.some(D=>D.kind==="exit"&&D.side===m.side&&D.fillBar===H&&D.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 Vt=null;if(m){let E=t.length-1;if(B(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);Vt={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 Jt=(m?R(t[t.length-1].c):f)-n.initialEquityUsd,gn=Jt/n.initialEquityUsd*100,Kt=0,Xe=0,We=0;for(let E of I)E.netPnlUsd>0?(Kt+=1,Xe+=E.netPnlUsd):E.netPnlUsd<0&&(We+=-E.netPnlUsd);let Ze=I.length,bn=Ze===0?0:Kt/Ze,Qe=0;We>0?Qe=Xe/We:Xe>0&&(Qe=1e12);let En={netPnlUsd:Jt,netPnlPct:gn,maxDrawdownPct:as(x),winRate:bn,profitFactor:Qe,tradeCount:Ze,sharpe:is(x),turnoverUsd:S,exposurePct:M/t.length*100},kn={initialEquityUsd:n.initialEquityUsd,takerFeeBps:n.takerFeeBps,builderFeeBps:n.builderFeeBps,slippageBps:n.slippageBps,latencyBars:n.latencyBars,maxVolumeParticipationPct:n.maxVolumeParticipationPct},Yt={barsHash:o,strategyHash:a.strategyHash,compilerHash:pe,compilerVersion:Oe,config:kn,trades:I,equityCurve:x,metrics:En,costs:{feesUsd:p,builderFeesUsd:h,fundingUsd:b,slippageUsd:k},liquidations:_,missedFills:w,openPositionAtEnd:Vt,flags:P};return Ot(Yt),vt(Ve(Yt))}var Ko,ss,Be=V(()=>{me();de();Ko=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:100});ss=Object.freeze(["fundingRate","openInterest","premium","oiDelta","bookImbalance"])});import{createHash as cs}from"node:crypto";function ys(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Nt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Nt(t);return Object.freeze(e)}for(let t of Object.keys(e))Nt(e[t]);return Object.freeze(e)}function ws(e){return String(e).trim().replace(/\s+/g," ")}function gs(e){let t=e.match(/\b(long|short)\b/i);return t?t[1].toLowerCase():null}function bs(e){for(let r of us)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 Es(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 ls.has(r)?r:null}function ks(e){let t={...ds},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 a=e.match(/position\s*size\s*(\d+(?:\.\d+)?)\s*%?/i);a&&(t.positionSizePct=Number(a[1]));let s=e.match(/max\s*notional\s*(?:usd\s*)?\$?\s*(\d+(?:\.\d+)?)/i);return s&&(t.maxNotionalUsd=Number(s[1])),t}function xs(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 Ss(e){let t=cs("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 As(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 a=/\b(exit\s+on\s+reverse|reverse\s+exit)\b/i.test(e);return{kind:"ema_cross",fast:r,slow:o,direction:n,reverse:a}}function $s(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 Ps(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 Ts(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 Is(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 _s(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 vs(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 Os(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 Yr(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 Ns({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:s,spec:i}){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:i.direction,left:"emaLeft",right:"emaRight"}],u={entryLong:null,entryShort:null,exitLong:null,exitShort:null};if(e==="long"?u.entryLong="cross":u.entryShort="cross",i.reverse){let d=i.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:a,name:s,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{ema_left_period:Yr(i.fast),ema_right_period:Yr(i.slow)},nodes:l,rules:u,risk:{...n,expiresAt:o}}}function Ms({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:s,spec:i}){let l=[{id:"c",type:"input",field:"close"},{id:"rsi",type:"indicator",indicator:"rsi",input:"c",period:i.period},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"rsi",right:"thr"}];return{version:1,id:a,name:s,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 Rs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:s,spec:i}){let l=[{id:"fr",type:"input",field:"fundingRate"},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"fr",right:"thr"}];return{version:1,id:a,name:s,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 Ls({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:s,spec:i}){let l=[{id:"oi",type:"input",field:"openInterest"},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"oi",right:"thr"}];return{version:1,id:a,name:s,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 js({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:s,spec:i}){let u=[{id:"sig_input",type:"input",field:Fs[i.kind]},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"sig_input",right:"thr"}];return{version:1,id:a,name:s,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 Gr(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(!ys(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=hs;if("expiresInMs"in t){if(!Number.isInteger(t.expiresInMs))throw new K("expiresInMs must be an integer");if(n=t.expiresInMs,n<ps||n>ms)throw new K("expiresInMs must be between 1h and 30d")}if(fs.test(e))throw new K(`prompt appears to contain secrets and is rejected. ${Se}`);let o=ws(e);if(!o)throw new K(`empty prompt. ${Se}`);if(xs(o))throw new K(`duplicate interval or risk clause. ${Se}`);let a=gs(o),s=bs(o),i=Es(o);if(!a||!s||!i)throw new K(`could not parse side/coin/interval. ${Se}`);let l=ks(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 u=r+n,d=Ss(o),c=`Draft ${s} ${a}`.slice(0,100),f=As(o),p=$s(o),h=Ps(o),b=Ts(o),k=Is(o),S=_s(o),I=vs(o),_=[f,p,h,b,k,S,I].filter(Boolean);if(_.length!==1)throw new K(`unsupported or ambiguous prompt. ${Se}`);if(!Os(o,_[0]))throw new K(`unsupported or ambiguous prompt. ${Se}`);let w,P=_[0],x={side:a,coin:s,interval:i,risk:l,expiresAt:u,id:d,name:c,spec:P};P.kind==="ema_cross"?w=Ns(x):P.kind==="rsi"?w=Ms(x):P.kind==="open_interest"?w=Ls(x):P.kind==="funding"?w=Rs(x):w=js(x);let m=It(w,{nowMs:r});if(!m.ok)throw new K(`draft failed validation: ${m.errors.map(M=>M.message).join("; ")}`);return Nt(Y(w,{nowMs:r}))}var K,ls,us,fs,Se,ds,ps,ms,hs,Fs,Xr=V(()=>{de();K=class extends Error{constructor(t){super(t),this.name="StrategyDraftError"}},ls=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),us=new Set(["BTC","ETH","SOL","HYPE"]),fs=/\b(mnemonic|private\s*key|privkey|seed\s*phrase|seed\b|api[_-]?key|secret\s*key|wallet\s*key|passphrase)\b/i,Se="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.",ds=Object.freeze({maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3}),ps=36e5,ms=30*864e5,hs=864e5;Fs=Object.freeze({funding:"fundingRate",open_interest:"openInterest",premium:"premium",oi_delta:"oiDelta",book_imbalance:"bookImbalance"})});import{createHash as Hs}from"node:crypto";function Qr(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 en(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Rt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Rt(t);return Object.freeze(e)}for(let t of Object.keys(e))Rt(e[t]);return Object.freeze(e)}function Fe(e){if(Array.isArray(e))return e.map(Fe);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Fe(e[r]);return t}return e}function Ke(e){return JSON.stringify(Fe(e))}function Cs(e){let{min:t,max:r,step:n}=e;if(!(n>0)||t>r)return[];let o=[],a=Math.floor((r-t)/n+1e-9);for(let i=0;i<=a;i++){let l=t+i*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 s=o[o.length-1];if(Math.abs(s-r)>1e-9){let i=(r-t)/n;Math.abs(i-Math.round(i))<=1e-9&&o.push(r)}return o}function qs(e,t){if(e.length===0)return[];let r=[{}];for(let n of e){let o=t[n],a=[];for(let s of r)for(let i of o)a.push({...s,[n]:i});r=a}return r.sort((n,o)=>{let a=Ke(n),s=Ke(o);return a<s?-1:a>s?1:0}),r}function Mt(e,t,r,n,o){let a=0;if(e==="maxDrawdownPct"){if(a=t.maxDrawdownPct-n.maxDrawdownPct,a!==0)return a<0}else if(a=t[e]-n[e],a!==0)return a>0;let s=Ke(r),i=Ke(o);return s<i}function tn(e,t,r={}){if(!en(r))throw new TypeError("options must be a plain object");for(let w of Object.keys(r))if(Qr(w))throw new TypeError(`options must not include holdout/test/oos key "${w}"`);let n=new Set(["maxTrials","objective","backtestOptions"]);for(let w of Object.keys(r))if(!n.has(w))throw new TypeError(`unknown option "${w}"`);let o=64;if("maxTrials"in r){let w=r.maxTrials;if(!Number.isInteger(w)||w<1||w>Wr)throw new TypeError(`maxTrials must be an integer 1..${Wr}`);o=w}let a=r.objective??"netPnlUsd";if(!Zr.has(a))throw new TypeError(`objective must be one of ${[...Zr].join("|")}`);let s=r.backtestOptions??{};if(!en(s))throw new TypeError("backtestOptions must be a plain object");for(let w of Object.keys(s))if(Qr(w))throw new TypeError(`backtestOptions must not include holdout/test/oos key "${w}"`);let i=Y(e),l=Object.keys(i.parameters).sort();if(l.length===0)throw new Error("optimizeStrategy requires at least one declared parameter");let u={},d=1;for(let w of l){let P=Cs(i.parameters[w]);if(P.length===0)throw new Error(`parameter "${w}" produces an empty grid`);u[w]=P,d*=P.length}let c=qs(l,u);if(c.length===0)throw new Error("parameter grid is empty");let f=c.slice(0,o),p=[],h=null,b=null;for(let w of f){let P=Me(i,w),x=ae(P,t,s);b==null&&(b=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:{...w},metrics:m};p.push(M),(!h||Mt(a,m,w,h.metrics,h.parameters))&&(h=M)}p.sort((w,P)=>Mt(a,w.metrics,w.parameters,P.metrics,P.parameters)?-1:Mt(a,P.metrics,P.parameters,w.metrics,w.parameters)?1:0);let k={...h.parameters},S=Me(i,k),I={strategyHash:ge(i),compilerHash:pe,trainBarsHash:_e(t),backtestConfig:b,objective:a,maxTrials:o,trialsRun:p.length,candidates:p,bestParameters:k,bestStrategy:S},_={id:Hs("sha256").update(JSON.stringify(Fe(I)),"utf8").digest("hex"),...I};return Rt(Fe(JSON.parse(JSON.stringify(_))))}var Wr,Zr,rn=V(()=>{me();de();Be();Wr=256,Zr=new Set(["netPnlUsd","profitFactor","sharpe","maxDrawdownPct"])});import ie from"node:fs";import Ye from"node:path";function Ge(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function oe(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Bs(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Ae(e,t="record"){if(Array.isArray(e)){e.forEach((r,n)=>Ae(r,`${t}[${n}]`));return}if(Ge(e))for(let[r,n]of Object.entries(e)){let o=Bs(r);if(Us.some(a=>o.includes(a)))throw new Error(`shadow-store: forbidden secret-like field at ${t}.${r}`);Ae(n,`${t}.${r}`)}}function Ds(e){if(typeof e!="string"||!e||!Ye.isAbsolute(e))throw new Error("shadow-store: path must be an absolute path")}function nn(e){let t;try{t=ie.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 zs(){return{version:Ft,runners:[]}}function on(e,t){let r;try{r=JSON.parse(e)}catch{throw new Error("shadow-store: malformed JSON")}if(!Ge(r))throw new Error("shadow-store: malformed JSON root");if(r.version!==Ft)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 Ae(r,Ye.basename(t)),{version:Ft,runners:r.runners.map(n=>oe(n))}}function sn(e,t){Ae(t,"store");let r=Ye.dirname(e);ie.mkdirSync(r,{recursive:!0,mode:448});let n=Ye.join(r,`.shadow-store.${process.pid}.${Date.now()}.tmp`),o=`${JSON.stringify(t)}
3
+ `;try{ie.writeFileSync(n,o,{mode:384,flag:"wx"}),ie.renameSync(n,e);try{ie.chmodSync(e,384)}catch{}}catch(a){try{ie.unlinkSync(n)}catch{}throw a}}function an(e={}){let t=e.path;if(Ds(t),nn(t),ie.existsSync(t)?on(ie.readFileSync(t,"utf8"),t):sn(t,zs()),Lt.has(t))return Lt.get(t);let r=!1,n=[];function o(){if(r)return;let h=n.shift();if(h){r=!0;try{let b=h.fn();r=!1,h.resolve(b),o()}catch(b){r=!1,h.reject(b),o()}}}function a(h){if(!r&&n.length===0){r=!0;try{return h()}finally{r=!1,queueMicrotask(o)}}return new Promise((b,k)=>{n.push({fn:h,resolve:b,reject:k}),queueMicrotask(o)})}function s(){return nn(t),on(ie.readFileSync(t,"utf8"),t)}function i(h){sn(t,h)}function l(h){if(!Ge(h)||typeof h.id!="string"||!h.id)throw new Error("shadow-store: create requires record with string id");Ae(h,"record");let b=s();if(b.runners.some(S=>S.id===h.id))throw new Error(`shadow-store: runner id already exists: ${h.id}`);let k=oe(h);return b.runners.push(k),i(b),oe(k)}function u(h){let b=s().runners.find(k=>k.id===h);return b?oe(b):null}function d(){return s().runners.map(h=>oe(h))}function c(h,b){if(typeof b!="function")throw new Error("shadow-store: updater must be a function");let k=s(),S=k.runners.findIndex(w=>w.id===h);if(S<0)throw new Error(`shadow-store: runner not found: ${h}`);let I=oe(k.runners[S]),_=b(I);if(!Ge(_)||_.id!==h)throw new Error("shadow-store: updater must return record with same id");return Ae(_,"record"),k.runners[S]=oe(_),i(k),oe(k.runners[S])}function f(h){let b=s(),k=b.runners.findIndex(I=>I.id===h);if(k<0)throw new Error(`shadow-store: runner not found: ${h}`);let S=oe(b.runners[k]);return S.status!=="stopped"&&(S.status="stopped",b.runners[k]=S,i(b)),oe(b.runners[k])}let p={create(h){return a(()=>l(h))},get(h){return u(h)},list(){return d()},update(h,b){return a(()=>c(h,b))},stop(h){return a(()=>f(h))}};return Lt.set(t,p),p}var Ft,Us,Lt,cn=V(()=>{Ft=1,Us=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];Lt=new Map});import{createHash as Ct}from"node:crypto";function jt(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Ht(e){return Array.isArray(e)?e.map(Ht):e&&typeof e=="object"?Object.fromEntries(Object.keys(e).sort().map(t=>[t,Ht(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 Ct("sha256").update(JSON.stringify(Ht(e))).digest("hex")}function Vs(e,t,r,n,o){return Ct("sha256").update(`${e}|${t}|${r}|${n}|${o}`).digest("hex")}function Js(e,t,r,n){return Ct("sha256").update(`shadow|${e}|${t}|${r}|${n??""}`).digest("hex")}function Ks(e){return e==="entryLong"||e==="exitShort"?"buy":e==="entryShort"||e==="exitLong"?"sell":e}function ln(e){return e==="entryLong"||e==="entryShort"}function qt({storePath:e,clock:t=Date.now}={}){if(typeof e!="string"||!e)throw new Error("shadow-runner: storePath required");let r=an({path:e});function n({strategy:l,evidenceId:u=null}={}){let d=G(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 jt(f);let p=t(),h=Js(p,d.strategyHash,d.compilerHash,c),b=r.get(h);if(b)return jt(b);let k={id:h,strategy:jt(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 a(){return r.list()}function s(l){return r.stop(l)}function i(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=G(c.strategy).evaluateAll(u),h=new Map;for(let y=0;y<u.length;y++)h.set(u[y].t,y);let b=c.cursor,k=[];for(let y=0;y<u.length;y++){let $=u[y].t;(b==null||$>b)&&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])),w=(y,$)=>`${y}|${$}`,P=new Map(c.markouts.map(y=>[w(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 X({action:y,signalBarT:$,signalIndex:T}){let L=Ks(y),j=Vs(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:ln(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)),ln(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=w(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&&(b==null||u[T].t>b)&&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 B=X({action:R,signalBarT:$.t,signalIndex:y}),ee=y+1;ee<u.length?U(B,u[ee],ee):z(B)},O=R=>{if(!x||x.side==="long"&&R!=="exitLong"||x.side==="short"&&R!=="exitShort")return;let J=X({action:R,signalBarT:$.t,signalIndex:y}),B=y+1;B<u.length?U(J,u[B],B):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:i,list:a,get:o,stop:s}}var fn=V(()=>{me();cn()});var mn={};$n(mn,{runStrategyOperation:()=>ti});import Ys from"node:os";import Gs from"node:path";function je(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Ws(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Bt(e){if(Array.isArray(e)){for(let t of e)Bt(t);return}if(je(e))for(let[t,r]of Object.entries(e)){if(Xs.some(n=>Ws(t).includes(n)))throw new Error(`strategy service: secret-like field "${t}" is forbidden`);Bt(r)}}function Zs(e){if(!je(e))throw new TypeError("strategy input must be a plain object");return Bt(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 Ut(e,t,r,n){if(Array.isArray(t.bars))return t.bars;let o=Et(e.venue),a=r.fetchBars??o.fetchBars;if(typeof a!="function")throw new Error(`strategy venue ${o.id} does not support history`);r.signal?.throwIfAborted?.();let s=await a({coin:e.market.coin,interval:e.market.interval,count:t.count??1500,endTime:t.endTime??n},{signal:r.signal});r.signal?.throwIfAborted?.();let i=Array.isArray(s)?s:s?.bars;if(!Array.isArray(i))throw new Error("strategy history provider returned no bars");return i}function Dt(e,t){let r=e.backtestOptions??{};if(!je(r))throw new TypeError("backtestOptions must be a plain object");return{...r,nowMs:t}}function dn(e,t,r,n,o={}){let a=e.evidenceOptions??{};if(!je(a))throw new TypeError("evidenceOptions must be a plain object");return{...a,...o,strategy:t,bars:r,backtestOptions:Dt(e,n)}}function pn(){return Gs.join(Ys.homedir(),".oracle","strategy-shadow.json")}function ei(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 ti(e,t={},r={}){r.signal?.throwIfAborted?.();let n=Zs(t),o=Qs(n,r);if(e==="draft")return{strategy:Gr(n.prompt,{nowMs:o})};if(e==="validate"){let a=G(n.strategy);if(a.strategy.risk.expiresAt<=o)throw new Error("strategy is expired");return{valid:!0,strategy:a.strategy,strategyHash:a.strategyHash,compilerHash:a.compilerHash,compilerVersion:a.compilerVersion,requiredSeries:a.requiredSeries}}if(e==="backtest"||e==="evidence"){let a=G(n.strategy),s=await Ut(a.strategy,n,r,o);Le(a,s);let i=mt(dn(n,a.strategy,s,o));return e==="evidence"?i:{backtest:ae(a.strategy,s,Dt(n,o)),evidence:i}}if(e==="optimize"){let a=G(n.strategy),s=await Ut(a.strategy,n,r,o);Le(a,s);let i=n.trainFraction,l=n.evidenceOptions?.trainFraction;if(i!=null&&l!=null&&i!==l)throw new TypeError("conflicting trainFraction controls are forbidden");let u=i??l??.7;if(typeof u!="number"||u<=0||u>=1)throw new TypeError("trainFraction must be in (0,1)");let d=s.slice(0,Math.floor(s.length*u)),c=n.options??{};if(!je(c))throw new TypeError("options must be a plain object");let f=tn(a.strategy,d,{...c,...n.maxTrials==null?{}:{maxTrials:n.maxTrials},backtestOptions:Dt(n,o)}),p=f.bestStrategy;return{strategy:p,optimization:f,evidence:mt(dn(n,p,s,o,{trainFraction:u}))}}if(e==="shadow"){let a=qt({storePath:r.storePath??pn(),clock:()=>o}),s=n.action;if(s==="start")return await a.start({strategy:n.strategy,evidenceId:n.evidenceId??n.evidence?.id??null});if(s==="list")return await a.list();if(s==="get")return await a.get(n.id);if(s==="stop")return await a.stop(n.id);if(s==="step"){let i=await a.get(n.id);if(!i)throw new Error(`shadow runner not found: ${n.id}`);let l=await Ut(i.strategy,n,r,o);return Le(G(i.strategy),l),await a.step(n.id,l,n.stepOptions??{})}throw new Error(`unknown shadow action: ${s}`)}if(e==="prepare"){let a=G(n.strategy),s=Et(a.strategy.venue);if(typeof n.shadowId!="string"||!n.shadowId)throw new Error("strategy prepare requires a matching shadow runner id");let l=await qt({storePath:r.storePath??pn(),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!==a.strategyHash||l.compilerHash!==a.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??ei(a.strategy,o);return s.prepareIntent({strategy:a.strategy,evidence:n.evidence,shadow:{id:l.id,stateHash:un(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}`)}var Xs,hn=V(()=>{Be();me();ht();Xr();rn();fn();kt();Xs=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"]});import yn from"node:fs";function ri(e){let t={},r=[];for(let n=0;n<e.length;n++){let o=e[n];if(!o.startsWith("--")){r.push(o);continue}let a=o.slice(2),s=e[n+1];s!=null&&!s.startsWith("--")?(t[a]=s,n++):t[a]=!0}return{flags:t,positional:r}}function ye(e,t){if(!e)throw new Error(`${t} path required`);let r=e==="-"?yn.readFileSync(0,"utf8"):yn.readFileSync(e,"utf8");try{return JSON.parse(r)}catch{throw new Error(`${t} must contain valid JSON`)}}function wn(e,t){if(e==null)return;let r=Number(e);if(!Number.isFinite(r))throw new Error(`${t} must be a finite number`);return r}var ni=`oracle strategy <draft|validate|backtest|optimize|evidence|shadow|prepare> [args]
4
4
 
5
5
  oracle strategy draft "Long BTC when the 20 EMA crosses above the 50 EMA"
6
6
  oracle strategy validate strategy.json
@@ -14,5 +14,5 @@ var An=Object.defineProperty;var V=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(
14
14
  oracle strategy prepare strategy.json --evidence evidence.json --shadow-id <id> [--caps caps.json]
15
15
 
16
16
  Strategy simulation and shadowing are local and deterministic. Prepare returns an integrity-bound artifact, HMAC-authenticated when local attestation is configured. Sign and broadcast through an approved execution path.
17
- `,pa={name:"strategy",summary:"deterministic Hyperliquid strategy lab, evidence, shadow, prepare-only handoff",group:"read",usage:"oracle strategy <draft|validate|backtest|optimize|evidence|shadow|prepare> [args]",async run(e){let{flags:t,positional:r}=Ys(e.argv);if(t.help||r.length===0)return process.stdout.write(Gs),0;let[n,...o]=r,{runStrategyOperation:a}=await Promise.resolve().then(()=>(hn(),mn)),s={nowMs:Date.now(),count:wn(t.count,"count")};if(n==="draft")s.prompt=o.join(" ").trim();else if(["validate","backtest","optimize","evidence"].includes(n))s.strategy=ye(o[0],"strategy"),t.bars&&(s.bars=ye(t.bars,"bars")),s.maxTrials=wn(t["max-trials"],"max-trials");else if(n==="shadow"){let l=o[0];if(!l)throw new Error("shadow action required");s.action=l,l==="start"&&(s.strategy=ye(o[1],"strategy")),l==="step"&&(s.id=o[1],t.bars&&(s.bars=ye(t.bars,"bars"))),l==="stop"&&(s.id=o[1])}else if(n==="prepare")s.strategy=ye(o[0],"strategy"),s.evidence=ye(t.evidence,"evidence"),s.shadowId=t["shadow-id"],t.caps&&(s.caps=ye(t.caps,"caps"));else throw new Error(`unknown strategy operation: ${n}`);let i=await a(n,s);return process.stdout.write(`${JSON.stringify(i,null,2)}
18
- `),0}};export{pa as default};
17
+ `,ka={name:"strategy",summary:"deterministic Hyperliquid strategy lab, evidence, shadow, prepare-only handoff",group:"read",usage:"oracle strategy <draft|validate|backtest|optimize|evidence|shadow|prepare> [args]",async run(e){let{flags:t,positional:r}=ri(e.argv);if(t.help||r.length===0)return process.stdout.write(ni),0;let[n,...o]=r,{runStrategyOperation:a}=await Promise.resolve().then(()=>(hn(),mn)),s={nowMs:Date.now(),count:wn(t.count,"count")};if(n==="draft")s.prompt=o.join(" ").trim();else if(["validate","backtest","optimize","evidence"].includes(n))s.strategy=ye(o[0],"strategy"),t.bars&&(s.bars=ye(t.bars,"bars")),s.maxTrials=wn(t["max-trials"],"max-trials");else if(n==="shadow"){let l=o[0];if(!l)throw new Error("shadow action required");s.action=l,l==="start"&&(s.strategy=ye(o[1],"strategy")),l==="step"&&(s.id=o[1],t.bars&&(s.bars=ye(t.bars,"bars"))),l==="stop"&&(s.id=o[1])}else if(n==="prepare")s.strategy=ye(o[0],"strategy"),s.evidence=ye(t.evidence,"evidence"),s.shadowId=t["shadow-id"],t.caps&&(s.caps=ye(t.caps,"caps"));else throw new Error(`unknown strategy operation: ${n}`);let i=await a(n,s);return process.stdout.write(`${JSON.stringify(i,null,2)}
18
+ `),0}};export{ka as default};