@oracle-agent/oracle 0.35.43 → 0.35.44
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.
- package/dist/agent-sessions.mjs +19 -19
- package/dist/assets/skills/oracle-desk-product/SKILL.md +1 -1
- package/dist/bin/desk-server.mjs +28 -28
- package/dist/bin/oracle-data-mcp.mjs +19 -19
- package/dist/bin/oracle-gateway.mjs +42 -42
- package/dist/bin/oracle-investigate.mjs +5 -5
- package/dist/bin/oracle-launch-radar-shadow.mjs +6 -6
- package/dist/bin/oracle-mev-arb-shadow.mjs +6 -6
- package/dist/bin/oracle-mev-shadow.mjs +6 -6
- package/dist/bin/oracle-public-server.mjs +5 -5
- package/dist/bin/oracle-route.mjs +18 -18
- package/dist/bin/oracle-scan.mjs +11 -11
- package/dist/bin/oracle.mjs +12 -12
- package/dist/cli/commands/agent-session.mjs +21 -21
- package/dist/cli/commands/airdrop.mjs +10 -10
- package/dist/cli/commands/chat.mjs +218 -217
- package/dist/cli/commands/data.mjs +244 -8
- package/dist/cli/commands/doctor.mjs +5 -5
- package/dist/cli/commands/eval.mjs +157 -153
- package/dist/cli/commands/extension-policy.mjs +1 -1
- package/dist/cli/commands/farm.mjs +17 -17
- package/dist/cli/commands/fees.mjs +3 -3
- package/dist/cli/commands/follow.mjs +17 -17
- package/dist/cli/commands/mcp.mjs +6 -6
- package/dist/cli/commands/mint.mjs +10 -10
- package/dist/cli/commands/model.mjs +222 -221
- package/dist/cli/commands/quickstart.mjs +7 -7
- package/dist/cli/commands/receipt.mjs +8 -8
- package/dist/cli/commands/resolve.mjs +10 -10
- package/dist/cli/commands/sign.mjs +11 -11
- package/dist/cli/commands/signer.mjs +20 -20
- package/dist/cli/commands/snipe.mjs +11 -11
- package/dist/cli/commands/strategy.mjs +5 -5
- package/dist/cli/commands/swap.mjs +11 -11
- package/dist/cli/commands/venues.mjs +2 -2
- package/dist/data/desk-data.mjs +26 -26
- package/dist/data/names.mjs +3 -3
- package/dist/data/providers/farming.mjs +2 -2
- package/dist/data/providers/lp-destination-discovery.mjs +4 -4
- package/dist/index.mjs +44 -44
- package/dist/investigator/index.mjs +2 -2
- package/dist/launch-radar/index.mjs +5 -5
- package/dist/local-signer/anvil-attestation-worker.mjs +1 -1
- package/dist/local-signer/index.mjs +3 -3
- package/dist/local-signer/runtime.mjs +16 -16
- package/dist/nft/universal-mint-router.mjs +4 -4
- package/dist/notifications/index.mjs +7 -7
- package/dist/router/index.mjs +3 -3
- package/dist/router/prepare-bridge.mjs +2 -2
- package/dist/router/prepare-route.mjs +3 -3
- package/dist/scanner/index.mjs +4 -4
- package/dist/strategy/index.mjs +3 -3
- package/dist/tui/standalone-client.mjs +90 -88
- package/package.json +1 -1
- package/public/eval-report.json +347 -13
- package/public/oracle-splash/docs/browser-and-web/index.html +2 -2
- package/public/oracle-splash/docs/connectors/index.html +2 -2
- package/public/oracle-splash/docs/getting-started/index.html +2 -2
- package/public/oracle-splash/docs/index.html +3 -3
- package/public/oracle-splash/docs/reference/index.html +2 -2
- package/public/oracle-splash/docs/security/index.html +2 -2
- package/public/oracle-splash/docs/using-oracle/index.html +2 -2
- package/server.json +2 -2
package/dist/strategy/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createHash as Wo}from"node:crypto";import{createHash as kn}from"node:crypto";import{types as ue}from"node:util";import be from"node:net";import bn from"node:dns";var En=new Set(["localhost","metadata.google.internal","metadata.goog"]);function We(e){let t=String(e).toLowerCase().split("%")[0];if((t.match(/::/g)||[]).length>1)return null;let r=u=>{if(!u)return[];let c=u.split(":"),d=c.at(-1);if(d?.includes(".")){let m=d.split(".").map(Number);if(m.length!==4||m.some(p=>!Number.isInteger(p)||p<0||p>255))return null;c.splice(c.length-1,1,(m[0]<<8|m[1]).toString(16),(m[2]<<8|m[3]).toString(16))}return c.some(m=>!/^[0-9a-f]{1,4}$/.test(m))?null:c.map(m=>Number.parseInt(m,16))},[n,o]=t.split("::"),s=r(n),i=r(o);if(!s||!i)return null;let a=t.includes("::"),l=8-s.length-i.length;if(!a&&l!==0||a&&l<1)return null;let f=[...s,...Array(Math.max(0,l)).fill(0),...i];return f.length!==8?null:Uint8Array.from(f.flatMap(u=>[u>>8,u&255]))}function wt(e,t,r){let n=Math.floor(r/8),o=r%8;for(let i=0;i<n;i+=1)if(e[i]!==t[i])return!1;if(!o)return!0;let s=255<<8-o;return(e[n]&s)===(t[n]&s)}function gt(e){if(be.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(be.isIPv6(e)){let t=We(e);if(!t)return!1;let r=We("::ffff:0:0");return wt(t,r,96)?gt([...t.slice(12)].join(".")):wt(t,We("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([o,s])=>wt(t,We(o),s)):!1}return!1}function xn(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(En.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=be.isIP(r);return n!==0&&!gt(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function bt(e,{lookupFn:t=bn.promises.lookup}={}){let r=xn(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:be.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=>!gt(o.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}async function Et({requireUndici:e=!1,importUndici:t=()=>import("undici")}={}){let r,n;try{let c=await t();r=c.Agent,n=c.fetch}catch(c){if(e)throw new Error(`egress-guard: untrustedUrl pinning requires the undici package, which failed to load: ${c?.message||c}`);return null}if(typeof r!="function"||typeof n!="function"){if(e)throw new Error("egress-guard: untrustedUrl pinning requires undici's Agent and fetch exports, which were not found on the imported module");return null}let o=c=>String(c).toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,""),s=new Map,i=c=>(Array.isArray(c)?c:[c]).map(d=>typeof d=="string"?{address:d}:d).filter(d=>d&&d.address).map(d=>({address:d.address,family:d.family||(be.isIPv6(d.address)?6:4)})),a=(c,d,m)=>{s.set(o(c),i(typeof d=="string"?[{address:d,family:m}]:d))},l=c=>{let d=o(c);if(be.isIP(d))return[{address:d,family:be.isIPv6(d)?6:4}];let m=s.get(d);if(!m||!m.length)throw new Error(`refused: unpinned host ${c} during pinned fetch`);return m},f=new r({connect:{lookup(c,d,m){let p;try{p=l(c)}catch(w){return m(w)}return d?.all?m(null,p):m(null,p[0].address,p[0].family)}}}),u=Sn((c,d={})=>n(c,{...d,dispatcher:f}),a);return{dispatcher:f,fetch:u,pin:a,resolve:l,async close(){try{await f.destroy()}catch{}}}}var xt=Symbol.for("oracle.egressGuard.pinCapableFetch");function Sn(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[xt]=Object.freeze({pin:t}),e}function St(e){return typeof e=="function"&&typeof e[xt]?.pin=="function"}function fr(e,t,r){if(!St(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[xt].pin(t,r)}var Tn=new Set([408,425,429,500,502,503,504]),dr=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),An=2,pr=4e3,On=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"aborted")?.get,Pn=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"reason")?.get,$n=AbortSignal.prototype.throwIfAborted,In=EventTarget.prototype.addEventListener,mr=EventTarget.prototype.removeEventListener,hr=typeof AbortSignal.any=="function"?AbortSignal.any.bind(AbortSignal):null,Fe=e=>e?On.call(e):!1,_n=e=>e?Pn.call(e):void 0,vn=new Set([301,302,303,307,308]),Xe=3,pi=64*1024,le=Object.freeze({depth:32,nodes:1e4,fields:1e4,arrayLength:1e4,bytes:1024*1024});function V(e){return me(`HTTP JSON body refused: ${e}`)}function jn(e){return["isArgumentsObject","isArrayBuffer","isAnyArrayBuffer","isArrayBufferView","isBoxedPrimitive","isDataView","isDate","isExternal","isGeneratorObject","isKeyObject","isCryptoKey","isMap","isMapIterator","isModuleNamespaceObject","isNativeError","isPromise","isRegExp","isSet","isSetIterator","isTypedArray","isWeakMap","isWeakSet"].some(t=>typeof ue[t]=="function"&&ue[t](e))}function Nn(e){let t=[],r=0,n=0,o=0,s=0,i=new WeakSet,a=u=>{if(r+=Buffer.byteLength(u,"utf8"),r>le.bytes)throw V("serialized byte limit exceeded");t.push(u)},l=u=>{if(Buffer.byteLength(u,"utf8")>le.bytes)throw V("serialized byte limit exceeded");return JSON.stringify(u)},f=(u,c)=>{if(n+=1,n>le.nodes)throw V("node limit exceeded");if(c>le.depth)throw V("depth limit exceeded");if(u===null){a("null");return}if(typeof u=="string"){a(l(u));return}if(typeof u=="boolean"){a(u?"true":"false");return}if(typeof u=="number"){if(!Number.isFinite(u))throw V("non-finite number");a(Object.is(u,-0)?"0":String(u));return}if(typeof u!="object")throw V("unsupported non-JSON value");if(ue.isProxy(u))throw V("proxy value");if(jn(u))throw V("unsupported exotic object");if(i.has(u))throw V("cyclic value");i.add(u);try{if(Object.getOwnPropertySymbols(u).length>0)throw V("symbol-keyed fields are unsupported");if(Array.isArray(u)){let p=Object.getPrototypeOf(u),w=0;for(;p!==null;){if(ue.isProxy(p))throw V("proxy array prototype");if(w+=1,w>le.depth)throw V("array prototype depth limit exceeded");p=Object.getPrototypeOf(p)}if(u.length>le.arrayLength)throw V("array length limit exceeded");for(let S=0;S<u.length;S+=1){let v=Object.getOwnPropertyDescriptor(u,String(S));if(!v||!Object.hasOwn(v,"value")||v.enumerable!==!0)throw V("array entries must be dense enumerable own data")}let g=0;for(let S in u){if(s+=1,s>le.fields)throw V("enumeration limit exceeded");if(Object.hasOwn(u,S)&&(g+=1,g>u.length))throw V("named array fields are unsupported")}if(g!==u.length)throw V("array entries must be dense enumerable own data");a("[");for(let S=0;S<u.length;S+=1)S&&a(","),f(Object.getOwnPropertyDescriptor(u,String(S)).value,c+1);a("]");return}let d=Object.getPrototypeOf(u);if(d!==Object.prototype&&d!==null)throw V("non-plain object");let m=[];for(let p in u){if(s+=1,s>le.fields)throw V("enumeration limit exceeded");if(!Object.hasOwn(u,p))continue;if(o+=1,o>le.fields)throw V("field limit exceeded");let w=Object.getOwnPropertyDescriptor(u,p);if(!w||!Object.hasOwn(w,"value")||w.enumerable!==!0)throw V("object fields must be enumerable own data");m.push([p,w.value])}a("{");for(let p=0;p<m.length;p+=1)p&&a(","),a(l(m[p][0])),a(":"),f(m[p][1],c+1);a("}")}finally{i.delete(u)}};return f(e,0),t.join("")}function Rn(e){let t=Object.create(null);if(e==null)return t;if(typeof e!="object"&&typeof e!="function")throw new TypeError("HTTP headers must be an object");if(ue.isProxy(e))throw new TypeError("HTTP headers must not be a proxy");if(Object.getOwnPropertySymbols(e).length>0)throw new TypeError("HTTP headers must not contain symbol fields");let r=new Set;for(let n of Object.keys(e)){if(!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/u.test(n))throw new TypeError("HTTP header names must be valid tokens");let o=n.toLowerCase();if(r.has(o))throw new TypeError("HTTP headers contain a duplicate canonical name");r.add(o);let s=Object.getOwnPropertyDescriptor(e,n);if(!s||!Object.hasOwn(s,"value"))throw new TypeError("HTTP headers must contain own data properties");let i=s.value;if(i==null||["object","function","symbol"].includes(typeof i))throw new TypeError("HTTP header values must be scalar");t[n]=String(i)}return t}function Mn(){return Object.assign(Object.create(null),{Accept:"application/json"})}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}var kt=new Map,yr=new WeakMap,wr=1;function Ze(e){if((typeof e!="object"||e===null)&&typeof e!="function")return`${typeof e}:${String(e)}`;let t=yr.get(e);return t||(t=wr,wr+=1,yr.set(e,t)),`reference:${t}`}var Fn=new Set(["eth_blockNumber","eth_call","eth_chainId","eth_estimateGas","getHealth","minimumLedgerSlot","net_version","simulateTransaction","web3_clientVersion"]),Cn=new Set(["allMids","l2Book","outcomeMeta","spotClearinghouseState","userFills","meta","metaAndAssetCtxs","perpDexs","candleSnapshot","fundingHistory","openOrders","frontendOpenOrders","clearinghouseState","spotMeta","validatorSummaries","delegatorSummary","delegations","delegatorRewards","delegatorHistory","maxBuilderFee"]);function gr(e){if(!e||typeof e!="object"||Array.isArray(e)||!Object.hasOwn(e,"jsonrpc")||!Object.hasOwn(e,"method")||e.jsonrpc!=="2.0")return!1;let t=typeof e.method=="string"?e.method:"";return t?Fn.has(t)||/^get[A-Z0-9_]/u.test(t)||/^is[A-Z0-9_]/u.test(t)||/^eth_get[A-Z0-9_]/u.test(t):!1}function br(e,t){if(e==="GET"&&t==null)return!0;if(e!=="POST"||t==null)return!1;let r=t;if(typeof t=="string")try{r=JSON.parse(t)}catch{return!1}if(Array.isArray(r))return r.length>0&&r.every(gr);if(!r||typeof r!="object")return!1;if(Object.hasOwn(r,"jsonrpc")||Object.hasOwn(r,"method"))return gr(r);let n=Object.hasOwn(r,"type")?r.type:null;return typeof n=="string"&&Cn.has(n)&&(!Object.hasOwn(r,"action")||r.action==null)&&(!Object.hasOwn(r,"signature")||r.signature==null)&&(!Object.hasOwn(r,"nonce")||r.nonce==null)}function Dn(e,t,r,n={},o=null){let s=kn("sha256"),i=(l,f)=>{let u=String(f);s.update(String(Buffer.byteLength(l,"utf8"))).update(":").update(l),s.update("=").update(String(Buffer.byteLength(u,"utf8"))).update(":").update(u).update(`
|
|
2
|
-
`)};i("method",e),i("url",t),Object.keys(r||{}).map((l,f)=>({name:l.toLowerCase(),order:f,value:String(r[l])})).sort((l,f)=>l.name.localeCompare(f.name)||l.order-f.order).forEach((l,f)=>{i(`header-name-${f}`,l.name),i(`header-value-${f}`,l.value)}),i("body",o??"-");for(let l of["untrustedUrl","maxResponseBytes","sameOriginRedirectsOnly","redirectPolicy","maxRedirects","timeoutMs","retries","fetchImpl","realFetch","lookupFn","importUndici","validateResponse"])i(`context-${l}`,n[l]??"-");return s.digest("hex")}function Un(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,pr):Math.min(250*2**e,pr)+Math.floor(Math.random()*100)}var qn=e=>new Promise(t=>setTimeout(t,e));function me(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function Tt(e,t,r){return me(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function Ee(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 zn(e,t,{url:r,truncate:n=!1,onOversize:o}={}){if(t==null)return await e.text();let s=Number(e.headers?.get?.("content-length"));if(Number.isFinite(s)&&s>t&&(Ee(e),!n))throw Tt(r,`content-length ${s}`,t);let i=e.body?.getReader?.();if(!i){let c=await e.text(),d=Buffer.byteLength(c,"utf8");if(d>t){if(!n)throw Tt(r,`body ${d} bytes`,t);return Buffer.from(c,"utf8").subarray(0,t).toString("utf8")}return c}let a=[],l=0,f=!1;try{for(;;){let{value:c,done:d}=await i.read();if(d)break;if(c&&(a.push(Buffer.from(c)),l+=Bn(c),l>t)){f=!0;break}}}finally{if(f)try{await i.cancel()}catch{}try{i.releaseLock?.()}catch{}}if(f&&(typeof o=="function"&&o(),!n))throw Tt(r,`streamed ${l} bytes`,t);let u=Buffer.concat(a);return(f?u.subarray(0,t):u).toString("utf8")}function Vn(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function Jn(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:s,lookupFn:i,realFetch:a,untrustedUrl:l=!1,maxResponseBytes:f=null,sameOriginRedirectsOnly:u=!1,importUndici:c,validateResponse:d,signal:m,redirectPolicy:p="follow",maxRedirects:w=Xe}){let g=null,S=t,v=i?{lookupFn:i}:{};if(l&&!a&&!St(S))throw me(`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 O=new AbortController,x=setTimeout(()=>O.abort(),s),R=m?hr?hr([m,O.signal]):m:O.signal,P=async(h,{status:M=null}={})=>{let D=await bt(h,v);if(!D.ok)throw me(M==null?`HTTP refused ${h}: ${D.error}`:`HTTP redirect to ${h} ${D.error}`,M==null?{}:{status:M});let Y=new URL(h).hostname;if(a){if(g&&(await g.close(),g=null),!g)try{g=await Et({requireUndici:!0,...c?{importUndici:c}:{}})}catch(k){throw me(M==null?`HTTP refused ${h}: ${k?.message||k}`:`HTTP redirect to ${h} refused: ${k?.message||k}`,M==null?{}:{status:M})}g.pin(Y,D.addresses),S=g.fetch}else fr(S,Y,D.addresses);return D};try{let h=String(e),M=Object.assign(Object.create(null),n||{});l&&await P(h);for(let D=0;D<=w;D+=1){let Y=Object.assign(Object.create(null),{method:r,headers:M,body:o,signal:R,redirect:"manual",dispatcher:void 0}),k=await S(h,Y);if((p==="error"||w===0)&&k.status>=300&&k.status<400)throw Ee(k),me(`HTTP ${k.status} ${r} redirect refused`,{status:k.status,redirectRefused:!0});if(vn.has(k.status)){let _=u===!0&&r==="POST"&&[307,308].includes(k.status)&&br(r,o);if(r!=="GET"&&r!=="HEAD"&&!_){Ee(k);let A=new Error(`HTTP ${k.status} ${r} ${h} redirected non-idempotent request`);throw A.status=k.status,A}if(D===w)throw Ee(k),me(`HTTP ${k.status} ${r} redirect budget exhausted`,{status:k.status,redirectRefused:!0});let C=k.headers?.get?.("location"),L;try{L=Ln(C,h)}catch(A){throw Ee(k),A}let j=!Hn(L,h);if(Ee(k),j&&r==="POST"){let A=new Error(`HTTP ${k.status} ${r} cross-origin redirect refused`);throw A.status=k.status,A}if(j&&u){let A=new Error(`HTTP ${k.status} ${r} cross-origin redirect refused`);throw A.status=k.status,A.retryable=!1,A}if(j&&(M=Mn(M)),l)await P(L,{status:k.status});else if(j){let A=await bt(L,v);if(!A.ok){let N=new Error(`HTTP redirect from ${h} ${A.error}`);throw N.status=k.status,N.retryable=!1,N}a&&A.addresses?.length&&(g||(g=await Et(c?{importUndici:c}:{})),g&&(g.pin(new URL(L).hostname,A.addresses),S=g.fetch))}h=L;continue}if(typeof d=="function")try{await d(k,{url:h})}catch(_){throw Ee(k),me(_?.message||String(_))}let y=await zn(k,f,{url:h,onOversize:()=>O.abort()}),$=Vn(y);if(!k.ok){let _=new Error(`HTTP ${k.status} ${r} ${h}`);throw _.status=k.status,_.retryAfter=k.headers?.get?.("retry-after")??null,_.body=$??y.slice(0,300),_}return $??y}throw new Error(`HTTP redirect loop for ${e}`)}catch(h){if(O.signal.aborted&&!Fe(m)){let M=h&&(typeof h=="object"||typeof h=="function")&&!ue.isProxy(h)?h:null,D=M?Object.getOwnPropertyDescriptor(M,"oversize"):null;if(!(D&&Object.hasOwn(D,"value")&&D.value===!0))try{if(!M)throw new TypeError("unsafe rejection");Object.defineProperties(M,{oracleTimeout:{value:!0,enumerable:!1},retryable:{value:!1,enumerable:!1}})}catch{let k=new Error("HTTP request timed out");throw Object.defineProperties(k,{oracleTimeout:{value:!0,enumerable:!1},retryable:{value:!1,enumerable:!1}}),k}}throw h}finally{clearTimeout(x),g&&await g.close()}}async function Er(e,t={}){if(t!=null&&typeof t!="object"&&typeof t!="function")throw new TypeError("HTTP options must be an object");if(t!=null&&ue.isProxy(t))throw new TypeError("HTTP options must not be a proxy");let r=new Set(["body","dedupe","fetchImpl","headers","importUndici","lookupFn","maxRedirects","maxResponseBytes","method","redirectPolicy","retries","sameOriginRedirectsOnly","signal","timeoutMs","untrustedUrl","validateResponse"]);if(t!=null){if(Object.getOwnPropertySymbols(t).length>0)throw new TypeError("HTTP options contain unknown fields");for(let N of Object.getOwnPropertyNames(t)){let I=Object.getOwnPropertyDescriptor(t,N);if(!(N==="toJSON"&&I&&Object.hasOwn(I,"value")&&I.value===void 0)){if(!r.has(N))throw new TypeError("HTTP options contain unknown fields");if(!I||!I.enumerable||!Object.hasOwn(I,"value"))throw new TypeError("HTTP options must contain enumerable own data properties")}}}let n=N=>{if(t==null||!Object.hasOwn(t,N))return;let I=Object.getOwnPropertyDescriptor(t,N);if(!I||!Object.hasOwn(I,"value"))throw new TypeError("HTTP options must contain own data properties");return I.value};if(typeof e!="string"||e.length===0||e.length>8192)throw new TypeError("HTTP URL must be a bounded string");let o=n("method");if(o!==void 0&&(typeof o!="string"||!/^[A-Za-z]+$/u.test(o)))throw new TypeError("HTTP method must be a string token");let s=n("timeoutMs");if(s!==void 0&&(!Number.isInteger(s)||s<1||s>12e4))throw new TypeError("HTTP timeoutMs must be a bounded integer");let i=n("retries");if(i!==void 0&&(!Number.isInteger(i)||i<0||i>10))throw new TypeError("HTTP retries must be a bounded integer");let a=n("redirectPolicy");if(a!==void 0&&a!=="follow"&&a!=="error")throw new TypeError('HTTP redirectPolicy must be "follow" or "error"');let l=n("maxRedirects");if(l!==void 0&&(!Number.isInteger(l)||l<0||l>Xe))throw new TypeError(`HTTP maxRedirects must be an integer from 0 through ${Xe}`);if(a==="error"&&l!==void 0&&l!==0)throw new TypeError('HTTP redirectPolicy "error" requires maxRedirects 0 when supplied');let f=a??"follow",u=f==="error"?0:l??Xe;for(let N of["dedupe","untrustedUrl","sameOriginRedirectsOnly"]){let I=n(N);if(I!==void 0&&typeof I!="boolean")throw new TypeError(`HTTP ${N} must be boolean`)}let c=n("maxResponseBytes");if(c!==void 0&&(!Number.isInteger(c)||c<1||c>64*1024*1024))throw new TypeError("HTTP maxResponseBytes must be a bounded integer");let d=n("signal");if(d!==void 0){if(ue.isProxy(d)||!(d instanceof AbortSignal))throw new TypeError("HTTP signal must be a native AbortSignal");try{Fe(d)}catch{throw new TypeError("HTTP signal must be a native AbortSignal")}}for(let N of["importUndici","lookupFn","validateResponse"]){let I=n(N);if(I!==void 0&&typeof I!="function")throw new TypeError(`HTTP ${N} must be a function`)}let m=n("fetchImpl"),p=m||globalThis.fetch;if(typeof p!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let w=s??12e3,g=(o||"GET").toUpperCase(),S=n("headers"),v=Rn(S),O=Object.assign(Object.create(null),v);Object.keys(O).some(N=>N.toLowerCase()==="accept")||(O.Accept="application/json");let x=n("body");x!=null&&typeof x!="string"&&(Object.keys(O).find(I=>I.toLowerCase()==="content-type")||(O["Content-Type"]="application/json"),x=Nn(x));let R=i??An,P=n("lookupFn"),h=!m,M=n("untrustedUrl")===!0,D=n("sameOriginRedirectsOnly")===!0,Y=n("importUndici"),k=n("validateResponse"),y=d,$=c??null,_=async()=>{let N;for(let I=0;I<=R;I++){y&&$n.call(y);try{return await Jn(e,{fetchImpl:p,method:g,headers:O,body:x,timeoutMs:w,lookupFn:P,realFetch:h,untrustedUrl:M,maxResponseBytes:$,sameOriginRedirectsOnly:D,importUndici:Y,validateResponse:k,signal:y,redirectPolicy:f,maxRedirects:u})}catch(G){N=G;let ee=Oe=>{if(!G||typeof G!="object"&&typeof G!="function"||ue.isProxy(G))return;let ge=Object.getOwnPropertyDescriptor(G,Oe);return ge&&Object.hasOwn(ge,"value")?ge.value:void 0},pe=ee("status"),Ae=ee("oracleTimeout")===!0||ee("name")==="AbortError"||ee("name")==="TimeoutError"||Fe(y),Ke=new Set([408,425,429]),Ye=ee("retryable")===!1?!1:pe!=null?Ke.has(pe)||Tn.has(pe)&&dr.has(g):!Ae&&dr.has(g);if(I===R||!Ye)throw G;let dt=Un(I,ee("retryAfter"));y?await new Promise((Oe,ge)=>{let Me,ae=()=>{clearTimeout(Me),mr.call(y,"abort",ae),ge(_n(y)||new DOMException("Aborted","AbortError"))};if(Fe(y)){ae();return}Me=setTimeout(()=>{mr.call(y,"abort",ae),Oe()},dt),In.call(y,"abort",ae,{once:!0}),Fe(y)&&ae()}):await qn(dt)}}throw N};if(!(n("dedupe")!==!1&&!y&&br(g,x)))return _();let L=Dn(g,e,O,{untrustedUrl:M,maxResponseBytes:$,sameOriginRedirectsOnly:D,redirectPolicy:f,maxRedirects:u,timeoutMs:w,retries:R,fetchImpl:Ze(p),realFetch:h,lookupFn:Ze(P),importUndici:Ze(Y),validateResponse:Ze(k)},x),j=kt.get(L);if(j)return j;let A=_().finally(()=>kt.delete(L));return kt.set(L,A),A}import{types as xr}from"node:util";function Gn(e){if(!e||typeof e!="object"||xr.isProxy(e)||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Qe(e,t="provider response",r=0){if(r>64)throw new Error(`${t} exceeds the JSON nesting bound`);if(e===null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))return e;if(Array.isArray(e)){if(xr.isProxy(e)||e.length>1e5)throw new Error(`${t} contains an invalid array`);let o=new Array(e.length);for(let s=0;s<e.length;s+=1){let i=Object.getOwnPropertyDescriptor(e,String(s));if(!i||!Object.hasOwn(i,"value"))throw new Error(`${t} arrays must contain dense own data`);o[s]=Qe(i.value,t,r+1)}return o}if(!Gn(e))throw new Error(`${t} contains a non-JSON value`);let n=Object.create(null);for(let o of Object.keys(e)){let s=Object.getOwnPropertyDescriptor(e,o);if(!s||!Object.hasOwn(s,"value"))throw new Error(`${t} objects must contain own data`);n[o]=Qe(s.value,t,r+1)}return n}var Kn="https://api.hyperliquid.xyz/info",Yn="https://api.hyperliquid-testnet.xyz/info";function Wn({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"?Yn:Kn}async function Ce(e,t={}){if(!e||!e.type)throw new Error("hlInfo requires body.type");let r=Wn(t);return Qe(await Er(r,{method:"POST",body:e,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs,maxResponseBytes:t.maxResponseBytes,sameOriginRedirectsOnly:t.sameOriginRedirectsOnly}),"hyperliquid info response")}async function Sr(e,t={}){if(!e)throw new Error("hlL2Book requires coin");return Ce({type:"l2Book",coin:String(e)},t)}async function kr(e={}){return Ce({type:"meta"},e)}async function Tr(e={}){let t={type:"metaAndAssetCtxs"};return e.dex&&(t.dex=e.dex),Ce(t,e)}async function Ar({coin:e,interval:t="1h",startTime:r,endTime:n},o={}){if(!e)throw new Error("hlCandleSnapshot requires coin");let s={type:"candleSnapshot",req:{coin:String(e),interval:t,startTime:r??Date.now()-24*3600*1e3,endTime:n??Date.now()}};return Ce(s,o)}async function Or({coin:e,startTime:t,endTime:r},n={}){if(!e)throw new Error("hlFundingHistory requires coin");return Ce({type:"fundingHistory",coin:String(e),startTime:t??Date.now()-24*3600*1e3,endTime:r??Date.now()},n)}function Ue(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 he(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("period must be a positive integer")}function Zn(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");for(let t=0;t<e.length;t++){let r=e[t];if(r==null||typeof r!="object")throw new TypeError(`bars[${t}] must be an object`);for(let n of["o","h","l","c"]){let o=r[n];if(typeof o!="number"||!Number.isFinite(o))throw new TypeError(`bars[${t}].${n} must be a finite number`)}if(r.h<r.l)throw new TypeError(`bars[${t}] high must be >= low`)}}function At(e,t){Ue(e),he(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){Ue(e),he(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=0;for(let i=0;i<t;i++)n+=e[i];let o=n/t;r[t-1]=o;let s=2/(t+1);for(let i=t;i<e.length;i++)o=s*e[i]+(1-s)*o,r[i]=o;return r}function Ot(e,t){Ue(e),he(t);let r=new Array(e.length).fill(null);if(e.length<=t)return r;let n=0,o=0;for(let a=1;a<=t;a++){let l=e[a]-e[a-1];l>=0?n+=l:o-=l}let s=n/t,i=o/t;r[t]=Pr(s,i);for(let a=t+1;a<e.length;a++){let l=e[a]-e[a-1],f=l>0?l:0,u=l<0?-l:0;s=(s*(t-1)+f)/t,i=(i*(t-1)+u)/t,r[a]=Pr(s,i)}return r}function Pr(e,t){return e===0&&t===0?50:t===0?100:e===0?0:100-100/(1+e/t)}function Pt(e,t={}){Ue(e);let r=t.fastPeriod,n=t.slowPeriod,o=t.signalPeriod;if(he(r),he(n),he(o),r>=n)throw new TypeError("fastPeriod must be < slowPeriod");let s=De(e,r),i=De(e,n),a=new Array(e.length).fill(null);for(let c=0;c<e.length;c++)s[c]!=null&&i[c]!=null&&(a[c]=s[c]-i[c]);let l=new Array(e.length).fill(null),f=new Array(e.length).fill(null),u=[];for(let c=0;c<a.length;c++)a[c]!=null&&u.push(c);if(u.length>=o){let c=0;for(let w=0;w<o;w++)c+=a[u[w]];let d=c/o,m=u[o-1];l[m]=d,f[m]=a[m]-d;let p=2/(o+1);for(let w=o;w<u.length;w++){let g=u[w];d=p*a[g]+(1-p)*d,l[g]=d,f[g]=a[g]-d}}return{line:a,signal:l,histogram:f}}function $t(e,t={}){Ue(e);let r=t.period,n=t.stdDev;if(he(r),typeof n!="number"||!Number.isFinite(n)||n<=0)throw new TypeError("stdDev must be a finite number > 0");let o=new Array(e.length).fill(null),s=new Array(e.length).fill(null),i=new Array(e.length).fill(null);if(e.length<r)return{upper:s,middle:o,lower:i};let a=0,l=0;for(let f=0;f<e.length;f++){let u=e[f];if(a+=u,l+=u*u,f>=r){let c=e[f-r];a-=c,l-=c*c}if(f>=r-1){let c=a/r,d=l/r-c*c;d<0&&d>-1e-12&&(d=0);let m=Math.sqrt(d);o[f]=c,s[f]=c+n*m,i[f]=c-n*m}}return{upper:s,middle:o,lower:i}}function It(e,t){Zn(e),he(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=new Array(e.length);for(let i=0;i<e.length;i++){let a=e[i];if(i===0)n[i]=a.h-a.l;else{let l=e[i-1].c;n[i]=Math.max(a.h-a.l,Math.abs(a.h-l),Math.abs(a.l-l))}}let o=0;for(let i=0;i<t;i++)o+=n[i];let s=o/t;r[t-1]=s;for(let i=t;i<e.length;i++)s=(s*(t-1)+n[i])/t,r[i]=s;return r}import{createHash as Xn}from"node:crypto";var _t=3,Qn="7477966facc4ef928a94e6221c8fd238eef4fcbeec46b96ae1b89178e13c2d5f",eo="68f5b412a9975f04024cf9b9b6209b4bccedd52f176e95f34f786b3f53479c6a",to="967fd45ecddd0d59ac0f662fe92ea813c32620ba751f249b4ace6cb6b809fb5e",$r=Xn("sha256").update(JSON.stringify({version:_t,compilerSourceHash:Qn,indicatorsSourceHash:eo,schemaSourceHash:to})).digest("hex");var $e=_t,ye=$r,ro=Object.freeze({open:"o",high:"h",low:"l",close:"c",volume:"v",fundingRate:"fundingRate",openInterest:"openInterest",premium:"premium",oiDelta:"oiDelta",bookImbalance:"bookImbalance"}),no=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5});function X(e){return typeof e=="number"&&Number.isFinite(e)}function oo(e){let t=new Map(e.map(a=>[a.id,a])),r=a=>{switch(a.type){case"indicator":return a.input?[a.input]:[];case"compare":case"cross":return[a.left,a.right];case"logic":return[...a.inputs];default:return[]}},n=new Map,o=new Map;for(let a of e)n.set(a.id,0),o.set(a.id,[]);for(let a of e)for(let l of r(a))t.has(l)&&(o.get(l).push(a.id),n.set(a.id,n.get(a.id)+1));let s=[];for(let[a,l]of n)l===0&&s.push(a);let i=[];for(;s.length;){let a=s.shift();i.push(a);for(let l of o.get(a))n.set(l,n.get(l)-1),n.get(l)===0&&s.push(l)}if(i.length!==e.length)throw new Error("strategy graph is cyclic");return i}function Pe(e,t){return e!=null&&typeof e=="object"&&"param"in e?t[e.param].value:e}function so(e,t,r){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");if(!Number.isInteger(t)||t<0||t>=e.length)throw new RangeError("index out of range");let n=null;for(let o=0;o<=t;o++){let s=e[o];if(s==null||typeof s!="object"||Array.isArray(s))throw new TypeError(`bars[${o}] must be an object`);let{t:i,o:a,h:l,l:f,c:u,v:c}=s;if(!X(i)&&(typeof i=="number"&&Number.isFinite(i)),!Number.isFinite(i))throw new TypeError(`bars[${o}].t must be finite`);for(let[d,m]of[["o",a],["h",l],["l",f],["c",u],["v",c]])if(!X(m))throw new TypeError(`bars[${o}].${d} must be a finite number`);for(let[d,m]of[["o",a],["h",l],["l",f],["c",u]])if(!(m>0))throw new TypeError(`bars[${o}].${d} price must be positive`);if(c<0)throw new TypeError(`bars[${o}].v volume must be non-negative`);if(l<Math.max(a,u,f))throw new TypeError(`bars[${o}] high must be >= max(open, close, low)`);if(f>Math.min(a,u,l))throw new TypeError(`bars[${o}] low must be <= min(open, close, high)`);if(n!=null){if(!(i>n))throw new TypeError("bars t must be strictly increasing");if(i-n!==no[r])throw new TypeError(`bars t must match ${r} cadence`)}if(n=i,"fundingRate"in s&&s.fundingRate!=null&&!X(s.fundingRate))throw new TypeError(`bars[${o}].fundingRate must be finite when present`);if("openInterest"in s&&s.openInterest!=null){if(!X(s.openInterest))throw new TypeError(`bars[${o}].openInterest must be finite when present`);if(s.openInterest<0)throw new TypeError(`bars[${o}].openInterest must be non-negative`)}for(let d of["premium","oiDelta"])if(d in s&&s[d]!=null&&!X(s[d]))throw new TypeError(`bars[${o}].${d} must be finite when present`);if("bookImbalance"in s&&s.bookImbalance!=null){if(!X(s.bookImbalance))throw new TypeError(`bars[${o}].bookImbalance must be finite when present`);if(s.bookImbalance<-1||s.bookImbalance>1)throw new TypeError(`bars[${o}].bookImbalance must be within [-1, 1]`)}}}function xe(e,t,r,n,o,s){if(s.has(e))return s.get(e);let i=t.get(e),a;switch(i.type){case"input":{let l=ro[i.field];a=new Array(o+1);for(let f=0;f<=o;f++){let u=n[f][l];a[f]=u===void 0?null:u}break}case"constant":{let l=Pe(i.value,r);a=new Array(o+1).fill(l);break}case"indicator":{let l=i.period!=null?Pe(i.period,r):void 0;if(i.indicator==="atr"){let c=[];for(let d=0;d<=o;d++){let m=n[d];c.push({o:m.o,h:m.h,l:m.l,c:m.c})}a=It(c,l);break}let u=xe(i.input,t,r,n,o,s).map((c,d)=>{if(c==null||!X(c))throw new TypeError(`indicator input ${i.input} has non-finite value at ${d}`);return c});if(i.indicator==="sma")a=At(u,l);else if(i.indicator==="ema")a=De(u,l);else if(i.indicator==="rsi")a=Ot(u,l);else if(i.indicator==="macd")a=Pt(u,{fastPeriod:Pe(i.fastPeriod,r),slowPeriod:Pe(i.slowPeriod,r),signalPeriod:Pe(i.signalPeriod,r)})[i.output];else if(i.indicator==="bollinger")a=$t(u,{period:l,stdDev:Pe(i.stdDev,r)})[i.output];else throw new Error(`unsupported indicator ${i.indicator}`);break}case"compare":{let l=xe(i.left,t,r,n,o,s),f=xe(i.right,t,r,n,o,s);a=new Array(o+1);for(let u=0;u<=o;u++){let c=l[u],d=f[u];if(c==null||d==null||!X(c)||!X(d)){a[u]=!1;continue}switch(i.op){case"gt":a[u]=c>d;break;case"gte":a[u]=c>=d;break;case"lt":a[u]=c<d;break;case"lte":a[u]=c<=d;break;case"eq":a[u]=c===d;break;default:a[u]=!1}}break}case"logic":{let l=i.inputs.map(f=>xe(f,t,r,n,o,s));a=new Array(o+1);for(let f=0;f<=o;f++)if(i.op==="not"){let u=l[0][f];a[f]=u===!0?!1:u===!1}else if(i.op==="and"){let u=!0;for(let c of l)if(c[f]!==!0){u=!1;break}a[f]=u}else if(i.op==="or"){let u=!1;for(let c of l)if(c[f]===!0){u=!0;break}a[f]=u}else a[f]=!1;break}case"cross":{let l=xe(i.left,t,r,n,o,s),f=xe(i.right,t,r,n,o,s);a=new Array(o+1),a[0]=!1;for(let u=1;u<=o;u++){let c=l[u-1],d=f[u-1],m=l[u],p=f[u];if(c==null||d==null||m==null||p==null||!X(c)||!X(d)||!X(m)||!X(p)){a[u]=!1;continue}i.direction==="above"?a[u]=c<=d&&m>p:a[u]=c>=d&&m<p}break}default:throw new Error(`unknown node type ${i.type}`)}return s.set(e,a),a}function W(e,t={}){let r=Z(e);t&&Object.keys(t).length&&(r=Ie(r,t));let n=new Map(r.nodes.map(m=>[m.id,m])),o=Object.freeze(oo(r.nodes)),s=r.parameters,i=new Set(r.nodes.filter(m=>m.type==="input").map(m=>m.field));if(r.nodes.some(m=>m.type==="indicator"&&m.indicator==="atr"))for(let m of["open","high","low","close"])i.add(m);let a=Object.freeze([...i].sort()),l=Se(r);function f(m,p){let w={};for(let S of o){let v=m.get(S);w[S]=v[p]}let g=S=>S!=null&&w[S]===!0;return{values:w,signals:{entryLong:g(r.rules.entryLong),entryShort:g(r.rules.entryShort),exitLong:g(r.rules.exitLong),exitShort:g(r.rules.exitShort)}}}function u(m,p){so(m,p,r.market.interval);let w=new Map;for(let g of o)xe(g,n,s,m,p,w);return w}function c(m,p){return f(u(m,p),p)}function d(m){if(!Array.isArray(m)||m.length===0)throw new TypeError("bars must be a non-empty array");let p=m.length-1,w=u(m,p);return Object.freeze(m.map((g,S)=>Object.freeze(f(w,S))))}return Object.freeze({strategy:r,strategyHash:l,compilerVersion:$e,compilerHash:ye,requiredSeries:a,nodeOrder:o,evaluate:c,evaluateAll:d})}import{createHash as ko}from"node:crypto";import{createHash as io}from"node:crypto";var ao=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:100});function co(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 et(e){if(Array.isArray(e))return e.map(et);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=et(e[r]);return t}return e}function jt(e,t="result"){if(typeof e=="number"){if(!Number.isFinite(e))throw new Error(`non-finite backtest result at ${t}`);return}if(!(e==null||typeof e!="object")){if(Array.isArray(e)){e.forEach((r,n)=>jt(r,`${t}[${n}]`));return}for(let[r,n]of Object.entries(e))jt(n,`${t}.${r}`)}}function _r(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");let t=null;for(let r=0;r<e.length;r++){let n=e[r];if(n==null||typeof n!="object"||Array.isArray(n))throw new TypeError(`bars[${r}] must be an object`);let{t:o,o:s,h:i,l:a,c:l,v:f}=n;if(!ne(o))throw new TypeError(`bars[${r}].t must be finite`);for(let[u,c]of[["o",s],["h",i],["l",a],["c",l],["v",f]])if(!ne(c))throw new TypeError(`bars[${r}].${u} must be a finite number`);for(let[u,c]of[["o",s],["h",i],["l",a],["c",l]])if(!(c>0))throw new TypeError(`bars[${r}].${u} price must be positive`);if(f<0)throw new TypeError(`bars[${r}].v volume must be non-negative`);if(i<Math.max(s,l,a))throw new TypeError(`bars[${r}] high must be >= max(open, close, low)`);if(a>Math.min(s,l,i))throw new TypeError(`bars[${r}] low must be <= min(open, close, high)`);if(t!=null&&!(o>t))throw new TypeError("bars t must be strictly increasing");if(t=o,"fundingRate"in n&&n.fundingRate!=null&&!ne(n.fundingRate))throw new TypeError(`bars[${r}].fundingRate must be finite when present`);if("fundingPaymentRate"in n&&n.fundingPaymentRate!=null&&!ne(n.fundingPaymentRate))throw new TypeError(`bars[${r}].fundingPaymentRate must be finite when present`);if("openInterest"in n&&n.openInterest!=null&&!ne(n.openInterest))throw new TypeError(`bars[${r}].openInterest must be finite when present`)}}function qe(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");return e.length>0&&_r(e),io("sha256").update(JSON.stringify(et(e)),"utf8").digest("hex")}function lo(e){if(e==null&&(e={}),!co(e))throw new TypeError("options must be a plain object");let t={...ao},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 tt(e){return e/1e4}function uo(e,t,r){let n=tt(r);return t==="long"?e*(1+n):e*(1-n)}function fo(e,t,r){let n=tt(r);return t==="long"?e*(1-n):e*(1+n)}function Ir(e,t,r){let n=Math.abs(e)*tt(t),o=Math.abs(e)*tt(r);return{taker:n,builder:o,total:n+o}}function po(e,t){let r=e*(t.positionSizePct/100)*t.maxLeverage;return Math.min(r,t.maxNotionalUsd)}function mo(e,t,r){let n=r/100;return t==="long"?e*(1-n):e*(1+n)}function ho(e,t,r){let n=r/100;return t==="long"?e*(1+n):e*(1-n)}function yo(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 wo(e,t,r){return t==="long"?e.l<=r:e.h>=r}function go(e,t,r){return t==="long"?e.h>=r:e.l<=r}function bo(e,t,r){return t==="long"?e.l<=r:e.h>=r}var Eo=Object.freeze(["fundingRate","openInterest","premium","oiDelta","bookImbalance"]);function Be(e,t){for(let r of e.requiredSeries)if(Eo.includes(r)&&!t.every(n=>ne(n?.[r])))throw new Error(`strategy required series is absent: ${r}`)}function xo(e){if(e.length<3)return 0;let t=[];for(let i=1;i<e.length;i++){let a=e[i-1].equity,l=e[i].equity;a>0&&t.push((l-a)/a)}if(t.length<2)return 0;let r=0;for(let i of t)r+=i;let n=r/t.length,o=0;for(let i of t)o+=(i-n)**2;let s=Math.sqrt(o/(t.length-1));return s>0?n/s:0}function So(e){let t=-1/0,r=0;for(let n of e){let o=n.equity;if(o>t&&(t=o),t>0){let s=(t-o)/t*100;s>r&&(r=s)}}return r}function fe(e,t,r={}){let n=lo(r);_r(t);let o=qe(t);n.nowMs!==void 0&&Z(e,{nowMs:n.nowMs});let s=W(e);if(Be(s,t),n.nowMs!==void 0&&s.strategy.risk.expiresAt<=n.nowMs)throw new Error("strategy is expired: risk.expiresAt must be strictly greater than nowMs");let i=s.strategy.risk,a=s.evaluateAll(t),l=n.latencyBars,f=n.slippageBps,u=n.takerFeeBps,c=n.builderFeeBps,d=n.initialEquityUsd,m=0,p=0,w=0,g=0,S=0,v=[],O=[],x=[],R=[],P=[],h=null,M=0,D=null,Y=d,k=!1,y=0,$=0,_=[],C=new Array(t.length).fill(0);function L(E){_.push(E)}function j(E){let H=t[E].v*(n.maxVolumeParticipationPct/100);return Math.max(0,H-C[E])}function A(E){if(!h)return d;let H=h.side==="long"?(E-h.entryPrice)*h.qty:(h.entryPrice-E)*h.qty;return d+H}function N(E,H,T){let q=T.o,F=po(d,i);if(!(F>0)||!(q>0))return;let B=uo(q,H,f),U=F/B,J=j(E),Le=B*J;if(U>J){x.push({kind:"entry",barIndex:E,time:T.t,side:H,requestedNotionalUsd:F,maxFillNotionalUsd:Le,reason:"volume_participation"});return}C[E]+=U;let re=Math.abs(B-q)*U,ce=Ir(F,u,c);d-=ce.total,m+=ce.taker,p+=ce.builder,g+=re,S+=F,h={lifecycleEpoch:++$,side:H,entryBarIndex:E,entryReferencePrice:q,entryPrice:B,qty:U,notionalUsd:F,stop:mo(B,H,i.stopLossPct),take:ho(B,H,i.takeProfitPct),liq:yo(B,H,i.maxLeverage,u+c),entryFees:ce.taker,entryBuilderFees:ce.builder,entrySlippageUsd:re,fundingAccrued:0}}function I(E,H,T,q){if(!h)return!1;let F=h.side,B=H,U=B;T!=="liquidation"&&q&&(U=fo(B,F,f));let J=h.qty,Le=J*U;if(T!=="liquidation"){let ur=j(E),gn=U*ur;if(J>ur)return x.push({kind:"exit",barIndex:E,time:t[E].t,side:F,requestedNotionalUsd:Le,maxFillNotionalUsd:gn,reason:"volume_participation",triggerReason:T}),!1;C[E]+=J}let re=Ir(Le,u,c),ce=T==="liquidation"?0:Math.abs(U-B)*J,He,yt;F==="long"?(He=(B-h.entryReferencePrice)*J,yt=(U-h.entryPrice)*J):(He=(h.entryReferencePrice-B)*J,yt=(h.entryPrice-U)*J),d+=yt,d-=re.total,m+=re.taker,p+=re.builder,g+=ce,S+=Le;let wn={side:F,entryBarIndex:h.entryBarIndex,entryTime:t[h.entryBarIndex].t,entryPrice:h.entryPrice,exitBarIndex:E,exitTime:t[E].t,exitPrice:U,exitReason:T,qty:J,notionalUsd:h.notionalUsd,grossPnlUsd:He,feesUsd:h.entryFees+re.taker,builderFeesUsd:h.entryBuilderFees+re.builder,fundingUsd:h.fundingAccrued,slippageUsd:h.entrySlippageUsd+ce,netPnlUsd:He-(h.entryFees+re.taker+h.entryBuilderFees+re.builder)-h.fundingAccrued-(h.entrySlippageUsd+ce)};return v.push(wn),T==="liquidation"&&O.push({barIndex:E,time:t[E].t,side:F,price:U,tradeIndex:v.length-1}),h=null,$+=1,y=E+1+(i.cooldownBars||0),!0}function G(E,H,T,q){let F=E+1;if(F>=t.length)return;_.some(U=>U.kind==="exit"&&U.side===H&&U.fillBar===F&&U.epoch===q)||L({kind:"exit",side:H,signalBar:E,fillBar:F,reason:T,epoch:q})}function ee(E){let H=_.filter(T=>T.fillBar===E);for(let T=_.length-1;T>=0;T--)_[T].fillBar===E&&_.splice(T,1);H.sort((T,q)=>{let F=B=>B.kind==="exit"?0:1;return F(T)-F(q)});for(let T of H)if(T.kind==="exit"){if(!h||h.side!==T.side||h.lifecycleEpoch!==T.epoch)continue;let q=T.reason||"rule";I(E,t[E].o,q,!0)||G(E,T.side,q,T.epoch)}else if(T.kind==="entry"){if(h||T.epoch!==$||E<y)continue;N(E,T.side,t[E])}}function pe(E){if(!h)return;let H=t[E],T=H.fundingPaymentRate;if(T==null||!ne(T)||T===0)return;let q=Math.abs(h.qty*H.c),F=T*q;h.side==="long"?(d-=F,h.fundingAccrued+=F,w+=F):(d+=F,h.fundingAccrued-=F,w-=F)}function Ae(E){if(!h)return;let H=t[E].o;(h.side==="long"?H<=h.liq:H>=h.liq)&&I(E,H,"liquidation",!1)}function Ke(E){if(!h)return;let H=t[E],T=h.side,q=bo(H,T,h.liq),F=wo(H,T,h.stop),B=go(H,T,h.take),U=J=>T==="long"?Math.min(J,H.o):Math.max(J,H.o);if(q){I(E,U(h.liq),"liquidation",!1);return}if(F&&B){I(E,U(h.stop),"stop_loss",!0)||G(E,T,"stop_loss",h.lifecycleEpoch);return}if(F){I(E,U(h.stop),"stop_loss",!0)||G(E,T,"stop_loss",h.lifecycleEpoch);return}B&&(I(E,h.take,"take_profit",!0)||G(E,T,"take_profit",h.lifecycleEpoch))}for(let E=0;E<t.length;E++){let H=Math.floor(t[E].t/864e5);H!==D&&(D=H,Y=A(t[E].o),k=!1),Ae(E),ee(E),Ke(E),pe(E),!k&&A(t[E].c)<=Y*(1-i.maxDailyLossPct/100)&&(k=!0,R.push({type:"daily_loss_limit",barIndex:E,time:t[E].t,message:"daily loss limit reached; new entries blocked for UTC day"}));let T=a[E].signals,q=E+l;if(h)(h.side==="long"&&T.exitLong===!0||h.side==="short"&&T.exitShort===!0)&&q<t.length&&(_.some(J=>J.kind==="exit"&&J.side===h.side&&J.fillBar===q&&J.epoch===h.lifecycleEpoch)||L({kind:"exit",side:h.side,signalBar:E,fillBar:q,reason:"rule",epoch:h.lifecycleEpoch}));else{let B=T.entryLong===!0,U=T.entryShort===!0;B&&U?R.push({type:"conflicting_entry_signals",barIndex:E,time:t[E].t,message:"conflicting entry signals; no position opened"}):!k&&(B||U)&&q<t.length&&E>=y&&L({kind:"entry",side:B?"long":"short",signalBar:E,fillBar:q,epoch:$})}let F=d;h&&(M+=1,F=A(t[E].c)),P.push({barIndex:E,time:t[E].t,equity:F,positionSide:h?h.side:null})}let Ye=null;if(h){let E=t.length-1;if(I(E,t[E].c,"end_of_data",!0))P[E]={barIndex:E,time:t[E].t,equity:d,positionSide:null};else{let T=A(t[E].c);Ye={side:h.side,entryBarIndex:h.entryBarIndex,entryTime:t[h.entryBarIndex].t,entryPrice:h.entryPrice,qty:h.qty,notionalUsd:h.notionalUsd,markPrice:t[E].c,markedEquityUsd:T},R.push({type:"open_position_at_end",barIndex:E,time:t[E].t,message:"end-of-data exit missed; position remains open and marked"})}}let Oe=(h?A(t[t.length-1].c):d)-n.initialEquityUsd,ge=Oe/n.initialEquityUsd*100,Me=0,ae=0,pt=0;for(let E of v)E.netPnlUsd>0?(Me+=1,ae+=E.netPnlUsd):E.netPnlUsd<0&&(pt+=-E.netPnlUsd);let mt=v.length,mn=mt===0?0:Me/mt,ht=0;pt>0?ht=ae/pt:ae>0&&(ht=1e12);let hn={netPnlUsd:Oe,netPnlPct:ge,maxDrawdownPct:So(P),winRate:mn,profitFactor:ht,tradeCount:mt,sharpe:xo(P),turnoverUsd:S,exposurePct:M/t.length*100},yn={initialEquityUsd:n.initialEquityUsd,takerFeeBps:n.takerFeeBps,builderFeeBps:n.builderFeeBps,slippageBps:n.slippageBps,latencyBars:n.latencyBars,maxVolumeParticipationPct:n.maxVolumeParticipationPct},lr={barsHash:o,strategyHash:s.strategyHash,compilerHash:ye,compilerVersion:$e,config:yn,trades:v,equityCurve:P,metrics:hn,costs:{feesUsd:m,builderFeesUsd:p,fundingUsd:w,slippageUsd:g},liquidations:O,missedFills:x,openPositionAtEnd:Ye,flags:R};return jt(lr),vt(et(lr))}var Nr=Object.freeze(["fail","pass_paper_only","pass_live_eligible"]);function oe(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function _e(e){return typeof e=="number"&&Number.isFinite(e)}function Mt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Mt(t);return Object.freeze(e)}for(let t of Object.keys(e))Mt(e[t]);return Object.freeze(e)}function ke(e){if(Array.isArray(e))return e.map(ke);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=ke(e[r]);return t}return e}function Nt(e){return{netPnlUsd:e.metrics.netPnlUsd,netPnlPct:e.metrics.netPnlPct,maxDrawdownPct:e.metrics.maxDrawdownPct,winRate:e.metrics.winRate,profitFactor:e.metrics.profitFactor,tradeCount:e.metrics.tradeCount,sharpe:e.metrics.sharpe,turnoverUsd:e.metrics.turnoverUsd,exposurePct:e.metrics.exposurePct}}function vr(e){return{feesUsd:e.costs.feesUsd,builderFeesUsd:e.costs.builderFeesUsd,fundingUsd:e.costs.fundingUsd,slippageUsd:e.costs.slippageUsd}}function To(e){return(e.feesUsd||0)+(e.builderFeesUsd||0)+Math.max(0,e.fundingUsd||0)+(e.slippageUsd||0)}function Ao(e){let t=0;for(let r of e.trades)r.grossPnlUsd>0&&(t+=r.grossPnlUsd);return t}function Oo(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 Rr(e){if(!oe(e))throw new TypeError("evidence artifact must be a plain object");if(!Nr.includes(e.status))throw new TypeError("evidence artifact status is invalid");for(let t of["strategyHash","compilerHash","barsHash"])if(typeof e[t]!="string"||!/^[0-9a-f]{64}$/.test(e[t]))throw new TypeError(`evidence artifact ${t} must be a sha256 hash`);if(!oe(e.split))throw new TypeError("evidence artifact split required");if(!Array.isArray(e.flags))throw new TypeError("evidence artifact flags must be an array");if(!oe(e.walkForward)||!Array.isArray(e.walkForward.windows))throw new TypeError("evidence artifact walkForward windows required");if(e.status==="pass_live_eligible"&&(!oe(e.train)||!oe(e.holdout)))throw new TypeError("live-eligible evidence artifact requires train and holdout facts");return ke({barsHash:e.barsHash,compilerHash:e.compilerHash,flags:e.flags.map(t=>ke(t)),holdout:e.holdout??null,split:e.split,status:e.status,strategyHash:e.strategyHash,train:e.train??null,walkForward:{passRate:e.walkForward.passRate,windowsRun:e.walkForward.windowsRun??e.walkForward.windows.length,windows:e.walkForward.windows.map(t=>({index:t.index,trainStartIndex:t.trainStartIndex,trainEndIndex:t.trainEndIndex,passed:t.passed,reason:t.reason,evalStartIndex:t.evalStartIndex,evalEndIndex:t.evalEndIndex,metrics:t.metrics}))}})}function Lt(e){return ko("sha256").update(JSON.stringify(Rr(e)),"utf8").digest("hex")}function te(e,t,r=0){if(!Number.isInteger(e)||e<r)throw new Error(`${t} must be an integer >= ${r}`);return e}function Rt(e,t){if(!oe(e)||!oe(e.metrics))throw new Error(`${t} metrics required`);let r=te(e.tradeCount,`${t}.tradeCount`);if(e.metrics.tradeCount!==r)throw new Error(`${t} tradeCount contradicts metrics.tradeCount`);for(let n of["netPnlUsd","profitFactor","maxDrawdownPct"])if(!_e(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 Po(e,{maxDailyLossPct:t}={}){let r=e.split,n=te(r.trainStartIndex,"split.trainStartIndex"),o=te(r.trainEndIndex,"split.trainEndIndex"),s=te(r.trainBarCount,"split.trainBarCount",1),i=te(r.holdoutStartIndex,"split.holdoutStartIndex"),a=te(r.holdoutEndIndex,"split.holdoutEndIndex"),l=te(r.holdoutBarCount,"split.holdoutBarCount",1);if(n!==0||o-n+1!==s||i!==o+1||a-i+1!==l)throw new Error("evidence split must be contiguous, chronological, and count-consistent");if(!_e(r.trainFraction)||r.trainFraction<=0||r.trainFraction>=1)throw new Error("split.trainFraction must be in (0,1)");Rt(e.train,"train");let f=Rt(e.holdout,"holdout");if(f.tradeCount<1||f.netPnlUsd<=0||f.profitFactor<=1)throw new Error("live-eligible holdout metrics do not pass");if(_e(t)&&f.maxDrawdownPct>t)throw new Error("live-eligible holdout drawdown exceeds strategy risk");if(e.flags.length>0)throw new Error("live-eligible evidence cannot contain failure flags");let u=e.walkForward,c=u.windows;if(c.length<1||u.windowsRun!==c.length)throw new Error("live-eligible walk-forward windowsRun must match nonempty windows");let d=0,m=-1;for(let w=0;w<c.length;w++){let g=c[w];if(!oe(g)||g.index!==w||typeof g.passed!="boolean")throw new Error("walk-forward windows must be ordered and structurally valid");let S=te(g.trainStartIndex,`walkForward.windows[${w}].trainStartIndex`),v=te(g.trainEndIndex,`walkForward.windows[${w}].trainEndIndex`),O=te(g.evalStartIndex,`walkForward.windows[${w}].evalStartIndex`),x=te(g.evalEndIndex,`walkForward.windows[${w}].evalEndIndex`);if(S!==0||v>=O||O>x||O<=m)throw new Error("walk-forward windows must be chronological and disjoint");if(m=x,g.passed){if(d+=1,g.reason!=="pass")throw new Error("passed walk-forward window reason must be pass");let R=Rt({metrics:g.metrics,tradeCount:g.metrics?.tradeCount},`walkForward.windows[${w}]`);if(R.tradeCount<1||R.netPnlUsd<=0||R.profitFactor<=1)throw new Error("passed walk-forward window metrics do not pass");if(_e(t)&&R.maxDrawdownPct>t)throw new Error("passed walk-forward drawdown exceeds strategy risk")}else if(g.reason==="pass")throw new Error("failed walk-forward window cannot have pass reason")}let p=d/c.length;if(!_e(u.passRate)||Math.abs(u.passRate-p)>Number.EPSILON||p<.6)throw new Error("walk-forward passRate contradicts concrete windows or is below live threshold")}function Ht(e,t={}){if(typeof e?.id!="string"||!/^[0-9a-f]{64}$/.test(e.id))throw new Error("evidence.id must be a sha256 evidence artifact hash");let r=Rr(e),n=ke({id:e.id,...r});if(JSON.stringify(ke(e))!==JSON.stringify(n))throw new Error("evidence artifact contains fields unbound from its deterministic identity");let o=Lt(e);if(e.id!==o)throw new Error("evidence.id does not match its deterministic artifact facts digest");return e.status==="pass_live_eligible"&&Po(e,t),e}function rt({strategy:e,bars:t,backtestOptions:r={},trainFraction:n=.7,walkForwardWindows:o=3,minTrades:s=10}={}){let i=[];if(!oe(e))throw new TypeError("strategy must be a plain object");if(!Array.isArray(t))throw new TypeError("bars must be an array");if(!oe(r))throw new TypeError("backtestOptions must be a plain object");if(!_e(n)||n<=0||n>=1)throw new TypeError("trainFraction must be in (0,1)");if(!Number.isInteger(o)||o<1)throw new TypeError("walkForwardWindows must be a positive integer");if(!Number.isInteger(s)||s<0)throw new TypeError("minTrades must be an integer >= 0");let a=Z(e),l=Se(a),f=qe(t),u=t.length,c=(j=[],A={})=>jr({status:"fail",strategy:a,sHash:l,barsHash:f,split:A.split||{trainStartIndex:0,trainEndIndex:-1,trainBarCount:0,holdoutStartIndex:0,holdoutEndIndex:-1,holdoutBarCount:0,trainFraction:n},train:A.train||null,holdout:A.holdout||null,walkForward:A.walkForward||{windows:[],passRate:0},flags:[...i,...j]});if(u<10)return c([{type:"insufficient_bars",message:"need at least 10 bars for evidence"}]);let d=Math.floor(u*n),m=d,p=u-m;if(d<5||p<3)return c([{type:"invalid_windowing",message:"train/holdout split too small",trainCount:d,holdoutCount:p}]);let w=t.slice(0,d),g=t.slice(m),S,v;try{S=fe(a,w,r),v=fe(a,g,r)}catch(j){return c([{type:"backtest_error",message:String(j.message||j)}])}let O={metrics:Nt(S),costs:vr(S),tradeCount:S.metrics.tradeCount},x={metrics:Nt(v),costs:vr(v),tradeCount:v.metrics.tradeCount},R={trainStartIndex:0,trainEndIndex:d-1,trainBarCount:d,holdoutStartIndex:m,holdoutEndIndex:u-1,holdoutBarCount:p,trainFraction:n},P=[],h=Math.floor(u/(o+1));if(h<3)i.push({type:"invalid_windowing",message:"walk-forward window size too small",wfSize:h});else for(let j=0;j<o;j++){let A=h*(j+1),N=A,I=Math.min(u,N+h);if(I-N<3||A<3){P.push({index:j,trainStartIndex:0,trainEndIndex:A-1,evalStartIndex:N,evalEndIndex:I-1,passed:!1,reason:"window_too_small",metrics:null});continue}let G=t.slice(N,I),ee;try{ee=fe(a,G,r)}catch{P.push({index:j,trainStartIndex:0,trainEndIndex:A-1,evalStartIndex:N,evalEndIndex:I-1,passed:!1,reason:"backtest_error",metrics:null});continue}let pe=Nt(ee),Ae=Oo(pe,a.risk,s);P.push({index:j,trainStartIndex:0,trainEndIndex:A-1,evalStartIndex:N,evalEndIndex:I-1,passed:Ae,reason:Ae?"pass":"fail_metrics",metrics:pe})}let M=P.filter(j=>j.passed).length,D=P.length===0?0:M/P.length,Y={windows:P,passRate:D,windowsRun:P.length};x.metrics.tradeCount===0&&O.metrics.tradeCount===0&&i.push({type:"no_trades",message:"no trades in train or holdout"}),x.metrics.tradeCount===0&&i.push({type:"absent_oos_trades",message:"holdout produced no trades"}),x.metrics.netPnlUsd<0&&i.push({type:"holdout_loss",message:"holdout netPnlUsd is negative"}),O.metrics.netPnlUsd>0&&x.metrics.netPnlUsd<0&&O.metrics.netPnlUsd>Math.abs(x.metrics.netPnlUsd)*.25?i.push({type:"overfit",message:"profitable train with losing holdout (OOS collapse)"}):O.metrics.netPnlUsd>0&&x.metrics.netPnlUsd>0&&x.metrics.netPnlUsd<O.metrics.netPnlUsd*.1&&O.metrics.tradeCount>=s&&i.push({type:"severe_oos_collapse",message:"holdout pnl collapsed vs train"});let k=To(x.costs),y=Ao(v);y>0&&k>y&&i.push({type:"costs_exceed_gross",message:"holdout costs exceed gross gains"});let $=i.some(j=>["insufficient_bars","invalid_windowing","absent_oos_trades","holdout_loss","no_trades","severe_oos_collapse","backtest_error"].includes(j.type)),_=i.some(j=>j.type==="overfit"),C="fail";return x.metrics.tradeCount>=s&&x.metrics.netPnlUsd>0&&x.metrics.profitFactor>1&&x.metrics.maxDrawdownPct<=a.risk.maxDailyLossPct&&D>=.6&&!(y>0&&k>y)&&!_&&!i.some(j=>j.type==="severe_oos_collapse"||j.type==="invalid_windowing")?C="pass_live_eligible":!$&&x.metrics.tradeCount>0&&O.metrics.tradeCount>0&&Number.isFinite(x.metrics.netPnlUsd)?(C="pass_paper_only",x.metrics.tradeCount<s&&i.push({type:"undersampled",message:"holdout trades below minTrades"})):_&&x.metrics.tradeCount>0&&O.metrics.netPnlUsd>0?C="fail":x.metrics.tradeCount>0&&O.metrics.tradeCount>0&&!$?C="pass_paper_only":C="fail",x.metrics.netPnlUsd<0&&(C=C==="pass_live_eligible"?"fail":C==="pass_paper_only"?"pass_paper_only":"fail",C="fail"),jr({status:C,strategy:a,sHash:l,barsHash:f,split:R,train:O,holdout:x,walkForward:Y,flags:i})}function jr({status:e,strategy:t,sHash:r,barsHash:n,split:o,train:s,holdout:i,walkForward:a,flags:l}){let f={status:e,strategyHash:r,compilerHash:ye,barsHash:n,split:o,train:s,holdout:i,walkForward:a,flags:l};return f.id=Lt(f),Mt(ke(JSON.parse(JSON.stringify(f))))}import{createHash as $o,createHmac as Io,timingSafeEqual as Hi}from"node:crypto";var _o=2,vo=300*1e3,jo=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})();function Ft(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(Ft).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${Ft(e[r])}`).join(",")}}`}function Mr(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function Lr(e=process.env){return Mr(process.env)||Mr(e)}function No(e){let{prepareHash:t,prepareMac:r,note:n,...o}=e||{};return o}function Ro(e){let t=No(e);return $o("sha256").update(Ft(t)).digest("hex")}function Mo(e,t=Lr()){return t?Io("sha256",t).update(String(e)).digest("hex"):""}function Hr(e,{provider:t,kind:r,env:n=process.env,nowMs:o=Date.now(),expiresAtMs:s}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let i=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(i&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let a={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1,oraclePrepared:i?e.oraclePrepared:!0};if(!a.provider)throw new Error("stampPrepared: provider required");if(!a.kind)throw new Error("stampPrepared: kind required");let l=Number(o),f=s==null?l+vo:Number(s),u=f-l;if(!Number.isSafeInteger(l)||!Number.isSafeInteger(f)||u<=0||u>jo)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let d={...a,preparedAt:l,expiresAt:f,prepareVersion:_o},m=Ro(d),p=Lr(n),w=p?Mo(m,p):void 0,g={...d,prepareHash:m};return w&&(g.prepareMac=w),g}var Lo=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function ze(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Ho(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Dt(e,t="value"){if(Array.isArray(e)){e.forEach((r,n)=>Dt(r,`${t}[${n}]`));return}if(ze(e))for(let[r,n]of Object.entries(e)){let o=Ho(r);if(Lo.some(s=>o.includes(s)))throw new Error(`handoff: forbidden secret-like field at ${t}.${r}`);Dt(n,`${t}.${r}`)}}function Ct(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function Ut({strategy:e,evidence:t,shadow:r,caps:n,nowMs:o=Date.now(),env:s=process.env}={}){if(Dt({strategy:e,evidence:t,shadow:r,caps:n},"handoff"),!ze(e))throw new Error("handoff: strategy required");if(!ze(t))throw new Error("handoff: evidence required");if(!ze(r))throw new Error("handoff: shadow required");if(!ze(n))throw new Error("handoff: caps required");if(typeof r.id!="string"||!r.id.trim())throw new Error("handoff: shadow.id required");if(typeof r.stateHash!="string"||!/^[0-9a-f]{64}$/.test(r.stateHash))throw new Error("handoff: shadow.stateHash must be a sha256 hash");if(r.status!=="running")throw new Error("handoff: shadow.status must be running");if(!Number.isInteger(r.cursor)||r.cursor<=0)throw new Error("handoff: shadow.cursor must be a positive integer");if(!Number.isInteger(r.updatedAt)||r.updatedAt<=0||r.updatedAt>o)throw new Error("handoff: shadow.updatedAt must be a positive integer <= nowMs");let i=Z(e,{nowMs:o}),a=W(i);if(Ht(t,{maxDailyLossPct:i.risk.maxDailyLossPct}),t.status!=="pass_live_eligible")throw new Error("handoff: evidence.status must be pass_live_eligible");if(t.strategyHash!==a.strategyHash)throw new Error("handoff: evidence.strategyHash mismatch");if(t.compilerHash!==a.compilerHash)throw new Error("handoff: evidence.compilerHash mismatch");let l=["perStrategyNotionalUsd","maxLeverage","dailyLossCapUsd","chainAllowlist","assetAllowlist","expiresAt","killSwitchRequired"];for(let d of l)if(!(d in n)||n[d]==null)throw new Error(`handoff: caps.${d} required`);if(!Ct(n.perStrategyNotionalUsd))throw new Error("handoff: caps.perStrategyNotionalUsd must be positive");if(n.perStrategyNotionalUsd>a.strategy.risk.maxNotionalUsd)throw new Error("handoff: caps.perStrategyNotionalUsd exceeds strategy.risk.maxNotionalUsd");if(!Ct(n.maxLeverage))throw new Error("handoff: caps.maxLeverage must be positive");if(n.maxLeverage>a.strategy.risk.maxLeverage)throw new Error("handoff: caps.maxLeverage exceeds strategy.risk.maxLeverage");if(!Ct(n.dailyLossCapUsd))throw new Error("handoff: caps.dailyLossCapUsd must be positive");let f=a.strategy.risk.maxNotionalUsd*(a.strategy.risk.maxDailyLossPct/100);if(n.dailyLossCapUsd>f)throw new Error("handoff: caps.dailyLossCapUsd exceeds strategy daily loss ceiling");if(!Array.isArray(n.chainAllowlist)||n.chainAllowlist.length===0)throw new Error("handoff: caps.chainAllowlist must be a non-empty array");if(!n.chainAllowlist.every(d=>d==="hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include only hyperliquid");if(!n.chainAllowlist.includes("hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include hyperliquid");if(!Array.isArray(n.assetAllowlist)||n.assetAllowlist.length===0)throw new Error("handoff: caps.assetAllowlist must be a non-empty array");if(n.assetAllowlist.length!==1||n.assetAllowlist[0]!==a.strategy.market.coin)throw new Error("handoff: caps.assetAllowlist must contain only the strategy market coin");if(!Number.isInteger(n.expiresAt)||!(n.expiresAt>o))throw new Error("handoff: caps.expiresAt must be an integer > nowMs");if(n.expiresAt>a.strategy.risk.expiresAt)throw new Error("handoff: caps.expiresAt exceeds strategy.risk.expiresAt");if(n.killSwitchRequired!==!0)throw new Error("handoff: caps.killSwitchRequired must be exactly true");let u={perStrategyNotionalUsd:n.perStrategyNotionalUsd,maxLeverage:n.maxLeverage,dailyLossCapUsd:n.dailyLossCapUsd,chainAllowlist:[...n.chainAllowlist],assetAllowlist:[...n.assetAllowlist],expiresAt:n.expiresAt,killSwitchRequired:!0},c={strategyHash:a.strategyHash,compilerHash:a.compilerHash,evidence:JSON.parse(JSON.stringify(t)),shadow:{id:r.id,stateHash:r.stateHash,status:r.status,cursor:r.cursor,updatedAt:r.updatedAt},compiled:{strategyHash:a.strategyHash,compilerHash:a.compilerHash,compilerVersion:$e,venue:"hyperliquid",market:{coin:a.strategy.market.coin,kind:"perp",interval:a.strategy.market.interval},risk:{...a.strategy.risk},strategy:JSON.parse(JSON.stringify(a.strategy))},arming:{liveBroadcast:!1,requiresExplicitUserArm:!0,caps:u},requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,executionReady:!1};return Hr(c,{provider:"hl-strategy",kind:"strategy-live-handoff",env:s})}var Fo=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 ve(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function je(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be a non-negative safe integer`);return e}function Ve(e){if(Array.isArray(e))for(let t of e)Ve(t);else if(e&&typeof e=="object")for(let t of Object.values(e))Ve(t);return Object.freeze(e)}function Fr(e){let t=Fo[e];if(!t)throw new TypeError(`unsupported strategy interval: ${e}`);return t}function Cr(e,{endTime:t=Number.MAX_SAFE_INTEGER}={}){if(!Array.isArray(e))throw new TypeError("Hyperliquid candles must be an array");je(t,"endTime");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`candles[${n}] must be an object`);let s=je(Number(o.t),`candles[${n}].t`);if(je(Number(o.T),`candles[${n}].T`)>t)continue;let a={t:s,o:ve(o.o,`candles[${n}].o`),h:ve(o.h,`candles[${n}].h`),l:ve(o.l,`candles[${n}].l`),c:ve(o.c,`candles[${n}].c`),v:ve(o.v,`candles[${n}].v`)};if(a.h<Math.max(a.o,a.c,a.l))throw new TypeError(`candles[${n}].h is below another price`);if(a.l>Math.min(a.o,a.c,a.h))throw new TypeError(`candles[${n}].l is above another price`);if(a.v<0)throw new TypeError(`candles[${n}].v must be non-negative`);let l=r.get(s);if(l&&JSON.stringify(l)!==JSON.stringify(a))throw new TypeError(`conflicting duplicate candle at timestamp ${s}`);l||r.set(s,a)}return Ve([...r.values()].sort((n,o)=>n.t-o.t))}function Co(e,t){if(!Array.isArray(e))throw new TypeError("Hyperliquid funding history must be an array");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`funding[${n}] must be an object`);let s=je(Number(o.time),`funding[${n}].time`);s>t||r.set(s,{time:s,fundingRate:ve(o.fundingRate,`funding[${n}].fundingRate`)})}return[...r.values()].sort((n,o)=>n.time-o.time)}async function Do({coin:e,startTime:t,endTime:r},n){let o=[],s=Math.max(0,t-288e5),i=!1;for(let a=0;a<16&&s<=r;a++){let l=await Or({coin:e,startTime:s,endTime:r},n);if(!Array.isArray(l))throw new TypeError("Hyperliquid funding history must be an array");o.push(...l);let f=s;for(let u of l){let c=Number(u?.time);Number.isSafeInteger(c)&&c>f&&(f=c)}if(l.length<500||f>=r){i=!0;break}if(f<=s)throw new Error("Hyperliquid funding history pagination did not advance");s=f+1}if(!i)throw new Error("strategy history exceeds the bounded funding history limit");return Co(o,r)}function Uo(e,t,r){let n=0,o=null;return e.map(s=>{let i=s.t+r,a=0;for(;n<t.length&&t[n].time<i;){let l=t[n];o=l.fundingRate,l.time>=s.t&&(a+=l.fundingRate),n+=1}return o==null?{...s,fundingPaymentRate:a}:{...s,fundingRate:o,fundingPaymentRate:a}})}async function qt(e,t={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("strategy history input must be an object");let r=String(e.coin||"").trim().toUpperCase();if(!/^[A-Z0-9][A-Z0-9._-]{0,11}$/.test(r))throw new TypeError("coin must be an uppercase Hyperliquid asset id");let n=String(e.interval||"15m"),o=Fr(n);if(e.endTime==null)throw new TypeError("endTime is required for deterministic history");let s=je(e.endTime,"endTime"),i=e.count==null?1500:e.count;if(!Number.isInteger(i)||i<20||i>5e3)throw new TypeError("count must be an integer from 20 to 5000");let a=e.startTime==null?Math.max(0,s-i*o):je(e.startTime,"startTime");if(a>=s)throw new TypeError("startTime must be before endTime");let[l,f]=await Promise.all([Ar({coin:r,interval:n,startTime:a,endTime:s},t),Do({coin:r,startTime:a,endTime:s},t)]),u=Cr(l,{endTime:s}),c=Ve(Uo(u,f,o));return Ve({coin:r,interval:n,range:{startTime:a,endTime:s},bars:c})}var qo=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),Bo=new Set(["coin","interval"]);function zo(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))Bo.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"||!qo.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 Vo(e={}){let t=await kr(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 Dr=Object.freeze({id:"hyperliquid",validateMarket:zo,fetchBars:qt,listMarkets:Vo,prepareIntent(e){return Ut(e)}});var Jo=Object.freeze(["id","validateMarket","prepareIntent"]);function Go(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 Jo.slice(1))if(typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} requires ${t}()`);for(let t of["fetchBars","listMarkets"])if(e[t]!=null&&typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} ${t} must be a function`);return e}var Ur=[Dr].map(Go),Ko=new Map(Ur.map(e=>[e.id,e])),Yo=Object.freeze([...Ur]);function nt(e){return typeof e!="string"?null:Ko.get(e)??null}function ot(e){let t=nt(e);if(!t)throw new Error(`unknown strategy venue: ${String(e)}`);return t}var st=1,Zr=/^[a-z0-9][a-z0-9._-]{0,63}$/,Xr=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Zo=new Set(["open","high","low","close","volume","fundingRate","openInterest","premium","oiDelta","bookImbalance"]),Xo=new Set(["sma","ema","rsi","macd","bollinger","atr"]),Qo=new Set(["gt","gte","lt","lte","eq"]),es=new Set(["and","or","not"]),ts=new Set(["above","below"]),rs=new Set(["line","signal","histogram"]),ns=new Set(["upper","middle","lower"]),Bt=new Set(["compare","logic","cross"]),qr=new Set(["version","id","name","venue","market","parameters","nodes","rules","risk"]),Br=new Set(["value","min","max","step"]),zt=new Set(["entryLong","entryShort","exitLong","exitShort"]),zr=new Set(["maxLeverage","maxNotionalUsd","positionSizePct","stopLossPct","takeProfitPct","cooldownBars","maxDailyLossPct","expiresAt"]),os=new Set(["id","type"]),Vr={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"])},Jr=16,Gr=128,Kr=100,Te=class extends Error{constructor(t){let r=t.map(n=>`${n.path}: ${n.message}`);super(`invalid strategy (${t.length} error${t.length===1?"":"s"}): ${r.join("; ")}`),this.name="StrategyValidationError",this.errors=t}};function Q(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function z(e){return typeof e=="number"&&Number.isFinite(e)}function Yr(e){return Number.isInteger(e)&&e>0}function Jt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Jt(t);return Object.freeze(e)}for(let t of Object.keys(e))Jt(e[t]);return Object.freeze(e)}function Gt(e){if(Array.isArray(e))return e.map(Gt);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Gt(e[r]);return t}return e}function b(e,t,r){e.push({path:t,message:r})}function we(e,t,r,n){for(let o of Object.keys(e))t.has(o)||b(n,r?`${r}.${o}`:o,"unknown field is not allowed")}function Qr(e,t,r,n){if(!z(e)||!z(t)||!z(r)||!z(n)||n<=0||e<t||e>r)return!1;let o=(e-t)/n;if(!Number.isFinite(o))return!1;let s=Math.round(o);return Math.abs(o-s)<=1e-9}function Vt(e,t,r,n){if(Q(e)){if(we(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param)return b(n,`${t}.param`,"must be a parameter name string"),null;if(!Object.prototype.hasOwnProperty.call(r,e.param))return b(n,`${t}.param`,`unknown parameter "${e.param}"`),null;let o=r[e.param];return!Q(o)||![o.value,o.min,o.max,o.step].every(Yr)?(b(n,`${t}.param`,"referenced period parameter value min max and step must be positive integers"),null):{param:e.param}}return Yr(e)?e:(b(n,t,"must be a positive integer or {param}"),null)}function Wr(e,t,r,n){return Q(e)?(we(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param?(b(n,`${t}.param`,"must be a parameter name string"),null):Object.prototype.hasOwnProperty.call(r,e.param)?{param:e.param}:(b(n,`${t}.param`,`unknown parameter "${e.param}"`),null)):z(e)?e:(b(n,t,"must be a finite number or {param}"),null)}function it(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 ss(e){let t=new Map,r=n=>{let o=t.get(n)||0;if(o===1)return!0;if(o===2)return!1;t.set(n,1);let s=e.get(n);if(s){for(let i of it(s))if(e.has(i)&&r(i))return!0}return t.set(n,2),!1};for(let n of e.keys())if(r(n))return!0;return!1}function is(e,t){if(!Q(e))return b(t,"parameters","must be a plain object"),null;let r=Object.keys(e);if(r.length>Jr)return b(t,"parameters",`too many parameters (max ${Jr})`),null;let n={};for(let o of r){if(!Zr.test(o)){b(t,`parameters.${o}`,"parameter name is malformed");continue}let s=e[o],i=`parameters.${o}`;if(!Q(s)){b(t,i,"must be a plain object");continue}we(s,Br,i,t);for(let c of Br)c in s||b(t,`${i}.${c}`,"required field is missing");let{value:a,min:l,max:f,step:u}=s;z(l)||b(t,`${i}.min`,"must be a finite number"),z(f)||b(t,`${i}.max`,"must be a finite number"),(!z(u)||u<=0)&&b(t,`${i}.step`,"must be a positive finite number"),z(a)||b(t,`${i}.value`,"must be a finite number"),z(l)&&z(f)&&l>f&&b(t,`${i}.min`,"min must be <= max"),z(a)&&z(l)&&z(f)&&z(u)&&u>0&&(Qr(a,l,f,u)||b(t,`${i}.value`,"value must lie on the declared min/max/step grid")),n[o]={value:a,min:l,max:f,step:u}}return n}function as(e,t,r,n){let o=`nodes.${t}`;if(!Q(e))return b(n,o,"must be a plain object"),null;if(typeof e.type!="string"||!Vr[e.type])return b(n,`${o}.type`,"unknown or missing node type"),we(e,os,o,n),null;switch(we(e,Vr[e.type],o,n),(typeof e.id!="string"||!Xr.test(e.id))&&b(n,`${o}.id`,"must be a 1-64 char id starting with alphanumeric"),e.type){case"input":return(typeof e.field!="string"||!Zo.has(e.field))&&b(n,`${o}.field`,"must be one of open|high|low|close|volume|fundingRate|openInterest|premium|oiDelta|bookImbalance"),{id:e.id,type:"input",field:e.field};case"constant":{let s=Wr(e.value,`${o}.value`,r,n);return{id:e.id,type:"constant",value:s}}case"indicator":{(typeof e.indicator!="string"||!Xo.has(e.indicator))&&b(n,`${o}.indicator`,"must be one of sma|ema|rsi|macd|bollinger|atr");let s=e.indicator,i={id:e.id,type:"indicator",indicator:s};if(s==="atr"){"input"in e&&(typeof e.input!="string"||!e.input?b(n,`${o}.input`,"must be a node id string when provided"):i.input=e.input);let a=Vt(e.period,`${o}.period`,r,n);a!=null&&(i.period=a)}else typeof e.input!="string"||!e.input?b(n,`${o}.input`,"must be a node id string"):i.input=e.input;if((s==="sma"||s==="ema"||s==="rsi"||s==="bollinger"||s==="atr")&&("period"in e,s!=="macd"))if(!("period"in e))b(n,`${o}.period`,"required field is missing");else{let a=Vt(e.period,`${o}.period`,r,n);a!=null&&(i.period=a)}if(s==="macd"){for(let a of["fastPeriod","slowPeriod","signalPeriod"])if(!(a in e))b(n,`${o}.${a}`,"required field is missing");else{let l=Vt(e[a],`${o}.${a}`,r,n);l!=null&&(i[a]=l)}"output"in e?rs.has(e.output)?i.output=e.output:b(n,`${o}.output`,"must be line|signal|histogram"):b(n,`${o}.output`,"required field is missing"),"period"in e&&b(n,`${o}.period`,"forbidden for macd"),"stdDev"in e&&b(n,`${o}.stdDev`,"forbidden for macd")}else if(s==="bollinger"){if(!("stdDev"in e))b(n,`${o}.stdDev`,"required field is missing");else{let a=Wr(e.stdDev,`${o}.stdDev`,r,n);a!=null&&(typeof a=="number"&&a<=0?b(n,`${o}.stdDev`,"must be > 0"):i.stdDev=a)}"output"in e?ns.has(e.output)?i.output=e.output:b(n,`${o}.output`,"must be upper|middle|lower"):b(n,`${o}.output`,"required field is missing");for(let a of["fastPeriod","slowPeriod","signalPeriod"])a in e&&b(n,`${o}.${a}`,`forbidden for ${s}`)}else{"output"in e&&b(n,`${o}.output`,`forbidden for ${s}`),"stdDev"in e&&s!=="bollinger"&&b(n,`${o}.stdDev`,`forbidden for ${s}`);for(let a of["fastPeriod","slowPeriod","signalPeriod"])a in e&&b(n,`${o}.${a}`,`forbidden for ${s}`)}return i}case"compare":return(typeof e.op!="string"||!Qo.has(e.op))&&b(n,`${o}.op`,"must be gt|gte|lt|lte|eq"),(typeof e.left!="string"||!e.left)&&b(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&b(n,`${o}.right`,"must be a node id"),{id:e.id,type:"compare",op:e.op,left:e.left,right:e.right};case"logic":{if((typeof e.op!="string"||!es.has(e.op))&&b(n,`${o}.op`,"must be and|or|not"),!Array.isArray(e.inputs))return b(n,`${o}.inputs`,"must be an array of node ids"),{id:e.id,type:"logic",op:e.op,inputs:[]};let s=[];for(let i=0;i<e.inputs.length;i++){let a=e.inputs[i];typeof a!="string"||!a?b(n,`${o}.inputs.${i}`,"must be a node id"):s.push(a)}return e.op==="not"?s.length!==1&&b(n,`${o}.inputs`,"not requires exactly one input"):(e.op==="and"||e.op==="or")&&s.length<2&&b(n,`${o}.inputs`,`${e.op} requires at least two inputs`),{id:e.id,type:"logic",op:e.op,inputs:s}}case"cross":return(typeof e.direction!="string"||!ts.has(e.direction))&&b(n,`${o}.direction`,"must be above|below"),(typeof e.left!="string"||!e.left)&&b(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&b(n,`${o}.right`,"must be a node id"),{id:e.id,type:"cross",direction:e.direction,left:e.left,right:e.right};default:return null}}function cs(e,t,r){if(!Q(e))return b(t,"risk","must be a plain object"),null;we(e,zr,"risk",t);for(let d of zr)(!(d in e)||e[d]==null)&&b(t,`risk.${d}`,"required field is missing");let n={},o=e.maxLeverage;!z(o)||o<=0||o>50?b(t,"risk.maxLeverage","must be a number > 0 and <= 50"):n.maxLeverage=o;let s=e.maxNotionalUsd;!z(s)||s<=0?b(t,"risk.maxNotionalUsd","must be a number > 0"):n.maxNotionalUsd=s;let i=e.positionSizePct;!z(i)||i<=0||i>100?b(t,"risk.positionSizePct","must be a number > 0 and <= 100"):n.positionSizePct=i;let a=e.stopLossPct;!z(a)||a<=0||a>100?b(t,"risk.stopLossPct","must be a number > 0 and <= 100"):n.stopLossPct=a;let l=e.takeProfitPct;!z(l)||l<=0||l>1e3?b(t,"risk.takeProfitPct","must be a number > 0 and <= 1000"):n.takeProfitPct=l;let f=e.cooldownBars;!Number.isInteger(f)||f<0||f>1e5?b(t,"risk.cooldownBars","must be an integer >= 0 and <= 100000"):n.cooldownBars=f;let u=e.maxDailyLossPct;!z(u)||u<=0||u>100?b(t,"risk.maxDailyLossPct","must be a number > 0 and <= 100"):n.maxDailyLossPct=u;let c=e.expiresAt;return!Number.isInteger(c)||c<=0?b(t,"risk.expiresAt","must be an integer epoch milliseconds > 0"):(r.nowMs!==void 0&&(Number.isInteger(r.nowMs)?c<=r.nowMs&&b(t,"risk.expiresAt","must be strictly greater than nowMs"):b(t,"nowMs","must be an integer epoch milliseconds")),n.expiresAt=c),n}function at(e,t={}){let r=[];if(!Q(e))return b(r,"","strategy must be a plain object"),{ok:!1,errors:r,strategy:null};we(e,qr,"",r);for(let c of qr)(!(c in e)||e[c]==null)&&b(r,c,"required field is missing");e.version!==st&&b(r,"version",`must be ${st}`),(typeof e.id!="string"||!Zr.test(e.id))&&b(r,"id","must match /^[a-z0-9][a-z0-9._-]{0,63}$/"),(typeof e.name!="string"||e.name.length===0||e.name.length>Kr)&&b(r,"name",`must be a non-empty string max ${Kr}`);let n=nt(e.venue);n||b(r,"venue",`unknown strategy venue "${String(e.venue)}"`);let o=null;if(!n)Q(e.market)||b(r,"market","must be a plain object");else{let c=n.validateMarket(e.market);if(!c||typeof c.ok!="boolean"||!Array.isArray(c.errors))b(r,"market",`venue ${n.id} returned an invalid market validation result`);else if(c.ok)o=c.market;else for(let d of c.errors)b(r,d.path,d.message)}let s=is(e.parameters,r),i=null,a=new Map;if(!Array.isArray(e.nodes))b(r,"nodes","must be an array");else if(e.nodes.length>Gr)b(r,"nodes",`too many nodes (max ${Gr})`);else{i=[];for(let c=0;c<e.nodes.length;c++){let d=as(e.nodes[c],c,s||{},r);d&&(typeof d.id=="string"&&Xr.test(d.id)&&(a.has(d.id)?b(r,`nodes.${c}.id`,`duplicate node id "${d.id}"`):a.set(d.id,d)),i.push(d))}for(let c=0;c<i.length;c++){let d=i[c],m=`nodes.${c}`;for(let p of it(d))a.has(p)||b(r,m,`unknown node ref "${p}"`);if(d.type==="indicator"||d.type==="compare"||d.type==="cross")for(let p of it(d)){let w=a.get(p);w&&Bt.has(w.type)&&b(r,m,`node ref "${p}" must be numeric`)}if(d.type==="logic")for(let p of it(d)){let w=a.get(p);w&&!Bt.has(w.type)&&b(r,m,`node ref "${p}" must be boolean`)}}ss(a)&&b(r,"nodes","graph contains a cycle")}let l=null;if(!Q(e.rules))b(r,"rules","must be a plain object");else{we(e.rules,zt,"rules",r);for(let c of zt)c in e.rules||b(r,`rules.${c}`,"required field is missing");l={};for(let c of zt){let d=e.rules[c];if(d===null){l[c]=null;continue}if(typeof d!="string"||!d){b(r,`rules.${c}`,"must be a node id or null"),l[c]=d;continue}if(!a.has(d)){b(r,`rules.${c}`,`unknown node ref "${d}"`),l[c]=d;continue}let m=a.get(d);Bt.has(m.type)||b(r,`rules.${c}`,`rule must reference a boolean node, not ${m.type}`),l[c]=d}}let f=cs(e.risk,r,t);if(r.length)return{ok:!1,errors:r,strategy:null};let u=Jt({version:st,id:e.id,name:e.name,venue:n.id,market:o,parameters:s,nodes:i,rules:l,risk:f});return{ok:!0,errors:[],strategy:u}}function Z(e,t={}){let r=at(e,t);if(!r.ok)throw new Te(r.errors);return r.strategy}function en(e){let t=Z(e);return JSON.stringify(Gt(t))}function Se(e){let t=en(e);return Wo("sha256").update(t,"utf8").digest("hex")}function Ie(e,t){if(!Q(e))throw new Te([{path:"",message:"strategy must be a plain object"}]);if(!Q(t))throw new Te([{path:"overrides",message:"must be a plain object"}]);let r=Z(e),n={};for(let[s,i]of Object.entries(r.parameters))n[s]={value:i.value,min:i.min,max:i.max,step:i.step};let o=[];for(let[s,i]of Object.entries(t)){if(!Object.prototype.hasOwnProperty.call(n,s)){b(o,s,`unknown parameter "${s}"`);continue}let a=n[s];if(!z(i)){b(o,s,"override must be a finite number");continue}if(!Qr(i,a.min,a.max,a.step)){b(o,s,"override must lie on the declared min/max/step grid");continue}n[s]={...a,value:i}}if(o.length)throw new Te(o);return Z({version:r.version,id:r.id,name:r.name,venue:r.venue,market:{coin:r.market.coin,interval:r.market.interval},parameters:n,nodes:r.nodes.map(s=>{let i={...s};return Array.isArray(s.inputs)&&(i.inputs=[...s.inputs]),i}),rules:{...r.rules},risk:{...r.risk}})}var ls=50;function se(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function tn(e,t,r){if(!Array.isArray(e))throw new TypeError(`${r} must be an array`);let n=0;for(let o=0;o<e.length;o++){let s=se(e[o]?.px,`${r}[${o}].px`),i=se(e[o]?.sz,`${r}[${o}].sz`);if(i<0)throw new TypeError(`${r}[${o}].sz must be non-negative`);Math.abs((s-t)/t)*1e4<=ls&&(n+=i)}return n}async function us(e,t={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("sampleLiveSeries input must be an object");let r=String(e.coin||"").trim().toUpperCase();if(!/^[A-Z0-9][A-Z0-9._-]{0,11}$/.test(r))throw new TypeError("coin must be an uppercase Hyperliquid asset id");if(!Number.isSafeInteger(e.nowMs)||e.nowMs<=0)throw new TypeError("nowMs is required integer epoch ms");let[n,o]=await Promise.all([Tr(t),Sr(r,t)]),s=n?.[0]?.universe,i=n?.[1];if(!Array.isArray(s)||!Array.isArray(i))throw new TypeError("metaAndAssetCtxs payload malformed");let a=s.findIndex(w=>w?.name===r);if(a<0)throw new Error(`unknown coin: ${r}`);let l=i[a];if(!l||typeof l!="object")throw new TypeError("asset ctx malformed");let f=se(l.premium,"ctx.premium"),u=se(l.openInterest,"ctx.openInterest");if(u<0)throw new TypeError("ctx.openInterest must be non-negative");let c=se(l.midPx,"ctx.midPx"),d=o?.levels;if(!Array.isArray(d)||d.length!==2)throw new TypeError("l2Book levels malformed");let m=tn(d[0],c,"book.bids"),p=tn(d[1],c,"book.asks");if(m+p<=0)throw new TypeError("book depth near mid is empty");return Object.freeze({coin:r,t:e.nowMs,premium:f,openInterest:u,book:Object.freeze({bidDepth:m,askDepth:p})})}function fs(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("snapshots must be a non-empty array");let t=e[0]?.coin,r=[],n=null;for(let o=0;o<e.length;o++){let s=e[o];if(!s||typeof s!="object")throw new TypeError(`snapshots[${o}] must be an object`);if(s.coin!==t)throw new TypeError("snapshots must be a single coin");let i=se(s.t,`snapshots[${o}].t`);if(n!=null&&!(i>n.t))throw new TypeError("snapshot times must be strictly increasing");let a=se(s.premium,`snapshots[${o}].premium`),l=se(s.openInterest,`snapshots[${o}].openInterest`),f=se(s.book?.bidDepth,`snapshots[${o}].book.bidDepth`),u=se(s.book?.askDepth,`snapshots[${o}].book.askDepth`),c=f+u;if(!(c>0))throw new TypeError(`snapshots[${o}] book depth must be positive`);r.push({coin:t,t:i,premium:a,openInterest:l,oiDelta:n==null?null:l-n.openInterest,bookImbalance:(f-u)/c}),n={t:i,openInterest:l}}return r}function ds(e,t,r){if(!Array.isArray(e))throw new TypeError("bars must be an array");if(!Array.isArray(t))throw new TypeError("rows must be an array");if(!Number.isSafeInteger(r)||r<=0)throw new TypeError("intervalMs must be a positive integer");let n=0;return e.map(o=>{let s=o.t+r,i=null;for(;n<t.length&&t[n].t<s;)t[n].t>=o.t&&(i=t[n]),n+=1;if(!i)return{...o};let a={...o};return i.premium!=null&&(a.premium=i.premium),i.openInterest!=null&&(a.openInterest=i.openInterest),i.oiDelta!=null&&(a.oiDelta=i.oiDelta),i.bookImbalance!=null&&(a.bookImbalance=i.bookImbalance),a})}import{createHash as ps}from"node:crypto";var Yt=256,rn=new Set(["netPnlUsd","profitFactor","sharpe","maxDrawdownPct"]);function nn(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 on(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Wt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Wt(t);return Object.freeze(e)}for(let t of Object.keys(e))Wt(e[t]);return Object.freeze(e)}function Je(e){if(Array.isArray(e))return e.map(Je);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Je(e[r]);return t}return e}function ct(e){return JSON.stringify(Je(e))}function ms(e){let{min:t,max:r,step:n}=e;if(!(n>0)||t>r)return[];let o=[],s=Math.floor((r-t)/n+1e-9);for(let a=0;a<=s;a++){let l=t+a*n;if(l>r+1e-9)break;let f=Math.abs(l-Math.round(l))<1e-9?Math.round(l):Number(l.toPrecision(12));f<t-1e-9||f>r+1e-9||o.push(f)}if(o.length===0)return[];let i=o[o.length-1];if(Math.abs(i-r)>1e-9){let a=(r-t)/n;Math.abs(a-Math.round(a))<=1e-9&&o.push(r)}return o}function hs(e,t){if(e.length===0)return[];let r=[{}];for(let n of e){let o=t[n],s=[];for(let i of r)for(let a of o)s.push({...i,[n]:a});r=s}return r.sort((n,o)=>{let s=ct(n),i=ct(o);return s<i?-1:s>i?1:0}),r}function Kt(e,t,r,n,o){let s=0;if(e==="maxDrawdownPct"){if(s=t.maxDrawdownPct-n.maxDrawdownPct,s!==0)return s<0}else if(s=t[e]-n[e],s!==0)return s>0;let i=ct(r),a=ct(o);return i<a}function Zt(e,t,r={}){if(!on(r))throw new TypeError("options must be a plain object");for(let x of Object.keys(r))if(nn(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>Yt)throw new TypeError(`maxTrials must be an integer 1..${Yt}`);o=x}let s=r.objective??"netPnlUsd";if(!rn.has(s))throw new TypeError(`objective must be one of ${[...rn].join("|")}`);let i=r.backtestOptions??{};if(!on(i))throw new TypeError("backtestOptions must be a plain object");for(let x of Object.keys(i))if(nn(x))throw new TypeError(`backtestOptions must not include holdout/test/oos key "${x}"`);let a=Z(e),l=Object.keys(a.parameters).sort();if(l.length===0)throw new Error("optimizeStrategy requires at least one declared parameter");let f={},u=1;for(let x of l){let R=ms(a.parameters[x]);if(R.length===0)throw new Error(`parameter "${x}" produces an empty grid`);f[x]=R,u*=R.length}let c=hs(l,f);if(c.length===0)throw new Error("parameter grid is empty");let d=c.slice(0,o),m=[],p=null,w=null;for(let x of d){let R=Ie(a,x),P=fe(R,t,i);w==null&&(w=P.config);let h={netPnlUsd:P.metrics.netPnlUsd,netPnlPct:P.metrics.netPnlPct,maxDrawdownPct:P.metrics.maxDrawdownPct,winRate:P.metrics.winRate,profitFactor:P.metrics.profitFactor,tradeCount:P.metrics.tradeCount,sharpe:P.metrics.sharpe,turnoverUsd:P.metrics.turnoverUsd},M={parameters:{...x},metrics:h};m.push(M),(!p||Kt(s,h,x,p.metrics,p.parameters))&&(p=M)}m.sort((x,R)=>Kt(s,x.metrics,x.parameters,R.metrics,R.parameters)?-1:Kt(s,R.metrics,R.parameters,x.metrics,x.parameters)?1:0);let g={...p.parameters},S=Ie(a,g),v={strategyHash:Se(a),compilerHash:ye,trainBarsHash:qe(t),backtestConfig:w,objective:s,maxTrials:o,trialsRun:m.length,candidates:m,bestParameters:g,bestStrategy:S},O={id:ps("sha256").update(JSON.stringify(Je(v)),"utf8").digest("hex"),...v};return Wt(Je(JSON.parse(JSON.stringify(O))))}import{createHash as ys}from"node:crypto";var K=class extends Error{constructor(t){super(t),this.name="StrategyDraftError"}},ws=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),gs=new Set(["BTC","ETH","SOL","HYPE"]),bs=/\b(mnemonic|private\s*key|privkey|seed\s*phrase|seed\b|api[_-]?key|secret\s*key|wallet\s*key|passphrase)\b/i,Ne="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.",Es=Object.freeze({maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3}),xs=36e5,Ss=30*864e5,ks=864e5;function Ts(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Xt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Xt(t);return Object.freeze(e)}for(let t of Object.keys(e))Xt(e[t]);return Object.freeze(e)}function As(e){return String(e).trim().replace(/\s+/g," ")}function Os(e){let t=e.match(/\b(long|short)\b/i);return t?t[1].toLowerCase():null}function Ps(e){for(let r of gs)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 $s(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 ws.has(r)?r:null}function Is(e){let t={...Es},r=e.match(/stop\s*loss\s*(\d+(?:\.\d+)?)\s*%?/i);r&&(t.stopLossPct=Number(r[1]));let n=e.match(/take\s*profit\s*(\d+(?:\.\d+)?)\s*%?/i);n&&(t.takeProfitPct=Number(n[1]));let o=e.match(/leverage\s*(\d+(?:\.\d+)?)/i);o&&(t.maxLeverage=Number(o[1]));let s=e.match(/position\s*size\s*(\d+(?:\.\d+)?)\s*%?/i);s&&(t.positionSizePct=Number(s[1]));let i=e.match(/max\s*notional\s*(?:usd\s*)?\$?\s*(\d+(?:\.\d+)?)/i);return i&&(t.maxNotionalUsd=Number(i[1])),t}function _s(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 vs(e){let t=ys("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 js(e){let t=e.match(/\bema\s*(\d+)\s*cross(?:es)?\s*(above|below)\s*ema\s*(\d+)\b/i);if(!t)return null;let r=Number(t[1]),n=t[2].toLowerCase(),o=Number(t[3]);if(!(r>0)||!(o>0)||r===o)return null;let s=/\b(exit\s+on\s+reverse|reverse\s+exit)\b/i.test(e);return{kind:"ema_cross",fast:r,slow:o,direction:n,reverse:s}}function Ns(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 Rs(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 Ms(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 Ls(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 Hs(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 Fs(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 Cs(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 sn(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 Ds({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"c",type:"input",field:"close"},{id:"emaLeft",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_left_period"}},{id:"emaRight",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_right_period"}},{id:"cross",type:"cross",direction:a.direction,left:"emaLeft",right:"emaRight"}],f={entryLong:null,entryShort:null,exitLong:null,exitShort:null};if(e==="long"?f.entryLong="cross":f.entryShort="cross",a.reverse){let u=a.direction==="above"?"below":"above";l.push({id:"crossRev",type:"cross",direction:u,left:"emaLeft",right:"emaRight"}),e==="long"?f.exitLong="crossRev":f.exitShort="crossRev"}return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{ema_left_period:sn(a.fast),ema_right_period:sn(a.slow)},nodes:l,rules:f,risk:{...n,expiresAt:o}}}function Us({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"c",type:"input",field:"close"},{id:"rsi",type:"indicator",indicator:"rsi",input:"c",period:a.period},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"rsi",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function qs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"fr",type:"input",field:"fundingRate"},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"fr",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function Bs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"oi",type:"input",field:"openInterest"},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"oi",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}var zs=Object.freeze({funding:"fundingRate",open_interest:"openInterest",premium:"premium",oi_delta:"oiDelta",book_imbalance:"bookImbalance"});function Vs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let f=[{id:"sig_input",type:"input",field:zs[a.kind]},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"sig_input",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:f,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function Qt(e,t={}){if(typeof e!="string")throw new K("prompt must be a string");if(e.length>1e3)throw new K("prompt length must be <= 1000");if(!Ts(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=ks;if("expiresInMs"in t){if(!Number.isInteger(t.expiresInMs))throw new K("expiresInMs must be an integer");if(n=t.expiresInMs,n<xs||n>Ss)throw new K("expiresInMs must be between 1h and 30d")}if(bs.test(e))throw new K(`prompt appears to contain secrets and is rejected. ${Ne}`);let o=As(e);if(!o)throw new K(`empty prompt. ${Ne}`);if(_s(o))throw new K(`duplicate interval or risk clause. ${Ne}`);let s=Os(o),i=Ps(o),a=$s(o);if(!s||!i||!a)throw new K(`could not parse side/coin/interval. ${Ne}`);let l=Is(o);if(!(l.maxLeverage>0)||l.maxLeverage>50)throw new K("leverage out of range");if(!(l.positionSizePct>0)||l.positionSizePct>100)throw new K("position size out of range");let f=r+n,u=vs(o),c=`Draft ${i} ${s}`.slice(0,100),d=js(o),m=Ns(o),p=Rs(o),w=Ms(o),g=Ls(o),S=Hs(o),v=Fs(o),O=[d,m,p,w,g,S,v].filter(Boolean);if(O.length!==1)throw new K(`unsupported or ambiguous prompt. ${Ne}`);if(!Cs(o,O[0]))throw new K(`unsupported or ambiguous prompt. ${Ne}`);let x,R=O[0],P={side:s,coin:i,interval:a,risk:l,expiresAt:f,id:u,name:c,spec:R};R.kind==="ema_cross"?x=Ds(P):R.kind==="rsi"?x=Us(P):R.kind==="open_interest"?x=Bs(P):R.kind==="funding"?x=qs(P):x=Vs(P);let h=at(x,{nowMs:r});if(!h.ok)throw new K(`draft failed validation: ${h.errors.map(M=>M.message).join("; ")}`);return Xt(Z(x,{nowMs:r}))}import de from"node:fs";import lt from"node:path";var tr=1,Js=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function ut(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ie(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Gs(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Re(e,t="record"){if(Array.isArray(e)){e.forEach((r,n)=>Re(r,`${t}[${n}]`));return}if(ut(e))for(let[r,n]of Object.entries(e)){let o=Gs(r);if(Js.some(s=>o.includes(s)))throw new Error(`shadow-store: forbidden secret-like field at ${t}.${r}`);Re(n,`${t}.${r}`)}}function Ks(e){if(typeof e!="string"||!e||!lt.isAbsolute(e))throw new Error("shadow-store: path must be an absolute path")}function an(e){let t;try{t=de.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 Ys(){return{version:tr,runners:[]}}function cn(e,t){let r;try{r=JSON.parse(e)}catch{throw new Error("shadow-store: malformed JSON")}if(!ut(r))throw new Error("shadow-store: malformed JSON root");if(r.version!==tr)throw new Error(`shadow-store: unsupported version ${r.version}`);if(!Array.isArray(r.runners))throw new Error("shadow-store: runners must be an array");return Re(r,lt.basename(t)),{version:tr,runners:r.runners.map(n=>ie(n))}}function ln(e,t){Re(t,"store");let r=lt.dirname(e);de.mkdirSync(r,{recursive:!0,mode:448});let n=lt.join(r,`.shadow-store.${process.pid}.${Date.now()}.tmp`),o=`${JSON.stringify(t)}
|
|
3
|
-
`;try{de.writeFileSync(n,o,{mode:384,flag:"wx"}),de.renameSync(n,e);try{de.chmodSync(e,384)}catch{}}catch(s){try{de.unlinkSync(n)}catch{}throw s}}var er=new Map;function rr(e={}){let t=e.path;if(Ks(t),an(t),de.existsSync(t)?cn(de.readFileSync(t,"utf8"),t):ln(t,Ys()),er.has(t))return er.get(t);let r=!1,n=[];function o(){if(r)return;let p=n.shift();if(p){r=!0;try{let w=p.fn();r=!1,p.resolve(w),o()}catch(w){r=!1,p.reject(w),o()}}}function s(p){if(!r&&n.length===0){r=!0;try{return p()}finally{r=!1,queueMicrotask(o)}}return new Promise((w,g)=>{n.push({fn:p,resolve:w,reject:g}),queueMicrotask(o)})}function i(){return an(t),cn(de.readFileSync(t,"utf8"),t)}function a(p){ln(t,p)}function l(p){if(!ut(p)||typeof p.id!="string"||!p.id)throw new Error("shadow-store: create requires record with string id");Re(p,"record");let w=i();if(w.runners.some(S=>S.id===p.id))throw new Error(`shadow-store: runner id already exists: ${p.id}`);let g=ie(p);return w.runners.push(g),a(w),ie(g)}function f(p){let w=i().runners.find(g=>g.id===p);return w?ie(w):null}function u(){return i().runners.map(p=>ie(p))}function c(p,w){if(typeof w!="function")throw new Error("shadow-store: updater must be a function");let g=i(),S=g.runners.findIndex(x=>x.id===p);if(S<0)throw new Error(`shadow-store: runner not found: ${p}`);let v=ie(g.runners[S]),O=w(v);if(!ut(O)||O.id!==p)throw new Error("shadow-store: updater must return record with same id");return Re(O,"record"),g.runners[S]=ie(O),a(g),ie(g.runners[S])}function d(p){let w=i(),g=w.runners.findIndex(v=>v.id===p);if(g<0)throw new Error(`shadow-store: runner not found: ${p}`);let S=ie(w.runners[g]);return S.status!=="stopped"&&(S.status="stopped",w.runners[g]=S,a(w)),ie(w.runners[g])}let m={create(p){return s(()=>l(p))},get(p){return f(p)},list(){return u()},update(p,w){return s(()=>c(p,w))},stop(p){return s(()=>d(p))}};return er.set(t,m),m}import{createHash as sr}from"node:crypto";function nr(e){return e==null?e:JSON.parse(JSON.stringify(e))}function or(e){return Array.isArray(e)?e.map(or):e&&typeof e=="object"?Object.fromEntries(Object.keys(e).sort().map(t=>[t,or(e[t])])):e}function fn(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("shadow-runner: record must be an object");return sr("sha256").update(JSON.stringify(or(e))).digest("hex")}function Ws(e,t,r,n,o){return sr("sha256").update(`${e}|${t}|${r}|${n}|${o}`).digest("hex")}function Zs(e,t,r,n){return sr("sha256").update(`shadow|${e}|${t}|${r}|${n??""}`).digest("hex")}function Xs(e){return e==="entryLong"||e==="exitShort"?"buy":e==="entryShort"||e==="exitLong"?"sell":e}function un(e){return e==="entryLong"||e==="entryShort"}function ft({storePath:e,clock:t=Date.now}={}){if(typeof e!="string"||!e)throw new Error("shadow-runner: storePath required");let r=rr({path:e});function n({strategy:l,evidenceId:f=null}={}){let u=W(l),c=f==null?null:String(f),d=r.list().filter(S=>S.status==="running"&&S.strategyHash===u.strategyHash&&S.compilerHash===u.compilerHash&&S.evidenceId===c).sort((S,v)=>S.createdAt-v.createdAt||S.id.localeCompare(v.id))[0];if(d)return nr(d);let m=t(),p=Zs(m,u.strategyHash,u.compilerHash,c),w=r.get(p);if(w)return nr(w);let g={id:p,strategy:nr(u.strategy),strategyHash:u.strategyHash,compilerHash:u.compilerHash,evidenceId:c,status:"running",cursor:null,intendedOrders:[],fills:[],missedFills:[],markouts:[],createdAt:m,updatedAt:m,position:null,cooldownBarsRemaining:0,cooldownStartT:null,lastProcessedBarIndex:-1};return r.create(g)}function o(l){return r.get(l)}function s(){return r.list()}function i(l){return r.stop(l)}function a(l,f,{markoutHorizons:u=[1,4,12]}={}){if(!Array.isArray(f))throw new TypeError("shadow-runner: bars must be an array");return r.update(l,c=>{if(c.status!=="running")throw new Error("shadow-runner: runner is stopped");if(f.length===0)return c;let m=W(c.strategy).evaluateAll(f),p=new Map;for(let y=0;y<f.length;y++)p.set(f[y].t,y);let w=c.cursor,g=[];for(let y=0;y<f.length;y++){let $=f[y].t;(w==null||$>w)&&g.push(y)}if(g.length===0)return c;let S=new Map(c.intendedOrders.map(y=>[y.id,y])),v=new Set(c.fills.map(y=>y.orderId)),O=new Map(c.missedFills.map(y=>[y.orderId,y])),x=(y,$)=>`${y}|${$}`,R=new Map(c.markouts.map(y=>[x(y.orderId,y.horizon),y])),P=c.position?{...c.position}:null,h=Number.isInteger(c.cooldownBarsRemaining)?Math.max(0,c.cooldownBarsRemaining):0,M=Number.isFinite(c.cooldownStartT)?c.cooldownStartT:null;function D({action:y,signalBarT:$,signalIndex:_}){let C=Xs(y),L=Ws(c.id,c.strategyHash,$,C,y);if(S.has(L))return S.get(L);let j=_+1,A=j<f.length,N={id:L,action:y,type:y,side:C,signalBarT:$,fillBarT:A?f[j].t:null,status:A?"open":"missed"};return S.set(L,N),c.intendedOrders.push(N),N}function Y(y,$,_){if(v.has(y.id))return;let C={orderId:y.id,action:un(y.action)?"entry":"exit",side:y.side,price:$.o,barT:$.t,signalBarT:y.signalBarT,barIndex:_};if(c.fills.push(C),v.add(y.id),y.status="filled",y.fillBarT=$.t,O.has(y.id)&&(O.delete(y.id),c.missedFills=c.missedFills.filter(L=>L.orderId!==y.id)),un(y.action)){P={side:y.action==="entryLong"?"long":"short",entryOrderId:y.id,entryBarT:$.t,entryPrice:$.o,entryBarIndex:_};for(let L of u){let j=x(y.id,L);if(R.has(j))continue;let A={orderId:y.id,horizon:L,entryBarT:$.t,entryPrice:$.o,side:P.side,status:"pending",close:null,barT:null};R.set(j,A),c.markouts.push(A)}}else P=null,h=Number(c.strategy?.risk?.cooldownBars)||0,M=$.t}function k(y){if(v.has(y.id)||O.has(y.id))return;let $={orderId:y.id,action:y.action,side:y.side,signalBarT:y.signalBarT,status:"missed"};O.set(y.id,$),c.missedFills.push($),y.status="missed"}for(let y of c.intendedOrders){if(y.status==="filled"||v.has(y.id))continue;let $=p.get(y.signalBarT);if($==null)continue;let _=$+1;_<f.length&&(w==null||f[_].t>w)&&Y(y,f[_],_)}for(let y of g){let $=f[y],_=m[y].signals,C=P,L=A=>{if(P||h>0&&(M==null||$.t>=M))return;let I=D({action:A,signalBarT:$.t,signalIndex:y}),G=y+1;G<f.length?Y(I,f[G],G):k(I)},j=A=>{if(!P||P.side==="long"&&A!=="exitLong"||P.side==="short"&&A!=="exitShort")return;let N=D({action:A,signalBarT:$.t,signalIndex:y}),I=y+1;I<f.length?Y(N,f[I],I):k(N)};C?(_.exitLong&&j("exitLong"),_.exitShort&&j("exitShort")):_.entryLong&&_.entryShort||(_.entryLong&&L("entryLong"),_.entryShort&&L("entryShort")),h>0&&M!=null&&$.t>=M&&(h-=1,h===0&&(M=null)),c.cursor=$.t,c.lastProcessedBarIndex=y}for(let y of c.markouts){if(y.status!=="pending")continue;let $=c.fills.find(L=>L.orderId===y.orderId&&L.action==="entry");if(!$)continue;let _=p.get($.barT);if(_==null)continue;let C=_+y.horizon;if(C<f.length){y.close=f[C].c,y.barT=f[C].t,y.status="filled";let L=y.entryPrice;y.markout=y.side==="long"?(y.close-L)/L:(L-y.close)/L}}return c.position=P,c.cooldownBarsRemaining=h,c.cooldownStartT=M,c.updatedAt=t(),c})}return{start:n,step:a,list:s,get:o,stop:i}}import Qs from"node:os";import ei from"node:path";var ti=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Ge(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ri(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function ar(e){if(Array.isArray(e)){for(let t of e)ar(t);return}if(Ge(e))for(let[t,r]of Object.entries(e)){if(ti.some(n=>ri(t).includes(n)))throw new Error(`strategy service: secret-like field "${t}" is forbidden`);ar(r)}}function ni(e){if(!Ge(e))throw new TypeError("strategy input must be a plain object");return ar(e),e}function oi(e,t={}){if(t.nowMs!==void 0){if(!Number.isInteger(t.nowMs))throw new TypeError("nowMs must be an integer epoch milliseconds");return t.nowMs}let r=Date.now();if(e.nowMs===void 0||e.nowMs===null)return r;if(!Number.isInteger(e.nowMs))throw new TypeError("nowMs must be an integer epoch milliseconds");if(Math.abs(e.nowMs-r)>12e4)throw new Error("nowMs outside allowed wall-clock skew (120s); omit nowMs to use server time");return e.nowMs}async function ir(e,t,r,n){if(Array.isArray(t.bars))return t.bars;let o=ot(e.venue),s=r.fetchBars??o.fetchBars;if(typeof s!="function")throw new Error(`strategy venue ${o.id} does not support history`);r.signal?.throwIfAborted?.();let i=await s({coin:e.market.coin,interval:e.market.interval,count:t.count??1500,endTime:t.endTime??n},{signal:r.signal});r.signal?.throwIfAborted?.();let a=Array.isArray(i)?i:i?.bars;if(!Array.isArray(a))throw new Error("strategy history provider returned no bars");return a}function cr(e,t){let r=e.backtestOptions??{};if(!Ge(r))throw new TypeError("backtestOptions must be a plain object");return{...r,nowMs:t}}function dn(e,t,r,n,o={}){let s=e.evidenceOptions??{};if(!Ge(s))throw new TypeError("evidenceOptions must be a plain object");return{...s,...o,strategy:t,bars:r,backtestOptions:cr(e,n)}}function pn(){return ei.join(Qs.homedir(),".oracle","strategy-shadow.json")}function si(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 ii(e,t={},r={}){r.signal?.throwIfAborted?.();let n=ni(t),o=oi(n,r);if(e==="draft")return{strategy:Qt(n.prompt,{nowMs:o})};if(e==="validate"){let s=W(n.strategy);if(s.strategy.risk.expiresAt<=o)throw new Error("strategy is expired");return{valid:!0,strategy:s.strategy,strategyHash:s.strategyHash,compilerHash:s.compilerHash,compilerVersion:s.compilerVersion,requiredSeries:s.requiredSeries}}if(e==="backtest"||e==="evidence"){let s=W(n.strategy),i=await ir(s.strategy,n,r,o);Be(s,i);let a=rt(dn(n,s.strategy,i,o));return e==="evidence"?a:{backtest:fe(s.strategy,i,cr(n,o)),evidence:a}}if(e==="optimize"){let s=W(n.strategy),i=await ir(s.strategy,n,r,o);Be(s,i);let a=n.trainFraction,l=n.evidenceOptions?.trainFraction;if(a!=null&&l!=null&&a!==l)throw new TypeError("conflicting trainFraction controls are forbidden");let f=a??l??.7;if(typeof f!="number"||f<=0||f>=1)throw new TypeError("trainFraction must be in (0,1)");let u=i.slice(0,Math.floor(i.length*f)),c=n.options??{};if(!Ge(c))throw new TypeError("options must be a plain object");let d=Zt(s.strategy,u,{...c,...n.maxTrials==null?{}:{maxTrials:n.maxTrials},backtestOptions:cr(n,o)}),m=d.bestStrategy;return{strategy:m,optimization:d,evidence:rt(dn(n,m,i,o,{trainFraction:f}))}}if(e==="shadow"){let s=ft({storePath:r.storePath??pn(),clock:()=>o}),i=n.action;if(i==="start")return await s.start({strategy:n.strategy,evidenceId:n.evidenceId??n.evidence?.id??null});if(i==="list")return await s.list();if(i==="get")return await s.get(n.id);if(i==="stop")return await s.stop(n.id);if(i==="step"){let a=await s.get(n.id);if(!a)throw new Error(`shadow runner not found: ${n.id}`);let l=await ir(a.strategy,n,r,o);return Be(W(a.strategy),l),await s.step(n.id,l,n.stepOptions??{})}throw new Error(`unknown shadow action: ${i}`)}if(e==="prepare"){let s=W(n.strategy),i=ot(s.strategy.venue);if(typeof n.shadowId!="string"||!n.shadowId)throw new Error("strategy prepare requires a matching shadow runner id");let l=await ft({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!==s.strategyHash||l.compilerHash!==s.compilerHash)throw new Error("strategy prepare shadow runner does not match strategy artifacts");if(l.evidenceId!==n.evidence?.id)throw new Error("strategy prepare shadow runner does not match evidence artifact");let f=n.caps??si(s.strategy,o);return i.prepareIntent({strategy:s.strategy,evidence:n.evidence,shadow:{id:l.id,stateHash:fn(l),status:l.status,cursor:l.cursor,updatedAt:l.updatedAt},caps:f,nowMs:o,env:r.env??process.env})}throw new Error(`unknown strategy operation: ${e}`)}export{Nr as EVIDENCE_STATUSES,Yt as MAX_OPTIMIZER_TRIALS,ye as STRATEGY_COMPILER_HASH,$e as STRATEGY_COMPILER_VERSION,st as STRATEGY_VERSION,K as StrategyDraftError,Te as StrategyValidationError,Ie as applyParameterOverrides,Ht as assertEvidenceArtifact,It as atr,ds as attachDerivedSeries,fe as backtestStrategy,$t as bollinger,en as canonicalStrategyJson,W as compileStrategy,Lt as computeEvidenceArtifactId,ft as createShadowRunner,fs as deriveSeries,Qt as draftStrategyFromPrompt,De as ema,rt as evaluateEvidence,qt as fetchHyperliquidStrategyBars,Fr as intervalToMs,Pt as macd,Cr as normalizeHyperliquidCandles,Z as normalizeStrategy,rr as openShadowStore,Zt as optimizeStrategy,Ut as prepareStrategyLiveHandoff,ot as requireStrategyVenue,nt as resolveStrategyVenue,Ot as rsi,ii as runStrategyOperation,us as sampleLiveSeries,At as sma,Se as strategyHash,Yo as strategyVenues,at as validateStrategy};
|
|
1
|
+
import{createHash as ts}from"node:crypto";import{createHash as $n}from"node:crypto";import{types as de}from"node:util";import{AsyncLocalStorage as En}from"node:async_hooks";var xn=new En,Sn=["http","retry","shared"],kn=512;function Xe(e){let t=xn.getStore();if(!t||t.closed||!Sn.includes(e))return null;if(t.spans.length>=kn)return t.droppedSpans++,null;let r={stage:e,startMs:t.now()-t.start,durationMs:null,outcome:"pending",status:null};return t.spans.push(r),(n,o=null)=>{t.closed||r.durationMs!==null||(r.durationMs=Math.max(0,t.now()-t.start-r.startMs),r.outcome=n==="succeeded"?"succeeded":"failed",r.status=Number.isInteger(o)&&o>=100&&o<=599?o:null)}}import xe from"node:net";import An from"node:dns";var Tn=new Set(["localhost","metadata.google.internal","metadata.goog"]);function Qe(e){let t=String(e).toLowerCase().split("%")[0];if((t.match(/::/g)||[]).length>1)return null;let r=u=>{if(!u)return[];let c=u.split(":"),d=c.at(-1);if(d?.includes(".")){let m=d.split(".").map(Number);if(m.length!==4||m.some(p=>!Number.isInteger(p)||p<0||p>255))return null;c.splice(c.length-1,1,(m[0]<<8|m[1]).toString(16),(m[2]<<8|m[3]).toString(16))}return c.some(m=>!/^[0-9a-f]{1,4}$/.test(m))?null:c.map(m=>Number.parseInt(m,16))},[n,o]=t.split("::"),s=r(n),i=r(o);if(!s||!i)return null;let a=t.includes("::"),l=8-s.length-i.length;if(!a&&l!==0||a&&l<1)return null;let f=[...s,...Array(Math.max(0,l)).fill(0),...i];return f.length!==8?null:Uint8Array.from(f.flatMap(u=>[u>>8,u&255]))}function gt(e,t,r){let n=Math.floor(r/8),o=r%8;for(let i=0;i<n;i+=1)if(e[i]!==t[i])return!1;if(!o)return!0;let s=255<<8-o;return(e[n]&s)===(t[n]&s)}function bt(e){if(xe.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(xe.isIPv6(e)){let t=Qe(e);if(!t)return!1;let r=Qe("::ffff:0:0");return gt(t,r,96)?bt([...t.slice(12)].join(".")):gt(t,Qe("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([o,s])=>gt(t,Qe(o),s)):!1}return!1}function On(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=xe.isIP(r);return n!==0&&!bt(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function Et(e,{lookupFn:t=An.promises.lookup}={}){let r=On(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:xe.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=>!bt(o.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}async function xt({requireUndici:e=!1,importUndici:t=()=>import("undici")}={}){let r,n;try{let c=await t();r=c.Agent,n=c.fetch}catch(c){if(e)throw new Error(`egress-guard: untrustedUrl pinning requires the undici package, which failed to load: ${c?.message||c}`);return null}if(typeof r!="function"||typeof n!="function"){if(e)throw new Error("egress-guard: untrustedUrl pinning requires undici's Agent and fetch exports, which were not found on the imported module");return null}let o=c=>String(c).toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,""),s=new Map,i=c=>(Array.isArray(c)?c:[c]).map(d=>typeof d=="string"?{address:d}:d).filter(d=>d&&d.address).map(d=>({address:d.address,family:d.family||(xe.isIPv6(d.address)?6:4)})),a=(c,d,m)=>{s.set(o(c),i(typeof d=="string"?[{address:d,family:m}]:d))},l=c=>{let d=o(c);if(xe.isIP(d))return[{address:d,family:xe.isIPv6(d)?6:4}];let m=s.get(d);if(!m||!m.length)throw new Error(`refused: unpinned host ${c} during pinned fetch`);return m},f=new r({connect:{lookup(c,d,m){let p;try{p=l(c)}catch(w){return m(w)}return d?.all?m(null,p):m(null,p[0].address,p[0].family)}}}),u=Pn((c,d={})=>n(c,{...d,dispatcher:f}),a);return{dispatcher:f,fetch:u,pin:a,resolve:l,async close(){try{await f.destroy()}catch{}}}}var St=Symbol.for("oracle.egressGuard.pinCapableFetch");function Pn(e,t){if(typeof e!="function")throw new Error("markPinCapableFetch: fetchImpl must be a function");if(typeof t!="function")throw new Error("markPinCapableFetch: pin must be a function");return e[St]=Object.freeze({pin:t}),e}function kt(e){return typeof e=="function"&&typeof e[St]?.pin=="function"}function pr(e,t,r){if(!kt(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[St].pin(t,r)}var In=new Set([408,425,429,500,502,503,504]),mr=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),_n=2,hr=4e3,vn=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"aborted")?.get,jn=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"reason")?.get,Nn=AbortSignal.prototype.throwIfAborted,Rn=EventTarget.prototype.addEventListener,yr=EventTarget.prototype.removeEventListener,wr=typeof AbortSignal.any=="function"?AbortSignal.any.bind(AbortSignal):null,De=e=>e?vn.call(e):!1,Mn=e=>e?jn.call(e):void 0,Ln=new Set([301,302,303,307,308]),tt=3,xi=64*1024,fe=Object.freeze({depth:32,nodes:1e4,fields:1e4,arrayLength:1e4,bytes:1024*1024});function V(e){return he(`HTTP JSON body refused: ${e}`)}function Hn(e){return["isArgumentsObject","isArrayBuffer","isAnyArrayBuffer","isArrayBufferView","isBoxedPrimitive","isDataView","isDate","isExternal","isGeneratorObject","isKeyObject","isCryptoKey","isMap","isMapIterator","isModuleNamespaceObject","isNativeError","isPromise","isRegExp","isSet","isSetIterator","isTypedArray","isWeakMap","isWeakSet"].some(t=>typeof de[t]=="function"&&de[t](e))}function Fn(e){let t=[],r=0,n=0,o=0,s=0,i=new WeakSet,a=u=>{if(r+=Buffer.byteLength(u,"utf8"),r>fe.bytes)throw V("serialized byte limit exceeded");t.push(u)},l=u=>{if(Buffer.byteLength(u,"utf8")>fe.bytes)throw V("serialized byte limit exceeded");return JSON.stringify(u)},f=(u,c)=>{if(n+=1,n>fe.nodes)throw V("node limit exceeded");if(c>fe.depth)throw V("depth limit exceeded");if(u===null){a("null");return}if(typeof u=="string"){a(l(u));return}if(typeof u=="boolean"){a(u?"true":"false");return}if(typeof u=="number"){if(!Number.isFinite(u))throw V("non-finite number");a(Object.is(u,-0)?"0":String(u));return}if(typeof u!="object")throw V("unsupported non-JSON value");if(de.isProxy(u))throw V("proxy value");if(Hn(u))throw V("unsupported exotic object");if(i.has(u))throw V("cyclic value");i.add(u);try{if(Object.getOwnPropertySymbols(u).length>0)throw V("symbol-keyed fields are unsupported");if(Array.isArray(u)){let p=Object.getPrototypeOf(u),w=0;for(;p!==null;){if(de.isProxy(p))throw V("proxy array prototype");if(w+=1,w>fe.depth)throw V("array prototype depth limit exceeded");p=Object.getPrototypeOf(p)}if(u.length>fe.arrayLength)throw V("array length limit exceeded");for(let S=0;S<u.length;S+=1){let j=Object.getOwnPropertyDescriptor(u,String(S));if(!j||!Object.hasOwn(j,"value")||j.enumerable!==!0)throw V("array entries must be dense enumerable own data")}let g=0;for(let S in u){if(s+=1,s>fe.fields)throw V("enumeration limit exceeded");if(Object.hasOwn(u,S)&&(g+=1,g>u.length))throw V("named array fields are unsupported")}if(g!==u.length)throw V("array entries must be dense enumerable own data");a("[");for(let S=0;S<u.length;S+=1)S&&a(","),f(Object.getOwnPropertyDescriptor(u,String(S)).value,c+1);a("]");return}let d=Object.getPrototypeOf(u);if(d!==Object.prototype&&d!==null)throw V("non-plain object");let m=[];for(let p in u){if(s+=1,s>fe.fields)throw V("enumeration limit exceeded");if(!Object.hasOwn(u,p))continue;if(o+=1,o>fe.fields)throw V("field limit exceeded");let w=Object.getOwnPropertyDescriptor(u,p);if(!w||!Object.hasOwn(w,"value")||w.enumerable!==!0)throw V("object fields must be enumerable own data");m.push([p,w.value])}a("{");for(let p=0;p<m.length;p+=1)p&&a(","),a(l(m[p][0])),a(":"),f(m[p][1],c+1);a("}")}finally{i.delete(u)}};return f(e,0),t.join("")}function Cn(e){let t=Object.create(null);if(e==null)return t;if(typeof e!="object"&&typeof e!="function")throw new TypeError("HTTP headers must be an object");if(de.isProxy(e))throw new TypeError("HTTP headers must not be a proxy");if(Object.getOwnPropertySymbols(e).length>0)throw new TypeError("HTTP headers must not contain symbol fields");let r=new Set;for(let n of Object.keys(e)){if(!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/u.test(n))throw new TypeError("HTTP header names must be valid tokens");let o=n.toLowerCase();if(r.has(o))throw new TypeError("HTTP headers contain a duplicate canonical name");r.add(o);let s=Object.getOwnPropertyDescriptor(e,n);if(!s||!Object.hasOwn(s,"value"))throw new TypeError("HTTP headers must contain own data properties");let i=s.value;if(i==null||["object","function","symbol"].includes(typeof i))throw new TypeError("HTTP header values must be scalar");t[n]=String(i)}return t}function Dn(){return Object.assign(Object.create(null),{Accept:"application/json"})}function Un(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 qn(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}var At=new Map,gr=new WeakMap,br=1;function et(e){if((typeof e!="object"||e===null)&&typeof e!="function")return`${typeof e}:${String(e)}`;let t=gr.get(e);return t||(t=br,br+=1,gr.set(e,t)),`reference:${t}`}var Bn=new Set(["eth_blockNumber","eth_call","eth_chainId","eth_estimateGas","getHealth","minimumLedgerSlot","net_version","simulateTransaction","web3_clientVersion"]),zn=new Set(["allMids","l2Book","outcomeMeta","spotClearinghouseState","userFills","meta","metaAndAssetCtxs","perpDexs","candleSnapshot","fundingHistory","openOrders","frontendOpenOrders","clearinghouseState","spotMeta","validatorSummaries","delegatorSummary","delegations","delegatorRewards","delegatorHistory","maxBuilderFee"]);function Er(e){if(!e||typeof e!="object"||Array.isArray(e)||!Object.hasOwn(e,"jsonrpc")||!Object.hasOwn(e,"method")||e.jsonrpc!=="2.0")return!1;let t=typeof e.method=="string"?e.method:"";return t?Bn.has(t)||/^get[A-Z0-9_]/u.test(t)||/^is[A-Z0-9_]/u.test(t)||/^eth_get[A-Z0-9_]/u.test(t):!1}function xr(e,t){if(e==="GET"&&t==null)return!0;if(e!=="POST"||t==null)return!1;let r=t;if(typeof t=="string")try{r=JSON.parse(t)}catch{return!1}if(Array.isArray(r))return r.length>0&&r.every(Er);if(!r||typeof r!="object")return!1;if(Object.hasOwn(r,"jsonrpc")||Object.hasOwn(r,"method"))return Er(r);let n=Object.hasOwn(r,"type")?r.type:null;return typeof n=="string"&&zn.has(n)&&(!Object.hasOwn(r,"action")||r.action==null)&&(!Object.hasOwn(r,"signature")||r.signature==null)&&(!Object.hasOwn(r,"nonce")||r.nonce==null)}function Vn(e,t,r,n={},o=null){let s=$n("sha256"),i=(l,f)=>{let u=String(f);s.update(String(Buffer.byteLength(l,"utf8"))).update(":").update(l),s.update("=").update(String(Buffer.byteLength(u,"utf8"))).update(":").update(u).update(`
|
|
2
|
+
`)};i("method",e),i("url",t),Object.keys(r||{}).map((l,f)=>({name:l.toLowerCase(),order:f,value:String(r[l])})).sort((l,f)=>l.name.localeCompare(f.name)||l.order-f.order).forEach((l,f)=>{i(`header-name-${f}`,l.name),i(`header-value-${f}`,l.value)}),i("body",o??"-");for(let l of["untrustedUrl","maxResponseBytes","sameOriginRedirectsOnly","redirectPolicy","maxRedirects","timeoutMs","retries","fetchImpl","realFetch","lookupFn","importUndici","validateResponse"])i(`context-${l}`,n[l]??"-");return s.digest("hex")}function Jn(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,hr):Math.min(250*2**e,hr)+Math.floor(Math.random()*100)}var Gn=e=>new Promise(t=>setTimeout(t,e));function he(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function Tt(e,t,r){return he(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function Se(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function Kn(e){return e?e.byteLength??e.length??0:0}async function Yn(e,t,{url:r,truncate:n=!1,onOversize:o}={}){if(t==null)return await e.text();let s=Number(e.headers?.get?.("content-length"));if(Number.isFinite(s)&&s>t&&(Se(e),!n))throw Tt(r,`content-length ${s}`,t);let i=e.body?.getReader?.();if(!i){let c=await e.text(),d=Buffer.byteLength(c,"utf8");if(d>t){if(!n)throw Tt(r,`body ${d} bytes`,t);return Buffer.from(c,"utf8").subarray(0,t).toString("utf8")}return c}let a=[],l=0,f=!1;try{for(;;){let{value:c,done:d}=await i.read();if(d)break;if(c&&(a.push(Buffer.from(c)),l+=Kn(c),l>t)){f=!0;break}}}finally{if(f)try{await i.cancel()}catch{}try{i.releaseLock?.()}catch{}}if(f&&(typeof o=="function"&&o(),!n))throw Tt(r,`streamed ${l} bytes`,t);let u=Buffer.concat(a);return(f?u.subarray(0,t):u).toString("utf8")}function Wn(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:s,lookupFn:i,realFetch:a,untrustedUrl:l=!1,maxResponseBytes:f=null,sameOriginRedirectsOnly:u=!1,importUndici:c,validateResponse:d,signal:m,redirectPolicy:p="follow",maxRedirects:w=tt}){let g=null,S=t,j=i?{lookupFn:i}:{};if(l&&!a&&!kt(S))throw he(`HTTP refused ${e}: untrustedUrl requires a pin-capable fetchImpl (see markPinCapableFetch in egress-guard.mjs) or no fetchImpl override so Oracle can pin the connection itself`);let P=new AbortController,x=setTimeout(()=>P.abort(),s),R=m?wr?wr([m,P.signal]):m:P.signal,$=async(h,{status:M=null}={})=>{let D=await Et(h,j);if(!D.ok)throw he(M==null?`HTTP refused ${h}: ${D.error}`:`HTTP redirect to ${h} ${D.error}`,M==null?{}:{status:M});let K=new URL(h).hostname;if(a){if(g&&(await g.close(),g=null),!g)try{g=await xt({requireUndici:!0,...c?{importUndici:c}:{}})}catch(k){throw he(M==null?`HTTP refused ${h}: ${k?.message||k}`:`HTTP redirect to ${h} refused: ${k?.message||k}`,M==null?{}:{status:M})}g.pin(K,D.addresses),S=g.fetch}else pr(S,K,D.addresses);return D};try{let h=String(e),M=Object.assign(Object.create(null),n||{});l&&await $(h);for(let D=0;D<=w;D+=1){let K=Object.assign(Object.create(null),{method:r,headers:M,body:o,signal:R,redirect:"manual",dispatcher:void 0}),k=await S(h,K);if((p==="error"||w===0)&&k.status>=300&&k.status<400)throw Se(k),he(`HTTP ${k.status} ${r} redirect refused`,{status:k.status,redirectRefused:!0});if(Ln.has(k.status)){let _=u===!0&&r==="POST"&&[307,308].includes(k.status)&&xr(r,o);if(r!=="GET"&&r!=="HEAD"&&!_){Se(k);let T=new Error(`HTTP ${k.status} ${r} ${h} redirected non-idempotent request`);throw T.status=k.status,T}if(D===w)throw Se(k),he(`HTTP ${k.status} ${r} redirect budget exhausted`,{status:k.status,redirectRefused:!0});let C=k.headers?.get?.("location"),L;try{L=Un(C,h)}catch(T){throw Se(k),T}let N=!qn(L,h);if(Se(k),N&&r==="POST"){let T=new Error(`HTTP ${k.status} ${r} cross-origin redirect refused`);throw T.status=k.status,T}if(N&&u){let T=new Error(`HTTP ${k.status} ${r} cross-origin redirect refused`);throw T.status=k.status,T.retryable=!1,T}if(N&&(M=Dn(M)),l)await $(L,{status:k.status});else if(N){let T=await Et(L,j);if(!T.ok){let v=new Error(`HTTP redirect from ${h} ${T.error}`);throw v.status=k.status,v.retryable=!1,v}a&&T.addresses?.length&&(g||(g=await xt(c?{importUndici:c}:{})),g&&(g.pin(new URL(L).hostname,T.addresses),S=g.fetch))}h=L;continue}if(typeof d=="function")try{await d(k,{url:h})}catch(_){throw Se(k),he(_?.message||String(_))}let y=await Yn(k,f,{url:h,onOversize:()=>P.abort()}),I=Wn(y);if(!k.ok){let _=new Error(`HTTP ${k.status} ${r} ${h}`);throw _.status=k.status,_.retryAfter=k.headers?.get?.("retry-after")??null,_.body=I??y.slice(0,300),_}return I??y}throw new Error(`HTTP redirect loop for ${e}`)}catch(h){if(P.signal.aborted&&!De(m)){let M=h&&(typeof h=="object"||typeof h=="function")&&!de.isProxy(h)?h:null,D=M?Object.getOwnPropertyDescriptor(M,"oversize"):null;if(!(D&&Object.hasOwn(D,"value")&&D.value===!0))try{if(!M)throw new TypeError("unsafe rejection");Object.defineProperties(M,{oracleTimeout:{value:!0,enumerable:!1},retryable:{value:!1,enumerable:!1}})}catch{let k=new Error("HTTP request timed out");throw Object.defineProperties(k,{oracleTimeout:{value:!0,enumerable:!1},retryable:{value:!1,enumerable:!1}}),k}}throw h}finally{clearTimeout(x),g&&await g.close()}}async function Sr(e,t={}){if(t!=null&&typeof t!="object"&&typeof t!="function")throw new TypeError("HTTP options must be an object");if(t!=null&&de.isProxy(t))throw new TypeError("HTTP options must not be a proxy");let r=new Set(["body","dedupe","fetchImpl","headers","importUndici","lookupFn","maxRedirects","maxResponseBytes","method","redirectPolicy","retries","sameOriginRedirectsOnly","signal","timeoutMs","untrustedUrl","validateResponse"]);if(t!=null){if(Object.getOwnPropertySymbols(t).length>0)throw new TypeError("HTTP options contain unknown fields");for(let v of Object.getOwnPropertyNames(t)){let O=Object.getOwnPropertyDescriptor(t,v);if(!(v==="toJSON"&&O&&Object.hasOwn(O,"value")&&O.value===void 0)){if(!r.has(v))throw new TypeError("HTTP options contain unknown fields");if(!O||!O.enumerable||!Object.hasOwn(O,"value"))throw new TypeError("HTTP options must contain enumerable own data properties")}}}let n=v=>{if(t==null||!Object.hasOwn(t,v))return;let O=Object.getOwnPropertyDescriptor(t,v);if(!O||!Object.hasOwn(O,"value"))throw new TypeError("HTTP options must contain own data properties");return O.value};if(typeof e!="string"||e.length===0||e.length>8192)throw new TypeError("HTTP URL must be a bounded string");let o=n("method");if(o!==void 0&&(typeof o!="string"||!/^[A-Za-z]+$/u.test(o)))throw new TypeError("HTTP method must be a string token");let s=n("timeoutMs");if(s!==void 0&&(!Number.isInteger(s)||s<1||s>12e4))throw new TypeError("HTTP timeoutMs must be a bounded integer");let i=n("retries");if(i!==void 0&&(!Number.isInteger(i)||i<0||i>10))throw new TypeError("HTTP retries must be a bounded integer");let a=n("redirectPolicy");if(a!==void 0&&a!=="follow"&&a!=="error")throw new TypeError('HTTP redirectPolicy must be "follow" or "error"');let l=n("maxRedirects");if(l!==void 0&&(!Number.isInteger(l)||l<0||l>tt))throw new TypeError(`HTTP maxRedirects must be an integer from 0 through ${tt}`);if(a==="error"&&l!==void 0&&l!==0)throw new TypeError('HTTP redirectPolicy "error" requires maxRedirects 0 when supplied');let f=a??"follow",u=f==="error"?0:l??tt;for(let v of["dedupe","untrustedUrl","sameOriginRedirectsOnly"]){let O=n(v);if(O!==void 0&&typeof O!="boolean")throw new TypeError(`HTTP ${v} must be boolean`)}let c=n("maxResponseBytes");if(c!==void 0&&(!Number.isInteger(c)||c<1||c>64*1024*1024))throw new TypeError("HTTP maxResponseBytes must be a bounded integer");let d=n("signal");if(d!==void 0){if(de.isProxy(d)||!(d instanceof AbortSignal))throw new TypeError("HTTP signal must be a native AbortSignal");try{De(d)}catch{throw new TypeError("HTTP signal must be a native AbortSignal")}}for(let v of["importUndici","lookupFn","validateResponse"]){let O=n(v);if(O!==void 0&&typeof O!="function")throw new TypeError(`HTTP ${v} must be a function`)}let m=n("fetchImpl"),p=m||globalThis.fetch;if(typeof p!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let w=s??12e3,g=(o||"GET").toUpperCase(),S=n("headers"),j=Cn(S),P=Object.assign(Object.create(null),j);Object.keys(P).some(v=>v.toLowerCase()==="accept")||(P.Accept="application/json");let x=n("body");x!=null&&typeof x!="string"&&(Object.keys(P).find(O=>O.toLowerCase()==="content-type")||(P["Content-Type"]="application/json"),x=Fn(x));let R=i??_n,$=n("lookupFn"),h=!m,M=n("untrustedUrl")===!0,D=n("sameOriginRedirectsOnly")===!0,K=n("importUndici"),k=n("validateResponse"),y=d,I=c??null,_=async()=>{let v;for(let O=0;O<=R;O++){y&&Nn.call(y);let X=Xe("http");try{let Z=await Zn(e,{fetchImpl:p,method:g,headers:P,body:x,timeoutMs:w,lookupFn:$,realFetch:h,untrustedUrl:M,maxResponseBytes:I,sameOriginRedirectsOnly:D,importUndici:K,validateResponse:k,signal:y,redirectPolicy:f,maxRedirects:u});return X?.("succeeded"),Z}catch(Z){v=Z;let te=be=>{if(!Z||typeof Z!="object"&&typeof Z!="function"||de.isProxy(Z))return;let le=Object.getOwnPropertyDescriptor(Z,be);return le&&Object.hasOwn(le,"value")?le.value:void 0},ce=te("status");X?.("failed",ce);let We=te("oracleTimeout")===!0||te("name")==="AbortError"||te("name")==="TimeoutError"||De(y),Ze=new Set([408,425,429]),ur=te("retryable")===!1?!1:ce!=null?Ze.has(ce)||In.has(ce)&&mr.has(g):!We&&mr.has(g);if(O===R||!ur)throw Z;let Le=Jn(O,te("retryAfter")),ht=Xe("retry"),He=!1;try{y?await new Promise((be,le)=>{let Pe,Ee=()=>{clearTimeout(Pe),yr.call(y,"abort",Ee),le(Mn(y)||new DOMException("Aborted","AbortError"))};if(De(y)){Ee();return}Pe=setTimeout(()=>{yr.call(y,"abort",Ee),be()},Le),Rn.call(y,"abort",Ee,{once:!0}),De(y)&&Ee()}):await Gn(Le),He=!0}finally{ht?.(He?"succeeded":"failed")}}}throw v};if(!(n("dedupe")!==!1&&!y&&xr(g,x)))return _();let L=Vn(g,e,P,{untrustedUrl:M,maxResponseBytes:I,sameOriginRedirectsOnly:D,redirectPolicy:f,maxRedirects:u,timeoutMs:w,retries:R,fetchImpl:et(p),realFetch:h,lookupFn:et($),importUndici:et(K),validateResponse:et(k)},x),N=At.get(L);if(N){let v=Xe("shared");try{let O=await N;return v?.("succeeded"),O}catch(O){throw v?.("failed"),O}}let T=_().finally(()=>At.delete(L));return At.set(L,T),T}import{types as kr}from"node:util";function Xn(e){if(!e||typeof e!="object"||kr.isProxy(e)||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function rt(e,t="provider response",r=0){if(r>64)throw new Error(`${t} exceeds the JSON nesting bound`);if(e===null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))return e;if(Array.isArray(e)){if(kr.isProxy(e)||e.length>1e5)throw new Error(`${t} contains an invalid array`);let o=new Array(e.length);for(let s=0;s<e.length;s+=1){let i=Object.getOwnPropertyDescriptor(e,String(s));if(!i||!Object.hasOwn(i,"value"))throw new Error(`${t} arrays must contain dense own data`);o[s]=rt(i.value,t,r+1)}return o}if(!Xn(e))throw new Error(`${t} contains a non-JSON value`);let n=Object.create(null);for(let o of Object.keys(e)){let s=Object.getOwnPropertyDescriptor(e,o);if(!s||!Object.hasOwn(s,"value"))throw new Error(`${t} objects must contain own data`);n[o]=rt(s.value,t,r+1)}return n}var Qn="https://api.hyperliquid.xyz/info",eo="https://api.hyperliquid-testnet.xyz/info";function to({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"?eo:Qn}async function Ue(e,t={}){if(!e||!e.type)throw new Error("hlInfo requires body.type");let r=to(t);return rt(await Sr(r,{method:"POST",body:e,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs,maxResponseBytes:t.maxResponseBytes,sameOriginRedirectsOnly:t.sameOriginRedirectsOnly}),"hyperliquid info response")}async function Ar(e,t={}){if(!e)throw new Error("hlL2Book requires coin");return Ue({type:"l2Book",coin:String(e)},t)}async function Tr(e={}){return Ue({type:"meta"},e)}async function Or(e={}){let t={type:"metaAndAssetCtxs"};return e.dex&&(t.dex=e.dex),Ue(t,e)}async function Pr({coin:e,interval:t="1h",startTime:r,endTime:n},o={}){if(!e)throw new Error("hlCandleSnapshot requires coin");let s={type:"candleSnapshot",req:{coin:String(e),interval:t,startTime:r??Date.now()-24*3600*1e3,endTime:n??Date.now()}};return Ue(s,o)}async function $r({coin:e,startTime:t,endTime:r},n={}){if(!e)throw new Error("hlFundingHistory requires coin");return Ue({type:"fundingHistory",coin:String(e),startTime:t??Date.now()-24*3600*1e3,endTime:r??Date.now()},n)}function Be(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 ye(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("period must be a positive integer")}function ro(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 Ot(e,t){Be(e),ye(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 qe(e,t){Be(e),ye(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=0;for(let i=0;i<t;i++)n+=e[i];let o=n/t;r[t-1]=o;let s=2/(t+1);for(let i=t;i<e.length;i++)o=s*e[i]+(1-s)*o,r[i]=o;return r}function Pt(e,t){Be(e),ye(t);let r=new Array(e.length).fill(null);if(e.length<=t)return r;let n=0,o=0;for(let a=1;a<=t;a++){let l=e[a]-e[a-1];l>=0?n+=l:o-=l}let s=n/t,i=o/t;r[t]=Ir(s,i);for(let a=t+1;a<e.length;a++){let l=e[a]-e[a-1],f=l>0?l:0,u=l<0?-l:0;s=(s*(t-1)+f)/t,i=(i*(t-1)+u)/t,r[a]=Ir(s,i)}return r}function Ir(e,t){return e===0&&t===0?50:t===0?100:e===0?0:100-100/(1+e/t)}function $t(e,t={}){Be(e);let r=t.fastPeriod,n=t.slowPeriod,o=t.signalPeriod;if(ye(r),ye(n),ye(o),r>=n)throw new TypeError("fastPeriod must be < slowPeriod");let s=qe(e,r),i=qe(e,n),a=new Array(e.length).fill(null);for(let c=0;c<e.length;c++)s[c]!=null&&i[c]!=null&&(a[c]=s[c]-i[c]);let l=new Array(e.length).fill(null),f=new Array(e.length).fill(null),u=[];for(let c=0;c<a.length;c++)a[c]!=null&&u.push(c);if(u.length>=o){let c=0;for(let w=0;w<o;w++)c+=a[u[w]];let d=c/o,m=u[o-1];l[m]=d,f[m]=a[m]-d;let p=2/(o+1);for(let w=o;w<u.length;w++){let g=u[w];d=p*a[g]+(1-p)*d,l[g]=d,f[g]=a[g]-d}}return{line:a,signal:l,histogram:f}}function It(e,t={}){Be(e);let r=t.period,n=t.stdDev;if(ye(r),typeof n!="number"||!Number.isFinite(n)||n<=0)throw new TypeError("stdDev must be a finite number > 0");let o=new Array(e.length).fill(null),s=new Array(e.length).fill(null),i=new Array(e.length).fill(null);if(e.length<r)return{upper:s,middle:o,lower:i};let a=0,l=0;for(let f=0;f<e.length;f++){let u=e[f];if(a+=u,l+=u*u,f>=r){let c=e[f-r];a-=c,l-=c*c}if(f>=r-1){let c=a/r,d=l/r-c*c;d<0&&d>-1e-12&&(d=0);let m=Math.sqrt(d);o[f]=c,s[f]=c+n*m,i[f]=c-n*m}}return{upper:s,middle:o,lower:i}}function _t(e,t){ro(e),ye(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=new Array(e.length);for(let i=0;i<e.length;i++){let a=e[i];if(i===0)n[i]=a.h-a.l;else{let l=e[i-1].c;n[i]=Math.max(a.h-a.l,Math.abs(a.h-l),Math.abs(a.l-l))}}let o=0;for(let i=0;i<t;i++)o+=n[i];let s=o/t;r[t-1]=s;for(let i=t;i<e.length;i++)s=(s*(t-1)+n[i])/t,r[i]=s;return r}import{createHash as no}from"node:crypto";var vt=3,oo="7477966facc4ef928a94e6221c8fd238eef4fcbeec46b96ae1b89178e13c2d5f",so="68f5b412a9975f04024cf9b9b6209b4bccedd52f176e95f34f786b3f53479c6a",io="967fd45ecddd0d59ac0f662fe92ea813c32620ba751f249b4ace6cb6b809fb5e",_r=no("sha256").update(JSON.stringify({version:vt,compilerSourceHash:oo,indicatorsSourceHash:so,schemaSourceHash:io})).digest("hex");var Ie=vt,we=_r,ao=Object.freeze({open:"o",high:"h",low:"l",close:"c",volume:"v",fundingRate:"fundingRate",openInterest:"openInterest",premium:"premium",oiDelta:"oiDelta",bookImbalance:"bookImbalance"}),co=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 Q(e){return typeof e=="number"&&Number.isFinite(e)}function lo(e){let t=new Map(e.map(a=>[a.id,a])),r=a=>{switch(a.type){case"indicator":return a.input?[a.input]:[];case"compare":case"cross":return[a.left,a.right];case"logic":return[...a.inputs];default:return[]}},n=new Map,o=new Map;for(let a of e)n.set(a.id,0),o.set(a.id,[]);for(let a of e)for(let l of r(a))t.has(l)&&(o.get(l).push(a.id),n.set(a.id,n.get(a.id)+1));let s=[];for(let[a,l]of n)l===0&&s.push(a);let i=[];for(;s.length;){let a=s.shift();i.push(a);for(let l of o.get(a))n.set(l,n.get(l)-1),n.get(l)===0&&s.push(l)}if(i.length!==e.length)throw new Error("strategy graph is cyclic");return i}function $e(e,t){return e!=null&&typeof e=="object"&&"param"in e?t[e.param].value:e}function uo(e,t,r){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");if(!Number.isInteger(t)||t<0||t>=e.length)throw new RangeError("index out of range");let n=null;for(let o=0;o<=t;o++){let s=e[o];if(s==null||typeof s!="object"||Array.isArray(s))throw new TypeError(`bars[${o}] must be an object`);let{t:i,o:a,h:l,l:f,c:u,v:c}=s;if(!Q(i)&&(typeof i=="number"&&Number.isFinite(i)),!Number.isFinite(i))throw new TypeError(`bars[${o}].t must be finite`);for(let[d,m]of[["o",a],["h",l],["l",f],["c",u],["v",c]])if(!Q(m))throw new TypeError(`bars[${o}].${d} must be a finite number`);for(let[d,m]of[["o",a],["h",l],["l",f],["c",u]])if(!(m>0))throw new TypeError(`bars[${o}].${d} price must be positive`);if(c<0)throw new TypeError(`bars[${o}].v volume must be non-negative`);if(l<Math.max(a,u,f))throw new TypeError(`bars[${o}] high must be >= max(open, close, low)`);if(f>Math.min(a,u,l))throw new TypeError(`bars[${o}] low must be <= min(open, close, high)`);if(n!=null){if(!(i>n))throw new TypeError("bars t must be strictly increasing");if(i-n!==co[r])throw new TypeError(`bars t must match ${r} cadence`)}if(n=i,"fundingRate"in s&&s.fundingRate!=null&&!Q(s.fundingRate))throw new TypeError(`bars[${o}].fundingRate must be finite when present`);if("openInterest"in s&&s.openInterest!=null){if(!Q(s.openInterest))throw new TypeError(`bars[${o}].openInterest must be finite when present`);if(s.openInterest<0)throw new TypeError(`bars[${o}].openInterest must be non-negative`)}for(let d of["premium","oiDelta"])if(d in s&&s[d]!=null&&!Q(s[d]))throw new TypeError(`bars[${o}].${d} must be finite when present`);if("bookImbalance"in s&&s.bookImbalance!=null){if(!Q(s.bookImbalance))throw new TypeError(`bars[${o}].bookImbalance must be finite when present`);if(s.bookImbalance<-1||s.bookImbalance>1)throw new TypeError(`bars[${o}].bookImbalance must be within [-1, 1]`)}}}function ke(e,t,r,n,o,s){if(s.has(e))return s.get(e);let i=t.get(e),a;switch(i.type){case"input":{let l=ao[i.field];a=new Array(o+1);for(let f=0;f<=o;f++){let u=n[f][l];a[f]=u===void 0?null:u}break}case"constant":{let l=$e(i.value,r);a=new Array(o+1).fill(l);break}case"indicator":{let l=i.period!=null?$e(i.period,r):void 0;if(i.indicator==="atr"){let c=[];for(let d=0;d<=o;d++){let m=n[d];c.push({o:m.o,h:m.h,l:m.l,c:m.c})}a=_t(c,l);break}let u=ke(i.input,t,r,n,o,s).map((c,d)=>{if(c==null||!Q(c))throw new TypeError(`indicator input ${i.input} has non-finite value at ${d}`);return c});if(i.indicator==="sma")a=Ot(u,l);else if(i.indicator==="ema")a=qe(u,l);else if(i.indicator==="rsi")a=Pt(u,l);else if(i.indicator==="macd")a=$t(u,{fastPeriod:$e(i.fastPeriod,r),slowPeriod:$e(i.slowPeriod,r),signalPeriod:$e(i.signalPeriod,r)})[i.output];else if(i.indicator==="bollinger")a=It(u,{period:l,stdDev:$e(i.stdDev,r)})[i.output];else throw new Error(`unsupported indicator ${i.indicator}`);break}case"compare":{let l=ke(i.left,t,r,n,o,s),f=ke(i.right,t,r,n,o,s);a=new Array(o+1);for(let u=0;u<=o;u++){let c=l[u],d=f[u];if(c==null||d==null||!Q(c)||!Q(d)){a[u]=!1;continue}switch(i.op){case"gt":a[u]=c>d;break;case"gte":a[u]=c>=d;break;case"lt":a[u]=c<d;break;case"lte":a[u]=c<=d;break;case"eq":a[u]=c===d;break;default:a[u]=!1}}break}case"logic":{let l=i.inputs.map(f=>ke(f,t,r,n,o,s));a=new Array(o+1);for(let f=0;f<=o;f++)if(i.op==="not"){let u=l[0][f];a[f]=u===!0?!1:u===!1}else if(i.op==="and"){let u=!0;for(let c of l)if(c[f]!==!0){u=!1;break}a[f]=u}else if(i.op==="or"){let u=!1;for(let c of l)if(c[f]===!0){u=!0;break}a[f]=u}else a[f]=!1;break}case"cross":{let l=ke(i.left,t,r,n,o,s),f=ke(i.right,t,r,n,o,s);a=new Array(o+1),a[0]=!1;for(let u=1;u<=o;u++){let c=l[u-1],d=f[u-1],m=l[u],p=f[u];if(c==null||d==null||m==null||p==null||!Q(c)||!Q(d)||!Q(m)||!Q(p)){a[u]=!1;continue}i.direction==="above"?a[u]=c<=d&&m>p:a[u]=c>=d&&m<p}break}default:throw new Error(`unknown node type ${i.type}`)}return s.set(e,a),a}function Y(e,t={}){let r=W(e);t&&Object.keys(t).length&&(r=_e(r,t));let n=new Map(r.nodes.map(m=>[m.id,m])),o=Object.freeze(lo(r.nodes)),s=r.parameters,i=new Set(r.nodes.filter(m=>m.type==="input").map(m=>m.field));if(r.nodes.some(m=>m.type==="indicator"&&m.indicator==="atr"))for(let m of["open","high","low","close"])i.add(m);let a=Object.freeze([...i].sort()),l=Ae(r);function f(m,p){let w={};for(let S of o){let j=m.get(S);w[S]=j[p]}let g=S=>S!=null&&w[S]===!0;return{values:w,signals:{entryLong:g(r.rules.entryLong),entryShort:g(r.rules.entryShort),exitLong:g(r.rules.exitLong),exitShort:g(r.rules.exitShort)}}}function u(m,p){uo(m,p,r.market.interval);let w=new Map;for(let g of o)ke(g,n,s,m,p,w);return w}function c(m,p){return f(u(m,p),p)}function d(m){if(!Array.isArray(m)||m.length===0)throw new TypeError("bars must be a non-empty array");let p=m.length-1,w=u(m,p);return Object.freeze(m.map((g,S)=>Object.freeze(f(w,S))))}return Object.freeze({strategy:r,strategyHash:l,compilerVersion:Ie,compilerHash:we,requiredSeries:a,nodeOrder:o,evaluate:c,evaluateAll:d})}import{createHash as $o}from"node:crypto";import{createHash as fo}from"node:crypto";var po=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:100});function mo(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function oe(e){return typeof e=="number"&&Number.isFinite(e)}function jt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)jt(t);return Object.freeze(e)}for(let t of Object.keys(e))jt(e[t]);return Object.freeze(e)}function nt(e){if(Array.isArray(e))return e.map(nt);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=nt(e[r]);return t}return e}function Nt(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)=>Nt(r,`${t}[${n}]`));return}for(let[r,n]of Object.entries(e))Nt(n,`${t}.${r}`)}}function jr(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");let t=null;for(let r=0;r<e.length;r++){let n=e[r];if(n==null||typeof n!="object"||Array.isArray(n))throw new TypeError(`bars[${r}] must be an object`);let{t:o,o:s,h:i,l:a,c:l,v:f}=n;if(!oe(o))throw new TypeError(`bars[${r}].t must be finite`);for(let[u,c]of[["o",s],["h",i],["l",a],["c",l],["v",f]])if(!oe(c))throw new TypeError(`bars[${r}].${u} must be a finite number`);for(let[u,c]of[["o",s],["h",i],["l",a],["c",l]])if(!(c>0))throw new TypeError(`bars[${r}].${u} price must be positive`);if(f<0)throw new TypeError(`bars[${r}].v volume must be non-negative`);if(i<Math.max(s,l,a))throw new TypeError(`bars[${r}] high must be >= max(open, close, low)`);if(a>Math.min(s,l,i))throw new TypeError(`bars[${r}] low must be <= min(open, close, high)`);if(t!=null&&!(o>t))throw new TypeError("bars t must be strictly increasing");if(t=o,"fundingRate"in n&&n.fundingRate!=null&&!oe(n.fundingRate))throw new TypeError(`bars[${r}].fundingRate must be finite when present`);if("fundingPaymentRate"in n&&n.fundingPaymentRate!=null&&!oe(n.fundingPaymentRate))throw new TypeError(`bars[${r}].fundingPaymentRate must be finite when present`);if("openInterest"in n&&n.openInterest!=null&&!oe(n.openInterest))throw new TypeError(`bars[${r}].openInterest must be finite when present`)}}function ze(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");return e.length>0&&jr(e),fo("sha256").update(JSON.stringify(nt(e)),"utf8").digest("hex")}function ho(e){if(e==null&&(e={}),!mo(e))throw new TypeError("options must be a plain object");let t={...po},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(!oe(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(!oe(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(!oe(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 ot(e){return e/1e4}function yo(e,t,r){let n=ot(r);return t==="long"?e*(1+n):e*(1-n)}function wo(e,t,r){let n=ot(r);return t==="long"?e*(1-n):e*(1+n)}function vr(e,t,r){let n=Math.abs(e)*ot(t),o=Math.abs(e)*ot(r);return{taker:n,builder:o,total:n+o}}function go(e,t){let r=e*(t.positionSizePct/100)*t.maxLeverage;return Math.min(r,t.maxNotionalUsd)}function bo(e,t,r){let n=r/100;return t==="long"?e*(1-n):e*(1+n)}function Eo(e,t,r){let n=r/100;return t==="long"?e*(1+n):e*(1-n)}function xo(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 So(e,t,r){return t==="long"?e.l<=r:e.h>=r}function ko(e,t,r){return t==="long"?e.h>=r:e.l<=r}function Ao(e,t,r){return t==="long"?e.l<=r:e.h>=r}var To=Object.freeze(["fundingRate","openInterest","premium","oiDelta","bookImbalance"]);function Ve(e,t){for(let r of e.requiredSeries)if(To.includes(r)&&!t.every(n=>oe(n?.[r])))throw new Error(`strategy required series is absent: ${r}`)}function Oo(e){if(e.length<3)return 0;let t=[];for(let i=1;i<e.length;i++){let a=e[i-1].equity,l=e[i].equity;a>0&&t.push((l-a)/a)}if(t.length<2)return 0;let r=0;for(let i of t)r+=i;let n=r/t.length,o=0;for(let i of t)o+=(i-n)**2;let s=Math.sqrt(o/(t.length-1));return s>0?n/s:0}function Po(e){let t=-1/0,r=0;for(let n of e){let o=n.equity;if(o>t&&(t=o),t>0){let s=(t-o)/t*100;s>r&&(r=s)}}return r}function pe(e,t,r={}){let n=ho(r);jr(t);let o=ze(t);n.nowMs!==void 0&&W(e,{nowMs:n.nowMs});let s=Y(e);if(Ve(s,t),n.nowMs!==void 0&&s.strategy.risk.expiresAt<=n.nowMs)throw new Error("strategy is expired: risk.expiresAt must be strictly greater than nowMs");let i=s.strategy.risk,a=s.evaluateAll(t),l=n.latencyBars,f=n.slippageBps,u=n.takerFeeBps,c=n.builderFeeBps,d=n.initialEquityUsd,m=0,p=0,w=0,g=0,S=0,j=[],P=[],x=[],R=[],$=[],h=null,M=0,D=null,K=d,k=!1,y=0,I=0,_=[],C=new Array(t.length).fill(0);function L(E){_.push(E)}function N(E){let H=t[E].v*(n.maxVolumeParticipationPct/100);return Math.max(0,H-C[E])}function T(E){if(!h)return d;let H=h.side==="long"?(E-h.entryPrice)*h.qty:(h.entryPrice-E)*h.qty;return d+H}function v(E,H,A){let q=A.o,F=go(d,i);if(!(F>0)||!(q>0))return;let B=yo(q,H,f),U=F/B,J=N(E),Fe=B*J;if(U>J){x.push({kind:"entry",barIndex:E,time:A.t,side:H,requestedNotionalUsd:F,maxFillNotionalUsd:Fe,reason:"volume_participation"});return}C[E]+=U;let ne=Math.abs(B-q)*U,ue=vr(F,u,c);d-=ue.total,m+=ue.taker,p+=ue.builder,g+=ne,S+=F,h={lifecycleEpoch:++I,side:H,entryBarIndex:E,entryReferencePrice:q,entryPrice:B,qty:U,notionalUsd:F,stop:bo(B,H,i.stopLossPct),take:Eo(B,H,i.takeProfitPct),liq:xo(B,H,i.maxLeverage,u+c),entryFees:ue.taker,entryBuilderFees:ue.builder,entrySlippageUsd:ne,fundingAccrued:0}}function O(E,H,A,q){if(!h)return!1;let F=h.side,B=H,U=B;A!=="liquidation"&&q&&(U=wo(B,F,f));let J=h.qty,Fe=J*U;if(A!=="liquidation"){let dr=N(E),bn=U*dr;if(J>dr)return x.push({kind:"exit",barIndex:E,time:t[E].t,side:F,requestedNotionalUsd:Fe,maxFillNotionalUsd:bn,reason:"volume_participation",triggerReason:A}),!1;C[E]+=J}let ne=vr(Fe,u,c),ue=A==="liquidation"?0:Math.abs(U-B)*J,Ce,wt;F==="long"?(Ce=(B-h.entryReferencePrice)*J,wt=(U-h.entryPrice)*J):(Ce=(h.entryReferencePrice-B)*J,wt=(h.entryPrice-U)*J),d+=wt,d-=ne.total,m+=ne.taker,p+=ne.builder,g+=ue,S+=Fe;let gn={side:F,entryBarIndex:h.entryBarIndex,entryTime:t[h.entryBarIndex].t,entryPrice:h.entryPrice,exitBarIndex:E,exitTime:t[E].t,exitPrice:U,exitReason:A,qty:J,notionalUsd:h.notionalUsd,grossPnlUsd:Ce,feesUsd:h.entryFees+ne.taker,builderFeesUsd:h.entryBuilderFees+ne.builder,fundingUsd:h.fundingAccrued,slippageUsd:h.entrySlippageUsd+ue,netPnlUsd:Ce-(h.entryFees+ne.taker+h.entryBuilderFees+ne.builder)-h.fundingAccrued-(h.entrySlippageUsd+ue)};return j.push(gn),A==="liquidation"&&P.push({barIndex:E,time:t[E].t,side:F,price:U,tradeIndex:j.length-1}),h=null,I+=1,y=E+1+(i.cooldownBars||0),!0}function X(E,H,A,q){let F=E+1;if(F>=t.length)return;_.some(U=>U.kind==="exit"&&U.side===H&&U.fillBar===F&&U.epoch===q)||L({kind:"exit",side:H,signalBar:E,fillBar:F,reason:A,epoch:q})}function Z(E){let H=_.filter(A=>A.fillBar===E);for(let A=_.length-1;A>=0;A--)_[A].fillBar===E&&_.splice(A,1);H.sort((A,q)=>{let F=B=>B.kind==="exit"?0:1;return F(A)-F(q)});for(let A of H)if(A.kind==="exit"){if(!h||h.side!==A.side||h.lifecycleEpoch!==A.epoch)continue;let q=A.reason||"rule";O(E,t[E].o,q,!0)||X(E,A.side,q,A.epoch)}else if(A.kind==="entry"){if(h||A.epoch!==I||E<y)continue;v(E,A.side,t[E])}}function te(E){if(!h)return;let H=t[E],A=H.fundingPaymentRate;if(A==null||!oe(A)||A===0)return;let q=Math.abs(h.qty*H.c),F=A*q;h.side==="long"?(d-=F,h.fundingAccrued+=F,w+=F):(d+=F,h.fundingAccrued-=F,w-=F)}function ce(E){if(!h)return;let H=t[E].o;(h.side==="long"?H<=h.liq:H>=h.liq)&&O(E,H,"liquidation",!1)}function We(E){if(!h)return;let H=t[E],A=h.side,q=Ao(H,A,h.liq),F=So(H,A,h.stop),B=ko(H,A,h.take),U=J=>A==="long"?Math.min(J,H.o):Math.max(J,H.o);if(q){O(E,U(h.liq),"liquidation",!1);return}if(F&&B){O(E,U(h.stop),"stop_loss",!0)||X(E,A,"stop_loss",h.lifecycleEpoch);return}if(F){O(E,U(h.stop),"stop_loss",!0)||X(E,A,"stop_loss",h.lifecycleEpoch);return}B&&(O(E,h.take,"take_profit",!0)||X(E,A,"take_profit",h.lifecycleEpoch))}for(let E=0;E<t.length;E++){let H=Math.floor(t[E].t/864e5);H!==D&&(D=H,K=T(t[E].o),k=!1),ce(E),Z(E),We(E),te(E),!k&&T(t[E].c)<=K*(1-i.maxDailyLossPct/100)&&(k=!0,R.push({type:"daily_loss_limit",barIndex:E,time:t[E].t,message:"daily loss limit reached; new entries blocked for UTC day"}));let A=a[E].signals,q=E+l;if(h)(h.side==="long"&&A.exitLong===!0||h.side==="short"&&A.exitShort===!0)&&q<t.length&&(_.some(J=>J.kind==="exit"&&J.side===h.side&&J.fillBar===q&&J.epoch===h.lifecycleEpoch)||L({kind:"exit",side:h.side,signalBar:E,fillBar:q,reason:"rule",epoch:h.lifecycleEpoch}));else{let B=A.entryLong===!0,U=A.entryShort===!0;B&&U?R.push({type:"conflicting_entry_signals",barIndex:E,time:t[E].t,message:"conflicting entry signals; no position opened"}):!k&&(B||U)&&q<t.length&&E>=y&&L({kind:"entry",side:B?"long":"short",signalBar:E,fillBar:q,epoch:I})}let F=d;h&&(M+=1,F=T(t[E].c)),$.push({barIndex:E,time:t[E].t,equity:F,positionSide:h?h.side:null})}let Ze=null;if(h){let E=t.length-1;if(O(E,t[E].c,"end_of_data",!0))$[E]={barIndex:E,time:t[E].t,equity:d,positionSide:null};else{let A=T(t[E].c);Ze={side:h.side,entryBarIndex:h.entryBarIndex,entryTime:t[h.entryBarIndex].t,entryPrice:h.entryPrice,qty:h.qty,notionalUsd:h.notionalUsd,markPrice:t[E].c,markedEquityUsd:A},R.push({type:"open_position_at_end",barIndex:E,time:t[E].t,message:"end-of-data exit missed; position remains open and marked"})}}let Le=(h?T(t[t.length-1].c):d)-n.initialEquityUsd,ht=Le/n.initialEquityUsd*100,He=0,be=0,le=0;for(let E of j)E.netPnlUsd>0?(He+=1,be+=E.netPnlUsd):E.netPnlUsd<0&&(le+=-E.netPnlUsd);let Pe=j.length,Ee=Pe===0?0:He/Pe,yt=0;le>0?yt=be/le:be>0&&(yt=1e12);let yn={netPnlUsd:Le,netPnlPct:ht,maxDrawdownPct:Po($),winRate:Ee,profitFactor:yt,tradeCount:Pe,sharpe:Oo($),turnoverUsd:S,exposurePct:M/t.length*100},wn={initialEquityUsd:n.initialEquityUsd,takerFeeBps:n.takerFeeBps,builderFeeBps:n.builderFeeBps,slippageBps:n.slippageBps,latencyBars:n.latencyBars,maxVolumeParticipationPct:n.maxVolumeParticipationPct},fr={barsHash:o,strategyHash:s.strategyHash,compilerHash:we,compilerVersion:Ie,config:wn,trades:j,equityCurve:$,metrics:yn,costs:{feesUsd:m,builderFeesUsd:p,fundingUsd:w,slippageUsd:g},liquidations:P,missedFills:x,openPositionAtEnd:Ze,flags:R};return Nt(fr),jt(nt(fr))}var Mr=Object.freeze(["fail","pass_paper_only","pass_live_eligible"]);function se(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ve(e){return typeof e=="number"&&Number.isFinite(e)}function Lt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Lt(t);return Object.freeze(e)}for(let t of Object.keys(e))Lt(e[t]);return Object.freeze(e)}function Te(e){if(Array.isArray(e))return e.map(Te);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Te(e[r]);return t}return e}function Rt(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 Nr(e){return{feesUsd:e.costs.feesUsd,builderFeesUsd:e.costs.builderFeesUsd,fundingUsd:e.costs.fundingUsd,slippageUsd:e.costs.slippageUsd}}function Io(e){return(e.feesUsd||0)+(e.builderFeesUsd||0)+Math.max(0,e.fundingUsd||0)+(e.slippageUsd||0)}function _o(e){let t=0;for(let r of e.trades)r.grossPnlUsd>0&&(t+=r.grossPnlUsd);return t}function vo(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 Lr(e){if(!se(e))throw new TypeError("evidence artifact must be a plain object");if(!Mr.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(!se(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(!se(e.walkForward)||!Array.isArray(e.walkForward.windows))throw new TypeError("evidence artifact walkForward windows required");if(e.status==="pass_live_eligible"&&(!se(e.train)||!se(e.holdout)))throw new TypeError("live-eligible evidence artifact requires train and holdout facts");return Te({barsHash:e.barsHash,compilerHash:e.compilerHash,flags:e.flags.map(t=>Te(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 Ht(e){return $o("sha256").update(JSON.stringify(Lr(e)),"utf8").digest("hex")}function re(e,t,r=0){if(!Number.isInteger(e)||e<r)throw new Error(`${t} must be an integer >= ${r}`);return e}function Mt(e,t){if(!se(e)||!se(e.metrics))throw new Error(`${t} metrics required`);let r=re(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(!ve(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 jo(e,{maxDailyLossPct:t}={}){let r=e.split,n=re(r.trainStartIndex,"split.trainStartIndex"),o=re(r.trainEndIndex,"split.trainEndIndex"),s=re(r.trainBarCount,"split.trainBarCount",1),i=re(r.holdoutStartIndex,"split.holdoutStartIndex"),a=re(r.holdoutEndIndex,"split.holdoutEndIndex"),l=re(r.holdoutBarCount,"split.holdoutBarCount",1);if(n!==0||o-n+1!==s||i!==o+1||a-i+1!==l)throw new Error("evidence split must be contiguous, chronological, and count-consistent");if(!ve(r.trainFraction)||r.trainFraction<=0||r.trainFraction>=1)throw new Error("split.trainFraction must be in (0,1)");Mt(e.train,"train");let f=Mt(e.holdout,"holdout");if(f.tradeCount<1||f.netPnlUsd<=0||f.profitFactor<=1)throw new Error("live-eligible holdout metrics do not pass");if(ve(t)&&f.maxDrawdownPct>t)throw new Error("live-eligible holdout drawdown exceeds strategy risk");if(e.flags.length>0)throw new Error("live-eligible evidence cannot contain failure flags");let u=e.walkForward,c=u.windows;if(c.length<1||u.windowsRun!==c.length)throw new Error("live-eligible walk-forward windowsRun must match nonempty windows");let d=0,m=-1;for(let w=0;w<c.length;w++){let g=c[w];if(!se(g)||g.index!==w||typeof g.passed!="boolean")throw new Error("walk-forward windows must be ordered and structurally valid");let S=re(g.trainStartIndex,`walkForward.windows[${w}].trainStartIndex`),j=re(g.trainEndIndex,`walkForward.windows[${w}].trainEndIndex`),P=re(g.evalStartIndex,`walkForward.windows[${w}].evalStartIndex`),x=re(g.evalEndIndex,`walkForward.windows[${w}].evalEndIndex`);if(S!==0||j>=P||P>x||P<=m)throw new Error("walk-forward windows must be chronological and disjoint");if(m=x,g.passed){if(d+=1,g.reason!=="pass")throw new Error("passed walk-forward window reason must be pass");let R=Mt({metrics:g.metrics,tradeCount:g.metrics?.tradeCount},`walkForward.windows[${w}]`);if(R.tradeCount<1||R.netPnlUsd<=0||R.profitFactor<=1)throw new Error("passed walk-forward window metrics do not pass");if(ve(t)&&R.maxDrawdownPct>t)throw new Error("passed walk-forward drawdown exceeds strategy risk")}else if(g.reason==="pass")throw new Error("failed walk-forward window cannot have pass reason")}let p=d/c.length;if(!ve(u.passRate)||Math.abs(u.passRate-p)>Number.EPSILON||p<.6)throw new Error("walk-forward passRate contradicts concrete windows or is below live threshold")}function Ft(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=Lr(e),n=Te({id:e.id,...r});if(JSON.stringify(Te(e))!==JSON.stringify(n))throw new Error("evidence artifact contains fields unbound from its deterministic identity");let o=Ht(e);if(e.id!==o)throw new Error("evidence.id does not match its deterministic artifact facts digest");return e.status==="pass_live_eligible"&&jo(e,t),e}function st({strategy:e,bars:t,backtestOptions:r={},trainFraction:n=.7,walkForwardWindows:o=3,minTrades:s=10}={}){let i=[];if(!se(e))throw new TypeError("strategy must be a plain object");if(!Array.isArray(t))throw new TypeError("bars must be an array");if(!se(r))throw new TypeError("backtestOptions must be a plain object");if(!ve(n)||n<=0||n>=1)throw new TypeError("trainFraction must be in (0,1)");if(!Number.isInteger(o)||o<1)throw new TypeError("walkForwardWindows must be a positive integer");if(!Number.isInteger(s)||s<0)throw new TypeError("minTrades must be an integer >= 0");let a=W(e),l=Ae(a),f=ze(t),u=t.length,c=(N=[],T={})=>Rr({status:"fail",strategy:a,sHash:l,barsHash:f,split:T.split||{trainStartIndex:0,trainEndIndex:-1,trainBarCount:0,holdoutStartIndex:0,holdoutEndIndex:-1,holdoutBarCount:0,trainFraction:n},train:T.train||null,holdout:T.holdout||null,walkForward:T.walkForward||{windows:[],passRate:0},flags:[...i,...N]});if(u<10)return c([{type:"insufficient_bars",message:"need at least 10 bars for evidence"}]);let d=Math.floor(u*n),m=d,p=u-m;if(d<5||p<3)return c([{type:"invalid_windowing",message:"train/holdout split too small",trainCount:d,holdoutCount:p}]);let w=t.slice(0,d),g=t.slice(m),S,j;try{S=pe(a,w,r),j=pe(a,g,r)}catch(N){return c([{type:"backtest_error",message:String(N.message||N)}])}let P={metrics:Rt(S),costs:Nr(S),tradeCount:S.metrics.tradeCount},x={metrics:Rt(j),costs:Nr(j),tradeCount:j.metrics.tradeCount},R={trainStartIndex:0,trainEndIndex:d-1,trainBarCount:d,holdoutStartIndex:m,holdoutEndIndex:u-1,holdoutBarCount:p,trainFraction:n},$=[],h=Math.floor(u/(o+1));if(h<3)i.push({type:"invalid_windowing",message:"walk-forward window size too small",wfSize:h});else for(let N=0;N<o;N++){let T=h*(N+1),v=T,O=Math.min(u,v+h);if(O-v<3||T<3){$.push({index:N,trainStartIndex:0,trainEndIndex:T-1,evalStartIndex:v,evalEndIndex:O-1,passed:!1,reason:"window_too_small",metrics:null});continue}let X=t.slice(v,O),Z;try{Z=pe(a,X,r)}catch{$.push({index:N,trainStartIndex:0,trainEndIndex:T-1,evalStartIndex:v,evalEndIndex:O-1,passed:!1,reason:"backtest_error",metrics:null});continue}let te=Rt(Z),ce=vo(te,a.risk,s);$.push({index:N,trainStartIndex:0,trainEndIndex:T-1,evalStartIndex:v,evalEndIndex:O-1,passed:ce,reason:ce?"pass":"fail_metrics",metrics:te})}let M=$.filter(N=>N.passed).length,D=$.length===0?0:M/$.length,K={windows:$,passRate:D,windowsRun:$.length};x.metrics.tradeCount===0&&P.metrics.tradeCount===0&&i.push({type:"no_trades",message:"no trades in train or holdout"}),x.metrics.tradeCount===0&&i.push({type:"absent_oos_trades",message:"holdout produced no trades"}),x.metrics.netPnlUsd<0&&i.push({type:"holdout_loss",message:"holdout netPnlUsd is negative"}),P.metrics.netPnlUsd>0&&x.metrics.netPnlUsd<0&&P.metrics.netPnlUsd>Math.abs(x.metrics.netPnlUsd)*.25?i.push({type:"overfit",message:"profitable train with losing holdout (OOS collapse)"}):P.metrics.netPnlUsd>0&&x.metrics.netPnlUsd>0&&x.metrics.netPnlUsd<P.metrics.netPnlUsd*.1&&P.metrics.tradeCount>=s&&i.push({type:"severe_oos_collapse",message:"holdout pnl collapsed vs train"});let k=Io(x.costs),y=_o(j);y>0&&k>y&&i.push({type:"costs_exceed_gross",message:"holdout costs exceed gross gains"});let I=i.some(N=>["insufficient_bars","invalid_windowing","absent_oos_trades","holdout_loss","no_trades","severe_oos_collapse","backtest_error"].includes(N.type)),_=i.some(N=>N.type==="overfit"),C="fail";return x.metrics.tradeCount>=s&&x.metrics.netPnlUsd>0&&x.metrics.profitFactor>1&&x.metrics.maxDrawdownPct<=a.risk.maxDailyLossPct&&D>=.6&&!(y>0&&k>y)&&!_&&!i.some(N=>N.type==="severe_oos_collapse"||N.type==="invalid_windowing")?C="pass_live_eligible":!I&&x.metrics.tradeCount>0&&P.metrics.tradeCount>0&&Number.isFinite(x.metrics.netPnlUsd)?(C="pass_paper_only",x.metrics.tradeCount<s&&i.push({type:"undersampled",message:"holdout trades below minTrades"})):_&&x.metrics.tradeCount>0&&P.metrics.netPnlUsd>0?C="fail":x.metrics.tradeCount>0&&P.metrics.tradeCount>0&&!I?C="pass_paper_only":C="fail",x.metrics.netPnlUsd<0&&(C=C==="pass_live_eligible"?"fail":C==="pass_paper_only"?"pass_paper_only":"fail",C="fail"),Rr({status:C,strategy:a,sHash:l,barsHash:f,split:R,train:P,holdout:x,walkForward:K,flags:i})}function Rr({status:e,strategy:t,sHash:r,barsHash:n,split:o,train:s,holdout:i,walkForward:a,flags:l}){let f={status:e,strategyHash:r,compilerHash:we,barsHash:n,split:o,train:s,holdout:i,walkForward:a,flags:l};return f.id=Ht(f),Lt(Te(JSON.parse(JSON.stringify(f))))}import{createHash as No,createHmac as Ro,timingSafeEqual as Vi}from"node:crypto";var Mo=2,Lo=300*1e3,Ho=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})();function Ct(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(Ct).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${Ct(e[r])}`).join(",")}}`}function Hr(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function Fr(e=process.env){return Hr(process.env)||Hr(e)}function Fo(e){let{prepareHash:t,prepareMac:r,note:n,...o}=e||{};return o}function Co(e){let t=Fo(e);return No("sha256").update(Ct(t)).digest("hex")}function Do(e,t=Fr()){return t?Ro("sha256",t).update(String(e)).digest("hex"):""}function Cr(e,{provider:t,kind:r,env:n=process.env,nowMs:o=Date.now(),expiresAtMs:s}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let i=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(i&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let a={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1,oraclePrepared:i?e.oraclePrepared:!0};if(!a.provider)throw new Error("stampPrepared: provider required");if(!a.kind)throw new Error("stampPrepared: kind required");let l=Number(o),f=s==null?l+Lo:Number(s),u=f-l;if(!Number.isSafeInteger(l)||!Number.isSafeInteger(f)||u<=0||u>Ho)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let d={...a,preparedAt:l,expiresAt:f,prepareVersion:Mo},m=Co(d),p=Fr(n),w=p?Do(m,p):void 0,g={...d,prepareHash:m};return w&&(g.prepareMac=w),g}var Uo=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Je(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function qo(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Ut(e,t="value"){if(Array.isArray(e)){e.forEach((r,n)=>Ut(r,`${t}[${n}]`));return}if(Je(e))for(let[r,n]of Object.entries(e)){let o=qo(r);if(Uo.some(s=>o.includes(s)))throw new Error(`handoff: forbidden secret-like field at ${t}.${r}`);Ut(n,`${t}.${r}`)}}function Dt(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function qt({strategy:e,evidence:t,shadow:r,caps:n,nowMs:o=Date.now(),env:s=process.env}={}){if(Ut({strategy:e,evidence:t,shadow:r,caps:n},"handoff"),!Je(e))throw new Error("handoff: strategy required");if(!Je(t))throw new Error("handoff: evidence required");if(!Je(r))throw new Error("handoff: shadow required");if(!Je(n))throw new Error("handoff: caps required");if(typeof r.id!="string"||!r.id.trim())throw new Error("handoff: shadow.id required");if(typeof r.stateHash!="string"||!/^[0-9a-f]{64}$/.test(r.stateHash))throw new Error("handoff: shadow.stateHash must be a sha256 hash");if(r.status!=="running")throw new Error("handoff: shadow.status must be running");if(!Number.isInteger(r.cursor)||r.cursor<=0)throw new Error("handoff: shadow.cursor must be a positive integer");if(!Number.isInteger(r.updatedAt)||r.updatedAt<=0||r.updatedAt>o)throw new Error("handoff: shadow.updatedAt must be a positive integer <= nowMs");let i=W(e,{nowMs:o}),a=Y(i);if(Ft(t,{maxDailyLossPct:i.risk.maxDailyLossPct}),t.status!=="pass_live_eligible")throw new Error("handoff: evidence.status must be pass_live_eligible");if(t.strategyHash!==a.strategyHash)throw new Error("handoff: evidence.strategyHash mismatch");if(t.compilerHash!==a.compilerHash)throw new Error("handoff: evidence.compilerHash mismatch");let l=["perStrategyNotionalUsd","maxLeverage","dailyLossCapUsd","chainAllowlist","assetAllowlist","expiresAt","killSwitchRequired"];for(let d of l)if(!(d in n)||n[d]==null)throw new Error(`handoff: caps.${d} required`);if(!Dt(n.perStrategyNotionalUsd))throw new Error("handoff: caps.perStrategyNotionalUsd must be positive");if(n.perStrategyNotionalUsd>a.strategy.risk.maxNotionalUsd)throw new Error("handoff: caps.perStrategyNotionalUsd exceeds strategy.risk.maxNotionalUsd");if(!Dt(n.maxLeverage))throw new Error("handoff: caps.maxLeverage must be positive");if(n.maxLeverage>a.strategy.risk.maxLeverage)throw new Error("handoff: caps.maxLeverage exceeds strategy.risk.maxLeverage");if(!Dt(n.dailyLossCapUsd))throw new Error("handoff: caps.dailyLossCapUsd must be positive");let f=a.strategy.risk.maxNotionalUsd*(a.strategy.risk.maxDailyLossPct/100);if(n.dailyLossCapUsd>f)throw new Error("handoff: caps.dailyLossCapUsd exceeds strategy daily loss ceiling");if(!Array.isArray(n.chainAllowlist)||n.chainAllowlist.length===0)throw new Error("handoff: caps.chainAllowlist must be a non-empty array");if(!n.chainAllowlist.every(d=>d==="hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include only hyperliquid");if(!n.chainAllowlist.includes("hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include hyperliquid");if(!Array.isArray(n.assetAllowlist)||n.assetAllowlist.length===0)throw new Error("handoff: caps.assetAllowlist must be a non-empty array");if(n.assetAllowlist.length!==1||n.assetAllowlist[0]!==a.strategy.market.coin)throw new Error("handoff: caps.assetAllowlist must contain only the strategy market coin");if(!Number.isInteger(n.expiresAt)||!(n.expiresAt>o))throw new Error("handoff: caps.expiresAt must be an integer > nowMs");if(n.expiresAt>a.strategy.risk.expiresAt)throw new Error("handoff: caps.expiresAt exceeds strategy.risk.expiresAt");if(n.killSwitchRequired!==!0)throw new Error("handoff: caps.killSwitchRequired must be exactly true");let u={perStrategyNotionalUsd:n.perStrategyNotionalUsd,maxLeverage:n.maxLeverage,dailyLossCapUsd:n.dailyLossCapUsd,chainAllowlist:[...n.chainAllowlist],assetAllowlist:[...n.assetAllowlist],expiresAt:n.expiresAt,killSwitchRequired:!0},c={strategyHash:a.strategyHash,compilerHash:a.compilerHash,evidence:JSON.parse(JSON.stringify(t)),shadow:{id:r.id,stateHash:r.stateHash,status:r.status,cursor:r.cursor,updatedAt:r.updatedAt},compiled:{strategyHash:a.strategyHash,compilerHash:a.compilerHash,compilerVersion:Ie,venue:"hyperliquid",market:{coin:a.strategy.market.coin,kind:"perp",interval:a.strategy.market.interval},risk:{...a.strategy.risk},strategy:JSON.parse(JSON.stringify(a.strategy))},arming:{liveBroadcast:!1,requiresExplicitUserArm:!0,caps:u},requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,executionReady:!1};return Cr(c,{provider:"hl-strategy",kind:"strategy-live-handoff",env:s})}var Bo=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 je(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function Ne(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be a non-negative safe integer`);return e}function Ge(e){if(Array.isArray(e))for(let t of e)Ge(t);else if(e&&typeof e=="object")for(let t of Object.values(e))Ge(t);return Object.freeze(e)}function Dr(e){let t=Bo[e];if(!t)throw new TypeError(`unsupported strategy interval: ${e}`);return t}function Ur(e,{endTime:t=Number.MAX_SAFE_INTEGER}={}){if(!Array.isArray(e))throw new TypeError("Hyperliquid candles must be an array");Ne(t,"endTime");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`candles[${n}] must be an object`);let s=Ne(Number(o.t),`candles[${n}].t`);if(Ne(Number(o.T),`candles[${n}].T`)>t)continue;let a={t:s,o:je(o.o,`candles[${n}].o`),h:je(o.h,`candles[${n}].h`),l:je(o.l,`candles[${n}].l`),c:je(o.c,`candles[${n}].c`),v:je(o.v,`candles[${n}].v`)};if(a.h<Math.max(a.o,a.c,a.l))throw new TypeError(`candles[${n}].h is below another price`);if(a.l>Math.min(a.o,a.c,a.h))throw new TypeError(`candles[${n}].l is above another price`);if(a.v<0)throw new TypeError(`candles[${n}].v must be non-negative`);let l=r.get(s);if(l&&JSON.stringify(l)!==JSON.stringify(a))throw new TypeError(`conflicting duplicate candle at timestamp ${s}`);l||r.set(s,a)}return Ge([...r.values()].sort((n,o)=>n.t-o.t))}function zo(e,t){if(!Array.isArray(e))throw new TypeError("Hyperliquid funding history must be an array");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`funding[${n}] must be an object`);let s=Ne(Number(o.time),`funding[${n}].time`);s>t||r.set(s,{time:s,fundingRate:je(o.fundingRate,`funding[${n}].fundingRate`)})}return[...r.values()].sort((n,o)=>n.time-o.time)}async function Vo({coin:e,startTime:t,endTime:r},n){let o=[],s=Math.max(0,t-288e5),i=!1;for(let a=0;a<16&&s<=r;a++){let l=await $r({coin:e,startTime:s,endTime:r},n);if(!Array.isArray(l))throw new TypeError("Hyperliquid funding history must be an array");o.push(...l);let f=s;for(let u of l){let c=Number(u?.time);Number.isSafeInteger(c)&&c>f&&(f=c)}if(l.length<500||f>=r){i=!0;break}if(f<=s)throw new Error("Hyperliquid funding history pagination did not advance");s=f+1}if(!i)throw new Error("strategy history exceeds the bounded funding history limit");return zo(o,r)}function Jo(e,t,r){let n=0,o=null;return e.map(s=>{let i=s.t+r,a=0;for(;n<t.length&&t[n].time<i;){let l=t[n];o=l.fundingRate,l.time>=s.t&&(a+=l.fundingRate),n+=1}return o==null?{...s,fundingPaymentRate:a}:{...s,fundingRate:o,fundingPaymentRate:a}})}async function Bt(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=Dr(n);if(e.endTime==null)throw new TypeError("endTime is required for deterministic history");let s=Ne(e.endTime,"endTime"),i=e.count==null?1500:e.count;if(!Number.isInteger(i)||i<20||i>5e3)throw new TypeError("count must be an integer from 20 to 5000");let a=e.startTime==null?Math.max(0,s-i*o):Ne(e.startTime,"startTime");if(a>=s)throw new TypeError("startTime must be before endTime");let[l,f]=await Promise.all([Pr({coin:r,interval:n,startTime:a,endTime:s},t),Vo({coin:r,startTime:a,endTime:s},t)]),u=Ur(l,{endTime:s}),c=Ge(Jo(u,f,o));return Ge({coin:r,interval:n,range:{startTime:a,endTime:s},bars:c})}var Go=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),Ko=new Set(["coin","interval"]);function Yo(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))Ko.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"||!Go.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 Wo(e={}){let t=await Tr(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 qr=Object.freeze({id:"hyperliquid",validateMarket:Yo,fetchBars:Bt,listMarkets:Wo,prepareIntent(e){return qt(e)}});var Zo=Object.freeze(["id","validateMarket","prepareIntent"]);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 Zo.slice(1))if(typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} requires ${t}()`);for(let t of["fetchBars","listMarkets"])if(e[t]!=null&&typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} ${t} must be a function`);return e}var Br=[qr].map(Xo),Qo=new Map(Br.map(e=>[e.id,e])),es=Object.freeze([...Br]);function it(e){return typeof e!="string"?null:Qo.get(e)??null}function at(e){let t=it(e);if(!t)throw new Error(`unknown strategy venue: ${String(e)}`);return t}var ct=1,Qr=/^[a-z0-9][a-z0-9._-]{0,63}$/,en=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,rs=new Set(["open","high","low","close","volume","fundingRate","openInterest","premium","oiDelta","bookImbalance"]),ns=new Set(["sma","ema","rsi","macd","bollinger","atr"]),os=new Set(["gt","gte","lt","lte","eq"]),ss=new Set(["and","or","not"]),is=new Set(["above","below"]),as=new Set(["line","signal","histogram"]),cs=new Set(["upper","middle","lower"]),zt=new Set(["compare","logic","cross"]),zr=new Set(["version","id","name","venue","market","parameters","nodes","rules","risk"]),Vr=new Set(["value","min","max","step"]),Vt=new Set(["entryLong","entryShort","exitLong","exitShort"]),Jr=new Set(["maxLeverage","maxNotionalUsd","positionSizePct","stopLossPct","takeProfitPct","cooldownBars","maxDailyLossPct","expiresAt"]),ls=new Set(["id","type"]),Gr={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"])},Kr=16,Yr=128,Wr=100,Oe=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 ee(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function z(e){return typeof e=="number"&&Number.isFinite(e)}function Zr(e){return Number.isInteger(e)&&e>0}function Gt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Gt(t);return Object.freeze(e)}for(let t of Object.keys(e))Gt(e[t]);return Object.freeze(e)}function Kt(e){if(Array.isArray(e))return e.map(Kt);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Kt(e[r]);return t}return e}function b(e,t,r){e.push({path:t,message:r})}function ge(e,t,r,n){for(let o of Object.keys(e))t.has(o)||b(n,r?`${r}.${o}`:o,"unknown field is not allowed")}function tn(e,t,r,n){if(!z(e)||!z(t)||!z(r)||!z(n)||n<=0||e<t||e>r)return!1;let o=(e-t)/n;if(!Number.isFinite(o))return!1;let s=Math.round(o);return Math.abs(o-s)<=1e-9}function Jt(e,t,r,n){if(ee(e)){if(ge(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param)return b(n,`${t}.param`,"must be a parameter name string"),null;if(!Object.prototype.hasOwnProperty.call(r,e.param))return b(n,`${t}.param`,`unknown parameter "${e.param}"`),null;let o=r[e.param];return!ee(o)||![o.value,o.min,o.max,o.step].every(Zr)?(b(n,`${t}.param`,"referenced period parameter value min max and step must be positive integers"),null):{param:e.param}}return Zr(e)?e:(b(n,t,"must be a positive integer or {param}"),null)}function Xr(e,t,r,n){return ee(e)?(ge(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param?(b(n,`${t}.param`,"must be a parameter name string"),null):Object.prototype.hasOwnProperty.call(r,e.param)?{param:e.param}:(b(n,`${t}.param`,`unknown parameter "${e.param}"`),null)):z(e)?e:(b(n,t,"must be a finite number or {param}"),null)}function lt(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 us(e){let t=new Map,r=n=>{let o=t.get(n)||0;if(o===1)return!0;if(o===2)return!1;t.set(n,1);let s=e.get(n);if(s){for(let i of lt(s))if(e.has(i)&&r(i))return!0}return t.set(n,2),!1};for(let n of e.keys())if(r(n))return!0;return!1}function fs(e,t){if(!ee(e))return b(t,"parameters","must be a plain object"),null;let r=Object.keys(e);if(r.length>Kr)return b(t,"parameters",`too many parameters (max ${Kr})`),null;let n={};for(let o of r){if(!Qr.test(o)){b(t,`parameters.${o}`,"parameter name is malformed");continue}let s=e[o],i=`parameters.${o}`;if(!ee(s)){b(t,i,"must be a plain object");continue}ge(s,Vr,i,t);for(let c of Vr)c in s||b(t,`${i}.${c}`,"required field is missing");let{value:a,min:l,max:f,step:u}=s;z(l)||b(t,`${i}.min`,"must be a finite number"),z(f)||b(t,`${i}.max`,"must be a finite number"),(!z(u)||u<=0)&&b(t,`${i}.step`,"must be a positive finite number"),z(a)||b(t,`${i}.value`,"must be a finite number"),z(l)&&z(f)&&l>f&&b(t,`${i}.min`,"min must be <= max"),z(a)&&z(l)&&z(f)&&z(u)&&u>0&&(tn(a,l,f,u)||b(t,`${i}.value`,"value must lie on the declared min/max/step grid")),n[o]={value:a,min:l,max:f,step:u}}return n}function ds(e,t,r,n){let o=`nodes.${t}`;if(!ee(e))return b(n,o,"must be a plain object"),null;if(typeof e.type!="string"||!Gr[e.type])return b(n,`${o}.type`,"unknown or missing node type"),ge(e,ls,o,n),null;switch(ge(e,Gr[e.type],o,n),(typeof e.id!="string"||!en.test(e.id))&&b(n,`${o}.id`,"must be a 1-64 char id starting with alphanumeric"),e.type){case"input":return(typeof e.field!="string"||!rs.has(e.field))&&b(n,`${o}.field`,"must be one of open|high|low|close|volume|fundingRate|openInterest|premium|oiDelta|bookImbalance"),{id:e.id,type:"input",field:e.field};case"constant":{let s=Xr(e.value,`${o}.value`,r,n);return{id:e.id,type:"constant",value:s}}case"indicator":{(typeof e.indicator!="string"||!ns.has(e.indicator))&&b(n,`${o}.indicator`,"must be one of sma|ema|rsi|macd|bollinger|atr");let s=e.indicator,i={id:e.id,type:"indicator",indicator:s};if(s==="atr"){"input"in e&&(typeof e.input!="string"||!e.input?b(n,`${o}.input`,"must be a node id string when provided"):i.input=e.input);let a=Jt(e.period,`${o}.period`,r,n);a!=null&&(i.period=a)}else typeof e.input!="string"||!e.input?b(n,`${o}.input`,"must be a node id string"):i.input=e.input;if((s==="sma"||s==="ema"||s==="rsi"||s==="bollinger"||s==="atr")&&("period"in e,s!=="macd"))if(!("period"in e))b(n,`${o}.period`,"required field is missing");else{let a=Jt(e.period,`${o}.period`,r,n);a!=null&&(i.period=a)}if(s==="macd"){for(let a of["fastPeriod","slowPeriod","signalPeriod"])if(!(a in e))b(n,`${o}.${a}`,"required field is missing");else{let l=Jt(e[a],`${o}.${a}`,r,n);l!=null&&(i[a]=l)}"output"in e?as.has(e.output)?i.output=e.output:b(n,`${o}.output`,"must be line|signal|histogram"):b(n,`${o}.output`,"required field is missing"),"period"in e&&b(n,`${o}.period`,"forbidden for macd"),"stdDev"in e&&b(n,`${o}.stdDev`,"forbidden for macd")}else if(s==="bollinger"){if(!("stdDev"in e))b(n,`${o}.stdDev`,"required field is missing");else{let a=Xr(e.stdDev,`${o}.stdDev`,r,n);a!=null&&(typeof a=="number"&&a<=0?b(n,`${o}.stdDev`,"must be > 0"):i.stdDev=a)}"output"in e?cs.has(e.output)?i.output=e.output:b(n,`${o}.output`,"must be upper|middle|lower"):b(n,`${o}.output`,"required field is missing");for(let a of["fastPeriod","slowPeriod","signalPeriod"])a in e&&b(n,`${o}.${a}`,`forbidden for ${s}`)}else{"output"in e&&b(n,`${o}.output`,`forbidden for ${s}`),"stdDev"in e&&s!=="bollinger"&&b(n,`${o}.stdDev`,`forbidden for ${s}`);for(let a of["fastPeriod","slowPeriod","signalPeriod"])a in e&&b(n,`${o}.${a}`,`forbidden for ${s}`)}return i}case"compare":return(typeof e.op!="string"||!os.has(e.op))&&b(n,`${o}.op`,"must be gt|gte|lt|lte|eq"),(typeof e.left!="string"||!e.left)&&b(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&b(n,`${o}.right`,"must be a node id"),{id:e.id,type:"compare",op:e.op,left:e.left,right:e.right};case"logic":{if((typeof e.op!="string"||!ss.has(e.op))&&b(n,`${o}.op`,"must be and|or|not"),!Array.isArray(e.inputs))return b(n,`${o}.inputs`,"must be an array of node ids"),{id:e.id,type:"logic",op:e.op,inputs:[]};let s=[];for(let i=0;i<e.inputs.length;i++){let a=e.inputs[i];typeof a!="string"||!a?b(n,`${o}.inputs.${i}`,"must be a node id"):s.push(a)}return e.op==="not"?s.length!==1&&b(n,`${o}.inputs`,"not requires exactly one input"):(e.op==="and"||e.op==="or")&&s.length<2&&b(n,`${o}.inputs`,`${e.op} requires at least two inputs`),{id:e.id,type:"logic",op:e.op,inputs:s}}case"cross":return(typeof e.direction!="string"||!is.has(e.direction))&&b(n,`${o}.direction`,"must be above|below"),(typeof e.left!="string"||!e.left)&&b(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&b(n,`${o}.right`,"must be a node id"),{id:e.id,type:"cross",direction:e.direction,left:e.left,right:e.right};default:return null}}function ps(e,t,r){if(!ee(e))return b(t,"risk","must be a plain object"),null;ge(e,Jr,"risk",t);for(let d of Jr)(!(d in e)||e[d]==null)&&b(t,`risk.${d}`,"required field is missing");let n={},o=e.maxLeverage;!z(o)||o<=0||o>50?b(t,"risk.maxLeverage","must be a number > 0 and <= 50"):n.maxLeverage=o;let s=e.maxNotionalUsd;!z(s)||s<=0?b(t,"risk.maxNotionalUsd","must be a number > 0"):n.maxNotionalUsd=s;let i=e.positionSizePct;!z(i)||i<=0||i>100?b(t,"risk.positionSizePct","must be a number > 0 and <= 100"):n.positionSizePct=i;let a=e.stopLossPct;!z(a)||a<=0||a>100?b(t,"risk.stopLossPct","must be a number > 0 and <= 100"):n.stopLossPct=a;let l=e.takeProfitPct;!z(l)||l<=0||l>1e3?b(t,"risk.takeProfitPct","must be a number > 0 and <= 1000"):n.takeProfitPct=l;let f=e.cooldownBars;!Number.isInteger(f)||f<0||f>1e5?b(t,"risk.cooldownBars","must be an integer >= 0 and <= 100000"):n.cooldownBars=f;let u=e.maxDailyLossPct;!z(u)||u<=0||u>100?b(t,"risk.maxDailyLossPct","must be a number > 0 and <= 100"):n.maxDailyLossPct=u;let c=e.expiresAt;return!Number.isInteger(c)||c<=0?b(t,"risk.expiresAt","must be an integer epoch milliseconds > 0"):(r.nowMs!==void 0&&(Number.isInteger(r.nowMs)?c<=r.nowMs&&b(t,"risk.expiresAt","must be strictly greater than nowMs"):b(t,"nowMs","must be an integer epoch milliseconds")),n.expiresAt=c),n}function ut(e,t={}){let r=[];if(!ee(e))return b(r,"","strategy must be a plain object"),{ok:!1,errors:r,strategy:null};ge(e,zr,"",r);for(let c of zr)(!(c in e)||e[c]==null)&&b(r,c,"required field is missing");e.version!==ct&&b(r,"version",`must be ${ct}`),(typeof e.id!="string"||!Qr.test(e.id))&&b(r,"id","must match /^[a-z0-9][a-z0-9._-]{0,63}$/"),(typeof e.name!="string"||e.name.length===0||e.name.length>Wr)&&b(r,"name",`must be a non-empty string max ${Wr}`);let n=it(e.venue);n||b(r,"venue",`unknown strategy venue "${String(e.venue)}"`);let o=null;if(!n)ee(e.market)||b(r,"market","must be a plain object");else{let c=n.validateMarket(e.market);if(!c||typeof c.ok!="boolean"||!Array.isArray(c.errors))b(r,"market",`venue ${n.id} returned an invalid market validation result`);else if(c.ok)o=c.market;else for(let d of c.errors)b(r,d.path,d.message)}let s=fs(e.parameters,r),i=null,a=new Map;if(!Array.isArray(e.nodes))b(r,"nodes","must be an array");else if(e.nodes.length>Yr)b(r,"nodes",`too many nodes (max ${Yr})`);else{i=[];for(let c=0;c<e.nodes.length;c++){let d=ds(e.nodes[c],c,s||{},r);d&&(typeof d.id=="string"&&en.test(d.id)&&(a.has(d.id)?b(r,`nodes.${c}.id`,`duplicate node id "${d.id}"`):a.set(d.id,d)),i.push(d))}for(let c=0;c<i.length;c++){let d=i[c],m=`nodes.${c}`;for(let p of lt(d))a.has(p)||b(r,m,`unknown node ref "${p}"`);if(d.type==="indicator"||d.type==="compare"||d.type==="cross")for(let p of lt(d)){let w=a.get(p);w&&zt.has(w.type)&&b(r,m,`node ref "${p}" must be numeric`)}if(d.type==="logic")for(let p of lt(d)){let w=a.get(p);w&&!zt.has(w.type)&&b(r,m,`node ref "${p}" must be boolean`)}}us(a)&&b(r,"nodes","graph contains a cycle")}let l=null;if(!ee(e.rules))b(r,"rules","must be a plain object");else{ge(e.rules,Vt,"rules",r);for(let c of Vt)c in e.rules||b(r,`rules.${c}`,"required field is missing");l={};for(let c of Vt){let d=e.rules[c];if(d===null){l[c]=null;continue}if(typeof d!="string"||!d){b(r,`rules.${c}`,"must be a node id or null"),l[c]=d;continue}if(!a.has(d)){b(r,`rules.${c}`,`unknown node ref "${d}"`),l[c]=d;continue}let m=a.get(d);zt.has(m.type)||b(r,`rules.${c}`,`rule must reference a boolean node, not ${m.type}`),l[c]=d}}let f=ps(e.risk,r,t);if(r.length)return{ok:!1,errors:r,strategy:null};let u=Gt({version:ct,id:e.id,name:e.name,venue:n.id,market:o,parameters:s,nodes:i,rules:l,risk:f});return{ok:!0,errors:[],strategy:u}}function W(e,t={}){let r=ut(e,t);if(!r.ok)throw new Oe(r.errors);return r.strategy}function rn(e){let t=W(e);return JSON.stringify(Kt(t))}function Ae(e){let t=rn(e);return ts("sha256").update(t,"utf8").digest("hex")}function _e(e,t){if(!ee(e))throw new Oe([{path:"",message:"strategy must be a plain object"}]);if(!ee(t))throw new Oe([{path:"overrides",message:"must be a plain object"}]);let r=W(e),n={};for(let[s,i]of Object.entries(r.parameters))n[s]={value:i.value,min:i.min,max:i.max,step:i.step};let o=[];for(let[s,i]of Object.entries(t)){if(!Object.prototype.hasOwnProperty.call(n,s)){b(o,s,`unknown parameter "${s}"`);continue}let a=n[s];if(!z(i)){b(o,s,"override must be a finite number");continue}if(!tn(i,a.min,a.max,a.step)){b(o,s,"override must lie on the declared min/max/step grid");continue}n[s]={...a,value:i}}if(o.length)throw new Oe(o);return W({version:r.version,id:r.id,name:r.name,venue:r.venue,market:{coin:r.market.coin,interval:r.market.interval},parameters:n,nodes:r.nodes.map(s=>{let i={...s};return Array.isArray(s.inputs)&&(i.inputs=[...s.inputs]),i}),rules:{...r.rules},risk:{...r.risk}})}var ms=50;function ie(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function nn(e,t,r){if(!Array.isArray(e))throw new TypeError(`${r} must be an array`);let n=0;for(let o=0;o<e.length;o++){let s=ie(e[o]?.px,`${r}[${o}].px`),i=ie(e[o]?.sz,`${r}[${o}].sz`);if(i<0)throw new TypeError(`${r}[${o}].sz must be non-negative`);Math.abs((s-t)/t)*1e4<=ms&&(n+=i)}return n}async function hs(e,t={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("sampleLiveSeries input must be an object");let r=String(e.coin||"").trim().toUpperCase();if(!/^[A-Z0-9][A-Z0-9._-]{0,11}$/.test(r))throw new TypeError("coin must be an uppercase Hyperliquid asset id");if(!Number.isSafeInteger(e.nowMs)||e.nowMs<=0)throw new TypeError("nowMs is required integer epoch ms");let[n,o]=await Promise.all([Or(t),Ar(r,t)]),s=n?.[0]?.universe,i=n?.[1];if(!Array.isArray(s)||!Array.isArray(i))throw new TypeError("metaAndAssetCtxs payload malformed");let a=s.findIndex(w=>w?.name===r);if(a<0)throw new Error(`unknown coin: ${r}`);let l=i[a];if(!l||typeof l!="object")throw new TypeError("asset ctx malformed");let f=ie(l.premium,"ctx.premium"),u=ie(l.openInterest,"ctx.openInterest");if(u<0)throw new TypeError("ctx.openInterest must be non-negative");let c=ie(l.midPx,"ctx.midPx"),d=o?.levels;if(!Array.isArray(d)||d.length!==2)throw new TypeError("l2Book levels malformed");let m=nn(d[0],c,"book.bids"),p=nn(d[1],c,"book.asks");if(m+p<=0)throw new TypeError("book depth near mid is empty");return Object.freeze({coin:r,t:e.nowMs,premium:f,openInterest:u,book:Object.freeze({bidDepth:m,askDepth:p})})}function ys(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("snapshots must be a non-empty array");let t=e[0]?.coin,r=[],n=null;for(let o=0;o<e.length;o++){let s=e[o];if(!s||typeof s!="object")throw new TypeError(`snapshots[${o}] must be an object`);if(s.coin!==t)throw new TypeError("snapshots must be a single coin");let i=ie(s.t,`snapshots[${o}].t`);if(n!=null&&!(i>n.t))throw new TypeError("snapshot times must be strictly increasing");let a=ie(s.premium,`snapshots[${o}].premium`),l=ie(s.openInterest,`snapshots[${o}].openInterest`),f=ie(s.book?.bidDepth,`snapshots[${o}].book.bidDepth`),u=ie(s.book?.askDepth,`snapshots[${o}].book.askDepth`),c=f+u;if(!(c>0))throw new TypeError(`snapshots[${o}] book depth must be positive`);r.push({coin:t,t:i,premium:a,openInterest:l,oiDelta:n==null?null:l-n.openInterest,bookImbalance:(f-u)/c}),n={t:i,openInterest:l}}return r}function ws(e,t,r){if(!Array.isArray(e))throw new TypeError("bars must be an array");if(!Array.isArray(t))throw new TypeError("rows must be an array");if(!Number.isSafeInteger(r)||r<=0)throw new TypeError("intervalMs must be a positive integer");let n=0;return e.map(o=>{let s=o.t+r,i=null;for(;n<t.length&&t[n].t<s;)t[n].t>=o.t&&(i=t[n]),n+=1;if(!i)return{...o};let a={...o};return i.premium!=null&&(a.premium=i.premium),i.openInterest!=null&&(a.openInterest=i.openInterest),i.oiDelta!=null&&(a.oiDelta=i.oiDelta),i.bookImbalance!=null&&(a.bookImbalance=i.bookImbalance),a})}import{createHash as gs}from"node:crypto";var Wt=256,on=new Set(["netPnlUsd","profitFactor","sharpe","maxDrawdownPct"]);function sn(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 an(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Zt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Zt(t);return Object.freeze(e)}for(let t of Object.keys(e))Zt(e[t]);return Object.freeze(e)}function Ke(e){if(Array.isArray(e))return e.map(Ke);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Ke(e[r]);return t}return e}function ft(e){return JSON.stringify(Ke(e))}function bs(e){let{min:t,max:r,step:n}=e;if(!(n>0)||t>r)return[];let o=[],s=Math.floor((r-t)/n+1e-9);for(let a=0;a<=s;a++){let l=t+a*n;if(l>r+1e-9)break;let f=Math.abs(l-Math.round(l))<1e-9?Math.round(l):Number(l.toPrecision(12));f<t-1e-9||f>r+1e-9||o.push(f)}if(o.length===0)return[];let i=o[o.length-1];if(Math.abs(i-r)>1e-9){let a=(r-t)/n;Math.abs(a-Math.round(a))<=1e-9&&o.push(r)}return o}function Es(e,t){if(e.length===0)return[];let r=[{}];for(let n of e){let o=t[n],s=[];for(let i of r)for(let a of o)s.push({...i,[n]:a});r=s}return r.sort((n,o)=>{let s=ft(n),i=ft(o);return s<i?-1:s>i?1:0}),r}function Yt(e,t,r,n,o){let s=0;if(e==="maxDrawdownPct"){if(s=t.maxDrawdownPct-n.maxDrawdownPct,s!==0)return s<0}else if(s=t[e]-n[e],s!==0)return s>0;let i=ft(r),a=ft(o);return i<a}function Xt(e,t,r={}){if(!an(r))throw new TypeError("options must be a plain object");for(let x of Object.keys(r))if(sn(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>Wt)throw new TypeError(`maxTrials must be an integer 1..${Wt}`);o=x}let s=r.objective??"netPnlUsd";if(!on.has(s))throw new TypeError(`objective must be one of ${[...on].join("|")}`);let i=r.backtestOptions??{};if(!an(i))throw new TypeError("backtestOptions must be a plain object");for(let x of Object.keys(i))if(sn(x))throw new TypeError(`backtestOptions must not include holdout/test/oos key "${x}"`);let a=W(e),l=Object.keys(a.parameters).sort();if(l.length===0)throw new Error("optimizeStrategy requires at least one declared parameter");let f={},u=1;for(let x of l){let R=bs(a.parameters[x]);if(R.length===0)throw new Error(`parameter "${x}" produces an empty grid`);f[x]=R,u*=R.length}let c=Es(l,f);if(c.length===0)throw new Error("parameter grid is empty");let d=c.slice(0,o),m=[],p=null,w=null;for(let x of d){let R=_e(a,x),$=pe(R,t,i);w==null&&(w=$.config);let h={netPnlUsd:$.metrics.netPnlUsd,netPnlPct:$.metrics.netPnlPct,maxDrawdownPct:$.metrics.maxDrawdownPct,winRate:$.metrics.winRate,profitFactor:$.metrics.profitFactor,tradeCount:$.metrics.tradeCount,sharpe:$.metrics.sharpe,turnoverUsd:$.metrics.turnoverUsd},M={parameters:{...x},metrics:h};m.push(M),(!p||Yt(s,h,x,p.metrics,p.parameters))&&(p=M)}m.sort((x,R)=>Yt(s,x.metrics,x.parameters,R.metrics,R.parameters)?-1:Yt(s,R.metrics,R.parameters,x.metrics,x.parameters)?1:0);let g={...p.parameters},S=_e(a,g),j={strategyHash:Ae(a),compilerHash:we,trainBarsHash:ze(t),backtestConfig:w,objective:s,maxTrials:o,trialsRun:m.length,candidates:m,bestParameters:g,bestStrategy:S},P={id:gs("sha256").update(JSON.stringify(Ke(j)),"utf8").digest("hex"),...j};return Zt(Ke(JSON.parse(JSON.stringify(P))))}import{createHash as xs}from"node:crypto";var G=class extends Error{constructor(t){super(t),this.name="StrategyDraftError"}},Ss=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),ks=new Set(["BTC","ETH","SOL","HYPE"]),As=/\b(mnemonic|private\s*key|privkey|seed\s*phrase|seed\b|api[_-]?key|secret\s*key|wallet\s*key|passphrase)\b/i,Re="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.",Ts=Object.freeze({maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3}),Os=36e5,Ps=30*864e5,$s=864e5;function Is(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Qt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Qt(t);return Object.freeze(e)}for(let t of Object.keys(e))Qt(e[t]);return Object.freeze(e)}function _s(e){return String(e).trim().replace(/\s+/g," ")}function vs(e){let t=e.match(/\b(long|short)\b/i);return t?t[1].toLowerCase():null}function js(e){for(let r of ks)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 Ns(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 Ss.has(r)?r:null}function Rs(e){let t={...Ts},r=e.match(/stop\s*loss\s*(\d+(?:\.\d+)?)\s*%?/i);r&&(t.stopLossPct=Number(r[1]));let n=e.match(/take\s*profit\s*(\d+(?:\.\d+)?)\s*%?/i);n&&(t.takeProfitPct=Number(n[1]));let o=e.match(/leverage\s*(\d+(?:\.\d+)?)/i);o&&(t.maxLeverage=Number(o[1]));let s=e.match(/position\s*size\s*(\d+(?:\.\d+)?)\s*%?/i);s&&(t.positionSizePct=Number(s[1]));let i=e.match(/max\s*notional\s*(?:usd\s*)?\$?\s*(\d+(?:\.\d+)?)/i);return i&&(t.maxNotionalUsd=Number(i[1])),t}function Ms(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 Ls(e){let t=xs("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 Hs(e){let t=e.match(/\bema\s*(\d+)\s*cross(?:es)?\s*(above|below)\s*ema\s*(\d+)\b/i);if(!t)return null;let r=Number(t[1]),n=t[2].toLowerCase(),o=Number(t[3]);if(!(r>0)||!(o>0)||r===o)return null;let s=/\b(exit\s+on\s+reverse|reverse\s+exit)\b/i.test(e);return{kind:"ema_cross",fast:r,slow:o,direction:n,reverse:s}}function Fs(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 Cs(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 Ds(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 Us(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 qs(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 Bs(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 zs(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 cn(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 Vs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"c",type:"input",field:"close"},{id:"emaLeft",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_left_period"}},{id:"emaRight",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_right_period"}},{id:"cross",type:"cross",direction:a.direction,left:"emaLeft",right:"emaRight"}],f={entryLong:null,entryShort:null,exitLong:null,exitShort:null};if(e==="long"?f.entryLong="cross":f.entryShort="cross",a.reverse){let u=a.direction==="above"?"below":"above";l.push({id:"crossRev",type:"cross",direction:u,left:"emaLeft",right:"emaRight"}),e==="long"?f.exitLong="crossRev":f.exitShort="crossRev"}return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{ema_left_period:cn(a.fast),ema_right_period:cn(a.slow)},nodes:l,rules:f,risk:{...n,expiresAt:o}}}function Js({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"c",type:"input",field:"close"},{id:"rsi",type:"indicator",indicator:"rsi",input:"c",period:a.period},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"rsi",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function Gs({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"fr",type:"input",field:"fundingRate"},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"fr",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function Ks({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let l=[{id:"oi",type:"input",field:"openInterest"},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"oi",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:l,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}var Ys=Object.freeze({funding:"fundingRate",open_interest:"openInterest",premium:"premium",oi_delta:"oiDelta",book_imbalance:"bookImbalance"});function Ws({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:i,spec:a}){let f=[{id:"sig_input",type:"input",field:Ys[a.kind]},{id:"thr",type:"constant",value:a.threshold},{id:"sig",type:"compare",op:a.op==="above"?"gt":"lt",left:"sig_input",right:"thr"}];return{version:1,id:s,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:f,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function er(e,t={}){if(typeof e!="string")throw new G("prompt must be a string");if(e.length>1e3)throw new G("prompt length must be <= 1000");if(!Is(t))throw new G("options must be a plain object");if(!Number.isInteger(t.nowMs))throw new G("options.nowMs is required integer epoch ms");let r=t.nowMs,n=$s;if("expiresInMs"in t){if(!Number.isInteger(t.expiresInMs))throw new G("expiresInMs must be an integer");if(n=t.expiresInMs,n<Os||n>Ps)throw new G("expiresInMs must be between 1h and 30d")}if(As.test(e))throw new G(`prompt appears to contain secrets and is rejected. ${Re}`);let o=_s(e);if(!o)throw new G(`empty prompt. ${Re}`);if(Ms(o))throw new G(`duplicate interval or risk clause. ${Re}`);let s=vs(o),i=js(o),a=Ns(o);if(!s||!i||!a)throw new G(`could not parse side/coin/interval. ${Re}`);let l=Rs(o);if(!(l.maxLeverage>0)||l.maxLeverage>50)throw new G("leverage out of range");if(!(l.positionSizePct>0)||l.positionSizePct>100)throw new G("position size out of range");let f=r+n,u=Ls(o),c=`Draft ${i} ${s}`.slice(0,100),d=Hs(o),m=Fs(o),p=Cs(o),w=Ds(o),g=Us(o),S=qs(o),j=Bs(o),P=[d,m,p,w,g,S,j].filter(Boolean);if(P.length!==1)throw new G(`unsupported or ambiguous prompt. ${Re}`);if(!zs(o,P[0]))throw new G(`unsupported or ambiguous prompt. ${Re}`);let x,R=P[0],$={side:s,coin:i,interval:a,risk:l,expiresAt:f,id:u,name:c,spec:R};R.kind==="ema_cross"?x=Vs($):R.kind==="rsi"?x=Js($):R.kind==="open_interest"?x=Ks($):R.kind==="funding"?x=Gs($):x=Ws($);let h=ut(x,{nowMs:r});if(!h.ok)throw new G(`draft failed validation: ${h.errors.map(M=>M.message).join("; ")}`);return Qt(W(x,{nowMs:r}))}import me from"node:fs";import dt from"node:path";var rr=1,Zs=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function pt(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ae(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Xs(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Me(e,t="record"){if(Array.isArray(e)){e.forEach((r,n)=>Me(r,`${t}[${n}]`));return}if(pt(e))for(let[r,n]of Object.entries(e)){let o=Xs(r);if(Zs.some(s=>o.includes(s)))throw new Error(`shadow-store: forbidden secret-like field at ${t}.${r}`);Me(n,`${t}.${r}`)}}function Qs(e){if(typeof e!="string"||!e||!dt.isAbsolute(e))throw new Error("shadow-store: path must be an absolute path")}function ln(e){let t;try{t=me.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 ei(){return{version:rr,runners:[]}}function un(e,t){let r;try{r=JSON.parse(e)}catch{throw new Error("shadow-store: malformed JSON")}if(!pt(r))throw new Error("shadow-store: malformed JSON root");if(r.version!==rr)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 Me(r,dt.basename(t)),{version:rr,runners:r.runners.map(n=>ae(n))}}function fn(e,t){Me(t,"store");let r=dt.dirname(e);me.mkdirSync(r,{recursive:!0,mode:448});let n=dt.join(r,`.shadow-store.${process.pid}.${Date.now()}.tmp`),o=`${JSON.stringify(t)}
|
|
3
|
+
`;try{me.writeFileSync(n,o,{mode:384,flag:"wx"}),me.renameSync(n,e);try{me.chmodSync(e,384)}catch{}}catch(s){try{me.unlinkSync(n)}catch{}throw s}}var tr=new Map;function nr(e={}){let t=e.path;if(Qs(t),ln(t),me.existsSync(t)?un(me.readFileSync(t,"utf8"),t):fn(t,ei()),tr.has(t))return tr.get(t);let r=!1,n=[];function o(){if(r)return;let p=n.shift();if(p){r=!0;try{let w=p.fn();r=!1,p.resolve(w),o()}catch(w){r=!1,p.reject(w),o()}}}function s(p){if(!r&&n.length===0){r=!0;try{return p()}finally{r=!1,queueMicrotask(o)}}return new Promise((w,g)=>{n.push({fn:p,resolve:w,reject:g}),queueMicrotask(o)})}function i(){return ln(t),un(me.readFileSync(t,"utf8"),t)}function a(p){fn(t,p)}function l(p){if(!pt(p)||typeof p.id!="string"||!p.id)throw new Error("shadow-store: create requires record with string id");Me(p,"record");let w=i();if(w.runners.some(S=>S.id===p.id))throw new Error(`shadow-store: runner id already exists: ${p.id}`);let g=ae(p);return w.runners.push(g),a(w),ae(g)}function f(p){let w=i().runners.find(g=>g.id===p);return w?ae(w):null}function u(){return i().runners.map(p=>ae(p))}function c(p,w){if(typeof w!="function")throw new Error("shadow-store: updater must be a function");let g=i(),S=g.runners.findIndex(x=>x.id===p);if(S<0)throw new Error(`shadow-store: runner not found: ${p}`);let j=ae(g.runners[S]),P=w(j);if(!pt(P)||P.id!==p)throw new Error("shadow-store: updater must return record with same id");return Me(P,"record"),g.runners[S]=ae(P),a(g),ae(g.runners[S])}function d(p){let w=i(),g=w.runners.findIndex(j=>j.id===p);if(g<0)throw new Error(`shadow-store: runner not found: ${p}`);let S=ae(w.runners[g]);return S.status!=="stopped"&&(S.status="stopped",w.runners[g]=S,a(w)),ae(w.runners[g])}let m={create(p){return s(()=>l(p))},get(p){return f(p)},list(){return u()},update(p,w){return s(()=>c(p,w))},stop(p){return s(()=>d(p))}};return tr.set(t,m),m}import{createHash as ir}from"node:crypto";function or(e){return e==null?e:JSON.parse(JSON.stringify(e))}function sr(e){return Array.isArray(e)?e.map(sr):e&&typeof e=="object"?Object.fromEntries(Object.keys(e).sort().map(t=>[t,sr(e[t])])):e}function pn(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("shadow-runner: record must be an object");return ir("sha256").update(JSON.stringify(sr(e))).digest("hex")}function ti(e,t,r,n,o){return ir("sha256").update(`${e}|${t}|${r}|${n}|${o}`).digest("hex")}function ri(e,t,r,n){return ir("sha256").update(`shadow|${e}|${t}|${r}|${n??""}`).digest("hex")}function ni(e){return e==="entryLong"||e==="exitShort"?"buy":e==="entryShort"||e==="exitLong"?"sell":e}function dn(e){return e==="entryLong"||e==="entryShort"}function mt({storePath:e,clock:t=Date.now}={}){if(typeof e!="string"||!e)throw new Error("shadow-runner: storePath required");let r=nr({path:e});function n({strategy:l,evidenceId:f=null}={}){let u=Y(l),c=f==null?null:String(f),d=r.list().filter(S=>S.status==="running"&&S.strategyHash===u.strategyHash&&S.compilerHash===u.compilerHash&&S.evidenceId===c).sort((S,j)=>S.createdAt-j.createdAt||S.id.localeCompare(j.id))[0];if(d)return or(d);let m=t(),p=ri(m,u.strategyHash,u.compilerHash,c),w=r.get(p);if(w)return or(w);let g={id:p,strategy:or(u.strategy),strategyHash:u.strategyHash,compilerHash:u.compilerHash,evidenceId:c,status:"running",cursor:null,intendedOrders:[],fills:[],missedFills:[],markouts:[],createdAt:m,updatedAt:m,position:null,cooldownBarsRemaining:0,cooldownStartT:null,lastProcessedBarIndex:-1};return r.create(g)}function o(l){return r.get(l)}function s(){return r.list()}function i(l){return r.stop(l)}function a(l,f,{markoutHorizons:u=[1,4,12]}={}){if(!Array.isArray(f))throw new TypeError("shadow-runner: bars must be an array");return r.update(l,c=>{if(c.status!=="running")throw new Error("shadow-runner: runner is stopped");if(f.length===0)return c;let m=Y(c.strategy).evaluateAll(f),p=new Map;for(let y=0;y<f.length;y++)p.set(f[y].t,y);let w=c.cursor,g=[];for(let y=0;y<f.length;y++){let I=f[y].t;(w==null||I>w)&&g.push(y)}if(g.length===0)return c;let S=new Map(c.intendedOrders.map(y=>[y.id,y])),j=new Set(c.fills.map(y=>y.orderId)),P=new Map(c.missedFills.map(y=>[y.orderId,y])),x=(y,I)=>`${y}|${I}`,R=new Map(c.markouts.map(y=>[x(y.orderId,y.horizon),y])),$=c.position?{...c.position}:null,h=Number.isInteger(c.cooldownBarsRemaining)?Math.max(0,c.cooldownBarsRemaining):0,M=Number.isFinite(c.cooldownStartT)?c.cooldownStartT:null;function D({action:y,signalBarT:I,signalIndex:_}){let C=ni(y),L=ti(c.id,c.strategyHash,I,C,y);if(S.has(L))return S.get(L);let N=_+1,T=N<f.length,v={id:L,action:y,type:y,side:C,signalBarT:I,fillBarT:T?f[N].t:null,status:T?"open":"missed"};return S.set(L,v),c.intendedOrders.push(v),v}function K(y,I,_){if(j.has(y.id))return;let C={orderId:y.id,action:dn(y.action)?"entry":"exit",side:y.side,price:I.o,barT:I.t,signalBarT:y.signalBarT,barIndex:_};if(c.fills.push(C),j.add(y.id),y.status="filled",y.fillBarT=I.t,P.has(y.id)&&(P.delete(y.id),c.missedFills=c.missedFills.filter(L=>L.orderId!==y.id)),dn(y.action)){$={side:y.action==="entryLong"?"long":"short",entryOrderId:y.id,entryBarT:I.t,entryPrice:I.o,entryBarIndex:_};for(let L of u){let N=x(y.id,L);if(R.has(N))continue;let T={orderId:y.id,horizon:L,entryBarT:I.t,entryPrice:I.o,side:$.side,status:"pending",close:null,barT:null};R.set(N,T),c.markouts.push(T)}}else $=null,h=Number(c.strategy?.risk?.cooldownBars)||0,M=I.t}function k(y){if(j.has(y.id)||P.has(y.id))return;let I={orderId:y.id,action:y.action,side:y.side,signalBarT:y.signalBarT,status:"missed"};P.set(y.id,I),c.missedFills.push(I),y.status="missed"}for(let y of c.intendedOrders){if(y.status==="filled"||j.has(y.id))continue;let I=p.get(y.signalBarT);if(I==null)continue;let _=I+1;_<f.length&&(w==null||f[_].t>w)&&K(y,f[_],_)}for(let y of g){let I=f[y],_=m[y].signals,C=$,L=T=>{if($||h>0&&(M==null||I.t>=M))return;let O=D({action:T,signalBarT:I.t,signalIndex:y}),X=y+1;X<f.length?K(O,f[X],X):k(O)},N=T=>{if(!$||$.side==="long"&&T!=="exitLong"||$.side==="short"&&T!=="exitShort")return;let v=D({action:T,signalBarT:I.t,signalIndex:y}),O=y+1;O<f.length?K(v,f[O],O):k(v)};C?(_.exitLong&&N("exitLong"),_.exitShort&&N("exitShort")):_.entryLong&&_.entryShort||(_.entryLong&&L("entryLong"),_.entryShort&&L("entryShort")),h>0&&M!=null&&I.t>=M&&(h-=1,h===0&&(M=null)),c.cursor=I.t,c.lastProcessedBarIndex=y}for(let y of c.markouts){if(y.status!=="pending")continue;let I=c.fills.find(L=>L.orderId===y.orderId&&L.action==="entry");if(!I)continue;let _=p.get(I.barT);if(_==null)continue;let C=_+y.horizon;if(C<f.length){y.close=f[C].c,y.barT=f[C].t,y.status="filled";let L=y.entryPrice;y.markout=y.side==="long"?(y.close-L)/L:(L-y.close)/L}}return c.position=$,c.cooldownBarsRemaining=h,c.cooldownStartT=M,c.updatedAt=t(),c})}return{start:n,step:a,list:s,get:o,stop:i}}import oi from"node:os";import si from"node:path";var ii=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Ye(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ai(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function cr(e){if(Array.isArray(e)){for(let t of e)cr(t);return}if(Ye(e))for(let[t,r]of Object.entries(e)){if(ii.some(n=>ai(t).includes(n)))throw new Error(`strategy service: secret-like field "${t}" is forbidden`);cr(r)}}function ci(e){if(!Ye(e))throw new TypeError("strategy input must be a plain object");return cr(e),e}function li(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 ar(e,t,r,n){if(Array.isArray(t.bars))return t.bars;let o=at(e.venue),s=r.fetchBars??o.fetchBars;if(typeof s!="function")throw new Error(`strategy venue ${o.id} does not support history`);r.signal?.throwIfAborted?.();let i=await s({coin:e.market.coin,interval:e.market.interval,count:t.count??1500,endTime:t.endTime??n},{signal:r.signal});r.signal?.throwIfAborted?.();let a=Array.isArray(i)?i:i?.bars;if(!Array.isArray(a))throw new Error("strategy history provider returned no bars");return a}function lr(e,t){let r=e.backtestOptions??{};if(!Ye(r))throw new TypeError("backtestOptions must be a plain object");return{...r,nowMs:t}}function mn(e,t,r,n,o={}){let s=e.evidenceOptions??{};if(!Ye(s))throw new TypeError("evidenceOptions must be a plain object");return{...s,...o,strategy:t,bars:r,backtestOptions:lr(e,n)}}function hn(){return si.join(oi.homedir(),".oracle","strategy-shadow.json")}function ui(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 fi(e,t={},r={}){r.signal?.throwIfAborted?.();let n=ci(t),o=li(n,r);if(e==="draft")return{strategy:er(n.prompt,{nowMs:o})};if(e==="validate"){let s=Y(n.strategy);if(s.strategy.risk.expiresAt<=o)throw new Error("strategy is expired");return{valid:!0,strategy:s.strategy,strategyHash:s.strategyHash,compilerHash:s.compilerHash,compilerVersion:s.compilerVersion,requiredSeries:s.requiredSeries}}if(e==="backtest"||e==="evidence"){let s=Y(n.strategy),i=await ar(s.strategy,n,r,o);Ve(s,i);let a=st(mn(n,s.strategy,i,o));return e==="evidence"?a:{backtest:pe(s.strategy,i,lr(n,o)),evidence:a}}if(e==="optimize"){let s=Y(n.strategy),i=await ar(s.strategy,n,r,o);Ve(s,i);let a=n.trainFraction,l=n.evidenceOptions?.trainFraction;if(a!=null&&l!=null&&a!==l)throw new TypeError("conflicting trainFraction controls are forbidden");let f=a??l??.7;if(typeof f!="number"||f<=0||f>=1)throw new TypeError("trainFraction must be in (0,1)");let u=i.slice(0,Math.floor(i.length*f)),c=n.options??{};if(!Ye(c))throw new TypeError("options must be a plain object");let d=Xt(s.strategy,u,{...c,...n.maxTrials==null?{}:{maxTrials:n.maxTrials},backtestOptions:lr(n,o)}),m=d.bestStrategy;return{strategy:m,optimization:d,evidence:st(mn(n,m,i,o,{trainFraction:f}))}}if(e==="shadow"){let s=mt({storePath:r.storePath??hn(),clock:()=>o}),i=n.action;if(i==="start")return await s.start({strategy:n.strategy,evidenceId:n.evidenceId??n.evidence?.id??null});if(i==="list")return await s.list();if(i==="get")return await s.get(n.id);if(i==="stop")return await s.stop(n.id);if(i==="step"){let a=await s.get(n.id);if(!a)throw new Error(`shadow runner not found: ${n.id}`);let l=await ar(a.strategy,n,r,o);return Ve(Y(a.strategy),l),await s.step(n.id,l,n.stepOptions??{})}throw new Error(`unknown shadow action: ${i}`)}if(e==="prepare"){let s=Y(n.strategy),i=at(s.strategy.venue);if(typeof n.shadowId!="string"||!n.shadowId)throw new Error("strategy prepare requires a matching shadow runner id");let l=await mt({storePath:r.storePath??hn(),clock:()=>o}).get(n.shadowId);if(!l)throw new Error("strategy prepare shadow runner not found");if(l.status!=="running")throw new Error("strategy prepare requires an active shadow runner");if(!Number.isFinite(l.cursor))throw new Error("strategy prepare requires a stepped shadow runner");if(l.strategyHash!==s.strategyHash||l.compilerHash!==s.compilerHash)throw new Error("strategy prepare shadow runner does not match strategy artifacts");if(l.evidenceId!==n.evidence?.id)throw new Error("strategy prepare shadow runner does not match evidence artifact");let f=n.caps??ui(s.strategy,o);return i.prepareIntent({strategy:s.strategy,evidence:n.evidence,shadow:{id:l.id,stateHash:pn(l),status:l.status,cursor:l.cursor,updatedAt:l.updatedAt},caps:f,nowMs:o,env:r.env??process.env})}throw new Error(`unknown strategy operation: ${e}`)}export{Mr as EVIDENCE_STATUSES,Wt as MAX_OPTIMIZER_TRIALS,we as STRATEGY_COMPILER_HASH,Ie as STRATEGY_COMPILER_VERSION,ct as STRATEGY_VERSION,G as StrategyDraftError,Oe as StrategyValidationError,_e as applyParameterOverrides,Ft as assertEvidenceArtifact,_t as atr,ws as attachDerivedSeries,pe as backtestStrategy,It as bollinger,rn as canonicalStrategyJson,Y as compileStrategy,Ht as computeEvidenceArtifactId,mt as createShadowRunner,ys as deriveSeries,er as draftStrategyFromPrompt,qe as ema,st as evaluateEvidence,Bt as fetchHyperliquidStrategyBars,Dr as intervalToMs,$t as macd,Ur as normalizeHyperliquidCandles,W as normalizeStrategy,nr as openShadowStore,Xt as optimizeStrategy,qt as prepareStrategyLiveHandoff,at as requireStrategyVenue,it as resolveStrategyVenue,Pt as rsi,fi as runStrategyOperation,hs as sampleLiveSeries,Ot as sma,Ae as strategyHash,es as strategyVenues,ut as validateStrategy};
|