@invinite-org/chartlang-runtime 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +71 -0
- package/dist/buildComputeContext.d.ts.map +1 -1
- package/dist/buildComputeContext.js +6 -1
- package/dist/buildComputeContext.js.map +1 -1
- package/dist/createScriptRunner.d.ts.map +1 -1
- package/dist/createScriptRunner.js +37 -7
- package/dist/createScriptRunner.js.map +1 -1
- package/dist/dep/DepRunner.d.ts +7 -0
- package/dist/dep/DepRunner.d.ts.map +1 -1
- package/dist/dep/DepRunner.js +3 -0
- package/dist/dep/DepRunner.js.map +1 -1
- package/dist/emit/barcolor.d.ts +44 -0
- package/dist/emit/barcolor.d.ts.map +1 -0
- package/dist/emit/barcolor.js +40 -0
- package/dist/emit/barcolor.js.map +1 -0
- package/dist/emit/bgcolor.d.ts +44 -0
- package/dist/emit/bgcolor.d.ts.map +1 -0
- package/dist/emit/bgcolor.js +45 -0
- package/dist/emit/bgcolor.js.map +1 -0
- package/dist/emit/index.d.ts +2 -0
- package/dist/emit/index.d.ts.map +1 -1
- package/dist/emit/index.js +2 -0
- package/dist/emit/index.js.map +1 -1
- package/dist/emit/plot.d.ts +23 -1
- package/dist/emit/plot.d.ts.map +1 -1
- package/dist/emit/plot.js +32 -1
- package/dist/emit/plot.js.map +1 -1
- package/dist/execution/dispose.d.ts.map +1 -1
- package/dist/execution/dispose.js +3 -1
- package/dist/execution/dispose.js.map +1 -1
- package/dist/execution/runComputeStep.d.ts.map +1 -1
- package/dist/execution/runComputeStep.js +3 -1
- package/dist/execution/runComputeStep.js.map +1 -1
- package/dist/inputs/resolveInputs.js +1 -0
- package/dist/inputs/resolveInputs.js.map +1 -1
- package/dist/persistentStateStore.runtime.d.ts.map +1 -1
- package/dist/persistentStateStore.runtime.js +10 -5
- package/dist/persistentStateStore.runtime.js.map +1 -1
- package/dist/primitives.d.ts +1 -1
- package/dist/primitives.d.ts.map +1 -1
- package/dist/primitives.js +7 -1
- package/dist/primitives.js.map +1 -1
- package/dist/request/lowerTf.d.ts.map +1 -1
- package/dist/request/lowerTf.js +6 -0
- package/dist/request/lowerTf.js.map +1 -1
- package/dist/request/requestNamespace.d.ts.map +1 -1
- package/dist/request/requestNamespace.js +17 -3
- package/dist/request/requestNamespace.js.map +1 -1
- package/dist/request/security.d.ts +23 -6
- package/dist/request/security.d.ts.map +1 -1
- package/dist/request/security.js +64 -29
- package/dist/request/security.js.map +1 -1
- package/dist/request/securityExprRunner.d.ts +12 -8
- package/dist/request/securityExprRunner.d.ts.map +1 -1
- package/dist/request/securityExprRunner.js +32 -14
- package/dist/request/securityExprRunner.js.map +1 -1
- package/dist/ringBuffer.d.ts +19 -0
- package/dist/ringBuffer.d.ts.map +1 -1
- package/dist/ringBuffer.js +23 -0
- package/dist/ringBuffer.js.map +1 -1
- package/dist/runtimeContext.d.ts +49 -12
- package/dist/runtimeContext.d.ts.map +1 -1
- package/dist/runtimeContext.js.map +1 -1
- package/dist/state/arrayPersistence.d.ts +48 -0
- package/dist/state/arrayPersistence.d.ts.map +1 -0
- package/dist/state/arrayPersistence.js +88 -0
- package/dist/state/arrayPersistence.js.map +1 -0
- package/dist/state/arrayStateSlot.d.ts +78 -0
- package/dist/state/arrayStateSlot.d.ts.map +1 -0
- package/dist/state/arrayStateSlot.js +116 -0
- package/dist/state/arrayStateSlot.js.map +1 -0
- package/dist/state/index.d.ts +3 -1
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +3 -1
- package/dist/state/index.js.map +1 -1
- package/dist/state/lifecycle.d.ts +28 -0
- package/dist/state/lifecycle.d.ts.map +1 -1
- package/dist/state/lifecycle.js +36 -0
- package/dist/state/lifecycle.js.map +1 -1
- package/dist/state/stateNamespace.d.ts.map +1 -1
- package/dist/state/stateNamespace.js +27 -0
- package/dist/state/stateNamespace.js.map +1 -1
- package/dist/ta/sessionVolumeProfile.d.ts.map +1 -1
- package/dist/ta/sessionVolumeProfile.js +1 -17
- package/dist/ta/sessionVolumeProfile.js.map +1 -1
- package/dist/time-accessors/civil.d.ts +73 -0
- package/dist/time-accessors/civil.d.ts.map +1 -0
- package/dist/time-accessors/civil.js +105 -0
- package/dist/time-accessors/civil.js.map +1 -0
- package/dist/time-accessors/index.d.ts +8 -0
- package/dist/time-accessors/index.d.ts.map +1 -0
- package/dist/time-accessors/index.js +9 -0
- package/dist/time-accessors/index.js.map +1 -0
- package/dist/time-accessors/sessionAccessors.d.ts +50 -0
- package/dist/time-accessors/sessionAccessors.d.ts.map +1 -0
- package/dist/time-accessors/sessionAccessors.js +79 -0
- package/dist/time-accessors/sessionAccessors.js.map +1 -0
- package/dist/time-accessors/sessionWindow.d.ts +17 -0
- package/dist/time-accessors/sessionWindow.d.ts.map +1 -0
- package/dist/time-accessors/sessionWindow.js +41 -0
- package/dist/time-accessors/sessionWindow.js.map +1 -0
- package/dist/time-accessors/timeAccessors.d.ts +54 -0
- package/dist/time-accessors/timeAccessors.d.ts.map +1 -0
- package/dist/time-accessors/timeAccessors.js +132 -0
- package/dist/time-accessors/timeAccessors.js.map +1 -0
- package/dist/time-accessors/tzDiagnostic.d.ts +17 -0
- package/dist/time-accessors/tzDiagnostic.d.ts.map +1 -0
- package/dist/time-accessors/tzDiagnostic.js +34 -0
- package/dist/time-accessors/tzDiagnostic.js.map +1 -0
- package/dist/time-accessors/tzOffset.d.ts +31 -0
- package/dist/time-accessors/tzOffset.d.ts.map +1 -0
- package/dist/time-accessors/tzOffset.js +67 -0
- package/dist/time-accessors/tzOffset.js.map +1 -0
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/request/security.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { SecurityBar, Series } from \"@invinite-org/chartlang-core\";\n\nimport type { RuntimeContext } from \"../runtimeContext.js\";\nimport type { StreamState } from \"../streamState.js\";\nimport { getOrAlign } from \"./alignHtfSeriesCache.js\";\nimport { pushOnce } from \"./pushOnce.js\";\nimport { type SecurityExprRunner, ascendingValues } from \"./securityExprRunner.js\";\nimport { ascendingBarsFor, makeConstantStringSeries } from \"./streamBars.js\";\n\ntype NumericSourceKey =\n | \"time\"\n | \"open\"\n | \"high\"\n | \"low\"\n | \"close\"\n | \"volume\"\n | \"hl2\"\n | \"hlc3\"\n | \"ohlc4\"\n | \"hlcc4\";\n\nconst NUMERIC_SOURCE_KEYS: ReadonlyArray<NumericSourceKey> = Object.freeze([\n \"time\",\n \"open\",\n \"high\",\n \"low\",\n \"close\",\n \"volume\",\n \"hl2\",\n \"hlc3\",\n \"ohlc4\",\n \"hlcc4\",\n]);\n\nfunction makeSeries<T>(current: T): Series<T> {\n return Object.freeze({ current, length: 0 }) as Series<T>;\n}\n\n/**\n * Build the all-NaN `SecurityBar` fallback for unsupported MTF paths.\n *\n * @since 0.4\n * @stable\n * @example\n * const bar = makeNanSecurityBar();\n * const close = bar.close.current;\n * void close;\n */\nexport function makeNanSecurityBar(): SecurityBar {\n const nanNumberSeries = makeSeries(Number.NaN);\n const nanStringSeries = makeSeries(\"\");\n return Object.freeze({\n time: nanNumberSeries,\n open: nanNumberSeries,\n high: nanNumberSeries,\n low: nanNumberSeries,\n close: nanNumberSeries,\n volume: nanNumberSeries,\n hl2: nanNumberSeries,\n hlc3: nanNumberSeries,\n ohlc4: nanNumberSeries,\n hlcc4: nanNumberSeries,\n symbol: nanStringSeries,\n interval: nanStringSeries,\n });\n}\n\nfunction seriesAscending(stream: StreamState, sourceKey: NumericSourceKey): ReadonlyArray<number> {\n const values: number[] = [];\n const source = stream.ohlcv[sourceKey];\n for (let age = source.length - 1; age >= 0; age -= 1) {\n values.push(source.at(age));\n }\n return values;\n}\n\nfunction alignmentKey(slotId: string, interval: string, sourceKey: NumericSourceKey): string {\n return `${slotId}|${interval}|${sourceKey}`;\n}\n\nfunction alignedSeries(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n sourceKey: NumericSourceKey,\n secondary: StreamState,\n): ReadonlyArray<number> {\n const key = alignmentKey(slotId, interval, sourceKey);\n const existing = ctx.requestSecurityAlignments.get(key);\n if (existing !== undefined) return existing;\n const htfBars = ascendingBarsFor(ctx, secondary);\n const ltfBars = ascendingBarsFor(ctx, ctx.stream);\n const aligned = getOrAlign(htfBars, seriesAscending(secondary, sourceKey), ltfBars);\n ctx.requestSecurityAlignments.set(key, aligned);\n return aligned;\n}\n\n/**\n * Wrap a producer of the latest main-aligned array in the head-relative\n * `Series<number>` Proxy shape. `current` / `[n]` re-run `produce` (cheap —\n * `getOrAlign` memoises per bar) and read from the tail; `length` is the main\n * stream's bar count. Shared by the OHLCV `SecurityBar` fields and the\n * expression-output series so both walk the identical no-lookahead alignment.\n */\nfunction makeAlignedSeriesProxy(\n ctx: RuntimeContext,\n produce: () => ReadonlyArray<number>,\n): Series<number> {\n const target = {\n get current() {\n const aligned = produce();\n const value = aligned[aligned.length - 1];\n return value === undefined ? Number.NaN : value;\n },\n get length() {\n return ctx.stream.ohlcv.close.length;\n },\n };\n return new Proxy(Object.freeze(target), {\n get(obj, prop, receiver) {\n if (typeof prop === \"string\") {\n const n = Number(prop);\n if (Number.isInteger(n) && n >= 0) {\n const aligned = produce();\n const value = aligned[aligned.length - 1 - n];\n return value === undefined ? Number.NaN : value;\n }\n }\n return Reflect.get(obj, prop, receiver);\n },\n }) as Series<number>;\n}\n\nfunction makeAlignedNumberSeries(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n sourceKey: NumericSourceKey,\n secondary: StreamState,\n): Series<number> {\n return makeAlignedSeriesProxy(ctx, () =>\n alignedSeries(ctx, slotId, interval, sourceKey, secondary),\n );\n}\n\nfunction makeLiveSecurityBar(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n secondary: StreamState,\n): SecurityBar {\n const numeric = new Map<NumericSourceKey, Series<number>>();\n for (const key of NUMERIC_SOURCE_KEYS) {\n numeric.set(key, makeAlignedNumberSeries(ctx, slotId, interval, key, secondary));\n }\n return Object.freeze({\n time: numeric.get(\"time\") ?? makeSeries(Number.NaN),\n open: numeric.get(\"open\") ?? makeSeries(Number.NaN),\n high: numeric.get(\"high\") ?? makeSeries(Number.NaN),\n low: numeric.get(\"low\") ?? makeSeries(Number.NaN),\n close: numeric.get(\"close\") ?? makeSeries(Number.NaN),\n volume: numeric.get(\"volume\") ?? makeSeries(Number.NaN),\n hl2: numeric.get(\"hl2\") ?? makeSeries(Number.NaN),\n hlc3: numeric.get(\"hlc3\") ?? makeSeries(Number.NaN),\n ohlc4: numeric.get(\"ohlc4\") ?? makeSeries(Number.NaN),\n hlcc4: numeric.get(\"hlcc4\") ?? makeSeries(Number.NaN),\n symbol: makeConstantStringSeries(secondary.bar.symbol),\n interval: makeConstantStringSeries(interval),\n });\n}\n\nfunction fallbackNaN(\n ctx: RuntimeContext,\n cacheKey: string,\n slotId: string,\n interval: string,\n code: \"unsupported-interval\" | \"multi-timeframe-not-supported\" | \"unknown-secondary-stream\",\n message: string,\n): SecurityBar {\n pushOnce(ctx, code, slotId, interval, \"security\", message);\n const bar = makeNanSecurityBar();\n ctx.requestSecurityBars.set(cacheKey, bar);\n return bar;\n}\n\n/**\n * Return the runtime `request.security` bar for a callsite and interval.\n *\n * @since 0.5\n * @stable\n * @example\n * // const bar = makeSecurityBar(ctx, \"slot#0\", \"1D\");\n * const requested = \"1D\";\n * void requested;\n */\nexport function makeSecurityBar(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n): SecurityBar {\n const cacheKey = `${slotId}|${interval}`;\n const existing = ctx.requestSecurityBars.get(cacheKey);\n if (existing !== undefined) return existing;\n\n if (!ctx.capabilities.multiTimeframe) {\n return fallbackNaN(\n ctx,\n cacheKey,\n slotId,\n interval,\n \"multi-timeframe-not-supported\",\n \"Adapter declares multiTimeframe: false; request.security returns NaN\",\n );\n }\n\n const known = ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval);\n if (!known) {\n return fallbackNaN(\n ctx,\n cacheKey,\n slotId,\n interval,\n \"unsupported-interval\",\n `Requested interval \"${interval}\" is not in Capabilities.intervals`,\n );\n }\n\n const secondary = ctx.secondaryStreams.get(interval);\n if (secondary === undefined) {\n return fallbackNaN(\n ctx,\n cacheKey,\n slotId,\n interval,\n \"unknown-secondary-stream\",\n `Requested interval \"${interval}\" has no registered secondary stream`,\n );\n }\n\n const bar = makeLiveSecurityBar(ctx, slotId, interval, secondary);\n ctx.requestSecurityBars.set(cacheKey, bar);\n return bar;\n}\n\nfunction makeNanNumberSeries(): Series<number> {\n return makeSeries(Number.NaN);\n}\n\nfunction resolveSecondaryOrDiagnose(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n): StreamState | undefined {\n if (!ctx.capabilities.multiTimeframe) {\n pushOnce(\n ctx,\n \"multi-timeframe-not-supported\",\n slotId,\n interval,\n \"security\",\n \"Adapter declares multiTimeframe: false; request.security returns NaN\",\n );\n return undefined;\n }\n if (!ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval)) {\n pushOnce(\n ctx,\n \"unsupported-interval\",\n slotId,\n interval,\n \"security\",\n `Requested interval \"${interval}\" is not in Capabilities.intervals`,\n );\n return undefined;\n }\n const secondary = ctx.secondaryStreams.get(interval);\n if (secondary === undefined) {\n pushOnce(\n ctx,\n \"unknown-secondary-stream\",\n slotId,\n interval,\n \"security\",\n `Requested interval \"${interval}\" has no registered secondary stream`,\n );\n }\n return secondary;\n}\n\n/**\n * Return the main-aligned output series for an HTF expression callsite. The\n * runner's `output` buffer holds one sampled value per HTF bar; this aligns it\n * no-lookahead to the main timeline against the real secondary stream's\n * timestamps (so `output[i]` pairs with secondary ascending bar `i`). Reuses\n * the OHLCV alignment kernel via {@link getOrAlign}. Capability / interval /\n * stream fallbacks return an all-NaN series and push a deduped diagnostic,\n * matching {@link makeSecurityBar}. The returned Proxy identity is cached per\n * `slotId|interval` for the bar.\n *\n * @since 0.7\n * @stable\n * @example\n * // const trend = makeSecurityExprSeries(ctx, runner, \"1W\");\n * const requested = \"1W\";\n * void requested;\n */\nexport function makeSecurityExprSeries(\n ctx: RuntimeContext,\n runner: SecurityExprRunner,\n interval: string,\n): Series<number> {\n const cacheKey = `${runner.slotId}|${interval}`;\n const cache = ctx.requestSecurityExprSeries;\n const existing = cache?.get(cacheKey);\n if (existing !== undefined) return existing;\n\n const secondary = resolveSecondaryOrDiagnose(ctx, runner.slotId, interval);\n const series =\n secondary === undefined\n ? makeNanNumberSeries()\n : makeAlignedSeriesProxy(ctx, () =>\n getOrAlign(\n ascendingBarsFor(ctx, secondary),\n ascendingValues(runner.output),\n ascendingBarsFor(ctx, ctx.stream),\n ),\n );\n cache?.set(cacheKey, series);\n return series;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/request/security.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAG/D,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAIvD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAA2B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAc7E,MAAM,mBAAmB,GAAoC,MAAM,CAAC,MAAM,CAAC;IACvE,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,OAAO;IACP,QAAQ;IACR,KAAK;IACL,MAAM;IACN,OAAO;IACP,OAAO;CACV,CAAC,CAAC;AAEH,SAAS,UAAU,CAAI,OAAU;IAC7B,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,CAAc,CAAC;AAC9D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB;IAC9B,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,eAAe,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IACvC,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,eAAe;QACrB,GAAG,EAAE,eAAe;QACpB,KAAK,EAAE,eAAe;QACtB,MAAM,EAAE,eAAe;QACvB,GAAG,EAAE,eAAe;QACpB,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,eAAe;QACtB,KAAK,EAAE,eAAe;QACtB,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE,eAAe;KAC5B,CAAC,CAAC;AACP,CAAC;AAED,SAAS,eAAe,CAAC,MAAmB,EAAE,SAA2B;IACrE,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACvC,KAAK,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,YAAY,CAAC,MAAc,EAAE,IAAY,EAAE,SAA2B;IAC3E,OAAO,GAAG,MAAM,IAAI,IAAI,IAAI,SAAS,EAAE,CAAC;AAC5C,CAAC;AAED,SAAS,aAAa,CAClB,GAAmB,EACnB,MAAc,EACd,IAAY,EACZ,SAA2B,EAC3B,SAAsB;IAEtB,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,GAAG,CAAC,yBAAyB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC5C,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,EAAE,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;IACpF,GAAG,CAAC,yBAAyB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,sBAAsB,CAC3B,GAAmB,EACnB,OAAoC;IAEpC,MAAM,MAAM,GAAG;QACX,IAAI,OAAO;YACP,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC1C,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;QACpD,CAAC;QACD,IAAI,MAAM;YACN,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QACzC,CAAC;KACJ,CAAC;IACF,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;QACpC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ;YACnB,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;gBACvB,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBAChC,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC;oBAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;oBAC9C,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;gBACpD,CAAC;YACL,CAAC;YACD,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;KACJ,CAAmB,CAAC;AACzB,CAAC;AAED,SAAS,uBAAuB,CAC5B,GAAmB,EACnB,MAAc,EACd,IAAY,EACZ,SAA2B,EAC3B,SAAsB;IAEtB,OAAO,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,CACpC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CACzD,CAAC;AACN,CAAC;AAED,SAAS,mBAAmB,CACxB,GAAmB,EACnB,MAAc,EACd,IAAY,EACZ,QAAgB,EAChB,SAAsB;IAEtB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC5D,KAAK,MAAM,GAAG,IAAI,mBAAmB,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACnD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACnD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACnD,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACjD,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACrD,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACvD,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACjD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACnD,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACrD,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;QACrD,MAAM,EAAE,wBAAwB,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC;QACtD,QAAQ,EAAE,wBAAwB,CAAC,QAAQ,CAAC;KAC/C,CAAC,CAAC;AACP,CAAC;AAED,8EAA8E;AAC9E,wEAAwE;AACxE,0EAA0E;AAC1E,MAAM,gBAAgB,GAClB,0FAA0F,CAAC;AAE/F,SAAS,WAAW,CAChB,GAAmB,EACnB,QAAgB,EAChB,MAAc,EACd,IAAY,EACZ,IAIgC,EAChC,OAAe;IAEf,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;IACjC,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC3C,OAAO,GAAG,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAC3B,GAAmB,EACnB,MAAc,EACd,MAA0B,EAC1B,QAAgB;IAEhB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAE5C,4EAA4E;IAC5E,gEAAgE;IAChE,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;QACxD,OAAO,WAAW,CACd,GAAG,EACH,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,4BAA4B,EAC5B,gBAAgB,CACnB,CAAC;IACN,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC;QACnC,OAAO,WAAW,CACd,GAAG,EACH,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,+BAA+B,EAC/B,sEAAsE,CACzE,CAAC;IACN,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;IAC7F,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,WAAW,CACd,GAAG,EACH,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,sBAAsB,EACtB,uBAAuB,QAAQ,oCAAoC,CACtE,CAAC;IACN,CAAC;IAED,MAAM,SAAS,GAAG,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,WAAW,CACd,GAAG,EACH,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,0BAA0B,EAC1B,uBAAuB,QAAQ,sCAAsC,CACxE,CAAC;IACN,CAAC;IAED,MAAM,GAAG,GAAG,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IACxE,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC3C,OAAO,GAAG,CAAC;AACf,CAAC;AAED,SAAS,mBAAmB;IACxB,OAAO,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,0BAA0B,CAC/B,GAAmB,EACnB,MAAc,EACd,IAAY,EACZ,QAAgB;IAEhB,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC;QACnC,QAAQ,CACJ,GAAG,EACH,+BAA+B,EAC/B,MAAM,EACN,IAAI,EACJ,UAAU,EACV,sEAAsE,CACzE,CAAC;QACF,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;QAClF,QAAQ,CACJ,GAAG,EACH,sBAAsB,EACtB,MAAM,EACN,IAAI,EACJ,UAAU,EACV,uBAAuB,QAAQ,oCAAoC,CACtE,CAAC;QACF,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,MAAM,SAAS,GAAG,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC1B,QAAQ,CACJ,GAAG,EACH,0BAA0B,EAC1B,MAAM,EACN,IAAI,EACJ,UAAU,EACV,uBAAuB,QAAQ,sCAAsC,CACxE,CAAC;IACN,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,sBAAsB,CAClC,GAAmB,EACnB,MAA0B,EAC1B,IAAY,EACZ,iBAA0B;IAE1B,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,yBAAyB,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAE5C,uEAAuE;IACvE,IAAI,iBAAiB,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;QACrD,QAAQ,CACJ,GAAG,EACH,4BAA4B,EAC5B,MAAM,CAAC,MAAM,EACb,IAAI,EACJ,UAAU,EACV,gBAAgB,CACnB,CAAC;QACF,MAAM,GAAG,GAAG,mBAAmB,EAAE,CAAC;QAClC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC1B,OAAO,GAAG,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAG,0BAA0B,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACxF,MAAM,MAAM,GACR,SAAS,KAAK,SAAS;QACnB,CAAC,CAAC,mBAAmB,EAAE;QACvB,CAAC,CAAC,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,CAC7B,UAAU,CACN,gBAAgB,CAAC,GAAG,EAAE,SAAS,CAAC,EAChC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,EAC9B,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CACpC,CACJ,CAAC;IACZ,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC;AAClB,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { SecurityBar, Series } from \"@invinite-org/chartlang-core\";\nimport { feedKey } from \"@invinite-org/chartlang-core\";\n\nimport type { RuntimeContext } from \"../runtimeContext.js\";\nimport type { StreamState } from \"../streamState.js\";\nimport { getOrAlign } from \"./alignHtfSeriesCache.js\";\nimport { pushOnce } from \"./pushOnce.js\";\nimport { type SecurityExprRunner, ascendingValues } from \"./securityExprRunner.js\";\nimport { ascendingBarsFor, makeConstantStringSeries } from \"./streamBars.js\";\n\ntype NumericSourceKey =\n | \"time\"\n | \"open\"\n | \"high\"\n | \"low\"\n | \"close\"\n | \"volume\"\n | \"hl2\"\n | \"hlc3\"\n | \"ohlc4\"\n | \"hlcc4\";\n\nconst NUMERIC_SOURCE_KEYS: ReadonlyArray<NumericSourceKey> = Object.freeze([\n \"time\",\n \"open\",\n \"high\",\n \"low\",\n \"close\",\n \"volume\",\n \"hl2\",\n \"hlc3\",\n \"ohlc4\",\n \"hlcc4\",\n]);\n\nfunction makeSeries<T>(current: T): Series<T> {\n return Object.freeze({ current, length: 0 }) as Series<T>;\n}\n\n/**\n * Build the all-NaN `SecurityBar` fallback for unsupported MTF paths.\n *\n * @since 0.4\n * @stable\n * @example\n * const bar = makeNanSecurityBar();\n * const close = bar.close.current;\n * void close;\n */\nexport function makeNanSecurityBar(): SecurityBar {\n const nanNumberSeries = makeSeries(Number.NaN);\n const nanStringSeries = makeSeries(\"\");\n return Object.freeze({\n time: nanNumberSeries,\n open: nanNumberSeries,\n high: nanNumberSeries,\n low: nanNumberSeries,\n close: nanNumberSeries,\n volume: nanNumberSeries,\n hl2: nanNumberSeries,\n hlc3: nanNumberSeries,\n ohlc4: nanNumberSeries,\n hlcc4: nanNumberSeries,\n symbol: nanStringSeries,\n interval: nanStringSeries,\n });\n}\n\nfunction seriesAscending(stream: StreamState, sourceKey: NumericSourceKey): ReadonlyArray<number> {\n const values: number[] = [];\n const source = stream.ohlcv[sourceKey];\n for (let age = source.length - 1; age >= 0; age -= 1) {\n values.push(source.at(age));\n }\n return values;\n}\n\nfunction alignmentKey(slotId: string, feed: string, sourceKey: NumericSourceKey): string {\n return `${slotId}|${feed}|${sourceKey}`;\n}\n\nfunction alignedSeries(\n ctx: RuntimeContext,\n slotId: string,\n feed: string,\n sourceKey: NumericSourceKey,\n secondary: StreamState,\n): ReadonlyArray<number> {\n const key = alignmentKey(slotId, feed, sourceKey);\n const existing = ctx.requestSecurityAlignments.get(key);\n if (existing !== undefined) return existing;\n const htfBars = ascendingBarsFor(ctx, secondary);\n const ltfBars = ascendingBarsFor(ctx, ctx.stream);\n const aligned = getOrAlign(htfBars, seriesAscending(secondary, sourceKey), ltfBars);\n ctx.requestSecurityAlignments.set(key, aligned);\n return aligned;\n}\n\n/**\n * Wrap a producer of the latest main-aligned array in the head-relative\n * `Series<number>` Proxy shape. `current` / `[n]` re-run `produce` (cheap —\n * `getOrAlign` memoises per bar) and read from the tail; `length` is the main\n * stream's bar count. Shared by the OHLCV `SecurityBar` fields and the\n * expression-output series so both walk the identical no-lookahead alignment.\n */\nfunction makeAlignedSeriesProxy(\n ctx: RuntimeContext,\n produce: () => ReadonlyArray<number>,\n): Series<number> {\n const target = {\n get current() {\n const aligned = produce();\n const value = aligned[aligned.length - 1];\n return value === undefined ? Number.NaN : value;\n },\n get length() {\n return ctx.stream.ohlcv.close.length;\n },\n };\n return new Proxy(Object.freeze(target), {\n get(obj, prop, receiver) {\n if (typeof prop === \"string\") {\n const n = Number(prop);\n if (Number.isInteger(n) && n >= 0) {\n const aligned = produce();\n const value = aligned[aligned.length - 1 - n];\n return value === undefined ? Number.NaN : value;\n }\n }\n return Reflect.get(obj, prop, receiver);\n },\n }) as Series<number>;\n}\n\nfunction makeAlignedNumberSeries(\n ctx: RuntimeContext,\n slotId: string,\n feed: string,\n sourceKey: NumericSourceKey,\n secondary: StreamState,\n): Series<number> {\n return makeAlignedSeriesProxy(ctx, () =>\n alignedSeries(ctx, slotId, feed, sourceKey, secondary),\n );\n}\n\nfunction makeLiveSecurityBar(\n ctx: RuntimeContext,\n slotId: string,\n feed: string,\n interval: string,\n secondary: StreamState,\n): SecurityBar {\n const numeric = new Map<NumericSourceKey, Series<number>>();\n for (const key of NUMERIC_SOURCE_KEYS) {\n numeric.set(key, makeAlignedNumberSeries(ctx, slotId, feed, key, secondary));\n }\n return Object.freeze({\n time: numeric.get(\"time\") ?? makeSeries(Number.NaN),\n open: numeric.get(\"open\") ?? makeSeries(Number.NaN),\n high: numeric.get(\"high\") ?? makeSeries(Number.NaN),\n low: numeric.get(\"low\") ?? makeSeries(Number.NaN),\n close: numeric.get(\"close\") ?? makeSeries(Number.NaN),\n volume: numeric.get(\"volume\") ?? makeSeries(Number.NaN),\n hl2: numeric.get(\"hl2\") ?? makeSeries(Number.NaN),\n hlc3: numeric.get(\"hlc3\") ?? makeSeries(Number.NaN),\n ohlc4: numeric.get(\"ohlc4\") ?? makeSeries(Number.NaN),\n hlcc4: numeric.get(\"hlcc4\") ?? makeSeries(Number.NaN),\n symbol: makeConstantStringSeries(secondary.bar.symbol),\n interval: makeConstantStringSeries(interval),\n });\n}\n\n// The adapter does not advertise `multiSymbol`, so a `request.security` for a\n// symbol other than the chart's own degrades to all-NaN — mirroring the\n// `multiTimeframe` fallback message exactly, only naming the symbol gate.\nconst MULTI_SYMBOL_MSG =\n \"Adapter declares multiSymbol: false; request.security for a different symbol returns NaN\";\n\nfunction fallbackNaN(\n ctx: RuntimeContext,\n cacheKey: string,\n slotId: string,\n feed: string,\n code:\n | \"unsupported-interval\"\n | \"multi-timeframe-not-supported\"\n | \"multi-symbol-not-supported\"\n | \"unknown-secondary-stream\",\n message: string,\n): SecurityBar {\n pushOnce(ctx, code, slotId, feed, \"security\", message);\n const bar = makeNanSecurityBar();\n ctx.requestSecurityBars.set(cacheKey, bar);\n return bar;\n}\n\n/**\n * Return the runtime `request.security` bar for a callsite and `(symbol,\n * interval)` feed. `symbol` is already chart-symbol resolved + collapsed by the\n * caller (`undefined` ⇒ the chart's own symbol), so the composite\n * {@link feedKey} collapses to the bare interval for the chart-symbol path —\n * keeping the cache key, secondary-stream lookup, and diagnostics\n * byte-identical to the pre-multi-symbol baseline.\n *\n * A non-`undefined` `symbol` is therefore always a DIFFERENT symbol: the gate\n * order is symbol (`multiSymbol`) → timeframe (`multiTimeframe`) →\n * `unsupported-interval` → `unknown-secondary-stream`, so a request that is\n * both a different symbol AND a different interval against `multiSymbol: false`\n * trips `multi-symbol-not-supported` first (one diagnostic, not both).\n *\n * @since 0.5\n * @stable\n * @example\n * // const bar = makeSecurityBar(ctx, \"slot#0\", undefined, \"1D\");\n * const requested = \"1D\";\n * void requested;\n */\nexport function makeSecurityBar(\n ctx: RuntimeContext,\n slotId: string,\n symbol: string | undefined,\n interval: string,\n): SecurityBar {\n const feed = feedKey(symbol, interval);\n const cacheKey = `${slotId}|${feed}`;\n const existing = ctx.requestSecurityBars.get(cacheKey);\n if (existing !== undefined) return existing;\n\n // Symbol gate precedes the timeframe gate: a different symbol is a strictly\n // larger ask than a higher timeframe of the chart's own symbol.\n if (symbol !== undefined && !ctx.capabilities.multiSymbol) {\n return fallbackNaN(\n ctx,\n cacheKey,\n slotId,\n feed,\n \"multi-symbol-not-supported\",\n MULTI_SYMBOL_MSG,\n );\n }\n\n if (!ctx.capabilities.multiTimeframe) {\n return fallbackNaN(\n ctx,\n cacheKey,\n slotId,\n feed,\n \"multi-timeframe-not-supported\",\n \"Adapter declares multiTimeframe: false; request.security returns NaN\",\n );\n }\n\n const known = ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval);\n if (!known) {\n return fallbackNaN(\n ctx,\n cacheKey,\n slotId,\n feed,\n \"unsupported-interval\",\n `Requested interval \"${interval}\" is not in Capabilities.intervals`,\n );\n }\n\n const secondary = ctx.secondaryStreams.get(feed);\n if (secondary === undefined) {\n return fallbackNaN(\n ctx,\n cacheKey,\n slotId,\n feed,\n \"unknown-secondary-stream\",\n `Requested interval \"${interval}\" has no registered secondary stream`,\n );\n }\n\n const bar = makeLiveSecurityBar(ctx, slotId, feed, interval, secondary);\n ctx.requestSecurityBars.set(cacheKey, bar);\n return bar;\n}\n\nfunction makeNanNumberSeries(): Series<number> {\n return makeSeries(Number.NaN);\n}\n\nfunction resolveSecondaryOrDiagnose(\n ctx: RuntimeContext,\n slotId: string,\n feed: string,\n interval: string,\n): StreamState | undefined {\n if (!ctx.capabilities.multiTimeframe) {\n pushOnce(\n ctx,\n \"multi-timeframe-not-supported\",\n slotId,\n feed,\n \"security\",\n \"Adapter declares multiTimeframe: false; request.security returns NaN\",\n );\n return undefined;\n }\n if (!ctx.capabilities.intervals.some((descriptor) => descriptor.value === interval)) {\n pushOnce(\n ctx,\n \"unsupported-interval\",\n slotId,\n feed,\n \"security\",\n `Requested interval \"${interval}\" is not in Capabilities.intervals`,\n );\n return undefined;\n }\n const secondary = ctx.secondaryStreams.get(feed);\n if (secondary === undefined) {\n pushOnce(\n ctx,\n \"unknown-secondary-stream\",\n slotId,\n feed,\n \"security\",\n `Requested interval \"${interval}\" has no registered secondary stream`,\n );\n }\n return secondary;\n}\n\n/**\n * Return the main-aligned output series for an HTF expression callsite. The\n * runner's `output` buffer holds one sampled value per HTF bar; this aligns it\n * no-lookahead to the main timeline against the real secondary stream's\n * timestamps (so `output[i]` pairs with secondary ascending bar `i`). Reuses\n * the OHLCV alignment kernel via {@link getOrAlign}. Capability / interval /\n * stream fallbacks return an all-NaN series and push a deduped diagnostic,\n * matching {@link makeSecurityBar}. The returned Proxy identity is cached per\n * `slotId|feedKey` for the bar. `feed` is the composite key the caller built\n * from the resolved `(symbol, interval)`; `runner.interval` is the bare\n * interval used for the capability check and diagnostic text.\n *\n * `isDifferentSymbol` (`true` when the resolved symbol differs from the chart\n * symbol) gates the all-NaN `multi-symbol-not-supported` fallback BEFORE the\n * timeframe gate, mirroring {@link makeSecurityBar}'s order exactly.\n *\n * @since 0.7\n * @stable\n * @example\n * // const trend = makeSecurityExprSeries(ctx, runner, \"1W\", false);\n * const requested = \"1W\";\n * void requested;\n */\nexport function makeSecurityExprSeries(\n ctx: RuntimeContext,\n runner: SecurityExprRunner,\n feed: string,\n isDifferentSymbol: boolean,\n): Series<number> {\n const cacheKey = `${runner.slotId}|${feed}`;\n const cache = ctx.requestSecurityExprSeries;\n const existing = cache?.get(cacheKey);\n if (existing !== undefined) return existing;\n\n // Symbol gate precedes the timeframe gate, matching `makeSecurityBar`.\n if (isDifferentSymbol && !ctx.capabilities.multiSymbol) {\n pushOnce(\n ctx,\n \"multi-symbol-not-supported\",\n runner.slotId,\n feed,\n \"security\",\n MULTI_SYMBOL_MSG,\n );\n const nan = makeNanNumberSeries();\n cache?.set(cacheKey, nan);\n return nan;\n }\n\n const secondary = resolveSecondaryOrDiagnose(ctx, runner.slotId, feed, runner.interval);\n const series =\n secondary === undefined\n ? makeNanNumberSeries()\n : makeAlignedSeriesProxy(ctx, () =>\n getOrAlign(\n ascendingBarsFor(ctx, secondary),\n ascendingValues(runner.output),\n ascendingBarsFor(ctx, ctx.stream),\n ),\n );\n cache?.set(cacheKey, series);\n return series;\n}\n"]}
|
|
@@ -39,21 +39,22 @@ export type SecurityExprRunner = {
|
|
|
39
39
|
};
|
|
40
40
|
/**
|
|
41
41
|
* The pair of lookup maps the runtime threads onto its {@link RuntimeContext}:
|
|
42
|
-
* `bySlot` keyed by `slotId` (overload dispatch + capture) and `
|
|
43
|
-
*
|
|
42
|
+
* `bySlot` keyed by `slotId` (overload dispatch + capture) and `byFeed` keyed
|
|
43
|
+
* by the composite `feedKey(symbol, interval)` (the fan-out from a secondary
|
|
44
|
+
* close, whose `streamKey` carries that same composite key).
|
|
44
45
|
*
|
|
45
46
|
* @since 0.7
|
|
46
47
|
* @stable
|
|
47
48
|
* @example
|
|
48
49
|
* const registry: SecurityExprRegistry = {
|
|
49
50
|
* bySlot: new Map(),
|
|
50
|
-
*
|
|
51
|
+
* byFeed: new Map(),
|
|
51
52
|
* };
|
|
52
53
|
* void registry;
|
|
53
54
|
*/
|
|
54
55
|
export type SecurityExprRegistry = {
|
|
55
56
|
readonly bySlot: Map<string, SecurityExprRunner>;
|
|
56
|
-
readonly
|
|
57
|
+
readonly byFeed: ReadonlyMap<string, ReadonlyArray<SecurityExprRunner>>;
|
|
57
58
|
};
|
|
58
59
|
/**
|
|
59
60
|
* Construct one {@link SecurityExprRunner}. The fold stream and output buffer
|
|
@@ -70,13 +71,14 @@ export type SecurityExprRegistry = {
|
|
|
70
71
|
*/
|
|
71
72
|
export declare function createSecurityExprRunner(args: {
|
|
72
73
|
readonly slotId: string;
|
|
74
|
+
readonly symbol: string;
|
|
73
75
|
readonly interval: string;
|
|
74
76
|
readonly capacity: number;
|
|
75
77
|
readonly parent: RuntimeContext;
|
|
76
78
|
}): SecurityExprRunner;
|
|
77
79
|
/**
|
|
78
80
|
* Mount one runner per `manifest.securityExpressions` entry and return the
|
|
79
|
-
* `bySlot` / `
|
|
81
|
+
* `bySlot` / `byFeed` lookup maps. Returns empty maps when the manifest
|
|
80
82
|
* declares no expression callsites (the common single-timeframe case), so the
|
|
81
83
|
* secondary-close drive pays a single empty-map check.
|
|
82
84
|
*
|
|
@@ -84,12 +86,14 @@ export declare function createSecurityExprRunner(args: {
|
|
|
84
86
|
* @stable
|
|
85
87
|
* @example
|
|
86
88
|
* // const registry = buildSecurityExprRunners(manifest, ctx, 64);
|
|
87
|
-
* const built = "bySlot +
|
|
89
|
+
* const built = "bySlot + byFeed";
|
|
88
90
|
* void built;
|
|
89
91
|
*/
|
|
90
92
|
export declare function buildSecurityExprRunners(manifest: ScriptManifest, parent: RuntimeContext, capacity: number): SecurityExprRegistry;
|
|
91
93
|
/**
|
|
92
|
-
* Drive every runner registered on `
|
|
94
|
+
* Drive every runner registered on the composite feed key `streamKey` for one
|
|
95
|
+
* secondary event. `streamKey` is the `feedKey(symbol, interval)` the secondary
|
|
96
|
+
* stream is registered under (and that `CandleEvent.streamKey` carries). A
|
|
93
97
|
* `"close"` folds the bar into the fold stream and appends one sampled output;
|
|
94
98
|
* a `"tick"` replaces the fold head and the output head without advancing
|
|
95
99
|
* length. Runners whose callback is not yet captured are skipped — the first
|
|
@@ -102,7 +106,7 @@ export declare function buildSecurityExprRunners(manifest: ScriptManifest, paren
|
|
|
102
106
|
* const mode = "close";
|
|
103
107
|
* void mode;
|
|
104
108
|
*/
|
|
105
|
-
export declare function driveSecurityExpressions(parent: RuntimeContext,
|
|
109
|
+
export declare function driveSecurityExpressions(parent: RuntimeContext, streamKey: string, mode: "close" | "tick", bar: Bar): void;
|
|
106
110
|
/**
|
|
107
111
|
* Store the callback the first time main compute provides it, then replay the
|
|
108
112
|
* real secondary stream oldest→newest through the runner's fold stream until
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"securityExprRunner.d.ts","sourceRoot":"","sources":["../../src/request/securityExprRunner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,GAAG,EACH,cAAc,EACd,WAAW,EACX,YAAY,EAEf,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"securityExprRunner.d.ts","sourceRoot":"","sources":["../../src/request/securityExprRunner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,GAAG,EACH,cAAc,EACd,WAAW,EACX,YAAY,EAEf,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAA0B,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EACH,KAAK,WAAW,EAInB,MAAM,mBAAmB,CAAC;AAI3B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAC/B,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC;CAC3E,CAAC;AAuEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;CACnC,GAAG,kBAAkB,CAYrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACpC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,GACjB,oBAAoB,CAgCtB;AAqCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,GAAG,MAAM,EACtB,GAAG,EAAE,GAAG,GACT,IAAI,CAUN;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE,YAAY,EAClB,SAAS,EAAE,WAAW,GACvB,IAAI,CAON;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,aAAa,CAAC,MAAM,CAAC,CAMhF"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
2
2
|
// See the LICENSE file in the repo root for full license text.
|
|
3
|
+
import { feedKey } from "@invinite-org/chartlang-core";
|
|
3
4
|
import { ACTIVE_RUNTIME_CONTEXT } from "../runtimeContext.js";
|
|
4
5
|
import { Float64RingBuffer } from "../ringBuffer.js";
|
|
5
6
|
import { advanceSeriesSlots, commitSeriesSlots, resetSeriesHeads } from "../state/index.js";
|
|
@@ -7,7 +8,7 @@ import { inMemoryStateStore } from "../stateStore.js";
|
|
|
7
8
|
import { appendBarToStream, createStreamState, replaceStreamHead, } from "../streamState.js";
|
|
8
9
|
import { createRuntimeViews } from "../views/index.js";
|
|
9
10
|
import { barFromStream, makeConstantStringSeries } from "./streamBars.js";
|
|
10
|
-
function makeFoldBar(foldStream, interval) {
|
|
11
|
+
function makeFoldBar(foldStream, symbol, interval) {
|
|
11
12
|
const { seriesViews } = foldStream;
|
|
12
13
|
return Object.freeze({
|
|
13
14
|
time: seriesViews.time,
|
|
@@ -20,7 +21,7 @@ function makeFoldBar(foldStream, interval) {
|
|
|
20
21
|
hlc3: seriesViews.hlc3,
|
|
21
22
|
ohlc4: seriesViews.ohlc4,
|
|
22
23
|
hlcc4: seriesViews.hlcc4,
|
|
23
|
-
symbol: makeConstantStringSeries(
|
|
24
|
+
symbol: makeConstantStringSeries(symbol),
|
|
24
25
|
interval: makeConstantStringSeries(interval),
|
|
25
26
|
});
|
|
26
27
|
}
|
|
@@ -50,12 +51,15 @@ function buildExprContext(parent, slotId, foldStream) {
|
|
|
50
51
|
scriptMaxDrawings: null,
|
|
51
52
|
stateSlots: new Map(),
|
|
52
53
|
seriesSlots: new Map(),
|
|
54
|
+
arraySlots: new Map(),
|
|
55
|
+
chartSymbol: parent.chartSymbol,
|
|
53
56
|
secondaryStreams: parent.secondaryStreams,
|
|
54
57
|
requestSecurityBars: new Map(),
|
|
55
58
|
requestSecurityAlignments: new Map(),
|
|
56
59
|
requestSecurityAscendingBars: new Map(),
|
|
57
60
|
requestLowerTfViews: new Map(),
|
|
58
61
|
diagnosedRequestKeys: new Set(),
|
|
62
|
+
diagnosedTzKeys: new Set(),
|
|
59
63
|
logBudget: 0,
|
|
60
64
|
logBudgetExceededDiagnosed: false,
|
|
61
65
|
resolvedInputs: parent.resolvedInputs,
|
|
@@ -81,13 +85,13 @@ function buildExprContext(parent, slotId, foldStream) {
|
|
|
81
85
|
* void interval;
|
|
82
86
|
*/
|
|
83
87
|
export function createSecurityExprRunner(args) {
|
|
84
|
-
const { slotId, interval, capacity, parent } = args;
|
|
85
|
-
const foldStream = createStreamState({ interval, capacity, symbol
|
|
88
|
+
const { slotId, symbol, interval, capacity, parent } = args;
|
|
89
|
+
const foldStream = createStreamState({ interval, capacity, symbol });
|
|
86
90
|
return {
|
|
87
91
|
slotId,
|
|
88
92
|
interval,
|
|
89
93
|
foldStream,
|
|
90
|
-
foldBar: makeFoldBar(foldStream, interval),
|
|
94
|
+
foldBar: makeFoldBar(foldStream, symbol, interval),
|
|
91
95
|
ctx: buildExprContext(parent, slotId, foldStream),
|
|
92
96
|
output: new Float64RingBuffer(capacity),
|
|
93
97
|
processedHtfCount: 0,
|
|
@@ -95,7 +99,7 @@ export function createSecurityExprRunner(args) {
|
|
|
95
99
|
}
|
|
96
100
|
/**
|
|
97
101
|
* Mount one runner per `manifest.securityExpressions` entry and return the
|
|
98
|
-
* `bySlot` / `
|
|
102
|
+
* `bySlot` / `byFeed` lookup maps. Returns empty maps when the manifest
|
|
99
103
|
* declares no expression callsites (the common single-timeframe case), so the
|
|
100
104
|
* secondary-close drive pays a single empty-map check.
|
|
101
105
|
*
|
|
@@ -103,29 +107,41 @@ export function createSecurityExprRunner(args) {
|
|
|
103
107
|
* @stable
|
|
104
108
|
* @example
|
|
105
109
|
* // const registry = buildSecurityExprRunners(manifest, ctx, 64);
|
|
106
|
-
* const built = "bySlot +
|
|
110
|
+
* const built = "bySlot + byFeed";
|
|
107
111
|
* void built;
|
|
108
112
|
*/
|
|
109
113
|
export function buildSecurityExprRunners(manifest, parent, capacity) {
|
|
110
114
|
const bySlot = new Map();
|
|
111
|
-
const
|
|
115
|
+
const byFeed = new Map();
|
|
112
116
|
for (const descriptor of manifest.securityExpressions ?? []) {
|
|
117
|
+
// Index by the composite feed key (the same key the secondary stream is
|
|
118
|
+
// registered under and `CandleEvent.streamKey` carries). Collapse a
|
|
119
|
+
// chart-symbol descriptor (omitted, or the chart's own ticker passed
|
|
120
|
+
// explicitly) to `undefined` BEFORE keying — mirroring
|
|
121
|
+
// `createSecondaryStreams` — so the omitted-symbol path stays
|
|
122
|
+
// byte-identical to the pre-multi-symbol baseline. The fold stream
|
|
123
|
+
// carries the RESOLVED symbol (chart symbol when omitted).
|
|
124
|
+
const resolved = descriptor.symbol === undefined || descriptor.symbol === parent.chartSymbol
|
|
125
|
+
? undefined
|
|
126
|
+
: descriptor.symbol;
|
|
127
|
+
const key = feedKey(resolved, descriptor.interval);
|
|
113
128
|
const runner = createSecurityExprRunner({
|
|
114
129
|
slotId: descriptor.slotId,
|
|
130
|
+
symbol: descriptor.symbol ?? parent.chartSymbol,
|
|
115
131
|
interval: descriptor.interval,
|
|
116
132
|
capacity,
|
|
117
133
|
parent,
|
|
118
134
|
});
|
|
119
135
|
bySlot.set(descriptor.slotId, runner);
|
|
120
|
-
const list =
|
|
136
|
+
const list = byFeed.get(key);
|
|
121
137
|
if (list === undefined) {
|
|
122
|
-
|
|
138
|
+
byFeed.set(key, [runner]);
|
|
123
139
|
}
|
|
124
140
|
else {
|
|
125
141
|
list.push(runner);
|
|
126
142
|
}
|
|
127
143
|
}
|
|
128
|
-
return { bySlot,
|
|
144
|
+
return { bySlot, byFeed };
|
|
129
145
|
}
|
|
130
146
|
function sampleOutput(result) {
|
|
131
147
|
return typeof result === "number" ? result : result.current;
|
|
@@ -165,7 +181,9 @@ function foldTick(runner, bar) {
|
|
|
165
181
|
runner.output.replaceHead(evaluate(runner, runner.callback, true));
|
|
166
182
|
}
|
|
167
183
|
/**
|
|
168
|
-
* Drive every runner registered on `
|
|
184
|
+
* Drive every runner registered on the composite feed key `streamKey` for one
|
|
185
|
+
* secondary event. `streamKey` is the `feedKey(symbol, interval)` the secondary
|
|
186
|
+
* stream is registered under (and that `CandleEvent.streamKey` carries). A
|
|
169
187
|
* `"close"` folds the bar into the fold stream and appends one sampled output;
|
|
170
188
|
* a `"tick"` replaces the fold head and the output head without advancing
|
|
171
189
|
* length. Runners whose callback is not yet captured are skipped — the first
|
|
@@ -178,8 +196,8 @@ function foldTick(runner, bar) {
|
|
|
178
196
|
* const mode = "close";
|
|
179
197
|
* void mode;
|
|
180
198
|
*/
|
|
181
|
-
export function driveSecurityExpressions(parent,
|
|
182
|
-
const runners = parent.
|
|
199
|
+
export function driveSecurityExpressions(parent, streamKey, mode, bar) {
|
|
200
|
+
const runners = parent.securityExprRunnersByFeed?.get(streamKey);
|
|
183
201
|
if (runners === undefined)
|
|
184
202
|
return;
|
|
185
203
|
for (const runner of runners) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"securityExprRunner.js","sourceRoot":"","sources":["../../src/request/securityExprRunner.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type {\n Bar,\n ScriptManifest,\n SecurityBar,\n SecurityExpr,\n Series,\n} from \"@invinite-org/chartlang-core\";\n\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { advanceSeriesSlots, commitSeriesSlots, resetSeriesHeads } from \"../state/index.js\";\nimport { inMemoryStateStore } from \"../stateStore.js\";\nimport {\n type StreamState,\n appendBarToStream,\n createStreamState,\n replaceStreamHead,\n} from \"../streamState.js\";\nimport { createRuntimeViews } from \"../views/index.js\";\nimport { barFromStream, makeConstantStringSeries } from \"./streamBars.js\";\n\n/**\n * One mounted higher-timeframe expression unit. The compiler records each\n * `request.security({ interval }, (bar) => …)` callsite in\n * `manifest.securityExpressions`; the runtime mounts one runner per entry.\n *\n * The runner owns a dedicated fold {@link StreamState} clocked on the HTF\n * `interval`, a `Float64RingBuffer` output buffer (one sampled value per HTF\n * bar), a fold {@link SecurityBar} view backed by the fold stream's head, and\n * a private {@link RuntimeContext} (`stream = foldStream`,\n * `slotIdPrefix = \"security:<slotId>/\"`) so `ta.*` inside the callback\n * accumulate on the HTF clock without colliding with the main stream.\n *\n * `callback` is captured lazily the first time the main compute body calls\n * `request.security(slotId, opts, expr)`. `processedHtfCount` tracks how many\n * HTF bars have already been folded into `output` so replay catches up history\n * exactly once.\n *\n * @since 0.7\n * @stable\n * @example\n * // const runner = createSecurityExprRunner({ slotId: \"s#0\", interval: \"1W\",\n * // capacity: 64, parent });\n * const slotId = \"s#0\";\n * void slotId;\n */\nexport type SecurityExprRunner = {\n readonly slotId: string;\n readonly interval: string;\n readonly foldStream: StreamState;\n readonly foldBar: SecurityBar;\n readonly ctx: RuntimeContext;\n readonly output: Float64RingBuffer;\n callback?: SecurityExpr;\n processedHtfCount: number;\n};\n\n/**\n * The pair of lookup maps the runtime threads onto its {@link RuntimeContext}:\n * `bySlot` keyed by `slotId` (overload dispatch + capture) and `byInterval`\n * keyed by `IntervalDescriptor.value` (the fan-out from a secondary close).\n *\n * @since 0.7\n * @stable\n * @example\n * const registry: SecurityExprRegistry = {\n * bySlot: new Map(),\n * byInterval: new Map(),\n * };\n * void registry;\n */\nexport type SecurityExprRegistry = {\n readonly bySlot: Map<string, SecurityExprRunner>;\n readonly byInterval: ReadonlyMap<string, ReadonlyArray<SecurityExprRunner>>;\n};\n\nfunction makeFoldBar(foldStream: StreamState, interval: string): SecurityBar {\n const { seriesViews } = foldStream;\n return Object.freeze({\n time: seriesViews.time,\n open: seriesViews.open,\n high: seriesViews.high,\n low: seriesViews.low,\n close: seriesViews.close,\n volume: seriesViews.volume,\n hl2: seriesViews.hl2,\n hlc3: seriesViews.hlc3,\n ohlc4: seriesViews.ohlc4,\n hlcc4: seriesViews.hlcc4,\n symbol: makeConstantStringSeries(\"\"),\n interval: makeConstantStringSeries(interval),\n });\n}\n\nfunction buildExprContext(\n parent: RuntimeContext,\n slotId: string,\n foldStream: StreamState,\n): RuntimeContext {\n return {\n stream: foldStream,\n stateStore: inMemoryStateStore(),\n lastPersistTime: 0,\n capabilities: parent.capabilities,\n // A throwaway bag — the callback may not emit (Task 2 forbids\n // non-`ta` refs), but an isolated queue guards if it somehow does.\n emissions: {\n plots: [],\n drawings: [],\n alerts: [],\n alertConditions: [],\n logs: [],\n diagnostics: [],\n fromBar: 0,\n toBar: 0,\n },\n barIndex: () => foldStream.ohlcv.close.length - 1,\n isTick: false,\n drawingSlots: new Map(),\n drawingSubIdCounters: new Map(),\n drawingBucketCounters: { lines: 0, labels: 0, boxes: 0, polylines: 0, other: 0 },\n scriptMaxDrawings: null,\n stateSlots: new Map(),\n seriesSlots: new Map(),\n secondaryStreams: parent.secondaryStreams,\n requestSecurityBars: new Map(),\n requestSecurityAlignments: new Map(),\n requestSecurityAscendingBars: new Map(),\n requestLowerTfViews: new Map(),\n diagnosedRequestKeys: new Set(),\n logBudget: 0,\n logBudgetExceededDiagnosed: false,\n resolvedInputs: parent.resolvedInputs,\n defaultPane: parent.defaultPane,\n scriptPane: parent.scriptPane,\n plotOverrides: Object.freeze({}),\n diagnosedInputKeys: new Set(),\n views: createRuntimeViews(),\n slotIdPrefix: `security:${slotId}/`,\n };\n}\n\n/**\n * Construct one {@link SecurityExprRunner}. The fold stream and output buffer\n * share the secondary stream's `capacity` so a deep-lookback callback\n * (`ta.sma(bar.close, 50)`) has enough HTF history to warm up.\n *\n * @since 0.7\n * @stable\n * @example\n * // const runner = createSecurityExprRunner({ slotId: \"s#0\",\n * // interval: \"1W\", capacity: 64, parent });\n * const interval = \"1W\";\n * void interval;\n */\nexport function createSecurityExprRunner(args: {\n readonly slotId: string;\n readonly interval: string;\n readonly capacity: number;\n readonly parent: RuntimeContext;\n}): SecurityExprRunner {\n const { slotId, interval, capacity, parent } = args;\n const foldStream = createStreamState({ interval, capacity, symbol: \"\" });\n return {\n slotId,\n interval,\n foldStream,\n foldBar: makeFoldBar(foldStream, interval),\n ctx: buildExprContext(parent, slotId, foldStream),\n output: new Float64RingBuffer(capacity),\n processedHtfCount: 0,\n };\n}\n\n/**\n * Mount one runner per `manifest.securityExpressions` entry and return the\n * `bySlot` / `byInterval` lookup maps. Returns empty maps when the manifest\n * declares no expression callsites (the common single-timeframe case), so the\n * secondary-close drive pays a single empty-map check.\n *\n * @since 0.7\n * @stable\n * @example\n * // const registry = buildSecurityExprRunners(manifest, ctx, 64);\n * const built = \"bySlot + byInterval\";\n * void built;\n */\nexport function buildSecurityExprRunners(\n manifest: ScriptManifest,\n parent: RuntimeContext,\n capacity: number,\n): SecurityExprRegistry {\n const bySlot = new Map<string, SecurityExprRunner>();\n const byInterval = new Map<string, SecurityExprRunner[]>();\n for (const descriptor of manifest.securityExpressions ?? []) {\n const runner = createSecurityExprRunner({\n slotId: descriptor.slotId,\n interval: descriptor.interval,\n capacity,\n parent,\n });\n bySlot.set(descriptor.slotId, runner);\n const list = byInterval.get(descriptor.interval);\n if (list === undefined) {\n byInterval.set(descriptor.interval, [runner]);\n } else {\n list.push(runner);\n }\n }\n return { bySlot, byInterval };\n}\n\nfunction sampleOutput(result: Series<number> | number): number {\n return typeof result === \"number\" ? result : result.current;\n}\n\nfunction evaluate(runner: SecurityExprRunner, callback: SecurityExpr, isTick: boolean): number {\n const previous = ACTIVE_RUNTIME_CONTEXT.current;\n ACTIVE_RUNTIME_CONTEXT.current = runner.ctx;\n runner.ctx.isTick = isTick;\n // `state.series` inside the callback accumulates on the HTF clock, so it\n // advances/commits in lockstep with the fold stream — the same close/tick\n // discipline `runComputeBody` applies to the main compute.\n if (isTick) resetSeriesHeads(runner.ctx);\n else advanceSeriesSlots(runner.ctx);\n try {\n return sampleOutput(callback(runner.foldBar));\n } finally {\n if (!isTick) commitSeriesSlots(runner.ctx);\n runner.ctx.isTick = false;\n ACTIVE_RUNTIME_CONTEXT.current = previous;\n }\n}\n\nfunction foldClose(runner: SecurityExprRunner, bar: Bar): void {\n if (runner.callback === undefined) return;\n appendBarToStream(runner.foldStream, bar);\n runner.output.append(evaluate(runner, runner.callback, false));\n runner.processedHtfCount += 1;\n}\n\nfunction foldTick(runner: SecurityExprRunner, bar: Bar): void {\n if (runner.callback === undefined) return;\n replaceStreamHead(runner.foldStream, bar);\n runner.output.replaceHead(evaluate(runner, runner.callback, true));\n}\n\n/**\n * Drive every runner registered on `interval` for one secondary event. A\n * `\"close\"` folds the bar into the fold stream and appends one sampled output;\n * a `\"tick\"` replaces the fold head and the output head without advancing\n * length. Runners whose callback is not yet captured are skipped — the first\n * main compute replays their backlog via {@link captureAndCatchUp}.\n *\n * @since 0.7\n * @stable\n * @example\n * // driveSecurityExpressions(ctx, \"1W\", \"close\", weeklyBar);\n * const mode = \"close\";\n * void mode;\n */\nexport function driveSecurityExpressions(\n parent: RuntimeContext,\n interval: string,\n mode: \"close\" | \"tick\",\n bar: Bar,\n): void {\n const runners = parent.securityExprRunnersByInterval?.get(interval);\n if (runners === undefined) return;\n for (const runner of runners) {\n if (mode === \"close\") {\n foldClose(runner, bar);\n } else {\n foldTick(runner, bar);\n }\n }\n}\n\n/**\n * Store the callback the first time main compute provides it, then replay the\n * real secondary stream oldest→newest through the runner's fold stream until\n * `processedHtfCount === secondary.length`. Idempotent once the backlog is\n * drained, so later calls in the same bar are no-ops.\n *\n * @since 0.7\n * @stable\n * @example\n * // captureAndCatchUp(runner, expr, secondaryStream);\n * const replayed = \"oldest -> newest\";\n * void replayed;\n */\nexport function captureAndCatchUp(\n runner: SecurityExprRunner,\n expr: SecurityExpr,\n secondary: StreamState,\n): void {\n if (runner.callback === undefined) runner.callback = expr;\n const length = secondary.ohlcv.close.length;\n while (runner.processedHtfCount < length) {\n const age = length - 1 - runner.processedHtfCount;\n foldClose(runner, barFromStream(secondary, age));\n }\n}\n\n/**\n * Materialise a `Float64RingBuffer`'s values oldest→newest. Used as the\n * `htfSeries` source when aligning a runner's output buffer to the main\n * timeline.\n *\n * @since 0.7\n * @stable\n * @example\n * // const values = ascendingValues(runner.output);\n * const order = \"oldest -> newest\";\n * void order;\n */\nexport function ascendingValues(buffer: Float64RingBuffer): ReadonlyArray<number> {\n const values: number[] = [];\n for (let age = buffer.length - 1; age >= 0; age -= 1) {\n values.push(buffer.at(age));\n }\n return values;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"securityExprRunner.js","sourceRoot":"","sources":["../../src/request/securityExprRunner.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type {\n Bar,\n ScriptManifest,\n SecurityBar,\n SecurityExpr,\n Series,\n} from \"@invinite-org/chartlang-core\";\nimport { feedKey } from \"@invinite-org/chartlang-core\";\n\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { advanceSeriesSlots, commitSeriesSlots, resetSeriesHeads } from \"../state/index.js\";\nimport { inMemoryStateStore } from \"../stateStore.js\";\nimport {\n type StreamState,\n appendBarToStream,\n createStreamState,\n replaceStreamHead,\n} from \"../streamState.js\";\nimport { createRuntimeViews } from \"../views/index.js\";\nimport { barFromStream, makeConstantStringSeries } from \"./streamBars.js\";\n\n/**\n * One mounted higher-timeframe expression unit. The compiler records each\n * `request.security({ interval }, (bar) => …)` callsite in\n * `manifest.securityExpressions`; the runtime mounts one runner per entry.\n *\n * The runner owns a dedicated fold {@link StreamState} clocked on the HTF\n * `interval`, a `Float64RingBuffer` output buffer (one sampled value per HTF\n * bar), a fold {@link SecurityBar} view backed by the fold stream's head, and\n * a private {@link RuntimeContext} (`stream = foldStream`,\n * `slotIdPrefix = \"security:<slotId>/\"`) so `ta.*` inside the callback\n * accumulate on the HTF clock without colliding with the main stream.\n *\n * `callback` is captured lazily the first time the main compute body calls\n * `request.security(slotId, opts, expr)`. `processedHtfCount` tracks how many\n * HTF bars have already been folded into `output` so replay catches up history\n * exactly once.\n *\n * @since 0.7\n * @stable\n * @example\n * // const runner = createSecurityExprRunner({ slotId: \"s#0\", interval: \"1W\",\n * // capacity: 64, parent });\n * const slotId = \"s#0\";\n * void slotId;\n */\nexport type SecurityExprRunner = {\n readonly slotId: string;\n readonly interval: string;\n readonly foldStream: StreamState;\n readonly foldBar: SecurityBar;\n readonly ctx: RuntimeContext;\n readonly output: Float64RingBuffer;\n callback?: SecurityExpr;\n processedHtfCount: number;\n};\n\n/**\n * The pair of lookup maps the runtime threads onto its {@link RuntimeContext}:\n * `bySlot` keyed by `slotId` (overload dispatch + capture) and `byFeed` keyed\n * by the composite `feedKey(symbol, interval)` (the fan-out from a secondary\n * close, whose `streamKey` carries that same composite key).\n *\n * @since 0.7\n * @stable\n * @example\n * const registry: SecurityExprRegistry = {\n * bySlot: new Map(),\n * byFeed: new Map(),\n * };\n * void registry;\n */\nexport type SecurityExprRegistry = {\n readonly bySlot: Map<string, SecurityExprRunner>;\n readonly byFeed: ReadonlyMap<string, ReadonlyArray<SecurityExprRunner>>;\n};\n\nfunction makeFoldBar(foldStream: StreamState, symbol: string, interval: string): SecurityBar {\n const { seriesViews } = foldStream;\n return Object.freeze({\n time: seriesViews.time,\n open: seriesViews.open,\n high: seriesViews.high,\n low: seriesViews.low,\n close: seriesViews.close,\n volume: seriesViews.volume,\n hl2: seriesViews.hl2,\n hlc3: seriesViews.hlc3,\n ohlc4: seriesViews.ohlc4,\n hlcc4: seriesViews.hlcc4,\n symbol: makeConstantStringSeries(symbol),\n interval: makeConstantStringSeries(interval),\n });\n}\n\nfunction buildExprContext(\n parent: RuntimeContext,\n slotId: string,\n foldStream: StreamState,\n): RuntimeContext {\n return {\n stream: foldStream,\n stateStore: inMemoryStateStore(),\n lastPersistTime: 0,\n capabilities: parent.capabilities,\n // A throwaway bag — the callback may not emit (Task 2 forbids\n // non-`ta` refs), but an isolated queue guards if it somehow does.\n emissions: {\n plots: [],\n drawings: [],\n alerts: [],\n alertConditions: [],\n logs: [],\n diagnostics: [],\n fromBar: 0,\n toBar: 0,\n },\n barIndex: () => foldStream.ohlcv.close.length - 1,\n isTick: false,\n drawingSlots: new Map(),\n drawingSubIdCounters: new Map(),\n drawingBucketCounters: { lines: 0, labels: 0, boxes: 0, polylines: 0, other: 0 },\n scriptMaxDrawings: null,\n stateSlots: new Map(),\n seriesSlots: new Map(),\n arraySlots: new Map(),\n chartSymbol: parent.chartSymbol,\n secondaryStreams: parent.secondaryStreams,\n requestSecurityBars: new Map(),\n requestSecurityAlignments: new Map(),\n requestSecurityAscendingBars: new Map(),\n requestLowerTfViews: new Map(),\n diagnosedRequestKeys: new Set(),\n diagnosedTzKeys: new Set(),\n logBudget: 0,\n logBudgetExceededDiagnosed: false,\n resolvedInputs: parent.resolvedInputs,\n defaultPane: parent.defaultPane,\n scriptPane: parent.scriptPane,\n plotOverrides: Object.freeze({}),\n diagnosedInputKeys: new Set(),\n views: createRuntimeViews(),\n slotIdPrefix: `security:${slotId}/`,\n };\n}\n\n/**\n * Construct one {@link SecurityExprRunner}. The fold stream and output buffer\n * share the secondary stream's `capacity` so a deep-lookback callback\n * (`ta.sma(bar.close, 50)`) has enough HTF history to warm up.\n *\n * @since 0.7\n * @stable\n * @example\n * // const runner = createSecurityExprRunner({ slotId: \"s#0\",\n * // interval: \"1W\", capacity: 64, parent });\n * const interval = \"1W\";\n * void interval;\n */\nexport function createSecurityExprRunner(args: {\n readonly slotId: string;\n readonly symbol: string;\n readonly interval: string;\n readonly capacity: number;\n readonly parent: RuntimeContext;\n}): SecurityExprRunner {\n const { slotId, symbol, interval, capacity, parent } = args;\n const foldStream = createStreamState({ interval, capacity, symbol });\n return {\n slotId,\n interval,\n foldStream,\n foldBar: makeFoldBar(foldStream, symbol, interval),\n ctx: buildExprContext(parent, slotId, foldStream),\n output: new Float64RingBuffer(capacity),\n processedHtfCount: 0,\n };\n}\n\n/**\n * Mount one runner per `manifest.securityExpressions` entry and return the\n * `bySlot` / `byFeed` lookup maps. Returns empty maps when the manifest\n * declares no expression callsites (the common single-timeframe case), so the\n * secondary-close drive pays a single empty-map check.\n *\n * @since 0.7\n * @stable\n * @example\n * // const registry = buildSecurityExprRunners(manifest, ctx, 64);\n * const built = \"bySlot + byFeed\";\n * void built;\n */\nexport function buildSecurityExprRunners(\n manifest: ScriptManifest,\n parent: RuntimeContext,\n capacity: number,\n): SecurityExprRegistry {\n const bySlot = new Map<string, SecurityExprRunner>();\n const byFeed = new Map<string, SecurityExprRunner[]>();\n for (const descriptor of manifest.securityExpressions ?? []) {\n // Index by the composite feed key (the same key the secondary stream is\n // registered under and `CandleEvent.streamKey` carries). Collapse a\n // chart-symbol descriptor (omitted, or the chart's own ticker passed\n // explicitly) to `undefined` BEFORE keying — mirroring\n // `createSecondaryStreams` — so the omitted-symbol path stays\n // byte-identical to the pre-multi-symbol baseline. The fold stream\n // carries the RESOLVED symbol (chart symbol when omitted).\n const resolved =\n descriptor.symbol === undefined || descriptor.symbol === parent.chartSymbol\n ? undefined\n : descriptor.symbol;\n const key = feedKey(resolved, descriptor.interval);\n const runner = createSecurityExprRunner({\n slotId: descriptor.slotId,\n symbol: descriptor.symbol ?? parent.chartSymbol,\n interval: descriptor.interval,\n capacity,\n parent,\n });\n bySlot.set(descriptor.slotId, runner);\n const list = byFeed.get(key);\n if (list === undefined) {\n byFeed.set(key, [runner]);\n } else {\n list.push(runner);\n }\n }\n return { bySlot, byFeed };\n}\n\nfunction sampleOutput(result: Series<number> | number): number {\n return typeof result === \"number\" ? result : result.current;\n}\n\nfunction evaluate(runner: SecurityExprRunner, callback: SecurityExpr, isTick: boolean): number {\n const previous = ACTIVE_RUNTIME_CONTEXT.current;\n ACTIVE_RUNTIME_CONTEXT.current = runner.ctx;\n runner.ctx.isTick = isTick;\n // `state.series` inside the callback accumulates on the HTF clock, so it\n // advances/commits in lockstep with the fold stream — the same close/tick\n // discipline `runComputeBody` applies to the main compute.\n if (isTick) resetSeriesHeads(runner.ctx);\n else advanceSeriesSlots(runner.ctx);\n try {\n return sampleOutput(callback(runner.foldBar));\n } finally {\n if (!isTick) commitSeriesSlots(runner.ctx);\n runner.ctx.isTick = false;\n ACTIVE_RUNTIME_CONTEXT.current = previous;\n }\n}\n\nfunction foldClose(runner: SecurityExprRunner, bar: Bar): void {\n if (runner.callback === undefined) return;\n appendBarToStream(runner.foldStream, bar);\n runner.output.append(evaluate(runner, runner.callback, false));\n runner.processedHtfCount += 1;\n}\n\nfunction foldTick(runner: SecurityExprRunner, bar: Bar): void {\n if (runner.callback === undefined) return;\n replaceStreamHead(runner.foldStream, bar);\n runner.output.replaceHead(evaluate(runner, runner.callback, true));\n}\n\n/**\n * Drive every runner registered on the composite feed key `streamKey` for one\n * secondary event. `streamKey` is the `feedKey(symbol, interval)` the secondary\n * stream is registered under (and that `CandleEvent.streamKey` carries). A\n * `\"close\"` folds the bar into the fold stream and appends one sampled output;\n * a `\"tick\"` replaces the fold head and the output head without advancing\n * length. Runners whose callback is not yet captured are skipped — the first\n * main compute replays their backlog via {@link captureAndCatchUp}.\n *\n * @since 0.7\n * @stable\n * @example\n * // driveSecurityExpressions(ctx, \"1W\", \"close\", weeklyBar);\n * const mode = \"close\";\n * void mode;\n */\nexport function driveSecurityExpressions(\n parent: RuntimeContext,\n streamKey: string,\n mode: \"close\" | \"tick\",\n bar: Bar,\n): void {\n const runners = parent.securityExprRunnersByFeed?.get(streamKey);\n if (runners === undefined) return;\n for (const runner of runners) {\n if (mode === \"close\") {\n foldClose(runner, bar);\n } else {\n foldTick(runner, bar);\n }\n }\n}\n\n/**\n * Store the callback the first time main compute provides it, then replay the\n * real secondary stream oldest→newest through the runner's fold stream until\n * `processedHtfCount === secondary.length`. Idempotent once the backlog is\n * drained, so later calls in the same bar are no-ops.\n *\n * @since 0.7\n * @stable\n * @example\n * // captureAndCatchUp(runner, expr, secondaryStream);\n * const replayed = \"oldest -> newest\";\n * void replayed;\n */\nexport function captureAndCatchUp(\n runner: SecurityExprRunner,\n expr: SecurityExpr,\n secondary: StreamState,\n): void {\n if (runner.callback === undefined) runner.callback = expr;\n const length = secondary.ohlcv.close.length;\n while (runner.processedHtfCount < length) {\n const age = length - 1 - runner.processedHtfCount;\n foldClose(runner, barFromStream(secondary, age));\n }\n}\n\n/**\n * Materialise a `Float64RingBuffer`'s values oldest→newest. Used as the\n * `htfSeries` source when aligning a runner's output buffer to the main\n * timeline.\n *\n * @since 0.7\n * @stable\n * @example\n * // const values = ascendingValues(runner.output);\n * const order = \"oldest -> newest\";\n * void order;\n */\nexport function ascendingValues(buffer: Float64RingBuffer): ReadonlyArray<number> {\n const values: number[] = [];\n for (let age = buffer.length - 1; age >= 0; age -= 1) {\n values.push(buffer.at(age));\n }\n return values;\n}\n"]}
|
package/dist/ringBuffer.d.ts
CHANGED
|
@@ -91,5 +91,24 @@ export declare class Float64RingBuffer implements RingBufferLike<number> {
|
|
|
91
91
|
values: ReadonlyArray<number | null>;
|
|
92
92
|
}>): void;
|
|
93
93
|
reset(): void;
|
|
94
|
+
/**
|
|
95
|
+
* Overwrite this ring's entire state with a copy of `other`'s. A single
|
|
96
|
+
* `Float64Array.prototype.set()` memcpy plus a head/filled copy — `O(capacity)`
|
|
97
|
+
* with a small constant, not an element loop. `state.array`'s two-ring tick
|
|
98
|
+
* discipline (`packages/runtime/src/state/arrayStateSlot.ts`) calls this every
|
|
99
|
+
* tick to roll the tentative ring back to committed (and on close to commit it),
|
|
100
|
+
* so the typed-array `set()` is load-bearing for the hot path. Both rings in a
|
|
101
|
+
* slot share `capacity`, so this never reshapes the backing array.
|
|
102
|
+
*
|
|
103
|
+
* @since 1.3
|
|
104
|
+
* @stable
|
|
105
|
+
* @example
|
|
106
|
+
* const a = new Float64RingBuffer(4);
|
|
107
|
+
* const b = new Float64RingBuffer(4);
|
|
108
|
+
* a.append(1);
|
|
109
|
+
* b.copyFrom(a);
|
|
110
|
+
* b.at(0); // 1
|
|
111
|
+
*/
|
|
112
|
+
copyFrom(other: Float64RingBuffer): void;
|
|
94
113
|
}
|
|
95
114
|
//# sourceMappingURL=ringBuffer.d.ts.map
|
package/dist/ringBuffer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ringBuffer.d.ts","sourceRoot":"","sources":["../src/ringBuffer.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACnB,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACxB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,UAAU,CAAC,CAAC,CAAE,YAAW,cAAc,CAAC,CAAC,CAAC;aAKvB,QAAQ,EAAE,MAAM;IAJ5C,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,MAAM,CAAK;gBAES,QAAQ,EAAE,MAAM;IAI5C,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI;IAMlB,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI;IAQvB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAK5B,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,KAAK,IAAI,IAAI;CAKhB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,iBAAkB,YAAW,cAAc,CAAC,MAAM,CAAC;aAKhC,QAAQ,EAAE,MAAM;IAJ5C,OAAO,CAAC,GAAG,CAAe;IAC1B,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,MAAM,CAAK;gBAES,QAAQ,EAAE,MAAM;IAI5C,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAMvB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ5B,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAKrB,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,uBAAuB,IAAI,QAAQ,CAAC;QAChC,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;KACxC,CAAC;IAYF,yBAAyB,CACrB,IAAI,EAAE,QAAQ,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;KACxC,CAAC,GACH,IAAI;IAwBP,KAAK,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"ringBuffer.d.ts","sourceRoot":"","sources":["../src/ringBuffer.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACnB,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACxB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,UAAU,CAAC,CAAC,CAAE,YAAW,cAAc,CAAC,CAAC,CAAC;aAKvB,QAAQ,EAAE,MAAM;IAJ5C,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,MAAM,CAAK;gBAES,QAAQ,EAAE,MAAM;IAI5C,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI;IAMlB,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI;IAQvB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAK5B,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,KAAK,IAAI,IAAI;CAKhB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,iBAAkB,YAAW,cAAc,CAAC,MAAM,CAAC;aAKhC,QAAQ,EAAE,MAAM;IAJ5C,OAAO,CAAC,GAAG,CAAe;IAC1B,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,MAAM,CAAK;gBAES,QAAQ,EAAE,MAAM;IAI5C,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAMvB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ5B,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAKrB,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,uBAAuB,IAAI,QAAQ,CAAC;QAChC,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;KACxC,CAAC;IAYF,yBAAyB,CACrB,IAAI,EAAE,QAAQ,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;KACxC,CAAC,GACH,IAAI;IAwBP,KAAK,IAAI,IAAI;IAMb;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;CAK3C"}
|
package/dist/ringBuffer.js
CHANGED
|
@@ -142,5 +142,28 @@ export class Float64RingBuffer {
|
|
|
142
142
|
this.head = -1;
|
|
143
143
|
this.filled = 0;
|
|
144
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Overwrite this ring's entire state with a copy of `other`'s. A single
|
|
147
|
+
* `Float64Array.prototype.set()` memcpy plus a head/filled copy — `O(capacity)`
|
|
148
|
+
* with a small constant, not an element loop. `state.array`'s two-ring tick
|
|
149
|
+
* discipline (`packages/runtime/src/state/arrayStateSlot.ts`) calls this every
|
|
150
|
+
* tick to roll the tentative ring back to committed (and on close to commit it),
|
|
151
|
+
* so the typed-array `set()` is load-bearing for the hot path. Both rings in a
|
|
152
|
+
* slot share `capacity`, so this never reshapes the backing array.
|
|
153
|
+
*
|
|
154
|
+
* @since 1.3
|
|
155
|
+
* @stable
|
|
156
|
+
* @example
|
|
157
|
+
* const a = new Float64RingBuffer(4);
|
|
158
|
+
* const b = new Float64RingBuffer(4);
|
|
159
|
+
* a.append(1);
|
|
160
|
+
* b.copyFrom(a);
|
|
161
|
+
* b.at(0); // 1
|
|
162
|
+
*/
|
|
163
|
+
copyFrom(other) {
|
|
164
|
+
this.buf.set(other.buf);
|
|
165
|
+
this.head = other.head;
|
|
166
|
+
this.filled = other.filled;
|
|
167
|
+
}
|
|
145
168
|
}
|
|
146
169
|
//# sourceMappingURL=ringBuffer.js.map
|
package/dist/ringBuffer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ringBuffer.js","sourceRoot":"","sources":["../src/ringBuffer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\n/**\n * Shared contract for the two ring-buffer flavours the runtime ships\n * (`RingBuffer<T>` for object payloads, `Float64RingBuffer` for numeric\n * payloads). Both share one read contract — `at(n)` returns `undefined` on\n * out-of-range reads in the generic shape; `Float64RingBuffer` narrows\n * the return to `number` with `NaN` as the OOR sentinel.\n *\n * @since 0.1\n * @example\n * const buf: RingBufferLike<number> = new Float64RingBuffer(8);\n * buf.append(42);\n * buf.at(0); // 42\n */\nexport interface RingBufferLike<T> {\n readonly capacity: number;\n readonly length: number;\n append(v: T): void;\n replaceHead(v: T): void;\n at(n: number): T | undefined;\n reset(): void;\n}\n\n/**\n * Generic ring buffer over an `Array<T>`. Backs object-valued\n * `Series<T>` (e.g. Phase-3 drawing handles). For numeric series use\n * `Float64RingBuffer` — it avoids the array-pointer indirection on\n * every read.\n *\n * Out-of-range `at(n)` returns `undefined`. `replaceHead` on an empty\n * buffer behaves like `append` so the first call after construction\n * does not need a special-case branch in callers.\n *\n * @since 0.1\n * @example\n * const buf = new RingBuffer<string>(3);\n * buf.append(\"a\");\n * buf.append(\"b\");\n * buf.append(\"c\");\n * buf.append(\"d\"); // overwrites \"a\"\n * buf.at(0); // \"d\"\n * buf.at(2); // \"b\"\n */\nexport class RingBuffer<T> implements RingBufferLike<T> {\n private buf: Array<T | undefined>;\n private head = -1;\n private filled = 0;\n\n constructor(public readonly capacity: number) {\n this.buf = new Array<T | undefined>(capacity);\n }\n\n append(v: T): void {\n this.head = (this.head + 1) % this.capacity;\n this.buf[this.head] = v;\n if (this.filled < this.capacity) this.filled += 1;\n }\n\n replaceHead(v: T): void {\n if (this.head === -1) {\n this.append(v);\n return;\n }\n this.buf[this.head] = v;\n }\n\n at(n: number): T | undefined {\n if (n < 0 || n >= this.filled) return undefined;\n return this.buf[(this.head - n + this.capacity) % this.capacity];\n }\n\n get length(): number {\n return this.filled;\n }\n\n reset(): void {\n this.buf = new Array<T | undefined>(this.capacity);\n this.head = -1;\n this.filled = 0;\n }\n}\n\n/**\n * Numeric ring buffer backed by a `Float64Array`. Reads are direct\n * memory hits — no boxing, no map lookup. Out-of-range reads return\n * `NaN` (the language-wide warmup sentinel), which\n * is the correct value for unwarmed indicator slots.\n *\n * `at(n)` narrows the shared `RingBufferLike<T>`'s `T | undefined`\n * return to plain `number` in a covariant return position; callers\n * that hold this concrete class see `number`, callers that hold\n * the wider interface see `number | undefined`.\n *\n * @since 0.1\n * @example\n * const buf = new Float64RingBuffer(4);\n * buf.append(1.0);\n * buf.append(2.0);\n * buf.at(0); // 2\n * buf.at(5); // NaN\n */\nexport class Float64RingBuffer implements RingBufferLike<number> {\n private buf: Float64Array;\n private head = -1;\n private filled = 0;\n\n constructor(public readonly capacity: number) {\n this.buf = new Float64Array(capacity);\n }\n\n append(v: number): void {\n this.head = (this.head + 1) % this.capacity;\n this.buf[this.head] = v;\n if (this.filled < this.capacity) this.filled += 1;\n }\n\n replaceHead(v: number): void {\n if (this.head === -1) {\n this.append(v);\n return;\n }\n this.buf[this.head] = v;\n }\n\n at(n: number): number {\n if (n < 0 || n >= this.filled) return Number.NaN;\n return this.buf[(this.head - n + this.capacity) % this.capacity];\n }\n\n get length(): number {\n return this.filled;\n }\n\n serialiseSnapshotBuffer(): Readonly<{\n headIndex: number;\n filled: number;\n values: ReadonlyArray<number | null>;\n }> {\n const values: Array<number | null> = [];\n for (const value of this.buf) {\n values.push(Number.isNaN(value) ? null : value);\n }\n return Object.freeze({\n headIndex: this.head,\n filled: this.filled,\n values: Object.freeze(values),\n });\n }\n\n restoreFromSnapshotBuffer(\n args: Readonly<{\n headIndex: number;\n filled: number;\n values: ReadonlyArray<number | null>;\n }>,\n ): void {\n if (\n args.values.length !== this.capacity ||\n !Number.isInteger(args.headIndex) ||\n args.headIndex < -1 ||\n args.headIndex >= this.capacity ||\n !Number.isInteger(args.filled) ||\n args.filled < 0 ||\n args.filled > this.capacity ||\n (args.filled === 0 && args.headIndex !== -1) ||\n (args.filled > 0 && args.headIndex < 0)\n ) {\n throw new Error(\"invalid ring buffer snapshot\");\n }\n const next = new Float64Array(this.capacity);\n for (let i = 0; i < args.values.length; i += 1) {\n const value = args.values[i];\n next[i] = value === null ? Number.NaN : value;\n }\n this.buf = next;\n this.head = args.headIndex;\n this.filled = args.filled;\n }\n\n reset(): void {\n this.buf = new Float64Array(this.capacity);\n this.head = -1;\n this.filled = 0;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ringBuffer.js","sourceRoot":"","sources":["../src/ringBuffer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\n/**\n * Shared contract for the two ring-buffer flavours the runtime ships\n * (`RingBuffer<T>` for object payloads, `Float64RingBuffer` for numeric\n * payloads). Both share one read contract — `at(n)` returns `undefined` on\n * out-of-range reads in the generic shape; `Float64RingBuffer` narrows\n * the return to `number` with `NaN` as the OOR sentinel.\n *\n * @since 0.1\n * @example\n * const buf: RingBufferLike<number> = new Float64RingBuffer(8);\n * buf.append(42);\n * buf.at(0); // 42\n */\nexport interface RingBufferLike<T> {\n readonly capacity: number;\n readonly length: number;\n append(v: T): void;\n replaceHead(v: T): void;\n at(n: number): T | undefined;\n reset(): void;\n}\n\n/**\n * Generic ring buffer over an `Array<T>`. Backs object-valued\n * `Series<T>` (e.g. Phase-3 drawing handles). For numeric series use\n * `Float64RingBuffer` — it avoids the array-pointer indirection on\n * every read.\n *\n * Out-of-range `at(n)` returns `undefined`. `replaceHead` on an empty\n * buffer behaves like `append` so the first call after construction\n * does not need a special-case branch in callers.\n *\n * @since 0.1\n * @example\n * const buf = new RingBuffer<string>(3);\n * buf.append(\"a\");\n * buf.append(\"b\");\n * buf.append(\"c\");\n * buf.append(\"d\"); // overwrites \"a\"\n * buf.at(0); // \"d\"\n * buf.at(2); // \"b\"\n */\nexport class RingBuffer<T> implements RingBufferLike<T> {\n private buf: Array<T | undefined>;\n private head = -1;\n private filled = 0;\n\n constructor(public readonly capacity: number) {\n this.buf = new Array<T | undefined>(capacity);\n }\n\n append(v: T): void {\n this.head = (this.head + 1) % this.capacity;\n this.buf[this.head] = v;\n if (this.filled < this.capacity) this.filled += 1;\n }\n\n replaceHead(v: T): void {\n if (this.head === -1) {\n this.append(v);\n return;\n }\n this.buf[this.head] = v;\n }\n\n at(n: number): T | undefined {\n if (n < 0 || n >= this.filled) return undefined;\n return this.buf[(this.head - n + this.capacity) % this.capacity];\n }\n\n get length(): number {\n return this.filled;\n }\n\n reset(): void {\n this.buf = new Array<T | undefined>(this.capacity);\n this.head = -1;\n this.filled = 0;\n }\n}\n\n/**\n * Numeric ring buffer backed by a `Float64Array`. Reads are direct\n * memory hits — no boxing, no map lookup. Out-of-range reads return\n * `NaN` (the language-wide warmup sentinel), which\n * is the correct value for unwarmed indicator slots.\n *\n * `at(n)` narrows the shared `RingBufferLike<T>`'s `T | undefined`\n * return to plain `number` in a covariant return position; callers\n * that hold this concrete class see `number`, callers that hold\n * the wider interface see `number | undefined`.\n *\n * @since 0.1\n * @example\n * const buf = new Float64RingBuffer(4);\n * buf.append(1.0);\n * buf.append(2.0);\n * buf.at(0); // 2\n * buf.at(5); // NaN\n */\nexport class Float64RingBuffer implements RingBufferLike<number> {\n private buf: Float64Array;\n private head = -1;\n private filled = 0;\n\n constructor(public readonly capacity: number) {\n this.buf = new Float64Array(capacity);\n }\n\n append(v: number): void {\n this.head = (this.head + 1) % this.capacity;\n this.buf[this.head] = v;\n if (this.filled < this.capacity) this.filled += 1;\n }\n\n replaceHead(v: number): void {\n if (this.head === -1) {\n this.append(v);\n return;\n }\n this.buf[this.head] = v;\n }\n\n at(n: number): number {\n if (n < 0 || n >= this.filled) return Number.NaN;\n return this.buf[(this.head - n + this.capacity) % this.capacity];\n }\n\n get length(): number {\n return this.filled;\n }\n\n serialiseSnapshotBuffer(): Readonly<{\n headIndex: number;\n filled: number;\n values: ReadonlyArray<number | null>;\n }> {\n const values: Array<number | null> = [];\n for (const value of this.buf) {\n values.push(Number.isNaN(value) ? null : value);\n }\n return Object.freeze({\n headIndex: this.head,\n filled: this.filled,\n values: Object.freeze(values),\n });\n }\n\n restoreFromSnapshotBuffer(\n args: Readonly<{\n headIndex: number;\n filled: number;\n values: ReadonlyArray<number | null>;\n }>,\n ): void {\n if (\n args.values.length !== this.capacity ||\n !Number.isInteger(args.headIndex) ||\n args.headIndex < -1 ||\n args.headIndex >= this.capacity ||\n !Number.isInteger(args.filled) ||\n args.filled < 0 ||\n args.filled > this.capacity ||\n (args.filled === 0 && args.headIndex !== -1) ||\n (args.filled > 0 && args.headIndex < 0)\n ) {\n throw new Error(\"invalid ring buffer snapshot\");\n }\n const next = new Float64Array(this.capacity);\n for (let i = 0; i < args.values.length; i += 1) {\n const value = args.values[i];\n next[i] = value === null ? Number.NaN : value;\n }\n this.buf = next;\n this.head = args.headIndex;\n this.filled = args.filled;\n }\n\n reset(): void {\n this.buf = new Float64Array(this.capacity);\n this.head = -1;\n this.filled = 0;\n }\n\n /**\n * Overwrite this ring's entire state with a copy of `other`'s. A single\n * `Float64Array.prototype.set()` memcpy plus a head/filled copy — `O(capacity)`\n * with a small constant, not an element loop. `state.array`'s two-ring tick\n * discipline (`packages/runtime/src/state/arrayStateSlot.ts`) calls this every\n * tick to roll the tentative ring back to committed (and on close to commit it),\n * so the typed-array `set()` is load-bearing for the hot path. Both rings in a\n * slot share `capacity`, so this never reshapes the backing array.\n *\n * @since 1.3\n * @stable\n * @example\n * const a = new Float64RingBuffer(4);\n * const b = new Float64RingBuffer(4);\n * a.append(1);\n * b.copyFrom(a);\n * b.at(0); // 1\n */\n copyFrom(other: Float64RingBuffer): void {\n this.buf.set(other.buf);\n this.head = other.head;\n this.filled = other.filled;\n }\n}\n"]}
|
package/dist/runtimeContext.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { AlertConditionDefinition, Bar, DrawingBucket, DrawingCounts, Drawi
|
|
|
3
3
|
import type { DepOutputStore } from "./dep/DepOutputStore.js";
|
|
4
4
|
import type { PersistentStateStore } from "./persistentStateStore.js";
|
|
5
5
|
import type { SecurityExprRunner } from "./request/securityExprRunner.js";
|
|
6
|
+
import type { ArrayStateSlot } from "./state/arrayStateSlot.js";
|
|
6
7
|
import type { SeriesSlot } from "./state/seriesSlot.js";
|
|
7
8
|
import type { StateSlot } from "./state/stateSlot.js";
|
|
8
9
|
import type { StateStore } from "./stateStore.js";
|
|
@@ -161,20 +162,46 @@ export type RuntimeContext = {
|
|
|
161
162
|
*/
|
|
162
163
|
readonly seriesSlots: Map<string, SeriesSlot>;
|
|
163
164
|
/**
|
|
164
|
-
*
|
|
165
|
-
*
|
|
165
|
+
* Runtime `state.array` slot store keyed by
|
|
166
|
+
* `${slotIdPrefix ?? ""}${slotId}:array`. Each holds two
|
|
167
|
+
* `Float64RingBuffer`s (committed + tentative) behind an identity-stable
|
|
168
|
+
* bounded-FIFO handle. A parallel map (vs folding into `stateSlots`)
|
|
169
|
+
* mirrors the `state.series` precedent — both collection primitives share
|
|
170
|
+
* the two-ring shape and snapshot directly from the live map with no
|
|
171
|
+
* `StateStore` flush. Cleared on `dispose`. @since 1.3
|
|
172
|
+
*/
|
|
173
|
+
readonly arraySlots: Map<string, ArrayStateSlot>;
|
|
174
|
+
/**
|
|
175
|
+
* The chart's own symbol, resolved once at mount from the adapter
|
|
176
|
+
* `syminfo.ticker` (`""` when the adapter supplies none). A
|
|
177
|
+
* `request.security` call that omits `symbol` — or passes this exact
|
|
178
|
+
* ticker — resolves to it and collapses to the bare-interval
|
|
179
|
+
* {@link feedKey}, so the chart-symbol path is byte-identical to the
|
|
180
|
+
* pre-multi-symbol baseline. Only a *different* symbol allocates a
|
|
181
|
+
* `"<symbol>@<interval>"` feed. @since 1.3
|
|
182
|
+
*/
|
|
183
|
+
readonly chartSymbol: string;
|
|
184
|
+
/**
|
|
185
|
+
* Secondary candle streams keyed by the composite
|
|
186
|
+
* `feedKey(symbol, interval)` (the shared core helper). A symbol-omitted
|
|
187
|
+
* feed collapses to the bare interval — `feedKey(undefined, "1D") === "1D"`
|
|
188
|
+
* — so the chart-symbol path is byte-identical to the pre-multi-symbol
|
|
189
|
+
* baseline; a non-chart symbol keys as `"<symbol>@<interval>"`. Mutated only
|
|
190
|
+
* by `createScriptRunner` mount/restore/routing. @since 0.5
|
|
166
191
|
*/
|
|
167
192
|
readonly secondaryStreams: Map<string, StreamState>;
|
|
168
193
|
/**
|
|
169
|
-
* Per-`request.security` slot cache keyed by `slotId|
|
|
194
|
+
* Per-`request.security` slot cache keyed by `slotId|feedKey`. Phase 4
|
|
170
195
|
* stores NaN fallback bars here; Phase 5 replaces the value producer with
|
|
171
|
-
* aligned secondary stream series while preserving stable identity.
|
|
196
|
+
* aligned secondary stream series while preserving stable identity. The
|
|
197
|
+
* `feedKey` collapses to the bare interval for chart-symbol requests, so
|
|
198
|
+
* the omitted-symbol cache key is byte-identical to the baseline.
|
|
172
199
|
* @since 0.4
|
|
173
200
|
*/
|
|
174
201
|
readonly requestSecurityBars: Map<string, SecurityBar>;
|
|
175
202
|
/**
|
|
176
203
|
* Per-compute aligned numeric arrays keyed by
|
|
177
|
-
* `slotId|
|
|
204
|
+
* `slotId|feedKey|sourceKey`. Cleared on main-stream close/tick before
|
|
178
205
|
* `compute` so `request.security` re-aligns against the latest
|
|
179
206
|
* secondary buffers. @since 0.5
|
|
180
207
|
*/
|
|
@@ -199,16 +226,18 @@ export type RuntimeContext = {
|
|
|
199
226
|
*/
|
|
200
227
|
securityExprRunners?: Map<string, SecurityExprRunner>;
|
|
201
228
|
/**
|
|
202
|
-
* Per-
|
|
203
|
-
* `
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
229
|
+
* Per-feed index into {@link securityExprRunners}, keyed by the composite
|
|
230
|
+
* `feedKey(symbol, interval)`. `driveSecurityExpressions` fans a secondary
|
|
231
|
+
* close / tick (tagged with that same composite key on
|
|
232
|
+
* `CandleEvent.streamKey`) out to every runner on that feed. A
|
|
233
|
+
* symbol-omitted callsite collapses to the bare interval, byte-identical to
|
|
234
|
+
* the pre-multi-symbol baseline. Absent when no expression callsites are
|
|
235
|
+
* declared. Cleared on `dispose`. @since 0.7
|
|
207
236
|
*/
|
|
208
|
-
|
|
237
|
+
securityExprRunnersByFeed?: ReadonlyMap<string, ReadonlyArray<SecurityExprRunner>>;
|
|
209
238
|
/**
|
|
210
239
|
* Per-compute aligned expression-output series cache keyed by
|
|
211
|
-
* `slotId|
|
|
240
|
+
* `slotId|feedKey`. Holds the stable `Series<number>` Proxy each
|
|
212
241
|
* expression-form `request.security` returns; cleared each bar
|
|
213
242
|
* (alongside {@link requestSecurityAlignments}) so the proxy re-aligns
|
|
214
243
|
* the runner's output buffer against the latest secondary buffers.
|
|
@@ -226,6 +255,14 @@ export type RuntimeContext = {
|
|
|
226
255
|
* `code|slotId|interval|kind`. Cleared on `dispose`. @since 0.4
|
|
227
256
|
*/
|
|
228
257
|
readonly diagnosedRequestKeys: Set<string>;
|
|
258
|
+
/**
|
|
259
|
+
* Runtime diagnostic dedupe for `time.*` / `session.*` DST-zone
|
|
260
|
+
* fallbacks, keyed by `tz-dst-unsupported|<tz>`. The calendar accessors
|
|
261
|
+
* are `slot: false` (no slotId to key on), so they dedupe on the
|
|
262
|
+
* timezone string here — a DST zone warns at most once per distinct tz
|
|
263
|
+
* per mount. Cleared on `dispose`. @since 1.5
|
|
264
|
+
*/
|
|
265
|
+
readonly diagnosedTzKeys: Set<string>;
|
|
229
266
|
/**
|
|
230
267
|
* Manifest-declared alert conditions keyed by condition id. Used by
|
|
231
268
|
* `signal(conditionId, fired)` to reject unknown ids without
|