@invinite-org/chartlang-runtime 1.1.1 → 1.2.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 (226) hide show
  1. package/CHANGELOG.md +236 -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/createScriptRunner.d.ts +6 -3
  11. package/dist/createScriptRunner.d.ts.map +1 -1
  12. package/dist/createScriptRunner.js +29 -5
  13. package/dist/createScriptRunner.js.map +1 -1
  14. package/dist/dep/DepRunner.d.ts.map +1 -1
  15. package/dist/dep/DepRunner.js +1 -0
  16. package/dist/dep/DepRunner.js.map +1 -1
  17. package/dist/emit/draw/boxes/fillBetween.d.ts +45 -0
  18. package/dist/emit/draw/boxes/fillBetween.d.ts.map +1 -0
  19. package/dist/emit/draw/boxes/fillBetween.js +36 -0
  20. package/dist/emit/draw/boxes/fillBetween.js.map +1 -0
  21. package/dist/emit/draw/handle.d.ts +9 -0
  22. package/dist/emit/draw/handle.d.ts.map +1 -1
  23. package/dist/emit/draw/handle.js +65 -10
  24. package/dist/emit/draw/handle.js.map +1 -1
  25. package/dist/emit/draw/namespace.d.ts +4 -3
  26. package/dist/emit/draw/namespace.d.ts.map +1 -1
  27. package/dist/emit/draw/namespace.js +6 -3
  28. package/dist/emit/draw/namespace.js.map +1 -1
  29. package/dist/emit/plot.d.ts +7 -0
  30. package/dist/emit/plot.d.ts.map +1 -1
  31. package/dist/emit/plot.js +13 -0
  32. package/dist/emit/plot.js.map +1 -1
  33. package/dist/execution/dispose.d.ts.map +1 -1
  34. package/dist/execution/dispose.js +16 -0
  35. package/dist/execution/dispose.js.map +1 -1
  36. package/dist/execution/runComputeStep.d.ts.map +1 -1
  37. package/dist/execution/runComputeStep.js +10 -1
  38. package/dist/execution/runComputeStep.js.map +1 -1
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +1 -1
  42. package/dist/index.js.map +1 -1
  43. package/dist/persistentStateStore.runtime.d.ts.map +1 -1
  44. package/dist/persistentStateStore.runtime.js +21 -7
  45. package/dist/persistentStateStore.runtime.js.map +1 -1
  46. package/dist/request/index.d.ts +2 -1
  47. package/dist/request/index.d.ts.map +1 -1
  48. package/dist/request/index.js +2 -1
  49. package/dist/request/index.js.map +1 -1
  50. package/dist/request/requestNamespace.d.ts.map +1 -1
  51. package/dist/request/requestNamespace.js +16 -3
  52. package/dist/request/requestNamespace.js.map +1 -1
  53. package/dist/request/security.d.ts +20 -1
  54. package/dist/request/security.d.ts.map +1 -1
  55. package/dist/request/security.js +62 -23
  56. package/dist/request/security.js.map +1 -1
  57. package/dist/request/securityExprRunner.d.ts +133 -0
  58. package/dist/request/securityExprRunner.d.ts.map +1 -0
  59. package/dist/request/securityExprRunner.js +235 -0
  60. package/dist/request/securityExprRunner.js.map +1 -0
  61. package/dist/request/streamBars.d.ts +14 -1
  62. package/dist/request/streamBars.d.ts.map +1 -1
  63. package/dist/request/streamBars.js +39 -1
  64. package/dist/request/streamBars.js.map +1 -1
  65. package/dist/runtimeContext.d.ts +48 -0
  66. package/dist/runtimeContext.d.ts.map +1 -1
  67. package/dist/runtimeContext.js.map +1 -1
  68. package/dist/seriesView.d.ts +42 -17
  69. package/dist/seriesView.d.ts.map +1 -1
  70. package/dist/seriesView.js +65 -42
  71. package/dist/seriesView.js.map +1 -1
  72. package/dist/state/index.d.ts +2 -1
  73. package/dist/state/index.d.ts.map +1 -1
  74. package/dist/state/index.js +2 -1
  75. package/dist/state/index.js.map +1 -1
  76. package/dist/state/lifecycle.d.ts +40 -0
  77. package/dist/state/lifecycle.d.ts.map +1 -1
  78. package/dist/state/lifecycle.js +53 -0
  79. package/dist/state/lifecycle.js.map +1 -1
  80. package/dist/state/seriesPersistence.d.ts +48 -0
  81. package/dist/state/seriesPersistence.d.ts.map +1 -0
  82. package/dist/state/seriesPersistence.js +87 -0
  83. package/dist/state/seriesPersistence.js.map +1 -0
  84. package/dist/state/seriesSlot.d.ts +105 -0
  85. package/dist/state/seriesSlot.d.ts.map +1 -0
  86. package/dist/state/seriesSlot.js +123 -0
  87. package/dist/state/seriesSlot.js.map +1 -0
  88. package/dist/state/stateNamespace.d.ts.map +1 -1
  89. package/dist/state/stateNamespace.js +28 -0
  90. package/dist/state/stateNamespace.js.map +1 -1
  91. package/dist/streamState.d.ts +25 -19
  92. package/dist/streamState.d.ts.map +1 -1
  93. package/dist/streamState.js +40 -66
  94. package/dist/streamState.js.map +1 -1
  95. package/dist/ta/adx.d.ts +3 -2
  96. package/dist/ta/adx.d.ts.map +1 -1
  97. package/dist/ta/adx.js +3 -2
  98. package/dist/ta/adx.js.map +1 -1
  99. package/dist/ta/alma.d.ts +6 -4
  100. package/dist/ta/alma.d.ts.map +1 -1
  101. package/dist/ta/alma.js +19 -6
  102. package/dist/ta/alma.js.map +1 -1
  103. package/dist/ta/atr.d.ts +3 -2
  104. package/dist/ta/atr.d.ts.map +1 -1
  105. package/dist/ta/atr.js +3 -2
  106. package/dist/ta/atr.js.map +1 -1
  107. package/dist/ta/bb.d.ts +3 -2
  108. package/dist/ta/bb.d.ts.map +1 -1
  109. package/dist/ta/bb.js +3 -2
  110. package/dist/ta/bb.js.map +1 -1
  111. package/dist/ta/chaikinOsc.d.ts +3 -2
  112. package/dist/ta/chaikinOsc.d.ts.map +1 -1
  113. package/dist/ta/chaikinOsc.js +3 -2
  114. package/dist/ta/chaikinOsc.js.map +1 -1
  115. package/dist/ta/crossover.d.ts +3 -2
  116. package/dist/ta/crossover.d.ts.map +1 -1
  117. package/dist/ta/crossover.js +3 -2
  118. package/dist/ta/crossover.js.map +1 -1
  119. package/dist/ta/crossunder.d.ts +3 -2
  120. package/dist/ta/crossunder.d.ts.map +1 -1
  121. package/dist/ta/crossunder.js +3 -2
  122. package/dist/ta/crossunder.js.map +1 -1
  123. package/dist/ta/dmi.d.ts +4 -3
  124. package/dist/ta/dmi.d.ts.map +1 -1
  125. package/dist/ta/dmi.js +4 -3
  126. package/dist/ta/dmi.js.map +1 -1
  127. package/dist/ta/ema.d.ts +3 -2
  128. package/dist/ta/ema.d.ts.map +1 -1
  129. package/dist/ta/ema.js +3 -2
  130. package/dist/ta/ema.js.map +1 -1
  131. package/dist/ta/eom.d.ts +3 -1
  132. package/dist/ta/eom.d.ts.map +1 -1
  133. package/dist/ta/eom.js +3 -1
  134. package/dist/ta/eom.js.map +1 -1
  135. package/dist/ta/highestbars.d.ts +25 -0
  136. package/dist/ta/highestbars.d.ts.map +1 -0
  137. package/dist/ta/highestbars.js +106 -0
  138. package/dist/ta/highestbars.js.map +1 -0
  139. package/dist/ta/historicalVolatility.d.ts +3 -2
  140. package/dist/ta/historicalVolatility.d.ts.map +1 -1
  141. package/dist/ta/historicalVolatility.js +3 -2
  142. package/dist/ta/historicalVolatility.js.map +1 -1
  143. package/dist/ta/ichimoku.d.ts +3 -1
  144. package/dist/ta/ichimoku.d.ts.map +1 -1
  145. package/dist/ta/ichimoku.js +3 -1
  146. package/dist/ta/ichimoku.js.map +1 -1
  147. package/dist/ta/lowestbars.d.ts +25 -0
  148. package/dist/ta/lowestbars.d.ts.map +1 -0
  149. package/dist/ta/lowestbars.js +102 -0
  150. package/dist/ta/lowestbars.js.map +1 -0
  151. package/dist/ta/macd.d.ts +3 -2
  152. package/dist/ta/macd.d.ts.map +1 -1
  153. package/dist/ta/macd.js +3 -2
  154. package/dist/ta/macd.js.map +1 -1
  155. package/dist/ta/massIndex.d.ts +3 -2
  156. package/dist/ta/massIndex.d.ts.map +1 -1
  157. package/dist/ta/massIndex.js +3 -2
  158. package/dist/ta/massIndex.js.map +1 -1
  159. package/dist/ta/mfi.d.ts +3 -1
  160. package/dist/ta/mfi.d.ts.map +1 -1
  161. package/dist/ta/mfi.js +3 -1
  162. package/dist/ta/mfi.js.map +1 -1
  163. package/dist/ta/netVolume.d.ts +3 -1
  164. package/dist/ta/netVolume.d.ts.map +1 -1
  165. package/dist/ta/netVolume.js +3 -1
  166. package/dist/ta/netVolume.js.map +1 -1
  167. package/dist/ta/nvi.d.ts +3 -1
  168. package/dist/ta/nvi.d.ts.map +1 -1
  169. package/dist/ta/nvi.js +3 -1
  170. package/dist/ta/nvi.js.map +1 -1
  171. package/dist/ta/persistence.d.ts.map +1 -1
  172. package/dist/ta/persistence.js +1 -40
  173. package/dist/ta/persistence.js.map +1 -1
  174. package/dist/ta/ppo.d.ts +3 -2
  175. package/dist/ta/ppo.d.ts.map +1 -1
  176. package/dist/ta/ppo.js +3 -2
  177. package/dist/ta/ppo.js.map +1 -1
  178. package/dist/ta/pvi.d.ts +3 -1
  179. package/dist/ta/pvi.d.ts.map +1 -1
  180. package/dist/ta/pvi.js +3 -1
  181. package/dist/ta/pvi.js.map +1 -1
  182. package/dist/ta/pvo.d.ts +3 -1
  183. package/dist/ta/pvo.d.ts.map +1 -1
  184. package/dist/ta/pvo.js +3 -1
  185. package/dist/ta/pvo.js.map +1 -1
  186. package/dist/ta/pvt.d.ts +3 -1
  187. package/dist/ta/pvt.d.ts.map +1 -1
  188. package/dist/ta/pvt.js +3 -1
  189. package/dist/ta/pvt.js.map +1 -1
  190. package/dist/ta/registry.d.ts +7 -1
  191. package/dist/ta/registry.d.ts.map +1 -1
  192. package/dist/ta/registry.js +4 -0
  193. package/dist/ta/registry.js.map +1 -1
  194. package/dist/ta/rsi.d.ts +3 -2
  195. package/dist/ta/rsi.d.ts.map +1 -1
  196. package/dist/ta/rsi.js +3 -2
  197. package/dist/ta/rsi.js.map +1 -1
  198. package/dist/ta/rvi.d.ts +3 -2
  199. package/dist/ta/rvi.d.ts.map +1 -1
  200. package/dist/ta/rvi.js +3 -2
  201. package/dist/ta/rvi.js.map +1 -1
  202. package/dist/ta/sma.d.ts +6 -3
  203. package/dist/ta/sma.d.ts.map +1 -1
  204. package/dist/ta/sma.js +6 -3
  205. package/dist/ta/sma.js.map +1 -1
  206. package/dist/ta/stdev.d.ts +3 -2
  207. package/dist/ta/stdev.d.ts.map +1 -1
  208. package/dist/ta/stdev.js +3 -2
  209. package/dist/ta/stdev.js.map +1 -1
  210. package/dist/ta/trendStrengthIndex.d.ts +3 -2
  211. package/dist/ta/trendStrengthIndex.d.ts.map +1 -1
  212. package/dist/ta/trendStrengthIndex.js +3 -2
  213. package/dist/ta/trendStrengthIndex.js.map +1 -1
  214. package/dist/ta/trix.d.ts +4 -3
  215. package/dist/ta/trix.d.ts.map +1 -1
  216. package/dist/ta/trix.js +4 -3
  217. package/dist/ta/trix.js.map +1 -1
  218. package/dist/ta/vortex.d.ts +3 -2
  219. package/dist/ta/vortex.d.ts.map +1 -1
  220. package/dist/ta/vortex.js +3 -2
  221. package/dist/ta/vortex.js.map +1 -1
  222. package/package.json +3 -3
  223. package/dist/ta/lib/applyOffset.d.ts +0 -19
  224. package/dist/ta/lib/applyOffset.d.ts.map +0 -1
  225. package/dist/ta/lib/applyOffset.js +0 -38
  226. package/dist/ta/lib/applyOffset.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"streamState.js","sourceRoot":"","sources":["../src/streamState.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, BarViewport, Series, StreamSnapshot } from \"@invinite-org/chartlang-core\";\n\nimport { Float64RingBuffer } from \"./ringBuffer.js\";\nimport { makeSeriesView } from \"./seriesView.js\";\n\ntype DerivedBarValues = Readonly<{\n hl2: number;\n hlc3: number;\n ohlc4: number;\n hlcc4: number;\n}>;\n\nfunction deriveBarSources(rawBar: Bar): DerivedBarValues {\n return {\n hl2: (rawBar.high + rawBar.low) / 2,\n hlc3: (rawBar.high + rawBar.low + rawBar.close) / 3,\n ohlc4: (rawBar.open + rawBar.high + rawBar.low + rawBar.close) / 4,\n hlcc4: (rawBar.high + rawBar.low + rawBar.close + rawBar.close) / 4,\n };\n}\n\n/**\n * The per-stream OHLCV ring-buffer set. Each field is a\n * `Float64RingBuffer` of identical capacity. Derived sources\n * (`hl2`, `hlc3`, `ohlc4`, `hlcc4`) are pre-computed by Task 6's\n * execution loop alongside the raw OHLCV fields so primitives can\n * read them as plain `Series<number>` without re-computing per\n * lookup.\n *\n * @since 0.1\n * @example\n * // import { createStreamState } from \"@invinite-org/chartlang-runtime\";\n * // const { ohlcv } = createStreamState({\n * // interval: \"1D\",\n * // capacity: 5,\n * // symbol: \"AAPL\",\n * // });\n * // ohlcv.close.capacity; // 5\n */\nexport type OhlcvBuffers = {\n readonly time: Float64RingBuffer;\n readonly open: Float64RingBuffer;\n readonly high: Float64RingBuffer;\n readonly low: Float64RingBuffer;\n readonly close: Float64RingBuffer;\n readonly volume: Float64RingBuffer;\n readonly hl2: Float64RingBuffer;\n readonly hlc3: Float64RingBuffer;\n readonly ohlc4: Float64RingBuffer;\n readonly hlcc4: Float64RingBuffer;\n};\n\n/**\n * Mutable scalar view of the current bar. Identity stays stable across\n * the run — Task 6's execution loop mutates the fields in place per\n * bar so scripts that destructure `bar` in `compute` keep seeing fresh\n * values without rebinding.\n *\n * `symbol` and `interval` are constant for a given `StreamState`\n * instance; the rest are NaN / 0 before the first bar lands.\n *\n * @since 0.1\n * @example\n * // import { createStreamState } from \"@invinite-org/chartlang-runtime\";\n * // const { bar } = createStreamState({\n * // interval: \"1D\",\n * // capacity: 5,\n * // symbol: \"AAPL\",\n * // });\n * // bar.symbol; // \"AAPL\"\n * // bar.interval; // \"1D\"\n * // bar.close; // NaN until the first bar\n */\nexport type BarView = {\n time: number;\n open: number;\n high: number;\n low: number;\n close: number;\n volume: number;\n hl2: number;\n hlc3: number;\n ohlc4: number;\n hlcc4: number;\n symbol: string;\n interval: string;\n viewport: BarViewport;\n};\n\n/**\n * Everything the runtime owns for a single interval stream — the OHLCV\n * ring buffers, the mutable `BarView`, cached `Series<number>` Proxies\n * for each source field (one identity per buffer for the lifetime of\n * the stream), and a `taSlots` map keyed by compiler-assigned slot id\n * that stateful primitives in Task 7 use as their hidden-state\n * scratchpad.\n *\n * Phase 1 ships single-stream scripts; secondary streams via\n * `request.security` arrive in Phase 5 and reuse this exact shape per\n * interval.\n *\n * @since 0.1\n * @example\n * // import { createStreamState } from \"@invinite-org/chartlang-runtime\";\n * // const stream = createStreamState({\n * // interval: \"1D\",\n * // capacity: 21,\n * // symbol: \"AAPL\",\n * // });\n * // stream.taSlots.size; // 0\n */\nexport type StreamState = {\n readonly interval: string;\n readonly ohlcv: OhlcvBuffers;\n readonly bar: BarView;\n readonly seriesViews: {\n readonly time: Series<number>;\n readonly open: Series<number>;\n readonly high: Series<number>;\n readonly low: Series<number>;\n readonly close: Series<number>;\n readonly volume: Series<number>;\n readonly hl2: Series<number>;\n readonly hlc3: Series<number>;\n readonly ohlc4: Series<number>;\n readonly hlcc4: Series<number>;\n };\n readonly taSlots: Map<string, unknown>;\n serialiseSnapshot(): StreamSnapshot;\n restoreFromSnapshot(snapshot: StreamSnapshot): void;\n};\n\nconst rawBufferKeys = [\"time\", \"open\", \"high\", \"low\", \"close\", \"volume\"] as const;\n\ntype RawBufferKey = (typeof rawBufferKeys)[number];\n\nfunction rawBuffers(ohlcv: OhlcvBuffers): Readonly<Record<RawBufferKey, Float64RingBuffer>> {\n return {\n time: ohlcv.time,\n open: ohlcv.open,\n high: ohlcv.high,\n low: ohlcv.low,\n close: ohlcv.close,\n volume: ohlcv.volume,\n };\n}\n\nfunction valueAt(values: ReadonlyArray<number | null>, index: number): number {\n const value = values[index];\n return value === null || value === undefined ? Number.NaN : value;\n}\n\nfunction recomputeDerivedBuffers(ohlcv: OhlcvBuffers, snapshot: StreamSnapshot): void {\n const { headIndex, filled, buffers } = snapshot;\n const capacity = ohlcv.hl2.capacity;\n const derived = {\n hl2: new Array<number | null>(capacity),\n hlc3: new Array<number | null>(capacity),\n ohlc4: new Array<number | null>(capacity),\n hlcc4: new Array<number | null>(capacity),\n };\n for (let i = 0; i < capacity; i += 1) {\n const high = valueAt(buffers.high, i);\n const low = valueAt(buffers.low, i);\n const open = valueAt(buffers.open, i);\n const close = valueAt(buffers.close, i);\n derived.hl2[i] = Number.isNaN(high) || Number.isNaN(low) ? null : (high + low) / 2;\n derived.hlc3[i] =\n Number.isNaN(high) || Number.isNaN(low) || Number.isNaN(close)\n ? null\n : (high + low + close) / 3;\n derived.ohlc4[i] =\n Number.isNaN(open) || Number.isNaN(high) || Number.isNaN(low) || Number.isNaN(close)\n ? null\n : (open + high + low + close) / 4;\n derived.hlcc4[i] =\n Number.isNaN(high) || Number.isNaN(low) || Number.isNaN(close)\n ? null\n : (high + low + close + close) / 4;\n }\n ohlcv.hl2.restoreFromSnapshotBuffer({ headIndex, filled, values: derived.hl2 });\n ohlcv.hlc3.restoreFromSnapshotBuffer({ headIndex, filled, values: derived.hlc3 });\n ohlcv.ohlc4.restoreFromSnapshotBuffer({ headIndex, filled, values: derived.ohlc4 });\n ohlcv.hlcc4.restoreFromSnapshotBuffer({ headIndex, filled, values: derived.hlcc4 });\n}\n\n/**\n * Construct a fresh `StreamState`. The ring-buffer capacity is the\n * compiler-emitted `manifest.maxLookback + 1`\n * (caller must enforce `capacity >= 1`). All buffers start empty;\n * the `BarView` starts with `NaN` prices, `0` time and volume, and the\n * supplied `symbol` / `interval` constants. `taSlots` is an empty map.\n *\n * @since 0.1\n * @example\n * // import { createStreamState } from \"@invinite-org/chartlang-runtime\";\n * // const stream = createStreamState({\n * // interval: \"5m\",\n * // capacity: 12,\n * // symbol: \"BTCUSD\",\n * // });\n * // stream.bar.close; // NaN\n * // stream.ohlcv.close.length; // 0\n */\nexport function createStreamState(args: {\n interval: string;\n capacity: number;\n symbol: string;\n}): StreamState {\n const { interval, capacity, symbol } = args;\n const ohlcv: OhlcvBuffers = {\n time: new Float64RingBuffer(capacity),\n open: new Float64RingBuffer(capacity),\n high: new Float64RingBuffer(capacity),\n low: new Float64RingBuffer(capacity),\n close: new Float64RingBuffer(capacity),\n volume: new Float64RingBuffer(capacity),\n hl2: new Float64RingBuffer(capacity),\n hlc3: new Float64RingBuffer(capacity),\n ohlc4: new Float64RingBuffer(capacity),\n hlcc4: new Float64RingBuffer(capacity),\n };\n const bar: BarView = {\n time: 0,\n open: Number.NaN,\n high: Number.NaN,\n low: Number.NaN,\n close: Number.NaN,\n volume: 0,\n hl2: Number.NaN,\n hlc3: Number.NaN,\n ohlc4: Number.NaN,\n hlcc4: Number.NaN,\n symbol,\n interval,\n viewport: Object.freeze({ fromTime: 0, toTime: 0 }),\n };\n const seriesViews: StreamState[\"seriesViews\"] = {\n time: makeSeriesView<number>(ohlcv.time),\n open: makeSeriesView<number>(ohlcv.open),\n high: makeSeriesView<number>(ohlcv.high),\n low: makeSeriesView<number>(ohlcv.low),\n close: makeSeriesView<number>(ohlcv.close),\n volume: makeSeriesView<number>(ohlcv.volume),\n hl2: makeSeriesView<number>(ohlcv.hl2),\n hlc3: makeSeriesView<number>(ohlcv.hlc3),\n ohlc4: makeSeriesView<number>(ohlcv.ohlc4),\n hlcc4: makeSeriesView<number>(ohlcv.hlcc4),\n };\n const stream: StreamState = {\n interval,\n ohlcv,\n bar,\n seriesViews,\n taSlots: new Map<string, unknown>(),\n serialiseSnapshot(): StreamSnapshot {\n const close = ohlcv.close.serialiseSnapshotBuffer();\n const buffers = rawBuffers(ohlcv);\n return Object.freeze({\n interval: bar.interval,\n headIndex: close.headIndex,\n filled: close.filled,\n buffers: Object.freeze({\n time: buffers.time.serialiseSnapshotBuffer().values,\n open: buffers.open.serialiseSnapshotBuffer().values,\n high: buffers.high.serialiseSnapshotBuffer().values,\n low: buffers.low.serialiseSnapshotBuffer().values,\n close: close.values,\n volume: buffers.volume.serialiseSnapshotBuffer().values,\n }),\n });\n },\n restoreFromSnapshot(snapshot: StreamSnapshot): void {\n const buffers = rawBuffers(ohlcv);\n for (const key of rawBufferKeys) {\n buffers[key].restoreFromSnapshotBuffer({\n headIndex: snapshot.headIndex,\n filled: snapshot.filled,\n values: snapshot.buffers[key],\n });\n }\n recomputeDerivedBuffers(ohlcv, snapshot);\n const current = snapshot.headIndex;\n if (snapshot.filled === 0 || current < 0) {\n bar.time = 0;\n bar.open = Number.NaN;\n bar.high = Number.NaN;\n bar.low = Number.NaN;\n bar.close = Number.NaN;\n bar.volume = 0;\n bar.hl2 = Number.NaN;\n bar.hlc3 = Number.NaN;\n bar.ohlc4 = Number.NaN;\n bar.hlcc4 = Number.NaN;\n } else {\n bar.time = valueAt(snapshot.buffers.time, current);\n bar.open = valueAt(snapshot.buffers.open, current);\n bar.high = valueAt(snapshot.buffers.high, current);\n bar.low = valueAt(snapshot.buffers.low, current);\n bar.close = valueAt(snapshot.buffers.close, current);\n bar.volume = valueAt(snapshot.buffers.volume, current);\n bar.hl2 = (bar.high + bar.low) / 2;\n bar.hlc3 = (bar.high + bar.low + bar.close) / 3;\n bar.ohlc4 = (bar.open + bar.high + bar.low + bar.close) / 4;\n bar.hlcc4 = (bar.high + bar.low + bar.close + bar.close) / 4;\n }\n bar.interval = snapshot.interval;\n },\n };\n return stream;\n}\n\n/**\n * Append a finalised candle to a stream — extends the OHLCV ring buffers\n * by one bar and writes every field of the mutable `BarView` (including\n * `time` / `open`). Used by both the main close path and secondary\n * stream history.\n *\n * @since 0.5\n * @example\n * // appendBarToStream(stream, rawBar);\n */\nexport function appendBarToStream(stream: StreamState, rawBar: Bar): void {\n const values = deriveBarSources(rawBar);\n const { ohlcv, bar } = stream;\n ohlcv.time.append(rawBar.time);\n ohlcv.open.append(rawBar.open);\n ohlcv.high.append(rawBar.high);\n ohlcv.low.append(rawBar.low);\n ohlcv.close.append(rawBar.close);\n ohlcv.volume.append(rawBar.volume);\n ohlcv.hl2.append(values.hl2);\n ohlcv.hlc3.append(values.hlc3);\n ohlcv.ohlc4.append(values.ohlc4);\n ohlcv.hlcc4.append(values.hlcc4);\n bar.time = rawBar.time;\n bar.open = rawBar.open;\n bar.high = rawBar.high;\n bar.low = rawBar.low;\n bar.close = rawBar.close;\n bar.volume = rawBar.volume;\n bar.hl2 = values.hl2;\n bar.hlc3 = values.hlc3;\n bar.ohlc4 = values.ohlc4;\n bar.hlcc4 = values.hlcc4;\n bar.symbol = rawBar.symbol;\n bar.interval = rawBar.interval;\n}\n\n/**\n * Replace the head of every OHLCV ring buffer in a stream and write\n * every field of the `BarView`. Used by the secondary-stream replace\n * path — falls back to {@link appendBarToStream} for the empty-buffer\n * case so the first secondary bar arrives correctly even when delivered\n * as a replace.\n *\n * @since 0.5\n * @example\n * // replaceStreamHead(stream, rawBar);\n */\nexport function replaceStreamHead(stream: StreamState, rawBar: Bar): void {\n if (stream.ohlcv.close.length === 0) {\n appendBarToStream(stream, rawBar);\n return;\n }\n const values = deriveBarSources(rawBar);\n const { ohlcv, bar } = stream;\n ohlcv.time.replaceHead(rawBar.time);\n ohlcv.open.replaceHead(rawBar.open);\n ohlcv.high.replaceHead(rawBar.high);\n ohlcv.low.replaceHead(rawBar.low);\n ohlcv.close.replaceHead(rawBar.close);\n ohlcv.volume.replaceHead(rawBar.volume);\n ohlcv.hl2.replaceHead(values.hl2);\n ohlcv.hlc3.replaceHead(values.hlc3);\n ohlcv.ohlc4.replaceHead(values.ohlc4);\n ohlcv.hlcc4.replaceHead(values.hlcc4);\n bar.time = rawBar.time;\n bar.open = rawBar.open;\n bar.high = rawBar.high;\n bar.low = rawBar.low;\n bar.close = rawBar.close;\n bar.volume = rawBar.volume;\n bar.hl2 = values.hl2;\n bar.hlc3 = values.hlc3;\n bar.ohlc4 = values.ohlc4;\n bar.hlcc4 = values.hlcc4;\n bar.symbol = rawBar.symbol;\n bar.interval = rawBar.interval;\n}\n\n/**\n * Replace the head of the close-side OHLCV ring buffers (close, high,\n * low, volume, derived sources) for a tick within the in-progress bar.\n * `time` and `open` are intentionally untouched — see\n * `packages/runtime/CLAUDE.md` \"onBarTick does NOT touch time / open\"\n * invariant. Mirrors the partial `BarView` update.\n *\n * @since 0.5\n * @example\n * // replaceTickHead(stream, tickBar);\n */\nexport function replaceTickHead(stream: StreamState, rawBar: Bar): void {\n const values = deriveBarSources(rawBar);\n const { ohlcv, bar } = stream;\n ohlcv.close.replaceHead(rawBar.close);\n ohlcv.high.replaceHead(rawBar.high);\n ohlcv.low.replaceHead(rawBar.low);\n ohlcv.volume.replaceHead(rawBar.volume);\n ohlcv.hl2.replaceHead(values.hl2);\n ohlcv.hlc3.replaceHead(values.hlc3);\n ohlcv.ohlc4.replaceHead(values.ohlc4);\n ohlcv.hlcc4.replaceHead(values.hlcc4);\n bar.close = rawBar.close;\n bar.high = rawBar.high;\n bar.low = rawBar.low;\n bar.volume = rawBar.volume;\n bar.hl2 = values.hl2;\n bar.hlc3 = values.hlc3;\n bar.ohlc4 = values.ohlc4;\n bar.hlcc4 = values.hlcc4;\n}\n\n/**\n * Refresh the stream's fallback visible range to the latest `limit`\n * bars ending at the current head.\n *\n * @since 0.5\n * @example\n * // updateFallbackViewport(stream);\n */\nexport function updateFallbackViewport(stream: StreamState, limit = 100): void {\n const length = stream.ohlcv.time.length;\n if (length === 0) {\n stream.bar.viewport = Object.freeze({ fromTime: 0, toTime: 0 });\n return;\n }\n const lookback = Math.min(length - 1, Math.max(0, limit - 1));\n const fromTime = stream.ohlcv.time.at(lookback);\n const toTime = stream.ohlcv.time.at(0);\n stream.bar.viewport = Object.freeze({\n fromTime: Number.isFinite(fromTime) ? fromTime : toTime,\n toTime,\n });\n}\n"]}
1
+ {"version":3,"file":"streamState.js","sourceRoot":"","sources":["../src/streamState.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 BarViewport,\n Price,\n PriceSeries,\n Series,\n StreamSnapshot,\n VolumeSeries,\n WorldPoint,\n} from \"@invinite-org/chartlang-core\";\n\nimport { resolveBarPoint } from \"./barPoint.js\";\nimport { Float64RingBuffer } from \"./ringBuffer.js\";\nimport { makeSeriesView } from \"./seriesView.js\";\n\ntype DerivedBarValues = Readonly<{\n hl2: number;\n hlc3: number;\n ohlc4: number;\n hlcc4: number;\n}>;\n\nfunction deriveBarSources(rawBar: Bar): DerivedBarValues {\n return {\n hl2: (rawBar.high + rawBar.low) / 2,\n hlc3: (rawBar.high + rawBar.low + rawBar.close) / 3,\n ohlc4: (rawBar.open + rawBar.high + rawBar.low + rawBar.close) / 4,\n hlcc4: (rawBar.high + rawBar.low + rawBar.close + rawBar.close) / 4,\n };\n}\n\n/**\n * The per-stream OHLCV ring-buffer set. Each field is a\n * `Float64RingBuffer` of identical capacity. Derived sources\n * (`hl2`, `hlc3`, `ohlc4`, `hlcc4`) are pre-computed by Task 6's\n * execution loop alongside the raw OHLCV fields so primitives can\n * read them as plain `Series<number>` without re-computing per\n * lookup.\n *\n * @since 0.1\n * @example\n * // import { createStreamState } from \"@invinite-org/chartlang-runtime\";\n * // const { ohlcv } = createStreamState({\n * // interval: \"1D\",\n * // capacity: 5,\n * // symbol: \"AAPL\",\n * // });\n * // ohlcv.close.capacity; // 5\n */\nexport type OhlcvBuffers = {\n readonly time: Float64RingBuffer;\n readonly open: Float64RingBuffer;\n readonly high: Float64RingBuffer;\n readonly low: Float64RingBuffer;\n readonly close: Float64RingBuffer;\n readonly volume: Float64RingBuffer;\n readonly hl2: Float64RingBuffer;\n readonly hlc3: Float64RingBuffer;\n readonly ohlc4: Float64RingBuffer;\n readonly hlcc4: Float64RingBuffer;\n};\n\n/**\n * View of the current bar handed to `compute`. Identity stays stable across\n * the run. The OHLCV + derived price/volume fields are the stream's cached\n * number-coercible `Series` views (one identity per ring buffer) — they read\n * the live buffer head, so a script can both use `bar.close` as a scalar\n * (`bar.close * 2`) and index it (`bar.close[1]`) without the runtime copying\n * scalars per bar. `time` stays a mutable scalar (the timestamp axis the\n * emit/draw pipeline consumes as a raw number); `symbol` / `interval` are\n * constant strings for a given `StreamState`.\n *\n * Before the first bar the buffers are empty, so `bar.close[0]` / `+bar.close`\n * read `NaN` and `bar.close.length` is `0`.\n *\n * @since 0.1\n * @example\n * // import { createStreamState } from \"@invinite-org/chartlang-runtime\";\n * // const { bar } = createStreamState({\n * // interval: \"1D\",\n * // capacity: 5,\n * // symbol: \"AAPL\",\n * // });\n * // bar.symbol; // \"AAPL\"\n * // bar.interval; // \"1D\"\n * // +bar.close; // NaN until the first bar\n * // bar.close.length; // 0 until the first bar\n */\nexport type BarView = {\n time: number;\n open: PriceSeries;\n high: PriceSeries;\n low: PriceSeries;\n close: PriceSeries;\n volume: VolumeSeries;\n hl2: PriceSeries;\n hlc3: PriceSeries;\n ohlc4: PriceSeries;\n hlcc4: PriceSeries;\n symbol: string;\n interval: string;\n viewport: BarViewport;\n point(offset: number, price: Price): WorldPoint;\n};\n\n/**\n * Everything the runtime owns for a single interval stream — the OHLCV\n * ring buffers, the mutable `BarView`, cached `Series<number>` Proxies\n * for each source field (one identity per buffer for the lifetime of\n * the stream), and a `taSlots` map keyed by compiler-assigned slot id\n * that stateful primitives in Task 7 use as their hidden-state\n * scratchpad.\n *\n * Phase 1 ships single-stream scripts; secondary streams via\n * `request.security` arrive in Phase 5 and reuse this exact shape per\n * interval.\n *\n * @since 0.1\n * @example\n * // import { createStreamState } from \"@invinite-org/chartlang-runtime\";\n * // const stream = createStreamState({\n * // interval: \"1D\",\n * // capacity: 21,\n * // symbol: \"AAPL\",\n * // });\n * // stream.taSlots.size; // 0\n */\nexport type StreamState = {\n readonly interval: string;\n readonly ohlcv: OhlcvBuffers;\n readonly bar: BarView;\n readonly seriesViews: {\n readonly time: Series<number>;\n readonly open: Series<number>;\n readonly high: Series<number>;\n readonly low: Series<number>;\n readonly close: Series<number>;\n readonly volume: Series<number>;\n readonly hl2: Series<number>;\n readonly hlc3: Series<number>;\n readonly ohlc4: Series<number>;\n readonly hlcc4: Series<number>;\n };\n readonly taSlots: Map<string, unknown>;\n serialiseSnapshot(): StreamSnapshot;\n restoreFromSnapshot(snapshot: StreamSnapshot): void;\n};\n\nconst rawBufferKeys = [\"time\", \"open\", \"high\", \"low\", \"close\", \"volume\"] as const;\n\ntype RawBufferKey = (typeof rawBufferKeys)[number];\n\nfunction rawBuffers(ohlcv: OhlcvBuffers): Readonly<Record<RawBufferKey, Float64RingBuffer>> {\n return {\n time: ohlcv.time,\n open: ohlcv.open,\n high: ohlcv.high,\n low: ohlcv.low,\n close: ohlcv.close,\n volume: ohlcv.volume,\n };\n}\n\nfunction valueAt(values: ReadonlyArray<number | null>, index: number): number {\n const value = values[index];\n return value === null || value === undefined ? Number.NaN : value;\n}\n\nfunction recomputeDerivedBuffers(ohlcv: OhlcvBuffers, snapshot: StreamSnapshot): void {\n const { headIndex, filled, buffers } = snapshot;\n const capacity = ohlcv.hl2.capacity;\n const derived = {\n hl2: new Array<number | null>(capacity),\n hlc3: new Array<number | null>(capacity),\n ohlc4: new Array<number | null>(capacity),\n hlcc4: new Array<number | null>(capacity),\n };\n for (let i = 0; i < capacity; i += 1) {\n const high = valueAt(buffers.high, i);\n const low = valueAt(buffers.low, i);\n const open = valueAt(buffers.open, i);\n const close = valueAt(buffers.close, i);\n derived.hl2[i] = Number.isNaN(high) || Number.isNaN(low) ? null : (high + low) / 2;\n derived.hlc3[i] =\n Number.isNaN(high) || Number.isNaN(low) || Number.isNaN(close)\n ? null\n : (high + low + close) / 3;\n derived.ohlc4[i] =\n Number.isNaN(open) || Number.isNaN(high) || Number.isNaN(low) || Number.isNaN(close)\n ? null\n : (open + high + low + close) / 4;\n derived.hlcc4[i] =\n Number.isNaN(high) || Number.isNaN(low) || Number.isNaN(close)\n ? null\n : (high + low + close + close) / 4;\n }\n ohlcv.hl2.restoreFromSnapshotBuffer({ headIndex, filled, values: derived.hl2 });\n ohlcv.hlc3.restoreFromSnapshotBuffer({ headIndex, filled, values: derived.hlc3 });\n ohlcv.ohlc4.restoreFromSnapshotBuffer({ headIndex, filled, values: derived.ohlc4 });\n ohlcv.hlcc4.restoreFromSnapshotBuffer({ headIndex, filled, values: derived.hlcc4 });\n}\n\n/**\n * Construct a fresh `StreamState`. The ring-buffer capacity is the\n * compiler-emitted `manifest.maxLookback + 1`\n * (caller must enforce `capacity >= 1`). All buffers start empty;\n * the `BarView` starts with `NaN` prices, `0` time and volume, and the\n * supplied `symbol` / `interval` constants. `taSlots` is an empty map.\n *\n * @since 0.1\n * @example\n * // import { createStreamState } from \"@invinite-org/chartlang-runtime\";\n * // const stream = createStreamState({\n * // interval: \"5m\",\n * // capacity: 12,\n * // symbol: \"BTCUSD\",\n * // });\n * // stream.bar.close; // NaN\n * // stream.ohlcv.close.length; // 0\n */\nexport function createStreamState(args: {\n interval: string;\n capacity: number;\n symbol: string;\n}): StreamState {\n const { interval, capacity, symbol } = args;\n const ohlcv: OhlcvBuffers = {\n time: new Float64RingBuffer(capacity),\n open: new Float64RingBuffer(capacity),\n high: new Float64RingBuffer(capacity),\n low: new Float64RingBuffer(capacity),\n close: new Float64RingBuffer(capacity),\n volume: new Float64RingBuffer(capacity),\n hl2: new Float64RingBuffer(capacity),\n hlc3: new Float64RingBuffer(capacity),\n ohlc4: new Float64RingBuffer(capacity),\n hlcc4: new Float64RingBuffer(capacity),\n };\n const seriesViews: StreamState[\"seriesViews\"] = {\n time: makeSeriesView<number>(ohlcv.time),\n open: makeSeriesView<number>(ohlcv.open),\n high: makeSeriesView<number>(ohlcv.high),\n low: makeSeriesView<number>(ohlcv.low),\n close: makeSeriesView<number>(ohlcv.close),\n volume: makeSeriesView<number>(ohlcv.volume),\n hl2: makeSeriesView<number>(ohlcv.hl2),\n hlc3: makeSeriesView<number>(ohlcv.hlc3),\n ohlc4: makeSeriesView<number>(ohlcv.ohlc4),\n hlcc4: makeSeriesView<number>(ohlcv.hlcc4),\n };\n // The OHLCV + derived bar fields ARE the cached series views (one identity\n // per ring buffer): the views are number-coercible, so `bar.close` works\n // as a scalar (`+bar.close` / arithmetic reads the live head) and as an\n // index (`bar.close[1]` reads a prior bar). No per-bar scalar copy is\n // needed — the views read the buffer head directly, including mid-tick.\n const bar: BarView = {\n time: 0,\n open: seriesViews.open as PriceSeries,\n high: seriesViews.high as PriceSeries,\n low: seriesViews.low as PriceSeries,\n close: seriesViews.close as PriceSeries,\n volume: seriesViews.volume as VolumeSeries,\n hl2: seriesViews.hl2 as PriceSeries,\n hlc3: seriesViews.hlc3 as PriceSeries,\n ohlc4: seriesViews.ohlc4 as PriceSeries,\n hlcc4: seriesViews.hlcc4 as PriceSeries,\n symbol,\n interval,\n viewport: Object.freeze({ fromTime: 0, toTime: 0 }),\n // Closes over the stream's time history + the live scalar `bar.time` /\n // `bar.interval` so offset-anchored drawings resolve against the real /\n // extrapolated time at compute time. The `WorldPoint` it returns is the\n // only persisted anchor frame — `bar.point` adds no new wire shape.\n point: (offset: number, price: Price): WorldPoint =>\n resolveBarPoint(ohlcv.time, bar.interval, bar.time, offset, price),\n };\n const stream: StreamState = {\n interval,\n ohlcv,\n bar,\n seriesViews,\n taSlots: new Map<string, unknown>(),\n serialiseSnapshot(): StreamSnapshot {\n const close = ohlcv.close.serialiseSnapshotBuffer();\n const buffers = rawBuffers(ohlcv);\n return Object.freeze({\n interval: bar.interval,\n headIndex: close.headIndex,\n filled: close.filled,\n buffers: Object.freeze({\n time: buffers.time.serialiseSnapshotBuffer().values,\n open: buffers.open.serialiseSnapshotBuffer().values,\n high: buffers.high.serialiseSnapshotBuffer().values,\n low: buffers.low.serialiseSnapshotBuffer().values,\n close: close.values,\n volume: buffers.volume.serialiseSnapshotBuffer().values,\n }),\n });\n },\n restoreFromSnapshot(snapshot: StreamSnapshot): void {\n const buffers = rawBuffers(ohlcv);\n for (const key of rawBufferKeys) {\n buffers[key].restoreFromSnapshotBuffer({\n headIndex: snapshot.headIndex,\n filled: snapshot.filled,\n values: snapshot.buffers[key],\n });\n }\n recomputeDerivedBuffers(ohlcv, snapshot);\n // The OHLCV + derived `bar.*` fields are the series views over the\n // ring buffers just restored above, so they reflect the restored\n // head with no scalar copy. Only the scalar `time` / `interval`\n // need writing.\n const current = snapshot.headIndex;\n bar.time =\n snapshot.filled === 0 || current < 0 ? 0 : valueAt(snapshot.buffers.time, current);\n bar.interval = snapshot.interval;\n },\n };\n return stream;\n}\n\n/**\n * Append a finalised candle to a stream — extends the OHLCV ring buffers\n * by one bar and writes every field of the mutable `BarView` (including\n * `time` / `open`). Used by both the main close path and secondary\n * stream history.\n *\n * @since 0.5\n * @example\n * // appendBarToStream(stream, rawBar);\n */\nexport function appendBarToStream(stream: StreamState, rawBar: Bar): void {\n const values = deriveBarSources(rawBar);\n const { ohlcv, bar } = stream;\n ohlcv.time.append(rawBar.time);\n ohlcv.open.append(rawBar.open);\n ohlcv.high.append(rawBar.high);\n ohlcv.low.append(rawBar.low);\n ohlcv.close.append(rawBar.close);\n ohlcv.volume.append(rawBar.volume);\n ohlcv.hl2.append(values.hl2);\n ohlcv.hlc3.append(values.hlc3);\n ohlcv.ohlc4.append(values.ohlc4);\n ohlcv.hlcc4.append(values.hlcc4);\n // OHLCV + derived bar fields read the buffer head live (they ARE the\n // series views), so only the scalar `time` / `symbol` / `interval` are\n // copied onto the `BarView`.\n bar.time = rawBar.time;\n bar.symbol = rawBar.symbol;\n bar.interval = rawBar.interval;\n}\n\n/**\n * Replace the head of every OHLCV ring buffer in a stream and write\n * every field of the `BarView`. Used by the secondary-stream replace\n * path — falls back to {@link appendBarToStream} for the empty-buffer\n * case so the first secondary bar arrives correctly even when delivered\n * as a replace.\n *\n * @since 0.5\n * @example\n * // replaceStreamHead(stream, rawBar);\n */\nexport function replaceStreamHead(stream: StreamState, rawBar: Bar): void {\n if (stream.ohlcv.close.length === 0) {\n appendBarToStream(stream, rawBar);\n return;\n }\n const values = deriveBarSources(rawBar);\n const { ohlcv, bar } = stream;\n ohlcv.time.replaceHead(rawBar.time);\n ohlcv.open.replaceHead(rawBar.open);\n ohlcv.high.replaceHead(rawBar.high);\n ohlcv.low.replaceHead(rawBar.low);\n ohlcv.close.replaceHead(rawBar.close);\n ohlcv.volume.replaceHead(rawBar.volume);\n ohlcv.hl2.replaceHead(values.hl2);\n ohlcv.hlc3.replaceHead(values.hlc3);\n ohlcv.ohlc4.replaceHead(values.ohlc4);\n ohlcv.hlcc4.replaceHead(values.hlcc4);\n // See appendBarToStream — the OHLCV/derived views read the head live.\n bar.time = rawBar.time;\n bar.symbol = rawBar.symbol;\n bar.interval = rawBar.interval;\n}\n\n/**\n * Replace the head of the close-side OHLCV ring buffers (close, high,\n * low, volume, derived sources) for a tick within the in-progress bar.\n * `time` and `open` are intentionally untouched — see\n * `packages/runtime/CLAUDE.md` \"onBarTick does NOT touch time / open\"\n * invariant. Mirrors the partial `BarView` update.\n *\n * @since 0.5\n * @example\n * // replaceTickHead(stream, tickBar);\n */\nexport function replaceTickHead(stream: StreamState, rawBar: Bar): void {\n const values = deriveBarSources(rawBar);\n const { ohlcv } = stream;\n ohlcv.close.replaceHead(rawBar.close);\n ohlcv.high.replaceHead(rawBar.high);\n ohlcv.low.replaceHead(rawBar.low);\n ohlcv.volume.replaceHead(rawBar.volume);\n ohlcv.hl2.replaceHead(values.hl2);\n ohlcv.hlc3.replaceHead(values.hlc3);\n ohlcv.ohlc4.replaceHead(values.ohlc4);\n ohlcv.hlcc4.replaceHead(values.hlcc4);\n // The close-side / derived `bar.*` fields are the series views over these\n // buffers, so replacing the buffer head is the whole update — no scalar\n // copy. `time` / `open` are intentionally untouched (tick invariant).\n}\n\n/**\n * Refresh the stream's fallback visible range to the latest `limit`\n * bars ending at the current head.\n *\n * @since 0.5\n * @example\n * // updateFallbackViewport(stream);\n */\nexport function updateFallbackViewport(stream: StreamState, limit = 100): void {\n const length = stream.ohlcv.time.length;\n if (length === 0) {\n stream.bar.viewport = Object.freeze({ fromTime: 0, toTime: 0 });\n return;\n }\n const lookback = Math.min(length - 1, Math.max(0, limit - 1));\n const fromTime = stream.ohlcv.time.at(lookback);\n const toTime = stream.ohlcv.time.at(0);\n stream.bar.viewport = Object.freeze({\n fromTime: Number.isFinite(fromTime) ? fromTime : toTime,\n toTime,\n });\n}\n"]}
package/dist/ta/adx.d.ts CHANGED
@@ -18,8 +18,9 @@ import type { AdxOpts, Series } from "@invinite-org/chartlang-core";
18
18
  * @since 0.2
19
19
  * @stable
20
20
  *
21
- * `opts.offset` shifts the returned series
22
- * `series.current` returns the value `offset` bars ago.
21
+ * `opts.offset` is a presentation display shift carried to the plot
22
+ * emission as `xShift` (`+n` right / future, `−n` left / past); the
23
+ * series value is unshifted.
23
24
  *
24
25
  * @example
25
26
  * // import { ta } from "@invinite-org/chartlang-runtime";
@@ -1 +1 @@
1
- {"version":3,"file":"adx.d.ts","sourceRoot":"","sources":["../../src/ta/adx.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AA0IpE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAelF"}
1
+ {"version":3,"file":"adx.d.ts","sourceRoot":"","sources":["../../src/ta/adx.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AA0IpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAelF"}
package/dist/ta/adx.js CHANGED
@@ -138,8 +138,9 @@ function tickValue(slot, high, low, close) {
138
138
  * @since 0.2
139
139
  * @stable
140
140
  *
141
- * `opts.offset` shifts the returned series
142
- * `series.current` returns the value `offset` bars ago.
141
+ * `opts.offset` is a presentation display shift carried to the plot
142
+ * emission as `xShift` (`+n` right / future, `−n` left / past); the
143
+ * series value is unshifted.
143
144
  *
144
145
  * @example
145
146
  * // import { ta } from "@invinite-org/chartlang-runtime";
@@ -1 +1 @@
1
- {"version":3,"file":"adx.js","sourceRoot":"","sources":["../../src/ta/adx.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// Ported from invinite/src/components/trading-chart/indicators/adx.ts\n// plus lib/wilder-directional.ts + lib/adx-from-di.ts\n// (commit 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite).\n// Re-licensed MIT for chartlang. The math is the reference, the code\n// style is not.\n// Structural choices (callsite-id slot, Series<T> proxy, replaceHead\n// mode) follow chartlang's primitive shape — NOT invinite's\n// IndicatorPlugin shape. ADX reads `bar.high` / `bar.low` /\n// `bar.close` directly (mirrors Pine's `ta.adx(length)` — no source\n// param) and runs the Wilder DI smoothing AND the DX → Wilder-\n// smoothed ADX recurrence incrementally via `wilderStep` (the same\n// per-step recurrence the reference helpers\n// `lib/wilderDirectional.ts` + `lib/adxFromDi.ts` use internally).\n\nimport type { AdxOpts, Series } from \"@invinite-org/chartlang-core\";\n\nimport {\n advanceDirectionalClose,\n initDirectionalState,\n tickDirectional,\n} from \"./lib/directionalState.js\";\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeSeriesView, makeShiftedSeriesView } from \"../seriesView.js\";\nimport { wilderStep } from \"./lib/wilderSmoothing.js\";\n\nconst DEFAULT_SMOOTHING = 14;\n\ntype AdxSlot = {\n readonly outBuffer: Float64RingBuffer;\n readonly series: Series<number>;\n readonly smoothingLength: number;\n readonly dirState: ReturnType<typeof initDirectionalState>;\n /** Running sum of DX samples while the ADX seed window fills. */\n dxSeed: number;\n /** Number of DX samples folded into the seed (0..smoothingLength). */\n dxSeedCount: number;\n /** Wilder-smoothed ADX. NaN until the DX seed completes. */\n adx: number;\n /** ADX as of the prior closed bar — used by tick-mode replay. */\n prevClosedAdx: number;\n /** DX seed accumulator + count as of the prior closed bar — used by\n * tick replay when the seed window is still filling. */\n prevClosedDxSeed: number;\n prevClosedDxSeedCount: number;\n /** Per-offset Series-view cache; see `sma.ts` for the convention. */\n readonly shiftedViews: Map<number, Series<number>>;\n};\n\nfunction getCtx(): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(\"ta.adx called outside an active script step\");\n }\n return ctx;\n}\n\nfunction initSlot(length: number, smoothingLength: number, capacity: number): AdxSlot {\n const outBuffer = new Float64RingBuffer(capacity);\n return {\n outBuffer,\n series: makeSeriesView<number>(outBuffer),\n smoothingLength,\n dirState: initDirectionalState(length),\n dxSeed: 0,\n dxSeedCount: 0,\n adx: Number.NaN,\n prevClosedAdx: Number.NaN,\n prevClosedDxSeed: 0,\n prevClosedDxSeedCount: 0,\n shiftedViews: new Map(),\n };\n}\n\nfunction viewForOffset(slot: AdxSlot, offset: number): Series<number> {\n if (offset === 0) return slot.series;\n let view = slot.shiftedViews.get(offset);\n if (view === undefined) {\n view = makeShiftedSeriesView<number>(slot.outBuffer, offset);\n slot.shiftedViews.set(offset, view);\n }\n return view;\n}\n\nfunction dxFromDi(plusDi: number, minusDi: number): number {\n const sum = plusDi + minusDi;\n if (sum === 0) return 0;\n return (100 * Math.abs(plusDi - minusDi)) / sum;\n}\n\nfunction closeValue(slot: AdxSlot, high: number, low: number, close: number): number {\n if (!Number.isFinite(high) || !Number.isFinite(low) || !Number.isFinite(close)) {\n // NaN inputs: do not advance the DI / DX recurrence. Hold the\n // prior ADX forward (matches `atr.ts` / `rsi.ts` NaN-input\n // semantics). The DI helper's own NaN handling already returns\n // the held-forward DI, but folding the held-DI into a fresh DX\n // would falsely advance the ADX recurrence.\n return Number.isFinite(slot.adx) ? slot.adx : Number.NaN;\n }\n const { plusDi, minusDi } = advanceDirectionalClose(slot.dirState, high, low, close);\n if (!Number.isFinite(plusDi) || !Number.isFinite(minusDi)) {\n // DI still in warmup — capture prior state for tick replay.\n slot.prevClosedAdx = slot.adx;\n slot.prevClosedDxSeed = slot.dxSeed;\n slot.prevClosedDxSeedCount = slot.dxSeedCount;\n return Number.NaN;\n }\n const dx = dxFromDi(plusDi, minusDi);\n // Capture prior state BEFORE folding this close into the DX seed.\n slot.prevClosedAdx = slot.adx;\n slot.prevClosedDxSeed = slot.dxSeed;\n slot.prevClosedDxSeedCount = slot.dxSeedCount;\n\n if (slot.dxSeedCount < slot.smoothingLength) {\n slot.dxSeed += dx;\n slot.dxSeedCount += 1;\n if (slot.dxSeedCount === slot.smoothingLength) {\n slot.adx = slot.dxSeed / slot.smoothingLength;\n return slot.adx;\n }\n return Number.NaN;\n }\n slot.adx = wilderStep(slot.adx, dx, slot.smoothingLength);\n return slot.adx;\n}\n\nfunction tickValue(slot: AdxSlot, high: number, low: number, close: number): number {\n const { plusDi, minusDi } = tickDirectional(slot.dirState, high, low, close);\n if (!Number.isFinite(plusDi) || !Number.isFinite(minusDi)) {\n // Defensive: `tickDirectional` returns NaN only when the\n // directional-state warmup has not completed (barCount <\n // length + 1) — and at that point `slot.adx` is still NaN\n // (adx warms strictly later than DI). So `Number.isFinite(slot.adx)`\n // is always false on this branch; kept for safety.\n return /* c8 ignore next */ Number.isFinite(slot.adx) ? slot.adx : Number.NaN;\n }\n const dx = dxFromDi(plusDi, minusDi);\n // Defensive: the close-side advance runs first on every bar and\n // raises `prevClosedDxSeedCount` to `smoothingLength` once the\n // seed window completes. The tick-side never observes a partial\n // DX-seed window because the bar that completes it has already\n // committed its close-side increment by the time `tickValue` runs.\n /* c8 ignore start */\n if (slot.prevClosedDxSeedCount < slot.smoothingLength) {\n const provisionalCount = slot.prevClosedDxSeedCount + 1;\n if (provisionalCount < slot.smoothingLength) return Number.NaN;\n return (slot.prevClosedDxSeed + dx) / slot.smoothingLength;\n }\n /* c8 ignore stop */\n return wilderStep(slot.prevClosedAdx, dx, slot.smoothingLength);\n}\n\n/**\n * Wilder's Average Directional Index — single-line trend-strength\n * oscillator bounded in `[0, 100]`. Reads `bar.high` / `bar.low` /\n * `bar.close` directly (mirrors Pine's `ta.adx(length)` — no source\n * param). Composes onto the same Wilder directional-movement\n * recurrence `ta.dmi` runs (`+DI` / `−DI` from Wilder-smoothed `+DM`\n * / `−DM` / TR), then folds DX = `100 · |+DI − −DI| / (+DI + −DI)`\n * into a second Wilder-smoothing window of length\n * `opts.smoothing` (default `14`).\n *\n * @formula +DI, −DI per `ta.dmi(length)` ;\n * DX[t] = (+DI + −DI) === 0 ? 0 : 100 · |+DI − −DI| / (+DI + −DI) ;\n * seed at first defined ADX bar = mean(DX over `smoothing` samples) ;\n * ADX[t] = wilderStep(ADX[t−1], DX[t], smoothing)\n * @warmup length + smoothing − 1\n * @anchors length, smoothing\n * @since 0.2\n * @stable\n *\n * `opts.offset` shifts the returned series —\n * `series.current` returns the value `offset` bars ago.\n *\n * @example\n * // import { ta } from \"@invinite-org/chartlang-runtime\";\n * // const a = ta.adx(\"slot\", 14);\n * // plot(a);\n * // const lagged = ta.adx(\"slot2\", 14, { offset: 5 });\n */\nexport function adx(slotId: string, length: number, opts?: AdxOpts): Series<number> {\n const ctx = getCtx();\n const smoothingLength = opts?.smoothing ?? DEFAULT_SMOOTHING;\n let slot = ctx.stream.taSlots.get(slotId) as AdxSlot | undefined;\n if (slot === undefined) {\n slot = initSlot(length, smoothingLength, ctx.stream.ohlcv.close.capacity);\n ctx.stream.taSlots.set(slotId, slot);\n }\n const bar = ctx.stream.bar;\n if (ctx.isTick) {\n slot.outBuffer.replaceHead(tickValue(slot, bar.high, bar.low, bar.close));\n } else {\n slot.outBuffer.append(closeValue(slot, bar.high, bar.low, bar.close));\n }\n return viewForOffset(slot, opts?.offset ?? 0);\n}\n"]}
1
+ {"version":3,"file":"adx.js","sourceRoot":"","sources":["../../src/ta/adx.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// Ported from invinite/src/components/trading-chart/indicators/adx.ts\n// plus lib/wilder-directional.ts + lib/adx-from-di.ts\n// (commit 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite).\n// Re-licensed MIT for chartlang. The math is the reference, the code\n// style is not.\n// Structural choices (callsite-id slot, Series<T> proxy, replaceHead\n// mode) follow chartlang's primitive shape — NOT invinite's\n// IndicatorPlugin shape. ADX reads `bar.high` / `bar.low` /\n// `bar.close` directly (mirrors Pine's `ta.adx(length)` — no source\n// param) and runs the Wilder DI smoothing AND the DX → Wilder-\n// smoothed ADX recurrence incrementally via `wilderStep` (the same\n// per-step recurrence the reference helpers\n// `lib/wilderDirectional.ts` + `lib/adxFromDi.ts` use internally).\n\nimport type { AdxOpts, Series } from \"@invinite-org/chartlang-core\";\n\nimport {\n advanceDirectionalClose,\n initDirectionalState,\n tickDirectional,\n} from \"./lib/directionalState.js\";\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeSeriesView, makeShiftedSeriesView } from \"../seriesView.js\";\nimport { wilderStep } from \"./lib/wilderSmoothing.js\";\n\nconst DEFAULT_SMOOTHING = 14;\n\ntype AdxSlot = {\n readonly outBuffer: Float64RingBuffer;\n readonly series: Series<number>;\n readonly smoothingLength: number;\n readonly dirState: ReturnType<typeof initDirectionalState>;\n /** Running sum of DX samples while the ADX seed window fills. */\n dxSeed: number;\n /** Number of DX samples folded into the seed (0..smoothingLength). */\n dxSeedCount: number;\n /** Wilder-smoothed ADX. NaN until the DX seed completes. */\n adx: number;\n /** ADX as of the prior closed bar — used by tick-mode replay. */\n prevClosedAdx: number;\n /** DX seed accumulator + count as of the prior closed bar — used by\n * tick replay when the seed window is still filling. */\n prevClosedDxSeed: number;\n prevClosedDxSeedCount: number;\n /** Per-offset Series-view cache; see `sma.ts` for the convention. */\n readonly shiftedViews: Map<number, Series<number>>;\n};\n\nfunction getCtx(): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(\"ta.adx called outside an active script step\");\n }\n return ctx;\n}\n\nfunction initSlot(length: number, smoothingLength: number, capacity: number): AdxSlot {\n const outBuffer = new Float64RingBuffer(capacity);\n return {\n outBuffer,\n series: makeSeriesView<number>(outBuffer),\n smoothingLength,\n dirState: initDirectionalState(length),\n dxSeed: 0,\n dxSeedCount: 0,\n adx: Number.NaN,\n prevClosedAdx: Number.NaN,\n prevClosedDxSeed: 0,\n prevClosedDxSeedCount: 0,\n shiftedViews: new Map(),\n };\n}\n\nfunction viewForOffset(slot: AdxSlot, offset: number): Series<number> {\n if (offset === 0) return slot.series;\n let view = slot.shiftedViews.get(offset);\n if (view === undefined) {\n view = makeShiftedSeriesView<number>(slot.outBuffer, offset);\n slot.shiftedViews.set(offset, view);\n }\n return view;\n}\n\nfunction dxFromDi(plusDi: number, minusDi: number): number {\n const sum = plusDi + minusDi;\n if (sum === 0) return 0;\n return (100 * Math.abs(plusDi - minusDi)) / sum;\n}\n\nfunction closeValue(slot: AdxSlot, high: number, low: number, close: number): number {\n if (!Number.isFinite(high) || !Number.isFinite(low) || !Number.isFinite(close)) {\n // NaN inputs: do not advance the DI / DX recurrence. Hold the\n // prior ADX forward (matches `atr.ts` / `rsi.ts` NaN-input\n // semantics). The DI helper's own NaN handling already returns\n // the held-forward DI, but folding the held-DI into a fresh DX\n // would falsely advance the ADX recurrence.\n return Number.isFinite(slot.adx) ? slot.adx : Number.NaN;\n }\n const { plusDi, minusDi } = advanceDirectionalClose(slot.dirState, high, low, close);\n if (!Number.isFinite(plusDi) || !Number.isFinite(minusDi)) {\n // DI still in warmup — capture prior state for tick replay.\n slot.prevClosedAdx = slot.adx;\n slot.prevClosedDxSeed = slot.dxSeed;\n slot.prevClosedDxSeedCount = slot.dxSeedCount;\n return Number.NaN;\n }\n const dx = dxFromDi(plusDi, minusDi);\n // Capture prior state BEFORE folding this close into the DX seed.\n slot.prevClosedAdx = slot.adx;\n slot.prevClosedDxSeed = slot.dxSeed;\n slot.prevClosedDxSeedCount = slot.dxSeedCount;\n\n if (slot.dxSeedCount < slot.smoothingLength) {\n slot.dxSeed += dx;\n slot.dxSeedCount += 1;\n if (slot.dxSeedCount === slot.smoothingLength) {\n slot.adx = slot.dxSeed / slot.smoothingLength;\n return slot.adx;\n }\n return Number.NaN;\n }\n slot.adx = wilderStep(slot.adx, dx, slot.smoothingLength);\n return slot.adx;\n}\n\nfunction tickValue(slot: AdxSlot, high: number, low: number, close: number): number {\n const { plusDi, minusDi } = tickDirectional(slot.dirState, high, low, close);\n if (!Number.isFinite(plusDi) || !Number.isFinite(minusDi)) {\n // Defensive: `tickDirectional` returns NaN only when the\n // directional-state warmup has not completed (barCount <\n // length + 1) — and at that point `slot.adx` is still NaN\n // (adx warms strictly later than DI). So `Number.isFinite(slot.adx)`\n // is always false on this branch; kept for safety.\n return /* c8 ignore next */ Number.isFinite(slot.adx) ? slot.adx : Number.NaN;\n }\n const dx = dxFromDi(plusDi, minusDi);\n // Defensive: the close-side advance runs first on every bar and\n // raises `prevClosedDxSeedCount` to `smoothingLength` once the\n // seed window completes. The tick-side never observes a partial\n // DX-seed window because the bar that completes it has already\n // committed its close-side increment by the time `tickValue` runs.\n /* c8 ignore start */\n if (slot.prevClosedDxSeedCount < slot.smoothingLength) {\n const provisionalCount = slot.prevClosedDxSeedCount + 1;\n if (provisionalCount < slot.smoothingLength) return Number.NaN;\n return (slot.prevClosedDxSeed + dx) / slot.smoothingLength;\n }\n /* c8 ignore stop */\n return wilderStep(slot.prevClosedAdx, dx, slot.smoothingLength);\n}\n\n/**\n * Wilder's Average Directional Index — single-line trend-strength\n * oscillator bounded in `[0, 100]`. Reads `bar.high` / `bar.low` /\n * `bar.close` directly (mirrors Pine's `ta.adx(length)` — no source\n * param). Composes onto the same Wilder directional-movement\n * recurrence `ta.dmi` runs (`+DI` / `−DI` from Wilder-smoothed `+DM`\n * / `−DM` / TR), then folds DX = `100 · |+DI − −DI| / (+DI + −DI)`\n * into a second Wilder-smoothing window of length\n * `opts.smoothing` (default `14`).\n *\n * @formula +DI, −DI per `ta.dmi(length)` ;\n * DX[t] = (+DI + −DI) === 0 ? 0 : 100 · |+DI − −DI| / (+DI + −DI) ;\n * seed at first defined ADX bar = mean(DX over `smoothing` samples) ;\n * ADX[t] = wilderStep(ADX[t−1], DX[t], smoothing)\n * @warmup length + smoothing − 1\n * @anchors length, smoothing\n * @since 0.2\n * @stable\n *\n * `opts.offset` is a presentation display shift carried to the plot\n * emission as `xShift` (`+n` right / future, `−n` left / past); the\n * series value is unshifted.\n *\n * @example\n * // import { ta } from \"@invinite-org/chartlang-runtime\";\n * // const a = ta.adx(\"slot\", 14);\n * // plot(a);\n * // const lagged = ta.adx(\"slot2\", 14, { offset: 5 });\n */\nexport function adx(slotId: string, length: number, opts?: AdxOpts): Series<number> {\n const ctx = getCtx();\n const smoothingLength = opts?.smoothing ?? DEFAULT_SMOOTHING;\n let slot = ctx.stream.taSlots.get(slotId) as AdxSlot | undefined;\n if (slot === undefined) {\n slot = initSlot(length, smoothingLength, ctx.stream.ohlcv.close.capacity);\n ctx.stream.taSlots.set(slotId, slot);\n }\n const bar = ctx.stream.bar;\n if (ctx.isTick) {\n slot.outBuffer.replaceHead(tickValue(slot, bar.high, bar.low, bar.close));\n } else {\n slot.outBuffer.append(closeValue(slot, bar.high, bar.low, bar.close));\n }\n return viewForOffset(slot, opts?.offset ?? 0);\n}\n"]}
package/dist/ta/alma.d.ts CHANGED
@@ -11,10 +11,12 @@ import { type ScalarOrSeries } from "./lib/sourceValue.js";
11
11
  * weighted-window convention).
12
12
  *
13
13
  * **`opts.offset` is the Gaussian-centre position in `[0, 1]`**, NOT
14
- * the universal bar-shift. The universal shift on ALMA uses the
15
- * distinct `opts.barShift` field accepted on the surface (its
16
- * runtime side is wired alongside the universal `offset` support on
17
- * every primitive).
14
+ * the universal bar-shift. ALMA's universal shift lives on the distinct
15
+ * `opts.barShift` field: a presentation display shift (`+n` renders the
16
+ * series `n` bars right / future, `−n` `n` bars left / past) carried to
17
+ * the plot emission as `xShift`. It does not transform the series value —
18
+ * `series.current` is unshifted, matching every other primitive's
19
+ * `opts.offset`.
18
20
  *
19
21
  * @formula m = offset · (length − 1) ;
20
22
  * s = length / sigma ;
@@ -1 +1 @@
1
- {"version":3,"file":"alma.d.ts","sourceRoot":"","sources":["../../src/ta/alma.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAKrE,OAAO,EAAE,KAAK,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAiF5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,IAAI,CAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,QAAQ,GAChB,MAAM,CAAC,MAAM,CAAC,CAmBhB"}
1
+ {"version":3,"file":"alma.d.ts","sourceRoot":"","sources":["../../src/ta/alma.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAKrE,OAAO,EAAE,KAAK,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAoG5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,IAAI,CAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,QAAQ,GAChB,MAAM,CAAC,MAAM,CAAC,CAmBhB"}
package/dist/ta/alma.js CHANGED
@@ -12,7 +12,7 @@
12
12
  // which lives on `opts.barShift`.
13
13
  import { Float64RingBuffer } from "../ringBuffer.js";
14
14
  import { ACTIVE_RUNTIME_CONTEXT } from "../runtimeContext.js";
15
- import { makeSeriesView } from "../seriesView.js";
15
+ import { makeSeriesView, makeShiftedSeriesView } from "../seriesView.js";
16
16
  import { readSourceValue } from "./lib/sourceValue.js";
17
17
  const DEFAULT_OFFSET = 0.85;
18
18
  const DEFAULT_SIGMA = 6;
@@ -42,8 +42,19 @@ function initSlot(length, offsetCentre, sigma, capacity) {
42
42
  sourceWindow: new Float64RingBuffer(length),
43
43
  weights,
44
44
  normaliser,
45
+ shiftedViews: new Map(),
45
46
  };
46
47
  }
48
+ function viewForOffset(slot, barShift) {
49
+ if (barShift === 0)
50
+ return slot.series;
51
+ let view = slot.shiftedViews.get(barShift);
52
+ if (view === undefined) {
53
+ view = makeShiftedSeriesView(slot.outBuffer, barShift);
54
+ slot.shiftedViews.set(barShift, view);
55
+ }
56
+ return view;
57
+ }
47
58
  function weightedFromWindow(slot, headOverride) {
48
59
  let sum = 0;
49
60
  for (let j = 0; j < slot.length; j += 1) {
@@ -82,10 +93,12 @@ function tickValue(slot, src) {
82
93
  * weighted-window convention).
83
94
  *
84
95
  * **`opts.offset` is the Gaussian-centre position in `[0, 1]`**, NOT
85
- * the universal bar-shift. The universal shift on ALMA uses the
86
- * distinct `opts.barShift` field accepted on the surface (its
87
- * runtime side is wired alongside the universal `offset` support on
88
- * every primitive).
96
+ * the universal bar-shift. ALMA's universal shift lives on the distinct
97
+ * `opts.barShift` field: a presentation display shift (`+n` renders the
98
+ * series `n` bars right / future, `−n` `n` bars left / past) carried to
99
+ * the plot emission as `xShift`. It does not transform the series value —
100
+ * `series.current` is unshifted, matching every other primitive's
101
+ * `opts.offset`.
89
102
  *
90
103
  * @formula m = offset · (length − 1) ;
91
104
  * s = length / sigma ;
@@ -116,6 +129,6 @@ export function alma(slotId, source, length, opts) {
116
129
  else {
117
130
  slot.outBuffer.append(closeValue(slot, src));
118
131
  }
119
- return slot.series;
132
+ return viewForOffset(slot, opts?.barShift ?? 0);
120
133
  }
121
134
  //# sourceMappingURL=alma.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"alma.js","sourceRoot":"","sources":["../../src/ta/alma.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// Ported from invinite/src/components/trading-chart/indicators/alma.ts\n// (commit 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite).\n// Re-licensed MIT for chartlang. The math is the reference, the code\n// style is not.\n// Structural choices (callsite-id slot, Series<T> proxy, replaceHead\n// mode) follow chartlang's primitive shape — NOT invinite's\n// IndicatorPlugin shape. The ALMA `offset` opt is the Gaussian centre\n// in `[0, 1]` (default 0.85), distinct from the universal bar-shift\n// which lives on `opts.barShift`.\n\nimport type { AlmaOpts, Series } from \"@invinite-org/chartlang-core\";\n\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeSeriesView } from \"../seriesView.js\";\nimport { type ScalarOrSeries, readSourceValue } from \"./lib/sourceValue.js\";\n\nconst DEFAULT_OFFSET = 0.85;\nconst DEFAULT_SIGMA = 6;\n\ntype AlmaSlot = {\n readonly outBuffer: Float64RingBuffer;\n readonly series: Series<number>;\n readonly length: number;\n /**\n * Trailing `length` source values; `at(0)` is the head (most\n * recent), `at(length - 1)` is the oldest still in the window.\n */\n readonly sourceWindow: Float64RingBuffer;\n /**\n * Pre-computed Gaussian weights. `weights[j]` aligns with the\n * j-th OLDEST window entry (i.e. `window.at(length - 1 - j)`) so\n * `j = length - 1` weights the head and `j = 0` weights the\n * oldest — matches the invinite reference's `computeAlma` loop.\n */\n readonly weights: Float64Array;\n readonly normaliser: number;\n};\n\nfunction getCtx(): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(\"ta.alma called outside an active script step\");\n }\n return ctx;\n}\n\nfunction initSlot(length: number, offsetCentre: number, sigma: number, capacity: number): AlmaSlot {\n const outBuffer = new Float64RingBuffer(capacity);\n const m = offsetCentre * (length - 1);\n const s = length / sigma;\n const weights = new Float64Array(length);\n let normaliser = 0;\n for (let j = 0; j < length; j += 1) {\n const d = j - m;\n const w = Math.exp(-(d * d) / (2 * s * s));\n weights[j] = w;\n normaliser += w;\n }\n return {\n outBuffer,\n series: makeSeriesView<number>(outBuffer),\n length,\n sourceWindow: new Float64RingBuffer(length),\n weights,\n normaliser,\n };\n}\n\nfunction weightedFromWindow(slot: AlmaSlot, headOverride?: number): number {\n let sum = 0;\n for (let j = 0; j < slot.length; j += 1) {\n // j = 0 → oldest (window.at(length - 1)); j = length - 1 → head.\n const ageFromHead = slot.length - 1 - j;\n const v =\n ageFromHead === 0 && headOverride !== undefined\n ? headOverride\n : slot.sourceWindow.at(ageFromHead);\n if (!Number.isFinite(v)) return Number.NaN;\n sum += v * slot.weights[j];\n }\n return sum / slot.normaliser;\n}\n\nfunction closeValue(slot: AlmaSlot, src: number): number {\n slot.sourceWindow.append(src);\n if (slot.sourceWindow.length < slot.length) return Number.NaN;\n return weightedFromWindow(slot);\n}\n\nfunction tickValue(slot: AlmaSlot, src: number): number {\n if (slot.sourceWindow.length < slot.length) return Number.NaN;\n if (!Number.isFinite(src)) return Number.NaN;\n return weightedFromWindow(slot, src);\n}\n\n/**\n * Arnaud Legoux Moving Average — a Gaussian-weighted MA. Weights peak\n * at `offset · (length − 1)` (default `0.85 · (length − 1)`, near the\n * recent end of the window) and decay with standard deviation\n * `length / sigma` (default `length / 6`). Weights are pre-computed\n * once at slot init from `opts.offset` + `opts.sigma`; per-bar cost is\n * an O(length) window walk. A NaN anywhere in the window\n * short-circuits the output to NaN (matches the WMA full-recompute\n * weighted-window convention).\n *\n * **`opts.offset` is the Gaussian-centre position in `[0, 1]`**, NOT\n * the universal bar-shift. The universal shift on ALMA uses the\n * distinct `opts.barShift` field — accepted on the surface (its\n * runtime side is wired alongside the universal `offset` support on\n * every primitive).\n *\n * @formula m = offset · (length − 1) ;\n * s = length / sigma ;\n * w[j] = exp(−((j − m)² / (2 · s²))) for j = 0..length − 1 ;\n * norm = Σ w[j] ;\n * out[t] = (Σ_{j=0..length-1} w[j] · src[t − length + 1 + j]) / norm\n * @warmup length − 1\n * @anchors offset, sigma\n * @since 0.2\n * @stable\n *\n * @example\n * // import { ta } from \"@invinite-org/chartlang-core\";\n * // const a = ta.alma(bar.close, 9, { offset: 0.85, sigma: 6 });\n * // plot(a);\n */\nexport function alma(\n slotId: string,\n source: ScalarOrSeries,\n length: number,\n opts?: AlmaOpts,\n): Series<number> {\n const ctx = getCtx();\n let slot = ctx.stream.taSlots.get(slotId) as AlmaSlot | undefined;\n if (slot === undefined) {\n slot = initSlot(\n length,\n opts?.offset ?? DEFAULT_OFFSET,\n opts?.sigma ?? DEFAULT_SIGMA,\n ctx.stream.ohlcv.close.capacity,\n );\n ctx.stream.taSlots.set(slotId, slot);\n }\n const src = readSourceValue(source);\n if (ctx.isTick) {\n slot.outBuffer.replaceHead(tickValue(slot, src));\n } else {\n slot.outBuffer.append(closeValue(slot, src));\n }\n return slot.series;\n}\n"]}
1
+ {"version":3,"file":"alma.js","sourceRoot":"","sources":["../../src/ta/alma.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// Ported from invinite/src/components/trading-chart/indicators/alma.ts\n// (commit 078f41fe2569d659d5aba726da8bcb5d3e2ced02, © Invinite).\n// Re-licensed MIT for chartlang. The math is the reference, the code\n// style is not.\n// Structural choices (callsite-id slot, Series<T> proxy, replaceHead\n// mode) follow chartlang's primitive shape — NOT invinite's\n// IndicatorPlugin shape. The ALMA `offset` opt is the Gaussian centre\n// in `[0, 1]` (default 0.85), distinct from the universal bar-shift\n// which lives on `opts.barShift`.\n\nimport type { AlmaOpts, Series } from \"@invinite-org/chartlang-core\";\n\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeSeriesView, makeShiftedSeriesView } from \"../seriesView.js\";\nimport { type ScalarOrSeries, readSourceValue } from \"./lib/sourceValue.js\";\n\nconst DEFAULT_OFFSET = 0.85;\nconst DEFAULT_SIGMA = 6;\n\ntype AlmaSlot = {\n readonly outBuffer: Float64RingBuffer;\n readonly series: Series<number>;\n readonly length: number;\n /**\n * Trailing `length` source values; `at(0)` is the head (most\n * recent), `at(length - 1)` is the oldest still in the window.\n */\n readonly sourceWindow: Float64RingBuffer;\n /**\n * Pre-computed Gaussian weights. `weights[j]` aligns with the\n * j-th OLDEST window entry (i.e. `window.at(length - 1 - j)`) so\n * `j = length - 1` weights the head and `j = 0` weights the\n * oldest — matches the invinite reference's `computeAlma` loop.\n */\n readonly weights: Float64Array;\n readonly normaliser: number;\n /**\n * Lazy cache of `barShift`-tagged Series views keyed by\n * `opts.barShift`. `barShift === 0` callers bypass this map and\n * return `series` directly — identity-preserving. ALMA's `opts.offset`\n * is the Gaussian centre, NOT the universal shift, so it is never\n * tagged here; the bidirectional display shift lives on `barShift`.\n */\n readonly shiftedViews: Map<number, Series<number>>;\n};\n\nfunction getCtx(): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(\"ta.alma called outside an active script step\");\n }\n return ctx;\n}\n\nfunction initSlot(length: number, offsetCentre: number, sigma: number, capacity: number): AlmaSlot {\n const outBuffer = new Float64RingBuffer(capacity);\n const m = offsetCentre * (length - 1);\n const s = length / sigma;\n const weights = new Float64Array(length);\n let normaliser = 0;\n for (let j = 0; j < length; j += 1) {\n const d = j - m;\n const w = Math.exp(-(d * d) / (2 * s * s));\n weights[j] = w;\n normaliser += w;\n }\n return {\n outBuffer,\n series: makeSeriesView<number>(outBuffer),\n length,\n sourceWindow: new Float64RingBuffer(length),\n weights,\n normaliser,\n shiftedViews: new Map(),\n };\n}\n\nfunction viewForOffset(slot: AlmaSlot, barShift: number): Series<number> {\n if (barShift === 0) return slot.series;\n let view = slot.shiftedViews.get(barShift);\n if (view === undefined) {\n view = makeShiftedSeriesView<number>(slot.outBuffer, barShift);\n slot.shiftedViews.set(barShift, view);\n }\n return view;\n}\n\nfunction weightedFromWindow(slot: AlmaSlot, headOverride?: number): number {\n let sum = 0;\n for (let j = 0; j < slot.length; j += 1) {\n // j = 0 → oldest (window.at(length - 1)); j = length - 1 → head.\n const ageFromHead = slot.length - 1 - j;\n const v =\n ageFromHead === 0 && headOverride !== undefined\n ? headOverride\n : slot.sourceWindow.at(ageFromHead);\n if (!Number.isFinite(v)) return Number.NaN;\n sum += v * slot.weights[j];\n }\n return sum / slot.normaliser;\n}\n\nfunction closeValue(slot: AlmaSlot, src: number): number {\n slot.sourceWindow.append(src);\n if (slot.sourceWindow.length < slot.length) return Number.NaN;\n return weightedFromWindow(slot);\n}\n\nfunction tickValue(slot: AlmaSlot, src: number): number {\n if (slot.sourceWindow.length < slot.length) return Number.NaN;\n if (!Number.isFinite(src)) return Number.NaN;\n return weightedFromWindow(slot, src);\n}\n\n/**\n * Arnaud Legoux Moving Average — a Gaussian-weighted MA. Weights peak\n * at `offset · (length − 1)` (default `0.85 · (length − 1)`, near the\n * recent end of the window) and decay with standard deviation\n * `length / sigma` (default `length / 6`). Weights are pre-computed\n * once at slot init from `opts.offset` + `opts.sigma`; per-bar cost is\n * an O(length) window walk. A NaN anywhere in the window\n * short-circuits the output to NaN (matches the WMA full-recompute\n * weighted-window convention).\n *\n * **`opts.offset` is the Gaussian-centre position in `[0, 1]`**, NOT\n * the universal bar-shift. ALMA's universal shift lives on the distinct\n * `opts.barShift` field: a presentation display shift (`+n` renders the\n * series `n` bars right / future, `−n` `n` bars left / past) carried to\n * the plot emission as `xShift`. It does not transform the series value —\n * `series.current` is unshifted, matching every other primitive's\n * `opts.offset`.\n *\n * @formula m = offset · (length − 1) ;\n * s = length / sigma ;\n * w[j] = exp(−((j − m)² / (2 · s²))) for j = 0..length − 1 ;\n * norm = Σ w[j] ;\n * out[t] = (Σ_{j=0..length-1} w[j] · src[t − length + 1 + j]) / norm\n * @warmup length − 1\n * @anchors offset, sigma\n * @since 0.2\n * @stable\n *\n * @example\n * // import { ta } from \"@invinite-org/chartlang-core\";\n * // const a = ta.alma(bar.close, 9, { offset: 0.85, sigma: 6 });\n * // plot(a);\n */\nexport function alma(\n slotId: string,\n source: ScalarOrSeries,\n length: number,\n opts?: AlmaOpts,\n): Series<number> {\n const ctx = getCtx();\n let slot = ctx.stream.taSlots.get(slotId) as AlmaSlot | undefined;\n if (slot === undefined) {\n slot = initSlot(\n length,\n opts?.offset ?? DEFAULT_OFFSET,\n opts?.sigma ?? DEFAULT_SIGMA,\n ctx.stream.ohlcv.close.capacity,\n );\n ctx.stream.taSlots.set(slotId, slot);\n }\n const src = readSourceValue(source);\n if (ctx.isTick) {\n slot.outBuffer.replaceHead(tickValue(slot, src));\n } else {\n slot.outBuffer.append(closeValue(slot, src));\n }\n return viewForOffset(slot, opts?.barShift ?? 0);\n}\n"]}
package/dist/ta/atr.d.ts CHANGED
@@ -12,8 +12,9 @@ import type { AtrOpts, Series } from "@invinite-org/chartlang-core";
12
12
  * @since 0.1
13
13
  * @stable
14
14
  *
15
- * `opts.offset` shifts the returned series so `series.current` reads
16
- * the value `offset` bars ago.
15
+ * `opts.offset` is a presentation display shift carried to the plot
16
+ * emission as `xShift` (`+n` right / future, `−n` left / past); the
17
+ * series value is unshifted.
17
18
  *
18
19
  * @example
19
20
  * // import { ta } from "@invinite-org/chartlang-runtime";
@@ -1 +1 @@
1
- {"version":3,"file":"atr.d.ts","sourceRoot":"","sources":["../../src/ta/atr.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAyGpE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAclF"}
1
+ {"version":3,"file":"atr.d.ts","sourceRoot":"","sources":["../../src/ta/atr.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAyGpE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAclF"}
package/dist/ta/atr.js CHANGED
@@ -104,8 +104,9 @@ function tickValue(slot, high, low, close) {
104
104
  * @since 0.1
105
105
  * @stable
106
106
  *
107
- * `opts.offset` shifts the returned series so `series.current` reads
108
- * the value `offset` bars ago.
107
+ * `opts.offset` is a presentation display shift carried to the plot
108
+ * emission as `xShift` (`+n` right / future, `−n` left / past); the
109
+ * series value is unshifted.
109
110
  *
110
111
  * @example
111
112
  * // import { ta } from "@invinite-org/chartlang-runtime";
@@ -1 +1 @@
1
- {"version":3,"file":"atr.js","sourceRoot":"","sources":["../../src/ta/atr.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// Ported from invinite/src/components/trading-chart/indicators/atr.ts\n// plus lib/tr-series.ts\n// (commit d2d1043c1b039f66d2f3674526d303d31cf2f1e0, © Invinite).\n// Re-licensed MIT for chartlang. The math is the reference, the code\n// style is not.\n// Structural choices (callsite-id slot, Series<T> proxy, replaceHead\n// mode) follow chartlang's primitive shape — NOT invinite's\n// IndicatorPlugin shape. ATR derives from `bar.high`/`bar.low`/\n// `bar.close` directly — no `source` argument per Pine.\n\nimport type { AtrOpts, Series } from \"@invinite-org/chartlang-core\";\n\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeSeriesView, makeShiftedSeriesView } from \"../seriesView.js\";\nimport { wilderStep } from \"./lib/wilderSmoothing.js\";\n\ntype AtrSlot = {\n readonly outBuffer: Float64RingBuffer;\n readonly series: Series<number>;\n readonly length: number;\n seedTrSum: number;\n /** Number of TR values folded into the seed so far. */\n trCount: number;\n atr: number;\n /** Close of the prior closed bar — used to compute TR on the next close. */\n prevClose: number;\n /** Close of the bar before the current bar (i.e. the close 2 bars ago). */\n prevPrevClose: number;\n /** ATR as of the prior closed bar — used by tick-mode replay. */\n prevClosedAtr: number;\n /** Per-offset Series-view cache; see `sma.ts` for the convention. */\n readonly shiftedViews: Map<number, Series<number>>;\n};\n\nfunction getCtx(): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(\"ta.atr called outside an active script step\");\n }\n return ctx;\n}\n\nfunction initSlot(length: number, capacity: number): AtrSlot {\n const outBuffer = new Float64RingBuffer(capacity);\n return {\n outBuffer,\n series: makeSeriesView<number>(outBuffer),\n length,\n seedTrSum: 0,\n trCount: 0,\n atr: Number.NaN,\n prevClose: Number.NaN,\n prevPrevClose: Number.NaN,\n prevClosedAtr: Number.NaN,\n shiftedViews: new Map(),\n };\n}\n\nfunction viewForOffset(slot: AtrSlot, offset: number): Series<number> {\n if (offset === 0) return slot.series;\n let view = slot.shiftedViews.get(offset);\n if (view === undefined) {\n view = makeShiftedSeriesView<number>(slot.outBuffer, offset);\n slot.shiftedViews.set(offset, view);\n }\n return view;\n}\n\nfunction trueRange(high: number, low: number, prevClose: number): number {\n if (!Number.isFinite(prevClose)) return high - low;\n return Math.max(high - low, Math.abs(high - prevClose), Math.abs(low - prevClose));\n}\n\nfunction closeValue(slot: AtrSlot, high: number, low: number, close: number): number {\n if (!Number.isFinite(high) || !Number.isFinite(low) || !Number.isFinite(close)) {\n if (Number.isFinite(slot.atr)) return slot.atr;\n return Number.NaN;\n }\n const tr = trueRange(high, low, slot.prevClose);\n slot.prevPrevClose = slot.prevClose;\n slot.prevClose = close;\n slot.trCount += 1;\n\n if (slot.trCount < slot.length) {\n slot.seedTrSum += tr;\n return Number.NaN;\n }\n if (slot.trCount === slot.length) {\n slot.seedTrSum += tr;\n slot.atr = slot.seedTrSum / slot.length;\n slot.prevClosedAtr = slot.atr;\n return slot.atr;\n }\n slot.prevClosedAtr = slot.atr;\n slot.atr = wilderStep(slot.atr, tr, slot.length);\n return slot.atr;\n}\n\nfunction tickValue(slot: AtrSlot, high: number, low: number, close: number): number {\n if (!Number.isFinite(high) || !Number.isFinite(low) || !Number.isFinite(close)) {\n return Number.isFinite(slot.atr) ? slot.atr : Number.NaN;\n }\n if (slot.trCount < slot.length) return Number.NaN;\n // Tick TR uses the **bar before the current bar**'s close — frozen\n // by the prior close-side advance as `prevPrevClose`.\n const tr = trueRange(high, low, slot.prevPrevClose);\n if (slot.trCount === slot.length) {\n // We just seeded on the current close; tick replays the same seed\n // (the seed window is fixed once the bar closes).\n return slot.atr;\n }\n return wilderStep(slot.prevClosedAtr, tr, slot.length);\n}\n\n/**\n * Wilder's Average True Range. Sources from `bar.high` / `bar.low` /\n * `bar.close` directly (no `source` arg — matches Pine). Seeds at bar\n * `length − 1` as the simple mean of the first `length` TR values;\n * subsequent slots use the Wilder recurrence with α = 1/length.\n *\n * @formula TR[t] = max(high − low, |high − prevClose|, |low − prevClose|) ;\n * seed at bar length − 1 = mean(TR[0 .. length − 1]) ;\n * ATR[t] = (ATR[t − 1] · (length − 1) + TR[t]) / length\n * @warmup length − 1\n * @since 0.1\n * @stable\n *\n * `opts.offset` shifts the returned series so `series.current` reads\n * the value `offset` bars ago.\n *\n * @example\n * // import { ta } from \"@invinite-org/chartlang-runtime\";\n * // const a = ta.atr(\"slot\", 14);\n * // const head = a.current;\n * // const lagged = ta.atr(\"slot2\", 14, { offset: 5 });\n */\nexport function atr(slotId: string, length: number, opts?: AtrOpts): Series<number> {\n const ctx = getCtx();\n let slot = ctx.stream.taSlots.get(slotId) as AtrSlot | undefined;\n if (slot === undefined) {\n slot = initSlot(length, ctx.stream.ohlcv.close.capacity);\n ctx.stream.taSlots.set(slotId, slot);\n }\n const bar = ctx.stream.bar;\n if (ctx.isTick) {\n slot.outBuffer.replaceHead(tickValue(slot, bar.high, bar.low, bar.close));\n } else {\n slot.outBuffer.append(closeValue(slot, bar.high, bar.low, bar.close));\n }\n return viewForOffset(slot, opts?.offset ?? 0);\n}\n"]}
1
+ {"version":3,"file":"atr.js","sourceRoot":"","sources":["../../src/ta/atr.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// Ported from invinite/src/components/trading-chart/indicators/atr.ts\n// plus lib/tr-series.ts\n// (commit d2d1043c1b039f66d2f3674526d303d31cf2f1e0, © Invinite).\n// Re-licensed MIT for chartlang. The math is the reference, the code\n// style is not.\n// Structural choices (callsite-id slot, Series<T> proxy, replaceHead\n// mode) follow chartlang's primitive shape — NOT invinite's\n// IndicatorPlugin shape. ATR derives from `bar.high`/`bar.low`/\n// `bar.close` directly — no `source` argument per Pine.\n\nimport type { AtrOpts, Series } from \"@invinite-org/chartlang-core\";\n\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeSeriesView, makeShiftedSeriesView } from \"../seriesView.js\";\nimport { wilderStep } from \"./lib/wilderSmoothing.js\";\n\ntype AtrSlot = {\n readonly outBuffer: Float64RingBuffer;\n readonly series: Series<number>;\n readonly length: number;\n seedTrSum: number;\n /** Number of TR values folded into the seed so far. */\n trCount: number;\n atr: number;\n /** Close of the prior closed bar — used to compute TR on the next close. */\n prevClose: number;\n /** Close of the bar before the current bar (i.e. the close 2 bars ago). */\n prevPrevClose: number;\n /** ATR as of the prior closed bar — used by tick-mode replay. */\n prevClosedAtr: number;\n /** Per-offset Series-view cache; see `sma.ts` for the convention. */\n readonly shiftedViews: Map<number, Series<number>>;\n};\n\nfunction getCtx(): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(\"ta.atr called outside an active script step\");\n }\n return ctx;\n}\n\nfunction initSlot(length: number, capacity: number): AtrSlot {\n const outBuffer = new Float64RingBuffer(capacity);\n return {\n outBuffer,\n series: makeSeriesView<number>(outBuffer),\n length,\n seedTrSum: 0,\n trCount: 0,\n atr: Number.NaN,\n prevClose: Number.NaN,\n prevPrevClose: Number.NaN,\n prevClosedAtr: Number.NaN,\n shiftedViews: new Map(),\n };\n}\n\nfunction viewForOffset(slot: AtrSlot, offset: number): Series<number> {\n if (offset === 0) return slot.series;\n let view = slot.shiftedViews.get(offset);\n if (view === undefined) {\n view = makeShiftedSeriesView<number>(slot.outBuffer, offset);\n slot.shiftedViews.set(offset, view);\n }\n return view;\n}\n\nfunction trueRange(high: number, low: number, prevClose: number): number {\n if (!Number.isFinite(prevClose)) return high - low;\n return Math.max(high - low, Math.abs(high - prevClose), Math.abs(low - prevClose));\n}\n\nfunction closeValue(slot: AtrSlot, high: number, low: number, close: number): number {\n if (!Number.isFinite(high) || !Number.isFinite(low) || !Number.isFinite(close)) {\n if (Number.isFinite(slot.atr)) return slot.atr;\n return Number.NaN;\n }\n const tr = trueRange(high, low, slot.prevClose);\n slot.prevPrevClose = slot.prevClose;\n slot.prevClose = close;\n slot.trCount += 1;\n\n if (slot.trCount < slot.length) {\n slot.seedTrSum += tr;\n return Number.NaN;\n }\n if (slot.trCount === slot.length) {\n slot.seedTrSum += tr;\n slot.atr = slot.seedTrSum / slot.length;\n slot.prevClosedAtr = slot.atr;\n return slot.atr;\n }\n slot.prevClosedAtr = slot.atr;\n slot.atr = wilderStep(slot.atr, tr, slot.length);\n return slot.atr;\n}\n\nfunction tickValue(slot: AtrSlot, high: number, low: number, close: number): number {\n if (!Number.isFinite(high) || !Number.isFinite(low) || !Number.isFinite(close)) {\n return Number.isFinite(slot.atr) ? slot.atr : Number.NaN;\n }\n if (slot.trCount < slot.length) return Number.NaN;\n // Tick TR uses the **bar before the current bar**'s close — frozen\n // by the prior close-side advance as `prevPrevClose`.\n const tr = trueRange(high, low, slot.prevPrevClose);\n if (slot.trCount === slot.length) {\n // We just seeded on the current close; tick replays the same seed\n // (the seed window is fixed once the bar closes).\n return slot.atr;\n }\n return wilderStep(slot.prevClosedAtr, tr, slot.length);\n}\n\n/**\n * Wilder's Average True Range. Sources from `bar.high` / `bar.low` /\n * `bar.close` directly (no `source` arg — matches Pine). Seeds at bar\n * `length − 1` as the simple mean of the first `length` TR values;\n * subsequent slots use the Wilder recurrence with α = 1/length.\n *\n * @formula TR[t] = max(high − low, |high − prevClose|, |low − prevClose|) ;\n * seed at bar length − 1 = mean(TR[0 .. length − 1]) ;\n * ATR[t] = (ATR[t − 1] · (length − 1) + TR[t]) / length\n * @warmup length − 1\n * @since 0.1\n * @stable\n *\n * `opts.offset` is a presentation display shift carried to the plot\n * emission as `xShift` (`+n` right / future, `−n` left / past); the\n * series value is unshifted.\n *\n * @example\n * // import { ta } from \"@invinite-org/chartlang-runtime\";\n * // const a = ta.atr(\"slot\", 14);\n * // const head = a.current;\n * // const lagged = ta.atr(\"slot2\", 14, { offset: 5 });\n */\nexport function atr(slotId: string, length: number, opts?: AtrOpts): Series<number> {\n const ctx = getCtx();\n let slot = ctx.stream.taSlots.get(slotId) as AtrSlot | undefined;\n if (slot === undefined) {\n slot = initSlot(length, ctx.stream.ohlcv.close.capacity);\n ctx.stream.taSlots.set(slotId, slot);\n }\n const bar = ctx.stream.bar;\n if (ctx.isTick) {\n slot.outBuffer.replaceHead(tickValue(slot, bar.high, bar.low, bar.close));\n } else {\n slot.outBuffer.append(closeValue(slot, bar.high, bar.low, bar.close));\n }\n return viewForOffset(slot, opts?.offset ?? 0);\n}\n"]}
package/dist/ta/bb.d.ts CHANGED
@@ -15,8 +15,9 @@ import { type ScalarOrSeries } from "./lib/sourceValue.js";
15
15
  * @since 0.1
16
16
  * @stable
17
17
  *
18
- * `opts.offset` shifts all three bands in lockstep
19
- * `series.current` on each band returns the value `offset` bars ago.
18
+ * `opts.offset` is a presentation display shift carried to the plot
19
+ * emission as `xShift` for all three bands in lockstep (`+n` right / future,
20
+ * `−n` left / past); the series values are unshifted.
20
21
  *
21
22
  * @example
22
23
  * // import { ta } from "@invinite-org/chartlang-runtime";
@@ -1 +1 @@
1
- {"version":3,"file":"bb.d.ts","sourceRoot":"","sources":["../../src/ta/bb.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAU,MAAM,8BAA8B,CAAC;AAM7E,OAAO,EAAE,KAAK,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AA8D5E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,EAAE,CACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACd,QAAQ,CA4CV"}
1
+ {"version":3,"file":"bb.d.ts","sourceRoot":"","sources":["../../src/ta/bb.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAU,MAAM,8BAA8B,CAAC;AAM7E,OAAO,EAAE,KAAK,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AA8D5E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,EAAE,CACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,MAAM,GACd,QAAQ,CA4CV"}
package/dist/ta/bb.js CHANGED
@@ -66,8 +66,9 @@ function resultForOffset(slot, offset) {
66
66
  * @since 0.1
67
67
  * @stable
68
68
  *
69
- * `opts.offset` shifts all three bands in lockstep
70
- * `series.current` on each band returns the value `offset` bars ago.
69
+ * `opts.offset` is a presentation display shift carried to the plot
70
+ * emission as `xShift` for all three bands in lockstep (`+n` right / future,
71
+ * `−n` left / past); the series values are unshifted.
71
72
  *
72
73
  * @example
73
74
  * // import { ta } from "@invinite-org/chartlang-runtime";
package/dist/ta/bb.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bb.js","sourceRoot":"","sources":["../../src/ta/bb.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// Ported from invinite/src/components/trading-chart/indicators/bb.ts\n// (commit d2d1043c1b039f66d2f3674526d303d31cf2f1e0, © Invinite).\n// Re-licensed MIT for chartlang. The math is the reference, the code\n// style is not.\n// Structural choices (callsite-id slot, Series<T> proxy, replaceHead\n// mode) follow chartlang's primitive shape — NOT invinite's\n// IndicatorPlugin shape. BB is composed from `sma` + `stdev` via\n// sub-slot ids so a fix to either primitive flows in for free.\n\nimport type { BbOpts, BbResult, Series } from \"@invinite-org/chartlang-core\";\n\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeSeriesView, makeShiftedSeriesView } from \"../seriesView.js\";\nimport { sma } from \"./sma.js\";\nimport { type ScalarOrSeries, readSourceValue } from \"./lib/sourceValue.js\";\nimport { stdev } from \"./stdev.js\";\n\nconst DEFAULT_MULTIPLIER = 2;\n\ntype BbSlot = {\n readonly result: BbResult;\n readonly upper: Float64RingBuffer;\n readonly middle: Series<number>;\n readonly lower: Float64RingBuffer;\n /**\n * Reference to the SMA sub-slot's output ring buffer. Captured at\n * first call so per-offset shifted middle views can be constructed\n * without re-entering `sma()` (which would double-advance the\n * sub-slot's compute on every bar).\n */\n readonly middleBuf: Float64RingBuffer;\n /**\n * Per-offset frozen `BbResult` cache. `offset === 0` returns\n * `result` directly (identity-preserving). Each cached result\n * proxies the same three underlying buffers via shifted views.\n */\n readonly shiftedResults: Map<number, BbResult>;\n};\n\nfunction getCtx(): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(\"ta.bb called outside an active script step\");\n }\n return ctx;\n}\n\nfunction initSlot(capacity: number, middle: Series<number>, middleBuf: Float64RingBuffer): BbSlot {\n const upper = new Float64RingBuffer(capacity);\n const lower = new Float64RingBuffer(capacity);\n const upperView = makeSeriesView<number>(upper);\n const lowerView = makeSeriesView<number>(lower);\n return {\n result: Object.freeze({ upper: upperView, middle, lower: lowerView }),\n upper,\n middle,\n lower,\n middleBuf,\n shiftedResults: new Map(),\n };\n}\n\nfunction resultForOffset(slot: BbSlot, offset: number): BbResult {\n if (offset === 0) return slot.result;\n let cached = slot.shiftedResults.get(offset);\n if (cached === undefined) {\n cached = Object.freeze({\n upper: makeShiftedSeriesView<number>(slot.upper, offset),\n middle: makeShiftedSeriesView<number>(slot.middleBuf, offset),\n lower: makeShiftedSeriesView<number>(slot.lower, offset),\n });\n slot.shiftedResults.set(offset, cached);\n }\n return cached;\n}\n\n/**\n * Bollinger Bands — `multiplier × σ` envelope around an SMA(length)\n * middle band. Default `multiplier = 2` per Pine. Returns a cached\n * `{ upper, middle, lower }` record (same identity every bar) backed\n * by three `Series<number>` Proxies. The middle band is the\n * underlying SMA primitive's output (identity-shared).\n *\n * @formula middle = sma(source, length) ;\n * σ = stdev(source, length, { biased: true }) ;\n * upper = middle + multiplier · σ ;\n * lower = middle − multiplier · σ\n * @warmup length − 1\n * @since 0.1\n * @stable\n *\n * `opts.offset` shifts all three bands in lockstep —\n * `series.current` on each band returns the value `offset` bars ago.\n *\n * @example\n * // import { ta } from \"@invinite-org/chartlang-runtime\";\n * // const bands = ta.bb(\"slot\", bar.close, 20, { multiplier: 2 });\n * // const u = bands.upper.current;\n * // const lagged = ta.bb(\"slot2\", bar.close, 20, { offset: 5 });\n */\nexport function bb(\n slotId: string,\n source: ScalarOrSeries,\n length: number,\n opts?: BbOpts,\n): BbResult {\n const ctx = getCtx();\n const multiplier = opts?.multiplier ?? DEFAULT_MULTIPLIER;\n const src = readSourceValue(source);\n const middleSlotId = `${slotId}/sma`;\n const stdevSlotId = `${slotId}/stdev`;\n // Compose: sma updates the middle band; stdev updates a separate\n // rolling-sigma series. Both primitives respect ctx.isTick. The\n // un-shifted middle (no offset) drives the per-bar math; the\n // shifted middle for non-zero offset is composed lazily in\n // `resultForOffset` to keep the close-path tight.\n const middleSeries = sma(middleSlotId, src, length);\n // BB's invinite math uses population sigma (denominator length); we\n // pass `biased: true` so the helper matches.\n const sigmaSeries = stdev(stdevSlotId, src, length, { biased: true });\n\n let slot = ctx.stream.taSlots.get(slotId) as BbSlot | undefined;\n if (slot === undefined) {\n // Capture the SMA sub-slot's output ring buffer so future\n // shifted-view lookups don't need to re-enter `sma()`.\n const smaSlot = ctx.stream.taSlots.get(middleSlotId) as { outBuffer: Float64RingBuffer };\n slot = initSlot(ctx.stream.ohlcv.close.capacity, middleSeries, smaSlot.outBuffer);\n ctx.stream.taSlots.set(slotId, slot);\n }\n\n const mid = middleSeries.current;\n const sigma = sigmaSeries.current;\n let upperValue: number;\n let lowerValue: number;\n if (Number.isFinite(mid) && Number.isFinite(sigma)) {\n upperValue = mid + multiplier * sigma;\n lowerValue = mid - multiplier * sigma;\n } else {\n upperValue = Number.NaN;\n lowerValue = Number.NaN;\n }\n if (ctx.isTick) {\n slot.upper.replaceHead(upperValue);\n slot.lower.replaceHead(lowerValue);\n } else {\n slot.upper.append(upperValue);\n slot.lower.append(lowerValue);\n }\n return resultForOffset(slot, opts?.offset ?? 0);\n}\n"]}
1
+ {"version":3,"file":"bb.js","sourceRoot":"","sources":["../../src/ta/bb.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// Ported from invinite/src/components/trading-chart/indicators/bb.ts\n// (commit d2d1043c1b039f66d2f3674526d303d31cf2f1e0, © Invinite).\n// Re-licensed MIT for chartlang. The math is the reference, the code\n// style is not.\n// Structural choices (callsite-id slot, Series<T> proxy, replaceHead\n// mode) follow chartlang's primitive shape — NOT invinite's\n// IndicatorPlugin shape. BB is composed from `sma` + `stdev` via\n// sub-slot ids so a fix to either primitive flows in for free.\n\nimport type { BbOpts, BbResult, Series } from \"@invinite-org/chartlang-core\";\n\nimport { Float64RingBuffer } from \"../ringBuffer.js\";\nimport { ACTIVE_RUNTIME_CONTEXT, type RuntimeContext } from \"../runtimeContext.js\";\nimport { makeSeriesView, makeShiftedSeriesView } from \"../seriesView.js\";\nimport { sma } from \"./sma.js\";\nimport { type ScalarOrSeries, readSourceValue } from \"./lib/sourceValue.js\";\nimport { stdev } from \"./stdev.js\";\n\nconst DEFAULT_MULTIPLIER = 2;\n\ntype BbSlot = {\n readonly result: BbResult;\n readonly upper: Float64RingBuffer;\n readonly middle: Series<number>;\n readonly lower: Float64RingBuffer;\n /**\n * Reference to the SMA sub-slot's output ring buffer. Captured at\n * first call so per-offset shifted middle views can be constructed\n * without re-entering `sma()` (which would double-advance the\n * sub-slot's compute on every bar).\n */\n readonly middleBuf: Float64RingBuffer;\n /**\n * Per-offset frozen `BbResult` cache. `offset === 0` returns\n * `result` directly (identity-preserving). Each cached result\n * proxies the same three underlying buffers via shifted views.\n */\n readonly shiftedResults: Map<number, BbResult>;\n};\n\nfunction getCtx(): RuntimeContext {\n const ctx = ACTIVE_RUNTIME_CONTEXT.current;\n if (ctx === null) {\n throw new Error(\"ta.bb called outside an active script step\");\n }\n return ctx;\n}\n\nfunction initSlot(capacity: number, middle: Series<number>, middleBuf: Float64RingBuffer): BbSlot {\n const upper = new Float64RingBuffer(capacity);\n const lower = new Float64RingBuffer(capacity);\n const upperView = makeSeriesView<number>(upper);\n const lowerView = makeSeriesView<number>(lower);\n return {\n result: Object.freeze({ upper: upperView, middle, lower: lowerView }),\n upper,\n middle,\n lower,\n middleBuf,\n shiftedResults: new Map(),\n };\n}\n\nfunction resultForOffset(slot: BbSlot, offset: number): BbResult {\n if (offset === 0) return slot.result;\n let cached = slot.shiftedResults.get(offset);\n if (cached === undefined) {\n cached = Object.freeze({\n upper: makeShiftedSeriesView<number>(slot.upper, offset),\n middle: makeShiftedSeriesView<number>(slot.middleBuf, offset),\n lower: makeShiftedSeriesView<number>(slot.lower, offset),\n });\n slot.shiftedResults.set(offset, cached);\n }\n return cached;\n}\n\n/**\n * Bollinger Bands — `multiplier × σ` envelope around an SMA(length)\n * middle band. Default `multiplier = 2` per Pine. Returns a cached\n * `{ upper, middle, lower }` record (same identity every bar) backed\n * by three `Series<number>` Proxies. The middle band is the\n * underlying SMA primitive's output (identity-shared).\n *\n * @formula middle = sma(source, length) ;\n * σ = stdev(source, length, { biased: true }) ;\n * upper = middle + multiplier · σ ;\n * lower = middle − multiplier · σ\n * @warmup length − 1\n * @since 0.1\n * @stable\n *\n * `opts.offset` is a presentation display shift carried to the plot\n * emission as `xShift` for all three bands in lockstep (`+n` right / future,\n * `−n` left / past); the series values are unshifted.\n *\n * @example\n * // import { ta } from \"@invinite-org/chartlang-runtime\";\n * // const bands = ta.bb(\"slot\", bar.close, 20, { multiplier: 2 });\n * // const u = bands.upper.current;\n * // const lagged = ta.bb(\"slot2\", bar.close, 20, { offset: 5 });\n */\nexport function bb(\n slotId: string,\n source: ScalarOrSeries,\n length: number,\n opts?: BbOpts,\n): BbResult {\n const ctx = getCtx();\n const multiplier = opts?.multiplier ?? DEFAULT_MULTIPLIER;\n const src = readSourceValue(source);\n const middleSlotId = `${slotId}/sma`;\n const stdevSlotId = `${slotId}/stdev`;\n // Compose: sma updates the middle band; stdev updates a separate\n // rolling-sigma series. Both primitives respect ctx.isTick. The\n // un-shifted middle (no offset) drives the per-bar math; the\n // shifted middle for non-zero offset is composed lazily in\n // `resultForOffset` to keep the close-path tight.\n const middleSeries = sma(middleSlotId, src, length);\n // BB's invinite math uses population sigma (denominator length); we\n // pass `biased: true` so the helper matches.\n const sigmaSeries = stdev(stdevSlotId, src, length, { biased: true });\n\n let slot = ctx.stream.taSlots.get(slotId) as BbSlot | undefined;\n if (slot === undefined) {\n // Capture the SMA sub-slot's output ring buffer so future\n // shifted-view lookups don't need to re-enter `sma()`.\n const smaSlot = ctx.stream.taSlots.get(middleSlotId) as { outBuffer: Float64RingBuffer };\n slot = initSlot(ctx.stream.ohlcv.close.capacity, middleSeries, smaSlot.outBuffer);\n ctx.stream.taSlots.set(slotId, slot);\n }\n\n const mid = middleSeries.current;\n const sigma = sigmaSeries.current;\n let upperValue: number;\n let lowerValue: number;\n if (Number.isFinite(mid) && Number.isFinite(sigma)) {\n upperValue = mid + multiplier * sigma;\n lowerValue = mid - multiplier * sigma;\n } else {\n upperValue = Number.NaN;\n lowerValue = Number.NaN;\n }\n if (ctx.isTick) {\n slot.upper.replaceHead(upperValue);\n slot.lower.replaceHead(lowerValue);\n } else {\n slot.upper.append(upperValue);\n slot.lower.append(lowerValue);\n }\n return resultForOffset(slot, opts?.offset ?? 0);\n}\n"]}
@@ -21,8 +21,9 @@ import type { ChaikinOscOpts, Series } from "@invinite-org/chartlang-core";
21
21
  * @since 0.2
22
22
  * @stable
23
23
  *
24
- * `opts.offset` shifts the returned series so `series.current` reads
25
- * the value `offset` bars ago.
24
+ * `opts.offset` is a presentation display shift carried to the plot
25
+ * emission as `xShift` (`+n` right / future, `−n` left / past); the
26
+ * series value is unshifted.
26
27
  *
27
28
  * @example
28
29
  * // import { ta, plot } from "@invinite-org/chartlang-core";
@@ -1 +1 @@
1
- {"version":3,"file":"chaikinOsc.d.ts","sourceRoot":"","sources":["../../src/ta/chaikinOsc.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAiD3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,CAmBhF"}
1
+ {"version":3,"file":"chaikinOsc.d.ts","sourceRoot":"","sources":["../../src/ta/chaikinOsc.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAiD3E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,CAmBhF"}
@@ -69,8 +69,9 @@ function diff(fast, slow) {
69
69
  * @since 0.2
70
70
  * @stable
71
71
  *
72
- * `opts.offset` shifts the returned series so `series.current` reads
73
- * the value `offset` bars ago.
72
+ * `opts.offset` is a presentation display shift carried to the plot
73
+ * emission as `xShift` (`+n` right / future, `−n` left / past); the
74
+ * series value is unshifted.
74
75
  *
75
76
  * @example
76
77
  * // import { ta, plot } from "@invinite-org/chartlang-core";