@invinite-org/chartlang-runtime 1.1.1 → 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.
Files changed (294) hide show
  1. package/CHANGELOG.md +307 -0
  2. package/dist/barPoint.d.ts +20 -0
  3. package/dist/barPoint.d.ts.map +1 -0
  4. package/dist/barPoint.js +72 -0
  5. package/dist/barPoint.js.map +1 -0
  6. package/dist/bufferSnapshot.d.ts +102 -0
  7. package/dist/bufferSnapshot.d.ts.map +1 -0
  8. package/dist/bufferSnapshot.js +119 -0
  9. package/dist/bufferSnapshot.js.map +1 -0
  10. package/dist/buildComputeContext.d.ts.map +1 -1
  11. package/dist/buildComputeContext.js +6 -1
  12. package/dist/buildComputeContext.js.map +1 -1
  13. package/dist/createScriptRunner.d.ts +6 -3
  14. package/dist/createScriptRunner.d.ts.map +1 -1
  15. package/dist/createScriptRunner.js +65 -11
  16. package/dist/createScriptRunner.js.map +1 -1
  17. package/dist/dep/DepRunner.d.ts +7 -0
  18. package/dist/dep/DepRunner.d.ts.map +1 -1
  19. package/dist/dep/DepRunner.js +4 -0
  20. package/dist/dep/DepRunner.js.map +1 -1
  21. package/dist/emit/barcolor.d.ts +44 -0
  22. package/dist/emit/barcolor.d.ts.map +1 -0
  23. package/dist/emit/barcolor.js +40 -0
  24. package/dist/emit/barcolor.js.map +1 -0
  25. package/dist/emit/bgcolor.d.ts +44 -0
  26. package/dist/emit/bgcolor.d.ts.map +1 -0
  27. package/dist/emit/bgcolor.js +45 -0
  28. package/dist/emit/bgcolor.js.map +1 -0
  29. package/dist/emit/draw/boxes/fillBetween.d.ts +45 -0
  30. package/dist/emit/draw/boxes/fillBetween.d.ts.map +1 -0
  31. package/dist/emit/draw/boxes/fillBetween.js +36 -0
  32. package/dist/emit/draw/boxes/fillBetween.js.map +1 -0
  33. package/dist/emit/draw/handle.d.ts +9 -0
  34. package/dist/emit/draw/handle.d.ts.map +1 -1
  35. package/dist/emit/draw/handle.js +65 -10
  36. package/dist/emit/draw/handle.js.map +1 -1
  37. package/dist/emit/draw/namespace.d.ts +4 -3
  38. package/dist/emit/draw/namespace.d.ts.map +1 -1
  39. package/dist/emit/draw/namespace.js +6 -3
  40. package/dist/emit/draw/namespace.js.map +1 -1
  41. package/dist/emit/index.d.ts +2 -0
  42. package/dist/emit/index.d.ts.map +1 -1
  43. package/dist/emit/index.js +2 -0
  44. package/dist/emit/index.js.map +1 -1
  45. package/dist/emit/plot.d.ts +30 -1
  46. package/dist/emit/plot.d.ts.map +1 -1
  47. package/dist/emit/plot.js +45 -1
  48. package/dist/emit/plot.js.map +1 -1
  49. package/dist/execution/dispose.d.ts.map +1 -1
  50. package/dist/execution/dispose.js +18 -0
  51. package/dist/execution/dispose.js.map +1 -1
  52. package/dist/execution/runComputeStep.d.ts.map +1 -1
  53. package/dist/execution/runComputeStep.js +12 -1
  54. package/dist/execution/runComputeStep.js.map +1 -1
  55. package/dist/index.d.ts +1 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +1 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/inputs/resolveInputs.js +1 -0
  60. package/dist/inputs/resolveInputs.js.map +1 -1
  61. package/dist/persistentStateStore.runtime.d.ts.map +1 -1
  62. package/dist/persistentStateStore.runtime.js +26 -7
  63. package/dist/persistentStateStore.runtime.js.map +1 -1
  64. package/dist/primitives.d.ts +1 -1
  65. package/dist/primitives.d.ts.map +1 -1
  66. package/dist/primitives.js +7 -1
  67. package/dist/primitives.js.map +1 -1
  68. package/dist/request/index.d.ts +2 -1
  69. package/dist/request/index.d.ts.map +1 -1
  70. package/dist/request/index.js +2 -1
  71. package/dist/request/index.js.map +1 -1
  72. package/dist/request/lowerTf.d.ts.map +1 -1
  73. package/dist/request/lowerTf.js +6 -0
  74. package/dist/request/lowerTf.js.map +1 -1
  75. package/dist/request/requestNamespace.d.ts.map +1 -1
  76. package/dist/request/requestNamespace.js +30 -3
  77. package/dist/request/requestNamespace.js.map +1 -1
  78. package/dist/request/security.d.ts +40 -4
  79. package/dist/request/security.d.ts.map +1 -1
  80. package/dist/request/security.js +114 -40
  81. package/dist/request/security.js.map +1 -1
  82. package/dist/request/securityExprRunner.d.ts +137 -0
  83. package/dist/request/securityExprRunner.d.ts.map +1 -0
  84. package/dist/request/securityExprRunner.js +253 -0
  85. package/dist/request/securityExprRunner.js.map +1 -0
  86. package/dist/request/streamBars.d.ts +14 -1
  87. package/dist/request/streamBars.d.ts.map +1 -1
  88. package/dist/request/streamBars.js +39 -1
  89. package/dist/request/streamBars.js.map +1 -1
  90. package/dist/ringBuffer.d.ts +19 -0
  91. package/dist/ringBuffer.d.ts.map +1 -1
  92. package/dist/ringBuffer.js +23 -0
  93. package/dist/ringBuffer.js.map +1 -1
  94. package/dist/runtimeContext.d.ts +90 -5
  95. package/dist/runtimeContext.d.ts.map +1 -1
  96. package/dist/runtimeContext.js.map +1 -1
  97. package/dist/seriesView.d.ts +42 -17
  98. package/dist/seriesView.d.ts.map +1 -1
  99. package/dist/seriesView.js +65 -42
  100. package/dist/seriesView.js.map +1 -1
  101. package/dist/state/arrayPersistence.d.ts +48 -0
  102. package/dist/state/arrayPersistence.d.ts.map +1 -0
  103. package/dist/state/arrayPersistence.js +88 -0
  104. package/dist/state/arrayPersistence.js.map +1 -0
  105. package/dist/state/arrayStateSlot.d.ts +78 -0
  106. package/dist/state/arrayStateSlot.d.ts.map +1 -0
  107. package/dist/state/arrayStateSlot.js +116 -0
  108. package/dist/state/arrayStateSlot.js.map +1 -0
  109. package/dist/state/index.d.ts +4 -1
  110. package/dist/state/index.d.ts.map +1 -1
  111. package/dist/state/index.js +4 -1
  112. package/dist/state/index.js.map +1 -1
  113. package/dist/state/lifecycle.d.ts +68 -0
  114. package/dist/state/lifecycle.d.ts.map +1 -1
  115. package/dist/state/lifecycle.js +89 -0
  116. package/dist/state/lifecycle.js.map +1 -1
  117. package/dist/state/seriesPersistence.d.ts +48 -0
  118. package/dist/state/seriesPersistence.d.ts.map +1 -0
  119. package/dist/state/seriesPersistence.js +87 -0
  120. package/dist/state/seriesPersistence.js.map +1 -0
  121. package/dist/state/seriesSlot.d.ts +105 -0
  122. package/dist/state/seriesSlot.d.ts.map +1 -0
  123. package/dist/state/seriesSlot.js +123 -0
  124. package/dist/state/seriesSlot.js.map +1 -0
  125. package/dist/state/stateNamespace.d.ts.map +1 -1
  126. package/dist/state/stateNamespace.js +55 -0
  127. package/dist/state/stateNamespace.js.map +1 -1
  128. package/dist/streamState.d.ts +25 -19
  129. package/dist/streamState.d.ts.map +1 -1
  130. package/dist/streamState.js +40 -66
  131. package/dist/streamState.js.map +1 -1
  132. package/dist/ta/adx.d.ts +3 -2
  133. package/dist/ta/adx.d.ts.map +1 -1
  134. package/dist/ta/adx.js +3 -2
  135. package/dist/ta/adx.js.map +1 -1
  136. package/dist/ta/alma.d.ts +6 -4
  137. package/dist/ta/alma.d.ts.map +1 -1
  138. package/dist/ta/alma.js +19 -6
  139. package/dist/ta/alma.js.map +1 -1
  140. package/dist/ta/atr.d.ts +3 -2
  141. package/dist/ta/atr.d.ts.map +1 -1
  142. package/dist/ta/atr.js +3 -2
  143. package/dist/ta/atr.js.map +1 -1
  144. package/dist/ta/bb.d.ts +3 -2
  145. package/dist/ta/bb.d.ts.map +1 -1
  146. package/dist/ta/bb.js +3 -2
  147. package/dist/ta/bb.js.map +1 -1
  148. package/dist/ta/chaikinOsc.d.ts +3 -2
  149. package/dist/ta/chaikinOsc.d.ts.map +1 -1
  150. package/dist/ta/chaikinOsc.js +3 -2
  151. package/dist/ta/chaikinOsc.js.map +1 -1
  152. package/dist/ta/crossover.d.ts +3 -2
  153. package/dist/ta/crossover.d.ts.map +1 -1
  154. package/dist/ta/crossover.js +3 -2
  155. package/dist/ta/crossover.js.map +1 -1
  156. package/dist/ta/crossunder.d.ts +3 -2
  157. package/dist/ta/crossunder.d.ts.map +1 -1
  158. package/dist/ta/crossunder.js +3 -2
  159. package/dist/ta/crossunder.js.map +1 -1
  160. package/dist/ta/dmi.d.ts +4 -3
  161. package/dist/ta/dmi.d.ts.map +1 -1
  162. package/dist/ta/dmi.js +4 -3
  163. package/dist/ta/dmi.js.map +1 -1
  164. package/dist/ta/ema.d.ts +3 -2
  165. package/dist/ta/ema.d.ts.map +1 -1
  166. package/dist/ta/ema.js +3 -2
  167. package/dist/ta/ema.js.map +1 -1
  168. package/dist/ta/eom.d.ts +3 -1
  169. package/dist/ta/eom.d.ts.map +1 -1
  170. package/dist/ta/eom.js +3 -1
  171. package/dist/ta/eom.js.map +1 -1
  172. package/dist/ta/highestbars.d.ts +25 -0
  173. package/dist/ta/highestbars.d.ts.map +1 -0
  174. package/dist/ta/highestbars.js +106 -0
  175. package/dist/ta/highestbars.js.map +1 -0
  176. package/dist/ta/historicalVolatility.d.ts +3 -2
  177. package/dist/ta/historicalVolatility.d.ts.map +1 -1
  178. package/dist/ta/historicalVolatility.js +3 -2
  179. package/dist/ta/historicalVolatility.js.map +1 -1
  180. package/dist/ta/ichimoku.d.ts +3 -1
  181. package/dist/ta/ichimoku.d.ts.map +1 -1
  182. package/dist/ta/ichimoku.js +3 -1
  183. package/dist/ta/ichimoku.js.map +1 -1
  184. package/dist/ta/lowestbars.d.ts +25 -0
  185. package/dist/ta/lowestbars.d.ts.map +1 -0
  186. package/dist/ta/lowestbars.js +102 -0
  187. package/dist/ta/lowestbars.js.map +1 -0
  188. package/dist/ta/macd.d.ts +3 -2
  189. package/dist/ta/macd.d.ts.map +1 -1
  190. package/dist/ta/macd.js +3 -2
  191. package/dist/ta/macd.js.map +1 -1
  192. package/dist/ta/massIndex.d.ts +3 -2
  193. package/dist/ta/massIndex.d.ts.map +1 -1
  194. package/dist/ta/massIndex.js +3 -2
  195. package/dist/ta/massIndex.js.map +1 -1
  196. package/dist/ta/mfi.d.ts +3 -1
  197. package/dist/ta/mfi.d.ts.map +1 -1
  198. package/dist/ta/mfi.js +3 -1
  199. package/dist/ta/mfi.js.map +1 -1
  200. package/dist/ta/netVolume.d.ts +3 -1
  201. package/dist/ta/netVolume.d.ts.map +1 -1
  202. package/dist/ta/netVolume.js +3 -1
  203. package/dist/ta/netVolume.js.map +1 -1
  204. package/dist/ta/nvi.d.ts +3 -1
  205. package/dist/ta/nvi.d.ts.map +1 -1
  206. package/dist/ta/nvi.js +3 -1
  207. package/dist/ta/nvi.js.map +1 -1
  208. package/dist/ta/persistence.d.ts.map +1 -1
  209. package/dist/ta/persistence.js +1 -40
  210. package/dist/ta/persistence.js.map +1 -1
  211. package/dist/ta/ppo.d.ts +3 -2
  212. package/dist/ta/ppo.d.ts.map +1 -1
  213. package/dist/ta/ppo.js +3 -2
  214. package/dist/ta/ppo.js.map +1 -1
  215. package/dist/ta/pvi.d.ts +3 -1
  216. package/dist/ta/pvi.d.ts.map +1 -1
  217. package/dist/ta/pvi.js +3 -1
  218. package/dist/ta/pvi.js.map +1 -1
  219. package/dist/ta/pvo.d.ts +3 -1
  220. package/dist/ta/pvo.d.ts.map +1 -1
  221. package/dist/ta/pvo.js +3 -1
  222. package/dist/ta/pvo.js.map +1 -1
  223. package/dist/ta/pvt.d.ts +3 -1
  224. package/dist/ta/pvt.d.ts.map +1 -1
  225. package/dist/ta/pvt.js +3 -1
  226. package/dist/ta/pvt.js.map +1 -1
  227. package/dist/ta/registry.d.ts +7 -1
  228. package/dist/ta/registry.d.ts.map +1 -1
  229. package/dist/ta/registry.js +4 -0
  230. package/dist/ta/registry.js.map +1 -1
  231. package/dist/ta/rsi.d.ts +3 -2
  232. package/dist/ta/rsi.d.ts.map +1 -1
  233. package/dist/ta/rsi.js +3 -2
  234. package/dist/ta/rsi.js.map +1 -1
  235. package/dist/ta/rvi.d.ts +3 -2
  236. package/dist/ta/rvi.d.ts.map +1 -1
  237. package/dist/ta/rvi.js +3 -2
  238. package/dist/ta/rvi.js.map +1 -1
  239. package/dist/ta/sessionVolumeProfile.d.ts.map +1 -1
  240. package/dist/ta/sessionVolumeProfile.js +1 -17
  241. package/dist/ta/sessionVolumeProfile.js.map +1 -1
  242. package/dist/ta/sma.d.ts +6 -3
  243. package/dist/ta/sma.d.ts.map +1 -1
  244. package/dist/ta/sma.js +6 -3
  245. package/dist/ta/sma.js.map +1 -1
  246. package/dist/ta/stdev.d.ts +3 -2
  247. package/dist/ta/stdev.d.ts.map +1 -1
  248. package/dist/ta/stdev.js +3 -2
  249. package/dist/ta/stdev.js.map +1 -1
  250. package/dist/ta/trendStrengthIndex.d.ts +3 -2
  251. package/dist/ta/trendStrengthIndex.d.ts.map +1 -1
  252. package/dist/ta/trendStrengthIndex.js +3 -2
  253. package/dist/ta/trendStrengthIndex.js.map +1 -1
  254. package/dist/ta/trix.d.ts +4 -3
  255. package/dist/ta/trix.d.ts.map +1 -1
  256. package/dist/ta/trix.js +4 -3
  257. package/dist/ta/trix.js.map +1 -1
  258. package/dist/ta/vortex.d.ts +3 -2
  259. package/dist/ta/vortex.d.ts.map +1 -1
  260. package/dist/ta/vortex.js +3 -2
  261. package/dist/ta/vortex.js.map +1 -1
  262. package/dist/time-accessors/civil.d.ts +73 -0
  263. package/dist/time-accessors/civil.d.ts.map +1 -0
  264. package/dist/time-accessors/civil.js +105 -0
  265. package/dist/time-accessors/civil.js.map +1 -0
  266. package/dist/time-accessors/index.d.ts +8 -0
  267. package/dist/time-accessors/index.d.ts.map +1 -0
  268. package/dist/time-accessors/index.js +9 -0
  269. package/dist/time-accessors/index.js.map +1 -0
  270. package/dist/time-accessors/sessionAccessors.d.ts +50 -0
  271. package/dist/time-accessors/sessionAccessors.d.ts.map +1 -0
  272. package/dist/time-accessors/sessionAccessors.js +79 -0
  273. package/dist/time-accessors/sessionAccessors.js.map +1 -0
  274. package/dist/time-accessors/sessionWindow.d.ts +17 -0
  275. package/dist/time-accessors/sessionWindow.d.ts.map +1 -0
  276. package/dist/time-accessors/sessionWindow.js +41 -0
  277. package/dist/time-accessors/sessionWindow.js.map +1 -0
  278. package/dist/time-accessors/timeAccessors.d.ts +54 -0
  279. package/dist/time-accessors/timeAccessors.d.ts.map +1 -0
  280. package/dist/time-accessors/timeAccessors.js +132 -0
  281. package/dist/time-accessors/timeAccessors.js.map +1 -0
  282. package/dist/time-accessors/tzDiagnostic.d.ts +17 -0
  283. package/dist/time-accessors/tzDiagnostic.d.ts.map +1 -0
  284. package/dist/time-accessors/tzDiagnostic.js +34 -0
  285. package/dist/time-accessors/tzDiagnostic.js.map +1 -0
  286. package/dist/time-accessors/tzOffset.d.ts +31 -0
  287. package/dist/time-accessors/tzOffset.d.ts.map +1 -0
  288. package/dist/time-accessors/tzOffset.js +67 -0
  289. package/dist/time-accessors/tzOffset.js.map +1 -0
  290. package/package.json +3 -3
  291. package/dist/ta/lib/applyOffset.d.ts +0 -19
  292. package/dist/ta/lib/applyOffset.d.ts.map +0 -1
  293. package/dist/ta/lib/applyOffset.js +0 -38
  294. package/dist/ta/lib/applyOffset.js.map +0 -1
@@ -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 { ascendingBarsFor } 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\nfunction makeAlignedNumberSeries(\n ctx: RuntimeContext,\n slotId: string,\n interval: string,\n sourceKey: NumericSourceKey,\n secondary: StreamState,\n): Series<number> {\n const target = {\n get current() {\n const aligned = alignedSeries(ctx, slotId, interval, sourceKey, secondary);\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 = alignedSeries(ctx, slotId, interval, sourceKey, secondary);\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 makeConstantStringSeries(value: string): Series<string> {\n const target = {\n get current() {\n return value;\n },\n get length() {\n return 0;\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) return value;\n }\n return Reflect.get(obj, prop, receiver);\n },\n }) as Series<string>;\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"]}
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\";\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"]}
@@ -0,0 +1,137 @@
1
+ import type { Bar, ScriptManifest, SecurityBar, SecurityExpr } from "@invinite-org/chartlang-core";
2
+ import { type RuntimeContext } from "../runtimeContext.js";
3
+ import { Float64RingBuffer } from "../ringBuffer.js";
4
+ import { type StreamState } from "../streamState.js";
5
+ /**
6
+ * One mounted higher-timeframe expression unit. The compiler records each
7
+ * `request.security({ interval }, (bar) => …)` callsite in
8
+ * `manifest.securityExpressions`; the runtime mounts one runner per entry.
9
+ *
10
+ * The runner owns a dedicated fold {@link StreamState} clocked on the HTF
11
+ * `interval`, a `Float64RingBuffer` output buffer (one sampled value per HTF
12
+ * bar), a fold {@link SecurityBar} view backed by the fold stream's head, and
13
+ * a private {@link RuntimeContext} (`stream = foldStream`,
14
+ * `slotIdPrefix = "security:<slotId>/"`) so `ta.*` inside the callback
15
+ * accumulate on the HTF clock without colliding with the main stream.
16
+ *
17
+ * `callback` is captured lazily the first time the main compute body calls
18
+ * `request.security(slotId, opts, expr)`. `processedHtfCount` tracks how many
19
+ * HTF bars have already been folded into `output` so replay catches up history
20
+ * exactly once.
21
+ *
22
+ * @since 0.7
23
+ * @stable
24
+ * @example
25
+ * // const runner = createSecurityExprRunner({ slotId: "s#0", interval: "1W",
26
+ * // capacity: 64, parent });
27
+ * const slotId = "s#0";
28
+ * void slotId;
29
+ */
30
+ export type SecurityExprRunner = {
31
+ readonly slotId: string;
32
+ readonly interval: string;
33
+ readonly foldStream: StreamState;
34
+ readonly foldBar: SecurityBar;
35
+ readonly ctx: RuntimeContext;
36
+ readonly output: Float64RingBuffer;
37
+ callback?: SecurityExpr;
38
+ processedHtfCount: number;
39
+ };
40
+ /**
41
+ * The pair of lookup maps the runtime threads onto its {@link RuntimeContext}:
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).
45
+ *
46
+ * @since 0.7
47
+ * @stable
48
+ * @example
49
+ * const registry: SecurityExprRegistry = {
50
+ * bySlot: new Map(),
51
+ * byFeed: new Map(),
52
+ * };
53
+ * void registry;
54
+ */
55
+ export type SecurityExprRegistry = {
56
+ readonly bySlot: Map<string, SecurityExprRunner>;
57
+ readonly byFeed: ReadonlyMap<string, ReadonlyArray<SecurityExprRunner>>;
58
+ };
59
+ /**
60
+ * Construct one {@link SecurityExprRunner}. The fold stream and output buffer
61
+ * share the secondary stream's `capacity` so a deep-lookback callback
62
+ * (`ta.sma(bar.close, 50)`) has enough HTF history to warm up.
63
+ *
64
+ * @since 0.7
65
+ * @stable
66
+ * @example
67
+ * // const runner = createSecurityExprRunner({ slotId: "s#0",
68
+ * // interval: "1W", capacity: 64, parent });
69
+ * const interval = "1W";
70
+ * void interval;
71
+ */
72
+ export declare function createSecurityExprRunner(args: {
73
+ readonly slotId: string;
74
+ readonly symbol: string;
75
+ readonly interval: string;
76
+ readonly capacity: number;
77
+ readonly parent: RuntimeContext;
78
+ }): SecurityExprRunner;
79
+ /**
80
+ * Mount one runner per `manifest.securityExpressions` entry and return the
81
+ * `bySlot` / `byFeed` lookup maps. Returns empty maps when the manifest
82
+ * declares no expression callsites (the common single-timeframe case), so the
83
+ * secondary-close drive pays a single empty-map check.
84
+ *
85
+ * @since 0.7
86
+ * @stable
87
+ * @example
88
+ * // const registry = buildSecurityExprRunners(manifest, ctx, 64);
89
+ * const built = "bySlot + byFeed";
90
+ * void built;
91
+ */
92
+ export declare function buildSecurityExprRunners(manifest: ScriptManifest, parent: RuntimeContext, capacity: number): SecurityExprRegistry;
93
+ /**
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
97
+ * `"close"` folds the bar into the fold stream and appends one sampled output;
98
+ * a `"tick"` replaces the fold head and the output head without advancing
99
+ * length. Runners whose callback is not yet captured are skipped — the first
100
+ * main compute replays their backlog via {@link captureAndCatchUp}.
101
+ *
102
+ * @since 0.7
103
+ * @stable
104
+ * @example
105
+ * // driveSecurityExpressions(ctx, "1W", "close", weeklyBar);
106
+ * const mode = "close";
107
+ * void mode;
108
+ */
109
+ export declare function driveSecurityExpressions(parent: RuntimeContext, streamKey: string, mode: "close" | "tick", bar: Bar): void;
110
+ /**
111
+ * Store the callback the first time main compute provides it, then replay the
112
+ * real secondary stream oldest→newest through the runner's fold stream until
113
+ * `processedHtfCount === secondary.length`. Idempotent once the backlog is
114
+ * drained, so later calls in the same bar are no-ops.
115
+ *
116
+ * @since 0.7
117
+ * @stable
118
+ * @example
119
+ * // captureAndCatchUp(runner, expr, secondaryStream);
120
+ * const replayed = "oldest -> newest";
121
+ * void replayed;
122
+ */
123
+ export declare function captureAndCatchUp(runner: SecurityExprRunner, expr: SecurityExpr, secondary: StreamState): void;
124
+ /**
125
+ * Materialise a `Float64RingBuffer`'s values oldest→newest. Used as the
126
+ * `htfSeries` source when aligning a runner's output buffer to the main
127
+ * timeline.
128
+ *
129
+ * @since 0.7
130
+ * @stable
131
+ * @example
132
+ * // const values = ascendingValues(runner.output);
133
+ * const order = "oldest -> newest";
134
+ * void order;
135
+ */
136
+ export declare function ascendingValues(buffer: Float64RingBuffer): ReadonlyArray<number>;
137
+ //# sourceMappingURL=securityExprRunner.d.ts.map
@@ -0,0 +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;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"}
@@ -0,0 +1,253 @@
1
+ // Copyright (c) 2026 Invinite. Licensed under the MIT License.
2
+ // See the LICENSE file in the repo root for full license text.
3
+ import { feedKey } from "@invinite-org/chartlang-core";
4
+ import { ACTIVE_RUNTIME_CONTEXT } from "../runtimeContext.js";
5
+ import { Float64RingBuffer } from "../ringBuffer.js";
6
+ import { advanceSeriesSlots, commitSeriesSlots, resetSeriesHeads } from "../state/index.js";
7
+ import { inMemoryStateStore } from "../stateStore.js";
8
+ import { appendBarToStream, createStreamState, replaceStreamHead, } from "../streamState.js";
9
+ import { createRuntimeViews } from "../views/index.js";
10
+ import { barFromStream, makeConstantStringSeries } from "./streamBars.js";
11
+ function makeFoldBar(foldStream, symbol, interval) {
12
+ const { seriesViews } = foldStream;
13
+ return Object.freeze({
14
+ time: seriesViews.time,
15
+ open: seriesViews.open,
16
+ high: seriesViews.high,
17
+ low: seriesViews.low,
18
+ close: seriesViews.close,
19
+ volume: seriesViews.volume,
20
+ hl2: seriesViews.hl2,
21
+ hlc3: seriesViews.hlc3,
22
+ ohlc4: seriesViews.ohlc4,
23
+ hlcc4: seriesViews.hlcc4,
24
+ symbol: makeConstantStringSeries(symbol),
25
+ interval: makeConstantStringSeries(interval),
26
+ });
27
+ }
28
+ function buildExprContext(parent, slotId, foldStream) {
29
+ return {
30
+ stream: foldStream,
31
+ stateStore: inMemoryStateStore(),
32
+ lastPersistTime: 0,
33
+ capabilities: parent.capabilities,
34
+ // A throwaway bag — the callback may not emit (Task 2 forbids
35
+ // non-`ta` refs), but an isolated queue guards if it somehow does.
36
+ emissions: {
37
+ plots: [],
38
+ drawings: [],
39
+ alerts: [],
40
+ alertConditions: [],
41
+ logs: [],
42
+ diagnostics: [],
43
+ fromBar: 0,
44
+ toBar: 0,
45
+ },
46
+ barIndex: () => foldStream.ohlcv.close.length - 1,
47
+ isTick: false,
48
+ drawingSlots: new Map(),
49
+ drawingSubIdCounters: new Map(),
50
+ drawingBucketCounters: { lines: 0, labels: 0, boxes: 0, polylines: 0, other: 0 },
51
+ scriptMaxDrawings: null,
52
+ stateSlots: new Map(),
53
+ seriesSlots: new Map(),
54
+ arraySlots: new Map(),
55
+ chartSymbol: parent.chartSymbol,
56
+ secondaryStreams: parent.secondaryStreams,
57
+ requestSecurityBars: new Map(),
58
+ requestSecurityAlignments: new Map(),
59
+ requestSecurityAscendingBars: new Map(),
60
+ requestLowerTfViews: new Map(),
61
+ diagnosedRequestKeys: new Set(),
62
+ diagnosedTzKeys: new Set(),
63
+ logBudget: 0,
64
+ logBudgetExceededDiagnosed: false,
65
+ resolvedInputs: parent.resolvedInputs,
66
+ defaultPane: parent.defaultPane,
67
+ scriptPane: parent.scriptPane,
68
+ plotOverrides: Object.freeze({}),
69
+ diagnosedInputKeys: new Set(),
70
+ views: createRuntimeViews(),
71
+ slotIdPrefix: `security:${slotId}/`,
72
+ };
73
+ }
74
+ /**
75
+ * Construct one {@link SecurityExprRunner}. The fold stream and output buffer
76
+ * share the secondary stream's `capacity` so a deep-lookback callback
77
+ * (`ta.sma(bar.close, 50)`) has enough HTF history to warm up.
78
+ *
79
+ * @since 0.7
80
+ * @stable
81
+ * @example
82
+ * // const runner = createSecurityExprRunner({ slotId: "s#0",
83
+ * // interval: "1W", capacity: 64, parent });
84
+ * const interval = "1W";
85
+ * void interval;
86
+ */
87
+ export function createSecurityExprRunner(args) {
88
+ const { slotId, symbol, interval, capacity, parent } = args;
89
+ const foldStream = createStreamState({ interval, capacity, symbol });
90
+ return {
91
+ slotId,
92
+ interval,
93
+ foldStream,
94
+ foldBar: makeFoldBar(foldStream, symbol, interval),
95
+ ctx: buildExprContext(parent, slotId, foldStream),
96
+ output: new Float64RingBuffer(capacity),
97
+ processedHtfCount: 0,
98
+ };
99
+ }
100
+ /**
101
+ * Mount one runner per `manifest.securityExpressions` entry and return the
102
+ * `bySlot` / `byFeed` lookup maps. Returns empty maps when the manifest
103
+ * declares no expression callsites (the common single-timeframe case), so the
104
+ * secondary-close drive pays a single empty-map check.
105
+ *
106
+ * @since 0.7
107
+ * @stable
108
+ * @example
109
+ * // const registry = buildSecurityExprRunners(manifest, ctx, 64);
110
+ * const built = "bySlot + byFeed";
111
+ * void built;
112
+ */
113
+ export function buildSecurityExprRunners(manifest, parent, capacity) {
114
+ const bySlot = new Map();
115
+ const byFeed = new Map();
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);
128
+ const runner = createSecurityExprRunner({
129
+ slotId: descriptor.slotId,
130
+ symbol: descriptor.symbol ?? parent.chartSymbol,
131
+ interval: descriptor.interval,
132
+ capacity,
133
+ parent,
134
+ });
135
+ bySlot.set(descriptor.slotId, runner);
136
+ const list = byFeed.get(key);
137
+ if (list === undefined) {
138
+ byFeed.set(key, [runner]);
139
+ }
140
+ else {
141
+ list.push(runner);
142
+ }
143
+ }
144
+ return { bySlot, byFeed };
145
+ }
146
+ function sampleOutput(result) {
147
+ return typeof result === "number" ? result : result.current;
148
+ }
149
+ function evaluate(runner, callback, isTick) {
150
+ const previous = ACTIVE_RUNTIME_CONTEXT.current;
151
+ ACTIVE_RUNTIME_CONTEXT.current = runner.ctx;
152
+ runner.ctx.isTick = isTick;
153
+ // `state.series` inside the callback accumulates on the HTF clock, so it
154
+ // advances/commits in lockstep with the fold stream — the same close/tick
155
+ // discipline `runComputeBody` applies to the main compute.
156
+ if (isTick)
157
+ resetSeriesHeads(runner.ctx);
158
+ else
159
+ advanceSeriesSlots(runner.ctx);
160
+ try {
161
+ return sampleOutput(callback(runner.foldBar));
162
+ }
163
+ finally {
164
+ if (!isTick)
165
+ commitSeriesSlots(runner.ctx);
166
+ runner.ctx.isTick = false;
167
+ ACTIVE_RUNTIME_CONTEXT.current = previous;
168
+ }
169
+ }
170
+ function foldClose(runner, bar) {
171
+ if (runner.callback === undefined)
172
+ return;
173
+ appendBarToStream(runner.foldStream, bar);
174
+ runner.output.append(evaluate(runner, runner.callback, false));
175
+ runner.processedHtfCount += 1;
176
+ }
177
+ function foldTick(runner, bar) {
178
+ if (runner.callback === undefined)
179
+ return;
180
+ replaceStreamHead(runner.foldStream, bar);
181
+ runner.output.replaceHead(evaluate(runner, runner.callback, true));
182
+ }
183
+ /**
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
187
+ * `"close"` folds the bar into the fold stream and appends one sampled output;
188
+ * a `"tick"` replaces the fold head and the output head without advancing
189
+ * length. Runners whose callback is not yet captured are skipped — the first
190
+ * main compute replays their backlog via {@link captureAndCatchUp}.
191
+ *
192
+ * @since 0.7
193
+ * @stable
194
+ * @example
195
+ * // driveSecurityExpressions(ctx, "1W", "close", weeklyBar);
196
+ * const mode = "close";
197
+ * void mode;
198
+ */
199
+ export function driveSecurityExpressions(parent, streamKey, mode, bar) {
200
+ const runners = parent.securityExprRunnersByFeed?.get(streamKey);
201
+ if (runners === undefined)
202
+ return;
203
+ for (const runner of runners) {
204
+ if (mode === "close") {
205
+ foldClose(runner, bar);
206
+ }
207
+ else {
208
+ foldTick(runner, bar);
209
+ }
210
+ }
211
+ }
212
+ /**
213
+ * Store the callback the first time main compute provides it, then replay the
214
+ * real secondary stream oldest→newest through the runner's fold stream until
215
+ * `processedHtfCount === secondary.length`. Idempotent once the backlog is
216
+ * drained, so later calls in the same bar are no-ops.
217
+ *
218
+ * @since 0.7
219
+ * @stable
220
+ * @example
221
+ * // captureAndCatchUp(runner, expr, secondaryStream);
222
+ * const replayed = "oldest -> newest";
223
+ * void replayed;
224
+ */
225
+ export function captureAndCatchUp(runner, expr, secondary) {
226
+ if (runner.callback === undefined)
227
+ runner.callback = expr;
228
+ const length = secondary.ohlcv.close.length;
229
+ while (runner.processedHtfCount < length) {
230
+ const age = length - 1 - runner.processedHtfCount;
231
+ foldClose(runner, barFromStream(secondary, age));
232
+ }
233
+ }
234
+ /**
235
+ * Materialise a `Float64RingBuffer`'s values oldest→newest. Used as the
236
+ * `htfSeries` source when aligning a runner's output buffer to the main
237
+ * timeline.
238
+ *
239
+ * @since 0.7
240
+ * @stable
241
+ * @example
242
+ * // const values = ascendingValues(runner.output);
243
+ * const order = "oldest -> newest";
244
+ * void order;
245
+ */
246
+ export function ascendingValues(buffer) {
247
+ const values = [];
248
+ for (let age = buffer.length - 1; age >= 0; age -= 1) {
249
+ values.push(buffer.at(age));
250
+ }
251
+ return values;
252
+ }
253
+ //# sourceMappingURL=securityExprRunner.js.map
@@ -0,0 +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\";\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"]}
@@ -1,6 +1,19 @@
1
- import type { Bar } from "@invinite-org/chartlang-core";
1
+ import type { Bar, Series } from "@invinite-org/chartlang-core";
2
2
  import type { RuntimeContext } from "../runtimeContext.js";
3
3
  import type { StreamState } from "../streamState.js";
4
+ /**
5
+ * A `Series<string>` whose every head-relative read returns a fixed `value`.
6
+ * Backs the `symbol` / `interval` fields of a materialised {@link SecurityBar}
7
+ * (both the data form's live bar and the expression form's fold bar), where the
8
+ * scalar is constant across history.
9
+ *
10
+ * @since 0.7
11
+ * @stable
12
+ * @example
13
+ * const s = makeConstantStringSeries("1W");
14
+ * void s.current; // "1W"
15
+ */
16
+ export declare function makeConstantStringSeries(value: string): Series<string>;
4
17
  /**
5
18
  * Materialise the bar at ring-buffer `age` from a stream state.
6
19
  *
@@ -1 +1 @@
1
- {"version":3,"file":"streamBars.d.ts","sourceRoot":"","sources":["../../src/request/streamBars.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,8BAA8B,CAAC;AAExD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,GAAG,CAmBnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,CAS7F"}
1
+ {"version":3,"file":"streamBars.d.ts","sourceRoot":"","sources":["../../src/request/streamBars.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAS,MAAM,EAAc,MAAM,8BAA8B,CAAC;AAGnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAkBtE;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,GAAG,CAyBnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,CAS7F"}
@@ -1,5 +1,38 @@
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 { resolveBarPoint } from "../barPoint.js";
4
+ /**
5
+ * A `Series<string>` whose every head-relative read returns a fixed `value`.
6
+ * Backs the `symbol` / `interval` fields of a materialised {@link SecurityBar}
7
+ * (both the data form's live bar and the expression form's fold bar), where the
8
+ * scalar is constant across history.
9
+ *
10
+ * @since 0.7
11
+ * @stable
12
+ * @example
13
+ * const s = makeConstantStringSeries("1W");
14
+ * void s.current; // "1W"
15
+ */
16
+ export function makeConstantStringSeries(value) {
17
+ const target = {
18
+ get current() {
19
+ return value;
20
+ },
21
+ get length() {
22
+ return 0;
23
+ },
24
+ };
25
+ return new Proxy(Object.freeze(target), {
26
+ get(obj, prop, receiver) {
27
+ if (typeof prop === "string") {
28
+ const n = Number(prop);
29
+ if (Number.isInteger(n) && n >= 0)
30
+ return value;
31
+ }
32
+ return Reflect.get(obj, prop, receiver);
33
+ },
34
+ });
35
+ }
3
36
  /**
4
37
  * Materialise the bar at ring-buffer `age` from a stream state.
5
38
  *
@@ -15,8 +48,9 @@ export function barFromStream(stream, age) {
15
48
  const high = stream.ohlcv.high.at(age);
16
49
  const low = stream.ohlcv.low.at(age);
17
50
  const close = stream.ohlcv.close.at(age);
51
+ const barTime = stream.ohlcv.time.at(age);
18
52
  return {
19
- time: stream.ohlcv.time.at(age),
53
+ time: barTime,
20
54
  open,
21
55
  high,
22
56
  low,
@@ -28,6 +62,10 @@ export function barFromStream(stream, age) {
28
62
  hlc3: (high + low + close) / 3,
29
63
  ohlc4: (open + high + low + close) / 4,
30
64
  hlcc4: (high + low + close + close) / 4,
65
+ // Anchored at this materialised bar's own `age`: a negative offset
66
+ // reads `time.at(age - offset)` (further back in this stream's
67
+ // history) so a snapshot bar's offsets stay relative to itself.
68
+ point: (offset, price) => resolveBarPoint(stream.ohlcv.time, stream.bar.interval, barTime, offset - age, price),
31
69
  };
32
70
  }
33
71
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"streamBars.js","sourceRoot":"","sources":["../../src/request/streamBars.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAO/D;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,MAAmB,EAAE,GAAW;IAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO;QACH,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;QAC/B,IAAI;QACJ,IAAI;QACJ,GAAG;QACH,KAAK;QACL,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC;QACnC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM;QACzB,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ;QAC7B,GAAG,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC;QACrB,IAAI,EAAE,CAAC,IAAI,GAAG,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QAC9B,KAAK,EAAE,CAAC,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QACtC,KAAK,EAAE,CAAC,IAAI,GAAG,GAAG,GAAG,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC;KAC1C,CAAC;AACN,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAmB,EAAE,MAAmB;IACrE,MAAM,MAAM,GAAG,GAAG,CAAC,4BAA4B,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5D,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACxC,MAAM,IAAI,GAAU,EAAE,CAAC;IACvB,KAAK,IAAI,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QAC/D,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,GAAG,CAAC,4BAA4B,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC;AAChB,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 { Bar } from \"@invinite-org/chartlang-core\";\n\nimport type { RuntimeContext } from \"../runtimeContext.js\";\nimport type { StreamState } from \"../streamState.js\";\n\n/**\n * Materialise the bar at ring-buffer `age` from a stream state.\n *\n * @since 0.6\n * @stable\n * @example\n * // const bar = barFromStream(stream, 0);\n * const age = 0;\n * void age;\n */\nexport function barFromStream(stream: StreamState, age: number): Bar {\n const open = stream.ohlcv.open.at(age);\n const high = stream.ohlcv.high.at(age);\n const low = stream.ohlcv.low.at(age);\n const close = stream.ohlcv.close.at(age);\n return {\n time: stream.ohlcv.time.at(age),\n open,\n high,\n low,\n close,\n volume: stream.ohlcv.volume.at(age),\n symbol: stream.bar.symbol,\n interval: stream.bar.interval,\n hl2: (high + low) / 2,\n hlc3: (high + low + close) / 3,\n ohlc4: (open + high + low + close) / 4,\n hlcc4: (high + low + close + close) / 4,\n };\n}\n\n/**\n * Return a stream's bars in ascending time order, memoised per step on\n * `ctx.requestSecurityAscendingBars` (cleared each bar close).\n *\n * @since 0.6\n * @stable\n * @example\n * // const bars = ascendingBarsFor(ctx, ctx.stream);\n * const memo = \"requestSecurityAscendingBars\";\n * void memo;\n */\nexport function ascendingBarsFor(ctx: RuntimeContext, stream: StreamState): ReadonlyArray<Bar> {\n const cached = ctx.requestSecurityAscendingBars.get(stream);\n if (cached !== undefined) return cached;\n const bars: Bar[] = [];\n for (let age = stream.ohlcv.close.length - 1; age >= 0; age -= 1) {\n bars.push(barFromStream(stream, age));\n }\n ctx.requestSecurityAscendingBars.set(stream, bars);\n return bars;\n}\n"]}
1
+ {"version":3,"file":"streamBars.js","sourceRoot":"","sources":["../../src/request/streamBars.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 { Bar, Price, Series, WorldPoint } from \"@invinite-org/chartlang-core\";\n\nimport { resolveBarPoint } from \"../barPoint.js\";\nimport type { RuntimeContext } from \"../runtimeContext.js\";\nimport type { StreamState } from \"../streamState.js\";\n\n/**\n * A `Series<string>` whose every head-relative read returns a fixed `value`.\n * Backs the `symbol` / `interval` fields of a materialised {@link SecurityBar}\n * (both the data form's live bar and the expression form's fold bar), where the\n * scalar is constant across history.\n *\n * @since 0.7\n * @stable\n * @example\n * const s = makeConstantStringSeries(\"1W\");\n * void s.current; // \"1W\"\n */\nexport function makeConstantStringSeries(value: string): Series<string> {\n const target = {\n get current() {\n return value;\n },\n get length() {\n return 0;\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) return value;\n }\n return Reflect.get(obj, prop, receiver);\n },\n }) as Series<string>;\n}\n\n/**\n * Materialise the bar at ring-buffer `age` from a stream state.\n *\n * @since 0.6\n * @stable\n * @example\n * // const bar = barFromStream(stream, 0);\n * const age = 0;\n * void age;\n */\nexport function barFromStream(stream: StreamState, age: number): Bar {\n const open = stream.ohlcv.open.at(age);\n const high = stream.ohlcv.high.at(age);\n const low = stream.ohlcv.low.at(age);\n const close = stream.ohlcv.close.at(age);\n const barTime = stream.ohlcv.time.at(age);\n return {\n time: barTime,\n open,\n high,\n low,\n close,\n volume: stream.ohlcv.volume.at(age),\n symbol: stream.bar.symbol,\n interval: stream.bar.interval,\n hl2: (high + low) / 2,\n hlc3: (high + low + close) / 3,\n ohlc4: (open + high + low + close) / 4,\n hlcc4: (high + low + close + close) / 4,\n // Anchored at this materialised bar's own `age`: a negative offset\n // reads `time.at(age - offset)` (further back in this stream's\n // history) so a snapshot bar's offsets stay relative to itself.\n point: (offset: number, price: Price): WorldPoint =>\n resolveBarPoint(stream.ohlcv.time, stream.bar.interval, barTime, offset - age, price),\n };\n}\n\n/**\n * Return a stream's bars in ascending time order, memoised per step on\n * `ctx.requestSecurityAscendingBars` (cleared each bar close).\n *\n * @since 0.6\n * @stable\n * @example\n * // const bars = ascendingBarsFor(ctx, ctx.stream);\n * const memo = \"requestSecurityAscendingBars\";\n * void memo;\n */\nexport function ascendingBarsFor(ctx: RuntimeContext, stream: StreamState): ReadonlyArray<Bar> {\n const cached = ctx.requestSecurityAscendingBars.get(stream);\n if (cached !== undefined) return cached;\n const bars: Bar[] = [];\n for (let age = stream.ohlcv.close.length - 1; age >= 0; age -= 1) {\n bars.push(barFromStream(stream, age));\n }\n ctx.requestSecurityAscendingBars.set(stream, bars);\n return bars;\n}\n"]}