@oracle-agent/oracle 0.35.46 → 0.35.48
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/assets/skills/oracle-desk-product/SKILL.md +1 -1
- package/dist/bin/desk-server.mjs +39 -36
- package/dist/bin/oracle-data-mcp.mjs +20 -20
- package/dist/bin/oracle-telegram-mcp.mjs +1 -1
- package/dist/bin/oracle.mjs +1 -1
- package/dist/cli/commands/account.mjs +11 -11
- package/dist/cli/commands/chat.mjs +86 -86
- package/dist/cli/commands/data.mjs +38 -35
- package/dist/cli/commands/eval.mjs +145 -142
- package/dist/cli/commands/model.mjs +86 -86
- package/dist/cli/commands/strategy.mjs +10 -6
- package/dist/data/desk-data.mjs +31 -28
- package/dist/index.mjs +49 -46
- package/dist/strategy/index.mjs +5 -5
- package/dist/tui/standalone-client.mjs +38 -38
- package/package.json +1 -1
- 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,5 +1,5 @@
|
|
|
1
|
-
import{createHash as ks}from"node:crypto";import{createHash as Yn}from"node:crypto";import{types as me}from"node:util";import{AsyncLocalStorage as Dn}from"node:async_hooks";var Bn=new Dn,Un=["http","retry","shared"],qn=512;function nt(e){let t=Bn.getStore();if(!t||t.closed||!Un.includes(e))return null;if(t.spans.length>=qn)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 Ae from"node:net";import zn from"node:dns";var Vn=new Set(["localhost","metadata.google.internal","metadata.goog"]);function ot(e){let t=String(e).toLowerCase().split("%")[0];if((t.match(/::/g)||[]).length>1)return null;let r=u=>{if(!u)return[];let l=u.split(":"),p=l.at(-1);if(p?.includes(".")){let h=p.split(".").map(Number);if(h.length!==4||h.some(d=>!Number.isInteger(d)||d<0||d>255))return null;l.splice(l.length-1,1,(h[0]<<8|h[1]).toString(16),(h[2]<<8|h[3]).toString(16))}return l.some(h=>!/^[0-9a-f]{1,4}$/.test(h))?null:l.map(h=>Number.parseInt(h,16))},[n,o]=t.split("::"),s=r(n),a=r(o);if(!s||!a)return null;let i=t.includes("::"),c=8-s.length-a.length;if(!i&&c!==0||i&&c<1)return null;let f=[...s,...Array(Math.max(0,c)).fill(0),...a];return f.length!==8?null:Uint8Array.from(f.flatMap(u=>[u>>8,u&255]))}function Tt(e,t,r){let n=Math.floor(r/8),o=r%8;for(let a=0;a<n;a+=1)if(e[a]!==t[a])return!1;if(!o)return!0;let s=255<<8-o;return(e[n]&s)===(t[n]&s)}function Ot(e){if(Ae.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(Ae.isIPv6(e)){let t=ot(e);if(!t)return!1;let r=ot("::ffff:0:0");return Tt(t,r,96)?Ot([...t.slice(12)].join(".")):Tt(t,ot("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([o,s])=>Tt(t,ot(o),s)):!1}return!1}function Jn(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(Vn.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=Ae.isIP(r);return n!==0&&!Ot(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function $t(e,{lookupFn:t=zn.promises.lookup}={}){let r=Jn(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:Ae.isIPv6(r.host)?6:4}]};let n;if(process.env.ORACLE_HOSTED_EGRESS_PROXY)return{ok:!0,url:r.url,addresses:[]};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=>!Ot(o.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}function Gn(e=process.env){let t=e.ORACLE_HOSTED_EGRESS_PROXY||"";if(!t)return null;let r;try{r=new URL(t)}catch{throw new Error("egress-guard: ORACLE_HOSTED_EGRESS_PROXY is not a URL")}if(r.protocol!=="http:"||!["127.0.0.1","::1","localhost","[::1]"].includes(r.hostname)||!r.port||r.username||r.password)throw new Error("egress-guard: egress proxy must be an exact loopback http origin");let n=e.ORACLE_HOSTED_EGRESS_TOKEN||"";if(!/^[A-Za-z0-9_-]{43}$/.test(n))throw new Error("egress-guard: egress proxy token is missing");return{uri:r.origin,token:n}}async function _t({requireUndici:e=!1,importUndici:t=()=>import("undici")}={}){let r,n,o;try{o=await t(),r=o.Agent,n=o.fetch}catch(h){if(e)throw new Error(`egress-guard: untrustedUrl pinning requires the undici package, which failed to load: ${h?.message||h}`);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 s=h=>String(h).toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,""),a=new Map,i=h=>(Array.isArray(h)?h:[h]).map(d=>typeof d=="string"?{address:d}:d).filter(d=>d&&d.address).map(d=>({address:d.address,family:d.family||(Ae.isIPv6(d.address)?6:4)})),c=(h,d,m)=>{a.set(s(h),i(typeof d=="string"?[{address:d,family:m}]:d))},f=h=>{let d=s(h);if(Ae.isIP(d))return[{address:d,family:Ae.isIPv6(d)?6:4}];let m=a.get(d);if(!m||!m.length)throw new Error(`refused: unpinned host ${h} during pinned fetch`);return m},u=Gn(),l=u&&typeof o.ProxyAgent=="function"?new o.ProxyAgent({uri:u.uri,token:`Bearer ${u.token}`,connectTimeout:1e4}):new r({connect:{lookup(h,d,m){let w;try{w=f(h)}catch(k){return m(k)}return d?.all?m(null,w):m(null,w[0].address,w[0].family)}}}),p=Kn((h,d={})=>n(h,{...d,dispatcher:l}),c);return{dispatcher:l,fetch:p,pin:c,resolve:f,async close(){try{await l.destroy()}catch{}}}}var vt=Symbol.for("oracle.egressGuard.pinCapableFetch");function Kn(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[vt]=Object.freeze({pin:t}),e}function It(e){return typeof e=="function"&&typeof e[vt]?.pin=="function"}function Or(e,t,r){if(!It(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[vt].pin(t,r)}var Wn=new Set([408,425,429,500,502,503,504]),$r=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),Xn=2,_r=4e3,Zn=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"aborted")?.get,Qn=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"reason")?.get,eo=AbortSignal.prototype.throwIfAborted,to=EventTarget.prototype.addEventListener,vr=EventTarget.prototype.removeEventListener,Ir=typeof AbortSignal.any=="function"?AbortSignal.any.bind(AbortSignal):null,ze=e=>e?Zn.call(e):!1,ro=e=>e?Qn.call(e):void 0,no=new Set([301,302,303,307,308]),it=3,ra=64*1024,he=Object.freeze({depth:32,nodes:1e4,fields:1e4,arrayLength:1e4,bytes:1024*1024});function V(e){return ge(`HTTP JSON body refused: ${e}`)}function oo(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 me[t]=="function"&&me[t](e))}function so(e){let t=[],r=0,n=0,o=0,s=0,a=new WeakSet,i=u=>{if(r+=Buffer.byteLength(u,"utf8"),r>he.bytes)throw V("serialized byte limit exceeded");t.push(u)},c=u=>{if(Buffer.byteLength(u,"utf8")>he.bytes)throw V("serialized byte limit exceeded");return JSON.stringify(u)},f=(u,l)=>{if(n+=1,n>he.nodes)throw V("node limit exceeded");if(l>he.depth)throw V("depth limit exceeded");if(u===null){i("null");return}if(typeof u=="string"){i(c(u));return}if(typeof u=="boolean"){i(u?"true":"false");return}if(typeof u=="number"){if(!Number.isFinite(u))throw V("non-finite number");i(Object.is(u,-0)?"0":String(u));return}if(typeof u!="object")throw V("unsupported non-JSON value");if(me.isProxy(u))throw V("proxy value");if(oo(u))throw V("unsupported exotic object");if(a.has(u))throw V("cyclic value");a.add(u);try{if(Object.getOwnPropertySymbols(u).length>0)throw V("symbol-keyed fields are unsupported");if(Array.isArray(u)){let d=Object.getPrototypeOf(u),m=0;for(;d!==null;){if(me.isProxy(d))throw V("proxy array prototype");if(m+=1,m>he.depth)throw V("array prototype depth limit exceeded");d=Object.getPrototypeOf(d)}if(u.length>he.arrayLength)throw V("array length limit exceeded");for(let k=0;k<u.length;k+=1){let S=Object.getOwnPropertyDescriptor(u,String(k));if(!S||!Object.hasOwn(S,"value")||S.enumerable!==!0)throw V("array entries must be dense enumerable own data")}let w=0;for(let k in u){if(s+=1,s>he.fields)throw V("enumeration limit exceeded");if(Object.hasOwn(u,k)&&(w+=1,w>u.length))throw V("named array fields are unsupported")}if(w!==u.length)throw V("array entries must be dense enumerable own data");i("[");for(let k=0;k<u.length;k+=1)k&&i(","),f(Object.getOwnPropertyDescriptor(u,String(k)).value,l+1);i("]");return}let p=Object.getPrototypeOf(u);if(p!==Object.prototype&&p!==null)throw V("non-plain object");let h=[];for(let d in u){if(s+=1,s>he.fields)throw V("enumeration limit exceeded");if(!Object.hasOwn(u,d))continue;if(o+=1,o>he.fields)throw V("field limit exceeded");let m=Object.getOwnPropertyDescriptor(u,d);if(!m||!Object.hasOwn(m,"value")||m.enumerable!==!0)throw V("object fields must be enumerable own data");h.push([d,m.value])}i("{");for(let d=0;d<h.length;d+=1)d&&i(","),i(c(h[d][0])),i(":"),f(h[d][1],l+1);i("}")}finally{a.delete(u)}};return f(e,0),t.join("")}function io(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(me.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 a=s.value;if(a==null||["object","function","symbol"].includes(typeof a))throw new TypeError("HTTP header values must be scalar");t[n]=String(a)}return t}function ao(){return Object.assign(Object.create(null),{Accept:"application/json"})}function co(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 lo(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}var Rt=new Map,Rr=new WeakMap,jr=1;function st(e){if((typeof e!="object"||e===null)&&typeof e!="function")return`${typeof e}:${String(e)}`;let t=Rr.get(e);return t||(t=jr,jr+=1,Rr.set(e,t)),`reference:${t}`}var uo=new Set(["eth_blockNumber","eth_call","eth_chainId","eth_estimateGas","getHealth","minimumLedgerSlot","net_version","simulateTransaction","web3_clientVersion"]),fo=new Set(["allMids","l2Book","outcomeMeta","spotClearinghouseState","userFills","meta","metaAndAssetCtxs","perpDexs","candleSnapshot","fundingHistory","openOrders","frontendOpenOrders","clearinghouseState","spotMeta","validatorSummaries","delegatorSummary","delegations","delegatorRewards","delegatorHistory","maxBuilderFee"]);function Mr(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?uo.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 Nr(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(Mr);if(!r||typeof r!="object")return!1;if(Object.hasOwn(r,"jsonrpc")||Object.hasOwn(r,"method"))return Mr(r);let n=Object.hasOwn(r,"type")?r.type:null;return typeof n=="string"&&fo.has(n)&&(!Object.hasOwn(r,"action")||r.action==null)&&(!Object.hasOwn(r,"signature")||r.signature==null)&&(!Object.hasOwn(r,"nonce")||r.nonce==null)}function po(e,t,r,n={},o=null){let s=Yn("sha256"),a=(c,f)=>{let u=String(f);s.update(String(Buffer.byteLength(c,"utf8"))).update(":").update(c),s.update("=").update(String(Buffer.byteLength(u,"utf8"))).update(":").update(u).update(`
|
|
2
|
-
`)};a("method",e),a("url",t),Object.keys(r||{}).map((c,f)=>({name:c.toLowerCase(),order:f,value:String(r[c])})).sort((c,f)=>c.name.localeCompare(f.name)||c.order-f.order).forEach((c,f)=>{a(`header-name-${f}`,c.name),a(`header-value-${f}`,c.value)}),a("body",o??"-");for(let c of["untrustedUrl","maxResponseBytes","sameOriginRedirectsOnly","redirectPolicy","maxRedirects","timeoutMs","retries","fetchImpl","realFetch","lookupFn","importUndici","validateResponse"])a(`context-${c}`,n[c]??"-");return s.digest("hex")}function ho(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,_r):Math.min(250*2**e,_r)+Math.floor(Math.random()*100)}var mo=e=>new Promise(t=>setTimeout(t,e));function ge(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function jt(e,t,r){return ge(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function Te(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function yo(e){return e?e.byteLength??e.length??0:0}async function wo(e,t,{url:r,truncate:n=!1,onOversize:o}={}){if(t==null)return await e.text();let s=Number(e.headers?.get?.("content-length"));if(Number.isFinite(s)&&s>t&&(Te(e),!n))throw jt(r,`content-length ${s}`,t);let a=e.body?.getReader?.();if(!a){let l=await e.text(),p=Buffer.byteLength(l,"utf8");if(p>t){if(!n)throw jt(r,`body ${p} bytes`,t);return Buffer.from(l,"utf8").subarray(0,t).toString("utf8")}return l}let i=[],c=0,f=!1;try{for(;;){let{value:l,done:p}=await a.read();if(p)break;if(l&&(i.push(Buffer.from(l)),c+=yo(l),c>t)){f=!0;break}}}finally{if(f)try{await a.cancel()}catch{}try{a.releaseLock?.()}catch{}}if(f&&(typeof o=="function"&&o(),!n))throw jt(r,`streamed ${c} bytes`,t);let u=Buffer.concat(i);return(f?u.subarray(0,t):u).toString("utf8")}function go(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function bo(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:s,lookupFn:a,realFetch:i,untrustedUrl:c=!1,maxResponseBytes:f=null,sameOriginRedirectsOnly:u=!1,importUndici:l,validateResponse:p,signal:h,redirectPolicy:d="follow",maxRedirects:m=it}){let w=null,k=t,S=a?{lookupFn:a}:{};if(c&&!i&&!It(k))throw ge(`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),M=h?Ir?Ir([h,P.signal]):h:P.signal,_=async(y,{status:N=null}={})=>{let D=await $t(y,S);if(!D.ok)throw ge(N==null?`HTTP refused ${y}: ${D.error}`:`HTTP redirect to ${y} ${D.error}`,N==null?{}:{status:N});let Y=new URL(y).hostname;if(i){if(w&&(await w.close(),w=null),!w)try{w=await _t({requireUndici:!0,...l?{importUndici:l}:{}})}catch(A){throw ge(N==null?`HTTP refused ${y}: ${A?.message||A}`:`HTTP redirect to ${y} refused: ${A?.message||A}`,N==null?{}:{status:N})}w.pin(Y,D.addresses),k=w.fetch}else Or(k,Y,D.addresses);return D};try{let y=String(e),N=Object.assign(Object.create(null),n||{});c&&await _(y);for(let D=0;D<=m;D+=1){let Y=Object.assign(Object.create(null),{method:r,headers:N,body:o,signal:M,redirect:"manual",dispatcher:void 0}),A=await k(y,Y);if((d==="error"||m===0)&&A.status>=300&&A.status<400)throw Te(A),ge(`HTTP ${A.status} ${r} redirect refused`,{status:A.status,redirectRefused:!0});if(no.has(A.status)){let I=u===!0&&r==="POST"&&[307,308].includes(A.status)&&Nr(r,o);if(r!=="GET"&&r!=="HEAD"&&!I){Te(A);let O=new Error(`HTTP ${A.status} ${r} ${y} redirected non-idempotent request`);throw O.status=A.status,O}if(D===m)throw Te(A),ge(`HTTP ${A.status} ${r} redirect budget exhausted`,{status:A.status,redirectRefused:!0});let C=A.headers?.get?.("location"),L;try{L=co(C,y)}catch(O){throw Te(A),O}let j=!lo(L,y);if(Te(A),j&&r==="POST"){let O=new Error(`HTTP ${A.status} ${r} cross-origin redirect refused`);throw O.status=A.status,O}if(j&&u){let O=new Error(`HTTP ${A.status} ${r} cross-origin redirect refused`);throw O.status=A.status,O.retryable=!1,O}if(j&&(N=ao(N)),c)await _(L,{status:A.status});else if(j){let O=await $t(L,S);if(!O.ok){let R=new Error(`HTTP redirect from ${y} ${O.error}`);throw R.status=A.status,R.retryable=!1,R}i&&O.addresses?.length&&(w||(w=await _t(l?{importUndici:l}:{})),w&&(w.pin(new URL(L).hostname,O.addresses),k=w.fetch))}y=L;continue}if(typeof p=="function")try{await p(A,{url:y})}catch(I){throw Te(A),ge(I?.message||String(I))}let g=await wo(A,f,{url:y,onOversize:()=>P.abort()}),v=go(g);if(!A.ok){let I=new Error(`HTTP ${A.status} ${r} ${y}`);throw I.status=A.status,I.retryAfter=A.headers?.get?.("retry-after")??null,I.body=v??g.slice(0,300),I}return v??g}throw new Error(`HTTP redirect loop for ${e}`)}catch(y){if(P.signal.aborted&&!ze(h)){let N=y&&(typeof y=="object"||typeof y=="function")&&!me.isProxy(y)?y:null,D=N?Object.getOwnPropertyDescriptor(N,"oversize"):null;if(!(D&&Object.hasOwn(D,"value")&&D.value===!0))try{if(!N)throw new TypeError("unsafe rejection");Object.defineProperties(N,{oracleTimeout:{value:!0,enumerable:!1},retryable:{value:!1,enumerable:!1}})}catch{let A=new Error("HTTP request timed out");throw Object.defineProperties(A,{oracleTimeout:{value:!0,enumerable:!1},retryable:{value:!1,enumerable:!1}}),A}}throw y}finally{clearTimeout(x),w&&await w.close()}}async function Lr(e,t={}){if(t!=null&&typeof t!="object"&&typeof t!="function")throw new TypeError("HTTP options must be an object");if(t!=null&&me.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 R of Object.getOwnPropertyNames(t)){let $=Object.getOwnPropertyDescriptor(t,R);if(!(R==="toJSON"&&$&&Object.hasOwn($,"value")&&$.value===void 0)){if(!r.has(R))throw new TypeError("HTTP options contain unknown fields");if(!$||!$.enumerable||!Object.hasOwn($,"value"))throw new TypeError("HTTP options must contain enumerable own data properties")}}}let n=R=>{if(t==null||!Object.hasOwn(t,R))return;let $=Object.getOwnPropertyDescriptor(t,R);if(!$||!Object.hasOwn($,"value"))throw new TypeError("HTTP options must contain own data properties");return $.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 a=n("retries");if(a!==void 0&&(!Number.isInteger(a)||a<0||a>10))throw new TypeError("HTTP retries must be a bounded integer");let i=n("redirectPolicy");if(i!==void 0&&i!=="follow"&&i!=="error")throw new TypeError('HTTP redirectPolicy must be "follow" or "error"');let c=n("maxRedirects");if(c!==void 0&&(!Number.isInteger(c)||c<0||c>it))throw new TypeError(`HTTP maxRedirects must be an integer from 0 through ${it}`);if(i==="error"&&c!==void 0&&c!==0)throw new TypeError('HTTP redirectPolicy "error" requires maxRedirects 0 when supplied');let f=i??"follow",u=f==="error"?0:c??it;for(let R of["dedupe","untrustedUrl","sameOriginRedirectsOnly"]){let $=n(R);if($!==void 0&&typeof $!="boolean")throw new TypeError(`HTTP ${R} must be boolean`)}let l=n("maxResponseBytes");if(l!==void 0&&(!Number.isInteger(l)||l<1||l>64*1024*1024))throw new TypeError("HTTP maxResponseBytes must be a bounded integer");let p=n("signal");if(p!==void 0){if(me.isProxy(p)||!(p instanceof AbortSignal))throw new TypeError("HTTP signal must be a native AbortSignal");try{ze(p)}catch{throw new TypeError("HTTP signal must be a native AbortSignal")}}for(let R of["importUndici","lookupFn","validateResponse"]){let $=n(R);if($!==void 0&&typeof $!="function")throw new TypeError(`HTTP ${R} must be a function`)}let h=n("fetchImpl"),d=h||globalThis.fetch;if(typeof d!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let m=s??12e3,w=(o||"GET").toUpperCase(),k=n("headers"),S=io(k),P=Object.assign(Object.create(null),S);Object.keys(P).some(R=>R.toLowerCase()==="accept")||(P.Accept="application/json");let x=n("body");x!=null&&typeof x!="string"&&(Object.keys(P).find($=>$.toLowerCase()==="content-type")||(P["Content-Type"]="application/json"),x=so(x));let M=a??Xn,_=n("lookupFn"),y=!h,N=n("untrustedUrl")===!0,D=n("sameOriginRedirectsOnly")===!0,Y=n("importUndici"),A=n("validateResponse"),g=p,v=l??null,I=async()=>{let R;for(let $=0;$<=M;$++){g&&eo.call(g);let Q=nt("http");try{let Z=await bo(e,{fetchImpl:d,method:w,headers:P,body:x,timeoutMs:m,lookupFn:_,realFetch:y,untrustedUrl:N,maxResponseBytes:v,sameOriginRedirectsOnly:D,importUndici:Y,validateResponse:A,signal:g,redirectPolicy:f,maxRedirects:u});return Q?.("succeeded"),Z}catch(Z){R=Z;let ne=Se=>{if(!Z||typeof Z!="object"&&typeof Z!="function"||me.isProxy(Z))return;let de=Object.getOwnPropertyDescriptor(Z,Se);return de&&Object.hasOwn(de,"value")?de.value:void 0},fe=ne("status");Q?.("failed",fe);let tt=ne("oracleTimeout")===!0||ne("name")==="AbortError"||ne("name")==="TimeoutError"||ze(g),rt=new Set([408,425,429]),Pr=ne("retryable")===!1?!1:fe!=null?rt.has(fe)||Wn.has(fe)&&$r.has(w):!tt&&$r.has(w);if($===M||!Pr)throw Z;let De=ho($,ne("retryAfter")),St=nt("retry"),Be=!1;try{g?await new Promise((Se,de)=>{let ve,Pe=()=>{clearTimeout(ve),vr.call(g,"abort",Pe),de(ro(g)||new DOMException("Aborted","AbortError"))};if(ze(g)){Pe();return}ve=setTimeout(()=>{vr.call(g,"abort",Pe),Se()},De),to.call(g,"abort",Pe,{once:!0}),ze(g)&&Pe()}):await mo(De),Be=!0}finally{St?.(Be?"succeeded":"failed")}}}throw R};if(!(n("dedupe")!==!1&&!g&&Nr(w,x)))return I();let L=po(w,e,P,{untrustedUrl:N,maxResponseBytes:v,sameOriginRedirectsOnly:D,redirectPolicy:f,maxRedirects:u,timeoutMs:m,retries:M,fetchImpl:st(d),realFetch:y,lookupFn:st(_),importUndici:st(Y),validateResponse:st(A)},x),j=Rt.get(L);if(j){let R=nt("shared");try{let $=await j;return R?.("succeeded"),$}catch($){throw R?.("failed"),$}}let O=I().finally(()=>Rt.delete(L));return Rt.set(L,O),O}import{types as Hr}from"node:util";function Eo(e){if(!e||typeof e!="object"||Hr.isProxy(e)||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function at(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(Hr.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 a=Object.getOwnPropertyDescriptor(e,String(s));if(!a||!Object.hasOwn(a,"value"))throw new Error(`${t} arrays must contain dense own data`);o[s]=at(a.value,t,r+1)}return o}if(!Eo(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]=at(s.value,t,r+1)}return n}var xo="https://api.hyperliquid.xyz/info",ko="https://api.hyperliquid-testnet.xyz/info";function So({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"?ko:xo}async function Ve(e,t={}){if(!e||!e.type)throw new Error("hlInfo requires body.type");let r=So(t);return at(await Lr(r,{method:"POST",body:e,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs,maxResponseBytes:t.maxResponseBytes,sameOriginRedirectsOnly:t.sameOriginRedirectsOnly}),"hyperliquid info response")}async function Fr(e,t={}){if(!e)throw new Error("hlL2Book requires coin");return Ve({type:"l2Book",coin:String(e)},t)}async function Cr(e={}){return Ve({type:"meta"},e)}async function Dr(e={}){let t={type:"metaAndAssetCtxs"};return e.dex&&(t.dex=e.dex),Ve(t,e)}async function Br({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 Ve(s,o)}async function Ur({coin:e,startTime:t,endTime:r},n={}){if(!e)throw new Error("hlFundingHistory requires coin");return Ve({type:"fundingHistory",coin:String(e),startTime:t??Date.now()-24*3600*1e3,endTime:r??Date.now()},n)}function Ge(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 be(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("period must be a positive integer")}function Po(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 Mt(e,t){Ge(e),be(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 Je(e,t){Ge(e),be(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=0;for(let a=0;a<t;a++)n+=e[a];let o=n/t;r[t-1]=o;let s=2/(t+1);for(let a=t;a<e.length;a++)o=s*e[a]+(1-s)*o,r[a]=o;return r}function Nt(e,t){Ge(e),be(t);let r=new Array(e.length).fill(null);if(e.length<=t)return r;let n=0,o=0;for(let i=1;i<=t;i++){let c=e[i]-e[i-1];c>=0?n+=c:o-=c}let s=n/t,a=o/t;r[t]=qr(s,a);for(let i=t+1;i<e.length;i++){let c=e[i]-e[i-1],f=c>0?c:0,u=c<0?-c:0;s=(s*(t-1)+f)/t,a=(a*(t-1)+u)/t,r[i]=qr(s,a)}return r}function qr(e,t){return e===0&&t===0?50:t===0?100:e===0?0:100-100/(1+e/t)}function Lt(e,t={}){Ge(e);let r=t.fastPeriod,n=t.slowPeriod,o=t.signalPeriod;if(be(r),be(n),be(o),r>=n)throw new TypeError("fastPeriod must be < slowPeriod");let s=Je(e,r),a=Je(e,n),i=new Array(e.length).fill(null);for(let l=0;l<e.length;l++)s[l]!=null&&a[l]!=null&&(i[l]=s[l]-a[l]);let c=new Array(e.length).fill(null),f=new Array(e.length).fill(null),u=[];for(let l=0;l<i.length;l++)i[l]!=null&&u.push(l);if(u.length>=o){let l=0;for(let m=0;m<o;m++)l+=i[u[m]];let p=l/o,h=u[o-1];c[h]=p,f[h]=i[h]-p;let d=2/(o+1);for(let m=o;m<u.length;m++){let w=u[m];p=d*i[w]+(1-d)*p,c[w]=p,f[w]=i[w]-p}}return{line:i,signal:c,histogram:f}}function Ht(e,t={}){Ge(e);let r=t.period,n=t.stdDev;if(be(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),a=new Array(e.length).fill(null);if(e.length<r)return{upper:s,middle:o,lower:a};let i=0,c=0;for(let f=0;f<e.length;f++){let u=e[f];if(i+=u,c+=u*u,f>=r){let l=e[f-r];i-=l,c-=l*l}if(f>=r-1){let l=i/r,p=c/r-l*l;p<0&&p>-1e-12&&(p=0);let h=Math.sqrt(p);o[f]=l,s[f]=l+n*h,a[f]=l-n*h}}return{upper:s,middle:o,lower:a}}function Ft(e,t){Po(e),be(t);let r=new Array(e.length).fill(null);if(e.length<t)return r;let n=new Array(e.length);for(let a=0;a<e.length;a++){let i=e[a];if(a===0)n[a]=i.h-i.l;else{let c=e[a-1].c;n[a]=Math.max(i.h-i.l,Math.abs(i.h-c),Math.abs(i.l-c))}}let o=0;for(let a=0;a<t;a++)o+=n[a];let s=o/t;r[t-1]=s;for(let a=t;a<e.length;a++)s=(s*(t-1)+n[a])/t,r[a]=s;return r}import{createHash as Ao}from"node:crypto";var Ct=3,To="7477966facc4ef928a94e6221c8fd238eef4fcbeec46b96ae1b89178e13c2d5f",Oo="68f5b412a9975f04024cf9b9b6209b4bccedd52f176e95f34f786b3f53479c6a",$o="967fd45ecddd0d59ac0f662fe92ea813c32620ba751f249b4ace6cb6b809fb5e",zr=Ao("sha256").update(JSON.stringify({version:Ct,compilerSourceHash:To,indicatorsSourceHash:Oo,schemaSourceHash:$o})).digest("hex");var Re=Ct,Ee=zr,_o=Object.freeze({open:"o",high:"h",low:"l",close:"c",volume:"v",fundingRate:"fundingRate",openInterest:"openInterest",premium:"premium",oiDelta:"oiDelta",bookImbalance:"bookImbalance"}),vo=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5});function ee(e){return typeof e=="number"&&Number.isFinite(e)}function Io(e){let t=new Map(e.map(i=>[i.id,i])),r=i=>{switch(i.type){case"indicator":return i.input?[i.input]:[];case"compare":case"cross":return[i.left,i.right];case"logic":return[...i.inputs];default:return[]}},n=new Map,o=new Map;for(let i of e)n.set(i.id,0),o.set(i.id,[]);for(let i of e)for(let c of r(i))t.has(c)&&(o.get(c).push(i.id),n.set(i.id,n.get(i.id)+1));let s=[];for(let[i,c]of n)c===0&&s.push(i);let a=[];for(;s.length;){let i=s.shift();a.push(i);for(let c of o.get(i))n.set(c,n.get(c)-1),n.get(c)===0&&s.push(c)}if(a.length!==e.length)throw new Error("strategy graph is cyclic");return a}function Ie(e,t){return e!=null&&typeof e=="object"&&"param"in e?t[e.param].value:e}function Ro(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:a,o:i,h:c,l:f,c:u,v:l}=s;if(!ee(a)&&(typeof a=="number"&&Number.isFinite(a)),!Number.isFinite(a))throw new TypeError(`bars[${o}].t must be finite`);for(let[p,h]of[["o",i],["h",c],["l",f],["c",u],["v",l]])if(!ee(h))throw new TypeError(`bars[${o}].${p} must be a finite number`);for(let[p,h]of[["o",i],["h",c],["l",f],["c",u]])if(!(h>0))throw new TypeError(`bars[${o}].${p} price must be positive`);if(l<0)throw new TypeError(`bars[${o}].v volume must be non-negative`);if(c<Math.max(i,u,f))throw new TypeError(`bars[${o}] high must be >= max(open, close, low)`);if(f>Math.min(i,u,c))throw new TypeError(`bars[${o}] low must be <= min(open, close, high)`);if(n!=null){if(!(a>n))throw new TypeError("bars t must be strictly increasing");if(a-n!==vo[r])throw new TypeError(`bars t must match ${r} cadence`)}if(n=a,"fundingRate"in s&&s.fundingRate!=null&&!ee(s.fundingRate))throw new TypeError(`bars[${o}].fundingRate must be finite when present`);if("openInterest"in s&&s.openInterest!=null){if(!ee(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 p of["premium","oiDelta"])if(p in s&&s[p]!=null&&!ee(s[p]))throw new TypeError(`bars[${o}].${p} must be finite when present`);if("bookImbalance"in s&&s.bookImbalance!=null){if(!ee(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 Oe(e,t,r,n,o,s){if(s.has(e))return s.get(e);let a=t.get(e),i;switch(a.type){case"input":{let c=_o[a.field];i=new Array(o+1);for(let f=0;f<=o;f++){let u=n[f][c];i[f]=u===void 0?null:u}break}case"constant":{let c=Ie(a.value,r);i=new Array(o+1).fill(c);break}case"indicator":{let c=a.period!=null?Ie(a.period,r):void 0;if(a.indicator==="atr"){let l=[];for(let p=0;p<=o;p++){let h=n[p];l.push({o:h.o,h:h.h,l:h.l,c:h.c})}i=Ft(l,c);break}let u=Oe(a.input,t,r,n,o,s).map((l,p)=>{if(l==null||!ee(l))throw new TypeError(`indicator input ${a.input} has non-finite value at ${p}`);return l});if(a.indicator==="sma")i=Mt(u,c);else if(a.indicator==="ema")i=Je(u,c);else if(a.indicator==="rsi")i=Nt(u,c);else if(a.indicator==="macd")i=Lt(u,{fastPeriod:Ie(a.fastPeriod,r),slowPeriod:Ie(a.slowPeriod,r),signalPeriod:Ie(a.signalPeriod,r)})[a.output];else if(a.indicator==="bollinger")i=Ht(u,{period:c,stdDev:Ie(a.stdDev,r)})[a.output];else throw new Error(`unsupported indicator ${a.indicator}`);break}case"compare":{let c=Oe(a.left,t,r,n,o,s),f=Oe(a.right,t,r,n,o,s);i=new Array(o+1);for(let u=0;u<=o;u++){let l=c[u],p=f[u];if(l==null||p==null||!ee(l)||!ee(p)){i[u]=!1;continue}switch(a.op){case"gt":i[u]=l>p;break;case"gte":i[u]=l>=p;break;case"lt":i[u]=l<p;break;case"lte":i[u]=l<=p;break;case"eq":i[u]=l===p;break;default:i[u]=!1}}break}case"logic":{let c=a.inputs.map(f=>Oe(f,t,r,n,o,s));i=new Array(o+1);for(let f=0;f<=o;f++)if(a.op==="not"){let u=c[0][f];i[f]=u===!0?!1:u===!1}else if(a.op==="and"){let u=!0;for(let l of c)if(l[f]!==!0){u=!1;break}i[f]=u}else if(a.op==="or"){let u=!1;for(let l of c)if(l[f]===!0){u=!0;break}i[f]=u}else i[f]=!1;break}case"cross":{let c=Oe(a.left,t,r,n,o,s),f=Oe(a.right,t,r,n,o,s);i=new Array(o+1),i[0]=!1;for(let u=1;u<=o;u++){let l=c[u-1],p=f[u-1],h=c[u],d=f[u];if(l==null||p==null||h==null||d==null||!ee(l)||!ee(p)||!ee(h)||!ee(d)){i[u]=!1;continue}a.direction==="above"?i[u]=l<=p&&h>d:i[u]=l>=p&&h<d}break}default:throw new Error(`unknown node type ${a.type}`)}return s.set(e,i),i}function W(e,t={}){let r=J(e);t&&Object.keys(t).length&&(r=je(r,t));let n=new Map(r.nodes.map(h=>[h.id,h])),o=Object.freeze(Io(r.nodes)),s=r.parameters,a=new Set(r.nodes.filter(h=>h.type==="input").map(h=>h.field));if(r.nodes.some(h=>h.type==="indicator"&&h.indicator==="atr"))for(let h of["open","high","low","close"])a.add(h);let i=Object.freeze([...a].sort()),c=ie(r);function f(h,d){let m={};for(let k of o){let S=h.get(k);m[k]=S[d]}let w=k=>k!=null&&m[k]===!0;return{values:m,signals:{entryLong:w(r.rules.entryLong),entryShort:w(r.rules.entryShort),exitLong:w(r.rules.exitLong),exitShort:w(r.rules.exitShort)}}}function u(h,d){Ro(h,d,r.market.interval);let m=new Map;for(let w of o)Oe(w,n,s,h,d,m);return m}function l(h,d){return f(u(h,d),d)}function p(h){if(!Array.isArray(h)||h.length===0)throw new TypeError("bars must be a non-empty array");let d=h.length-1,m=u(h,d);return Object.freeze(h.map((w,k)=>Object.freeze(f(m,k))))}return Object.freeze({strategy:r,strategyHash:c,compilerVersion:Re,compilerHash:Ee,requiredSeries:i,nodeOrder:o,evaluate:l,evaluateAll:p})}import{createHash as Yo}from"node:crypto";import{createHash as jo}from"node:crypto";var Mo=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:100});function No(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ae(e){return typeof e=="number"&&Number.isFinite(e)}function Dt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Dt(t);return Object.freeze(e)}for(let t of Object.keys(e))Dt(e[t]);return Object.freeze(e)}function ct(e){if(Array.isArray(e))return e.map(ct);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=ct(e[r]);return t}return e}function Bt(e,t="result"){if(typeof e=="number"){if(!Number.isFinite(e))throw new Error(`non-finite backtest result at ${t}`);return}if(!(e==null||typeof e!="object")){if(Array.isArray(e)){e.forEach((r,n)=>Bt(r,`${t}[${n}]`));return}for(let[r,n]of Object.entries(e))Bt(n,`${t}.${r}`)}}function 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:a,l:i,c,v:f}=n;if(!ae(o))throw new TypeError(`bars[${r}].t must be finite`);for(let[u,l]of[["o",s],["h",a],["l",i],["c",c],["v",f]])if(!ae(l))throw new TypeError(`bars[${r}].${u} must be a finite number`);for(let[u,l]of[["o",s],["h",a],["l",i],["c",c]])if(!(l>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(a<Math.max(s,c,i))throw new TypeError(`bars[${r}] high must be >= max(open, close, low)`);if(i>Math.min(s,c,a))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&&!ae(n.fundingRate))throw new TypeError(`bars[${r}].fundingRate must be finite when present`);if("fundingPaymentRate"in n&&n.fundingPaymentRate!=null&&!ae(n.fundingPaymentRate))throw new TypeError(`bars[${r}].fundingPaymentRate must be finite when present`);if("openInterest"in n&&n.openInterest!=null&&!ae(n.openInterest))throw new TypeError(`bars[${r}].openInterest must be finite when present`)}}function Ke(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");return e.length>0&&Jr(e),jo("sha256").update(JSON.stringify(ct(e)),"utf8").digest("hex")}function Lo(e){if(e==null&&(e={}),!No(e))throw new TypeError("options must be a plain object");let t={...Mo},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(!ae(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(!ae(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(!ae(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 lt(e){return e/1e4}function Ho(e,t,r){let n=lt(r);return t==="long"?e*(1+n):e*(1-n)}function Fo(e,t,r){let n=lt(r);return t==="long"?e*(1-n):e*(1+n)}function Vr(e,t,r){let n=Math.abs(e)*lt(t),o=Math.abs(e)*lt(r);return{taker:n,builder:o,total:n+o}}function Co(e,t){let r=e*(t.positionSizePct/100)*t.maxLeverage;return Math.min(r,t.maxNotionalUsd)}function Do(e,t,r){let n=r/100;return t==="long"?e*(1-n):e*(1+n)}function Bo(e,t,r){let n=r/100;return t==="long"?e*(1+n):e*(1-n)}function Uo(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 qo(e,t,r){return t==="long"?e.l<=r:e.h>=r}function zo(e,t,r){return t==="long"?e.h>=r:e.l<=r}function Vo(e,t,r){return t==="long"?e.l<=r:e.h>=r}var Jo=Object.freeze(["fundingRate","openInterest","premium","oiDelta","bookImbalance"]);function Ye(e,t){for(let r of e.requiredSeries)if(Jo.includes(r)&&!t.every(n=>ae(n?.[r])))throw new Error(`strategy required series is absent: ${r}`)}function Go(e){if(e.length<3)return 0;let t=[];for(let a=1;a<e.length;a++){let i=e[a-1].equity,c=e[a].equity;i>0&&t.push((c-i)/i)}if(t.length<2)return 0;let r=0;for(let a of t)r+=a;let n=r/t.length,o=0;for(let a of t)o+=(a-n)**2;let s=Math.sqrt(o/(t.length-1));return s>0?n/s:0}function Ko(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 te(e,t,r={}){let n=Lo(r);Jr(t);let o=Ke(t);n.nowMs!==void 0&&J(e,{nowMs:n.nowMs});let s=W(e);if(Ye(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 a=s.strategy.risk,i=s.evaluateAll(t),c=n.latencyBars,f=n.slippageBps,u=n.takerFeeBps,l=n.builderFeeBps,p=n.initialEquityUsd,h=0,d=0,m=0,w=0,k=0,S=[],P=[],x=[],M=[],_=[],y=null,N=0,D=null,Y=p,A=!1,g=0,v=0,I=[],C=new Array(t.length).fill(0);function L(E){I.push(E)}function j(E){let H=t[E].v*(n.maxVolumeParticipationPct/100);return Math.max(0,H-C[E])}function O(E){if(!y)return p;let H=y.side==="long"?(E-y.entryPrice)*y.qty:(y.entryPrice-E)*y.qty;return p+H}function R(E,H,T){let U=T.o,F=Co(p,a);if(!(F>0)||!(U>0))return;let q=Ho(U,H,f),B=F/q,G=j(E),Ue=q*G;if(B>G){x.push({kind:"entry",barIndex:E,time:T.t,side:H,requestedNotionalUsd:F,maxFillNotionalUsd:Ue,reason:"volume_participation"});return}C[E]+=B;let se=Math.abs(q-U)*B,pe=Vr(F,u,l);p-=pe.total,h+=pe.taker,d+=pe.builder,w+=se,k+=F,y={lifecycleEpoch:++v,side:H,entryBarIndex:E,entryReferencePrice:U,entryPrice:q,qty:B,notionalUsd:F,stop:Do(q,H,a.stopLossPct),take:Bo(q,H,a.takeProfitPct),liq:Uo(q,H,a.maxLeverage,u+l),entryFees:pe.taker,entryBuilderFees:pe.builder,entrySlippageUsd:se,fundingAccrued:0}}function $(E,H,T,U){if(!y)return!1;let F=y.side,q=H,B=q;T!=="liquidation"&&U&&(B=Fo(q,F,f));let G=y.qty,Ue=G*B;if(T!=="liquidation"){let Tr=j(E),Cn=B*Tr;if(G>Tr)return x.push({kind:"exit",barIndex:E,time:t[E].t,side:F,requestedNotionalUsd:Ue,maxFillNotionalUsd:Cn,reason:"volume_participation",triggerReason:T}),!1;C[E]+=G}let se=Vr(Ue,u,l),pe=T==="liquidation"?0:Math.abs(B-q)*G,qe,At;F==="long"?(qe=(q-y.entryReferencePrice)*G,At=(B-y.entryPrice)*G):(qe=(y.entryReferencePrice-q)*G,At=(y.entryPrice-B)*G),p+=At,p-=se.total,h+=se.taker,d+=se.builder,w+=pe,k+=Ue;let Fn={side:F,entryBarIndex:y.entryBarIndex,entryTime:t[y.entryBarIndex].t,entryPrice:y.entryPrice,exitBarIndex:E,exitTime:t[E].t,exitPrice:B,exitReason:T,qty:G,notionalUsd:y.notionalUsd,grossPnlUsd:qe,feesUsd:y.entryFees+se.taker,builderFeesUsd:y.entryBuilderFees+se.builder,fundingUsd:y.fundingAccrued,slippageUsd:y.entrySlippageUsd+pe,netPnlUsd:qe-(y.entryFees+se.taker+y.entryBuilderFees+se.builder)-y.fundingAccrued-(y.entrySlippageUsd+pe)};return S.push(Fn),T==="liquidation"&&P.push({barIndex:E,time:t[E].t,side:F,price:B,tradeIndex:S.length-1}),y=null,v+=1,g=E+1+(a.cooldownBars||0),!0}function Q(E,H,T,U){let F=E+1;if(F>=t.length)return;I.some(B=>B.kind==="exit"&&B.side===H&&B.fillBar===F&&B.epoch===U)||L({kind:"exit",side:H,signalBar:E,fillBar:F,reason:T,epoch:U})}function Z(E){let H=I.filter(T=>T.fillBar===E);for(let T=I.length-1;T>=0;T--)I[T].fillBar===E&&I.splice(T,1);H.sort((T,U)=>{let F=q=>q.kind==="exit"?0:1;return F(T)-F(U)});for(let T of H)if(T.kind==="exit"){if(!y||y.side!==T.side||y.lifecycleEpoch!==T.epoch)continue;let U=T.reason||"rule";$(E,t[E].o,U,!0)||Q(E,T.side,U,T.epoch)}else if(T.kind==="entry"){if(y||T.epoch!==v||E<g)continue;R(E,T.side,t[E])}}function ne(E){if(!y)return;let H=t[E],T=H.fundingPaymentRate;if(T==null||!ae(T)||T===0)return;let U=Math.abs(y.qty*H.c),F=T*U;y.side==="long"?(p-=F,y.fundingAccrued+=F,m+=F):(p+=F,y.fundingAccrued-=F,m-=F)}function fe(E){if(!y)return;let H=t[E].o;(y.side==="long"?H<=y.liq:H>=y.liq)&&$(E,H,"liquidation",!1)}function tt(E){if(!y)return;let H=t[E],T=y.side,U=Vo(H,T,y.liq),F=qo(H,T,y.stop),q=zo(H,T,y.take),B=G=>T==="long"?Math.min(G,H.o):Math.max(G,H.o);if(U){$(E,B(y.liq),"liquidation",!1);return}if(F&&q){$(E,B(y.stop),"stop_loss",!0)||Q(E,T,"stop_loss",y.lifecycleEpoch);return}if(F){$(E,B(y.stop),"stop_loss",!0)||Q(E,T,"stop_loss",y.lifecycleEpoch);return}q&&($(E,y.take,"take_profit",!0)||Q(E,T,"take_profit",y.lifecycleEpoch))}for(let E=0;E<t.length;E++){let H=Math.floor(t[E].t/864e5);H!==D&&(D=H,Y=O(t[E].o),A=!1),fe(E),Z(E),tt(E),ne(E),!A&&O(t[E].c)<=Y*(1-a.maxDailyLossPct/100)&&(A=!0,M.push({type:"daily_loss_limit",barIndex:E,time:t[E].t,message:"daily loss limit reached; new entries blocked for UTC day"}));let T=i[E].signals,U=E+c;if(y)(y.side==="long"&&T.exitLong===!0||y.side==="short"&&T.exitShort===!0)&&U<t.length&&(I.some(G=>G.kind==="exit"&&G.side===y.side&&G.fillBar===U&&G.epoch===y.lifecycleEpoch)||L({kind:"exit",side:y.side,signalBar:E,fillBar:U,reason:"rule",epoch:y.lifecycleEpoch}));else{let q=T.entryLong===!0,B=T.entryShort===!0;q&&B?M.push({type:"conflicting_entry_signals",barIndex:E,time:t[E].t,message:"conflicting entry signals; no position opened"}):!A&&(q||B)&&U<t.length&&E>=g&&L({kind:"entry",side:q?"long":"short",signalBar:E,fillBar:U,epoch:v})}let F=p;y&&(N+=1,F=O(t[E].c)),_.push({barIndex:E,time:t[E].t,equity:F,positionSide:y?y.side:null})}let rt=null;if(y){let E=t.length-1;if($(E,t[E].c,"end_of_data",!0))_[E]={barIndex:E,time:t[E].t,equity:p,positionSide:null};else{let T=O(t[E].c);rt={side:y.side,entryBarIndex:y.entryBarIndex,entryTime:t[y.entryBarIndex].t,entryPrice:y.entryPrice,qty:y.qty,notionalUsd:y.notionalUsd,markPrice:t[E].c,markedEquityUsd:T},M.push({type:"open_position_at_end",barIndex:E,time:t[E].t,message:"end-of-data exit missed; position remains open and marked"})}}let De=(y?O(t[t.length-1].c):p)-n.initialEquityUsd,St=De/n.initialEquityUsd*100,Be=0,Se=0,de=0;for(let E of S)E.netPnlUsd>0?(Be+=1,Se+=E.netPnlUsd):E.netPnlUsd<0&&(de+=-E.netPnlUsd);let ve=S.length,Pe=ve===0?0:Be/ve,Pt=0;de>0?Pt=Se/de:Se>0&&(Pt=1e12);let Ln={netPnlUsd:De,netPnlPct:St,maxDrawdownPct:Ko(_),winRate:Pe,profitFactor:Pt,tradeCount:ve,sharpe:Go(_),turnoverUsd:k,exposurePct:N/t.length*100},Hn={initialEquityUsd:n.initialEquityUsd,takerFeeBps:n.takerFeeBps,builderFeeBps:n.builderFeeBps,slippageBps:n.slippageBps,latencyBars:n.latencyBars,maxVolumeParticipationPct:n.maxVolumeParticipationPct},Ar={barsHash:o,strategyHash:s.strategyHash,compilerHash:Ee,compilerVersion:Re,config:Hn,trades:S,equityCurve:_,metrics:Ln,costs:{feesUsd:h,builderFeesUsd:d,fundingUsd:m,slippageUsd:w},liquidations:P,missedFills:x,openPositionAtEnd:rt,flags:M};return Bt(Ar),Dt(ct(Ar))}var Yr=Object.freeze(["fail","pass_paper_only","pass_live_eligible"]);function ce(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Me(e){return typeof e=="number"&&Number.isFinite(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 $e(e){if(Array.isArray(e))return e.map($e);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=$e(e[r]);return t}return e}function Ut(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 Gr(e){return{feesUsd:e.costs.feesUsd,builderFeesUsd:e.costs.builderFeesUsd,fundingUsd:e.costs.fundingUsd,slippageUsd:e.costs.slippageUsd}}function Wo(e){return(e.feesUsd||0)+(e.builderFeesUsd||0)+Math.max(0,e.fundingUsd||0)+(e.slippageUsd||0)}function Xo(e){let t=0;for(let r of e.trades)r.grossPnlUsd>0&&(t+=r.grossPnlUsd);return t}function Zo(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 Wr(e){if(!ce(e))throw new TypeError("evidence artifact must be a plain object");if(!Yr.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(!ce(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(!ce(e.walkForward)||!Array.isArray(e.walkForward.windows))throw new TypeError("evidence artifact walkForward windows required");if(e.status==="pass_live_eligible"&&(!ce(e.train)||!ce(e.holdout)))throw new TypeError("live-eligible evidence artifact requires train and holdout facts");return $e({barsHash:e.barsHash,compilerHash:e.compilerHash,flags:e.flags.map(t=>$e(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 Vt(e){return Yo("sha256").update(JSON.stringify(Wr(e)),"utf8").digest("hex")}function oe(e,t,r=0){if(!Number.isInteger(e)||e<r)throw new Error(`${t} must be an integer >= ${r}`);return e}function qt(e,t){if(!ce(e)||!ce(e.metrics))throw new Error(`${t} metrics required`);let r=oe(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(!Me(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 Qo(e,{maxDailyLossPct:t}={}){let r=e.split,n=oe(r.trainStartIndex,"split.trainStartIndex"),o=oe(r.trainEndIndex,"split.trainEndIndex"),s=oe(r.trainBarCount,"split.trainBarCount",1),a=oe(r.holdoutStartIndex,"split.holdoutStartIndex"),i=oe(r.holdoutEndIndex,"split.holdoutEndIndex"),c=oe(r.holdoutBarCount,"split.holdoutBarCount",1);if(n!==0||o-n+1!==s||a!==o+1||i-a+1!==c)throw new Error("evidence split must be contiguous, chronological, and count-consistent");if(!Me(r.trainFraction)||r.trainFraction<=0||r.trainFraction>=1)throw new Error("split.trainFraction must be in (0,1)");qt(e.train,"train");let f=qt(e.holdout,"holdout");if(f.tradeCount<1||f.netPnlUsd<=0||f.profitFactor<=1)throw new Error("live-eligible holdout metrics do not pass");if(Me(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,l=u.windows;if(l.length<1||u.windowsRun!==l.length)throw new Error("live-eligible walk-forward windowsRun must match nonempty windows");let p=0,h=-1;for(let m=0;m<l.length;m++){let w=l[m];if(!ce(w)||w.index!==m||typeof w.passed!="boolean")throw new Error("walk-forward windows must be ordered and structurally valid");let k=oe(w.trainStartIndex,`walkForward.windows[${m}].trainStartIndex`),S=oe(w.trainEndIndex,`walkForward.windows[${m}].trainEndIndex`),P=oe(w.evalStartIndex,`walkForward.windows[${m}].evalStartIndex`),x=oe(w.evalEndIndex,`walkForward.windows[${m}].evalEndIndex`);if(k!==0||S>=P||P>x||P<=h)throw new Error("walk-forward windows must be chronological and disjoint");if(h=x,w.passed){if(p+=1,w.reason!=="pass")throw new Error("passed walk-forward window reason must be pass");let M=qt({metrics:w.metrics,tradeCount:w.metrics?.tradeCount},`walkForward.windows[${m}]`);if(M.tradeCount<1||M.netPnlUsd<=0||M.profitFactor<=1)throw new Error("passed walk-forward window metrics do not pass");if(Me(t)&&M.maxDrawdownPct>t)throw new Error("passed walk-forward drawdown exceeds strategy risk")}else if(w.reason==="pass")throw new Error("failed walk-forward window cannot have pass reason")}let d=p/l.length;if(!Me(u.passRate)||Math.abs(u.passRate-d)>Number.EPSILON||d<.6)throw new Error("walk-forward passRate contradicts concrete windows or is below live threshold")}function Jt(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=Wr(e),n=$e({id:e.id,...r});if(JSON.stringify($e(e))!==JSON.stringify(n))throw new Error("evidence artifact contains fields unbound from its deterministic identity");let o=Vt(e);if(e.id!==o)throw new Error("evidence.id does not match its deterministic artifact facts digest");return e.status==="pass_live_eligible"&&Qo(e,t),e}function ut({strategy:e,bars:t,backtestOptions:r={},trainFraction:n=.7,walkForwardWindows:o=3,minTrades:s=10}={}){let a=[];if(!ce(e))throw new TypeError("strategy must be a plain object");if(!Array.isArray(t))throw new TypeError("bars must be an array");if(!ce(r))throw new TypeError("backtestOptions must be a plain object");if(!Me(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 i=J(e),c=ie(i),f=Ke(t),u=t.length,l=(j=[],O={})=>Kr({status:"fail",strategy:i,sHash:c,barsHash:f,split:O.split||{trainStartIndex:0,trainEndIndex:-1,trainBarCount:0,holdoutStartIndex:0,holdoutEndIndex:-1,holdoutBarCount:0,trainFraction:n},train:O.train||null,holdout:O.holdout||null,walkForward:O.walkForward||{windows:[],passRate:0},flags:[...a,...j]});if(u<10)return l([{type:"insufficient_bars",message:"need at least 10 bars for evidence"}]);let p=Math.floor(u*n),h=p,d=u-h;if(p<5||d<3)return l([{type:"invalid_windowing",message:"train/holdout split too small",trainCount:p,holdoutCount:d}]);let m=t.slice(0,p),w=t.slice(h),k,S;try{k=te(i,m,r),S=te(i,w,r)}catch(j){return l([{type:"backtest_error",message:String(j.message||j)}])}let P={metrics:Ut(k),costs:Gr(k),tradeCount:k.metrics.tradeCount},x={metrics:Ut(S),costs:Gr(S),tradeCount:S.metrics.tradeCount},M={trainStartIndex:0,trainEndIndex:p-1,trainBarCount:p,holdoutStartIndex:h,holdoutEndIndex:u-1,holdoutBarCount:d,trainFraction:n},_=[],y=Math.floor(u/(o+1));if(y<3)a.push({type:"invalid_windowing",message:"walk-forward window size too small",wfSize:y});else for(let j=0;j<o;j++){let O=y*(j+1),R=O,$=Math.min(u,R+y);if($-R<3||O<3){_.push({index:j,trainStartIndex:0,trainEndIndex:O-1,evalStartIndex:R,evalEndIndex:$-1,passed:!1,reason:"window_too_small",metrics:null});continue}let Q=t.slice(R,$),Z;try{Z=te(i,Q,r)}catch{_.push({index:j,trainStartIndex:0,trainEndIndex:O-1,evalStartIndex:R,evalEndIndex:$-1,passed:!1,reason:"backtest_error",metrics:null});continue}let ne=Ut(Z),fe=Zo(ne,i.risk,s);_.push({index:j,trainStartIndex:0,trainEndIndex:O-1,evalStartIndex:R,evalEndIndex:$-1,passed:fe,reason:fe?"pass":"fail_metrics",metrics:ne})}let N=_.filter(j=>j.passed).length,D=_.length===0?0:N/_.length,Y={windows:_,passRate:D,windowsRun:_.length};x.metrics.tradeCount===0&&P.metrics.tradeCount===0&&a.push({type:"no_trades",message:"no trades in train or holdout"}),x.metrics.tradeCount===0&&a.push({type:"absent_oos_trades",message:"holdout produced no trades"}),x.metrics.netPnlUsd<0&&a.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?a.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&&a.push({type:"severe_oos_collapse",message:"holdout pnl collapsed vs train"});let A=Wo(x.costs),g=Xo(S);g>0&&A>g&&a.push({type:"costs_exceed_gross",message:"holdout costs exceed gross gains"});let v=a.some(j=>["insufficient_bars","invalid_windowing","absent_oos_trades","holdout_loss","no_trades","severe_oos_collapse","backtest_error"].includes(j.type)),I=a.some(j=>j.type==="overfit"),C="fail";return x.metrics.tradeCount>=s&&x.metrics.netPnlUsd>0&&x.metrics.profitFactor>1&&x.metrics.maxDrawdownPct<=i.risk.maxDailyLossPct&&D>=.6&&!(g>0&&A>g)&&!I&&!a.some(j=>j.type==="severe_oos_collapse"||j.type==="invalid_windowing")?C="pass_live_eligible":!v&&x.metrics.tradeCount>0&&P.metrics.tradeCount>0&&Number.isFinite(x.metrics.netPnlUsd)?(C="pass_paper_only",x.metrics.tradeCount<s&&a.push({type:"undersampled",message:"holdout trades below minTrades"})):I&&x.metrics.tradeCount>0&&P.metrics.netPnlUsd>0?C="fail":x.metrics.tradeCount>0&&P.metrics.tradeCount>0&&!v?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"),Kr({status:C,strategy:i,sHash:c,barsHash:f,split:M,train:P,holdout:x,walkForward:Y,flags:a})}function Kr({status:e,strategy:t,sHash:r,barsHash:n,split:o,train:s,holdout:a,walkForward:i,flags:c}){let f={status:e,strategyHash:r,compilerHash:Ee,barsHash:n,split:o,train:s,holdout:a,walkForward:i,flags:c};return f.id=Vt(f),zt($e(JSON.parse(JSON.stringify(f))))}import{createHash as es,createHmac as ts,timingSafeEqual as Ta}from"node:crypto";var rs=2,ns=300*1e3,os=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})();function Gt(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(Gt).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${Gt(e[r])}`).join(",")}}`}function Xr(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function Zr(e=process.env){return Xr(process.env)||Xr(e)}function ss(e){let{prepareHash:t,prepareMac:r,note:n,...o}=e||{};return o}function is(e){let t=ss(e);return es("sha256").update(Gt(t)).digest("hex")}function as(e,t=Zr()){return t?ts("sha256",t).update(String(e)).digest("hex"):""}function Qr(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 a=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(a&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let i={...e,provider:e.provider||t,kind:e.kind||r,requiresUserSignature:e.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1,oraclePrepared:a?e.oraclePrepared:!0};if(!i.provider)throw new Error("stampPrepared: provider required");if(!i.kind)throw new Error("stampPrepared: kind required");let c=Number(o),f=s==null?c+ns:Number(s),u=f-c;if(!Number.isSafeInteger(c)||!Number.isSafeInteger(f)||u<=0||u>os)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let p={...i,preparedAt:c,expiresAt:f,prepareVersion:rs},h=is(p),d=Zr(n),m=d?as(h,d):void 0,w={...p,prepareHash:h};return m&&(w.prepareMac=m),w}var cs=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function We(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ls(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Yt(e,t="value"){if(Array.isArray(e)){e.forEach((r,n)=>Yt(r,`${t}[${n}]`));return}if(We(e))for(let[r,n]of Object.entries(e)){let o=ls(r);if(cs.some(s=>o.includes(s)))throw new Error(`handoff: forbidden secret-like field at ${t}.${r}`);Yt(n,`${t}.${r}`)}}function Kt(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function Wt({strategy:e,evidence:t,shadow:r,caps:n,nowMs:o=Date.now(),env:s=process.env}={}){if(Yt({strategy:e,evidence:t,shadow:r,caps:n},"handoff"),!We(e))throw new Error("handoff: strategy required");if(!We(t))throw new Error("handoff: evidence required");if(!We(r))throw new Error("handoff: shadow required");if(!We(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 a=J(e,{nowMs:o}),i=W(a);if(Jt(t,{maxDailyLossPct:a.risk.maxDailyLossPct}),t.status!=="pass_live_eligible")throw new Error("handoff: evidence.status must be pass_live_eligible");if(t.strategyHash!==i.strategyHash)throw new Error("handoff: evidence.strategyHash mismatch");if(t.compilerHash!==i.compilerHash)throw new Error("handoff: evidence.compilerHash mismatch");let c=["perStrategyNotionalUsd","maxLeverage","dailyLossCapUsd","chainAllowlist","assetAllowlist","expiresAt","killSwitchRequired"];for(let p of c)if(!(p in n)||n[p]==null)throw new Error(`handoff: caps.${p} required`);if(!Kt(n.perStrategyNotionalUsd))throw new Error("handoff: caps.perStrategyNotionalUsd must be positive");if(n.perStrategyNotionalUsd>i.strategy.risk.maxNotionalUsd)throw new Error("handoff: caps.perStrategyNotionalUsd exceeds strategy.risk.maxNotionalUsd");if(!Kt(n.maxLeverage))throw new Error("handoff: caps.maxLeverage must be positive");if(n.maxLeverage>i.strategy.risk.maxLeverage)throw new Error("handoff: caps.maxLeverage exceeds strategy.risk.maxLeverage");if(!Kt(n.dailyLossCapUsd))throw new Error("handoff: caps.dailyLossCapUsd must be positive");let f=i.strategy.risk.maxNotionalUsd*(i.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(p=>p==="hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include only hyperliquid");if(!n.chainAllowlist.includes("hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include hyperliquid");if(!Array.isArray(n.assetAllowlist)||n.assetAllowlist.length===0)throw new Error("handoff: caps.assetAllowlist must be a non-empty array");if(n.assetAllowlist.length!==1||n.assetAllowlist[0]!==i.strategy.market.coin)throw new Error("handoff: caps.assetAllowlist must contain only the strategy market coin");if(!Number.isInteger(n.expiresAt)||!(n.expiresAt>o))throw new Error("handoff: caps.expiresAt must be an integer > nowMs");if(n.expiresAt>i.strategy.risk.expiresAt)throw new Error("handoff: caps.expiresAt exceeds strategy.risk.expiresAt");if(n.killSwitchRequired!==!0)throw new Error("handoff: caps.killSwitchRequired must be exactly true");let u={perStrategyNotionalUsd:n.perStrategyNotionalUsd,maxLeverage:n.maxLeverage,dailyLossCapUsd:n.dailyLossCapUsd,chainAllowlist:[...n.chainAllowlist],assetAllowlist:[...n.assetAllowlist],expiresAt:n.expiresAt,killSwitchRequired:!0},l={strategyHash:i.strategyHash,compilerHash:i.compilerHash,evidence:JSON.parse(JSON.stringify(t)),shadow:{id:r.id,stateHash:r.stateHash,status:r.status,cursor:r.cursor,updatedAt:r.updatedAt},compiled:{strategyHash:i.strategyHash,compilerHash:i.compilerHash,compilerVersion:Re,venue:"hyperliquid",market:{coin:i.strategy.market.coin,kind:"perp",interval:i.strategy.market.interval},risk:{...i.strategy.risk},strategy:JSON.parse(JSON.stringify(i.strategy))},arming:{liveBroadcast:!1,requiresExplicitUserArm:!0,caps:u},requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,executionReady:!1};return Qr(l,{provider:"hl-strategy",kind:"strategy-live-handoff",env:s})}var us=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 Ne(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function Le(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be a non-negative safe integer`);return e}function Xe(e){if(Array.isArray(e))for(let t of e)Xe(t);else if(e&&typeof e=="object")for(let t of Object.values(e))Xe(t);return Object.freeze(e)}function en(e){let t=us[e];if(!t)throw new TypeError(`unsupported strategy interval: ${e}`);return t}function tn(e,{endTime:t=Number.MAX_SAFE_INTEGER}={}){if(!Array.isArray(e))throw new TypeError("Hyperliquid candles must be an array");Le(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=Le(Number(o.t),`candles[${n}].t`);if(Le(Number(o.T),`candles[${n}].T`)>t)continue;let i={t:s,o:Ne(o.o,`candles[${n}].o`),h:Ne(o.h,`candles[${n}].h`),l:Ne(o.l,`candles[${n}].l`),c:Ne(o.c,`candles[${n}].c`),v:Ne(o.v,`candles[${n}].v`)};if(i.h<Math.max(i.o,i.c,i.l))throw new TypeError(`candles[${n}].h is below another price`);if(i.l>Math.min(i.o,i.c,i.h))throw new TypeError(`candles[${n}].l is above another price`);if(i.v<0)throw new TypeError(`candles[${n}].v must be non-negative`);let c=r.get(s);if(c&&JSON.stringify(c)!==JSON.stringify(i))throw new TypeError(`conflicting duplicate candle at timestamp ${s}`);c||r.set(s,i)}return Xe([...r.values()].sort((n,o)=>n.t-o.t))}function fs(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=Le(Number(o.time),`funding[${n}].time`);s>t||r.set(s,{time:s,fundingRate:Ne(o.fundingRate,`funding[${n}].fundingRate`)})}return[...r.values()].sort((n,o)=>n.time-o.time)}async function ds({coin:e,startTime:t,endTime:r},n){let o=[],s=Math.max(0,t-288e5),a=!1;for(let i=0;i<16&&s<=r;i++){let c=await Ur({coin:e,startTime:s,endTime:r},n);if(!Array.isArray(c))throw new TypeError("Hyperliquid funding history must be an array");o.push(...c);let f=s;for(let u of c){let l=Number(u?.time);Number.isSafeInteger(l)&&l>f&&(f=l)}if(c.length<500||f>=r){a=!0;break}if(f<=s)throw new Error("Hyperliquid funding history pagination did not advance");s=f+1}if(!a)throw new Error("strategy history exceeds the bounded funding history limit");return fs(o,r)}function ps(e,t,r){let n=0,o=null;return e.map(s=>{let a=s.t+r,i=0;for(;n<t.length&&t[n].time<a;){let c=t[n];o=c.fundingRate,c.time>=s.t&&(i+=c.fundingRate),n+=1}return o==null?{...s,fundingPaymentRate:i}:{...s,fundingRate:o,fundingPaymentRate:i}})}async function Xt(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=en(n);if(e.endTime==null)throw new TypeError("endTime is required for deterministic history");let s=Le(e.endTime,"endTime"),a=e.count==null?1500:e.count;if(!Number.isInteger(a)||a<20||a>5e3)throw new TypeError("count must be an integer from 20 to 5000");let i=e.startTime==null?Math.max(0,s-a*o):Le(e.startTime,"startTime");if(i>=s)throw new TypeError("startTime must be before endTime");let[c,f]=await Promise.all([Br({coin:r,interval:n,startTime:i,endTime:s},t),ds({coin:r,startTime:i,endTime:s},t)]),u=tn(c,{endTime:s}),l=Xe(ps(u,f,o));return Xe({coin:r,interval:n,range:{startTime:i,endTime:s},bars:l})}var hs=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),ms=new Set(["coin","interval"]);function ys(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))ms.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"||!hs.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 ws(e={}){let t=await Cr(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 rn=Object.freeze({id:"hyperliquid",validateMarket:ys,fetchBars:Xt,listMarkets:ws,prepareIntent(e){return Wt(e)}});var gs=Object.freeze(["id","validateMarket","prepareIntent"]);function bs(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 gs.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 nn=[rn].map(bs),Es=new Map(nn.map(e=>[e.id,e])),xs=Object.freeze([...nn]);function ft(e){return typeof e!="string"?null:Es.get(e)??null}function dt(e){let t=ft(e);if(!t)throw new Error(`unknown strategy venue: ${String(e)}`);return t}var pt=1,hn=/^[a-z0-9][a-z0-9._-]{0,63}$/,mn=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Ss=new Set(["open","high","low","close","volume","fundingRate","openInterest","premium","oiDelta","bookImbalance"]),Ps=new Set(["sma","ema","rsi","macd","bollinger","atr"]),As=new Set(["gt","gte","lt","lte","eq"]),Ts=new Set(["and","or","not"]),Os=new Set(["above","below"]),$s=new Set(["line","signal","histogram"]),_s=new Set(["upper","middle","lower"]),Zt=new Set(["compare","logic","cross"]),on=new Set(["version","id","name","venue","market","parameters","nodes","rules","risk"]),sn=new Set(["value","min","max","step"]),Qt=new Set(["entryLong","entryShort","exitLong","exitShort"]),an=new Set(["maxLeverage","maxNotionalUsd","positionSizePct","stopLossPct","takeProfitPct","cooldownBars","maxDailyLossPct","expiresAt"]),vs=new Set(["id","type"]),cn={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"])},ln=16,un=128,fn=100,_e=class extends Error{constructor(t){let r=t.map(n=>`${n.path}: ${n.message}`);super(`invalid strategy (${t.length} error${t.length===1?"":"s"}): ${r.join("; ")}`),this.name="StrategyValidationError",this.errors=t}};function re(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function z(e){return typeof e=="number"&&Number.isFinite(e)}function dn(e){return Number.isInteger(e)&&e>0}function tr(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)tr(t);return Object.freeze(e)}for(let t of Object.keys(e))tr(e[t]);return Object.freeze(e)}function rr(e){if(Array.isArray(e))return e.map(rr);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=rr(e[r]);return t}return e}function b(e,t,r){e.push({path:t,message:r})}function xe(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 yn(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 er(e,t,r,n){if(re(e)){if(xe(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!re(o)||![o.value,o.min,o.max,o.step].every(dn)?(b(n,`${t}.param`,"referenced period parameter value min max and step must be positive integers"),null):{param:e.param}}return dn(e)?e:(b(n,t,"must be a positive integer or {param}"),null)}function pn(e,t,r,n){return re(e)?(xe(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 ht(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 Is(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 a of ht(s))if(e.has(a)&&r(a))return!0}return t.set(n,2),!1};for(let n of e.keys())if(r(n))return!0;return!1}function Rs(e,t){if(!re(e))return b(t,"parameters","must be a plain object"),null;let r=Object.keys(e);if(r.length>ln)return b(t,"parameters",`too many parameters (max ${ln})`),null;let n={};for(let o of r){if(!hn.test(o)){b(t,`parameters.${o}`,"parameter name is malformed");continue}let s=e[o],a=`parameters.${o}`;if(!re(s)){b(t,a,"must be a plain object");continue}xe(s,sn,a,t);for(let l of sn)l in s||b(t,`${a}.${l}`,"required field is missing");let{value:i,min:c,max:f,step:u}=s;z(c)||b(t,`${a}.min`,"must be a finite number"),z(f)||b(t,`${a}.max`,"must be a finite number"),(!z(u)||u<=0)&&b(t,`${a}.step`,"must be a positive finite number"),z(i)||b(t,`${a}.value`,"must be a finite number"),z(c)&&z(f)&&c>f&&b(t,`${a}.min`,"min must be <= max"),z(i)&&z(c)&&z(f)&&z(u)&&u>0&&(yn(i,c,f,u)||b(t,`${a}.value`,"value must lie on the declared min/max/step grid")),n[o]={value:i,min:c,max:f,step:u}}return n}function js(e,t,r,n){let o=`nodes.${t}`;if(!re(e))return b(n,o,"must be a plain object"),null;if(typeof e.type!="string"||!cn[e.type])return b(n,`${o}.type`,"unknown or missing node type"),xe(e,vs,o,n),null;switch(xe(e,cn[e.type],o,n),(typeof e.id!="string"||!mn.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"||!Ss.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=pn(e.value,`${o}.value`,r,n);return{id:e.id,type:"constant",value:s}}case"indicator":{(typeof e.indicator!="string"||!Ps.has(e.indicator))&&b(n,`${o}.indicator`,"must be one of sma|ema|rsi|macd|bollinger|atr");let s=e.indicator,a={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"):a.input=e.input);let i=er(e.period,`${o}.period`,r,n);i!=null&&(a.period=i)}else typeof e.input!="string"||!e.input?b(n,`${o}.input`,"must be a node id string"):a.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 i=er(e.period,`${o}.period`,r,n);i!=null&&(a.period=i)}if(s==="macd"){for(let i of["fastPeriod","slowPeriod","signalPeriod"])if(!(i in e))b(n,`${o}.${i}`,"required field is missing");else{let c=er(e[i],`${o}.${i}`,r,n);c!=null&&(a[i]=c)}"output"in e?$s.has(e.output)?a.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 i=pn(e.stdDev,`${o}.stdDev`,r,n);i!=null&&(typeof i=="number"&&i<=0?b(n,`${o}.stdDev`,"must be > 0"):a.stdDev=i)}"output"in e?_s.has(e.output)?a.output=e.output:b(n,`${o}.output`,"must be upper|middle|lower"):b(n,`${o}.output`,"required field is missing");for(let i of["fastPeriod","slowPeriod","signalPeriod"])i in e&&b(n,`${o}.${i}`,`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 i of["fastPeriod","slowPeriod","signalPeriod"])i in e&&b(n,`${o}.${i}`,`forbidden for ${s}`)}return a}case"compare":return(typeof e.op!="string"||!As.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"||!Ts.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 a=0;a<e.inputs.length;a++){let i=e.inputs[a];typeof i!="string"||!i?b(n,`${o}.inputs.${a}`,"must be a node id"):s.push(i)}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"||!Os.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 Ms(e,t,r){if(!re(e))return b(t,"risk","must be a plain object"),null;xe(e,an,"risk",t);for(let p of an)(!(p in e)||e[p]==null)&&b(t,`risk.${p}`,"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 a=e.positionSizePct;!z(a)||a<=0||a>100?b(t,"risk.positionSizePct","must be a number > 0 and <= 100"):n.positionSizePct=a;let i=e.stopLossPct;!z(i)||i<=0||i>100?b(t,"risk.stopLossPct","must be a number > 0 and <= 100"):n.stopLossPct=i;let c=e.takeProfitPct;!z(c)||c<=0||c>1e3?b(t,"risk.takeProfitPct","must be a number > 0 and <= 1000"):n.takeProfitPct=c;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 l=e.expiresAt;return!Number.isInteger(l)||l<=0?b(t,"risk.expiresAt","must be an integer epoch milliseconds > 0"):(r.nowMs!==void 0&&(Number.isInteger(r.nowMs)?l<=r.nowMs&&b(t,"risk.expiresAt","must be strictly greater than nowMs"):b(t,"nowMs","must be an integer epoch milliseconds")),n.expiresAt=l),n}function mt(e,t={}){let r=[];if(!re(e))return b(r,"","strategy must be a plain object"),{ok:!1,errors:r,strategy:null};xe(e,on,"",r);for(let l of on)(!(l in e)||e[l]==null)&&b(r,l,"required field is missing");e.version!==pt&&b(r,"version",`must be ${pt}`),(typeof e.id!="string"||!hn.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>fn)&&b(r,"name",`must be a non-empty string max ${fn}`);let n=ft(e.venue);n||b(r,"venue",`unknown strategy venue "${String(e.venue)}"`);let o=null;if(!n)re(e.market)||b(r,"market","must be a plain object");else{let l=n.validateMarket(e.market);if(!l||typeof l.ok!="boolean"||!Array.isArray(l.errors))b(r,"market",`venue ${n.id} returned an invalid market validation result`);else if(l.ok)o=l.market;else for(let p of l.errors)b(r,p.path,p.message)}let s=Rs(e.parameters,r),a=null,i=new Map;if(!Array.isArray(e.nodes))b(r,"nodes","must be an array");else if(e.nodes.length>un)b(r,"nodes",`too many nodes (max ${un})`);else{a=[];for(let l=0;l<e.nodes.length;l++){let p=js(e.nodes[l],l,s||{},r);p&&(typeof p.id=="string"&&mn.test(p.id)&&(i.has(p.id)?b(r,`nodes.${l}.id`,`duplicate node id "${p.id}"`):i.set(p.id,p)),a.push(p))}for(let l=0;l<a.length;l++){let p=a[l],h=`nodes.${l}`;for(let d of ht(p))i.has(d)||b(r,h,`unknown node ref "${d}"`);if(p.type==="indicator"||p.type==="compare"||p.type==="cross")for(let d of ht(p)){let m=i.get(d);m&&Zt.has(m.type)&&b(r,h,`node ref "${d}" must be numeric`)}if(p.type==="logic")for(let d of ht(p)){let m=i.get(d);m&&!Zt.has(m.type)&&b(r,h,`node ref "${d}" must be boolean`)}}Is(i)&&b(r,"nodes","graph contains a cycle")}let c=null;if(!re(e.rules))b(r,"rules","must be a plain object");else{xe(e.rules,Qt,"rules",r);for(let l of Qt)l in e.rules||b(r,`rules.${l}`,"required field is missing");c={};for(let l of Qt){let p=e.rules[l];if(p===null){c[l]=null;continue}if(typeof p!="string"||!p){b(r,`rules.${l}`,"must be a node id or null"),c[l]=p;continue}if(!i.has(p)){b(r,`rules.${l}`,`unknown node ref "${p}"`),c[l]=p;continue}let h=i.get(p);Zt.has(h.type)||b(r,`rules.${l}`,`rule must reference a boolean node, not ${h.type}`),c[l]=p}}let f=Ms(e.risk,r,t);if(r.length)return{ok:!1,errors:r,strategy:null};let u=tr({version:pt,id:e.id,name:e.name,venue:n.id,market:o,parameters:s,nodes:a,rules:c,risk:f});return{ok:!0,errors:[],strategy:u}}function J(e,t={}){let r=mt(e,t);if(!r.ok)throw new _e(r.errors);return r.strategy}function wn(e){let t=J(e);return JSON.stringify(rr(t))}function ie(e){let t=wn(e);return ks("sha256").update(t,"utf8").digest("hex")}function je(e,t){if(!re(e))throw new _e([{path:"",message:"strategy must be a plain object"}]);if(!re(t))throw new _e([{path:"overrides",message:"must be a plain object"}]);let r=J(e),n={};for(let[s,a]of Object.entries(r.parameters))n[s]={value:a.value,min:a.min,max:a.max,step:a.step};let o=[];for(let[s,a]of Object.entries(t)){if(!Object.prototype.hasOwnProperty.call(n,s)){b(o,s,`unknown parameter "${s}"`);continue}let i=n[s];if(!z(a)){b(o,s,"override must be a finite number");continue}if(!yn(a,i.min,i.max,i.step)){b(o,s,"override must lie on the declared min/max/step grid");continue}n[s]={...i,value:a}}if(o.length)throw new _e(o);return J({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 a={...s};return Array.isArray(s.inputs)&&(a.inputs=[...s.inputs]),a}),rules:{...r.rules},risk:{...r.risk}})}var Ns=50;function le(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function gn(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=le(e[o]?.px,`${r}[${o}].px`),a=le(e[o]?.sz,`${r}[${o}].sz`);if(a<0)throw new TypeError(`${r}[${o}].sz must be non-negative`);Math.abs((s-t)/t)*1e4<=Ns&&(n+=a)}return n}async function Ls(e,t={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("sampleLiveSeries input must be an object");let r=String(e.coin||"").trim().toUpperCase();if(!/^[A-Z0-9][A-Z0-9._-]{0,11}$/.test(r))throw new TypeError("coin must be an uppercase Hyperliquid asset id");if(!Number.isSafeInteger(e.nowMs)||e.nowMs<=0)throw new TypeError("nowMs is required integer epoch ms");let[n,o]=await Promise.all([Dr(t),Fr(r,t)]),s=n?.[0]?.universe,a=n?.[1];if(!Array.isArray(s)||!Array.isArray(a))throw new TypeError("metaAndAssetCtxs payload malformed");let i=s.findIndex(m=>m?.name===r);if(i<0)throw new Error(`unknown coin: ${r}`);let c=a[i];if(!c||typeof c!="object")throw new TypeError("asset ctx malformed");let f=le(c.premium,"ctx.premium"),u=le(c.openInterest,"ctx.openInterest");if(u<0)throw new TypeError("ctx.openInterest must be non-negative");let l=le(c.midPx,"ctx.midPx"),p=o?.levels;if(!Array.isArray(p)||p.length!==2)throw new TypeError("l2Book levels malformed");let h=gn(p[0],l,"book.bids"),d=gn(p[1],l,"book.asks");if(h+d<=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:h,askDepth:d})})}function Hs(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 a=le(s.t,`snapshots[${o}].t`);if(n!=null&&!(a>n.t))throw new TypeError("snapshot times must be strictly increasing");let i=le(s.premium,`snapshots[${o}].premium`),c=le(s.openInterest,`snapshots[${o}].openInterest`),f=le(s.book?.bidDepth,`snapshots[${o}].book.bidDepth`),u=le(s.book?.askDepth,`snapshots[${o}].book.askDepth`),l=f+u;if(!(l>0))throw new TypeError(`snapshots[${o}] book depth must be positive`);r.push({coin:t,t:a,premium:i,openInterest:c,oiDelta:n==null?null:c-n.openInterest,bookImbalance:(f-u)/l}),n={t:a,openInterest:c}}return r}function Fs(e,t,r){if(!Array.isArray(e))throw new TypeError("bars must be an array");if(!Array.isArray(t))throw new TypeError("rows must be an array");if(!Number.isSafeInteger(r)||r<=0)throw new TypeError("intervalMs must be a positive integer");let n=0;return e.map(o=>{let s=o.t+r,a=null;for(;n<t.length&&t[n].t<s;)t[n].t>=o.t&&(a=t[n]),n+=1;if(!a)return{...o};let i={...o};return a.premium!=null&&(i.premium=a.premium),a.openInterest!=null&&(i.openInterest=a.openInterest),a.oiDelta!=null&&(i.oiDelta=a.oiDelta),a.bookImbalance!=null&&(i.bookImbalance=a.bookImbalance),i})}import{createHash as Cs}from"node:crypto";var or=256,bn=new Set(["netPnlUsd","profitFactor","sharpe","maxDrawdownPct"]);function En(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 xn(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function sr(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)sr(t);return Object.freeze(e)}for(let t of Object.keys(e))sr(e[t]);return Object.freeze(e)}function Ze(e){if(Array.isArray(e))return e.map(Ze);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Ze(e[r]);return t}return e}function yt(e){return JSON.stringify(Ze(e))}function Ds(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 i=0;i<=s;i++){let c=t+i*n;if(c>r+1e-9)break;let f=Math.abs(c-Math.round(c))<1e-9?Math.round(c):Number(c.toPrecision(12));f<t-1e-9||f>r+1e-9||o.push(f)}if(o.length===0)return[];let a=o[o.length-1];if(Math.abs(a-r)>1e-9){let i=(r-t)/n;Math.abs(i-Math.round(i))<=1e-9&&o.push(r)}return o}function Bs(e,t){if(e.length===0)return[];let r=[{}];for(let n of e){let o=t[n],s=[];for(let a of r)for(let i of o)s.push({...a,[n]:i});r=s}return r.sort((n,o)=>{let s=yt(n),a=yt(o);return s<a?-1:s>a?1:0}),r}function nr(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 a=yt(r),i=yt(o);return a<i}function ir(e,t,r={}){if(!xn(r))throw new TypeError("options must be a plain object");for(let x of Object.keys(r))if(En(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>or)throw new TypeError(`maxTrials must be an integer 1..${or}`);o=x}let s=r.objective??"netPnlUsd";if(!bn.has(s))throw new TypeError(`objective must be one of ${[...bn].join("|")}`);let a=r.backtestOptions??{};if(!xn(a))throw new TypeError("backtestOptions must be a plain object");for(let x of Object.keys(a))if(En(x))throw new TypeError(`backtestOptions must not include holdout/test/oos key "${x}"`);let i=J(e),c=Object.keys(i.parameters).sort();if(c.length===0)throw new Error("optimizeStrategy requires at least one declared parameter");let f={},u=1;for(let x of c){let M=Ds(i.parameters[x]);if(M.length===0)throw new Error(`parameter "${x}" produces an empty grid`);f[x]=M,u*=M.length}let l=Bs(c,f);if(l.length===0)throw new Error("parameter grid is empty");let p=l.slice(0,o),h=[],d=null,m=null;for(let x of p){let M=je(i,x),_=te(M,t,a);m==null&&(m=_.config);let y={netPnlUsd:_.metrics.netPnlUsd,netPnlPct:_.metrics.netPnlPct,maxDrawdownPct:_.metrics.maxDrawdownPct,winRate:_.metrics.winRate,profitFactor:_.metrics.profitFactor,tradeCount:_.metrics.tradeCount,sharpe:_.metrics.sharpe,turnoverUsd:_.metrics.turnoverUsd},N={parameters:{...x},metrics:y};h.push(N),(!d||nr(s,y,x,d.metrics,d.parameters))&&(d=N)}h.sort((x,M)=>nr(s,x.metrics,x.parameters,M.metrics,M.parameters)?-1:nr(s,M.metrics,M.parameters,x.metrics,x.parameters)?1:0);let w={...d.parameters},k=je(i,w),S={strategyHash:ie(i),compilerHash:Ee,trainBarsHash:Ke(t),backtestConfig:m,objective:s,maxTrials:o,trialsRun:h.length,candidates:h,bestParameters:w,bestStrategy:k},P={id:Cs("sha256").update(JSON.stringify(Ze(S)),"utf8").digest("hex"),...S};return sr(Ze(JSON.parse(JSON.stringify(P))))}import{createHash as Us}from"node:crypto";var K=class extends Error{constructor(t){super(t),this.name="StrategyDraftError"}},qs=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),zs=new Set(["BTC","ETH","SOL","HYPE"]),Vs=/\b(mnemonic|private\s*key|privkey|seed\s*phrase|seed\b|api[_-]?key|secret\s*key|wallet\s*key|passphrase)\b/i,He="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.",Js=Object.freeze({maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3}),Gs=36e5,Ks=30*864e5,Ys=864e5;function Ws(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function ar(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)ar(t);return Object.freeze(e)}for(let t of Object.keys(e))ar(e[t]);return Object.freeze(e)}function Xs(e){return String(e).trim().replace(/\s+/g," ")}function Zs(e){let t=e.match(/\b(long|short)\b/i);return t?t[1].toLowerCase():null}function Qs(e){for(let r of zs)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 ei(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 qs.has(r)?r:null}function ti(e){let t={...Js},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 a=e.match(/max\s*notional\s*(?:usd\s*)?\$?\s*(\d+(?:\.\d+)?)/i);return a&&(t.maxNotionalUsd=Number(a[1])),t}function ri(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 ni(e){let t=Us("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 oi(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 si(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 ii(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 ai(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 ci(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 li(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 ui(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 fi(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 kn(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 di({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:a,spec:i}){let c=[{id:"c",type:"input",field:"close"},{id:"emaLeft",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_left_period"}},{id:"emaRight",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_right_period"}},{id:"cross",type:"cross",direction:i.direction,left:"emaLeft",right:"emaRight"}],f={entryLong:null,entryShort:null,exitLong:null,exitShort:null};if(e==="long"?f.entryLong="cross":f.entryShort="cross",i.reverse){let u=i.direction==="above"?"below":"above";c.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:a,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{ema_left_period:kn(i.fast),ema_right_period:kn(i.slow)},nodes:c,rules:f,risk:{...n,expiresAt:o}}}function pi({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:a,spec:i}){let c=[{id:"c",type:"input",field:"close"},{id:"rsi",type:"indicator",indicator:"rsi",input:"c",period:i.period},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"rsi",right:"thr"}];return{version:1,id:s,name:a,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:c,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function hi({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:a,spec:i}){let c=[{id:"fr",type:"input",field:"fundingRate"},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"fr",right:"thr"}];return{version:1,id:s,name:a,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:c,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function mi({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:a,spec:i}){let c=[{id:"oi",type:"input",field:"openInterest"},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"oi",right:"thr"}];return{version:1,id:s,name:a,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:c,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}var yi=Object.freeze({funding:"fundingRate",open_interest:"openInterest",premium:"premium",oi_delta:"oiDelta",book_imbalance:"bookImbalance"});function wi({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:s,name:a,spec:i}){let f=[{id:"sig_input",type:"input",field:yi[i.kind]},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"sig_input",right:"thr"}];return{version:1,id:s,name:a,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 cr(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(!Ws(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=Ys;if("expiresInMs"in t){if(!Number.isInteger(t.expiresInMs))throw new K("expiresInMs must be an integer");if(n=t.expiresInMs,n<Gs||n>Ks)throw new K("expiresInMs must be between 1h and 30d")}if(Vs.test(e))throw new K(`prompt appears to contain secrets and is rejected. ${He}`);let o=Xs(e);if(!o)throw new K(`empty prompt. ${He}`);if(ri(o))throw new K(`duplicate interval or risk clause. ${He}`);let s=Zs(o),a=Qs(o),i=ei(o);if(!s||!a||!i)throw new K(`could not parse side/coin/interval. ${He}`);let c=ti(o);if(!(c.maxLeverage>0)||c.maxLeverage>50)throw new K("leverage out of range");if(!(c.positionSizePct>0)||c.positionSizePct>100)throw new K("position size out of range");let f=r+n,u=ni(o),l=`Draft ${a} ${s}`.slice(0,100),p=oi(o),h=si(o),d=ii(o),m=ai(o),w=ci(o),k=li(o),S=ui(o),P=[p,h,d,m,w,k,S].filter(Boolean);if(P.length!==1)throw new K(`unsupported or ambiguous prompt. ${He}`);if(!fi(o,P[0]))throw new K(`unsupported or ambiguous prompt. ${He}`);let x,M=P[0],_={side:s,coin:a,interval:i,risk:c,expiresAt:f,id:u,name:l,spec:M};M.kind==="ema_cross"?x=di(_):M.kind==="rsi"?x=pi(_):M.kind==="open_interest"?x=mi(_):M.kind==="funding"?x=hi(_):x=wi(_);let y=mt(x,{nowMs:r});if(!y.ok)throw new K(`draft failed validation: ${y.errors.map(N=>N.message).join("; ")}`);return ar(J(x,{nowMs:r}))}var fr=1,Tn=3,Fe=5,Sn=2,gi=.3,Pn=5,lr=25;function ye(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Qe(e){return typeof e=="number"&&Number.isFinite(e)}function gt(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)gt(t);return Object.freeze(e)}for(let t of Object.keys(e))gt(e[t]);return Object.freeze(e)}function bt(e){return Math.round(e*1e4)/1e4}function X(e){let t=Qe(e)?e:0;return`${t>=0?"+":"-"}${Math.abs(t).toFixed(2)}%`}function wt(e,t=2){return Qe(e)?e>=1e9?">1e9":e.toFixed(t):"n/a"}function dr(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");for(let t=0;t<e.length;t++){let r=e[t];if(!ye(r)||!Qe(r.o)||!Qe(r.c)||!(r.o>0)||!(r.c>0))throw new TypeError(`bars[${t}] must have positive finite o and c`)}}function pr(e){dr(e);let t=e[0].o;return(e[e.length-1].c-t)/t*100}function bi(e){if(typeof e!="string"||!e.startsWith("/"))throw new TypeError(`bad json pointer "${e}"`);return e.slice(1).split("/").map(t=>t.replace(/~1/g,"/").replace(/~0/g,"~"))}function ur(e){return JSON.parse(JSON.stringify(e))}function On(e,t){if(!Array.isArray(t))throw new TypeError("patch must be an array of operations");let r=ur(J(e));for(let n=0;n<t.length;n++){let o=t[n];if(!ye(o))throw new TypeError(`patch[${n}] must be an object`);let s=bi(o.path),a=s[s.length-1],i=r;for(let c of s.slice(0,-1)){if(!ye(i)&&!Array.isArray(i))throw new TypeError(`patch[${n}] path not found: ${o.path}`);i=i[c]}if(!ye(i)&&!Array.isArray(i))throw new TypeError(`patch[${n}] path not found: ${o.path}`);if(o.op==="replace"){if(!(a in i))throw new TypeError(`patch[${n}] replace target missing: ${o.path}`);i[a]=ur(o.value)}else if(o.op==="add")i[a]=ur(o.value);else if(o.op==="remove")delete i[a];else throw new TypeError(`patch[${n}] unsupported op "${o.op}"`)}return J(r)}function ke(e,t,r){return{op:"replace",path:e,value:r,from:t}}function Ei(e){return e.exitBarIndex-e.entryBarIndex}function hr(e,t,r){return e==="long"?(r-t)/t:(t-r)/t}function xi({strategy:e,bars:t,trades:r}){let n=r.filter(i=>i.exitReason==="stop_loss");if(n.length===0)return null;let o=0;for(let i of n){let c=Math.min(t.length-1,i.exitBarIndex+Fe);for(let f=i.exitBarIndex+1;f<=c;f++)if(hr(i.side,i.entryPrice,t[f].c)>0){o+=1;break}}if(o===0)return null;let s=e.risk.stopLossPct,a=Math.min(100,bt(s*1.5));return{rule:"stop_then_reverse",severity:o/r.length,observation:`${o} of ${n.length} stop-outs saw price come back past entry within ${Fe} bars (${r.length} trades total)`,suggestion:`widen risk.stopLossPct from ${s} to ${a} so noise does not knock out positions that were right`,patch:a!==s?[ke("/risk/stopLossPct",s,a)]:null}}function ki({strategy:e,trades:t}){if(t.length===0)return null;let r=t.filter(a=>Ei(a)<=Sn&&a.netPnlUsd<0),n=r.length/t.length;if(n<gi)return null;let o=e.risk.cooldownBars,s=Math.min(1e5,o+3);return{rule:"whipsaw",severity:n,observation:`${r.length} of ${t.length} trades were losers held <= ${Sn} bars (whipsaw ratio ${(n*100).toFixed(0)}%)`,suggestion:`raise risk.cooldownBars from ${o} to ${s} to stop re-entering straight into chop`,patch:[ke("/risk/cooldownBars",o,s)]}}function Si({strategy:e,bars:t,trades:r}){let n=r.filter(c=>c.exitReason==="take_profit");if(n.length===0)return null;let o=e.risk.takeProfitPct/100,s=0;for(let c of n){let f=Math.min(t.length-1,c.exitBarIndex+Fe);for(let u=c.exitBarIndex+1;u<=f;u++)if(hr(c.side,c.entryPrice,t[u].c)>=o*1.5){s+=1;break}}if(s===0)return null;let a=e.risk.takeProfitPct,i=Math.min(1e3,bt(a*1.5));return{rule:"take_profit_capped_winners",severity:s/r.length,observation:`${s} of ${n.length} take-profit exits kept running at least 1.5x further within ${Fe} bars`,suggestion:`raise risk.takeProfitPct from ${a} to ${i} to let winners run`,patch:i!==a?[ke("/risk/takeProfitPct",a,i)]:null}}function Pi({strategy:e,bars:t,trades:r}){let n=r.filter(u=>u.exitReason==="rule");if(n.length===0)return null;let o=e.risk.takeProfitPct/100,s={long:0,short:0};for(let u of n){let l=Math.min(t.length-1,u.exitBarIndex+Fe);for(let p=u.exitBarIndex+1;p<=l;p++)if(hr(u.side,u.exitPrice,t[p].c)>=o/2){s[u.side]+=1;break}}let a=s.long+s.short;if(a===0)return null;let i=s.long>=s.short?"long":"short",c=i==="long"?"exitLong":"exitShort",f=e.rules[c];return{rule:"rule_exit_too_early",severity:a/r.length,observation:`${a} of ${n.length} rule exits were followed by at least half a take-profit move in the trade's favor within ${Fe} bars`,suggestion:`set rules.${c} to null so ${i} exits are governed by stop/take-profit instead of the early signal`,patch:f!=null?[ke(`/rules/${c}`,f,null)]:null}}function Ai({strategy:e,result:t,trades:r}){let n=t.equityCurve,o=t.metrics.maxDrawdownPct;if(!(o>0)||!Array.isArray(n)||n.length===0)return null;let s=-1/0,a=0,i=0,c=0,f=0;for(let w=0;w<n.length;w++){let k=n[w].equity;k>s&&(s=k,a=w);let S=s>0?(s-k)/s*100:0;S>i&&(i=S,c=a,f=w)}let u=r.filter(w=>w.exitBarIndex>c&&w.exitBarIndex<=f),l=0,p=0;for(let w of u)w.netPnlUsd<0?(l+=1,l>p&&(p=l)):l=0;let h=e.risk.positionSizePct,d=Math.max(1,bt(h/2)),m=o>Pn&&d<h;return{rule:"worst_drawdown_context",severity:Math.min(1,o/20),observation:`worst drawdown ${o.toFixed(2)}% ran from bar ${c} to bar ${f} across ${u.length} closed trades (${p} losers in a row)`,suggestion:m?`halve risk.positionSizePct from ${h} to ${d} to cut the depth of losing streaks`:`drawdown is under ${Pn}%; sizing left alone`,patch:m?[ke("/risk/positionSizePct",h,d)]:null}}function Ti({strategy:e,result:t,trades:r}){if(r.length===0)return null;let n=t.costs.feesUsd+t.costs.builderFeesUsd+t.costs.slippageUsd+Math.max(0,t.costs.fundingUsd),o=0;for(let i of r)o+=i.grossPnlUsd;if(!(o>0)||n<o*.5)return null;let s=e.risk.cooldownBars,a=Math.min(1e5,s+3);return{rule:"costs_ate_edge",severity:Math.min(1,n/o)*.8,observation:`fees+slippage ${n.toFixed(2)} USD against ${o.toFixed(2)} USD gross trade pnl over ${r.length} trades`,suggestion:`raise risk.cooldownBars from ${s} to ${a} to trade less and pay less`,patch:[ke("/risk/cooldownBars",s,a)]}}function Oi({strategy:e,result:t,buyAndHoldPct:r,trades:n}){let o=t.metrics.exposurePct;if(n.length===0){let i=e.risk.cooldownBars;return{rule:"time_in_market",severity:.5,observation:`0 trades; strategy was flat for 100% of ${t.equityCurve.length} bars while buy-and-hold returned ${X(r)}`,suggestion:i>0?`set risk.cooldownBars from ${i} to 0; the entry rules never fired`:"entry rules never fired; loosen the entry condition by hand",patch:i>0?[ke("/risk/cooldownBars",i,0)]:null}}if(!(o<lr)||!(r>0))return null;let s=e.risk.cooldownBars,a=Math.floor(s/2);return{rule:"time_in_market",severity:Math.min(1,(lr-o)/lr)*.5,observation:`in market only ${o.toFixed(1)}% of bars while buy-and-hold returned ${X(r)}`,suggestion:s>0?`lower risk.cooldownBars from ${s} to ${a} to sit out less of the move`:"sat out most of the move; entry rules are too strict",patch:s>0&&a!==s?[ke("/risk/cooldownBars",s,a)]:null}}var $i=[xi,ki,Si,Pi,Ai,Ti,Oi];function _i({label:e,returnPct:t,buyAndHoldPct:r,tradeCount:n,beatsHold:o}){return n===0?`${e} never traded (0 trades); buy-and-hold ${X(r)} wins by default`:t<0?o?`${e} lost ${Math.abs(t).toFixed(2)}%; buy-and-hold lost ${Math.abs(r).toFixed(2)}%, so ${e} lost less but still did not make money`:`${e} lost ${Math.abs(t).toFixed(2)}% vs market; buy-and-hold ${X(r)} still wins`:o?`${e} made ${X(t)} vs buy-and-hold ${X(r)} on these bars; past bars only, not a forecast`:`${e} made ${X(t)} but buy-and-hold ${X(r)} still wins`}function $n(e){if(!ye(e))throw new TypeError("reflectOnBacktest expects an object");let{strategy:t,bars:r,version:n=1,backtest:o=te,backtestOptions:s}=e;if(!Number.isInteger(n)||n<1)throw new TypeError("version must be an integer >= 1");if(typeof o!="function")throw new TypeError("backtest must be a function");dr(r);let a=J(t),i=e.result??o(a,r,s??{});if(!ye(i)||!ye(i.metrics)||!Array.isArray(i.trades))throw new TypeError("backtest result must contain metrics and trades");let c=i.trades,f=i.metrics.netPnlPct,u=pr(r);if(!Qe(f))throw new TypeError("metrics.netPnlPct must be finite");let l=c.length>0&&f>u,p=`V${n}`,h={strategy:a,bars:r,result:i,trades:c,buyAndHoldPct:u},d=[];for(let S of $i){let P=S(h);P&&d.push(P)}d.sort((S,P)=>P.severity-S.severity||(S.rule<P.rule?-1:S.rule>P.rule?1:0));let m=d.find(S=>Array.isArray(S.patch)&&S.patch.length>0)||null,w=l||!m?null:m.patch,k={reflectionVersion:fr,version:n,label:p,strategyId:a.id,strategyHash:ie(a),barsHash:typeof i.barsHash=="string"?i.barsHash:null,barCount:r.length,returnPct:f,buyAndHoldPct:u,beatsHold:l,outcome:c.length===0?"no_trades":f<0?"loser":l?"beat_hold":"trailed_hold",profitFactor:i.metrics.profitFactor,maxDrawdownPct:i.metrics.maxDrawdownPct,tradeCount:c.length,winRate:i.metrics.winRate,exposurePct:i.metrics.exposurePct,verdict:_i({label:p,returnPct:f,buyAndHoldPct:u,tradeCount:c.length,beatsHold:l}),critiques:d.map(S=>({rule:S.rule,severity:bt(S.severity),observation:S.observation,suggestion:S.suggestion,patchable:Array.isArray(S.patch)&&S.patch.length>0})),topCritique:m?m.rule:null,nextVersionPatch:w};return gt(k)}function vi(e){if(!ye(e))throw new TypeError("iterateStrategy expects an object");let{strategy:t,bars:r,maxVersions:n=Tn,backtest:o=te,backtestOptions:s}=e;if(!Number.isInteger(n)||n<1||n>20)throw new TypeError("maxVersions must be an integer in [1, 20]");dr(r);let a=J(t),i=new Set,c=[],f="max_versions";for(let d=1;d<=n;d++){let m=ie(a);if(i.has(m)){f="patch_cycle";break}i.add(m);let w=$n({strategy:a,bars:r,version:d,backtest:o,backtestOptions:s});if(c.push({version:d,strategy:a,reflection:w}),w.beatsHold){f="beats_hold";break}if(!w.nextVersionPatch){f="no_suggestion";break}if(d===n)break;let k;try{k=On(a,w.nextVersionPatch)}catch{f="patch_invalid";break}a=k}let u=pr(r),l=c[0];for(let d of c)d.reflection.returnPct>l.reflection.returnPct&&(l=d);let p=c.some(d=>d.reflection.beatsHold),h=p?`${l.reflection.label} beat buy-and-hold on these bars (${X(l.reflection.returnPct)} vs ${X(u)}); past bars only`:`no version beat buy-and-hold ${X(u)}; best was ${l.reflection.label} at ${X(l.reflection.returnPct)}`;return gt({reflectionVersion:fr,buyAndHoldPct:u,barCount:r.length,versions:c,bestVersion:l.version,anyBeatsHold:p,stopReason:f,summary:h})}function An(e){switch(e.outcome){case"beat_hold":return"BEAT HOLD";case"loser":return"LOSER";case"no_trades":return"NO TRADES";default:return"TRAILED HOLD"}}function Ii(e){if(!ye(e))throw new TypeError("renderReflectionCard expects a reflection or iteration result");let t=[];if(Array.isArray(e.versions)){t.push("Strategy iteration");for(let n of e.versions){let o=n.reflection;if(t.push(`${o.label} [${An(o)}] ${X(o.returnPct)} vs hold ${X(o.buyAndHoldPct)} | PF ${wt(o.profitFactor)} | DD ${wt(o.maxDrawdownPct)}% | ${o.tradeCount} trades`),t.push(` ${o.verdict}`),o.topCritique&&o.nextVersionPatch){let s=o.nextVersionPatch[0];t.push(` next: ${s.path} ${String(s.from)} -> ${String(s.value)} (${o.topCritique})`)}}return t.push(e.summary),t.push(`Backtest on ${e.barCount} bars. Past bars, not a forecast. Stopped: ${e.stopReason}.`),t.join(`
|
|
3
|
-
`).replace(/\*\*/g,"")}let r=e;if(t.push(`Strategy reflection ${r.label} [${
|
|
4
|
-
`).replace(/\*\*/g,"")}import
|
|
5
|
-
`;try{we.writeFileSync(n,o,{mode:384,flag:"wx"}),we.renameSync(n,e);try{we.chmodSync(e,384)}catch{}}catch(s){try{we.unlinkSync(n)}catch{}throw s}}var mr=new Map;function wr(e={}){let t=e.path;if(Mi(t),_n(t),we.existsSync(t)?vn(we.readFileSync(t,"utf8"),t):In(t,Ni()),mr.has(t))return mr.get(t);let r=!1,n=[];function o(){if(r)return;let d=n.shift();if(d){r=!0;try{let m=d.fn();r=!1,d.resolve(m),o()}catch(m){r=!1,d.reject(m),o()}}}function s(d){if(!r&&n.length===0){r=!0;try{return d()}finally{r=!1,queueMicrotask(o)}}return new Promise((m,w)=>{n.push({fn:d,resolve:m,reject:w}),queueMicrotask(o)})}function a(){return _n(t),vn(we.readFileSync(t,"utf8"),t)}function i(d){In(t,d)}function c(d){if(!xt(d)||typeof d.id!="string"||!d.id)throw new Error("shadow-store: create requires record with string id");Ce(d,"record");let m=a();if(m.runners.some(k=>k.id===d.id))throw new Error(`shadow-store: runner id already exists: ${d.id}`);let w=ue(d);return m.runners.push(w),i(m),ue(w)}function f(d){let m=a().runners.find(w=>w.id===d);return m?ue(m):null}function u(){return a().runners.map(d=>ue(d))}function l(d,m){if(typeof m!="function")throw new Error("shadow-store: updater must be a function");let w=a(),k=w.runners.findIndex(x=>x.id===d);if(k<0)throw new Error(`shadow-store: runner not found: ${d}`);let S=ue(w.runners[k]),P=m(S);if(!xt(P)||P.id!==d)throw new Error("shadow-store: updater must return record with same id");return Ce(P,"record"),w.runners[k]=ue(P),i(w),ue(w.runners[k])}function p(d){let m=a(),w=m.runners.findIndex(S=>S.id===d);if(w<0)throw new Error(`shadow-store: runner not found: ${d}`);let k=ue(m.runners[w]);return k.status!=="stopped"&&(k.status="stopped",m.runners[w]=k,i(m)),ue(m.runners[w])}let h={create(d){return s(()=>c(d))},get(d){return f(d)},list(){return u()},update(d,m){return s(()=>l(d,m))},stop(d){return s(()=>p(d))}};return mr.set(t,h),h}import{createHash as Er}from"node:crypto";function gr(e){return e==null?e:JSON.parse(JSON.stringify(e))}function br(e){return Array.isArray(e)?e.map(br):e&&typeof e=="object"?Object.fromEntries(Object.keys(e).sort().map(t=>[t,br(e[t])])):e}function jn(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("shadow-runner: record must be an object");return Er("sha256").update(JSON.stringify(br(e))).digest("hex")}function Li(e,t,r,n,o){return Er("sha256").update(`${e}|${t}|${r}|${n}|${o}`).digest("hex")}function Hi(e,t,r,n){return Er("sha256").update(`shadow|${e}|${t}|${r}|${n??""}`).digest("hex")}function Fi(e){return e==="entryLong"||e==="exitShort"?"buy":e==="entryShort"||e==="exitLong"?"sell":e}function Rn(e){return e==="entryLong"||e==="entryShort"}function kt({storePath:e,clock:t=Date.now}={}){if(typeof e!="string"||!e)throw new Error("shadow-runner: storePath required");let r=wr({path:e});function n({strategy:c,evidenceId:f=null}={}){let u=W(c),l=f==null?null:String(f),p=r.list().filter(k=>k.status==="running"&&k.strategyHash===u.strategyHash&&k.compilerHash===u.compilerHash&&k.evidenceId===l).sort((k,S)=>k.createdAt-S.createdAt||k.id.localeCompare(S.id))[0];if(p)return gr(p);let h=t(),d=Hi(h,u.strategyHash,u.compilerHash,l),m=r.get(d);if(m)return gr(m);let w={id:d,strategy:gr(u.strategy),strategyHash:u.strategyHash,compilerHash:u.compilerHash,evidenceId:l,status:"running",cursor:null,intendedOrders:[],fills:[],missedFills:[],markouts:[],createdAt:h,updatedAt:h,position:null,cooldownBarsRemaining:0,cooldownStartT:null,lastProcessedBarIndex:-1};return r.create(w)}function o(c){return r.get(c)}function s(){return r.list()}function a(c){return r.stop(c)}function i(c,f,{markoutHorizons:u=[1,4,12]}={}){if(!Array.isArray(f))throw new TypeError("shadow-runner: bars must be an array");return r.update(c,l=>{if(l.status!=="running")throw new Error("shadow-runner: runner is stopped");if(f.length===0)return l;let h=W(l.strategy).evaluateAll(f),d=new Map;for(let g=0;g<f.length;g++)d.set(f[g].t,g);let m=l.cursor,w=[];for(let g=0;g<f.length;g++){let v=f[g].t;(m==null||v>m)&&w.push(g)}if(w.length===0)return l;let k=new Map(l.intendedOrders.map(g=>[g.id,g])),S=new Set(l.fills.map(g=>g.orderId)),P=new Map(l.missedFills.map(g=>[g.orderId,g])),x=(g,v)=>`${g}|${v}`,M=new Map(l.markouts.map(g=>[x(g.orderId,g.horizon),g])),_=l.position?{...l.position}:null,y=Number.isInteger(l.cooldownBarsRemaining)?Math.max(0,l.cooldownBarsRemaining):0,N=Number.isFinite(l.cooldownStartT)?l.cooldownStartT:null;function D({action:g,signalBarT:v,signalIndex:I}){let C=Fi(g),L=Li(l.id,l.strategyHash,v,C,g);if(k.has(L))return k.get(L);let j=I+1,O=j<f.length,R={id:L,action:g,type:g,side:C,signalBarT:v,fillBarT:O?f[j].t:null,status:O?"open":"missed"};return k.set(L,R),l.intendedOrders.push(R),R}function Y(g,v,I){if(S.has(g.id))return;let C={orderId:g.id,action:Rn(g.action)?"entry":"exit",side:g.side,price:v.o,barT:v.t,signalBarT:g.signalBarT,barIndex:I};if(l.fills.push(C),S.add(g.id),g.status="filled",g.fillBarT=v.t,P.has(g.id)&&(P.delete(g.id),l.missedFills=l.missedFills.filter(L=>L.orderId!==g.id)),Rn(g.action)){_={side:g.action==="entryLong"?"long":"short",entryOrderId:g.id,entryBarT:v.t,entryPrice:v.o,entryBarIndex:I};for(let L of u){let j=x(g.id,L);if(M.has(j))continue;let O={orderId:g.id,horizon:L,entryBarT:v.t,entryPrice:v.o,side:_.side,status:"pending",close:null,barT:null};M.set(j,O),l.markouts.push(O)}}else _=null,y=Number(l.strategy?.risk?.cooldownBars)||0,N=v.t}function A(g){if(S.has(g.id)||P.has(g.id))return;let v={orderId:g.id,action:g.action,side:g.side,signalBarT:g.signalBarT,status:"missed"};P.set(g.id,v),l.missedFills.push(v),g.status="missed"}for(let g of l.intendedOrders){if(g.status==="filled"||S.has(g.id))continue;let v=d.get(g.signalBarT);if(v==null)continue;let I=v+1;I<f.length&&(m==null||f[I].t>m)&&Y(g,f[I],I)}for(let g of w){let v=f[g],I=h[g].signals,C=_,L=O=>{if(_||y>0&&(N==null||v.t>=N))return;let $=D({action:O,signalBarT:v.t,signalIndex:g}),Q=g+1;Q<f.length?Y($,f[Q],Q):A($)},j=O=>{if(!_||_.side==="long"&&O!=="exitLong"||_.side==="short"&&O!=="exitShort")return;let R=D({action:O,signalBarT:v.t,signalIndex:g}),$=g+1;$<f.length?Y(R,f[$],$):A(R)};C?(I.exitLong&&j("exitLong"),I.exitShort&&j("exitShort")):I.entryLong&&I.entryShort||(I.entryLong&&L("entryLong"),I.entryShort&&L("entryShort")),y>0&&N!=null&&v.t>=N&&(y-=1,y===0&&(N=null)),l.cursor=v.t,l.lastProcessedBarIndex=g}for(let g of l.markouts){if(g.status!=="pending")continue;let v=l.fills.find(L=>L.orderId===g.orderId&&L.action==="entry");if(!v)continue;let I=d.get(v.barT);if(I==null)continue;let C=I+g.horizon;if(C<f.length){g.close=f[C].c,g.barT=f[C].t,g.status="filled";let L=g.entryPrice;g.markout=g.side==="long"?(g.close-L)/L:(L-g.close)/L}}return l.position=_,l.cooldownBarsRemaining=y,l.cooldownStartT=N,l.updatedAt=t(),l})}return{start:n,step:i,list:s,get:o,stop:a}}import Ci from"node:os";import Di from"node:path";var Bi=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function et(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Ui(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function kr(e){if(Array.isArray(e)){for(let t of e)kr(t);return}if(et(e))for(let[t,r]of Object.entries(e)){if(Bi.some(n=>Ui(t).includes(n)))throw new Error(`strategy service: secret-like field "${t}" is forbidden`);kr(r)}}function qi(e){if(!et(e))throw new TypeError("strategy input must be a plain object");return kr(e),e}function zi(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 xr(e,t,r,n){if(Array.isArray(t.bars))return t.bars;let o=dt(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 a=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 i=Array.isArray(a)?a:a?.bars;if(!Array.isArray(i))throw new Error("strategy history provider returned no bars");return i}function Sr(e,t){let r=e.backtestOptions??{};if(!et(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(!et(s))throw new TypeError("evidenceOptions must be a plain object");return{...s,...o,strategy:t,bars:r,backtestOptions:Sr(e,n)}}function Nn(){return Di.join(Ci.homedir(),".oracle","strategy-shadow.json")}function Vi(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 Ji(e,t={},r={}){r.signal?.throwIfAborted?.();let n=qi(t),o=zi(n,r);if(e==="draft")return{strategy:cr(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),a=await xr(s.strategy,n,r,o);Ye(s,a);let i=ut(Mn(n,s.strategy,a,o));return e==="evidence"?i:{backtest:te(s.strategy,a,Sr(n,o)),evidence:i}}if(e==="optimize"){let s=W(n.strategy),a=await xr(s.strategy,n,r,o);Ye(s,a);let i=n.trainFraction,c=n.evidenceOptions?.trainFraction;if(i!=null&&c!=null&&i!==c)throw new TypeError("conflicting trainFraction controls are forbidden");let f=i??c??.7;if(typeof f!="number"||f<=0||f>=1)throw new TypeError("trainFraction must be in (0,1)");let u=a.slice(0,Math.floor(a.length*f)),l=n.options??{};if(!et(l))throw new TypeError("options must be a plain object");let p=ir(s.strategy,u,{...l,...n.maxTrials==null?{}:{maxTrials:n.maxTrials},backtestOptions:Sr(n,o)}),h=p.bestStrategy;return{strategy:h,optimization:p,evidence:ut(Mn(n,h,a,o,{trainFraction:f}))}}if(e==="shadow"){let s=kt({storePath:r.storePath??Nn(),clock:()=>o}),a=n.action;if(a==="start")return await s.start({strategy:n.strategy,evidenceId:n.evidenceId??n.evidence?.id??null});if(a==="list")return await s.list();if(a==="get")return await s.get(n.id);if(a==="stop")return await s.stop(n.id);if(a==="step"){let i=await s.get(n.id);if(!i)throw new Error(`shadow runner not found: ${n.id}`);let c=await xr(i.strategy,n,r,o);return Ye(W(i.strategy),c),await s.step(n.id,c,n.stepOptions??{})}throw new Error(`unknown shadow action: ${a}`)}if(e==="prepare"){let s=W(n.strategy),a=dt(s.strategy.venue);if(typeof n.shadowId!="string"||!n.shadowId)throw new Error("strategy prepare requires a matching shadow runner id");let c=await kt({storePath:r.storePath??Nn(),clock:()=>o}).get(n.shadowId);if(!c)throw new Error("strategy prepare shadow runner not found");if(c.status!=="running")throw new Error("strategy prepare requires an active shadow runner");if(!Number.isFinite(c.cursor))throw new Error("strategy prepare requires a stepped shadow runner");if(c.strategyHash!==s.strategyHash||c.compilerHash!==s.compilerHash)throw new Error("strategy prepare shadow runner does not match strategy artifacts");if(c.evidenceId!==n.evidence?.id)throw new Error("strategy prepare shadow runner does not match evidence artifact");let f=n.caps??Vi(s.strategy,o);return a.prepareIntent({strategy:s.strategy,evidence:n.evidence,shadow:{id:c.id,stateHash:jn(c),status:c.status,cursor:c.cursor,updatedAt:c.updatedAt},caps:f,nowMs:o,env:r.env??process.env})}throw new Error(`unknown strategy operation: ${e}`)}export{Tn as DEFAULT_MAX_VERSIONS,Yr as EVIDENCE_STATUSES,or as MAX_OPTIMIZER_TRIALS,fr as REFLECTION_VERSION,Ee as STRATEGY_COMPILER_HASH,Re as STRATEGY_COMPILER_VERSION,pt as STRATEGY_VERSION,K as StrategyDraftError,_e as StrategyValidationError,je as applyParameterOverrides,On as applyStrategyPatch,Jt as assertEvidenceArtifact,Ft as atr,Fs as attachDerivedSeries,te as backtestStrategy,Ht as bollinger,pr as buyAndHoldReturnPct,wn as canonicalStrategyJson,W as compileStrategy,Vt as computeEvidenceArtifactId,kt as createShadowRunner,Hs as deriveSeries,cr as draftStrategyFromPrompt,Je as ema,ut as evaluateEvidence,Xt as fetchHyperliquidStrategyBars,en as intervalToMs,vi as iterateStrategy,Lt as macd,tn as normalizeHyperliquidCandles,J as normalizeStrategy,wr as openShadowStore,ir as optimizeStrategy,Wt as prepareStrategyLiveHandoff,$n as reflectOnBacktest,Ii as renderReflectionCard,dt as requireStrategyVenue,ft as resolveStrategyVenue,Nt as rsi,Ji as runStrategyOperation,Ls as sampleLiveSeries,Mt as sma,ie as strategyHash,xs as strategyVenues,mt as validateStrategy};
|
|
1
|
+
var si=Object.defineProperty;var V=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var nr=(e,t)=>{for(var r in t)si(e,r,{get:t[r],enumerable:!0})};import{AsyncLocalStorage as ai}from"node:async_hooks";function kt(e){let t=ci.getStore();if(!t||t.closed||!li.includes(e))return null;if(t.spans.length>=ui)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)}}var ci,li,ui,bn=V(()=>{ci=new ai,li=["http","retry","shared"],ui=512});import je from"node:net";import fi from"node:dns";function Tt(e){let t=String(e).toLowerCase().split("%")[0];if((t.match(/::/g)||[]).length>1)return null;let r=u=>{if(!u)return[];let l=u.split(":"),h=l.at(-1);if(h?.includes(".")){let p=h.split(".").map(Number);if(p.length!==4||p.some(d=>!Number.isInteger(d)||d<0||d>255))return null;l.splice(l.length-1,1,(p[0]<<8|p[1]).toString(16),(p[2]<<8|p[3]).toString(16))}return l.some(p=>!/^[0-9a-f]{1,4}$/.test(p))?null:l.map(p=>Number.parseInt(p,16))},[n,o]=t.split("::"),a=r(n),i=r(o);if(!a||!i)return null;let s=t.includes("::"),c=8-a.length-i.length;if(!s&&c!==0||s&&c<1)return null;let f=[...a,...Array(Math.max(0,c)).fill(0),...i];return f.length!==8?null:Uint8Array.from(f.flatMap(u=>[u>>8,u&255]))}function or(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 a=255<<8-o;return(e[n]&a)===(t[n]&a)}function ir(e){if(je.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(je.isIPv6(e)){let t=Tt(e);if(!t)return!1;let r=Tt("::ffff:0:0");return or(t,r,96)?ir([...t.slice(12)].join(".")):or(t,Tt("2000::"),3)?![["2001::",23],["2001:db8::",32],["2001:10::",28],["2001:2::",48],["2002::",16],["3fff::",20]].some(([o,a])=>or(t,Tt(o),a)):!1}return!1}function pi(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(di.has(r)||r.endsWith(".localhost")||r.endsWith(".internal"))return{ok:!1,error:`refused internal host ${r}`};let n=je.isIP(r);return n!==0&&!ir(r)?{ok:!1,error:`refused private address ${r}`}:{ok:!0,url:t,host:r,isLiteralIp:n!==0}}async function sr(e,{lookupFn:t=fi.promises.lookup}={}){let r=pi(e);if(!r.ok)return r;if(r.isLiteralIp)return{ok:!0,url:r.url,addresses:[{address:r.host,family:je.isIPv6(r.host)?6:4}]};let n;if(process.env.ORACLE_HOSTED_EGRESS_PROXY)return{ok:!0,url:r.url,addresses:[]};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=>!ir(o.address))?{ok:!1,error:`refused: ${r.host} resolves to a non-public address`}:{ok:!0,url:r.url,addresses:n}}function hi(e=process.env){let t=e.ORACLE_HOSTED_EGRESS_PROXY||"";if(!t)return null;let r;try{r=new URL(t)}catch{throw new Error("egress-guard: ORACLE_HOSTED_EGRESS_PROXY is not a URL")}if(r.protocol!=="http:"||!["127.0.0.1","::1","localhost","[::1]"].includes(r.hostname)||!r.port||r.username||r.password)throw new Error("egress-guard: egress proxy must be an exact loopback http origin");let n=e.ORACLE_HOSTED_EGRESS_TOKEN||"";if(!/^[A-Za-z0-9_-]{43}$/.test(n))throw new Error("egress-guard: egress proxy token is missing");return{uri:r.origin,token:n}}async function ar({requireUndici:e=!1,importUndici:t=()=>import("undici")}={}){let r,n,o;try{o=await t(),r=o.Agent,n=o.fetch}catch(p){if(e)throw new Error(`egress-guard: untrustedUrl pinning requires the undici package, which failed to load: ${p?.message||p}`);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 a=p=>String(p).toLowerCase().replace(/^\[|\]$/g,"").replace(/\.+$/,""),i=new Map,s=p=>(Array.isArray(p)?p:[p]).map(d=>typeof d=="string"?{address:d}:d).filter(d=>d&&d.address).map(d=>({address:d.address,family:d.family||(je.isIPv6(d.address)?6:4)})),c=(p,d,m)=>{i.set(a(p),s(typeof d=="string"?[{address:d,family:m}]:d))},f=p=>{let d=a(p);if(je.isIP(d))return[{address:d,family:je.isIPv6(d)?6:4}];let m=i.get(d);if(!m||!m.length)throw new Error(`refused: unpinned host ${p} during pinned fetch`);return m},u=hi(),l=u&&typeof o.ProxyAgent=="function"?new o.ProxyAgent({uri:u.uri,token:`Bearer ${u.token}`,connectTimeout:1e4}):new r({connect:{lookup(p,d,m){let y;try{y=f(p)}catch(b){return m(b)}return d?.all?m(null,y):m(null,y[0].address,y[0].family)}}}),h=mi((p,d={})=>n(p,{...d,dispatcher:l}),c);return{dispatcher:l,fetch:h,pin:c,resolve:f,async close(){try{await l.destroy()}catch{}}}}function mi(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[cr]=Object.freeze({pin:t}),e}function lr(e){return typeof e=="function"&&typeof e[cr]?.pin=="function"}function En(e,t,r){if(!lr(e))throw new Error("pinFetchToAddresses: fetchImpl is not pin-capable");e[cr].pin(t,r)}var di,cr,xn=V(()=>{di=new Set(["localhost","metadata.google.internal","metadata.goog"]);cr=Symbol.for("oracle.egressGuard.pinCapableFetch")});import{createHash as yi}from"node:crypto";import{types as Se}from"node:util";function W(e){return ve(`HTTP JSON body refused: ${e}`)}function Ai(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 Se[t]=="function"&&Se[t](e))}function Oi(e){let t=[],r=0,n=0,o=0,a=0,i=new WeakSet,s=u=>{if(r+=Buffer.byteLength(u,"utf8"),r>xe.bytes)throw W("serialized byte limit exceeded");t.push(u)},c=u=>{if(Buffer.byteLength(u,"utf8")>xe.bytes)throw W("serialized byte limit exceeded");return JSON.stringify(u)},f=(u,l)=>{if(n+=1,n>xe.nodes)throw W("node limit exceeded");if(l>xe.depth)throw W("depth limit exceeded");if(u===null){s("null");return}if(typeof u=="string"){s(c(u));return}if(typeof u=="boolean"){s(u?"true":"false");return}if(typeof u=="number"){if(!Number.isFinite(u))throw W("non-finite number");s(Object.is(u,-0)?"0":String(u));return}if(typeof u!="object")throw W("unsupported non-JSON value");if(Se.isProxy(u))throw W("proxy value");if(Ai(u))throw W("unsupported exotic object");if(i.has(u))throw W("cyclic value");i.add(u);try{if(Object.getOwnPropertySymbols(u).length>0)throw W("symbol-keyed fields are unsupported");if(Array.isArray(u)){let d=Object.getPrototypeOf(u),m=0;for(;d!==null;){if(Se.isProxy(d))throw W("proxy array prototype");if(m+=1,m>xe.depth)throw W("array prototype depth limit exceeded");d=Object.getPrototypeOf(d)}if(u.length>xe.arrayLength)throw W("array length limit exceeded");for(let b=0;b<u.length;b+=1){let w=Object.getOwnPropertyDescriptor(u,String(b));if(!w||!Object.hasOwn(w,"value")||w.enumerable!==!0)throw W("array entries must be dense enumerable own data")}let y=0;for(let b in u){if(a+=1,a>xe.fields)throw W("enumeration limit exceeded");if(Object.hasOwn(u,b)&&(y+=1,y>u.length))throw W("named array fields are unsupported")}if(y!==u.length)throw W("array entries must be dense enumerable own data");s("[");for(let b=0;b<u.length;b+=1)b&&s(","),f(Object.getOwnPropertyDescriptor(u,String(b)).value,l+1);s("]");return}let h=Object.getPrototypeOf(u);if(h!==Object.prototype&&h!==null)throw W("non-plain object");let p=[];for(let d in u){if(a+=1,a>xe.fields)throw W("enumeration limit exceeded");if(!Object.hasOwn(u,d))continue;if(o+=1,o>xe.fields)throw W("field limit exceeded");let m=Object.getOwnPropertyDescriptor(u,d);if(!m||!Object.hasOwn(m,"value")||m.enumerable!==!0)throw W("object fields must be enumerable own data");p.push([d,m.value])}s("{");for(let d=0;d<p.length;d+=1)d&&s(","),s(c(p[d][0])),s(":"),f(p[d][1],l+1);s("}")}finally{i.delete(u)}};return f(e,0),t.join("")}function vi(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(Se.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 a=Object.getOwnPropertyDescriptor(e,n);if(!a||!Object.hasOwn(a,"value"))throw new TypeError("HTTP headers must contain own data properties");let i=a.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 Pi(){return Object.assign(Object.create(null),{Accept:"application/json"})}function $i(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 _i(e,t){return new URL(String(e)).origin===new URL(String(t)).origin}function At(e){if((typeof e!="object"||e===null)&&typeof e!="function")return`${typeof e}:${String(e)}`;let t=On.get(e);return t||(t=vn,vn+=1,On.set(e,t)),`reference:${t}`}function Pn(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?Ii.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 $n(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(Pn);if(!r||typeof r!="object")return!1;if(Object.hasOwn(r,"jsonrpc")||Object.hasOwn(r,"method"))return Pn(r);let n=Object.hasOwn(r,"type")?r.type:null;return typeof n=="string"&&Ri.has(n)&&(!Object.hasOwn(r,"action")||r.action==null)&&(!Object.hasOwn(r,"signature")||r.signature==null)&&(!Object.hasOwn(r,"nonce")||r.nonce==null)}function Ni(e,t,r,n={},o=null){let a=yi("sha256"),i=(c,f)=>{let u=String(f);a.update(String(Buffer.byteLength(c,"utf8"))).update(":").update(c),a.update("=").update(String(Buffer.byteLength(u,"utf8"))).update(":").update(u).update(`
|
|
2
|
+
`)};i("method",e),i("url",t),Object.keys(r||{}).map((c,f)=>({name:c.toLowerCase(),order:f,value:String(r[c])})).sort((c,f)=>c.name.localeCompare(f.name)||c.order-f.order).forEach((c,f)=>{i(`header-name-${f}`,c.name),i(`header-value-${f}`,c.value)}),i("body",o??"-");for(let c of["untrustedUrl","maxResponseBytes","sameOriginRedirectsOnly","redirectPolicy","maxRedirects","timeoutMs","retries","fetchImpl","realFetch","lookupFn","importUndici","validateResponse"])i(`context-${c}`,n[c]??"-");return a.digest("hex")}function ji(e,t){let r=Number(t);return Number.isFinite(r)&&r>0?Math.min(r*1e3,kn):Math.min(250*2**e,kn)+Math.floor(Math.random()*100)}function ve(e,t={}){let r=new Error(e);return r.retryable=!1,Object.assign(r,t),r}function fr(e,t,r){return ve(`HTTP response from ${e} exceeded maxResponseBytes ${r} (${t})`,{oversize:!0})}function Me(e){try{let t=e?.body?.cancel?.();t&&typeof t.then=="function"&&t.catch(()=>{})}catch{}}function Li(e){return e?e.byteLength??e.length??0:0}async function Hi(e,t,{url:r,truncate:n=!1,onOversize:o}={}){if(t==null)return await e.text();let a=Number(e.headers?.get?.("content-length"));if(Number.isFinite(a)&&a>t&&(Me(e),!n))throw fr(r,`content-length ${a}`,t);let i=e.body?.getReader?.();if(!i){let l=await e.text(),h=Buffer.byteLength(l,"utf8");if(h>t){if(!n)throw fr(r,`body ${h} bytes`,t);return Buffer.from(l,"utf8").subarray(0,t).toString("utf8")}return l}let s=[],c=0,f=!1;try{for(;;){let{value:l,done:h}=await i.read();if(h)break;if(l&&(s.push(Buffer.from(l)),c+=Li(l),c>t)){f=!0;break}}}finally{if(f)try{await i.cancel()}catch{}try{i.releaseLock?.()}catch{}}if(f&&(typeof o=="function"&&o(),!n))throw fr(r,`streamed ${c} bytes`,t);let u=Buffer.concat(s);return(f?u.subarray(0,t):u).toString("utf8")}function Ci(e){if(!e)return null;try{return JSON.parse(e)}catch{return null}}async function Fi(e,{fetchImpl:t,method:r,headers:n,body:o,timeoutMs:a,lookupFn:i,realFetch:s,untrustedUrl:c=!1,maxResponseBytes:f=null,sameOriginRedirectsOnly:u=!1,importUndici:l,validateResponse:h,signal:p,redirectPolicy:d="follow",maxRedirects:m=Ot}){let y=null,b=t,w=i?{lookupFn:i}:{};if(c&&!s&&!lr(b))throw ve(`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 A=new AbortController,E=setTimeout(()=>A.abort(),a),v=p?An?An([p,A.signal]):p:A.signal,O=async(g,{status:M=null}={})=>{let q=await sr(g,w);if(!q.ok)throw ve(M==null?`HTTP refused ${g}: ${q.error}`:`HTTP redirect to ${g} ${q.error}`,M==null?{}:{status:M});let z=new URL(g).hostname;if(s){if(y&&(await y.close(),y=null),!y)try{y=await ar({requireUndici:!0,...l?{importUndici:l}:{}})}catch(P){throw ve(M==null?`HTTP refused ${g}: ${P?.message||P}`:`HTTP redirect to ${g} refused: ${P?.message||P}`,M==null?{}:{status:M})}y.pin(z,q.addresses),b=y.fetch}else En(b,z,q.addresses);return q};try{let g=String(e),M=Object.assign(Object.create(null),n||{});c&&await O(g);for(let q=0;q<=m;q+=1){let z=Object.assign(Object.create(null),{method:r,headers:M,body:o,signal:v,redirect:"manual",dispatcher:void 0}),P=await b(g,z);if((d==="error"||m===0)&&P.status>=300&&P.status<400)throw Me(P),ve(`HTTP ${P.status} ${r} redirect refused`,{status:P.status,redirectRefused:!0});if(Ti.has(P.status)){let T=u===!0&&r==="POST"&&[307,308].includes(P.status)&&$n(r,o);if(r!=="GET"&&r!=="HEAD"&&!T){Me(P);let $=new Error(`HTTP ${P.status} ${r} ${g} redirected non-idempotent request`);throw $.status=P.status,$}if(q===m)throw Me(P),ve(`HTTP ${P.status} ${r} redirect budget exhausted`,{status:P.status,redirectRefused:!0});let C=P.headers?.get?.("location"),L;try{L=$i(C,g)}catch($){throw Me(P),$}let j=!_i(L,g);if(Me(P),j&&r==="POST"){let $=new Error(`HTTP ${P.status} ${r} cross-origin redirect refused`);throw $.status=P.status,$}if(j&&u){let $=new Error(`HTTP ${P.status} ${r} cross-origin redirect refused`);throw $.status=P.status,$.retryable=!1,$}if(j&&(M=Pi(M)),c)await O(L,{status:P.status});else if(j){let $=await sr(L,w);if(!$.ok){let R=new Error(`HTTP redirect from ${g} ${$.error}`);throw R.status=P.status,R.retryable=!1,R}s&&$.addresses?.length&&(y||(y=await ar(l?{importUndici:l}:{})),y&&(y.pin(new URL(L).hostname,$.addresses),b=y.fetch))}g=L;continue}if(typeof h=="function")try{await h(P,{url:g})}catch(T){throw Me(P),ve(T?.message||String(T))}let x=await Hi(P,f,{url:g,onOversize:()=>A.abort()}),N=Ci(x);if(!P.ok){let T=new Error(`HTTP ${P.status} ${r} ${g}`);throw T.status=P.status,T.retryAfter=P.headers?.get?.("retry-after")??null,T.body=N??x.slice(0,300),T}return N??x}throw new Error(`HTTP redirect loop for ${e}`)}catch(g){if(A.signal.aborted&&!ct(p)){let M=g&&(typeof g=="object"||typeof g=="function")&&!Se.isProxy(g)?g:null,q=M?Object.getOwnPropertyDescriptor(M,"oversize"):null;if(!(q&&Object.hasOwn(q,"value")&&q.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 P=new Error("HTTP request timed out");throw Object.defineProperties(P,{oracleTimeout:{value:!0,enumerable:!1},retryable:{value:!1,enumerable:!1}}),P}}throw g}finally{clearTimeout(E),y&&await y.close()}}async function _n(e,t={}){if(t!=null&&typeof t!="object"&&typeof t!="function")throw new TypeError("HTTP options must be an object");if(t!=null&&Se.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 R of Object.getOwnPropertyNames(t)){let I=Object.getOwnPropertyDescriptor(t,R);if(!(R==="toJSON"&&I&&Object.hasOwn(I,"value")&&I.value===void 0)){if(!r.has(R))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=R=>{if(t==null||!Object.hasOwn(t,R))return;let I=Object.getOwnPropertyDescriptor(t,R);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 a=n("timeoutMs");if(a!==void 0&&(!Number.isInteger(a)||a<1||a>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 s=n("redirectPolicy");if(s!==void 0&&s!=="follow"&&s!=="error")throw new TypeError('HTTP redirectPolicy must be "follow" or "error"');let c=n("maxRedirects");if(c!==void 0&&(!Number.isInteger(c)||c<0||c>Ot))throw new TypeError(`HTTP maxRedirects must be an integer from 0 through ${Ot}`);if(s==="error"&&c!==void 0&&c!==0)throw new TypeError('HTTP redirectPolicy "error" requires maxRedirects 0 when supplied');let f=s??"follow",u=f==="error"?0:c??Ot;for(let R of["dedupe","untrustedUrl","sameOriginRedirectsOnly"]){let I=n(R);if(I!==void 0&&typeof I!="boolean")throw new TypeError(`HTTP ${R} must be boolean`)}let l=n("maxResponseBytes");if(l!==void 0&&(!Number.isInteger(l)||l<1||l>64*1024*1024))throw new TypeError("HTTP maxResponseBytes must be a bounded integer");let h=n("signal");if(h!==void 0){if(Se.isProxy(h)||!(h instanceof AbortSignal))throw new TypeError("HTTP signal must be a native AbortSignal");try{ct(h)}catch{throw new TypeError("HTTP signal must be a native AbortSignal")}}for(let R of["importUndici","lookupFn","validateResponse"]){let I=n(R);if(I!==void 0&&typeof I!="function")throw new TypeError(`HTTP ${R} must be a function`)}let p=n("fetchImpl"),d=p||globalThis.fetch;if(typeof d!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let m=a??12e3,y=(o||"GET").toUpperCase(),b=n("headers"),w=vi(b),A=Object.assign(Object.create(null),w);Object.keys(A).some(R=>R.toLowerCase()==="accept")||(A.Accept="application/json");let E=n("body");E!=null&&typeof E!="string"&&(Object.keys(A).find(I=>I.toLowerCase()==="content-type")||(A["Content-Type"]="application/json"),E=Oi(E));let v=i??gi,O=n("lookupFn"),g=!p,M=n("untrustedUrl")===!0,q=n("sameOriginRedirectsOnly")===!0,z=n("importUndici"),P=n("validateResponse"),x=h,N=l??null,T=async()=>{let R;for(let I=0;I<=v;I++){x&&xi.call(x);let re=kt("http");try{let te=await Fi(e,{fetchImpl:d,method:y,headers:A,body:E,timeoutMs:m,lookupFn:O,realFetch:g,untrustedUrl:M,maxResponseBytes:N,sameOriginRedirectsOnly:q,importUndici:z,validateResponse:P,signal:x,redirectPolicy:f,maxRedirects:u});return re?.("succeeded"),te}catch(te){R=te;let se=Re=>{if(!te||typeof te!="object"&&typeof te!="function"||Se.isProxy(te))return;let be=Object.getOwnPropertyDescriptor(te,Re);return be&&Object.hasOwn(be,"value")?be.value:void 0},ge=se("status");re?.("failed",ge);let xt=se("oracleTimeout")===!0||se("name")==="AbortError"||se("name")==="TimeoutError"||ct(x),St=new Set([408,425,429]),yn=se("retryable")===!1?!1:ge!=null?St.has(ge)||wi.has(ge)&&Sn.has(y):!xt&&Sn.has(y);if(I===v||!yn)throw te;let ot=ji(I,se("retryAfter")),er=kt("retry"),it=!1;try{x?await new Promise((Re,be)=>{let ze,Ne=()=>{clearTimeout(ze),Tn.call(x,"abort",Ne),be(ki(x)||new DOMException("Aborted","AbortError"))};if(ct(x)){Ne();return}ze=setTimeout(()=>{Tn.call(x,"abort",Ne),Re()},ot),Si.call(x,"abort",Ne,{once:!0}),ct(x)&&Ne()}):await Mi(ot),it=!0}finally{er?.(it?"succeeded":"failed")}}}throw R};if(!(n("dedupe")!==!1&&!x&&$n(y,E)))return T();let L=Ni(y,e,A,{untrustedUrl:M,maxResponseBytes:N,sameOriginRedirectsOnly:q,redirectPolicy:f,maxRedirects:u,timeoutMs:m,retries:v,fetchImpl:At(d),realFetch:g,lookupFn:At(O),importUndici:At(z),validateResponse:At(P)},E),j=ur.get(L);if(j){let R=kt("shared");try{let I=await j;return R?.("succeeded"),I}catch(I){throw R?.("failed"),I}}let $=T().finally(()=>ur.delete(L));return ur.set(L,$),$}var wi,Sn,gi,kn,bi,Ei,xi,Si,Tn,An,ct,ki,Ti,Ot,Dc,xe,ur,On,vn,Ii,Ri,Mi,In=V(()=>{bn();xn();wi=new Set([408,425,429,500,502,503,504]),Sn=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),gi=2,kn=4e3,bi=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"aborted")?.get,Ei=Object.getOwnPropertyDescriptor(AbortSignal.prototype,"reason")?.get,xi=AbortSignal.prototype.throwIfAborted,Si=EventTarget.prototype.addEventListener,Tn=EventTarget.prototype.removeEventListener,An=typeof AbortSignal.any=="function"?AbortSignal.any.bind(AbortSignal):null,ct=e=>e?bi.call(e):!1,ki=e=>e?Ei.call(e):void 0,Ti=new Set([301,302,303,307,308]),Ot=3,Dc=64*1024,xe=Object.freeze({depth:32,nodes:1e4,fields:1e4,arrayLength:1e4,bytes:1024*1024});ur=new Map,On=new WeakMap,vn=1;Ii=new Set(["eth_blockNumber","eth_call","eth_chainId","eth_estimateGas","getHealth","minimumLedgerSlot","net_version","simulateTransaction","web3_clientVersion"]),Ri=new Set(["allMids","l2Book","outcomeMeta","spotClearinghouseState","userFills","meta","metaAndAssetCtxs","perpDexs","candleSnapshot","fundingHistory","openOrders","frontendOpenOrders","clearinghouseState","spotMeta","validatorSummaries","delegatorSummary","delegations","delegatorRewards","delegatorHistory","maxBuilderFee"]);Mi=e=>new Promise(t=>setTimeout(t,e))});import{types as Rn}from"node:util";function qi(e){if(!e||typeof e!="object"||Rn.isProxy(e)||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function vt(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(Rn.isProxy(e)||e.length>1e5)throw new Error(`${t} contains an invalid array`);let o=new Array(e.length);for(let a=0;a<e.length;a+=1){let i=Object.getOwnPropertyDescriptor(e,String(a));if(!i||!Object.hasOwn(i,"value"))throw new Error(`${t} arrays must contain dense own data`);o[a]=vt(i.value,t,r+1)}return o}if(!qi(e))throw new Error(`${t} contains a non-JSON value`);let n=Object.create(null);for(let o of Object.keys(e)){let a=Object.getOwnPropertyDescriptor(e,o);if(!a||!Object.hasOwn(a,"value"))throw new Error(`${t} objects must contain own data`);n[o]=vt(a.value,t,r+1)}return n}var Nn=V(()=>{});function Ui({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"?Di:Bi}async function ke(e,t={}){if(!e||!e.type)throw new Error("hlInfo requires body.type");let r=Ui(t);return vt(await _n(r,{method:"POST",body:e,fetchImpl:t.fetchImpl,timeoutMs:t.timeoutMs,maxResponseBytes:t.maxResponseBytes,sameOriginRedirectsOnly:t.sameOriginRedirectsOnly}),"hyperliquid info response")}async function jn(e,t={}){if(!e)throw new Error("hlL2Book requires coin");return ke({type:"l2Book",coin:String(e)},t)}async function Mn(e={}){return ke({type:"meta"},e)}async function Ln(e={}){let t={type:"metaAndAssetCtxs"};return e.dex&&(t.dex=e.dex),ke(t,e)}async function Hn({coin:e,interval:t="1h",startTime:r,endTime:n},o={}){if(!e)throw new Error("hlCandleSnapshot requires coin");let a={type:"candleSnapshot",req:{coin:String(e),interval:t,startTime:r??Date.now()-24*3600*1e3,endTime:n??Date.now()}};return ke(a,o)}async function Cn({coin:e,startTime:t,endTime:r},n={}){if(!e)throw new Error("hlFundingHistory requires coin");return ke({type:"fundingHistory",coin:String(e),startTime:t??Date.now()-24*3600*1e3,endTime:r??Date.now()},n)}var Bi,Di,Ve=V(()=>{In();Nn();Bi="https://api.hyperliquid.xyz/info",Di="https://api.hyperliquid-testnet.xyz/info"});function ut(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 Pe(e){if(!Number.isInteger(e)||e<=0)throw new TypeError("period must be a positive integer")}function zi(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 dr(e,t){ut(e),Pe(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 lt(e,t){ut(e),Pe(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 a=2/(t+1);for(let i=t;i<e.length;i++)o=a*e[i]+(1-a)*o,r[i]=o;return r}function pr(e,t){ut(e),Pe(t);let r=new Array(e.length).fill(null);if(e.length<=t)return r;let n=0,o=0;for(let s=1;s<=t;s++){let c=e[s]-e[s-1];c>=0?n+=c:o-=c}let a=n/t,i=o/t;r[t]=Fn(a,i);for(let s=t+1;s<e.length;s++){let c=e[s]-e[s-1],f=c>0?c:0,u=c<0?-c:0;a=(a*(t-1)+f)/t,i=(i*(t-1)+u)/t,r[s]=Fn(a,i)}return r}function Fn(e,t){return e===0&&t===0?50:t===0?100:e===0?0:100-100/(1+e/t)}function hr(e,t={}){ut(e);let r=t.fastPeriod,n=t.slowPeriod,o=t.signalPeriod;if(Pe(r),Pe(n),Pe(o),r>=n)throw new TypeError("fastPeriod must be < slowPeriod");let a=lt(e,r),i=lt(e,n),s=new Array(e.length).fill(null);for(let l=0;l<e.length;l++)a[l]!=null&&i[l]!=null&&(s[l]=a[l]-i[l]);let c=new Array(e.length).fill(null),f=new Array(e.length).fill(null),u=[];for(let l=0;l<s.length;l++)s[l]!=null&&u.push(l);if(u.length>=o){let l=0;for(let m=0;m<o;m++)l+=s[u[m]];let h=l/o,p=u[o-1];c[p]=h,f[p]=s[p]-h;let d=2/(o+1);for(let m=o;m<u.length;m++){let y=u[m];h=d*s[y]+(1-d)*h,c[y]=h,f[y]=s[y]-h}}return{line:s,signal:c,histogram:f}}function mr(e,t={}){ut(e);let r=t.period,n=t.stdDev;if(Pe(r),typeof n!="number"||!Number.isFinite(n)||n<=0)throw new TypeError("stdDev must be a finite number > 0");let o=new Array(e.length).fill(null),a=new Array(e.length).fill(null),i=new Array(e.length).fill(null);if(e.length<r)return{upper:a,middle:o,lower:i};let s=0,c=0;for(let f=0;f<e.length;f++){let u=e[f];if(s+=u,c+=u*u,f>=r){let l=e[f-r];s-=l,c-=l*l}if(f>=r-1){let l=s/r,h=c/r-l*l;h<0&&h>-1e-12&&(h=0);let p=Math.sqrt(h);o[f]=l,a[f]=l+n*p,i[f]=l-n*p}}return{upper:a,middle:o,lower:i}}function yr(e,t){zi(e),Pe(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 s=e[i];if(i===0)n[i]=s.h-s.l;else{let c=e[i-1].c;n[i]=Math.max(s.h-s.l,Math.abs(s.h-c),Math.abs(s.l-c))}}let o=0;for(let i=0;i<t;i++)o+=n[i];let a=o/t;r[t-1]=a;for(let i=t;i<e.length;i++)a=(a*(t-1)+n[i])/t,r[i]=a;return r}var wr=V(()=>{});import{createHash as Vi}from"node:crypto";var gr,Ji,Wi,Gi,qn,Bn=V(()=>{gr=3,Ji="7477966facc4ef928a94e6221c8fd238eef4fcbeec46b96ae1b89178e13c2d5f",Wi="68f5b412a9975f04024cf9b9b6209b4bccedd52f176e95f34f786b3f53479c6a",Gi="967fd45ecddd0d59ac0f662fe92ea813c32620ba751f249b4ace6cb6b809fb5e",qn=Vi("sha256").update(JSON.stringify({version:gr,compilerSourceHash:Ji,indicatorsSourceHash:Wi,schemaSourceHash:Gi})).digest("hex")});function ne(e){return typeof e=="number"&&Number.isFinite(e)}function Zi(e){let t=new Map(e.map(s=>[s.id,s])),r=s=>{switch(s.type){case"indicator":return s.input?[s.input]:[];case"compare":case"cross":return[s.left,s.right];case"logic":return[...s.inputs];default:return[]}},n=new Map,o=new Map;for(let s of e)n.set(s.id,0),o.set(s.id,[]);for(let s of e)for(let c of r(s))t.has(c)&&(o.get(c).push(s.id),n.set(s.id,n.get(s.id)+1));let a=[];for(let[s,c]of n)c===0&&a.push(s);let i=[];for(;a.length;){let s=a.shift();i.push(s);for(let c of o.get(s))n.set(c,n.get(c)-1),n.get(c)===0&&a.push(c)}if(i.length!==e.length)throw new Error("strategy graph is cyclic");return i}function Je(e,t){return e!=null&&typeof e=="object"&&"param"in e?t[e.param].value:e}function Xi(e,t,r){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");if(!Number.isInteger(t)||t<0||t>=e.length)throw new RangeError("index out of range");let n=null;for(let o=0;o<=t;o++){let a=e[o];if(a==null||typeof a!="object"||Array.isArray(a))throw new TypeError(`bars[${o}] must be an object`);let{t:i,o:s,h:c,l:f,c:u,v:l}=a;if(!ne(i)&&(typeof i=="number"&&Number.isFinite(i)),!Number.isFinite(i))throw new TypeError(`bars[${o}].t must be finite`);for(let[h,p]of[["o",s],["h",c],["l",f],["c",u],["v",l]])if(!ne(p))throw new TypeError(`bars[${o}].${h} must be a finite number`);for(let[h,p]of[["o",s],["h",c],["l",f],["c",u]])if(!(p>0))throw new TypeError(`bars[${o}].${h} price must be positive`);if(l<0)throw new TypeError(`bars[${o}].v volume must be non-negative`);if(c<Math.max(s,u,f))throw new TypeError(`bars[${o}] high must be >= max(open, close, low)`);if(f>Math.min(s,u,c))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!==Yi[r])throw new TypeError(`bars t must match ${r} cadence`)}if(n=i,"fundingRate"in a&&a.fundingRate!=null&&!ne(a.fundingRate))throw new TypeError(`bars[${o}].fundingRate must be finite when present`);if("openInterest"in a&&a.openInterest!=null){if(!ne(a.openInterest))throw new TypeError(`bars[${o}].openInterest must be finite when present`);if(a.openInterest<0)throw new TypeError(`bars[${o}].openInterest must be non-negative`)}for(let h of["premium","oiDelta"])if(h in a&&a[h]!=null&&!ne(a[h]))throw new TypeError(`bars[${o}].${h} must be finite when present`);if("bookImbalance"in a&&a.bookImbalance!=null){if(!ne(a.bookImbalance))throw new TypeError(`bars[${o}].bookImbalance must be finite when present`);if(a.bookImbalance<-1||a.bookImbalance>1)throw new TypeError(`bars[${o}].bookImbalance must be within [-1, 1]`)}}}function Le(e,t,r,n,o,a){if(a.has(e))return a.get(e);let i=t.get(e),s;switch(i.type){case"input":{let c=Ki[i.field];s=new Array(o+1);for(let f=0;f<=o;f++){let u=n[f][c];s[f]=u===void 0?null:u}break}case"constant":{let c=Je(i.value,r);s=new Array(o+1).fill(c);break}case"indicator":{let c=i.period!=null?Je(i.period,r):void 0;if(i.indicator==="atr"){let l=[];for(let h=0;h<=o;h++){let p=n[h];l.push({o:p.o,h:p.h,l:p.l,c:p.c})}s=yr(l,c);break}let u=Le(i.input,t,r,n,o,a).map((l,h)=>{if(l==null||!ne(l))throw new TypeError(`indicator input ${i.input} has non-finite value at ${h}`);return l});if(i.indicator==="sma")s=dr(u,c);else if(i.indicator==="ema")s=lt(u,c);else if(i.indicator==="rsi")s=pr(u,c);else if(i.indicator==="macd")s=hr(u,{fastPeriod:Je(i.fastPeriod,r),slowPeriod:Je(i.slowPeriod,r),signalPeriod:Je(i.signalPeriod,r)})[i.output];else if(i.indicator==="bollinger")s=mr(u,{period:c,stdDev:Je(i.stdDev,r)})[i.output];else throw new Error(`unsupported indicator ${i.indicator}`);break}case"compare":{let c=Le(i.left,t,r,n,o,a),f=Le(i.right,t,r,n,o,a);s=new Array(o+1);for(let u=0;u<=o;u++){let l=c[u],h=f[u];if(l==null||h==null||!ne(l)||!ne(h)){s[u]=!1;continue}switch(i.op){case"gt":s[u]=l>h;break;case"gte":s[u]=l>=h;break;case"lt":s[u]=l<h;break;case"lte":s[u]=l<=h;break;case"eq":s[u]=l===h;break;default:s[u]=!1}}break}case"logic":{let c=i.inputs.map(f=>Le(f,t,r,n,o,a));s=new Array(o+1);for(let f=0;f<=o;f++)if(i.op==="not"){let u=c[0][f];s[f]=u===!0?!1:u===!1}else if(i.op==="and"){let u=!0;for(let l of c)if(l[f]!==!0){u=!1;break}s[f]=u}else if(i.op==="or"){let u=!1;for(let l of c)if(l[f]===!0){u=!0;break}s[f]=u}else s[f]=!1;break}case"cross":{let c=Le(i.left,t,r,n,o,a),f=Le(i.right,t,r,n,o,a);s=new Array(o+1),s[0]=!1;for(let u=1;u<=o;u++){let l=c[u-1],h=f[u-1],p=c[u],d=f[u];if(l==null||h==null||p==null||d==null||!ne(l)||!ne(h)||!ne(p)||!ne(d)){s[u]=!1;continue}i.direction==="above"?s[u]=l<=h&&p>d:s[u]=l>=h&&p<d}break}default:throw new Error(`unknown node type ${i.type}`)}return a.set(e,s),s}function Y(e,t={}){let r=G(e);t&&Object.keys(t).length&&(r=Ge(r,t));let n=new Map(r.nodes.map(p=>[p.id,p])),o=Object.freeze(Zi(r.nodes)),a=r.parameters,i=new Set(r.nodes.filter(p=>p.type==="input").map(p=>p.field));if(r.nodes.some(p=>p.type==="indicator"&&p.indicator==="atr"))for(let p of["open","high","low","close"])i.add(p);let s=Object.freeze([...i].sort()),c=de(r);function f(p,d){let m={};for(let b of o){let w=p.get(b);m[b]=w[d]}let y=b=>b!=null&&m[b]===!0;return{values:m,signals:{entryLong:y(r.rules.entryLong),entryShort:y(r.rules.entryShort),exitLong:y(r.rules.exitLong),exitShort:y(r.rules.exitShort)}}}function u(p,d){Xi(p,d,r.market.interval);let m=new Map;for(let y of o)Le(y,n,a,p,d,m);return m}function l(p,d){return f(u(p,d),d)}function h(p){if(!Array.isArray(p)||p.length===0)throw new TypeError("bars must be a non-empty array");let d=p.length-1,m=u(p,d);return Object.freeze(p.map((y,b)=>Object.freeze(f(m,b))))}return Object.freeze({strategy:r,strategyHash:c,compilerVersion:We,compilerHash:ue,requiredSeries:s,nodeOrder:o,evaluate:l,evaluateAll:h})}var We,ue,Ki,Yi,fe=V(()=>{Te();wr();Bn();We=gr,ue=qn,Ki=Object.freeze({open:"o",high:"h",low:"l",close:"c",volume:"v",fundingRate:"fundingRate",openInterest:"openInterest",premium:"premium",oiDelta:"oiDelta",bookImbalance:"bookImbalance"}),Yi=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5})});import{createHash as Qi}from"node:crypto";function ts(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function pe(e){return typeof e=="number"&&Number.isFinite(e)}function br(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)br(t);return Object.freeze(e)}for(let t of Object.keys(e))br(e[t]);return Object.freeze(e)}function Pt(e){if(Array.isArray(e))return e.map(Pt);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Pt(e[r]);return t}return e}function Er(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)=>Er(r,`${t}[${n}]`));return}for(let[r,n]of Object.entries(e))Er(n,`${t}.${r}`)}}function Un(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");let t=null;for(let r=0;r<e.length;r++){let n=e[r];if(n==null||typeof n!="object"||Array.isArray(n))throw new TypeError(`bars[${r}] must be an object`);let{t:o,o:a,h:i,l:s,c,v:f}=n;if(!pe(o))throw new TypeError(`bars[${r}].t must be finite`);for(let[u,l]of[["o",a],["h",i],["l",s],["c",c],["v",f]])if(!pe(l))throw new TypeError(`bars[${r}].${u} must be a finite number`);for(let[u,l]of[["o",a],["h",i],["l",s],["c",c]])if(!(l>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(a,c,s))throw new TypeError(`bars[${r}] high must be >= max(open, close, low)`);if(s>Math.min(a,c,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&&!pe(n.fundingRate))throw new TypeError(`bars[${r}].fundingRate must be finite when present`);if("fundingPaymentRate"in n&&n.fundingPaymentRate!=null&&!pe(n.fundingPaymentRate))throw new TypeError(`bars[${r}].fundingPaymentRate must be finite when present`);if("openInterest"in n&&n.openInterest!=null&&!pe(n.openInterest))throw new TypeError(`bars[${r}].openInterest must be finite when present`)}}function He(e){if(!Array.isArray(e))throw new TypeError("bars must be an array");return e.length>0&&Un(e),Qi("sha256").update(JSON.stringify(Pt(e)),"utf8").digest("hex")}function rs(e){if(e==null&&(e={}),!ts(e))throw new TypeError("options must be a plain object");let t={...es},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(!pe(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(!pe(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(!pe(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 $t(e){return e/1e4}function ns(e,t,r){let n=$t(r);return t==="long"?e*(1+n):e*(1-n)}function os(e,t,r){let n=$t(r);return t==="long"?e*(1-n):e*(1+n)}function Dn(e,t,r){let n=Math.abs(e)*$t(t),o=Math.abs(e)*$t(r);return{taker:n,builder:o,total:n+o}}function is(e,t){let r=e*(t.positionSizePct/100)*t.maxLeverage;return Math.min(r,t.maxNotionalUsd)}function ss(e,t,r){let n=r/100;return t==="long"?e*(1-n):e*(1+n)}function as(e,t,r){let n=r/100;return t==="long"?e*(1+n):e*(1-n)}function cs(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 ls(e,t,r){return t==="long"?e.l<=r:e.h>=r}function us(e,t,r){return t==="long"?e.h>=r:e.l<=r}function fs(e,t,r){return t==="long"?e.l<=r:e.h>=r}function ft(e,t){for(let r of e.requiredSeries)if(ds.includes(r)&&!t.every(n=>pe(n?.[r])))throw new Error(`strategy required series is absent: ${r}`)}function ps(e){if(e.length<3)return 0;let t=[];for(let i=1;i<e.length;i++){let s=e[i-1].equity,c=e[i].equity;s>0&&t.push((c-s)/s)}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 a=Math.sqrt(o/(t.length-1));return a>0?n/a:0}function hs(e){let t=-1/0,r=0;for(let n of e){let o=n.equity;if(o>t&&(t=o),t>0){let a=(t-o)/t*100;a>r&&(r=a)}}return r}function ee(e,t,r={}){let n=rs(r);Un(t);let o=He(t);n.nowMs!==void 0&&G(e,{nowMs:n.nowMs});let a=Y(e);if(ft(a,t),n.nowMs!==void 0&&a.strategy.risk.expiresAt<=n.nowMs)throw new Error("strategy is expired: risk.expiresAt must be strictly greater than nowMs");let i=a.strategy.risk,s=a.evaluateAll(t),c=n.latencyBars,f=n.slippageBps,u=n.takerFeeBps,l=n.builderFeeBps,h=n.initialEquityUsd,p=0,d=0,m=0,y=0,b=0,w=[],A=[],E=[],v=[],O=[],g=null,M=0,q=null,z=h,P=!1,x=0,N=0,T=[],C=new Array(t.length).fill(0);function L(k){T.push(k)}function j(k){let H=t[k].v*(n.maxVolumeParticipationPct/100);return Math.max(0,H-C[k])}function $(k){if(!g)return h;let H=g.side==="long"?(k-g.entryPrice)*g.qty:(g.entryPrice-k)*g.qty;return h+H}function R(k,H,_){let D=_.o,F=is(h,i);if(!(F>0)||!(D>0))return;let U=ns(D,H,f),B=F/U,K=j(k),st=U*K;if(B>K){E.push({kind:"entry",barIndex:k,time:_.t,side:H,requestedNotionalUsd:F,maxFillNotionalUsd:st,reason:"volume_participation"});return}C[k]+=B;let le=Math.abs(U-D)*B,Ee=Dn(F,u,l);h-=Ee.total,p+=Ee.taker,d+=Ee.builder,y+=le,b+=F,g={lifecycleEpoch:++N,side:H,entryBarIndex:k,entryReferencePrice:D,entryPrice:U,qty:B,notionalUsd:F,stop:ss(U,H,i.stopLossPct),take:as(U,H,i.takeProfitPct),liq:cs(U,H,i.maxLeverage,u+l),entryFees:Ee.taker,entryBuilderFees:Ee.builder,entrySlippageUsd:le,fundingAccrued:0}}function I(k,H,_,D){if(!g)return!1;let F=g.side,U=H,B=U;_!=="liquidation"&&D&&(B=os(U,F,f));let K=g.qty,st=K*B;if(_!=="liquidation"){let gn=j(k),ii=B*gn;if(K>gn)return E.push({kind:"exit",barIndex:k,time:t[k].t,side:F,requestedNotionalUsd:st,maxFillNotionalUsd:ii,reason:"volume_participation",triggerReason:_}),!1;C[k]+=K}let le=Dn(st,u,l),Ee=_==="liquidation"?0:Math.abs(B-U)*K,at,rr;F==="long"?(at=(U-g.entryReferencePrice)*K,rr=(B-g.entryPrice)*K):(at=(g.entryReferencePrice-U)*K,rr=(g.entryPrice-B)*K),h+=rr,h-=le.total,p+=le.taker,d+=le.builder,y+=Ee,b+=st;let oi={side:F,entryBarIndex:g.entryBarIndex,entryTime:t[g.entryBarIndex].t,entryPrice:g.entryPrice,exitBarIndex:k,exitTime:t[k].t,exitPrice:B,exitReason:_,qty:K,notionalUsd:g.notionalUsd,grossPnlUsd:at,feesUsd:g.entryFees+le.taker,builderFeesUsd:g.entryBuilderFees+le.builder,fundingUsd:g.fundingAccrued,slippageUsd:g.entrySlippageUsd+Ee,netPnlUsd:at-(g.entryFees+le.taker+g.entryBuilderFees+le.builder)-g.fundingAccrued-(g.entrySlippageUsd+Ee)};return w.push(oi),_==="liquidation"&&A.push({barIndex:k,time:t[k].t,side:F,price:B,tradeIndex:w.length-1}),g=null,N+=1,x=k+1+(i.cooldownBars||0),!0}function re(k,H,_,D){let F=k+1;if(F>=t.length)return;T.some(B=>B.kind==="exit"&&B.side===H&&B.fillBar===F&&B.epoch===D)||L({kind:"exit",side:H,signalBar:k,fillBar:F,reason:_,epoch:D})}function te(k){let H=T.filter(_=>_.fillBar===k);for(let _=T.length-1;_>=0;_--)T[_].fillBar===k&&T.splice(_,1);H.sort((_,D)=>{let F=U=>U.kind==="exit"?0:1;return F(_)-F(D)});for(let _ of H)if(_.kind==="exit"){if(!g||g.side!==_.side||g.lifecycleEpoch!==_.epoch)continue;let D=_.reason||"rule";I(k,t[k].o,D,!0)||re(k,_.side,D,_.epoch)}else if(_.kind==="entry"){if(g||_.epoch!==N||k<x)continue;R(k,_.side,t[k])}}function se(k){if(!g)return;let H=t[k],_=H.fundingPaymentRate;if(_==null||!pe(_)||_===0)return;let D=Math.abs(g.qty*H.c),F=_*D;g.side==="long"?(h-=F,g.fundingAccrued+=F,m+=F):(h+=F,g.fundingAccrued-=F,m-=F)}function ge(k){if(!g)return;let H=t[k].o;(g.side==="long"?H<=g.liq:H>=g.liq)&&I(k,H,"liquidation",!1)}function xt(k){if(!g)return;let H=t[k],_=g.side,D=fs(H,_,g.liq),F=ls(H,_,g.stop),U=us(H,_,g.take),B=K=>_==="long"?Math.min(K,H.o):Math.max(K,H.o);if(D){I(k,B(g.liq),"liquidation",!1);return}if(F&&U){I(k,B(g.stop),"stop_loss",!0)||re(k,_,"stop_loss",g.lifecycleEpoch);return}if(F){I(k,B(g.stop),"stop_loss",!0)||re(k,_,"stop_loss",g.lifecycleEpoch);return}U&&(I(k,g.take,"take_profit",!0)||re(k,_,"take_profit",g.lifecycleEpoch))}for(let k=0;k<t.length;k++){let H=Math.floor(t[k].t/864e5);H!==q&&(q=H,z=$(t[k].o),P=!1),ge(k),te(k),xt(k),se(k),!P&&$(t[k].c)<=z*(1-i.maxDailyLossPct/100)&&(P=!0,v.push({type:"daily_loss_limit",barIndex:k,time:t[k].t,message:"daily loss limit reached; new entries blocked for UTC day"}));let _=s[k].signals,D=k+c;if(g)(g.side==="long"&&_.exitLong===!0||g.side==="short"&&_.exitShort===!0)&&D<t.length&&(T.some(K=>K.kind==="exit"&&K.side===g.side&&K.fillBar===D&&K.epoch===g.lifecycleEpoch)||L({kind:"exit",side:g.side,signalBar:k,fillBar:D,reason:"rule",epoch:g.lifecycleEpoch}));else{let U=_.entryLong===!0,B=_.entryShort===!0;U&&B?v.push({type:"conflicting_entry_signals",barIndex:k,time:t[k].t,message:"conflicting entry signals; no position opened"}):!P&&(U||B)&&D<t.length&&k>=x&&L({kind:"entry",side:U?"long":"short",signalBar:k,fillBar:D,epoch:N})}let F=h;g&&(M+=1,F=$(t[k].c)),O.push({barIndex:k,time:t[k].t,equity:F,positionSide:g?g.side:null})}let St=null;if(g){let k=t.length-1;if(I(k,t[k].c,"end_of_data",!0))O[k]={barIndex:k,time:t[k].t,equity:h,positionSide:null};else{let _=$(t[k].c);St={side:g.side,entryBarIndex:g.entryBarIndex,entryTime:t[g.entryBarIndex].t,entryPrice:g.entryPrice,qty:g.qty,notionalUsd:g.notionalUsd,markPrice:t[k].c,markedEquityUsd:_},v.push({type:"open_position_at_end",barIndex:k,time:t[k].t,message:"end-of-data exit missed; position remains open and marked"})}}let ot=(g?$(t[t.length-1].c):h)-n.initialEquityUsd,er=ot/n.initialEquityUsd*100,it=0,Re=0,be=0;for(let k of w)k.netPnlUsd>0?(it+=1,Re+=k.netPnlUsd):k.netPnlUsd<0&&(be+=-k.netPnlUsd);let ze=w.length,Ne=ze===0?0:it/ze,tr=0;be>0?tr=Re/be:Re>0&&(tr=1e12);let ri={netPnlUsd:ot,netPnlPct:er,maxDrawdownPct:hs(O),winRate:Ne,profitFactor:tr,tradeCount:ze,sharpe:ps(O),turnoverUsd:b,exposurePct:M/t.length*100},ni={initialEquityUsd:n.initialEquityUsd,takerFeeBps:n.takerFeeBps,builderFeeBps:n.builderFeeBps,slippageBps:n.slippageBps,latencyBars:n.latencyBars,maxVolumeParticipationPct:n.maxVolumeParticipationPct},wn={barsHash:o,strategyHash:a.strategyHash,compilerHash:ue,compilerVersion:We,config:ni,trades:w,equityCurve:O,metrics:ri,costs:{feesUsd:p,builderFeesUsd:d,fundingUsd:m,slippageUsd:y},liquidations:A,missedFills:E,openPositionAtEnd:St,flags:v};return Er(wn),br(Pt(wn))}var es,ds,Ce=V(()=>{fe();Te();es=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:100});ds=Object.freeze(["fundingRate","openInterest","premium","oiDelta","bookImbalance"])});import{createHash as ms}from"node:crypto";function he(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Ke(e){return typeof e=="number"&&Number.isFinite(e)}function kr(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)kr(t);return Object.freeze(e)}for(let t of Object.keys(e))kr(e[t]);return Object.freeze(e)}function Fe(e){if(Array.isArray(e))return e.map(Fe);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Fe(e[r]);return t}return e}function xr(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 zn(e){return{feesUsd:e.costs.feesUsd,builderFeesUsd:e.costs.builderFeesUsd,fundingUsd:e.costs.fundingUsd,slippageUsd:e.costs.slippageUsd}}function ys(e){return(e.feesUsd||0)+(e.builderFeesUsd||0)+Math.max(0,e.fundingUsd||0)+(e.slippageUsd||0)}function ws(e){let t=0;for(let r of e.trades)r.grossPnlUsd>0&&(t+=r.grossPnlUsd);return t}function gs(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 Wn(e){if(!he(e))throw new TypeError("evidence artifact must be a plain object");if(!Jn.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(!he(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(!he(e.walkForward)||!Array.isArray(e.walkForward.windows))throw new TypeError("evidence artifact walkForward windows required");if(e.status==="pass_live_eligible"&&(!he(e.train)||!he(e.holdout)))throw new TypeError("live-eligible evidence artifact requires train and holdout facts");return Fe({barsHash:e.barsHash,compilerHash:e.compilerHash,flags:e.flags.map(t=>Fe(t)),holdout:e.holdout??null,split:e.split,status:e.status,strategyHash:e.strategyHash,train:e.train??null,walkForward:{passRate:e.walkForward.passRate,windowsRun:e.walkForward.windowsRun??e.walkForward.windows.length,windows:e.walkForward.windows.map(t=>({index:t.index,trainStartIndex:t.trainStartIndex,trainEndIndex:t.trainEndIndex,passed:t.passed,reason:t.reason,evalStartIndex:t.evalStartIndex,evalEndIndex:t.evalEndIndex,metrics:t.metrics}))}})}function Tr(e){return ms("sha256").update(JSON.stringify(Wn(e)),"utf8").digest("hex")}function ae(e,t,r=0){if(!Number.isInteger(e)||e<r)throw new Error(`${t} must be an integer >= ${r}`);return e}function Sr(e,t){if(!he(e)||!he(e.metrics))throw new Error(`${t} metrics required`);let r=ae(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(!Ke(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 bs(e,{maxDailyLossPct:t}={}){let r=e.split,n=ae(r.trainStartIndex,"split.trainStartIndex"),o=ae(r.trainEndIndex,"split.trainEndIndex"),a=ae(r.trainBarCount,"split.trainBarCount",1),i=ae(r.holdoutStartIndex,"split.holdoutStartIndex"),s=ae(r.holdoutEndIndex,"split.holdoutEndIndex"),c=ae(r.holdoutBarCount,"split.holdoutBarCount",1);if(n!==0||o-n+1!==a||i!==o+1||s-i+1!==c)throw new Error("evidence split must be contiguous, chronological, and count-consistent");if(!Ke(r.trainFraction)||r.trainFraction<=0||r.trainFraction>=1)throw new Error("split.trainFraction must be in (0,1)");Sr(e.train,"train");let f=Sr(e.holdout,"holdout");if(f.tradeCount<1||f.netPnlUsd<=0||f.profitFactor<=1)throw new Error("live-eligible holdout metrics do not pass");if(Ke(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,l=u.windows;if(l.length<1||u.windowsRun!==l.length)throw new Error("live-eligible walk-forward windowsRun must match nonempty windows");let h=0,p=-1;for(let m=0;m<l.length;m++){let y=l[m];if(!he(y)||y.index!==m||typeof y.passed!="boolean")throw new Error("walk-forward windows must be ordered and structurally valid");let b=ae(y.trainStartIndex,`walkForward.windows[${m}].trainStartIndex`),w=ae(y.trainEndIndex,`walkForward.windows[${m}].trainEndIndex`),A=ae(y.evalStartIndex,`walkForward.windows[${m}].evalStartIndex`),E=ae(y.evalEndIndex,`walkForward.windows[${m}].evalEndIndex`);if(b!==0||w>=A||A>E||A<=p)throw new Error("walk-forward windows must be chronological and disjoint");if(p=E,y.passed){if(h+=1,y.reason!=="pass")throw new Error("passed walk-forward window reason must be pass");let v=Sr({metrics:y.metrics,tradeCount:y.metrics?.tradeCount},`walkForward.windows[${m}]`);if(v.tradeCount<1||v.netPnlUsd<=0||v.profitFactor<=1)throw new Error("passed walk-forward window metrics do not pass");if(Ke(t)&&v.maxDrawdownPct>t)throw new Error("passed walk-forward drawdown exceeds strategy risk")}else if(y.reason==="pass")throw new Error("failed walk-forward window cannot have pass reason")}let d=h/l.length;if(!Ke(u.passRate)||Math.abs(u.passRate-d)>Number.EPSILON||d<.6)throw new Error("walk-forward passRate contradicts concrete windows or is below live threshold")}function Ar(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=Wn(e),n=Fe({id:e.id,...r});if(JSON.stringify(Fe(e))!==JSON.stringify(n))throw new Error("evidence artifact contains fields unbound from its deterministic identity");let o=Tr(e);if(e.id!==o)throw new Error("evidence.id does not match its deterministic artifact facts digest");return e.status==="pass_live_eligible"&&bs(e,t),e}function _t({strategy:e,bars:t,backtestOptions:r={},trainFraction:n=.7,walkForwardWindows:o=3,minTrades:a=10}={}){let i=[];if(!he(e))throw new TypeError("strategy must be a plain object");if(!Array.isArray(t))throw new TypeError("bars must be an array");if(!he(r))throw new TypeError("backtestOptions must be a plain object");if(!Ke(n)||n<=0||n>=1)throw new TypeError("trainFraction must be in (0,1)");if(!Number.isInteger(o)||o<1)throw new TypeError("walkForwardWindows must be a positive integer");if(!Number.isInteger(a)||a<0)throw new TypeError("minTrades must be an integer >= 0");let s=G(e),c=de(s),f=He(t),u=t.length,l=(j=[],$={})=>Vn({status:"fail",strategy:s,sHash:c,barsHash:f,split:$.split||{trainStartIndex:0,trainEndIndex:-1,trainBarCount:0,holdoutStartIndex:0,holdoutEndIndex:-1,holdoutBarCount:0,trainFraction:n},train:$.train||null,holdout:$.holdout||null,walkForward:$.walkForward||{windows:[],passRate:0},flags:[...i,...j]});if(u<10)return l([{type:"insufficient_bars",message:"need at least 10 bars for evidence"}]);let h=Math.floor(u*n),p=h,d=u-p;if(h<5||d<3)return l([{type:"invalid_windowing",message:"train/holdout split too small",trainCount:h,holdoutCount:d}]);let m=t.slice(0,h),y=t.slice(p),b,w;try{b=ee(s,m,r),w=ee(s,y,r)}catch(j){return l([{type:"backtest_error",message:String(j.message||j)}])}let A={metrics:xr(b),costs:zn(b),tradeCount:b.metrics.tradeCount},E={metrics:xr(w),costs:zn(w),tradeCount:w.metrics.tradeCount},v={trainStartIndex:0,trainEndIndex:h-1,trainBarCount:h,holdoutStartIndex:p,holdoutEndIndex:u-1,holdoutBarCount:d,trainFraction:n},O=[],g=Math.floor(u/(o+1));if(g<3)i.push({type:"invalid_windowing",message:"walk-forward window size too small",wfSize:g});else for(let j=0;j<o;j++){let $=g*(j+1),R=$,I=Math.min(u,R+g);if(I-R<3||$<3){O.push({index:j,trainStartIndex:0,trainEndIndex:$-1,evalStartIndex:R,evalEndIndex:I-1,passed:!1,reason:"window_too_small",metrics:null});continue}let re=t.slice(R,I),te;try{te=ee(s,re,r)}catch{O.push({index:j,trainStartIndex:0,trainEndIndex:$-1,evalStartIndex:R,evalEndIndex:I-1,passed:!1,reason:"backtest_error",metrics:null});continue}let se=xr(te),ge=gs(se,s.risk,a);O.push({index:j,trainStartIndex:0,trainEndIndex:$-1,evalStartIndex:R,evalEndIndex:I-1,passed:ge,reason:ge?"pass":"fail_metrics",metrics:se})}let M=O.filter(j=>j.passed).length,q=O.length===0?0:M/O.length,z={windows:O,passRate:q,windowsRun:O.length};E.metrics.tradeCount===0&&A.metrics.tradeCount===0&&i.push({type:"no_trades",message:"no trades in train or holdout"}),E.metrics.tradeCount===0&&i.push({type:"absent_oos_trades",message:"holdout produced no trades"}),E.metrics.netPnlUsd<0&&i.push({type:"holdout_loss",message:"holdout netPnlUsd is negative"}),A.metrics.netPnlUsd>0&&E.metrics.netPnlUsd<0&&A.metrics.netPnlUsd>Math.abs(E.metrics.netPnlUsd)*.25?i.push({type:"overfit",message:"profitable train with losing holdout (OOS collapse)"}):A.metrics.netPnlUsd>0&&E.metrics.netPnlUsd>0&&E.metrics.netPnlUsd<A.metrics.netPnlUsd*.1&&A.metrics.tradeCount>=a&&i.push({type:"severe_oos_collapse",message:"holdout pnl collapsed vs train"});let P=ys(E.costs),x=ws(w);x>0&&P>x&&i.push({type:"costs_exceed_gross",message:"holdout costs exceed gross gains"});let N=i.some(j=>["insufficient_bars","invalid_windowing","absent_oos_trades","holdout_loss","no_trades","severe_oos_collapse","backtest_error"].includes(j.type)),T=i.some(j=>j.type==="overfit"),C="fail";return E.metrics.tradeCount>=a&&E.metrics.netPnlUsd>0&&E.metrics.profitFactor>1&&E.metrics.maxDrawdownPct<=s.risk.maxDailyLossPct&&q>=.6&&!(x>0&&P>x)&&!T&&!i.some(j=>j.type==="severe_oos_collapse"||j.type==="invalid_windowing")?C="pass_live_eligible":!N&&E.metrics.tradeCount>0&&A.metrics.tradeCount>0&&Number.isFinite(E.metrics.netPnlUsd)?(C="pass_paper_only",E.metrics.tradeCount<a&&i.push({type:"undersampled",message:"holdout trades below minTrades"})):T&&E.metrics.tradeCount>0&&A.metrics.netPnlUsd>0?C="fail":E.metrics.tradeCount>0&&A.metrics.tradeCount>0&&!N?C="pass_paper_only":C="fail",E.metrics.netPnlUsd<0&&(C=C==="pass_live_eligible"?"fail":C==="pass_paper_only"?"pass_paper_only":"fail",C="fail"),Vn({status:C,strategy:s,sHash:c,barsHash:f,split:v,train:A,holdout:E,walkForward:z,flags:i})}function Vn({status:e,strategy:t,sHash:r,barsHash:n,split:o,train:a,holdout:i,walkForward:s,flags:c}){let f={status:e,strategyHash:r,compilerHash:ue,barsHash:n,split:o,train:a,holdout:i,walkForward:s,flags:c};return f.id=Tr(f),kr(Fe(JSON.parse(JSON.stringify(f))))}var Jn,It=V(()=>{fe();Te();Ce();Jn=Object.freeze(["fail","pass_paper_only","pass_live_eligible"])});import{createHash as Es,createHmac as xs,timingSafeEqual as dl}from"node:crypto";function Or(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(Or).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${Or(e[r])}`).join(",")}}`}function Gn(e){let t=String(e?.ORACLE_STAMP_HMAC_SECRET||"").trim();return t.length>=16?t:""}function Kn(e=process.env){return Gn(process.env)||Gn(e)}function As(e){let{prepareHash:t,prepareMac:r,note:n,...o}=e||{};return o}function Os(e){let t=As(e);return Es("sha256").update(Or(t)).digest("hex")}function vs(e,t=Kn()){return t?xs("sha256",t).update(String(e)).digest("hex"):""}function Yn(e,{provider:t,kind:r,env:n=process.env,nowMs:o=Date.now(),expiresAtMs:a}={}){if(!e||typeof e!="object")throw new Error("stampPrepared: payload object required");let i=Object.prototype.hasOwnProperty.call(e,"oraclePrepared");if(i&&typeof e.oraclePrepared!="boolean")throw new Error("stampPrepared: oraclePrepared must be boolean");let s={...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(!s.provider)throw new Error("stampPrepared: provider required");if(!s.kind)throw new Error("stampPrepared: kind required");let c=Number(o),f=a==null?c+ks:Number(a),u=f-c;if(!Number.isSafeInteger(c)||!Number.isSafeInteger(f)||u<=0||u>Ts)throw new Error("stampPrepared: bounded preparedAt/expiresAt required");let h={...s,preparedAt:c,expiresAt:f,prepareVersion:Ss},p=Os(h),d=Kn(n),m=d?vs(p,d):void 0,y={...h,prepareHash:p};return m&&(y.prepareMac=m),y}var Ss,ks,Ts,Zn=V(()=>{Ss=2,ks=300*1e3,Ts=(()=>{let e=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(e)&&e>0?e:1800*1e3})()});function dt(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function $s(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Pr(e,t="value"){if(Array.isArray(e)){e.forEach((r,n)=>Pr(r,`${t}[${n}]`));return}if(dt(e))for(let[r,n]of Object.entries(e)){let o=$s(r);if(Ps.some(a=>o.includes(a)))throw new Error(`handoff: forbidden secret-like field at ${t}.${r}`);Pr(n,`${t}.${r}`)}}function vr(e){return typeof e=="number"&&Number.isFinite(e)&&e>0}function $r({strategy:e,evidence:t,shadow:r,caps:n,nowMs:o=Date.now(),env:a=process.env}={}){if(Pr({strategy:e,evidence:t,shadow:r,caps:n},"handoff"),!dt(e))throw new Error("handoff: strategy required");if(!dt(t))throw new Error("handoff: evidence required");if(!dt(r))throw new Error("handoff: shadow required");if(!dt(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=G(e,{nowMs:o}),s=Y(i);if(Ar(t,{maxDailyLossPct:i.risk.maxDailyLossPct}),t.status!=="pass_live_eligible")throw new Error("handoff: evidence.status must be pass_live_eligible");if(t.strategyHash!==s.strategyHash)throw new Error("handoff: evidence.strategyHash mismatch");if(t.compilerHash!==s.compilerHash)throw new Error("handoff: evidence.compilerHash mismatch");let c=["perStrategyNotionalUsd","maxLeverage","dailyLossCapUsd","chainAllowlist","assetAllowlist","expiresAt","killSwitchRequired"];for(let h of c)if(!(h in n)||n[h]==null)throw new Error(`handoff: caps.${h} required`);if(!vr(n.perStrategyNotionalUsd))throw new Error("handoff: caps.perStrategyNotionalUsd must be positive");if(n.perStrategyNotionalUsd>s.strategy.risk.maxNotionalUsd)throw new Error("handoff: caps.perStrategyNotionalUsd exceeds strategy.risk.maxNotionalUsd");if(!vr(n.maxLeverage))throw new Error("handoff: caps.maxLeverage must be positive");if(n.maxLeverage>s.strategy.risk.maxLeverage)throw new Error("handoff: caps.maxLeverage exceeds strategy.risk.maxLeverage");if(!vr(n.dailyLossCapUsd))throw new Error("handoff: caps.dailyLossCapUsd must be positive");let f=s.strategy.risk.maxNotionalUsd*(s.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(h=>h==="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]!==s.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>s.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},l={strategyHash:s.strategyHash,compilerHash:s.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:s.strategyHash,compilerHash:s.compilerHash,compilerVersion:We,venue:"hyperliquid",market:{coin:s.strategy.market.coin,kind:"perp",interval:s.strategy.market.interval},risk:{...s.strategy.risk},strategy:JSON.parse(JSON.stringify(s.strategy))},arming:{liveBroadcast:!1,requiresExplicitUserArm:!0,caps:u},requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,executionReady:!1};return Yn(l,{provider:"hl-strategy",kind:"strategy-live-handoff",env:a})}var Ps,_r=V(()=>{fe();It();Te();Zn();Ps=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"]});function Ye(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function Ze(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be a non-negative safe integer`);return e}function pt(e){if(Array.isArray(e))for(let t of e)pt(t);else if(e&&typeof e=="object")for(let t of Object.values(e))pt(t);return Object.freeze(e)}function $e(e){if(typeof e!="string")throw new TypeError("unsupported strategy interval");let t=_s[e];if(typeof t!="number")throw new TypeError("unsupported strategy interval");return t}function Xn(e,{endTime:t=Number.MAX_SAFE_INTEGER}={}){if(!Array.isArray(e))throw new TypeError("Hyperliquid candles must be an array");Ze(t,"endTime");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`candles[${n}] must be an object`);let a=Ze(Number(o.t),`candles[${n}].t`);if(Ze(Number(o.T),`candles[${n}].T`)>t)continue;let s={t:a,o:Ye(o.o,`candles[${n}].o`),h:Ye(o.h,`candles[${n}].h`),l:Ye(o.l,`candles[${n}].l`),c:Ye(o.c,`candles[${n}].c`),v:Ye(o.v,`candles[${n}].v`)};if(s.h<Math.max(s.o,s.c,s.l))throw new TypeError(`candles[${n}].h is below another price`);if(s.l>Math.min(s.o,s.c,s.h))throw new TypeError(`candles[${n}].l is above another price`);if(s.v<0)throw new TypeError(`candles[${n}].v must be non-negative`);let c=r.get(a);if(c&&JSON.stringify(c)!==JSON.stringify(s))throw new TypeError(`conflicting duplicate candle at timestamp ${a}`);c||r.set(a,s)}return pt([...r.values()].sort((n,o)=>n.t-o.t))}function Is(e,t){if(!Array.isArray(e))throw new TypeError("Hyperliquid funding history must be an array");let r=new Map;for(let n=0;n<e.length;n++){let o=e[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`funding[${n}] must be an object`);let a=Ze(Number(o.time),`funding[${n}].time`);a>t||r.set(a,{time:a,fundingRate:Ye(o.fundingRate,`funding[${n}].fundingRate`)})}return[...r.values()].sort((n,o)=>n.time-o.time)}async function Rs({coin:e,startTime:t,endTime:r},n){let o=[],a=Math.max(0,t-288e5),i=!1;for(let s=0;s<16&&a<=r;s++){let c=await Cn({coin:e,startTime:a,endTime:r},n);if(!Array.isArray(c))throw new TypeError("Hyperliquid funding history must be an array");o.push(...c);let f=a;for(let u of c){let l=Number(u?.time);Number.isSafeInteger(l)&&l>f&&(f=l)}if(c.length<500||f>=r){i=!0;break}if(f<=a)throw new Error("Hyperliquid funding history pagination did not advance");a=f+1}if(!i)throw new Error("strategy history exceeds the bounded funding history limit");return Is(o,r)}function Ns(e,t,r){let n=0,o=null;return e.map(a=>{let i=a.t+r,s=0;for(;n<t.length&&t[n].time<i;){let c=t[n];o=c.fundingRate,c.time>=a.t&&(s+=c.fundingRate),n+=1}return o==null?{...a,fundingPaymentRate:s}:{...a,fundingRate:o,fundingPaymentRate:s}})}async function ht(e,t={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("strategy history input must be an object");let r=e.coin;if(typeof r!="string"||r.length>32||!/^(?:[A-Za-z0-9][A-Za-z0-9._-]{0,31}|[a-z][a-z0-9]{0,15}:[A-Za-z0-9][A-Za-z0-9._-]{0,15})$/.test(r))throw new TypeError("coin must be a Hyperliquid market identifier");let n=String(e.interval||"15m"),o=$e(n);if(e.endTime==null)throw new TypeError("endTime is required for deterministic history");let a=Ze(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 s=e.startTime==null?Math.max(0,a-i*o):Ze(e.startTime,"startTime");if(s>=a)throw new TypeError("startTime must be before endTime");let[c,f]=await Promise.all([Hn({coin:r,interval:n,startTime:s,endTime:a},t),Rs({coin:r,startTime:s,endTime:a},t)]),u=Xn(c,{endTime:a}),l=pt(Ns(u,f,o));return pt({coin:r,interval:n,range:{startTime:s,endTime:a},bars:l})}var _s,Xe=V(()=>{Ve();_s=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 Ls(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))Ms.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"||!js.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 Hs(e={}){let t=await Mn(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 js,Ms,Qn,eo=V(()=>{Ve();_r();Xe();js=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),Ms=new Set(["coin","interval"]);Qn=Object.freeze({id:"hyperliquid",validateMarket:Ls,fetchBars:ht,listMarkets:Hs,prepareIntent(e){return $r(e)}})});function Fs(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 Cs.slice(1))if(typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} requires ${t}()`);for(let t of["fetchBars","listMarkets"])if(e[t]!=null&&typeof e[t]!="function")throw new TypeError(`strategy venue adapter ${e.id} ${t} must be a function`);return e}function Rt(e){return typeof e!="string"?null:qs.get(e)??null}function Nt(e){let t=Rt(e);if(!t)throw new Error(`unknown strategy venue: ${String(e)}`);return t}var Cs,to,qs,Bs,jt=V(()=>{eo();Cs=Object.freeze(["id","validateMarket","prepareIntent"]);to=[Qn].map(Fs),qs=new Map(to.map(e=>[e.id,e])),Bs=Object.freeze([...to])});import{createHash as Ds}from"node:crypto";function ie(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function J(e){return typeof e=="number"&&Number.isFinite(e)}function lo(e){return Number.isInteger(e)&&e>0}function jr(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)jr(t);return Object.freeze(e)}for(let t of Object.keys(e))jr(e[t]);return Object.freeze(e)}function Mr(e){if(Array.isArray(e))return e.map(Mr);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=Mr(e[r]);return t}return e}function S(e,t,r){e.push({path:t,message:r})}function _e(e,t,r,n){for(let o of Object.keys(e))t.has(o)||S(n,r?`${r}.${o}`:o,"unknown field is not allowed")}function ho(e,t,r,n){if(!J(e)||!J(t)||!J(r)||!J(n)||n<=0||e<t||e>r)return!1;let o=(e-t)/n;if(!Number.isFinite(o))return!1;let a=Math.round(o);return Math.abs(o-a)<=1e-9}function Nr(e,t,r,n){if(ie(e)){if(_e(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param)return S(n,`${t}.param`,"must be a parameter name string"),null;if(!Object.prototype.hasOwnProperty.call(r,e.param))return S(n,`${t}.param`,`unknown parameter "${e.param}"`),null;let o=r[e.param];return!ie(o)||![o.value,o.min,o.max,o.step].every(lo)?(S(n,`${t}.param`,"referenced period parameter value min max and step must be positive integers"),null):{param:e.param}}return lo(e)?e:(S(n,t,"must be a positive integer or {param}"),null)}function uo(e,t,r,n){return ie(e)?(_e(e,new Set(["param"]),t,n),typeof e.param!="string"||!e.param?(S(n,`${t}.param`,"must be a parameter name string"),null):Object.prototype.hasOwnProperty.call(r,e.param)?{param:e.param}:(S(n,`${t}.param`,`unknown parameter "${e.param}"`),null)):J(e)?e:(S(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 Zs(e){let t=new Map,r=n=>{let o=t.get(n)||0;if(o===1)return!0;if(o===2)return!1;t.set(n,1);let a=e.get(n);if(a){for(let i of Lt(a))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 Xs(e,t){if(!ie(e))return S(t,"parameters","must be a plain object"),null;let r=Object.keys(e);if(r.length>so)return S(t,"parameters",`too many parameters (max ${so})`),null;let n={};for(let o of r){if(!fo.test(o)){S(t,`parameters.${o}`,"parameter name is malformed");continue}let a=e[o],i=`parameters.${o}`;if(!ie(a)){S(t,i,"must be a plain object");continue}_e(a,no,i,t);for(let l of no)l in a||S(t,`${i}.${l}`,"required field is missing");let{value:s,min:c,max:f,step:u}=a;J(c)||S(t,`${i}.min`,"must be a finite number"),J(f)||S(t,`${i}.max`,"must be a finite number"),(!J(u)||u<=0)&&S(t,`${i}.step`,"must be a positive finite number"),J(s)||S(t,`${i}.value`,"must be a finite number"),J(c)&&J(f)&&c>f&&S(t,`${i}.min`,"min must be <= max"),J(s)&&J(c)&&J(f)&&J(u)&&u>0&&(ho(s,c,f,u)||S(t,`${i}.value`,"value must lie on the declared min/max/step grid")),n[o]={value:s,min:c,max:f,step:u}}return n}function Qs(e,t,r,n){let o=`nodes.${t}`;if(!ie(e))return S(n,o,"must be a plain object"),null;if(typeof e.type!="string"||!io[e.type])return S(n,`${o}.type`,"unknown or missing node type"),_e(e,Ys,o,n),null;switch(_e(e,io[e.type],o,n),(typeof e.id!="string"||!po.test(e.id))&&S(n,`${o}.id`,"must be a 1-64 char id starting with alphanumeric"),e.type){case"input":return(typeof e.field!="string"||!Us.has(e.field))&&S(n,`${o}.field`,"must be one of open|high|low|close|volume|fundingRate|openInterest|premium|oiDelta|bookImbalance"),{id:e.id,type:"input",field:e.field};case"constant":{let a=uo(e.value,`${o}.value`,r,n);return{id:e.id,type:"constant",value:a}}case"indicator":{(typeof e.indicator!="string"||!zs.has(e.indicator))&&S(n,`${o}.indicator`,"must be one of sma|ema|rsi|macd|bollinger|atr");let a=e.indicator,i={id:e.id,type:"indicator",indicator:a};if(a==="atr"){"input"in e&&(typeof e.input!="string"||!e.input?S(n,`${o}.input`,"must be a node id string when provided"):i.input=e.input);let s=Nr(e.period,`${o}.period`,r,n);s!=null&&(i.period=s)}else typeof e.input!="string"||!e.input?S(n,`${o}.input`,"must be a node id string"):i.input=e.input;if((a==="sma"||a==="ema"||a==="rsi"||a==="bollinger"||a==="atr")&&("period"in e,a!=="macd"))if(!("period"in e))S(n,`${o}.period`,"required field is missing");else{let s=Nr(e.period,`${o}.period`,r,n);s!=null&&(i.period=s)}if(a==="macd"){for(let s of["fastPeriod","slowPeriod","signalPeriod"])if(!(s in e))S(n,`${o}.${s}`,"required field is missing");else{let c=Nr(e[s],`${o}.${s}`,r,n);c!=null&&(i[s]=c)}"output"in e?Gs.has(e.output)?i.output=e.output:S(n,`${o}.output`,"must be line|signal|histogram"):S(n,`${o}.output`,"required field is missing"),"period"in e&&S(n,`${o}.period`,"forbidden for macd"),"stdDev"in e&&S(n,`${o}.stdDev`,"forbidden for macd")}else if(a==="bollinger"){if(!("stdDev"in e))S(n,`${o}.stdDev`,"required field is missing");else{let s=uo(e.stdDev,`${o}.stdDev`,r,n);s!=null&&(typeof s=="number"&&s<=0?S(n,`${o}.stdDev`,"must be > 0"):i.stdDev=s)}"output"in e?Ks.has(e.output)?i.output=e.output:S(n,`${o}.output`,"must be upper|middle|lower"):S(n,`${o}.output`,"required field is missing");for(let s of["fastPeriod","slowPeriod","signalPeriod"])s in e&&S(n,`${o}.${s}`,`forbidden for ${a}`)}else{"output"in e&&S(n,`${o}.output`,`forbidden for ${a}`),"stdDev"in e&&a!=="bollinger"&&S(n,`${o}.stdDev`,`forbidden for ${a}`);for(let s of["fastPeriod","slowPeriod","signalPeriod"])s in e&&S(n,`${o}.${s}`,`forbidden for ${a}`)}return i}case"compare":return(typeof e.op!="string"||!Vs.has(e.op))&&S(n,`${o}.op`,"must be gt|gte|lt|lte|eq"),(typeof e.left!="string"||!e.left)&&S(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&S(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"||!Js.has(e.op))&&S(n,`${o}.op`,"must be and|or|not"),!Array.isArray(e.inputs))return S(n,`${o}.inputs`,"must be an array of node ids"),{id:e.id,type:"logic",op:e.op,inputs:[]};let a=[];for(let i=0;i<e.inputs.length;i++){let s=e.inputs[i];typeof s!="string"||!s?S(n,`${o}.inputs.${i}`,"must be a node id"):a.push(s)}return e.op==="not"?a.length!==1&&S(n,`${o}.inputs`,"not requires exactly one input"):(e.op==="and"||e.op==="or")&&a.length<2&&S(n,`${o}.inputs`,`${e.op} requires at least two inputs`),{id:e.id,type:"logic",op:e.op,inputs:a}}case"cross":return(typeof e.direction!="string"||!Ws.has(e.direction))&&S(n,`${o}.direction`,"must be above|below"),(typeof e.left!="string"||!e.left)&&S(n,`${o}.left`,"must be a node id"),(typeof e.right!="string"||!e.right)&&S(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 ea(e,t,r){if(!ie(e))return S(t,"risk","must be a plain object"),null;_e(e,oo,"risk",t);for(let h of oo)(!(h in e)||e[h]==null)&&S(t,`risk.${h}`,"required field is missing");let n={},o=e.maxLeverage;!J(o)||o<=0||o>50?S(t,"risk.maxLeverage","must be a number > 0 and <= 50"):n.maxLeverage=o;let a=e.maxNotionalUsd;!J(a)||a<=0?S(t,"risk.maxNotionalUsd","must be a number > 0"):n.maxNotionalUsd=a;let i=e.positionSizePct;!J(i)||i<=0||i>100?S(t,"risk.positionSizePct","must be a number > 0 and <= 100"):n.positionSizePct=i;let s=e.stopLossPct;!J(s)||s<=0||s>100?S(t,"risk.stopLossPct","must be a number > 0 and <= 100"):n.stopLossPct=s;let c=e.takeProfitPct;!J(c)||c<=0||c>1e3?S(t,"risk.takeProfitPct","must be a number > 0 and <= 1000"):n.takeProfitPct=c;let f=e.cooldownBars;!Number.isInteger(f)||f<0||f>1e5?S(t,"risk.cooldownBars","must be an integer >= 0 and <= 100000"):n.cooldownBars=f;let u=e.maxDailyLossPct;!J(u)||u<=0||u>100?S(t,"risk.maxDailyLossPct","must be a number > 0 and <= 100"):n.maxDailyLossPct=u;let l=e.expiresAt;return!Number.isInteger(l)||l<=0?S(t,"risk.expiresAt","must be an integer epoch milliseconds > 0"):(r.nowMs!==void 0&&(Number.isInteger(r.nowMs)?l<=r.nowMs&&S(t,"risk.expiresAt","must be strictly greater than nowMs"):S(t,"nowMs","must be an integer epoch milliseconds")),n.expiresAt=l),n}function Ht(e,t={}){let r=[];if(!ie(e))return S(r,"","strategy must be a plain object"),{ok:!1,errors:r,strategy:null};_e(e,ro,"",r);for(let l of ro)(!(l in e)||e[l]==null)&&S(r,l,"required field is missing");e.version!==Mt&&S(r,"version",`must be ${Mt}`),(typeof e.id!="string"||!fo.test(e.id))&&S(r,"id","must match /^[a-z0-9][a-z0-9._-]{0,63}$/"),(typeof e.name!="string"||e.name.length===0||e.name.length>co)&&S(r,"name",`must be a non-empty string max ${co}`);let n=Rt(e.venue);n||S(r,"venue",`unknown strategy venue "${String(e.venue)}"`);let o=null;if(!n)ie(e.market)||S(r,"market","must be a plain object");else{let l=n.validateMarket(e.market);if(!l||typeof l.ok!="boolean"||!Array.isArray(l.errors))S(r,"market",`venue ${n.id} returned an invalid market validation result`);else if(l.ok)o=l.market;else for(let h of l.errors)S(r,h.path,h.message)}let a=Xs(e.parameters,r),i=null,s=new Map;if(!Array.isArray(e.nodes))S(r,"nodes","must be an array");else if(e.nodes.length>ao)S(r,"nodes",`too many nodes (max ${ao})`);else{i=[];for(let l=0;l<e.nodes.length;l++){let h=Qs(e.nodes[l],l,a||{},r);h&&(typeof h.id=="string"&&po.test(h.id)&&(s.has(h.id)?S(r,`nodes.${l}.id`,`duplicate node id "${h.id}"`):s.set(h.id,h)),i.push(h))}for(let l=0;l<i.length;l++){let h=i[l],p=`nodes.${l}`;for(let d of Lt(h))s.has(d)||S(r,p,`unknown node ref "${d}"`);if(h.type==="indicator"||h.type==="compare"||h.type==="cross")for(let d of Lt(h)){let m=s.get(d);m&&Ir.has(m.type)&&S(r,p,`node ref "${d}" must be numeric`)}if(h.type==="logic")for(let d of Lt(h)){let m=s.get(d);m&&!Ir.has(m.type)&&S(r,p,`node ref "${d}" must be boolean`)}}Zs(s)&&S(r,"nodes","graph contains a cycle")}let c=null;if(!ie(e.rules))S(r,"rules","must be a plain object");else{_e(e.rules,Rr,"rules",r);for(let l of Rr)l in e.rules||S(r,`rules.${l}`,"required field is missing");c={};for(let l of Rr){let h=e.rules[l];if(h===null){c[l]=null;continue}if(typeof h!="string"||!h){S(r,`rules.${l}`,"must be a node id or null"),c[l]=h;continue}if(!s.has(h)){S(r,`rules.${l}`,`unknown node ref "${h}"`),c[l]=h;continue}let p=s.get(h);Ir.has(p.type)||S(r,`rules.${l}`,`rule must reference a boolean node, not ${p.type}`),c[l]=h}}let f=ea(e.risk,r,t);if(r.length)return{ok:!1,errors:r,strategy:null};let u=jr({version:Mt,id:e.id,name:e.name,venue:n.id,market:o,parameters:a,nodes:i,rules:c,risk:f});return{ok:!0,errors:[],strategy:u}}function G(e,t={}){let r=Ht(e,t);if(!r.ok)throw new qe(r.errors);return r.strategy}function mo(e){let t=G(e);return JSON.stringify(Mr(t))}function de(e){let t=mo(e);return Ds("sha256").update(t,"utf8").digest("hex")}function Ge(e,t){if(!ie(e))throw new qe([{path:"",message:"strategy must be a plain object"}]);if(!ie(t))throw new qe([{path:"overrides",message:"must be a plain object"}]);let r=G(e),n={};for(let[a,i]of Object.entries(r.parameters))n[a]={value:i.value,min:i.min,max:i.max,step:i.step};let o=[];for(let[a,i]of Object.entries(t)){if(!Object.prototype.hasOwnProperty.call(n,a)){S(o,a,`unknown parameter "${a}"`);continue}let s=n[a];if(!J(i)){S(o,a,"override must be a finite number");continue}if(!ho(i,s.min,s.max,s.step)){S(o,a,"override must lie on the declared min/max/step grid");continue}n[a]={...s,value:i}}if(o.length)throw new qe(o);return G({version:r.version,id:r.id,name:r.name,venue:r.venue,market:{coin:r.market.coin,interval:r.market.interval},parameters:n,nodes:r.nodes.map(a=>{let i={...a};return Array.isArray(a.inputs)&&(i.inputs=[...a.inputs]),i}),rules:{...r.rules},risk:{...r.risk}})}var Mt,fo,po,Us,zs,Vs,Js,Ws,Gs,Ks,Ir,ro,no,Rr,oo,Ys,io,so,ao,co,qe,Te=V(()=>{jt();Mt=1,fo=/^[a-z0-9][a-z0-9._-]{0,63}$/,po=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Us=new Set(["open","high","low","close","volume","fundingRate","openInterest","premium","oiDelta","bookImbalance"]),zs=new Set(["sma","ema","rsi","macd","bollinger","atr"]),Vs=new Set(["gt","gte","lt","lte","eq"]),Js=new Set(["and","or","not"]),Ws=new Set(["above","below"]),Gs=new Set(["line","signal","histogram"]),Ks=new Set(["upper","middle","lower"]),Ir=new Set(["compare","logic","cross"]),ro=new Set(["version","id","name","venue","market","parameters","nodes","rules","risk"]),no=new Set(["value","min","max","step"]),Rr=new Set(["entryLong","entryShort","exitLong","exitShort"]),oo=new Set(["maxLeverage","maxNotionalUsd","positionSizePct","stopLossPct","takeProfitPct","cooldownBars","maxDailyLossPct","expiresAt"]),Ys=new Set(["id","type"]),io={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"])},so=16,ao=128,co=100,qe=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}}});import{types as ic}from"node:util";function rt(e,{omitUndefined:t=!1}={}){let r=new WeakSet,n=0,o=0;function a(i,s="",c=0){if(++n>3e5||c>10)throw new TypeError("bounded JSON input limit exceeded");if(i===null||typeof i=="boolean")return i;if(typeof i=="number"){if(!Number.isFinite(i))throw new TypeError("JSON numbers must be finite");return i}if(typeof i=="string"){if(o+=Buffer.byteLength(i),i.length>2048||o>8*1024*1024)throw new TypeError("bounded JSON string limit exceeded");if(ac.test(i)||/^(?:0x)?[a-fA-F0-9]{64}$/.test(i)&&!/hash$/i.test(s))throw new TypeError("secret-like or secret-bearing input is forbidden");return i}if(!i||typeof i!="object"||ic.isProxy(i))throw new TypeError("input must be plain JSON");if(r.has(i))throw new TypeError("JSON cycle is forbidden");let f=Array.isArray(i);if(!f&&![Object.prototype,null].includes(Object.getPrototypeOf(i)))throw new TypeError("input must be plain JSON");if(f&&i.length>1e4)throw new TypeError("bounded array limit exceeded");let u=Reflect.ownKeys(i).filter(h=>!(f&&h==="length"));if(!f&&u.length>64||f&&u.length!==i.length)throw new TypeError("bounded dense JSON required");r.add(i);let l=f?[]:{};for(let h of u){if(typeof h!="string"||h.length>64||["__proto__","constructor","prototype"].includes(h))throw new TypeError("invalid JSON key");if(sc.test(h.toLowerCase().replace(/[^a-z]/g,"")))throw new TypeError("secret-like or secret-bearing input is forbidden");let p=Object.getOwnPropertyDescriptor(i,h);if(!p.enumerable||!Object.hasOwn(p,"value"))throw new TypeError("JSON accessors are forbidden");if(f&&!/^(0|[1-9]\d*)$/.test(h))throw new TypeError("invalid JSON array");t&&c===0&&!f&&p.value===void 0||(l[h]=a(p.value,h,c+1))}return r.delete(i),l}return a(e)}var sc,ac,Vt=V(()=>{sc=/privatekey|privkey|mnemonic|seed|secret|password|passphrase|apikey|authorization|accesstoken|refreshtoken|signer|keystore|keymaterial|authtoken|credential|bearer|signature|xprv|xpriv|wif/,ac=/\b(?:private[\s_-]*key|mnemonic|seed[\s_-]*phrase|api[\s_-]*key|bearer\s+|sk-[A-Za-z0-9_-]{20,}|-----BEGIN .*PRIVATE KEY)/i});function nn({coin:e,interval:t="15m",maxTrials:r=X.max,nowMs:n}){if(!Number.isInteger(r)||r<X.min||r>X.max)throw new TypeError(`maxTrials must be an integer from ${X.min} to ${X.max}`);if(typeof t!="string"||!/^(1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)$/.test(t))throw new TypeError("unsupported interval");if($e(t),typeof e!="string"||e.length>32||!/^(?:[a-z][a-z0-9_-]*:)?[A-Za-z0-9][A-Za-z0-9._-]*$/.test(e))throw new TypeError("unsupported perp coin");if(!Number.isSafeInteger(n)||n<0||!Number.isSafeInteger(n+864e5))throw new TypeError("invalid nowMs");let o=[];for(let a=0;a<Jt.length;a++)for(let i of tn)for(let s of rn){if(o.length===r)return o;let c=s==="long",f=i==="rsi_mean_reversion"?{period:en[a][0],threshold:c?en[a][1]:100-en[a][1]}:{fast:Jt[a][0],slow:Jt[a][1]},u=`wallet-${i.replaceAll("_","-")}-${s}-${a}`,l=[{id:"close",type:"input",field:"close"}];i==="rsi_mean_reversion"?l.push({id:"rsi",type:"indicator",indicator:"rsi",input:"close",period:{param:"period"}},{id:"threshold",type:"constant",value:{param:"threshold"}},{id:"mid",type:"constant",value:50},{id:"entry",type:"compare",op:c?"lt":"gt",left:"rsi",right:"threshold"},{id:"exit",type:"compare",op:c?"gte":"lte",left:"rsi",right:"mid"}):l.push({id:"fast",type:"indicator",indicator:"ema",input:"close",period:{param:"fast"}},{id:"slow",type:"indicator",indicator:"ema",input:"close",period:{param:"slow"}},i==="ema_cross"?{id:"entry",type:"cross",direction:c?"above":"below",left:"fast",right:"slow"}:{id:"entry",type:"compare",op:c?"gt":"lt",left:"fast",right:"slow"},{id:"exit",type:"compare",op:c?"lte":"gte",left:"fast",right:"slow"});let h=Y({version:1,id:u,name:`Wallet candidate ${i} ${s}`,venue:"hyperliquid",market:{coin:e,interval:t},parameters:Object.fromEntries(Object.entries(f).map(([p,d])=>[p,{value:d,min:d,max:d,step:1}])),nodes:l,rules:{entryLong:c?"entry":null,entryShort:c?null:"entry",exitLong:c?"exit":null,exitShort:c?null:"exit"},risk:{maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3,expiresAt:n+864e5}});o.push({id:u,family:i,direction:s,parameters:f,strategy:h.strategy,strategyHash:h.strategyHash})}return o}function Ro({episodes:e,decisions:t},{coin:r,bars:n,startIndex:o,endIndex:a,intervalMs:i}){if(!Array.isArray(e)||!Array.isArray(t)||e.length>2e4||t.length>2e4)throw new TypeError("bounded reconstructed observations required");if(!Array.isArray(n)||n.length>5e3||!Number.isInteger(o)||!Number.isInteger(a)||o<0||a<o||a>n.length||!Number.isSafeInteger(i)||i<=0)throw new TypeError("invalid observation window");let s=e.filter(m=>m.coin===r),c=s.filter(m=>m.partialStart),f=new Map(s.filter(m=>!m.partialStart).map(m=>[`${m.fillIds[0]}:${m.side}`,m])),u=new Map;for(let m of t){if(m.coin!==r||!["entry","reverse"].includes(m.action))continue;let y=m.fillIds.map(v=>f.get(`${v}:${m.side}`)).find(Boolean);if(!y)continue;let b=y.openedAt,w=Math.floor((b-n[0].t)/i)-1;if(w<o||w>=a)continue;let A=n[w].t+i;if(A>b||b>=A+i)continue;let E=u.get(w)??[];E.push({...m,time:b,barIndex:w,featureClosedAt:A}),u.set(w,E)}let l=[],h=[],p=0,d=0;for(let m=o;m<a;m++){let y=n[m].t+i;if(c.some(w=>y<=(w.closedAt??Number.MAX_SAFE_INTEGER))){d++;continue}let b=u.get(m)??[];if(b.length>1){p++;continue}b.length&&h.push(b[0]),l.push({barIndex:m,label:b[0]?.side??null})}return{rows:l,labels:h,partialStartEpisodes:c.length,partialStartBars:d,ambiguousBars:p}}function Wt(e,t){if(!Array.isArray(t)||!t.length||t.length>5e3)throw new TypeError("bounded bars required");let r=null;return Y(e).evaluateAll(t).map(({signals:n})=>((r==="long"&&n.exitLong||r==="short"&&n.exitShort)&&(r=null),r||n.entryLong===n.entryShort?null:(r=n.entryLong?"long":"short",r)))}function No(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("invalid fitting input");if(Object.keys(e).some(u=>!["trials","bars","trainRows","validationRows"].includes(u)))throw new TypeError("unknown fitting option; holdout is forbidden");let{trials:t,bars:r,trainRows:n,validationRows:o}=e;if(!Array.isArray(t)||t.length<X.min||t.length>X.max)throw new TypeError("bounded candidate trials required");if(!Array.isArray(r)||!r.length||r.length>5e3)throw new TypeError("bounded bars required");let a=-1;for(let u of[n,o]){if(!Array.isArray(u)||u.length>5e3)throw new TypeError("bounded observations required");for(let l of u){if(!Number.isInteger(l?.barIndex)||l.barIndex<0||l.barIndex>=r.length)throw new TypeError("invalid observation index");if(l.barIndex<=a)throw new TypeError("observations must be chronological without overlap");a=l.barIndex}}let i=t.map(u=>{let l=Y(u.strategy),h=n.at(-1)?.barIndex??0,p=o.at(-1)?.barIndex??h,d=Wt(l.strategy,r.slice(0,h+1)),m=Wt(l.strategy,r.slice(0,p+1)),y=(E,v)=>Gt(E.map(O=>O.label),E.map(O=>v[O.barIndex])),b=y(n,d),w=y(o,m),A=[b,w].every(E=>E.positives>=3&&E.negatives>=20&&E.predictedPositives>=3&&E.precision>=.1&&E.recall>=.1&&E.balancedAccuracy>.5);return{id:u.id,family:u.family,direction:u.direction,parameters:u.parameters,strategyHash:l.strategyHash,train:b,validation:w,eligible:A,selectionScore:(b.f1+w.f1)/2}}),c=i.filter(u=>u.eligible).sort((u,l)=>l.selectionScore-u.selectionScore||u.id.localeCompare(l.id,"en"))[0],f=c?Object.freeze({id:c.id,family:c.family,direction:c.direction,parameters:Object.freeze({...c.parameters}),strategyHash:c.strategyHash,selectionScore:c.selectionScore}):null;return{trialsRun:i.length,candidateTrials:i,selectedCandidate:f}}function Gt(e,t){if(!Array.isArray(e)||!Array.isArray(t)||e.length!==t.length||e.length>5e3)throw new TypeError("label arrays must have equal bounded length");if([...e,...t].some(p=>p!==null&&p!=="long"&&p!=="short"))throw new TypeError("invalid decision label");let r=0,n=0,o=0,a=0,i=0,s={};for(let p=0;p<e.length;p++)e[p]!==null&&r++,t[p]!==null&&n++,e[p]===null&&t[p]===null&&a++,e[p]!==null&&e[p]===t[p]&&o++,e[p]!==null&&t[p]!==null&&e[p]!==t[p]&&i++;let c=(p,d)=>d?p/d:0,f=c(o,n),u=c(o,r),l=e.length-r,h=c(a,l);for(let p of["long","short"]){let d=0,m=0,y=0,b=0;for(let w=0;w<e.length;w++)e[w]===p&&t[w]===p?d++:t[w]===p?m++:e[w]===p?y++:b++;s[p]={truePositive:d,falsePositive:m,falseNegative:y,trueNegative:b,precision:c(d,d+m),recall:c(d,d+y)}}return{samples:e.length,positives:r,negatives:l,predictedPositives:n,correctEntries:o,trueNegative:a,wrongDirection:i,precision:f,recall:u,f1:c(2*f*u,f+u),specificity:h,balancedAccuracy:r&&l?(u+h)/2:null,accuracy:c(o+a,e.length),byDirection:s}}var Jt,en,tn,rn,X,Kt=V(()=>{fe();Xe();Jt=[[5,20],[8,21],[12,26],[20,50]],en=[[7,30],[14,30],[14,25],[21,35]],tn=["ema_cross","ema_trend","rsi_mean_reversion"],rn=["long","short"],X=Object.freeze({min:tn.length*rn.length,max:Jt.length*tn.length*rn.length})});var Vo={};nr(Vo,{collectWalletHistory:()=>zo,normalizeWalletHistory:()=>De,walletPositionUnits:()=>Be});import{createHash as Mo}from"node:crypto";import{types as Lo}from"node:util";function Yt(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be an epoch millisecond safe integer`);return e}function Co({wallet:e,startTime:t,endTime:r},n){if(typeof e!="string"||!/^0x[\da-fA-F]{40}$/.test(e))throw new TypeError("wallet must be a 20-byte hex address");Yt(t,"startTime"),Yt(r,"endTime");let o=Yt(n.nowMs??Date.now(),"nowMs time");if(t>=r||r>o)throw new TypeError("invalid time window");return o}function Fo(e,t,r=0){if(r>5)throw new TypeError("JSON depth limit exceeded");let n=s=>{if(t.row+=Buffer.byteLength(s),t.total+=Buffer.byteLength(s),t.row>cc||t.total>t.limit)throw new TypeError("payload byte limit exceeded");return s};if(e===null||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))return n(JSON.stringify(e));if(typeof e=="string"){if(e.length>4096)throw new TypeError("JSON string limit exceeded");return n(JSON.stringify(e))}if(!e||typeof e!="object")throw new TypeError("unsafe fill JSON value");if(Lo.isProxy(e))throw new TypeError("unsafe JSON proxy");let o=Array.isArray(e);if(!o&&![Object.prototype,null].includes(Object.getPrototypeOf(e)))throw new TypeError("unsafe JSON prototype");let a=Reflect.ownKeys(e).filter(s=>!(o&&s==="length"));if(a.length>64||o&&e.length>64)throw new TypeError("JSON member limit exceeded");if(o&&a.length!==e.length)throw new TypeError("unsafe JSON array");let i=[];for(let s of a.sort()){if(typeof s!="string"||s.length>64||["__proto__","constructor","prototype"].includes(s))throw new TypeError("unsafe JSON key");let c=Object.getOwnPropertyDescriptor(e,s);if(!c.enumerable||!Object.hasOwn(c,"value"))throw new TypeError("unsafe JSON accessor");if(o&&!/^(?:0|[1-9]\d*)$/.test(s))throw new TypeError("unsafe JSON array key");let f=o?"":n(`${JSON.stringify(s)}:`);i.push([s,f+Fo(c.value,t,r+1)])}return o&&i.sort((s,c)=>Number(s[0])-Number(c[0])),n((o?"[]":"{}")+",".repeat(Math.max(0,i.length-1))),`${o?"[":"{"}${i.map(s=>s[1]).join(",")}${o?"]":"}"}`}function wt(e,t,{signed:r=!1,positive:n=!1}={}){if(typeof e!="string"||e.length>62||!uc.test(e)||!Number.isFinite(Number(e)))throw new TypeError(`fill.${t} must be a bounded decimal string`);if(!r&&e.startsWith("-")||n&&Number(e)<=0)throw new TypeError(`fill.${t} has invalid quantity`);return e}function on(e,t){let r=Number.isSafeInteger(e)&&e>=0,n=typeof e=="string"&&/^(?:0|[1-9]\d{0,19})$/.test(e)&&BigInt(e)<=lc;if(!r&&!n)throw new TypeError(`fill.${t} must be an unsigned exact ID`);return e}function jo(e,t){if(typeof e!="string"||!fc.test(e))throw new TypeError(`fill.${t} must be a bounded market token`);return e}function dc(e,t,r,n){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("fill must be an object");n.row=0;let o=Fo(e,n),a=JSON.parse(o);for(let s of["coin","time","px","sz","side","startPosition","tid","oid"])if(!Object.hasOwn(a,s))throw new TypeError(`fill.${s} is required`);let i={coin:jo(a.coin,"coin"),time:Yt(a.time,"fill.time"),px:wt(a.px,"px",{positive:!0}),sz:wt(a.sz,"sz",{positive:!0}),side:a.side,startPosition:wt(a.startPosition,"startPosition",{signed:!0}),tid:on(a.tid,"tid"),oid:on(a.oid,"oid")};if(i.side!=="B"&&i.side!=="A")throw new TypeError("fill.side must be B or A");if(i.time<t||i.time>r)throw new TypeError("fill outside requested time window");for(let s of["fee","closedPnl","builderFee"])Object.hasOwn(a,s)&&(i[s]=wt(a[s],s,{signed:s!=="builderFee"}));if(Object.hasOwn(a,"dir")){if(typeof a.dir!="string"||!/^[\x20-\x7e]{1,96}$/.test(a.dir))throw new TypeError("fill.dir must be bounded text");i.dir=a.dir}if(Object.hasOwn(a,"crossed")){if(typeof a.crossed!="boolean")throw new TypeError("fill.crossed must be boolean");i.crossed=a.crossed}Object.hasOwn(a,"feeToken")&&(i.feeToken=jo(a.feeToken,"feeToken"));for(let[s,c]of[["hash",64],["cloid",32]])if(Object.hasOwn(a,s)){if(!(s==="cloid"&&a[s]===null)&&(typeof a[s]!="string"||!new RegExp(`^0x[\\da-fA-F]{${c}}$`).test(a[s])))throw new TypeError(`fill.${s} must be exact hex`);i[s]=a[s]}if(Object.hasOwn(a,"twapId")&&(i.twapId=a.twapId===null?null:on(a.twapId,"twapId")),Object.hasOwn(a,"liquidation")){let s=a.liquidation;if(!s||typeof s!="object"||Array.isArray(s)||typeof s.liquidatedUser!="string"||!/^0x[\da-fA-F]{40}$/.test(s.liquidatedUser)||typeof s.method!="string"||!/^[\x20-\x7e]{1,64}$/.test(s.method))throw new TypeError("fill.liquidation is invalid");i.liquidation={liquidatedUser:s.liquidatedUser,markPx:wt(s.markPx,"liquidation.markPx",{positive:!0}),method:s.method}}return{fill:i,canonical:o}}function Be(e){let t=e.startsWith("-"),[r,n=""]=(t?e.slice(1):e).split("."),o=BigInt(r)*10n**30n+BigInt(n.padEnd(30,"0"));return t?-o:o}function qo(e){return Be(e.startPosition)+Be(e.sz)*(e.side==="B"?1n:-1n)}function Bo(e,t){return e.fill.time!==t.fill.time?e.fill.time-t.fill.time:e.fill.coin!==t.fill.coin?e.fill.coin<t.fill.coin?-1:1:e.canonical<t.canonical?-1:e.canonical>t.canonical?1:0}function pc(e,t){if(e.length===1)return e;let r=new Map,n=f=>(r.has(f)||r.set(f,{outgoing:[],balance:0}),r.get(f));for(let f of e){let u=Be(f.fill.startPosition),l=qo(f.fill);n(u).outgoing.push({record:f,before:u,after:l}),n(u).balance++,n(l).balance--}let o=null,a=0;for(let[f,{balance:u}]of r)if(u===1&&o===null)o=f;else if(u===-1)a++;else if(u!==0)return null;if(o===null?a!==0:a!==1)return null;if(o===null){if(t===null||!r.has(t))return null;o=t}function i(f){let u=new Map,l=[{after:o,record:null}],h=[];for(;l.length;){let d=l.at(-1).after,m=r.get(d).outgoing,y=u.get(d)??0;if(y<m.length)u.set(d,y+1),l.push(m[f?m.length-1-y:y]);else{let b=l.pop();b.record&&h.push(b)}}if(h.reverse(),h.length!==e.length)return null;let p=o;for(let d of h){if(d.before!==p)return null;p=d.after}return h.map(d=>d.record)}let s=i(!1),c=i(!0);return s&&c&&s.every((f,u)=>f===c[u])?s:null}function hc(e){let t=[...e].sort(Bo),r=[],n=[],o=new Map;for(let a=0;a<t.length;){let{coin:i,time:s}=t[a].fill,c=a+1;for(;c<t.length&&t[c].fill.coin===i&&t[c].fill.time===s;)c++;let f=t.slice(a,c),u=pc(f,o.get(i)??null);u?(r.push(...u),o.set(i,qo(u.at(-1).fill))):(n.push(`ambiguous_fill_order:${i}:${s}`),r.push(...f),o.set(i,null)),a=c}return{ordered:r,reasons:n}}function Do(e,t,r,{limit:n=sn,bytes:o=Ho}={}){if(Lo.isProxy(e))throw new TypeError("unsafe fills proxy");if(!Array.isArray(e))throw new TypeError("fills must be an array");if(e.length>n)throw new TypeError("fill record count limit exceeded");let a={row:0,total:2+e.length,limit:o},i=[];for(let s=0;s<e.length;s++){let c=Object.getOwnPropertyDescriptor(e,String(s));if(!c?.enumerable||!Object.hasOwn(c,"value"))throw new TypeError("fills require dense own data, no accessors");i.push(dc(c.value,t,r,a))}return i}function an(e,t){let r=String(t.fill.tid),n=e.get(r);if(n&&n.canonical!==t.canonical)throw new TypeError("contradictory duplicate trade ID");n||e.set(r,t)}function Uo({wallet:e,startTime:t,endTime:r,records:n,status:o,pages:a,reasons:i,source:s,fetchedAt:c,rawPages:f}){let{ordered:u,reasons:l}=hc(n.values()),h=u.map(y=>y.fill),p={status:o,firstTime:h[0]?.time??null,lastTime:h.at(-1)?.time??null,fillCount:h.length,pages:a,reasons:[...i,...l]},d={startTime:t,endTime:r},m=Mo("sha256").update(JSON.stringify({schemaVersion:1,venue:"hyperliquid",wallet:e,requested:d,source:s,coverage:p,rawFills:u.map(y=>y.canonical),...f?{rawPages:f}:{}})).digest("hex");return{schemaVersion:1,venue:"hyperliquid",wallet:e,requested:d,fills:h,coverage:p,provenance:{source:s,fetchedAt:c,hash:m}}}function De({wallet:e,fills:t,startTime:r,endTime:n,source:o="import",coverage:a},i={}){let s=Co({wallet:e,startTime:r,endTime:n},i);if(typeof o!="string"||o.length>64)throw new TypeError("source must be bounded text");let c=new Map;for(let f of Do(t,r,n))an(c,f);return Uo({wallet:e,startTime:r,endTime:n,records:c,status:"unknown",pages:0,reasons:["import_coverage_unverified"],source:"import",fetchedAt:s})}async function zo({wallet:e,startTime:t,endTime:r,maxPages:n=5},o={}){let a=Co({wallet:e,startTime:t,endTime:r},o);if(!Number.isInteger(n)||n<1||n>10)throw new TypeError("maxPages must be an integer from 1 to 10");if(o.requestInfo!==void 0&&typeof o.requestInfo!="function")throw new TypeError("requestInfo must be a function");let i=o.requestInfo??(m=>ke(m,{timeoutMs:15e3,maxResponseBytes:2*1024*1024,sameOriginRedirectsOnly:!0})),s=new Map,c=[],f=["api_recent_10000_retention","unknown_first_history"],u="unknown",l=0,h=t,p=[],d=0;for(;l<n;){let m;l+=1;try{m=await i({type:"userFillsByTime",user:e,startTime:h,endTime:r,aggregateByTime:!1})}catch(E){if(E?.oversize===!0)throw new TypeError("payload byte limit exceeded");u="partial",f.push("network_error");break}let y=Do(m,h,r,{limit:2e3,bytes:2*1024*1024}).sort(Bo),b=`[${y.map(E=>E.canonical).join(",")}]`;c.push({startTime:h,hash:Mo("sha256").update(b).digest("hex")}),d+=Buffer.byteLength(b);let w=new Map;for(let E of y){an(w,E);let v=s.get(String(E.fill.tid));if(v&&v.canonical!==E.canonical)throw new TypeError("contradictory duplicate trade ID")}if(d>Ho){u="partial",f.push("payload_limit");break}for(let E of w.values())s.size<sn&&an(s,E);if(p.some(E=>!w.has(E))){u="partial",f.push("pagination_continuity_unproven");break}if(s.size>=sn){u="partial",f.push("record_limit");break}if(m.length<2e3){m.length===0&&f.push("empty_response");break}let A=y.at(-1).fill.time;if(A<=h){u="partial",f.push("ambiguous_same_timestamp_overflow");break}if(l===n){u="partial",f.push("page_limit");break}h=A,p=y.filter(E=>E.fill.time===h).map(E=>String(E.fill.tid))}return Uo({wallet:e,startTime:t,endTime:r,records:s,status:u,pages:l,reasons:f,source:"hyperliquid",fetchedAt:a,rawPages:c})}var sn,Ho,cc,lc,uc,fc,gt=V(()=>{Ve();sn=1e4,Ho=8*1024*1024,cc=16*1024,lc=18446744073709551615n,uc=/^-?(?:0|[1-9]\d{0,29})(?:\.\d{1,30})?$/,fc=/^[A-Za-z0-9@#][A-Za-z0-9._:@/#-]{0,63}$/});function mc(e,t){return e===0n?{action:"entry",side:ce(t)}:t===0n?{action:"exit",side:ce(e)}:ce(e)!==ce(t)?{action:"reverse",side:ce(t)}:{action:oe(t)>oe(e)?"increase":"reduce",side:ce(e)}}function yc(e,t){if(!(e.action==="reverse"||e.action==="entry"&&t.action==="increase")){if(e.action==="exit"&&t.action==="entry"){Object.assign(e,{action:"reverse",side:t.side});return}Object.assign(e,t)}}function cn(e,t,r,n,o){let a=Zt(oe(t)),i={coin:e.coin,side:ce(t),openedAt:e.time,closedAt:null,entryPrice:r?null:Number(e.px),exitPrice:null,size:a,partialStart:r,partialEnd:!0,fillIds:[]};return n.push(i),r&&o.push(`left_censored:${e.coin}:${e.time}`),{episode:i,peak:oe(t),entryQuantity:r?0:a,entryValue:r?0:a*Number(e.px),exitQuantity:0,exitValue:0}}function wc(e,t,r){let n=t.filter(i=>!i.partialStart&&!i.partialEnd),o=n.map(i=>i.closedAt-i.openedAt).sort((i,s)=>i-s),a=Math.floor(o.length/2);return{markets:[...new Set(e.map(i=>i.coin))].sort(),fillCount:e.length,decisionCount:r.length,episodeCount:t.length,closedEpisodeCount:t.filter(i=>i.closedAt!==null).length,completeEpisodeCount:n.length,partialStartCount:t.filter(i=>i.partialStart).length,partialEndCount:t.filter(i=>i.partialEnd).length,longEpisodeCount:t.filter(i=>i.side==="long").length,shortEpisodeCount:t.filter(i=>i.side==="short").length,reversalCount:r.filter(i=>i.action==="reverse").length,medianHoldingMs:o.length===0?null:o.length%2?o[a]:o[a-1]/2+o[a]/2}}function Xt(e){if(!e||e.schemaVersion!==1||e.venue!=="hyperliquid"||!e.requested)throw new TypeError("history must have schemaVersion 1 and venue hyperliquid");let{fills:t,coverage:r}=De({wallet:e.wallet,fills:e.fills,startTime:e.requested.startTime,endTime:e.requested.endTime},{nowMs:e.requested.endTime}),n=new Map,o=[],a=[],i=[e.coverage?.status==="partial"?"history_coverage_partial":"history_coverage_unverified"],s=new Set(r.reasons.filter(c=>c.startsWith("ambiguous_fill_order:")));i.push(...s);for(let c of t){if(s.has(`ambiguous_fill_order:${c.coin}:${c.time}`)){n.delete(c.coin);continue}let f=Be(c.startPosition),u=Be(c.sz)*(c.side==="B"?1n:-1n),l=f+u,h=String(c.tid),p=String(c.oid);n.has(c.coin)||n.set(c.coin,{position:null,active:null,epoch:0,groups:new Map});let d=n.get(c.coin);d.position!==null&&d.position!==f&&(i.push(`position_discontinuity:${c.coin}:${c.time}`),d.active=null,d.epoch+=1,d.groups.clear()),!d.active&&f!==0n&&(d.active=cn(c,f,!0,o,i));let m=`${p}:${c.side}`,y=mc(f,l),b=d.groups.get(m);if(!b||b.epoch!==d.epoch){let w={coin:c.coin,time:c.time,...y,orderId:p,fillIds:[]};a.push(w),b={epoch:d.epoch,decision:w},d.groups.set(m,b)}else yc(b.decision,y);if(b.decision.fillIds.push(h),f===0n)d.epoch+=1,d.active=cn(c,l,!1,o,i),d.active.episode.fillIds.push(h);else if(ce(f)===ce(l)&&l!==0n&&oe(l)>oe(f)){let w=d.active,A=Zt(oe(u));w.entryQuantity+=A,w.entryValue+=A*Number(c.px),w.episode.partialStart||(w.episode.entryPrice=w.entryValue/w.entryQuantity),oe(l)>w.peak&&(w.peak=oe(l),w.episode.size=Zt(w.peak)),w.episode.fillIds.push(h)}else{let w=d.active,A=Zt(oe(u)<oe(f)?oe(u):oe(f));w.exitQuantity+=A,w.exitValue+=A*Number(c.px),w.episode.fillIds.push(h),(l===0n||ce(f)!==ce(l))&&(d.epoch+=1,w.episode.closedAt=c.time,w.episode.exitPrice=w.exitValue/w.exitQuantity,w.episode.partialEnd=!1,d.active=null,l!==0n&&(d.epoch+=1,d.active=cn(c,l,!1,o,i),d.active.episode.fillIds.push(h)))}d.position=l,b.epoch=d.epoch}for(let c of o)c.partialEnd&&i.push(`incomplete_episode:${c.coin}:${c.openedAt}`);return{episodes:o,decisions:a,fingerprint:wc(t,o,a),warnings:i}}var oe,ce,Zt,ln=V(()=>{gt();oe=e=>e<0n?-e:e,ce=e=>e<0n?"short":"long",Zt=e=>+`${e}e-30`});var Ko={};nr(Ko,{inferWalletStrategy:()=>Go});import{createHash as gc}from"node:crypto";function fn(e){if(Array.isArray(e))return e.map(fn);if(e&&typeof e=="object")return Object.fromEntries(Object.keys(e).sort().map(t=>[t,fn(e[t])]));if(typeof e=="number"&&!Number.isFinite(e))throw new TypeError("non-finite inference result");return e}function nt(e){return gc("sha256").update(JSON.stringify(fn(e))).digest("hex")}function Qt(e,t){if(!Number.isSafeInteger(e)||e<0)throw new TypeError(`${t} must be an epoch millisecond safe integer`)}function bt(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("invalid input object");if(Object.keys(e).some(r=>!t.includes(r)))throw new TypeError("unknown input field")}function bc(e,t,r,n,o){if(!Array.isArray(e)||e.length>5e3)throw new TypeError("bars must be a bounded array, limit 5000");for(let a=0;a<e.length;a++){let i=e[a];if(!i||typeof i!="object"||Array.isArray(i))throw new TypeError("invalid bar");if(Qt(i.t,"bar time"),!Number.isSafeInteger(i.t+t)||i.t+t>r)throw new TypeError("bar close time must not be in the future");if(a&&i.t-e[a-1].t!==t)throw new TypeError("invalid bar cadence");if("T"in i&&i.T!==i.t+t-1&&i.T!==i.t+t)throw new TypeError("invalid bar close time");for(let s of["o","h","l","c"])if(typeof i[s]!="number"||!Number.isFinite(i[s])||i[s]<=0||i[s]>1e12)throw new TypeError("bar price must be positive finite and bounded");if(typeof i.v!="number"||!Number.isFinite(i.v)||i.v<0||i.v>1e24)throw new TypeError("bar volume must be non-negative finite and bounded");if(i.h<Math.max(i.o,i.c,i.l)||i.l>Math.min(i.o,i.c,i.h))throw new TypeError("invalid bar OHLC");if("s"in i&&i.s!==n)throw new TypeError("invalid bar market");if("i"in i&&i.i!==o)throw new TypeError("invalid bar interval");for(let s of["fundingRate","fundingPaymentRate"])if(i[s]!=null&&(typeof i[s]!="number"||!Number.isFinite(i[s])||Math.abs(i[s])>1))throw new TypeError("invalid finite funding rate");for(let s of["openInterest","premium","oiDelta","bookImbalance"])if(i[s]!=null&&(typeof i[s]!="number"||!Number.isFinite(i[s])))throw new TypeError("invalid optional bar series");if(i.openInterest!=null&&i.openInterest<0)throw new TypeError("invalid open interest");if(i.bookImbalance!=null&&Math.abs(i.bookImbalance)>1)throw new TypeError("invalid book imbalance")}}function Ec(e,t,r){let n=e.map((s,c)=>c>=we.warmupBars&&s.t+r>=t.startTime&&s.t+2*r<=t.endTime?c:-1).filter(s=>s>=0);if(n.length<5)return null;let o=n[0],a=n.length,i=[o,o+Math.floor(a*we.trainFraction),o+Math.floor(a*we.validationEndFraction),n.at(-1)+1];return Object.fromEntries(["train","validation","holdout"].map((s,c)=>[s,{startIndex:i[c],endIndex:i[c+1],startTime:e[i[c]].t+r,endTime:e[i[c+1]-1].t+2*r}]))}function Jo(e,t,r,n,o){let a=t.labels.length,i=[];return(t.rows.length<we.minimumSplitBars||r.endTime-r.startTime<we.minimumSplitSpanMs)&&i.push(`${e}: insufficient bars or time coverage`),(a<we.minimumSplitPositives||t.rows.length-a<we.minimumSplitNegatives)&&i.push(`${e}: insufficient positive episodes or no-trade observations`),a&&t.labels.at(-1).time-t.labels[0].time<we.minimumSplitSpanMs&&i.push(`${e}: positive episodes span insufficient time`),n.warnings.some(s=>s.startsWith(`position_discontinuity:${o}:`))&&i.push(`${e}: unstable position continuity`),n.warnings.some(s=>s.startsWith(`ambiguous_fill_order:${o}:`))&&i.push(`${e}: ambiguous same-time fill ordering`),t.ambiguousBars&&i.push(`${e}: multiple entry decisions share a candle; use finer cadence`),i}function Wo(e,t){return e.length?{startTime:e[0].t,endTime:e.at(-1).t+t,entryPrice:e[0].o,exitPrice:e.at(-1).c,grossReturnPct:(e.at(-1).c/e[0].o-1)*100}:null}function Go(e){let t=rt(e);bt(t,["history","coin","interval","bars","maxTrials","nowMs"]);let{history:r,coin:n,bars:o,interval:a="15m",maxTrials:i=X.max}=t;if(bt(r,["schemaVersion","venue","wallet","requested","fills","coverage","provenance"]),r.schemaVersion!==1||r.venue!=="hyperliquid")throw new TypeError("invalid wallet history schema or venue");if(bt(r.requested,["startTime","endTime"]),bt(r.coverage,["status","firstTime","lastTime","fillCount","pages","reasons"]),bt(r.provenance,["source","fetchedAt","hash"]),!["complete","partial","unknown"].includes(r.coverage.status)||!Array.isArray(r.coverage.reasons)||r.coverage.reasons.some(T=>typeof T!="string"))throw new TypeError("invalid history coverage");for(let T of["firstTime","lastTime"])r.coverage[T]!==null&&Qt(r.coverage[T],`coverage ${T}`);if(!Number.isInteger(r.coverage.fillCount)||r.coverage.fillCount<0||r.coverage.fillCount>1e4||!Number.isInteger(r.coverage.pages)||r.coverage.pages<0||r.coverage.pages>10)throw new TypeError("invalid coverage counts");if(typeof r.provenance.source!="string"||r.provenance.source.length>64||typeof r.provenance.hash!="string"||!/^[a-f0-9]{64}$/i.test(r.provenance.hash))throw new TypeError("invalid history provenance");let s=Object.hasOwn(t,"nowMs")?t.nowMs:r.provenance.fetchedAt;if(Qt(s,"nowMs"),Qt(r.provenance.fetchedAt,"history fetchedAt time"),r.provenance.fetchedAt>s||!Number.isSafeInteger(s+864e5))throw new TypeError("invalid nowMs time");if(typeof a!="string"||!/^(1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)$/.test(a))throw new TypeError("unsupported interval");if(!Number.isInteger(i)||i<X.min||i>X.max)throw new TypeError(`maxTrials must be an integer from ${X.min} to ${X.max}`);if(typeof n!="string"||n.length>32||!/^(?:@[0-9]+|(?:[a-z][a-z0-9_-]*:)?[A-Za-z0-9][A-Za-z0-9._-]*)$/.test(n))throw new TypeError("invalid perp coin");let c=$e(a);bc(o,c,s,n,a);let f=De({wallet:r.wallet,fills:r.fills,...r.requested,source:r.provenance.source,coverage:r.coverage},{nowMs:s}),u=Xt(f),l={...f.coverage,status:r.coverage.status==="partial"?"partial":"unknown",reasons:[...new Set([...f.coverage.reasons,...r.coverage.reasons])]},h=["Behavioral imitation candidate only, not recovery of the wallet owner algorithm or evidence of a profitable edge.","Imported history coverage is unverified; no-trade labels mean no observed entry, not proof of wallet inactivity.","Fill times are decision proxies. Hidden hedges, private signals and off-venue positions are unknown.","Risk defaults are fixed research caps, never inferred from wallet size; evidence, shadow and owner execution gates remain mandatory."],p={schemaVersion:1,status:"insufficient_evidence",strategy:null,reasons:h,fingerprint:u.fingerprint,coverage:l,warnings:u.warnings,armed:!1,executionReady:!1,requiredGates:["evidence","shadow","owner_execution"],split:null,selectedCandidate:null,candidateTrials:[],trialsRun:0,fit:{},noTradeBaseline:{},observations:{labels:[],positiveDecisions:0,partialStartEpisodes:u.episodes.filter(T=>T.coin===n&&T.partialStart).length}},d={coin:n,interval:a,maxTrials:i,nowMs:s,policy:we,replay:un,scoring:"directional entry proxies, mean train/validation F1; fixed risk exits excluded from imitation"};function m(){return p.provenance={source:"wallet_behavioral_inference",fetchedAt:s,historyCoverageVerified:!1,historyHash:nt(r),normalizedHistoryHash:nt(f),barsHash:He(o),compilerHash:ue,optionsHash:nt(d),splitHash:nt(p.split),candidateTrialsHash:nt(p.candidateTrials),selectedStrategyHash:p.selectedCandidate?.strategyHash??null},p.provenance.hash=nt(p),p}if(n.startsWith("@"))return p.status="unsupported_market",h.push("Spot @indices are unsupported, not leveraged perpetual markets."),m();let y=nn({coin:n,interval:a,maxTrials:i,nowMs:s});if(p.split=Ec(o,r.requested,c),!p.split)return h.push("Insufficient market overlap, bars and positive episodes."),m();let b=p.split,w={};function A(T){let C=b[T],L=De({wallet:f.wallet,fills:f.fills.filter(R=>R.time<C.endTime),startTime:f.requested.startTime,endTime:C.endTime-1},{nowMs:s}),j=Xt(L);w[T]={reconstruction:j,observations:Ro(j,{coin:n,bars:o,...C,intervalMs:c})};let $=w[T].observations.rows;p.noTradeBaseline[T]=Gt($.map(R=>R.label),$.map(()=>null))}function E(){p.observations.evaluatedSplits=Object.keys(w),p.observations.labels=Object.values(w).flatMap(T=>T.observations.labels),p.observations.positiveDecisions=p.observations.labels.length,p.observations.ambiguousBars=Object.values(w).reduce((T,C)=>T+C.observations.ambiguousBars,0)}A("train"),A("validation"),E();let v=["train","validation"].flatMap(T=>Jo(T,w[T].observations,b[T],w[T].reconstruction,n));if(b.holdout.endTime-b.train.startTime<we.minimumSpanMs&&v.push("Insufficient time coverage: at least seven days are required."),v.length)return h.push(...v),m();let O=No({trials:y,bars:o.slice(0,b.validation.endIndex),trainRows:w.train.observations.rows,validationRows:w.validation.observations.rows});if(Object.assign(p,O),!O.selectedCandidate)return h.push("All-no-trade or inadequate train/validation fits; no candidate clears the behavioral baseline."),m();let g=y.find(T=>T.id===O.selectedCandidate.id),M=O.candidateTrials.find(T=>T.id===g.id);A("holdout"),E();let q=Wt(g.strategy,o);p.fit={train:M.train,validation:M.validation,holdout:Gt(w.holdout.observations.rows.map(T=>T.label),w.holdout.observations.rows.map(T=>q[T.barIndex]))};let z=Jo("holdout",w.holdout.observations,b.holdout,w.holdout.reconstruction,n);(p.fit.holdout.predictedPositives===0||p.fit.holdout.balancedAccuracy<=.5||p.fit.holdout.recall<.1||p.fit.holdout.precision<.1)&&z.push("Frozen candidate has insufficient holdout behavioral fit; no re-optimization performed."),(l.status==="partial"||l.reasons.some(T=>/page_limit|record_limit|network_error|pagination_continuity|timestamp_overflow|payload_limit/.test(T)))&&z.push("Partial or truncated history cannot establish a reliable inference window.");let P=ee(g.strategy,o,un),x=o.slice(b.holdout.startIndex,b.holdout.endIndex+1),N=o.filter(T=>typeof T.fundingPaymentRate=="number").length;return p.backtest={full:P,holdout:ee(g.strategy,x,un),fundingCoverage:{status:"unknown",barsWithPaymentRates:N,totalBars:o.length,limitation:"Only explicit supplied fundingPaymentRate values are charged; event completeness is unverified, absent payments are not evidence of zero funding."},limitations:["Replay is not observed wallet profitability or delayed-copy performance.","Holdout replay starts flat and resets indicator warmup; full replay is descriptive, not out-of-sample performance.","Fixed research risk, next-open latency, fees, adverse slippage and volume participation are simulated, not venue execution guarantees."]},p.marketExposureComparison={basis:"Unlevered long price-only return; excludes fees, funding, slippage and execution constraints.",full:Wo(o,c),holdout:Wo(x,c)},z.length?h.push(...z):(p.status="candidate",p.strategy=g.strategy),m()}var un,we,dn=V(()=>{Vt();gt();ln();fe();Ce();Xe();Kt();un=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:1}),we=Object.freeze({warmupBars:64,trainFraction:.6,validationEndFraction:.8,minimumSpanMs:6048e5,minimumSplitSpanMs:864e5,minimumSplitBars:64,minimumSplitPositives:3,minimumSplitNegatives:20})});var Xo={};nr(Xo,{runWalletStrategyOperation:()=>kc});function Ue(e,t,r,n){if(!Number.isSafeInteger(e)||e<t||e>r)throw new TypeError(`${n} must be an integer from ${t} to ${r}`);return e}async function kc(e,t,r={}){let n=rt(t,{omitUndefined:!0});if(!n||typeof n!="object"||Array.isArray(n))throw new TypeError("wallet strategy input must be an object");let o=new Set(e==="collect"?Zo:xc);for(let v of Object.keys(n))if(!o.has(v))throw new TypeError("unsupported wallet strategy field");let a=r.nowMs;Ue(a,0,Number.MAX_SAFE_INTEGER,"nowMs");let i=n.history;if(i!==void 0&&(!i||typeof i!="object"||Array.isArray(i)))throw new TypeError("history must be a wallet history object");let s=n.wallet??i?.wallet;if(typeof s!="string"||!Yo.test(s))throw new TypeError("wallet must be an EVM address");if(i&&(typeof i.wallet!="string"||!Yo.test(i.wallet)||i.wallet.toLowerCase()!==s.toLowerCase()))throw new TypeError("history wallet identity must match wallet");let c=n.days??7;Ue(c,1,90,"days");let f=Ue(n.maxPages??5,1,10,"maxPages"),u=n.endTime??i?.requested?.endTime??a,l=n.startTime??i?.requested?.startTime??Math.max(0,u-c*864e5);if(Ue(u,1,a,"endTime"),Ue(l,0,u-1,"startTime"),i&&(l!==i.requested?.startTime||u!==i.requested?.endTime))throw new TypeError("history requested window must match the inference window");let h=n.interval??"15m",p=n.count??1500,d=n.maxTrials??X.max;if(e==="infer"){if(typeof n.coin!="string"||n.coin.length>32||!Sc.test(n.coin))throw new TypeError("coin must be a Hyperliquid market identifier");if($e(h),Ue(p,20,5e3,"count"),Ue(d,X.min,X.max,"maxTrials"),n.bars!==void 0&&(!Array.isArray(n.bars)||n.bars.length>5e3))throw new TypeError("bars must be an array with at most 5000 candles")}r.signal?.throwIfAborted?.();let{collectWalletHistory:m,normalizeWalletHistory:y}=await Promise.resolve().then(()=>(gt(),Vo)),w=i?y({wallet:s,fills:i.fills,startTime:l,endTime:u,source:"import",coverage:i.coverage},{nowMs:a}):await m({wallet:s,startTime:l,endTime:u,maxPages:f},{nowMs:a,requestInfo:async v=>{r.signal?.throwIfAborted?.();let O=r.requestInfo?await r.requestInfo(v):await ke(v,{timeoutMs:1e4,maxResponseBytes:2*1024*1024,sameOriginRedirectsOnly:!0});return r.signal?.throwIfAborted?.(),O}});if(r.signal?.throwIfAborted?.(),e==="collect")return w;let{inferWalletStrategy:A}=await Promise.resolve().then(()=>(dn(),Ko)),E=n.bars;if(E===void 0&&!n.coin.startsWith("@")&&w.fills.some(v=>v.coin===n.coin)){let O=await(r.fetchBars??ht)({coin:n.coin,interval:h,count:p,endTime:u},{signal:r.signal});if(E=Array.isArray(O)?O:O?.bars,!Array.isArray(E))throw new TypeError("strategy history provider returned no bars")}return r.signal?.throwIfAborted?.(),A({history:i??w,coin:n.coin,interval:h,bars:E??[],maxTrials:d,nowMs:a})}var Zo,xc,Yo,Sc,Qo=V(()=>{Xe();Ve();Kt();Vt();Zo=["wallet","startTime","endTime","days","maxPages","nowMs"],xc=[...Zo,"history","coin","interval","bars","count","maxTrials"],Yo=/^0x[0-9a-fA-F]{40}$/,Sc=/^(?:[A-Za-z0-9][A-Za-z0-9._-]{0,31}|[a-z][a-z0-9]{0,15}:[A-Za-z0-9][A-Za-z0-9._-]{0,15}|@[0-9]+)$/});Te();wr();Xe();fe();Ce();Ve();var ta=50;function me(e,t){let r=Number(e);if(!Number.isFinite(r))throw new TypeError(`${t} must be finite`);return r}function yo(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 a=me(e[o]?.px,`${r}[${o}].px`),i=me(e[o]?.sz,`${r}[${o}].sz`);if(i<0)throw new TypeError(`${r}[${o}].sz must be non-negative`);Math.abs((a-t)/t)*1e4<=ta&&(n+=i)}return n}async function ra(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([Ln(t),jn(r,t)]),a=n?.[0]?.universe,i=n?.[1];if(!Array.isArray(a)||!Array.isArray(i))throw new TypeError("metaAndAssetCtxs payload malformed");let s=a.findIndex(m=>m?.name===r);if(s<0)throw new Error(`unknown coin: ${r}`);let c=i[s];if(!c||typeof c!="object")throw new TypeError("asset ctx malformed");let f=me(c.premium,"ctx.premium"),u=me(c.openInterest,"ctx.openInterest");if(u<0)throw new TypeError("ctx.openInterest must be non-negative");let l=me(c.midPx,"ctx.midPx"),h=o?.levels;if(!Array.isArray(h)||h.length!==2)throw new TypeError("l2Book levels malformed");let p=yo(h[0],l,"book.bids"),d=yo(h[1],l,"book.asks");if(p+d<=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:p,askDepth:d})})}function na(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 a=e[o];if(!a||typeof a!="object")throw new TypeError(`snapshots[${o}] must be an object`);if(a.coin!==t)throw new TypeError("snapshots must be a single coin");let i=me(a.t,`snapshots[${o}].t`);if(n!=null&&!(i>n.t))throw new TypeError("snapshot times must be strictly increasing");let s=me(a.premium,`snapshots[${o}].premium`),c=me(a.openInterest,`snapshots[${o}].openInterest`),f=me(a.book?.bidDepth,`snapshots[${o}].book.bidDepth`),u=me(a.book?.askDepth,`snapshots[${o}].book.askDepth`),l=f+u;if(!(l>0))throw new TypeError(`snapshots[${o}] book depth must be positive`);r.push({coin:t,t:i,premium:s,openInterest:c,oiDelta:n==null?null:c-n.openInterest,bookImbalance:(f-u)/l}),n={t:i,openInterest:c}}return r}function oa(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 a=o.t+r,i=null;for(;n<t.length&&t[n].t<a;)t[n].t>=o.t&&(i=t[n]),n+=1;if(!i)return{...o};let s={...o};return i.premium!=null&&(s.premium=i.premium),i.openInterest!=null&&(s.openInterest=i.openInterest),i.oiDelta!=null&&(s.oiDelta=i.oiDelta),i.bookImbalance!=null&&(s.bookImbalance=i.bookImbalance),s})}fe();Te();Ce();import{createHash as ia}from"node:crypto";var Hr=256,wo=new Set(["netPnlUsd","profitFactor","sharpe","maxDrawdownPct"]);function go(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 bo(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function Cr(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)Cr(t);return Object.freeze(e)}for(let t of Object.keys(e))Cr(e[t]);return Object.freeze(e)}function mt(e){if(Array.isArray(e))return e.map(mt);if(e!=null&&typeof e=="object"){let t={};for(let r of Object.keys(e).sort())t[r]=mt(e[r]);return t}return e}function Ct(e){return JSON.stringify(mt(e))}function sa(e){let{min:t,max:r,step:n}=e;if(!(n>0)||t>r)return[];let o=[],a=Math.floor((r-t)/n+1e-9);for(let s=0;s<=a;s++){let c=t+s*n;if(c>r+1e-9)break;let f=Math.abs(c-Math.round(c))<1e-9?Math.round(c):Number(c.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 s=(r-t)/n;Math.abs(s-Math.round(s))<=1e-9&&o.push(r)}return o}function aa(e,t){if(e.length===0)return[];let r=[{}];for(let n of e){let o=t[n],a=[];for(let i of r)for(let s of o)a.push({...i,[n]:s});r=a}return r.sort((n,o)=>{let a=Ct(n),i=Ct(o);return a<i?-1:a>i?1:0}),r}function Lr(e,t,r,n,o){let a=0;if(e==="maxDrawdownPct"){if(a=t.maxDrawdownPct-n.maxDrawdownPct,a!==0)return a<0}else if(a=t[e]-n[e],a!==0)return a>0;let i=Ct(r),s=Ct(o);return i<s}function Fr(e,t,r={}){if(!bo(r))throw new TypeError("options must be a plain object");for(let E of Object.keys(r))if(go(E))throw new TypeError(`options must not include holdout/test/oos key "${E}"`);let n=new Set(["maxTrials","objective","backtestOptions"]);for(let E of Object.keys(r))if(!n.has(E))throw new TypeError(`unknown option "${E}"`);let o=64;if("maxTrials"in r){let E=r.maxTrials;if(!Number.isInteger(E)||E<1||E>Hr)throw new TypeError(`maxTrials must be an integer 1..${Hr}`);o=E}let a=r.objective??"netPnlUsd";if(!wo.has(a))throw new TypeError(`objective must be one of ${[...wo].join("|")}`);let i=r.backtestOptions??{};if(!bo(i))throw new TypeError("backtestOptions must be a plain object");for(let E of Object.keys(i))if(go(E))throw new TypeError(`backtestOptions must not include holdout/test/oos key "${E}"`);let s=G(e),c=Object.keys(s.parameters).sort();if(c.length===0)throw new Error("optimizeStrategy requires at least one declared parameter");let f={},u=1;for(let E of c){let v=sa(s.parameters[E]);if(v.length===0)throw new Error(`parameter "${E}" produces an empty grid`);f[E]=v,u*=v.length}let l=aa(c,f);if(l.length===0)throw new Error("parameter grid is empty");let h=l.slice(0,o),p=[],d=null,m=null;for(let E of h){let v=Ge(s,E),O=ee(v,t,i);m==null&&(m=O.config);let g={netPnlUsd:O.metrics.netPnlUsd,netPnlPct:O.metrics.netPnlPct,maxDrawdownPct:O.metrics.maxDrawdownPct,winRate:O.metrics.winRate,profitFactor:O.metrics.profitFactor,tradeCount:O.metrics.tradeCount,sharpe:O.metrics.sharpe,turnoverUsd:O.metrics.turnoverUsd},M={parameters:{...E},metrics:g};p.push(M),(!d||Lr(a,g,E,d.metrics,d.parameters))&&(d=M)}p.sort((E,v)=>Lr(a,E.metrics,E.parameters,v.metrics,v.parameters)?-1:Lr(a,v.metrics,v.parameters,E.metrics,E.parameters)?1:0);let y={...d.parameters},b=Ge(s,y),w={strategyHash:de(s),compilerHash:ue,trainBarsHash:He(t),backtestConfig:m,objective:a,maxTrials:o,trialsRun:p.length,candidates:p,bestParameters:y,bestStrategy:b},A={id:ia("sha256").update(JSON.stringify(mt(w)),"utf8").digest("hex"),...w};return Cr(mt(JSON.parse(JSON.stringify(A))))}It();Te();import{createHash as ca}from"node:crypto";var Z=class extends Error{constructor(t){super(t),this.name="StrategyDraftError"}},la=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),ua=new Set(["BTC","ETH","SOL","HYPE"]),fa=/\b(mnemonic|private\s*key|privkey|seed\s*phrase|seed\b|api[_-]?key|secret\s*key|wallet\s*key|passphrase)\b/i,Qe="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.",da=Object.freeze({maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3}),pa=36e5,ha=30*864e5,ma=864e5;function ya(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function qr(e){if(e==null||typeof e!="object"||Object.isFrozen(e))return e;if(Array.isArray(e)){for(let t of e)qr(t);return Object.freeze(e)}for(let t of Object.keys(e))qr(e[t]);return Object.freeze(e)}function wa(e){return String(e).trim().replace(/\s+/g," ")}function ga(e){let t=e.match(/\b(long|short)\b/i);return t?t[1].toLowerCase():null}function ba(e){for(let r of ua)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 Ea(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 la.has(r)?r:null}function xa(e){let t={...da},r=e.match(/stop\s*loss\s*(\d+(?:\.\d+)?)\s*%?/i);r&&(t.stopLossPct=Number(r[1]));let n=e.match(/take\s*profit\s*(\d+(?:\.\d+)?)\s*%?/i);n&&(t.takeProfitPct=Number(n[1]));let o=e.match(/leverage\s*(\d+(?:\.\d+)?)/i);o&&(t.maxLeverage=Number(o[1]));let a=e.match(/position\s*size\s*(\d+(?:\.\d+)?)\s*%?/i);a&&(t.positionSizePct=Number(a[1]));let i=e.match(/max\s*notional\s*(?:usd\s*)?\$?\s*(\d+(?:\.\d+)?)/i);return i&&(t.maxNotionalUsd=Number(i[1])),t}function Sa(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 ka(e){let t=ca("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 Ta(e){let t=e.match(/\bema\s*(\d+)\s*cross(?:es)?\s*(above|below)\s*ema\s*(\d+)\b/i);if(!t)return null;let r=Number(t[1]),n=t[2].toLowerCase(),o=Number(t[3]);if(!(r>0)||!(o>0)||r===o)return null;let a=/\b(exit\s+on\s+reverse|reverse\s+exit)\b/i.test(e);return{kind:"ema_cross",fast:r,slow:o,direction:n,reverse:a}}function Aa(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 Oa(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 va(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 Pa(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 $a(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 _a(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 Ia(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 Eo(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 Ra({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:i,spec:s}){let c=[{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:s.direction,left:"emaLeft",right:"emaRight"}],f={entryLong:null,entryShort:null,exitLong:null,exitShort:null};if(e==="long"?f.entryLong="cross":f.entryShort="cross",s.reverse){let u=s.direction==="above"?"below":"above";c.push({id:"crossRev",type:"cross",direction:u,left:"emaLeft",right:"emaRight"}),e==="long"?f.exitLong="crossRev":f.exitShort="crossRev"}return{version:1,id:a,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{ema_left_period:Eo(s.fast),ema_right_period:Eo(s.slow)},nodes:c,rules:f,risk:{...n,expiresAt:o}}}function Na({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:i,spec:s}){let c=[{id:"c",type:"input",field:"close"},{id:"rsi",type:"indicator",indicator:"rsi",input:"c",period:s.period},{id:"thr",type:"constant",value:s.threshold},{id:"sig",type:"compare",op:s.op==="above"?"gt":"lt",left:"rsi",right:"thr"}];return{version:1,id:a,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:c,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function ja({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:i,spec:s}){let c=[{id:"fr",type:"input",field:"fundingRate"},{id:"thr",type:"constant",value:s.threshold},{id:"sig",type:"compare",op:s.op==="above"?"gt":"lt",left:"fr",right:"thr"}];return{version:1,id:a,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:c,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function Ma({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:i,spec:s}){let c=[{id:"oi",type:"input",field:"openInterest"},{id:"thr",type:"constant",value:s.threshold},{id:"sig",type:"compare",op:s.op==="above"?"gt":"lt",left:"oi",right:"thr"}];return{version:1,id:a,name:i,venue:"hyperliquid",market:{coin:t,interval:r},parameters:{},nodes:c,rules:{entryLong:e==="long"?"sig":null,entryShort:e==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}var La=Object.freeze({funding:"fundingRate",open_interest:"openInterest",premium:"premium",oi_delta:"oiDelta",book_imbalance:"bookImbalance"});function Ha({side:e,coin:t,interval:r,risk:n,expiresAt:o,id:a,name:i,spec:s}){let f=[{id:"sig_input",type:"input",field:La[s.kind]},{id:"thr",type:"constant",value:s.threshold},{id:"sig",type:"compare",op:s.op==="above"?"gt":"lt",left:"sig_input",right:"thr"}];return{version:1,id:a,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 Br(e,t={}){if(typeof e!="string")throw new Z("prompt must be a string");if(e.length>1e3)throw new Z("prompt length must be <= 1000");if(!ya(t))throw new Z("options must be a plain object");if(!Number.isInteger(t.nowMs))throw new Z("options.nowMs is required integer epoch ms");let r=t.nowMs,n=ma;if("expiresInMs"in t){if(!Number.isInteger(t.expiresInMs))throw new Z("expiresInMs must be an integer");if(n=t.expiresInMs,n<pa||n>ha)throw new Z("expiresInMs must be between 1h and 30d")}if(fa.test(e))throw new Z(`prompt appears to contain secrets and is rejected. ${Qe}`);let o=wa(e);if(!o)throw new Z(`empty prompt. ${Qe}`);if(Sa(o))throw new Z(`duplicate interval or risk clause. ${Qe}`);let a=ga(o),i=ba(o),s=Ea(o);if(!a||!i||!s)throw new Z(`could not parse side/coin/interval. ${Qe}`);let c=xa(o);if(!(c.maxLeverage>0)||c.maxLeverage>50)throw new Z("leverage out of range");if(!(c.positionSizePct>0)||c.positionSizePct>100)throw new Z("position size out of range");let f=r+n,u=ka(o),l=`Draft ${i} ${a}`.slice(0,100),h=Ta(o),p=Aa(o),d=Oa(o),m=va(o),y=Pa(o),b=$a(o),w=_a(o),A=[h,p,d,m,y,b,w].filter(Boolean);if(A.length!==1)throw new Z(`unsupported or ambiguous prompt. ${Qe}`);if(!Ia(o,A[0]))throw new Z(`unsupported or ambiguous prompt. ${Qe}`);let E,v=A[0],O={side:a,coin:i,interval:s,risk:c,expiresAt:f,id:u,name:l,spec:v};v.kind==="ema_cross"?E=Ra(O):v.kind==="rsi"?E=Na(O):v.kind==="open_interest"?E=Ma(O):v.kind==="funding"?E=ja(O):E=Ha(O);let g=Ht(E,{nowMs:r});if(!g.ok)throw new Z(`draft failed validation: ${g.errors.map(M=>M.message).join("; ")}`);return qr(G(E,{nowMs:r}))}Ce();Te();var zr=1,To=3,et=5,xo=2,Ca=.3,So=5,Dr=25;function Ae(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function yt(e){return typeof e=="number"&&Number.isFinite(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 Bt(e){return Math.round(e*1e4)/1e4}function Q(e){let t=yt(e)?e:0;return`${t>=0?"+":"-"}${Math.abs(t).toFixed(2)}%`}function Ft(e,t=2){return yt(e)?e>=1e9?">1e9":e.toFixed(t):"n/a"}function Vr(e){if(!Array.isArray(e)||e.length===0)throw new TypeError("bars must be a non-empty array");for(let t=0;t<e.length;t++){let r=e[t];if(!Ae(r)||!yt(r.o)||!yt(r.c)||!(r.o>0)||!(r.c>0))throw new TypeError(`bars[${t}] must have positive finite o and c`)}}function Jr(e){Vr(e);let t=e[0].o;return(e[e.length-1].c-t)/t*100}function Fa(e){if(typeof e!="string"||!e.startsWith("/"))throw new TypeError(`bad json pointer "${e}"`);return e.slice(1).split("/").map(t=>t.replace(/~1/g,"/").replace(/~0/g,"~"))}function Ur(e){return JSON.parse(JSON.stringify(e))}function Ao(e,t){if(!Array.isArray(t))throw new TypeError("patch must be an array of operations");let r=Ur(G(e));for(let n=0;n<t.length;n++){let o=t[n];if(!Ae(o))throw new TypeError(`patch[${n}] must be an object`);let a=Fa(o.path),i=a[a.length-1],s=r;for(let c of a.slice(0,-1)){if(!Ae(s)&&!Array.isArray(s))throw new TypeError(`patch[${n}] path not found: ${o.path}`);s=s[c]}if(!Ae(s)&&!Array.isArray(s))throw new TypeError(`patch[${n}] path not found: ${o.path}`);if(o.op==="replace"){if(!(i in s))throw new TypeError(`patch[${n}] replace target missing: ${o.path}`);s[i]=Ur(o.value)}else if(o.op==="add")s[i]=Ur(o.value);else if(o.op==="remove")delete s[i];else throw new TypeError(`patch[${n}] unsupported op "${o.op}"`)}return G(r)}function Ie(e,t,r){return{op:"replace",path:e,value:r,from:t}}function qa(e){return e.exitBarIndex-e.entryBarIndex}function Wr(e,t,r){return e==="long"?(r-t)/t:(t-r)/t}function Ba({strategy:e,bars:t,trades:r}){let n=r.filter(s=>s.exitReason==="stop_loss");if(n.length===0)return null;let o=0;for(let s of n){let c=Math.min(t.length-1,s.exitBarIndex+et);for(let f=s.exitBarIndex+1;f<=c;f++)if(Wr(s.side,s.entryPrice,t[f].c)>0){o+=1;break}}if(o===0)return null;let a=e.risk.stopLossPct,i=Math.min(100,Bt(a*1.5));return{rule:"stop_then_reverse",severity:o/r.length,observation:`${o} of ${n.length} stop-outs saw price come back past entry within ${et} bars (${r.length} trades total)`,suggestion:`widen risk.stopLossPct from ${a} to ${i} so noise does not knock out positions that were right`,patch:i!==a?[Ie("/risk/stopLossPct",a,i)]:null}}function Da({strategy:e,trades:t}){if(t.length===0)return null;let r=t.filter(i=>qa(i)<=xo&&i.netPnlUsd<0),n=r.length/t.length;if(n<Ca)return null;let o=e.risk.cooldownBars,a=Math.min(1e5,o+3);return{rule:"whipsaw",severity:n,observation:`${r.length} of ${t.length} trades were losers held <= ${xo} bars (whipsaw ratio ${(n*100).toFixed(0)}%)`,suggestion:`raise risk.cooldownBars from ${o} to ${a} to stop re-entering straight into chop`,patch:[Ie("/risk/cooldownBars",o,a)]}}function Ua({strategy:e,bars:t,trades:r}){let n=r.filter(c=>c.exitReason==="take_profit");if(n.length===0)return null;let o=e.risk.takeProfitPct/100,a=0;for(let c of n){let f=Math.min(t.length-1,c.exitBarIndex+et);for(let u=c.exitBarIndex+1;u<=f;u++)if(Wr(c.side,c.entryPrice,t[u].c)>=o*1.5){a+=1;break}}if(a===0)return null;let i=e.risk.takeProfitPct,s=Math.min(1e3,Bt(i*1.5));return{rule:"take_profit_capped_winners",severity:a/r.length,observation:`${a} of ${n.length} take-profit exits kept running at least 1.5x further within ${et} bars`,suggestion:`raise risk.takeProfitPct from ${i} to ${s} to let winners run`,patch:s!==i?[Ie("/risk/takeProfitPct",i,s)]:null}}function za({strategy:e,bars:t,trades:r}){let n=r.filter(u=>u.exitReason==="rule");if(n.length===0)return null;let o=e.risk.takeProfitPct/100,a={long:0,short:0};for(let u of n){let l=Math.min(t.length-1,u.exitBarIndex+et);for(let h=u.exitBarIndex+1;h<=l;h++)if(Wr(u.side,u.exitPrice,t[h].c)>=o/2){a[u.side]+=1;break}}let i=a.long+a.short;if(i===0)return null;let s=a.long>=a.short?"long":"short",c=s==="long"?"exitLong":"exitShort",f=e.rules[c];return{rule:"rule_exit_too_early",severity:i/r.length,observation:`${i} of ${n.length} rule exits were followed by at least half a take-profit move in the trade's favor within ${et} bars`,suggestion:`set rules.${c} to null so ${s} exits are governed by stop/take-profit instead of the early signal`,patch:f!=null?[Ie(`/rules/${c}`,f,null)]:null}}function Va({strategy:e,result:t,trades:r}){let n=t.equityCurve,o=t.metrics.maxDrawdownPct;if(!(o>0)||!Array.isArray(n)||n.length===0)return null;let a=-1/0,i=0,s=0,c=0,f=0;for(let y=0;y<n.length;y++){let b=n[y].equity;b>a&&(a=b,i=y);let w=a>0?(a-b)/a*100:0;w>s&&(s=w,c=i,f=y)}let u=r.filter(y=>y.exitBarIndex>c&&y.exitBarIndex<=f),l=0,h=0;for(let y of u)y.netPnlUsd<0?(l+=1,l>h&&(h=l)):l=0;let p=e.risk.positionSizePct,d=Math.max(1,Bt(p/2)),m=o>So&&d<p;return{rule:"worst_drawdown_context",severity:Math.min(1,o/20),observation:`worst drawdown ${o.toFixed(2)}% ran from bar ${c} to bar ${f} across ${u.length} closed trades (${h} losers in a row)`,suggestion:m?`halve risk.positionSizePct from ${p} to ${d} to cut the depth of losing streaks`:`drawdown is under ${So}%; sizing left alone`,patch:m?[Ie("/risk/positionSizePct",p,d)]:null}}function Ja({strategy:e,result:t,trades:r}){if(r.length===0)return null;let n=t.costs.feesUsd+t.costs.builderFeesUsd+t.costs.slippageUsd+Math.max(0,t.costs.fundingUsd),o=0;for(let s of r)o+=s.grossPnlUsd;if(!(o>0)||n<o*.5)return null;let a=e.risk.cooldownBars,i=Math.min(1e5,a+3);return{rule:"costs_ate_edge",severity:Math.min(1,n/o)*.8,observation:`fees+slippage ${n.toFixed(2)} USD against ${o.toFixed(2)} USD gross trade pnl over ${r.length} trades`,suggestion:`raise risk.cooldownBars from ${a} to ${i} to trade less and pay less`,patch:[Ie("/risk/cooldownBars",a,i)]}}function Wa({strategy:e,result:t,buyAndHoldPct:r,trades:n}){let o=t.metrics.exposurePct;if(n.length===0){let s=e.risk.cooldownBars;return{rule:"time_in_market",severity:.5,observation:`0 trades; strategy was flat for 100% of ${t.equityCurve.length} bars while buy-and-hold returned ${Q(r)}`,suggestion:s>0?`set risk.cooldownBars from ${s} to 0; the entry rules never fired`:"entry rules never fired; loosen the entry condition by hand",patch:s>0?[Ie("/risk/cooldownBars",s,0)]:null}}if(!(o<Dr)||!(r>0))return null;let a=e.risk.cooldownBars,i=Math.floor(a/2);return{rule:"time_in_market",severity:Math.min(1,(Dr-o)/Dr)*.5,observation:`in market only ${o.toFixed(1)}% of bars while buy-and-hold returned ${Q(r)}`,suggestion:a>0?`lower risk.cooldownBars from ${a} to ${i} to sit out less of the move`:"sat out most of the move; entry rules are too strict",patch:a>0&&i!==a?[Ie("/risk/cooldownBars",a,i)]:null}}var Ga=[Ba,Da,Ua,za,Va,Ja,Wa];function Ka({label:e,returnPct:t,buyAndHoldPct:r,tradeCount:n,beatsHold:o}){return n===0?`${e} never traded (0 trades); buy-and-hold ${Q(r)} wins by default`:t<0?o?`${e} lost ${Math.abs(t).toFixed(2)}%; buy-and-hold lost ${Math.abs(r).toFixed(2)}%, so ${e} lost less but still did not make money`:`${e} lost ${Math.abs(t).toFixed(2)}% vs market; buy-and-hold ${Q(r)} still wins`:o?`${e} made ${Q(t)} vs buy-and-hold ${Q(r)} on these bars; past bars only, not a forecast`:`${e} made ${Q(t)} but buy-and-hold ${Q(r)} still wins`}function Oo(e){if(!Ae(e))throw new TypeError("reflectOnBacktest expects an object");let{strategy:t,bars:r,version:n=1,backtest:o=ee,backtestOptions:a}=e;if(!Number.isInteger(n)||n<1)throw new TypeError("version must be an integer >= 1");if(typeof o!="function")throw new TypeError("backtest must be a function");Vr(r);let i=G(t),s=e.result??o(i,r,a??{});if(!Ae(s)||!Ae(s.metrics)||!Array.isArray(s.trades))throw new TypeError("backtest result must contain metrics and trades");let c=s.trades,f=s.metrics.netPnlPct,u=Jr(r);if(!yt(f))throw new TypeError("metrics.netPnlPct must be finite");let l=c.length>0&&f>u,h=`V${n}`,p={strategy:i,bars:r,result:s,trades:c,buyAndHoldPct:u},d=[];for(let w of Ga){let A=w(p);A&&d.push(A)}d.sort((w,A)=>A.severity-w.severity||(w.rule<A.rule?-1:w.rule>A.rule?1:0));let m=d.find(w=>Array.isArray(w.patch)&&w.patch.length>0)||null,y=l||!m?null:m.patch,b={reflectionVersion:zr,version:n,label:h,strategyId:i.id,strategyHash:de(i),barsHash:typeof s.barsHash=="string"?s.barsHash:null,barCount:r.length,returnPct:f,buyAndHoldPct:u,beatsHold:l,outcome:c.length===0?"no_trades":f<0?"loser":l?"beat_hold":"trailed_hold",profitFactor:s.metrics.profitFactor,maxDrawdownPct:s.metrics.maxDrawdownPct,tradeCount:c.length,winRate:s.metrics.winRate,exposurePct:s.metrics.exposurePct,verdict:Ka({label:h,returnPct:f,buyAndHoldPct:u,tradeCount:c.length,beatsHold:l}),critiques:d.map(w=>({rule:w.rule,severity:Bt(w.severity),observation:w.observation,suggestion:w.suggestion,patchable:Array.isArray(w.patch)&&w.patch.length>0})),topCritique:m?m.rule:null,nextVersionPatch:y};return qt(b)}function Ya(e){if(!Ae(e))throw new TypeError("iterateStrategy expects an object");let{strategy:t,bars:r,maxVersions:n=To,backtest:o=ee,backtestOptions:a}=e;if(!Number.isInteger(n)||n<1||n>20)throw new TypeError("maxVersions must be an integer in [1, 20]");Vr(r);let i=G(t),s=new Set,c=[],f="max_versions";for(let d=1;d<=n;d++){let m=de(i);if(s.has(m)){f="patch_cycle";break}s.add(m);let y=Oo({strategy:i,bars:r,version:d,backtest:o,backtestOptions:a});if(c.push({version:d,strategy:i,reflection:y}),y.beatsHold){f="beats_hold";break}if(!y.nextVersionPatch){f="no_suggestion";break}if(d===n)break;let b;try{b=Ao(i,y.nextVersionPatch)}catch{f="patch_invalid";break}i=b}let u=Jr(r),l=c[0];for(let d of c)d.reflection.returnPct>l.reflection.returnPct&&(l=d);let h=c.some(d=>d.reflection.beatsHold),p=h?`${l.reflection.label} beat buy-and-hold on these bars (${Q(l.reflection.returnPct)} vs ${Q(u)}); past bars only`:`no version beat buy-and-hold ${Q(u)}; best was ${l.reflection.label} at ${Q(l.reflection.returnPct)}`;return qt({reflectionVersion:zr,buyAndHoldPct:u,barCount:r.length,versions:c,bestVersion:l.version,anyBeatsHold:h,stopReason:f,summary:p})}function ko(e){switch(e.outcome){case"beat_hold":return"BEAT HOLD";case"loser":return"LOSER";case"no_trades":return"NO TRADES";default:return"TRAILED HOLD"}}function Za(e){if(!Ae(e))throw new TypeError("renderReflectionCard expects a reflection or iteration result");let t=[];if(Array.isArray(e.versions)){t.push("Strategy iteration");for(let n of e.versions){let o=n.reflection;if(t.push(`${o.label} [${ko(o)}] ${Q(o.returnPct)} vs hold ${Q(o.buyAndHoldPct)} | PF ${Ft(o.profitFactor)} | DD ${Ft(o.maxDrawdownPct)}% | ${o.tradeCount} trades`),t.push(` ${o.verdict}`),o.topCritique&&o.nextVersionPatch){let a=o.nextVersionPatch[0];t.push(` next: ${a.path} ${String(a.from)} -> ${String(a.value)} (${o.topCritique})`)}}return t.push(e.summary),t.push(`Backtest on ${e.barCount} bars. Past bars, not a forecast. Stopped: ${e.stopReason}.`),t.join(`
|
|
3
|
+
`).replace(/\*\*/g,"")}let r=e;if(t.push(`Strategy reflection ${r.label} [${ko(r)}]`),t.push(r.verdict),t.push(`Return ${Q(r.returnPct)} | Buy-and-hold ${Q(r.buyAndHoldPct)} | PF ${Ft(r.profitFactor)} | Max DD ${Ft(r.maxDrawdownPct)}% | ${r.tradeCount} trades`),r.critiques.length?(t.push("Critiques:"),r.critiques.forEach((n,o)=>{t.push(`${o+1}. ${n.rule}: ${n.observation} -> ${n.suggestion}`)})):t.push("Critiques: none triggered"),r.nextVersionPatch){let n=r.nextVersionPatch[0];t.push(`Next V${r.version+1} patch: ${n.op} ${n.path} ${String(n.from)} -> ${String(n.value)}`)}else t.push(r.beatsHold?"No patch: this version already beat buy-and-hold on these bars":"No patch: no deterministic suggestion");return t.push(`Backtest on ${r.barCount} bars. Past bars, not a forecast.`),t.join(`
|
|
4
|
+
`).replace(/\*\*/g,"")}import Oe from"node:fs";import Dt from"node:path";var Kr=1,Xa=["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 ye(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Qa(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function tt(e,t="record"){if(Array.isArray(e)){e.forEach((r,n)=>tt(r,`${t}[${n}]`));return}if(Ut(e))for(let[r,n]of Object.entries(e)){let o=Qa(r);if(Xa.some(a=>o.includes(a)))throw new Error(`shadow-store: forbidden secret-like field at ${t}.${r}`);tt(n,`${t}.${r}`)}}function ec(e){if(typeof e!="string"||!e||!Dt.isAbsolute(e))throw new Error("shadow-store: path must be an absolute path")}function vo(e){let t;try{t=Oe.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 tc(){return{version:Kr,runners:[]}}function Po(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!==Kr)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 tt(r,Dt.basename(t)),{version:Kr,runners:r.runners.map(n=>ye(n))}}function $o(e,t){tt(t,"store");let r=Dt.dirname(e);Oe.mkdirSync(r,{recursive:!0,mode:448});let n=Dt.join(r,`.shadow-store.${process.pid}.${Date.now()}.tmp`),o=`${JSON.stringify(t)}
|
|
5
|
+
`;try{Oe.writeFileSync(n,o,{mode:384,flag:"wx"}),Oe.renameSync(n,e);try{Oe.chmodSync(e,384)}catch{}}catch(a){try{Oe.unlinkSync(n)}catch{}throw a}}var Gr=new Map;function Yr(e={}){let t=e.path;if(ec(t),vo(t),Oe.existsSync(t)?Po(Oe.readFileSync(t,"utf8"),t):$o(t,tc()),Gr.has(t))return Gr.get(t);let r=!1,n=[];function o(){if(r)return;let d=n.shift();if(d){r=!0;try{let m=d.fn();r=!1,d.resolve(m),o()}catch(m){r=!1,d.reject(m),o()}}}function a(d){if(!r&&n.length===0){r=!0;try{return d()}finally{r=!1,queueMicrotask(o)}}return new Promise((m,y)=>{n.push({fn:d,resolve:m,reject:y}),queueMicrotask(o)})}function i(){return vo(t),Po(Oe.readFileSync(t,"utf8"),t)}function s(d){$o(t,d)}function c(d){if(!Ut(d)||typeof d.id!="string"||!d.id)throw new Error("shadow-store: create requires record with string id");tt(d,"record");let m=i();if(m.runners.some(b=>b.id===d.id))throw new Error(`shadow-store: runner id already exists: ${d.id}`);let y=ye(d);return m.runners.push(y),s(m),ye(y)}function f(d){let m=i().runners.find(y=>y.id===d);return m?ye(m):null}function u(){return i().runners.map(d=>ye(d))}function l(d,m){if(typeof m!="function")throw new Error("shadow-store: updater must be a function");let y=i(),b=y.runners.findIndex(E=>E.id===d);if(b<0)throw new Error(`shadow-store: runner not found: ${d}`);let w=ye(y.runners[b]),A=m(w);if(!Ut(A)||A.id!==d)throw new Error("shadow-store: updater must return record with same id");return tt(A,"record"),y.runners[b]=ye(A),s(y),ye(y.runners[b])}function h(d){let m=i(),y=m.runners.findIndex(w=>w.id===d);if(y<0)throw new Error(`shadow-store: runner not found: ${d}`);let b=ye(m.runners[y]);return b.status!=="stopped"&&(b.status="stopped",m.runners[y]=b,s(m)),ye(m.runners[y])}let p={create(d){return a(()=>c(d))},get(d){return f(d)},list(){return u()},update(d,m){return a(()=>l(d,m))},stop(d){return a(()=>h(d))}};return Gr.set(t,p),p}fe();import{createHash as Qr}from"node:crypto";function Zr(e){return e==null?e:JSON.parse(JSON.stringify(e))}function Xr(e){return Array.isArray(e)?e.map(Xr):e&&typeof e=="object"?Object.fromEntries(Object.keys(e).sort().map(t=>[t,Xr(e[t])])):e}function Io(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("shadow-runner: record must be an object");return Qr("sha256").update(JSON.stringify(Xr(e))).digest("hex")}function rc(e,t,r,n,o){return Qr("sha256").update(`${e}|${t}|${r}|${n}|${o}`).digest("hex")}function nc(e,t,r,n){return Qr("sha256").update(`shadow|${e}|${t}|${r}|${n??""}`).digest("hex")}function oc(e){return e==="entryLong"||e==="exitShort"?"buy":e==="entryShort"||e==="exitLong"?"sell":e}function _o(e){return e==="entryLong"||e==="entryShort"}function zt({storePath:e,clock:t=Date.now}={}){if(typeof e!="string"||!e)throw new Error("shadow-runner: storePath required");let r=Yr({path:e});function n({strategy:c,evidenceId:f=null}={}){let u=Y(c),l=f==null?null:String(f),h=r.list().filter(b=>b.status==="running"&&b.strategyHash===u.strategyHash&&b.compilerHash===u.compilerHash&&b.evidenceId===l).sort((b,w)=>b.createdAt-w.createdAt||b.id.localeCompare(w.id))[0];if(h)return Zr(h);let p=t(),d=nc(p,u.strategyHash,u.compilerHash,l),m=r.get(d);if(m)return Zr(m);let y={id:d,strategy:Zr(u.strategy),strategyHash:u.strategyHash,compilerHash:u.compilerHash,evidenceId:l,status:"running",cursor:null,intendedOrders:[],fills:[],missedFills:[],markouts:[],createdAt:p,updatedAt:p,position:null,cooldownBarsRemaining:0,cooldownStartT:null,lastProcessedBarIndex:-1};return r.create(y)}function o(c){return r.get(c)}function a(){return r.list()}function i(c){return r.stop(c)}function s(c,f,{markoutHorizons:u=[1,4,12]}={}){if(!Array.isArray(f))throw new TypeError("shadow-runner: bars must be an array");return r.update(c,l=>{if(l.status!=="running")throw new Error("shadow-runner: runner is stopped");if(f.length===0)return l;let p=Y(l.strategy).evaluateAll(f),d=new Map;for(let x=0;x<f.length;x++)d.set(f[x].t,x);let m=l.cursor,y=[];for(let x=0;x<f.length;x++){let N=f[x].t;(m==null||N>m)&&y.push(x)}if(y.length===0)return l;let b=new Map(l.intendedOrders.map(x=>[x.id,x])),w=new Set(l.fills.map(x=>x.orderId)),A=new Map(l.missedFills.map(x=>[x.orderId,x])),E=(x,N)=>`${x}|${N}`,v=new Map(l.markouts.map(x=>[E(x.orderId,x.horizon),x])),O=l.position?{...l.position}:null,g=Number.isInteger(l.cooldownBarsRemaining)?Math.max(0,l.cooldownBarsRemaining):0,M=Number.isFinite(l.cooldownStartT)?l.cooldownStartT:null;function q({action:x,signalBarT:N,signalIndex:T}){let C=oc(x),L=rc(l.id,l.strategyHash,N,C,x);if(b.has(L))return b.get(L);let j=T+1,$=j<f.length,R={id:L,action:x,type:x,side:C,signalBarT:N,fillBarT:$?f[j].t:null,status:$?"open":"missed"};return b.set(L,R),l.intendedOrders.push(R),R}function z(x,N,T){if(w.has(x.id))return;let C={orderId:x.id,action:_o(x.action)?"entry":"exit",side:x.side,price:N.o,barT:N.t,signalBarT:x.signalBarT,barIndex:T};if(l.fills.push(C),w.add(x.id),x.status="filled",x.fillBarT=N.t,A.has(x.id)&&(A.delete(x.id),l.missedFills=l.missedFills.filter(L=>L.orderId!==x.id)),_o(x.action)){O={side:x.action==="entryLong"?"long":"short",entryOrderId:x.id,entryBarT:N.t,entryPrice:N.o,entryBarIndex:T};for(let L of u){let j=E(x.id,L);if(v.has(j))continue;let $={orderId:x.id,horizon:L,entryBarT:N.t,entryPrice:N.o,side:O.side,status:"pending",close:null,barT:null};v.set(j,$),l.markouts.push($)}}else O=null,g=Number(l.strategy?.risk?.cooldownBars)||0,M=N.t}function P(x){if(w.has(x.id)||A.has(x.id))return;let N={orderId:x.id,action:x.action,side:x.side,signalBarT:x.signalBarT,status:"missed"};A.set(x.id,N),l.missedFills.push(N),x.status="missed"}for(let x of l.intendedOrders){if(x.status==="filled"||w.has(x.id))continue;let N=d.get(x.signalBarT);if(N==null)continue;let T=N+1;T<f.length&&(m==null||f[T].t>m)&&z(x,f[T],T)}for(let x of y){let N=f[x],T=p[x].signals,C=O,L=$=>{if(O||g>0&&(M==null||N.t>=M))return;let I=q({action:$,signalBarT:N.t,signalIndex:x}),re=x+1;re<f.length?z(I,f[re],re):P(I)},j=$=>{if(!O||O.side==="long"&&$!=="exitLong"||O.side==="short"&&$!=="exitShort")return;let R=q({action:$,signalBarT:N.t,signalIndex:x}),I=x+1;I<f.length?z(R,f[I],I):P(R)};C?(T.exitLong&&j("exitLong"),T.exitShort&&j("exitShort")):T.entryLong&&T.entryShort||(T.entryLong&&L("entryLong"),T.entryShort&&L("entryShort")),g>0&&M!=null&&N.t>=M&&(g-=1,g===0&&(M=null)),l.cursor=N.t,l.lastProcessedBarIndex=x}for(let x of l.markouts){if(x.status!=="pending")continue;let N=l.fills.find(L=>L.orderId===x.orderId&&L.action==="entry");if(!N)continue;let T=d.get(N.barT);if(T==null)continue;let C=T+x.horizon;if(C<f.length){x.close=f[C].c,x.barT=f[C].t,x.status="filled";let L=x.entryPrice;x.markout=x.side==="long"?(x.close-L)/L:(L-x.close)/L}}return l.position=O,l.cooldownBarsRemaining=g,l.cooldownStartT=M,l.updatedAt=t(),l})}return{start:n,step:s,list:a,get:o,stop:i}}_r();Ce();fe();It();import Tc from"node:os";import Ac from"node:path";jt();Vt();var Oc=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Et(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function vc(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function hn(e){if(Array.isArray(e)){for(let t of e)hn(t);return}if(Et(e))for(let[t,r]of Object.entries(e)){if(Oc.some(n=>vc(t).includes(n)))throw new Error(`strategy service: secret-like field "${t}" is forbidden`);hn(r)}}function Pc(e){if(!Et(e))throw new TypeError("strategy input must be a plain object");return hn(e),e}function $c(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 pn(e,t,r,n){if(Array.isArray(t.bars))return t.bars;let o=Nt(e.venue),a=r.fetchBars??o.fetchBars;if(typeof a!="function")throw new Error(`strategy venue ${o.id} does not support history`);r.signal?.throwIfAborted?.();let i=await a({coin:e.market.coin,interval:e.market.interval,count:t.count??1500,endTime:t.endTime??n},{signal:r.signal});r.signal?.throwIfAborted?.();let s=Array.isArray(i)?i:i?.bars;if(!Array.isArray(s))throw new Error("strategy history provider returned no bars");return s}function mn(e,t){let r=e.backtestOptions??{};if(!Et(r))throw new TypeError("backtestOptions must be a plain object");return{...r,nowMs:t}}function ei(e,t,r,n,o={}){let a=e.evidenceOptions??{};if(!Et(a))throw new TypeError("evidenceOptions must be a plain object");return{...a,...o,strategy:t,bars:r,backtestOptions:mn(e,n)}}function ti(){return Ac.join(Tc.homedir(),".oracle","strategy-shadow.json")}function _c(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 Ic(e,t={},r={}){r.signal?.throwIfAborted?.();let n=Pc(e==="collect"||e==="infer"?rt(t,{omitUndefined:!0}):t),o=$c(n,r);if(e==="collect"||e==="infer"){let{runWalletStrategyOperation:a}=await Promise.resolve().then(()=>(Qo(),Xo));return a(e,n,{...r,nowMs:o})}if(e==="draft")return{strategy:Br(n.prompt,{nowMs:o})};if(e==="validate"){let a=Y(n.strategy);if(a.strategy.risk.expiresAt<=o)throw new Error("strategy is expired");return{valid:!0,strategy:a.strategy,strategyHash:a.strategyHash,compilerHash:a.compilerHash,compilerVersion:a.compilerVersion,requiredSeries:a.requiredSeries}}if(e==="backtest"||e==="evidence"){let a=Y(n.strategy),i=await pn(a.strategy,n,r,o);ft(a,i);let s=_t(ei(n,a.strategy,i,o));return e==="evidence"?s:{backtest:ee(a.strategy,i,mn(n,o)),evidence:s}}if(e==="optimize"){let a=Y(n.strategy),i=await pn(a.strategy,n,r,o);ft(a,i);let s=n.trainFraction,c=n.evidenceOptions?.trainFraction;if(s!=null&&c!=null&&s!==c)throw new TypeError("conflicting trainFraction controls are forbidden");let f=s??c??.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)),l=n.options??{};if(!Et(l))throw new TypeError("options must be a plain object");let h=Fr(a.strategy,u,{...l,...n.maxTrials==null?{}:{maxTrials:n.maxTrials},backtestOptions:mn(n,o)}),p=h.bestStrategy;return{strategy:p,optimization:h,evidence:_t(ei(n,p,i,o,{trainFraction:f}))}}if(e==="shadow"){let a=zt({storePath:r.storePath??ti(),clock:()=>o}),i=n.action;if(i==="start")return await a.start({strategy:n.strategy,evidenceId:n.evidenceId??n.evidence?.id??null});if(i==="list")return await a.list();if(i==="get")return await a.get(n.id);if(i==="stop")return await a.stop(n.id);if(i==="step"){let s=await a.get(n.id);if(!s)throw new Error(`shadow runner not found: ${n.id}`);let c=await pn(s.strategy,n,r,o);return ft(Y(s.strategy),c),await a.step(n.id,c,n.stepOptions??{})}throw new Error(`unknown shadow action: ${i}`)}if(e==="prepare"){let a=Y(n.strategy),i=Nt(a.strategy.venue);if(typeof n.shadowId!="string"||!n.shadowId)throw new Error("strategy prepare requires a matching shadow runner id");let c=await zt({storePath:r.storePath??ti(),clock:()=>o}).get(n.shadowId);if(!c)throw new Error("strategy prepare shadow runner not found");if(c.status!=="running")throw new Error("strategy prepare requires an active shadow runner");if(!Number.isFinite(c.cursor))throw new Error("strategy prepare requires a stepped shadow runner");if(c.strategyHash!==a.strategyHash||c.compilerHash!==a.compilerHash)throw new Error("strategy prepare shadow runner does not match strategy artifacts");if(c.evidenceId!==n.evidence?.id)throw new Error("strategy prepare shadow runner does not match evidence artifact");let f=n.caps??_c(a.strategy,o);return i.prepareIntent({strategy:a.strategy,evidence:n.evidence,shadow:{id:c.id,stateHash:Io(c),status:c.status,cursor:c.cursor,updatedAt:c.updatedAt},caps:f,nowMs:o,env:r.env??process.env})}throw new Error(`unknown strategy operation: ${e}`)}gt();ln();dn();Kt();jt();export{To as DEFAULT_MAX_VERSIONS,Jn as EVIDENCE_STATUSES,Hr as MAX_OPTIMIZER_TRIALS,zr as REFLECTION_VERSION,ue as STRATEGY_COMPILER_HASH,We as STRATEGY_COMPILER_VERSION,Mt as STRATEGY_VERSION,Z as StrategyDraftError,qe as StrategyValidationError,X as WALLET_TRIAL_LIMITS,Ge as applyParameterOverrides,Ao as applyStrategyPatch,Ar as assertEvidenceArtifact,yr as atr,oa as attachDerivedSeries,ee as backtestStrategy,mr as bollinger,nn as buildWalletCandidateTrials,Jr as buyAndHoldReturnPct,mo as canonicalStrategyJson,zo as collectWalletHistory,Y as compileStrategy,Tr as computeEvidenceArtifactId,zt as createShadowRunner,na as deriveSeries,Br as draftStrategyFromPrompt,lt as ema,_t as evaluateEvidence,ht as fetchHyperliquidStrategyBars,Go as inferWalletStrategy,$e as intervalToMs,Ya as iterateStrategy,hr as macd,Xn as normalizeHyperliquidCandles,G as normalizeStrategy,De as normalizeWalletHistory,Yr as openShadowStore,Fr as optimizeStrategy,$r as prepareStrategyLiveHandoff,Xt as reconstructWalletEpisodes,Oo as reflectOnBacktest,Za as renderReflectionCard,Nt as requireStrategyVenue,Rt as resolveStrategyVenue,pr as rsi,Ic as runStrategyOperation,ra as sampleLiveSeries,dr as sma,de as strategyHash,Bs as strategyVenues,Ht as validateStrategy};
|