oakscriptjs 0.8.2 → 0.9.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 (546) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +31 -9
  3. package/dist/cjs/array/index.d.ts +701 -0
  4. package/dist/cjs/array/index.d.ts.map +1 -0
  5. package/dist/cjs/array/index.js +392 -0
  6. package/dist/cjs/array/index.js.map +7 -0
  7. package/dist/cjs/box/index.d.ts +444 -0
  8. package/dist/cjs/box/index.d.ts.map +1 -0
  9. package/dist/cjs/box/index.js +246 -0
  10. package/dist/cjs/box/index.js.map +7 -0
  11. package/dist/cjs/callsite/index.d.ts +61 -0
  12. package/dist/cjs/callsite/index.d.ts.map +1 -0
  13. package/dist/cjs/callsite/index.js +65 -0
  14. package/dist/cjs/callsite/index.js.map +7 -0
  15. package/dist/cjs/chartpoint/index.d.ts +90 -0
  16. package/dist/cjs/chartpoint/index.d.ts.map +1 -0
  17. package/dist/cjs/chartpoint/index.js +56 -0
  18. package/dist/cjs/chartpoint/index.js.map +7 -0
  19. package/dist/cjs/color/index.d.ts +285 -0
  20. package/dist/cjs/color/index.d.ts.map +1 -0
  21. package/dist/cjs/color/index.js +143 -0
  22. package/dist/cjs/color/index.js.map +7 -0
  23. package/dist/cjs/compare/index.d.ts +26 -0
  24. package/dist/cjs/compare/index.d.ts.map +1 -0
  25. package/dist/cjs/compare/index.js +50 -0
  26. package/dist/cjs/compare/index.js.map +7 -0
  27. package/dist/cjs/drawing/registry.d.ts +42 -0
  28. package/dist/cjs/drawing/registry.d.ts.map +1 -0
  29. package/dist/cjs/drawing/registry.js +87 -0
  30. package/dist/cjs/drawing/registry.js.map +7 -0
  31. package/dist/cjs/index.d.ts +85 -0
  32. package/dist/cjs/index.d.ts.map +1 -0
  33. package/dist/cjs/index.js +184 -0
  34. package/dist/cjs/index.js.map +7 -0
  35. package/dist/cjs/indicator.d.ts +117 -0
  36. package/dist/cjs/indicator.d.ts.map +1 -0
  37. package/dist/cjs/indicator.js +74 -0
  38. package/dist/cjs/indicator.js.map +7 -0
  39. package/dist/cjs/input.d.ts +196 -0
  40. package/dist/cjs/input.d.ts.map +1 -0
  41. package/dist/cjs/input.js +197 -0
  42. package/dist/cjs/input.js.map +7 -0
  43. package/dist/cjs/label/index.d.ts +303 -0
  44. package/dist/cjs/label/index.d.ts.map +1 -0
  45. package/dist/cjs/label/index.js +190 -0
  46. package/dist/cjs/label/index.js.map +7 -0
  47. package/dist/cjs/lib/index.d.ts +8 -0
  48. package/dist/cjs/lib/index.d.ts.map +1 -0
  49. package/dist/cjs/lib/index.js +19 -0
  50. package/dist/cjs/lib/index.js.map +7 -0
  51. package/dist/{lib → cjs/lib}/zigzag/index.d.ts +4 -1
  52. package/dist/cjs/lib/zigzag/index.d.ts.map +1 -0
  53. package/dist/cjs/lib/zigzag/index.js +27 -0
  54. package/dist/cjs/lib/zigzag/index.js.map +7 -0
  55. package/dist/cjs/lib/zigzag/zigzag.d.ts +100 -0
  56. package/dist/cjs/lib/zigzag/zigzag.d.ts.map +1 -0
  57. package/dist/cjs/lib/zigzag/zigzag.js +207 -0
  58. package/dist/cjs/lib/zigzag/zigzag.js.map +7 -0
  59. package/dist/cjs/line/index.d.ts +342 -0
  60. package/dist/cjs/line/index.d.ts.map +1 -0
  61. package/dist/cjs/line/index.js +193 -0
  62. package/dist/cjs/line/index.js.map +7 -0
  63. package/dist/cjs/linefill/index.d.ts +124 -0
  64. package/dist/cjs/linefill/index.d.ts.map +1 -0
  65. package/dist/cjs/linefill/index.js +56 -0
  66. package/dist/cjs/linefill/index.js.map +7 -0
  67. package/dist/cjs/map/index.d.ts +69 -0
  68. package/dist/cjs/map/index.d.ts.map +1 -0
  69. package/dist/cjs/map/index.js +80 -0
  70. package/dist/cjs/map/index.js.map +7 -0
  71. package/dist/cjs/math/index.d.ts +560 -0
  72. package/dist/cjs/math/index.d.ts.map +1 -0
  73. package/dist/cjs/math/index.js +441 -0
  74. package/dist/cjs/math/index.js.map +7 -0
  75. package/dist/cjs/matrix/index.d.ts +1231 -0
  76. package/dist/cjs/matrix/index.d.ts.map +1 -0
  77. package/dist/cjs/matrix/index.js +1200 -0
  78. package/dist/cjs/matrix/index.js.map +7 -0
  79. package/dist/cjs/package.json +1 -0
  80. package/dist/cjs/plot.d.ts +76 -0
  81. package/dist/cjs/plot.d.ts.map +1 -0
  82. package/dist/cjs/plot.js +51 -0
  83. package/dist/cjs/plot.js.map +7 -0
  84. package/dist/cjs/polyline/index.d.ts +115 -0
  85. package/dist/cjs/polyline/index.d.ts.map +1 -0
  86. package/dist/cjs/polyline/index.js +76 -0
  87. package/dist/cjs/polyline/index.js.map +7 -0
  88. package/dist/cjs/runtime/adapters/LightweightChartsAdapter.d.ts +86 -0
  89. package/dist/cjs/runtime/adapters/LightweightChartsAdapter.d.ts.map +1 -0
  90. package/dist/cjs/runtime/adapters/LightweightChartsAdapter.js +141 -0
  91. package/dist/cjs/runtime/adapters/LightweightChartsAdapter.js.map +7 -0
  92. package/dist/cjs/runtime/adapters/SimpleInputAdapter.d.ts +59 -0
  93. package/dist/cjs/runtime/adapters/SimpleInputAdapter.d.ts.map +1 -0
  94. package/dist/cjs/runtime/adapters/SimpleInputAdapter.js +117 -0
  95. package/dist/cjs/runtime/adapters/SimpleInputAdapter.js.map +7 -0
  96. package/dist/{runtime → cjs/runtime}/index.d.ts +12 -5
  97. package/dist/cjs/runtime/index.d.ts.map +1 -0
  98. package/dist/cjs/runtime/index.js +49 -0
  99. package/dist/cjs/runtime/index.js.map +7 -0
  100. package/dist/cjs/runtime/inputs.d.ts +91 -0
  101. package/dist/cjs/runtime/inputs.d.ts.map +1 -0
  102. package/dist/cjs/runtime/inputs.js +262 -0
  103. package/dist/cjs/runtime/inputs.js.map +7 -0
  104. package/dist/cjs/runtime/runtime.d.ts +70 -0
  105. package/dist/cjs/runtime/runtime.d.ts.map +1 -0
  106. package/dist/cjs/runtime/runtime.js +148 -0
  107. package/dist/cjs/runtime/runtime.js.map +7 -0
  108. package/dist/cjs/runtime/series.d.ts +362 -0
  109. package/dist/cjs/runtime/series.d.ts.map +1 -0
  110. package/dist/cjs/runtime/series.js +560 -0
  111. package/dist/cjs/runtime/series.js.map +7 -0
  112. package/dist/cjs/runtime/types.d.ts +282 -0
  113. package/dist/cjs/runtime/types.d.ts.map +1 -0
  114. package/dist/cjs/runtime/types.js +17 -0
  115. package/dist/cjs/runtime/types.js.map +7 -0
  116. package/dist/cjs/script/index.d.ts +987 -0
  117. package/dist/cjs/script/index.d.ts.map +1 -0
  118. package/dist/cjs/script/index.js +1169 -0
  119. package/dist/cjs/script/index.js.map +7 -0
  120. package/dist/cjs/security/resample.d.ts +63 -0
  121. package/dist/cjs/security/resample.d.ts.map +1 -0
  122. package/dist/cjs/security/resample.js +84 -0
  123. package/dist/cjs/security/resample.js.map +7 -0
  124. package/dist/cjs/session/bars.d.ts +80 -0
  125. package/dist/cjs/session/bars.d.ts.map +1 -0
  126. package/dist/cjs/session/bars.js +219 -0
  127. package/dist/cjs/session/bars.js.map +7 -0
  128. package/dist/cjs/session/calendar.d.ts +70 -0
  129. package/dist/cjs/session/calendar.d.ts.map +1 -0
  130. package/dist/cjs/session/calendar.js +164 -0
  131. package/dist/cjs/session/calendar.js.map +7 -0
  132. package/dist/cjs/str/dateformat.d.ts +15 -0
  133. package/dist/cjs/str/dateformat.d.ts.map +1 -0
  134. package/dist/cjs/str/dateformat.js +149 -0
  135. package/dist/cjs/str/dateformat.js.map +7 -0
  136. package/dist/cjs/str/index.d.ts +459 -0
  137. package/dist/cjs/str/index.d.ts.map +1 -0
  138. package/dist/cjs/str/index.js +143 -0
  139. package/dist/cjs/str/index.js.map +7 -0
  140. package/dist/cjs/str/messageformat.d.ts +14 -0
  141. package/dist/cjs/str/messageformat.d.ts.map +1 -0
  142. package/dist/cjs/str/messageformat.js +114 -0
  143. package/dist/cjs/str/messageformat.js.map +7 -0
  144. package/dist/cjs/str/numberformat.d.ts +19 -0
  145. package/dist/cjs/str/numberformat.d.ts.map +1 -0
  146. package/dist/cjs/str/numberformat.js +170 -0
  147. package/dist/cjs/str/numberformat.js.map +7 -0
  148. package/dist/{strategy → cjs/strategy}/index.d.ts +50 -0
  149. package/dist/cjs/strategy/index.d.ts.map +1 -0
  150. package/dist/cjs/strategy/index.js +92 -0
  151. package/dist/cjs/strategy/index.js.map +7 -0
  152. package/dist/cjs/ta/index.d.ts +1397 -0
  153. package/dist/cjs/ta/index.d.ts.map +1 -0
  154. package/dist/cjs/ta/index.js +1715 -0
  155. package/dist/cjs/ta/index.js.map +7 -0
  156. package/dist/cjs/ta/running-sum.d.ts +30 -0
  157. package/dist/cjs/ta/running-sum.d.ts.map +1 -0
  158. package/dist/cjs/ta/running-sum.js +99 -0
  159. package/dist/cjs/ta/running-sum.js.map +7 -0
  160. package/dist/cjs/ta-series.d.ts +558 -0
  161. package/dist/cjs/ta-series.d.ts.map +1 -0
  162. package/dist/cjs/ta-series.js +606 -0
  163. package/dist/cjs/ta-series.js.map +7 -0
  164. package/dist/cjs/text/index.d.ts +14 -0
  165. package/dist/cjs/text/index.d.ts.map +1 -0
  166. package/dist/cjs/text/index.js +29 -0
  167. package/dist/cjs/text/index.js.map +7 -0
  168. package/dist/cjs/time/datestring.d.ts +23 -0
  169. package/dist/cjs/time/datestring.d.ts.map +1 -0
  170. package/dist/cjs/time/datestring.js +106 -0
  171. package/dist/cjs/time/datestring.js.map +7 -0
  172. package/dist/cjs/time/index.d.ts +89 -0
  173. package/dist/cjs/time/index.d.ts.map +1 -0
  174. package/dist/cjs/time/index.js +85 -0
  175. package/dist/cjs/time/index.js.map +7 -0
  176. package/dist/cjs/time/session.d.ts +17 -0
  177. package/dist/cjs/time/session.d.ts.map +1 -0
  178. package/dist/cjs/time/session.js +65 -0
  179. package/dist/cjs/time/session.js.map +7 -0
  180. package/dist/cjs/time/timezone.d.ts +40 -0
  181. package/dist/cjs/time/timezone.d.ts.map +1 -0
  182. package/dist/cjs/time/timezone.js +125 -0
  183. package/dist/cjs/time/timezone.js.map +7 -0
  184. package/dist/cjs/timeframe/index.d.ts +73 -0
  185. package/dist/cjs/timeframe/index.d.ts.map +1 -0
  186. package/dist/cjs/timeframe/index.js +85 -0
  187. package/dist/cjs/timeframe/index.js.map +7 -0
  188. package/dist/cjs/types/index.d.ts +343 -0
  189. package/dist/cjs/types/index.d.ts.map +1 -0
  190. package/dist/cjs/types/index.js +32 -0
  191. package/dist/cjs/types/index.js.map +7 -0
  192. package/dist/cjs/types/metadata.d.ts +300 -0
  193. package/dist/cjs/types/metadata.d.ts.map +1 -0
  194. package/dist/cjs/types/metadata.js +17 -0
  195. package/dist/cjs/types/metadata.js.map +7 -0
  196. package/dist/cjs/utils/index.d.ts +167 -0
  197. package/dist/cjs/utils/index.d.ts.map +1 -0
  198. package/dist/cjs/utils/index.js +209 -0
  199. package/dist/cjs/utils/index.js.map +7 -0
  200. package/dist/esm/array/index.d.ts +701 -0
  201. package/dist/esm/array/index.d.ts.map +1 -0
  202. package/dist/esm/array/index.js +983 -0
  203. package/dist/esm/array/index.js.map +1 -0
  204. package/dist/esm/box/index.d.ts +444 -0
  205. package/dist/esm/box/index.d.ts.map +1 -0
  206. package/dist/esm/box/index.js +602 -0
  207. package/dist/esm/box/index.js.map +1 -0
  208. package/dist/esm/callsite/index.d.ts +61 -0
  209. package/dist/esm/callsite/index.d.ts.map +1 -0
  210. package/dist/esm/callsite/index.js +97 -0
  211. package/dist/esm/callsite/index.js.map +1 -0
  212. package/dist/esm/chartpoint/index.d.ts +90 -0
  213. package/dist/esm/chartpoint/index.d.ts.map +1 -0
  214. package/dist/esm/chartpoint/index.js +113 -0
  215. package/dist/esm/chartpoint/index.js.map +1 -0
  216. package/dist/esm/color/index.d.ts +285 -0
  217. package/dist/esm/color/index.d.ts.map +1 -0
  218. package/dist/esm/color/index.js +373 -0
  219. package/dist/esm/color/index.js.map +1 -0
  220. package/dist/esm/compare/index.d.ts +26 -0
  221. package/dist/esm/compare/index.d.ts.map +1 -0
  222. package/dist/esm/compare/index.js +39 -0
  223. package/dist/esm/compare/index.js.map +1 -0
  224. package/dist/esm/drawing/registry.d.ts +42 -0
  225. package/dist/esm/drawing/registry.d.ts.map +1 -0
  226. package/dist/esm/drawing/registry.js +89 -0
  227. package/dist/esm/drawing/registry.js.map +1 -0
  228. package/dist/esm/index.d.ts +85 -0
  229. package/dist/esm/index.d.ts.map +1 -0
  230. package/dist/esm/index.js +96 -0
  231. package/dist/esm/index.js.map +1 -0
  232. package/dist/esm/indicator.d.ts +117 -0
  233. package/dist/esm/indicator.d.ts.map +1 -0
  234. package/dist/esm/indicator.js +84 -0
  235. package/dist/esm/indicator.js.map +1 -0
  236. package/dist/esm/input.d.ts +196 -0
  237. package/dist/esm/input.d.ts.map +1 -0
  238. package/dist/esm/input.js +183 -0
  239. package/dist/esm/input.js.map +1 -0
  240. package/dist/esm/label/index.d.ts +303 -0
  241. package/dist/esm/label/index.d.ts.map +1 -0
  242. package/dist/esm/label/index.js +417 -0
  243. package/dist/esm/label/index.js.map +1 -0
  244. package/dist/esm/lib/index.d.ts +8 -0
  245. package/dist/esm/lib/index.d.ts.map +1 -0
  246. package/dist/esm/lib/index.js +8 -0
  247. package/dist/esm/lib/index.js.map +1 -0
  248. package/dist/esm/lib/zigzag/index.d.ts +5 -0
  249. package/dist/esm/lib/zigzag/index.d.ts.map +1 -0
  250. package/dist/esm/lib/zigzag/index.js +5 -0
  251. package/dist/esm/lib/zigzag/index.js.map +1 -0
  252. package/dist/esm/lib/zigzag/zigzag.d.ts +100 -0
  253. package/dist/esm/lib/zigzag/zigzag.d.ts.map +1 -0
  254. package/dist/esm/lib/zigzag/zigzag.js +229 -0
  255. package/dist/esm/lib/zigzag/zigzag.js.map +1 -0
  256. package/dist/esm/line/index.d.ts +342 -0
  257. package/dist/esm/line/index.d.ts.map +1 -0
  258. package/dist/esm/line/index.js +470 -0
  259. package/dist/esm/line/index.js.map +1 -0
  260. package/dist/esm/linefill/index.d.ts +124 -0
  261. package/dist/esm/linefill/index.d.ts.map +1 -0
  262. package/dist/esm/linefill/index.js +144 -0
  263. package/dist/esm/linefill/index.js.map +1 -0
  264. package/dist/esm/map/index.d.ts +69 -0
  265. package/dist/esm/map/index.d.ts.map +1 -0
  266. package/dist/esm/map/index.js +106 -0
  267. package/dist/esm/map/index.js.map +1 -0
  268. package/dist/esm/math/index.d.ts +560 -0
  269. package/dist/esm/math/index.d.ts.map +1 -0
  270. package/dist/esm/math/index.js +495 -0
  271. package/dist/esm/math/index.js.map +1 -0
  272. package/dist/esm/matrix/index.d.ts +1231 -0
  273. package/dist/esm/matrix/index.d.ts.map +1 -0
  274. package/dist/esm/matrix/index.js +2450 -0
  275. package/dist/esm/matrix/index.js.map +1 -0
  276. package/dist/esm/plot.d.ts +76 -0
  277. package/dist/esm/plot.d.ts.map +1 -0
  278. package/dist/esm/plot.js +63 -0
  279. package/dist/esm/plot.js.map +1 -0
  280. package/dist/esm/polyline/index.d.ts +115 -0
  281. package/dist/esm/polyline/index.d.ts.map +1 -0
  282. package/dist/esm/polyline/index.js +157 -0
  283. package/dist/esm/polyline/index.js.map +1 -0
  284. package/dist/esm/runtime/adapters/LightweightChartsAdapter.d.ts +86 -0
  285. package/dist/esm/runtime/adapters/LightweightChartsAdapter.d.ts.map +1 -0
  286. package/dist/esm/runtime/adapters/LightweightChartsAdapter.js +140 -0
  287. package/dist/esm/runtime/adapters/LightweightChartsAdapter.js.map +1 -0
  288. package/dist/esm/runtime/adapters/SimpleInputAdapter.d.ts +59 -0
  289. package/dist/esm/runtime/adapters/SimpleInputAdapter.d.ts.map +1 -0
  290. package/dist/esm/runtime/adapters/SimpleInputAdapter.js +115 -0
  291. package/dist/esm/runtime/adapters/SimpleInputAdapter.js.map +1 -0
  292. package/dist/esm/runtime/index.d.ts +13 -0
  293. package/dist/esm/runtime/index.d.ts.map +1 -0
  294. package/dist/esm/runtime/index.js +14 -0
  295. package/dist/esm/runtime/index.js.map +1 -0
  296. package/dist/esm/runtime/inputs.d.ts +91 -0
  297. package/dist/esm/runtime/inputs.d.ts.map +1 -0
  298. package/dist/esm/runtime/inputs.js +334 -0
  299. package/dist/esm/runtime/inputs.js.map +1 -0
  300. package/dist/esm/runtime/runtime.d.ts +70 -0
  301. package/dist/esm/runtime/runtime.d.ts.map +1 -0
  302. package/dist/esm/runtime/runtime.js +193 -0
  303. package/dist/esm/runtime/runtime.js.map +1 -0
  304. package/dist/esm/runtime/series.d.ts +362 -0
  305. package/dist/esm/runtime/series.d.ts.map +1 -0
  306. package/dist/esm/runtime/series.js +583 -0
  307. package/dist/esm/runtime/series.js.map +1 -0
  308. package/dist/esm/runtime/types.d.ts +282 -0
  309. package/dist/esm/runtime/types.d.ts.map +1 -0
  310. package/dist/esm/runtime/types.js +7 -0
  311. package/dist/esm/runtime/types.js.map +1 -0
  312. package/dist/esm/script/index.d.ts +987 -0
  313. package/dist/esm/script/index.d.ts.map +1 -0
  314. package/dist/esm/script/index.js +1289 -0
  315. package/dist/esm/script/index.js.map +1 -0
  316. package/dist/esm/security/resample.d.ts +63 -0
  317. package/dist/esm/security/resample.d.ts.map +1 -0
  318. package/dist/esm/security/resample.js +110 -0
  319. package/dist/esm/security/resample.js.map +1 -0
  320. package/dist/esm/session/bars.d.ts +80 -0
  321. package/dist/esm/session/bars.d.ts.map +1 -0
  322. package/dist/esm/session/bars.js +232 -0
  323. package/dist/esm/session/bars.js.map +1 -0
  324. package/dist/esm/session/calendar.d.ts +70 -0
  325. package/dist/esm/session/calendar.d.ts.map +1 -0
  326. package/dist/esm/session/calendar.js +172 -0
  327. package/dist/esm/session/calendar.js.map +1 -0
  328. package/dist/esm/str/dateformat.d.ts +15 -0
  329. package/dist/esm/str/dateformat.d.ts.map +1 -0
  330. package/dist/esm/str/dateformat.js +136 -0
  331. package/dist/esm/str/dateformat.js.map +1 -0
  332. package/dist/esm/str/index.d.ts +459 -0
  333. package/dist/esm/str/index.d.ts.map +1 -0
  334. package/dist/esm/str/index.js +540 -0
  335. package/dist/esm/str/index.js.map +1 -0
  336. package/dist/esm/str/messageformat.d.ts +14 -0
  337. package/dist/esm/str/messageformat.d.ts.map +1 -0
  338. package/dist/esm/str/messageformat.js +111 -0
  339. package/dist/esm/str/messageformat.js.map +1 -0
  340. package/dist/esm/str/numberformat.d.ts +19 -0
  341. package/dist/esm/str/numberformat.d.ts.map +1 -0
  342. package/dist/esm/str/numberformat.js +189 -0
  343. package/dist/esm/str/numberformat.js.map +1 -0
  344. package/dist/esm/strategy/index.d.ts +245 -0
  345. package/dist/esm/strategy/index.d.ts.map +1 -0
  346. package/dist/esm/strategy/index.js +84 -0
  347. package/dist/esm/strategy/index.js.map +1 -0
  348. package/dist/esm/ta/index.d.ts +1397 -0
  349. package/dist/esm/ta/index.d.ts.map +1 -0
  350. package/dist/esm/ta/index.js +3227 -0
  351. package/dist/esm/ta/index.js.map +1 -0
  352. package/dist/esm/ta/running-sum.d.ts +30 -0
  353. package/dist/esm/ta/running-sum.d.ts.map +1 -0
  354. package/dist/esm/ta/running-sum.js +113 -0
  355. package/dist/esm/ta/running-sum.js.map +1 -0
  356. package/dist/esm/ta-series.d.ts +558 -0
  357. package/dist/esm/ta-series.d.ts.map +1 -0
  358. package/dist/esm/ta-series.js +910 -0
  359. package/dist/esm/ta-series.js.map +1 -0
  360. package/dist/esm/text/index.d.ts +14 -0
  361. package/dist/esm/text/index.d.ts.map +1 -0
  362. package/dist/esm/text/index.js +14 -0
  363. package/dist/esm/text/index.js.map +1 -0
  364. package/dist/esm/time/datestring.d.ts +23 -0
  365. package/dist/esm/time/datestring.d.ts.map +1 -0
  366. package/dist/esm/time/datestring.js +94 -0
  367. package/dist/esm/time/datestring.js.map +1 -0
  368. package/dist/esm/time/index.d.ts +89 -0
  369. package/dist/esm/time/index.d.ts.map +1 -0
  370. package/dist/esm/time/index.js +108 -0
  371. package/dist/esm/time/index.js.map +1 -0
  372. package/dist/esm/time/session.d.ts +17 -0
  373. package/dist/esm/time/session.d.ts.map +1 -0
  374. package/dist/esm/time/session.js +69 -0
  375. package/dist/esm/time/session.js.map +1 -0
  376. package/dist/esm/time/timezone.d.ts +40 -0
  377. package/dist/esm/time/timezone.d.ts.map +1 -0
  378. package/dist/esm/time/timezone.js +144 -0
  379. package/dist/esm/time/timezone.js.map +1 -0
  380. package/dist/esm/timeframe/index.d.ts +73 -0
  381. package/dist/esm/timeframe/index.d.ts.map +1 -0
  382. package/dist/esm/timeframe/index.js +131 -0
  383. package/dist/esm/timeframe/index.js.map +1 -0
  384. package/dist/esm/types/index.d.ts +343 -0
  385. package/dist/esm/types/index.d.ts.map +1 -0
  386. package/dist/esm/types/index.js +17 -0
  387. package/dist/esm/types/index.js.map +1 -0
  388. package/dist/esm/types/metadata.d.ts +300 -0
  389. package/dist/esm/types/metadata.d.ts.map +1 -0
  390. package/dist/esm/types/metadata.js +7 -0
  391. package/dist/esm/types/metadata.js.map +1 -0
  392. package/dist/esm/utils/index.d.ts +167 -0
  393. package/dist/esm/utils/index.d.ts.map +1 -0
  394. package/dist/esm/utils/index.js +295 -0
  395. package/dist/esm/utils/index.js.map +1 -0
  396. package/package.json +53 -23
  397. package/src/array/index.ts +1056 -0
  398. package/src/box/index.ts +680 -0
  399. package/src/callsite/index.ts +104 -0
  400. package/src/chartpoint/index.ts +126 -0
  401. package/src/color/index.ts +411 -0
  402. package/src/compare/index.ts +46 -0
  403. package/src/drawing/registry.ts +106 -0
  404. package/src/index.ts +201 -0
  405. package/src/indicator.ts +185 -0
  406. package/src/input.ts +280 -0
  407. package/src/label/index.ts +490 -0
  408. package/src/lib/index.ts +8 -0
  409. package/src/lib/zigzag/index.ts +13 -0
  410. package/src/lib/zigzag/zigzag.ts +318 -0
  411. package/src/line/index.ts +530 -0
  412. package/src/linefill/index.ts +152 -0
  413. package/src/map/index.ts +115 -0
  414. package/src/math/index.ts +1071 -0
  415. package/src/matrix/index.ts +2697 -0
  416. package/src/plot.ts +121 -0
  417. package/src/polyline/index.ts +184 -0
  418. package/src/runtime/adapters/LightweightChartsAdapter.ts +201 -0
  419. package/src/runtime/adapters/SimpleInputAdapter.ts +132 -0
  420. package/src/runtime/index.ts +52 -0
  421. package/src/runtime/inputs.ts +377 -0
  422. package/src/runtime/runtime.ts +241 -0
  423. package/src/runtime/series.ts +644 -0
  424. package/src/runtime/types.ts +292 -0
  425. package/src/script/index.ts +1865 -0
  426. package/src/security/resample.ts +119 -0
  427. package/src/session/bars.ts +262 -0
  428. package/src/session/calendar.ts +199 -0
  429. package/src/str/dateformat.ts +104 -0
  430. package/src/str/index.ts +557 -0
  431. package/src/str/messageformat.ts +109 -0
  432. package/src/str/numberformat.ts +197 -0
  433. package/src/strategy/index.ts +281 -0
  434. package/src/ta/index.ts +3580 -0
  435. package/src/ta/running-sum.ts +117 -0
  436. package/src/ta-series.ts +1036 -0
  437. package/src/text/index.ts +14 -0
  438. package/src/time/datestring.ts +96 -0
  439. package/src/time/index.ts +161 -0
  440. package/src/time/session.ts +79 -0
  441. package/src/time/timezone.ts +180 -0
  442. package/src/timeframe/index.ts +144 -0
  443. package/src/types/index.ts +398 -0
  444. package/src/types/metadata.ts +334 -0
  445. package/src/utils/index.ts +334 -0
  446. package/dist/array/index.d.ts +0 -57
  447. package/dist/array/index.d.ts.map +0 -1
  448. package/dist/box/index.d.ts +0 -37
  449. package/dist/box/index.d.ts.map +0 -1
  450. package/dist/callsite/index.d.ts +0 -7
  451. package/dist/callsite/index.d.ts.map +0 -1
  452. package/dist/chartpoint/index.d.ts +0 -8
  453. package/dist/chartpoint/index.d.ts.map +0 -1
  454. package/dist/color/index.d.ts +0 -28
  455. package/dist/color/index.d.ts.map +0 -1
  456. package/dist/compare/index.d.ts +0 -8
  457. package/dist/compare/index.d.ts.map +0 -1
  458. package/dist/drawing/registry.d.ts +0 -19
  459. package/dist/drawing/registry.d.ts.map +0 -1
  460. package/dist/index.cjs +0 -7981
  461. package/dist/index.d.ts +0 -64
  462. package/dist/index.d.ts.map +0 -1
  463. package/dist/index.mjs +0 -7964
  464. package/dist/indicator.d.ts +0 -42
  465. package/dist/indicator.d.ts.map +0 -1
  466. package/dist/input.d.ts +0 -47
  467. package/dist/input.d.ts.map +0 -1
  468. package/dist/label/index.d.ts +0 -30
  469. package/dist/label/index.d.ts.map +0 -1
  470. package/dist/lib/index.d.ts +0 -2
  471. package/dist/lib/index.d.ts.map +0 -1
  472. package/dist/lib/zigzag/index.d.ts.map +0 -1
  473. package/dist/lib/zigzag/zigzag.d.ts +0 -47
  474. package/dist/lib/zigzag/zigzag.d.ts.map +0 -1
  475. package/dist/line/index.d.ts +0 -30
  476. package/dist/line/index.d.ts.map +0 -1
  477. package/dist/linefill/index.d.ts +0 -10
  478. package/dist/linefill/index.d.ts.map +0 -1
  479. package/dist/map/index.d.ts +0 -14
  480. package/dist/map/index.d.ts.map +0 -1
  481. package/dist/math/index.d.ts +0 -53
  482. package/dist/math/index.d.ts.map +0 -1
  483. package/dist/matrix/index.d.ts +0 -52
  484. package/dist/matrix/index.d.ts.map +0 -1
  485. package/dist/plot.d.ts +0 -20
  486. package/dist/plot.d.ts.map +0 -1
  487. package/dist/polyline/index.d.ts +0 -11
  488. package/dist/polyline/index.d.ts.map +0 -1
  489. package/dist/runtime/adapters/LightweightChartsAdapter.d.ts +0 -15
  490. package/dist/runtime/adapters/LightweightChartsAdapter.d.ts.map +0 -1
  491. package/dist/runtime/adapters/SimpleInputAdapter.d.ts +0 -16
  492. package/dist/runtime/adapters/SimpleInputAdapter.d.ts.map +0 -1
  493. package/dist/runtime/index.cjs +0 -600
  494. package/dist/runtime/index.d.ts.map +0 -1
  495. package/dist/runtime/index.mjs +0 -577
  496. package/dist/runtime/inputs.d.ts +0 -13
  497. package/dist/runtime/inputs.d.ts.map +0 -1
  498. package/dist/runtime/runtime.d.ts +0 -16
  499. package/dist/runtime/runtime.d.ts.map +0 -1
  500. package/dist/runtime/series.d.ts +0 -60
  501. package/dist/runtime/series.d.ts.map +0 -1
  502. package/dist/runtime/types.d.ts +0 -126
  503. package/dist/runtime/types.d.ts.map +0 -1
  504. package/dist/script/index.cjs +0 -6377
  505. package/dist/script/index.d.ts +0 -713
  506. package/dist/script/index.d.ts.map +0 -1
  507. package/dist/script/index.mjs +0 -6360
  508. package/dist/security/resample.d.ts +0 -13
  509. package/dist/security/resample.d.ts.map +0 -1
  510. package/dist/session/bars.d.ts +0 -34
  511. package/dist/session/bars.d.ts.map +0 -1
  512. package/dist/session/calendar.d.ts +0 -31
  513. package/dist/session/calendar.d.ts.map +0 -1
  514. package/dist/str/dateformat.d.ts +0 -2
  515. package/dist/str/dateformat.d.ts.map +0 -1
  516. package/dist/str/index.d.ts +0 -24
  517. package/dist/str/index.d.ts.map +0 -1
  518. package/dist/str/messageformat.d.ts +0 -2
  519. package/dist/str/messageformat.d.ts.map +0 -1
  520. package/dist/str/numberformat.d.ts +0 -3
  521. package/dist/str/numberformat.d.ts.map +0 -1
  522. package/dist/strategy/index.d.ts.map +0 -1
  523. package/dist/ta/index.d.ts +0 -72
  524. package/dist/ta/index.d.ts.map +0 -1
  525. package/dist/ta/running-sum.d.ts +0 -3
  526. package/dist/ta/running-sum.d.ts.map +0 -1
  527. package/dist/ta-series.d.ts +0 -143
  528. package/dist/ta-series.d.ts.map +0 -1
  529. package/dist/text/index.d.ts +0 -4
  530. package/dist/text/index.d.ts.map +0 -1
  531. package/dist/time/datestring.d.ts +0 -2
  532. package/dist/time/datestring.d.ts.map +0 -1
  533. package/dist/time/index.d.ts +0 -15
  534. package/dist/time/index.d.ts.map +0 -1
  535. package/dist/time/session.d.ts +0 -2
  536. package/dist/time/session.d.ts.map +0 -1
  537. package/dist/time/timezone.d.ts +0 -13
  538. package/dist/time/timezone.d.ts.map +0 -1
  539. package/dist/timeframe/index.d.ts +0 -17
  540. package/dist/timeframe/index.d.ts.map +0 -1
  541. package/dist/types/index.d.ts +0 -181
  542. package/dist/types/index.d.ts.map +0 -1
  543. package/dist/types/metadata.d.ts +0 -132
  544. package/dist/types/metadata.d.ts.map +0 -1
  545. package/dist/utils/index.d.ts +0 -26
  546. package/dist/utils/index.d.ts.map +0 -1
@@ -0,0 +1,1289 @@
1
+ /**
2
+ * @fileoverview PineScript-style script API — write an indicator as a flat
3
+ * script instead of the explicit calculate() convention.
4
+ *
5
+ * ```typescript
6
+ * import { indicator, input, plot, ta } from 'oakscriptjs/script';
7
+ *
8
+ * indicator('My SMA', { overlay: true });
9
+ * const length = input.int(20, 'Length', { minval: 1 });
10
+ * const src = input.source('close', 'Source');
11
+ * plot(ta.sma(src, length), 'SMA', { color: '#2962FF' });
12
+ * ```
13
+ *
14
+ * Execution model: the host calls {@link executeScript} with the script body,
15
+ * the bars and the current input values. Declaration calls (indicator, input.*,
16
+ * plot, hline, fill, alertcondition) run as the body executes and are collected
17
+ * into a {@link ScriptRunResult}: the declarative configs (inputConfig,
18
+ * plotConfig, hlineConfig, fillConfig) plus an IndicatorResult with the plot
19
+ * data. Re-running the body with new bars or inputs is PineScript's
20
+ * recalculation model.
21
+ *
22
+ * `input.*` is idempotent like PineScript: it declares the input AND returns
23
+ * its current value (the host-supplied override, else the default).
24
+ *
25
+ * The OHLCV builtins (open/high/low/close/volume/hl2/hlc3/ohlc4/hlcc4) are
26
+ * Series bound to a module-level BarData that the host swaps per run, so
27
+ * derived Series memoize between identical runs and recompute when the bars
28
+ * version bumps.
29
+ *
30
+ * One script executes at a time (module-level context) — hosts that run many
31
+ * scripts must serialize executions, which a Web Worker does naturally.
32
+ *
33
+ * @module script
34
+ */
35
+ import { BarData, Series } from '../runtime/series.js';
36
+ import * as taSeries from '../ta-series.js';
37
+ import * as colorCore from '../color/index.js';
38
+ import { fixnan as fixnanValues, isNA, nz } from '../utils/index.js';
39
+ import * as lineCore from '../line/index.js';
40
+ import * as labelCore from '../label/index.js';
41
+ import * as boxCore from '../box/index.js';
42
+ import * as linefillCore from '../linefill/index.js';
43
+ import * as polylineCore from '../polyline/index.js';
44
+ import * as chartPointCore from '../chartpoint/index.js';
45
+ import * as textCore from '../text/index.js';
46
+ import * as mathCore from '../math/index.js';
47
+ import { resetDrawings, setDrawingLimits } from '../drawing/registry.js';
48
+ import * as timeframeCore from '../timeframe/index.js';
49
+ import * as timeCore from '../time/index.js';
50
+ import * as strCore from '../str/index.js';
51
+ import { formatMessage } from '../str/messageformat.js';
52
+ import { TradingCalendar } from '../session/calendar.js';
53
+ import { SessionBars, sessionFlags } from '../session/bars.js';
54
+ import { afterCompletion, heikinAshi, mapToChart, periodsOf, resample } from '../security/resample.js';
55
+ import { STRATEGY_CONSTANTS, STRATEGY_DEFAULTS, STRATEGY_NUMBER_VARIABLES, STRATEGY_TEXT_VARIABLES, } from '../strategy/index.js';
56
+ /** Bars for the current run. Module-level and REUSED across runs so builtins
57
+ * and every Series derived from them keep their version-keyed memoization. */
58
+ const ctxBars = new BarData([]);
59
+ let ctx = null;
60
+ function collector() {
61
+ if (!ctx) {
62
+ throw new Error('oakscriptjs/script functions can only run inside executeScript() — ' +
63
+ 'the host (chart/worker) drives script execution.');
64
+ }
65
+ return ctx;
66
+ }
67
+ function freshCollector(inputValues) {
68
+ return {
69
+ title: 'Untitled',
70
+ overlay: true,
71
+ inputValues,
72
+ inputConfig: [],
73
+ inputIds: new Set(),
74
+ defaultInputs: {},
75
+ plotConfig: [],
76
+ plots: {},
77
+ hlineConfig: [],
78
+ fills: [],
79
+ fillConfig: [],
80
+ shapeConfig: [],
81
+ markers: [],
82
+ arrowConfig: [],
83
+ arrows: [],
84
+ barColorConfig: [],
85
+ bgcolors: [],
86
+ barcolors: [],
87
+ alertConfig: [],
88
+ alerts: [],
89
+ };
90
+ }
91
+ /** Stable input id from the title ("ATR / Range Period" → "atr_range_period"). */
92
+ function slugId(title, fallback, taken) {
93
+ const base = (title ?? '')
94
+ .toLowerCase()
95
+ .replace(/[^a-z0-9]+/g, '_')
96
+ .replace(/^_+|_+$/g, '') || fallback;
97
+ let id = base;
98
+ for (let n = 2; taken.has(id); n++)
99
+ id = `${base}_${n}`;
100
+ taken.add(id);
101
+ return id;
102
+ }
103
+ let scriptOptions = {};
104
+ /**
105
+ * Runs a script body against `bars` with the given input overrides and
106
+ * collects everything it declared. `chart` describes the bars (chart timeframe,
107
+ * exchange time zone, session type) for the PineScript values that depend on them. `options.strategyEngine`
108
+ * supplies the order engine of strategy scripts. This is the host-side entry — editor
109
+ * panels, workers and tests call it; scripts never do.
110
+ */
111
+ export function executeScript(body, barsInput, inputs = {}, chart = {}, options = {}) {
112
+ ctxBars.setAll(barsInput);
113
+ chartCtx = { ...chart };
114
+ scriptOptions = options;
115
+ ctx = freshCollector(inputs);
116
+ resetDrawings();
117
+ try {
118
+ body();
119
+ const c = ctx;
120
+ return {
121
+ metadata: {
122
+ title: c.title,
123
+ shortTitle: c.shortTitle,
124
+ overlay: c.overlay,
125
+ precision: c.precision,
126
+ format: c.format,
127
+ },
128
+ inputConfig: c.inputConfig,
129
+ plotConfig: c.plotConfig,
130
+ hlineConfig: c.hlineConfig,
131
+ fillConfig: c.fillConfig,
132
+ shapeConfig: c.shapeConfig,
133
+ arrowConfig: c.arrowConfig,
134
+ barColorConfig: c.barColorConfig,
135
+ defaultInputs: c.defaultInputs,
136
+ alertConfig: c.alertConfig,
137
+ strategyConfig: c.strategy?.properties,
138
+ result: {
139
+ metadata: { title: c.title, shorttitle: c.shortTitle, overlay: c.overlay, precision: c.precision },
140
+ plots: c.plots,
141
+ fills: c.fills.length ? c.fills : undefined,
142
+ markers: c.markers.length ? c.markers : undefined,
143
+ arrows: c.arrows.length ? c.arrows : undefined,
144
+ bgcolors: c.bgcolors.length ? c.bgcolors : undefined,
145
+ barcolors: c.barcolors.length ? c.barcolors : undefined,
146
+ alerts: c.alerts.length ? c.alerts : undefined,
147
+ },
148
+ };
149
+ }
150
+ finally {
151
+ ctx = null;
152
+ }
153
+ }
154
+ /** PineScript `indicator()` — declares the script's metadata. */
155
+ export function indicator(title, options = {}) {
156
+ const c = collector();
157
+ declare(c, 'indicator');
158
+ c.title = title;
159
+ c.shortTitle = options.shorttitle;
160
+ c.overlay = options.overlay ?? true;
161
+ c.precision = options.precision;
162
+ c.format = options.format;
163
+ setDrawingLimits({
164
+ line: options.max_lines_count,
165
+ label: options.max_labels_count,
166
+ box: options.max_boxes_count,
167
+ polyline: options.max_polylines_count,
168
+ });
169
+ }
170
+ function declare(c, kind) {
171
+ if (c.declaration) {
172
+ throw new Error(`${kind}(): the script already declared ${c.declaration}(); a script has one declaration.`);
173
+ }
174
+ c.declaration = kind;
175
+ }
176
+ /** The InputConfig fields of the common input options (unset options are left out). */
177
+ function common(opts) {
178
+ const out = {};
179
+ if (opts.group !== undefined)
180
+ out.group = opts.group;
181
+ if (opts.inline !== undefined)
182
+ out.inline = opts.inline;
183
+ if (opts.tooltip !== undefined)
184
+ out.tooltip = opts.tooltip;
185
+ if (opts.confirm !== undefined)
186
+ out.confirm = opts.confirm;
187
+ if (opts.display !== undefined)
188
+ out.display = opts.display;
189
+ return out;
190
+ }
191
+ /** Declares the input in the collector and returns its current value (the
192
+ * host-supplied override when present, else the default). */
193
+ function registerInput(config, fallbackId) {
194
+ const c = collector();
195
+ const id = slugId(config.title, fallbackId, c.inputIds);
196
+ c.inputConfig.push({ id, ...config });
197
+ c.defaultInputs[id] = config.defval;
198
+ const value = c.inputValues[id];
199
+ return (value === undefined ? config.defval : value);
200
+ }
201
+ function registerNumeric(type, defval, title, opts = {}) {
202
+ const v = registerInput({ type, defval, title, min: opts.minval, max: opts.maxval, step: opts.step, ...common(opts) }, `input_${type}`);
203
+ return typeof v === 'number' ? v : defval;
204
+ }
205
+ /** PineScript `input.*` — declares an input AND returns its current value. */
206
+ export const input = {
207
+ int(defval, title, opts = {}) {
208
+ return Math.round(registerNumeric('int', defval, title, opts));
209
+ },
210
+ float(defval, title, opts = {}) {
211
+ return registerNumeric('float', defval, title, opts);
212
+ },
213
+ bool(defval, title, opts = {}) {
214
+ return registerInput({ type: 'bool', defval, title, ...common(opts) }, 'input_bool');
215
+ },
216
+ string(defval, title, opts = {}) {
217
+ return registerInput({ type: 'string', defval, title, options: opts.options, ...common(opts) }, 'input_string');
218
+ },
219
+ color(defval, title, opts = {}) {
220
+ return registerInput({ type: 'color', defval, title, ...common(opts) }, 'input_color');
221
+ },
222
+ /** Declares a source input and returns it as a Series. */
223
+ source(defval = 'close', title, opts = {}) {
224
+ const name = registerInput({ type: 'source', defval, title, ...common(opts) }, 'input_source');
225
+ return sourceSeries(name);
226
+ },
227
+ /** Timeframe string ("60", "1D", "W"). As in PineScript, "" means the chart timeframe. */
228
+ timeframe(defval, title, opts = {}) {
229
+ return registerInput({ type: 'timeframe', defval, title, options: opts.options, ...common(opts) }, 'input_timeframe');
230
+ },
231
+ /** Session string ("0930-1600", "0930-1600:23456"). */
232
+ session(defval, title, opts = {}) {
233
+ return registerInput({ type: 'session', defval, title, options: opts.options, ...common(opts) }, 'input_session');
234
+ },
235
+ /** Date and time as a UNIX time in milliseconds, e.g. `input.time(timestamp('2024-01-01'), 'Start')`. */
236
+ time(defval, title, opts = {}) {
237
+ const v = registerInput({ type: 'time', defval, title, ...common(opts) }, 'input_time');
238
+ return typeof v === 'number' ? v : defval;
239
+ },
240
+ };
241
+ // ── OHLCV builtins ───────────────────────────────────────────────────────────
242
+ export const open = Series.fromBars(ctxBars, 'open');
243
+ export const high = Series.fromBars(ctxBars, 'high');
244
+ export const low = Series.fromBars(ctxBars, 'low');
245
+ export const close = Series.fromBars(ctxBars, 'close');
246
+ export const volume = Series.fromBars(ctxBars, 'volume');
247
+ export const hl2 = new Series(ctxBars, (b) => (b.high + b.low) / 2);
248
+ export const hlc3 = new Series(ctxBars, (b) => (b.high + b.low + b.close) / 3);
249
+ export const ohlc4 = new Series(ctxBars, (b) => (b.open + b.high + b.low + b.close) / 4);
250
+ export const hlcc4 = new Series(ctxBars, (b) => (b.high + b.low + b.close + b.close) / 4);
251
+ const SOURCES = { open, high, low, close, volume, hl2, hlc3, ohlc4, hlcc4 };
252
+ function sourceSeries(name) {
253
+ return SOURCES[name] ?? close;
254
+ }
255
+ // ── Bound ta namespace ───────────────────────────────────────────────────────
256
+ const bars = () => ctxBars.bars;
257
+ /** A Series bound to the context bars whose values come from one pass over all bars
258
+ * (cumulative indicators), recomputed when the bars version changes. */
259
+ function barsSeries(compute) {
260
+ let version = -1;
261
+ let values = [];
262
+ return new Series(ctxBars, (_bar, i, data) => {
263
+ if (version !== ctxBars.version) {
264
+ values = compute(data).toArray();
265
+ version = ctxBars.version;
266
+ }
267
+ return values[i] ?? NaN;
268
+ });
269
+ }
270
+ /** ta.* with the chart-implicit (bars-first) functions bound to the context,
271
+ * so scripts call them like PineScript: `ta.tr(true)`, `ta.atr(14)`. */
272
+ export const ta = {
273
+ ...taSeries,
274
+ tr: (handleNa = false) => taSeries.tr(bars(), handleNa),
275
+ atr: (length) => taSeries.atr(bars(), length),
276
+ sar: (start, inc, max) => taSeries.sar(bars(), start, inc, max),
277
+ wpr: (length) => taSeries.wpr(bars(), length),
278
+ supertrend: (factor, atrLength) => taSeries.supertrend(bars(), factor, atrLength),
279
+ dmi: (diLength, adxSmoothing) => taSeries.dmi(bars(), diLength, adxSmoothing),
280
+ kc: (source, length, mult, useTrueRange) => taSeries.kc(bars(), source, length, mult, useTrueRange),
281
+ kcw: (source, length, mult, useTrueRange) => taSeries.kcw(bars(), source, length, mult, useTrueRange),
282
+ ichimoku: (conversionPeriods, basePeriods, laggingSpan2Periods, displacement) => taSeries.ichimoku(bars(), conversionPeriods, basePeriods, laggingSpan2Periods, displacement),
283
+ /** `ta.highest(source, length)` or `ta.highest(length)` (source = high). */
284
+ highest: (sourceOrLength, length) => typeof sourceOrLength === 'number' ? taSeries.highest(high, sourceOrLength) : taSeries.highest(sourceOrLength, length),
285
+ /** `ta.lowest(source, length)` or `ta.lowest(length)` (source = low). */
286
+ lowest: (sourceOrLength, length) => typeof sourceOrLength === 'number' ? taSeries.lowest(low, sourceOrLength) : taSeries.lowest(sourceOrLength, length),
287
+ /** `ta.highestbars(source, length)` or `ta.highestbars(length)` (source = high); offsets are 0 or negative. */
288
+ highestbars: (sourceOrLength, length) => typeof sourceOrLength === 'number'
289
+ ? taSeries.highestbars(high, sourceOrLength)
290
+ : taSeries.highestbars(sourceOrLength, length),
291
+ /** `ta.lowestbars(source, length)` or `ta.lowestbars(length)` (source = low); offsets are 0 or negative. */
292
+ lowestbars: (sourceOrLength, length) => typeof sourceOrLength === 'number'
293
+ ? taSeries.lowestbars(low, sourceOrLength)
294
+ : taSeries.lowestbars(sourceOrLength, length),
295
+ /** `ta.vwap(source, anchor?, stdev_mult?)` with the chart volume; the default anchor is a new trading
296
+ * day (`timeframe.change("1D")`), which needs the chart context (timeframe, time zone, session). */
297
+ vwap: ((source, anchor, stdev_mult) => {
298
+ const a = anchor ?? changeOf('1D'); // PineScript default: timeframe.change("1D")
299
+ return stdev_mult === undefined ? taSeries.vwap(source, volume, a) : taSeries.vwapBands(source, volume, a, stdev_mult);
300
+ }),
301
+ /** `ta.mfi(source, length)` with the chart volume (PineScript takes 2 arguments). */
302
+ mfi: (source, length) => taSeries.mfi(source, length, volume),
303
+ /** `ta.pivothigh(source, leftbars, rightbars)` or `ta.pivothigh(leftbars, rightbars)` (source = high).
304
+ * The value appears `rightbars` bars after the pivot bar, as in PineScript. */
305
+ pivothigh: (sourceOrLeft, leftOrRight, rightbars) => typeof sourceOrLeft === 'number'
306
+ ? taSeries.pivothigh(high, sourceOrLeft, leftOrRight)
307
+ : taSeries.pivothigh(sourceOrLeft, leftOrRight, rightbars),
308
+ /** `ta.pivotlow(source, leftbars, rightbars)` or `ta.pivotlow(leftbars, rightbars)` (source = low). */
309
+ pivotlow: (sourceOrLeft, leftOrRight, rightbars) => typeof sourceOrLeft === 'number'
310
+ ? taSeries.pivotlow(low, sourceOrLeft, leftOrRight)
311
+ : taSeries.pivotlow(sourceOrLeft, leftOrRight, rightbars),
312
+ // PineScript variables of the chart bars: `ta.obv`, not `ta.obv()`.
313
+ obv: barsSeries(taSeries.obv),
314
+ pvt: barsSeries(taSeries.pvt),
315
+ accdist: barsSeries(taSeries.accdist),
316
+ nvi: barsSeries(taSeries.nvi),
317
+ pvi: barsSeries(taSeries.pvi),
318
+ iii: barsSeries(taSeries.iii),
319
+ wad: barsSeries(taSeries.wad),
320
+ wvad: barsSeries(taSeries.wvad),
321
+ };
322
+ export function fixnan(source) {
323
+ return source instanceof Series ? Series.fromArray(ctxBars, fixnanValues(source.toArray())) : fixnanValues(source);
324
+ }
325
+ function colorWhen(cond, colorTrue, colorFalse) {
326
+ return cond.toArray().map((v) => (!isNA(v) && v !== 0 ? colorTrue : colorFalse));
327
+ }
328
+ /** color.* plus `when` — per-bar conditional colors for plot()/fill()/bgcolor()/barcolor(). */
329
+ export const color = {
330
+ ...colorCore,
331
+ new: colorCore.new_color,
332
+ when: colorWhen,
333
+ };
334
+ /** PineScript `plot()` — declares the plot and supplies its data in one call. */
335
+ function plotImpl(series, title, options = {}) {
336
+ const c = collector();
337
+ const id = `plot${c.plotConfig.length}`;
338
+ const perBar = Array.isArray(options.color) ? options.color : undefined;
339
+ const staticColor = typeof options.color === 'string' ? options.color : (perBar?.[perBar.length - 1] ?? '#2962FF');
340
+ c.plotConfig.push({
341
+ id,
342
+ title: title ?? id,
343
+ color: staticColor,
344
+ lineWidth: options.linewidth,
345
+ style: options.style,
346
+ linestyle: options.linestyle,
347
+ display: options.display,
348
+ histbase: options.histbase,
349
+ forceOverlay: options.force_overlay,
350
+ });
351
+ const values = series.toArray();
352
+ const b = bars();
353
+ const data = [];
354
+ for (let i = 0; i < b.length; i++) {
355
+ const value = values[i];
356
+ if (value === undefined || !Number.isFinite(value))
357
+ continue; // PineScript plots +/-Infinity as na
358
+ data.push(perBar ? { time: b[i].time, value, color: perBar[i] } : { time: b[i].time, value });
359
+ }
360
+ c.plots[id] = data;
361
+ return { id, kind: 'plot' };
362
+ }
363
+ /**
364
+ * PineScript `plot()`, with the `plot.style_*` and `plot.linestyle_*` constants:
365
+ * `plot(src, 'Level', { style: plot.style_stepline, linestyle: plot.linestyle_dashed })`.
366
+ */
367
+ export const plot = Object.assign(plotImpl, {
368
+ style_line: 'line',
369
+ style_linebr: 'linebr',
370
+ style_stepline: 'stepline',
371
+ style_steplinebr: 'steplinebr',
372
+ style_stepline_diamond: 'stepline_diamond',
373
+ style_histogram: 'histogram',
374
+ style_columns: 'columns',
375
+ style_area: 'area',
376
+ style_areabr: 'areabr',
377
+ style_circles: 'circles',
378
+ style_cross: 'cross',
379
+ linestyle_solid: 'solid',
380
+ linestyle_dotted: 'dotted',
381
+ linestyle_dashed: 'dashed',
382
+ });
383
+ /** PineScript `hline()` — a static horizontal level. Default line style: dashed (PineScript). */
384
+ function hlineImpl(price, title, options = {}) {
385
+ const c = collector();
386
+ const id = `hline${c.hlineConfig.length}`;
387
+ c.hlineConfig.push({
388
+ id,
389
+ price,
390
+ title,
391
+ color: options.color,
392
+ linestyle: options.linestyle ?? 'dashed',
393
+ linewidth: options.linewidth,
394
+ });
395
+ return { id, kind: 'hline' };
396
+ }
397
+ /** PineScript `hline()`, with the `hline.style_*` constants: `hline(0, 'Zero', { linestyle: hline.style_dotted })`. */
398
+ export const hline = Object.assign(hlineImpl, {
399
+ style_solid: 'solid',
400
+ style_dotted: 'dotted',
401
+ style_dashed: 'dashed',
402
+ });
403
+ function perBarValues(v, n) {
404
+ return v instanceof Series ? v.toArray().slice(0, n) : new Array(n).fill(v);
405
+ }
406
+ function perBarColors(c, n) {
407
+ if (Array.isArray(c))
408
+ return Array.from({ length: n }, (_, i) => c[i] ?? null);
409
+ return new Array(n).fill(c ?? null);
410
+ }
411
+ export function fill(a, b, ...args) {
412
+ const c = collector();
413
+ const third = args[0];
414
+ let perBar;
415
+ let staticColor;
416
+ let title;
417
+ let gradient;
418
+ if (typeof third === 'number' || third instanceof Series) {
419
+ const n = ctxBars.bars.length;
420
+ gradient = {
421
+ topValue: perBarValues(third, n),
422
+ bottomValue: perBarValues(args[1], n),
423
+ topColor: perBarColors(args[2], n),
424
+ bottomColor: perBarColors(args[3], n),
425
+ };
426
+ title = args[4];
427
+ }
428
+ else if (third !== null && typeof third === 'object' && !Array.isArray(third)) {
429
+ const options = third;
430
+ perBar = Array.isArray(options.color) ? options.color : undefined;
431
+ staticColor = typeof options.color === 'string' ? options.color : undefined;
432
+ title = options.title;
433
+ }
434
+ else {
435
+ const color = third;
436
+ perBar = Array.isArray(color) ? color.map((x) => x ?? '') : undefined;
437
+ staticColor = typeof color === 'string' ? color : undefined;
438
+ title = args[1];
439
+ }
440
+ if (a.kind === 'hline' && b.kind === 'hline') {
441
+ c.fillConfig.push({
442
+ id: `fill${c.fillConfig.length}`,
443
+ plot1: a.id,
444
+ plot2: b.id,
445
+ color: staticColor,
446
+ colors: perBar,
447
+ gradient,
448
+ title,
449
+ });
450
+ return;
451
+ }
452
+ c.fills.push({
453
+ plot1: a.id,
454
+ plot2: b.id,
455
+ options: { color: staticColor, title },
456
+ colors: perBar,
457
+ gradient,
458
+ });
459
+ }
460
+ /** Shared emitter for plotshape()/plotchar(). Emits one marker per bar where
461
+ * the condition is truthy (not na, not 0). */
462
+ function emitMarkers(kind, condition, title, options) {
463
+ const c = collector();
464
+ const id = `${kind}${c.shapeConfig.filter((s) => s.kind === kind).length}`;
465
+ const style = kind === 'shape' ? (options.style ?? 'xcross') : 'char';
466
+ const char = kind === 'char' ? (options.char ?? '*') : undefined;
467
+ const location = options.location ?? 'abovebar';
468
+ c.shapeConfig.push({
469
+ id,
470
+ kind,
471
+ title,
472
+ style: kind === 'shape' ? style : undefined,
473
+ char,
474
+ location,
475
+ color: options.color,
476
+ text: options.text,
477
+ textcolor: options.textcolor,
478
+ size: options.size,
479
+ offset: options.offset,
480
+ forceOverlay: options.force_overlay,
481
+ });
482
+ const values = condition.toArray();
483
+ const b = bars();
484
+ const off = options.offset ?? 0;
485
+ for (let i = 0; i < b.length; i++) {
486
+ const v = values[i];
487
+ if (v === undefined || Number.isNaN(v) || v === 0)
488
+ continue;
489
+ const j = i + off;
490
+ if (j < 0 || j >= b.length)
491
+ continue;
492
+ c.markers.push({
493
+ time: b[j].time,
494
+ id,
495
+ location,
496
+ style,
497
+ char,
498
+ color: options.color,
499
+ text: options.text,
500
+ textcolor: options.textcolor,
501
+ size: options.size,
502
+ tooltip: options.tooltip,
503
+ price: location === 'absolute' ? v : undefined,
504
+ });
505
+ }
506
+ }
507
+ /** PineScript `plotshape()` — a marker on each bar where the condition holds. */
508
+ export function plotshape(condition, title, options = {}) {
509
+ emitMarkers('shape', condition, title, options);
510
+ }
511
+ /** PineScript `plotchar()` — a character marker on each bar where the condition holds. */
512
+ export function plotchar(condition, title, options = {}) {
513
+ emitMarkers('char', condition, title, options);
514
+ }
515
+ /**
516
+ * PineScript `plotarrow()` — an up arrow below the bar for a positive value, a down arrow above the bar for a
517
+ * negative value, nothing for 0 / na. The arrows go to `result.arrows` (value and color per bar), the declaration to
518
+ * `arrowConfig`; the renderer scales the height with the absolute value between minheight and maxheight.
519
+ */
520
+ export function plotarrow(series, title, options = {}) {
521
+ const c = collector();
522
+ const id = `arrow${c.arrowConfig.length}`;
523
+ const pick = (col, fallback, i) => col === undefined ? fallback : typeof col === 'string' ? col : col[i];
524
+ const colorup = typeof options.colorup === 'string' ? options.colorup : '#00FF00';
525
+ const colordown = typeof options.colordown === 'string' ? options.colordown : '#FF0000';
526
+ c.arrowConfig.push({
527
+ id,
528
+ title,
529
+ colorup,
530
+ colordown,
531
+ minheight: options.minheight ?? 5,
532
+ maxheight: options.maxheight ?? 100,
533
+ offset: options.offset,
534
+ display: options.display,
535
+ forceOverlay: options.force_overlay,
536
+ });
537
+ const values = series.toArray();
538
+ const b = bars();
539
+ const off = options.offset ?? 0;
540
+ for (let i = 0; i < b.length; i++) {
541
+ const v = values[i];
542
+ if (v === undefined || Number.isNaN(v) || v === 0)
543
+ continue;
544
+ const j = i + off;
545
+ if (j < 0 || j >= b.length)
546
+ continue;
547
+ const color = v > 0 ? pick(options.colorup, '#00FF00', i) : pick(options.colordown, '#FF0000', i);
548
+ if (color === undefined)
549
+ continue; // na color: no arrow
550
+ c.arrows.push({ time: b[j].time, id, value: v, color });
551
+ }
552
+ }
553
+ /** Shared emitter for bgcolor()/barcolor(). A static color applies to every
554
+ * bar; a per-bar array (from color.when) skips undefined entries. The offset
555
+ * is baked in: the color computed at bar i lands on bar i + offset. */
556
+ function emitBarColors(kind, colors, options) {
557
+ const c = collector();
558
+ const id = `${kind}${c.barColorConfig.filter((x) => x.kind === kind).length}`;
559
+ c.barColorConfig.push({ id, kind, title: options.title, offset: options.offset, forceOverlay: options.force_overlay });
560
+ const b = bars();
561
+ const off = options.offset ?? 0;
562
+ const target = kind === 'bgcolor' ? c.bgcolors : c.barcolors;
563
+ for (let i = 0; i < b.length; i++) {
564
+ const col = typeof colors === 'string' ? colors : colors[i];
565
+ if (!col)
566
+ continue;
567
+ const j = i + off;
568
+ if (j < 0 || j >= b.length)
569
+ continue;
570
+ target.push({ time: b[j].time, color: col });
571
+ }
572
+ }
573
+ /**
574
+ * PineScript `bgcolor()` — per-bar background color. `force_overlay: true` colors the main chart pane even when the
575
+ * script is not an overlay.
576
+ */
577
+ export function bgcolor(colors, options = {}) {
578
+ emitBarColors('bgcolor', colors, options);
579
+ }
580
+ /** PineScript `barcolor()` — per-bar candle color override. */
581
+ export function barcolor(colors, options = {}) {
582
+ emitBarColors('barcolor', colors, options);
583
+ }
584
+ /**
585
+ * Runs the callback once per bar, in order, and collects the returned values
586
+ * into a Series. This is the escape hatch for PineScript logic the vectorized
587
+ * model cannot express:
588
+ *
589
+ * - `var x = 0` / `x := ...` → a plain `let` variable captured by the closure
590
+ * - per-bar `if` / `for` / `while` → native JS statements
591
+ * - `src[k]` → `c.get(src, k)`; self-reference → `c.prev()`
592
+ *
593
+ * Returning a boolean collects 1/0; returning nothing collects na (NaN).
594
+ *
595
+ * ```typescript
596
+ * let dir = 0; // var dir = 0
597
+ * const trend = eachBar((c) => {
598
+ * if (c.close > c.get(close, 1)) dir = 1; // dir := 1
599
+ * else if (c.close < c.get(close, 1)) dir = -1;
600
+ * return dir;
601
+ * });
602
+ * ```
603
+ */
604
+ export function eachBar(fn) {
605
+ collector(); // same lifecycle guard (and error message) as the declaration calls
606
+ const b = bars();
607
+ const out = new Array(b.length).fill(NaN);
608
+ const cache = new Map();
609
+ let idx = 0;
610
+ const ctx = {
611
+ get i() {
612
+ return idx;
613
+ },
614
+ n: b.length,
615
+ get time() {
616
+ return b[idx].time;
617
+ },
618
+ get open() {
619
+ return b[idx].open;
620
+ },
621
+ get high() {
622
+ return b[idx].high;
623
+ },
624
+ get low() {
625
+ return b[idx].low;
626
+ },
627
+ get close() {
628
+ return b[idx].close;
629
+ },
630
+ get volume() {
631
+ return b[idx].volume ?? NaN;
632
+ },
633
+ get(src, offset = 0) {
634
+ if (offset < 0)
635
+ throw new RangeError(`c.get(): the offset cannot be negative (${offset} would read a future bar).`);
636
+ let vals = cache.get(src);
637
+ if (!vals) {
638
+ vals = src.toArray();
639
+ cache.set(src, vals);
640
+ }
641
+ const j = idx - offset;
642
+ return j >= 0 && j < vals.length ? (vals[j] ?? NaN) : NaN;
643
+ },
644
+ prev(offset = 1) {
645
+ const j = idx - Math.max(1, offset);
646
+ return j >= 0 ? out[j] : NaN;
647
+ },
648
+ };
649
+ try {
650
+ for (idx = 0; idx < b.length; idx++) {
651
+ currentBar = idx;
652
+ const r = fn(ctx);
653
+ out[idx] = typeof r === 'number' ? r : typeof r === 'boolean' ? (r ? 1 : 0) : NaN;
654
+ }
655
+ }
656
+ finally {
657
+ currentBar = -1;
658
+ }
659
+ return Series.fromArray(ctxBars, out);
660
+ }
661
+ /** Bar index of the running eachBar() callback, -1 outside eachBar(). */
662
+ let currentBar = -1;
663
+ // ── Strategy (declaration and strategy.* API; the host supplies the order engine) ──
664
+ /** The strategy of the current run; throws when the script did not declare strategy(). */
665
+ function strategyRun(caller) {
666
+ const run = collector().strategy;
667
+ if (!run)
668
+ throw new Error(`${caller}: declare the script with strategy() first.`);
669
+ return run;
670
+ }
671
+ function strategyEngine(caller) {
672
+ const run = strategyRun(caller);
673
+ if (!run.engine) {
674
+ throw new Error(`${caller}: no strategy engine; pass it as executeScript(body, bars, inputs, chart, { strategyEngine }).`);
675
+ }
676
+ return run.engine;
677
+ }
678
+ /** The engine for an order call: order calls run inside strategy.eachBar(), at a bar close. */
679
+ function orderEngine(caller) {
680
+ const engine = strategyEngine(caller);
681
+ if (!strategyRun(caller).inLoop)
682
+ throw new Error(`${caller} must be called inside strategy.eachBar().`);
683
+ return engine;
684
+ }
685
+ /** Options without na (NaN) numbers and undefined values: in PineScript an na argument means "not given". */
686
+ function given(options) {
687
+ const out = {};
688
+ for (const [key, value] of Object.entries(options)) {
689
+ if (value === undefined || (typeof value === 'number' && Number.isNaN(value)))
690
+ continue;
691
+ out[key] = value;
692
+ }
693
+ return out;
694
+ }
695
+ /** The engine for a `strategy.*` read: the values are per bar, so they are read inside strategy.eachBar(). */
696
+ function readEngine(caller) {
697
+ const engine = strategyEngine(caller);
698
+ if (!strategyRun(caller).inLoop)
699
+ throw new Error(`${caller} must be read inside strategy.eachBar().`);
700
+ return engine;
701
+ }
702
+ /** `strategy.*` variables that do not change from bar to bar, readable anywhere in the script. */
703
+ const STRATEGY_CONSTANT_VARIABLES = new Set(['initial_capital', 'account_currency']);
704
+ function strategyVariable(name) {
705
+ const caller = `strategy.${name}`;
706
+ const engine = STRATEGY_CONSTANT_VARIABLES.has(name) ? strategyEngine(caller) : readEngine(caller);
707
+ const value = engine.get(name);
708
+ if (value === undefined)
709
+ throw new Error(`strategy.${name} is not provided by the strategy engine.`);
710
+ return value;
711
+ }
712
+ function riskRule(rule) {
713
+ const engine = strategyEngine(`strategy.risk.${rule.rule}()`);
714
+ if (!engine.risk)
715
+ throw new Error(`strategy.risk.${rule.rule}() is not provided by the strategy engine.`);
716
+ engine.risk(rule);
717
+ }
718
+ /** PineScript `strategy()` declaration: script metadata and strategy properties. */
719
+ function declareStrategy(title, options = {}) {
720
+ const c = collector();
721
+ declare(c, 'strategy');
722
+ c.title = title;
723
+ c.shortTitle = options.shorttitle;
724
+ c.overlay = options.overlay ?? false;
725
+ c.precision = options.precision;
726
+ c.format = options.format;
727
+ setDrawingLimits({
728
+ line: options.max_lines_count,
729
+ label: options.max_labels_count,
730
+ box: options.max_boxes_count,
731
+ polyline: options.max_polylines_count,
732
+ });
733
+ const properties = { ...STRATEGY_DEFAULTS };
734
+ const target = properties;
735
+ for (const key of [...Object.keys(STRATEGY_DEFAULTS), 'currency']) {
736
+ const value = options[key];
737
+ if (value !== undefined)
738
+ target[key] = value;
739
+ }
740
+ const factory = scriptOptions.strategyEngine;
741
+ c.strategy = {
742
+ properties,
743
+ engine: factory?.({ properties, bars: ctxBars.bars, chart: chartCtx }),
744
+ looped: false,
745
+ inLoop: false,
746
+ };
747
+ }
748
+ /**
749
+ * Runs the strategy logic once per bar, in order, like {@link eachBar}. On each bar the engine first
750
+ * fills the pending orders (`processBar`), then the callback runs at the bar close (order calls,
751
+ * `strategy.*` variables), then `processClose` runs. A script has one strategy.eachBar() per run.
752
+ * The callback's return values are collected into a Series, as with eachBar().
753
+ */
754
+ function strategyEachBar(fn) {
755
+ const run = strategyRun('strategy.eachBar()');
756
+ const engine = strategyEngine('strategy.eachBar()');
757
+ if (run.looped)
758
+ throw new Error('strategy.eachBar() runs once per script run.');
759
+ run.looped = true;
760
+ return eachBar((c) => {
761
+ engine.processBar(c.i);
762
+ run.inLoop = true;
763
+ try {
764
+ return fn(c);
765
+ }
766
+ finally {
767
+ run.inLoop = false;
768
+ engine.processClose(c.i);
769
+ }
770
+ });
771
+ }
772
+ const strategyMembers = {
773
+ ...STRATEGY_CONSTANTS,
774
+ eachBar: strategyEachBar,
775
+ entry(id, direction, options = {}) {
776
+ orderEngine('strategy.entry()').entry(id, direction, given(options));
777
+ },
778
+ order(id, direction, options = {}) {
779
+ orderEngine('strategy.order()').order(id, direction, given(options));
780
+ },
781
+ exit(id, options = {}) {
782
+ orderEngine('strategy.exit()').exit(id, given(options));
783
+ },
784
+ close(id, options = {}) {
785
+ orderEngine('strategy.close()').close(id, given(options));
786
+ },
787
+ close_all(options = {}) {
788
+ orderEngine('strategy.close_all()').close_all(given(options));
789
+ },
790
+ cancel(id) {
791
+ orderEngine('strategy.cancel()').cancel(id);
792
+ },
793
+ cancel_all() {
794
+ orderEngine('strategy.cancel_all()').cancel_all();
795
+ },
796
+ opentrade(index) {
797
+ return readEngine('strategy.opentrade()').openTrade(index);
798
+ },
799
+ closedtrade(index) {
800
+ return readEngine('strategy.closedtrade()').closedTrade(index);
801
+ },
802
+ default_entry_qty(fill_price) {
803
+ const engine = readEngine('strategy.default_entry_qty()');
804
+ if (!engine.defaultEntryQty)
805
+ throw new Error('strategy.default_entry_qty() is not provided by the strategy engine.');
806
+ return engine.defaultEntryQty(fill_price);
807
+ },
808
+ risk: {
809
+ allow_entry_in: (direction) => riskRule({ rule: 'allow_entry_in', direction }),
810
+ max_cons_loss_days: (count, alert_message) => riskRule(given({ rule: 'max_cons_loss_days', count, alert_message })),
811
+ max_drawdown: (value, type, alert_message) => riskRule(given({ rule: 'max_drawdown', value, type, alert_message })),
812
+ max_intraday_filled_orders: (count, alert_message) => riskRule(given({ rule: 'max_intraday_filled_orders', count, alert_message })),
813
+ max_intraday_loss: (value, type, alert_message) => riskRule(given({ rule: 'max_intraday_loss', value, type, alert_message })),
814
+ max_position_size: (contracts) => riskRule({ rule: 'max_position_size', contracts }),
815
+ },
816
+ };
817
+ const variableGetters = {};
818
+ for (const name of [...STRATEGY_NUMBER_VARIABLES, ...STRATEGY_TEXT_VARIABLES]) {
819
+ variableGetters[name] = { get: () => strategyVariable(name), enumerable: true };
820
+ }
821
+ /**
822
+ * PineScript `strategy`: call it to declare a strategy, and use its members as the `strategy.*` namespace.
823
+ * OakScriptJS does not fill orders: the host passes an engine in `executeScript(..., { strategyEngine })`,
824
+ * and the order calls and `strategy.*` variables are forwarded to it.
825
+ *
826
+ * ```typescript
827
+ * strategy('MA Cross', { initial_capital: 10000, default_qty_type: strategy.percent_of_equity, default_qty_value: 100 });
828
+ * const up = ta.crossover(ta.sma(close, 9), ta.sma(close, 21));
829
+ * strategy.eachBar((c) => {
830
+ * if (c.get(up) && strategy.position_size === 0) {
831
+ * strategy.entry('L', strategy.long);
832
+ * strategy.exit('X', { from_entry: 'L', stop: c.close * 0.95, limit: c.close * 1.15 });
833
+ * }
834
+ * });
835
+ * ```
836
+ */
837
+ export const strategy = Object.defineProperties(Object.assign((title, options) => declareStrategy(title, options), strategyMembers), variableGetters);
838
+ let chartCtx = {};
839
+ function chartTimeframe() {
840
+ collector();
841
+ if (!chartCtx.timeframe) {
842
+ throw new Error('The chart timeframe is not known: pass it as executeScript(body, bars, inputs, { timeframe }).');
843
+ }
844
+ return timeframeCore.info(chartCtx.timeframe);
845
+ }
846
+ function exchangeTimezone() {
847
+ collector();
848
+ if (!chartCtx.timezone) {
849
+ throw new Error('The exchange time zone is not known: pass it as executeScript(body, bars, inputs, { timezone }).');
850
+ }
851
+ return chartCtx.timezone;
852
+ }
853
+ /**
854
+ * PineScript `timeframe.*`: the chart timeframe variables (from the chart context), and
855
+ * `in_seconds(timeframe?)`, `from_seconds(seconds)`.
856
+ */
857
+ export const timeframe = {
858
+ ...timeframeCore,
859
+ get period() {
860
+ return chartTimeframe().period;
861
+ },
862
+ get main_period() {
863
+ return chartTimeframe().period;
864
+ },
865
+ get multiplier() {
866
+ return chartTimeframe().multiplier;
867
+ },
868
+ get isintraday() {
869
+ return chartTimeframe().isintraday;
870
+ },
871
+ get isdaily() {
872
+ return chartTimeframe().isdaily;
873
+ },
874
+ get isweekly() {
875
+ return chartTimeframe().isweekly;
876
+ },
877
+ get ismonthly() {
878
+ return chartTimeframe().ismonthly;
879
+ },
880
+ get isminutes() {
881
+ return chartTimeframe().isminutes;
882
+ },
883
+ get isseconds() {
884
+ return chartTimeframe().isseconds;
885
+ },
886
+ get isticks() {
887
+ return chartTimeframe().isticks;
888
+ },
889
+ get isdwm() {
890
+ return chartTimeframe().isdwm;
891
+ },
892
+ /** PineScript `timeframe.change(tf)`: 1 on bars that open a new `tf` period (0 on the first bar). */
893
+ change(tf) {
894
+ return changeOf(tf || chartTimeframe().period);
895
+ },
896
+ /** Seconds in `timeframe`; without it (or with "") the chart timeframe, as in PineScript. */
897
+ in_seconds(tf) {
898
+ return timeframeCore.in_seconds(tf === undefined || tf === '' ? chartTimeframe().period : tf);
899
+ },
900
+ };
901
+ /** A symbol property that the host passes in the chart context. */
902
+ function symbolProperty(key) {
903
+ collector();
904
+ const value = chartCtx[key];
905
+ if (value === undefined) {
906
+ throw new Error(`syminfo.${key} is not known: pass it as executeScript(body, bars, inputs, { ${key} }).`);
907
+ }
908
+ return value;
909
+ }
910
+ /**
911
+ * PineScript `syminfo.timezone`, `syminfo.tickerid`, `syminfo.session` (session type), `syminfo.mintick`,
912
+ * `syminfo.pointvalue` and `syminfo.mincontract`, from the chart context.
913
+ */
914
+ export const syminfo = {
915
+ get mintick() {
916
+ return symbolProperty('mintick');
917
+ },
918
+ get pointvalue() {
919
+ return symbolProperty('pointvalue');
920
+ },
921
+ get mincontract() {
922
+ return symbolProperty('mincontract');
923
+ },
924
+ get timezone() {
925
+ return exchangeTimezone();
926
+ },
927
+ get tickerid() {
928
+ collector();
929
+ if (!chartCtx.tickerid) {
930
+ throw new Error('The chart symbol is not known: pass it as executeScript(body, bars, inputs, { tickerid }).');
931
+ }
932
+ return chartCtx.tickerid;
933
+ },
934
+ get session() {
935
+ collector();
936
+ return chartCtx.sessionType ?? 'regular';
937
+ },
938
+ };
939
+ function calendar(fn) {
940
+ return ((time, timezone) => {
941
+ const tz = timezone ?? exchangeTimezone();
942
+ return time instanceof Series ? Series.fromArray(ctxBars, time.toArray().map((t) => fn(t, tz))) : fn(time, tz);
943
+ });
944
+ }
945
+ /** PineScript `year(time, timezone?)`; the default time zone is the exchange time zone. */
946
+ export const year = calendar(timeCore.year);
947
+ /** PineScript `month(time, timezone?)`; the default time zone is the exchange time zone. */
948
+ export const month = calendar(timeCore.month);
949
+ /** PineScript `weekofyear(time, timezone?)`; the default time zone is the exchange time zone. */
950
+ export const weekofyear = calendar(timeCore.weekofyear);
951
+ /** PineScript `dayofmonth(time, timezone?)`; the default time zone is the exchange time zone. */
952
+ export const dayofmonth = calendar(timeCore.dayofmonth);
953
+ /** PineScript `dayofweek(time, timezone?)`; the default time zone is the exchange time zone. */
954
+ export const dayofweek = calendar(timeCore.dayofweek);
955
+ /** PineScript `hour(time, timezone?)`; the default time zone is the exchange time zone. */
956
+ export const hour = calendar(timeCore.hour);
957
+ /** PineScript `minute(time, timezone?)`; the default time zone is the exchange time zone. */
958
+ export const minute = calendar(timeCore.minute);
959
+ /** PineScript `second(time, timezone?)`; the default time zone is the exchange time zone. */
960
+ export const second = calendar(timeCore.second);
961
+ export function timestamp(first, ...rest) {
962
+ if (typeof first === 'number') {
963
+ const [m, d, h, mi, s] = rest;
964
+ return timeCore.timestamp(exchangeTimezone(), first, m, d, h, mi, s);
965
+ }
966
+ if (rest.length === 0)
967
+ return timeCore.timestamp(first);
968
+ const [y, m, d, h, mi, s] = rest;
969
+ return timeCore.timestamp(first, y, m, d, h, mi, s);
970
+ }
971
+ /** Session test of PineScript `time(timeframe, session, timezone)`; the default time zone is the exchange time zone. */
972
+ export function inSession(time, session, timezone) {
973
+ return timeCore.inSession(time, session, timezone ?? exchangeTimezone());
974
+ }
975
+ /** PineScript `str.*`; `format_time` and the dates of `format` use the exchange time zone by default. */
976
+ export const str = {
977
+ ...strCore,
978
+ format_time(time, format = "yyyy-MM-dd'T'HH:mm:ssZ", timezone) {
979
+ return strCore.format_time(time, format, timezone ?? exchangeTimezone());
980
+ },
981
+ format(pattern, ...args) {
982
+ return formatMessage(pattern, args, exchangeTimezone);
983
+ },
984
+ };
985
+ // ── Session values (issue #100) ──────────────────────────────────────────────
986
+ /** Bar time in ms (PineScript `time`). */
987
+ function barTime(bar) {
988
+ return bar.time * (chartCtx.timeUnit === 'ms' ? 1 : 1000);
989
+ }
990
+ const toSpec = (s) => (typeof s === 'string' ? { session: s } : s);
991
+ let sessionCache = null;
992
+ /** Session calendars of the run (loaded bars and regular hours), built from the chart context. */
993
+ function sessionBars() {
994
+ const tz = exchangeTimezone();
995
+ const tf = chartTimeframe().period;
996
+ if (!chartCtx.session) {
997
+ throw new Error('The session is not known: pass it as executeScript(body, bars, inputs, { session }).');
998
+ }
999
+ if (sessionCache?.ctx !== chartCtx) {
1000
+ const loaded = toSpec(chartCtx.session);
1001
+ const regular = chartCtx.regularSession ? toSpec(chartCtx.regularSession) : loaded;
1002
+ sessionCache = {
1003
+ ctx: chartCtx,
1004
+ bars: new SessionBars(new TradingCalendar(tz, loaded), tf),
1005
+ regular: new SessionBars(new TradingCalendar(tz, { holidays: loaded.holidays, ...regular }), tf),
1006
+ };
1007
+ }
1008
+ return sessionCache;
1009
+ }
1010
+ /**
1011
+ * Calendar for `time(tf, session, timezone)` arguments. Without session and time zone: the loaded
1012
+ * session. As in PineScript, an explicit time zone reads the symbol session hours in that zone without
1013
+ * corrections and holidays, and an explicit session follows PineScript's session string rules.
1014
+ */
1015
+ function calendarFor(session, timezone) {
1016
+ const { bars } = sessionBars();
1017
+ if (!session && !timezone)
1018
+ return { bars, test: false };
1019
+ const tz = timezone ?? exchangeTimezone();
1020
+ const spec = session ? { session } : { session: toSpec(chartCtx.session).session };
1021
+ return { bars: new SessionBars(new TradingCalendar(tz, spec, session ? 'pine' : 'symbol'), bars.chart.period), test: true };
1022
+ }
1023
+ function perBar(fn) {
1024
+ const times = ctxBars.bars.map(barTime);
1025
+ return Series.fromArray(ctxBars, times.map((t, i) => fn(t, i, times)));
1026
+ }
1027
+ /** A Series that can also be called, like PineScript's `time` (variable) and `time(...)` (function). */
1028
+ function callableSeries(series, fn) {
1029
+ Object.setPrototypeOf(fn, Series.prototype);
1030
+ Object.assign(fn, series);
1031
+ return fn;
1032
+ }
1033
+ function timeFunction(tf, session, timezone) {
1034
+ collector();
1035
+ const { bars, test } = calendarFor(session, timezone);
1036
+ const timeframeString = tf || chartTimeframe().period;
1037
+ return perBar((t) => (test && !bars.inside(t) ? NaN : bars.timeOf(t, timeframeString)));
1038
+ }
1039
+ function timeCloseFunction(tf, session, timezone) {
1040
+ collector();
1041
+ const { bars, test } = calendarFor(session, timezone);
1042
+ const timeframeString = tf || chartTimeframe().period;
1043
+ return perBar((t) => (test && !bars.inside(t) ? NaN : bars.closeOf(t, timeframeString)));
1044
+ }
1045
+ /**
1046
+ * PineScript `time`: the bar open time in ms (a Series), and `time(timeframe?, session?, timezone?)`:
1047
+ * the open time of the `timeframe` period that contains the bar, `na` outside `session`.
1048
+ */
1049
+ export const time = callableSeries(new Series(ctxBars, (b) => barTime(b)), timeFunction);
1050
+ /**
1051
+ * PineScript `time_close`: the bar close time in ms (a Series), and `time_close(timeframe?, session?, timezone?)`.
1052
+ * Needs the chart timeframe and session.
1053
+ */
1054
+ export const time_close = callableSeries(new Series(ctxBars, (_b, i) => sessionBars().bars.closeOf(barTime(ctxBars.bars[i]), chartTimeframe().period)), timeCloseFunction);
1055
+ /** PineScript `time_tradingday`: 00:00 UTC of the trading day of each bar, in ms. */
1056
+ export const time_tradingday = new Series(ctxBars, (b) => sessionBars().bars.tradingDayTime(barTime(b)));
1057
+ function changeOf(tf) {
1058
+ const { bars } = sessionBars();
1059
+ return perBar((t, i, times) => (i > 0 && bars.timeOf(t, tf) !== bars.timeOf(times[i - 1], tf) ? 1 : 0));
1060
+ }
1061
+ function flag(key) {
1062
+ const { bars, regular } = sessionBars();
1063
+ const values = sessionFlags(ctxBars.bars.map(barTime), bars, regular)[key];
1064
+ return Series.fromArray(ctxBars, values.map((v) => (v ? 1 : 0)));
1065
+ }
1066
+ /** A 1 / 0 Series from a per-bar test on the bar index and the number of bars. */
1067
+ function barFlag(test) {
1068
+ const n = ctxBars.bars.length;
1069
+ return Series.fromArray(ctxBars, Array.from({ length: n }, (_, i) => (test(i, n) ? 1 : 0)));
1070
+ }
1071
+ const lastRealtime = (i, n) => i === n - 1 && chartCtx.realtime === true;
1072
+ /**
1073
+ * PineScript `barstate.*` (1 / 0 per bar). All bars but the last are confirmed history bars. The last bar is
1074
+ * confirmed only when the host says so (`ChartContext.lastBarConfirmed`, e.g. the closing update of a realtime
1075
+ * bar), and is a realtime bar only when it receives live updates (`ChartContext.realtime`); without live updates
1076
+ * it is a history bar, as in PineScript.
1077
+ * `islastconfirmedhistory` is the last bar when it is confirmed and not realtime, else the bar before it.
1078
+ */
1079
+ export const barstate = {
1080
+ get isfirst() { return barFlag((i) => i === 0); },
1081
+ get islast() { return barFlag((i, n) => i === n - 1); },
1082
+ get isconfirmed() { return barFlag((i, n) => i < n - 1 || chartCtx.lastBarConfirmed === true); },
1083
+ get isrealtime() { return barFlag(lastRealtime); },
1084
+ get ishistory() { return barFlag((i, n) => !lastRealtime(i, n)); },
1085
+ get isnew() { return barFlag((i, n) => !lastRealtime(i, n) || chartCtx.lastBarNew !== false); },
1086
+ get islastconfirmedhistory() {
1087
+ return barFlag((i, n) => {
1088
+ const lastConfirmed = chartCtx.lastBarConfirmed === true && chartCtx.realtime !== true;
1089
+ return i === (lastConfirmed ? n - 1 : n - 2);
1090
+ });
1091
+ },
1092
+ };
1093
+ /**
1094
+ * PineScript `session.*` (1 / 0 per bar) and the constants `session.regular` / `session.extended`.
1095
+ * First and last bars are per session period; market / pre / post market use the regular hours.
1096
+ */
1097
+ export const session = {
1098
+ regular: 'regular',
1099
+ extended: 'extended',
1100
+ get isfirstbar() { return flag('isfirstbar'); },
1101
+ get islastbar() { return flag('islastbar'); },
1102
+ get ismarket() { return flag('ismarket'); },
1103
+ get ispremarket() { return flag('ispremarket'); },
1104
+ get ispostmarket() { return flag('ispostmarket'); },
1105
+ get isfirstbar_regular() { return flag('isfirstbar_regular'); },
1106
+ get islastbar_regular() { return flag('islastbar_regular'); },
1107
+ };
1108
+ // ── request.security (issue #101) ─────────────────────────────────────────────
1109
+ /** PineScript `barmerge.*` constants of `request.security`. */
1110
+ export const barmerge = {
1111
+ gaps_on: 'gaps_on',
1112
+ gaps_off: 'gaps_off',
1113
+ lookahead_on: 'lookahead_on',
1114
+ lookahead_off: 'lookahead_off',
1115
+ };
1116
+ const HEIKIN_ASHI = 'heikinashi:';
1117
+ /** PineScript `ticker.heikinashi(symbol)` / `ticker.standard(symbol)` for the chart symbol. */
1118
+ export const ticker = {
1119
+ heikinashi(symbol) {
1120
+ return HEIKIN_ASHI + symbol;
1121
+ },
1122
+ standard(symbol) {
1123
+ return symbol.startsWith(HEIKIN_ASHI) ? symbol.slice(HEIKIN_ASHI.length) : symbol;
1124
+ },
1125
+ };
1126
+ function valuesOf(value, length) {
1127
+ if (!(value instanceof Series))
1128
+ return new Array(length).fill(Number(value));
1129
+ if (value.bars !== ctxBars.bars) {
1130
+ throw new Error('request.security(): the expression returned a series computed on the chart bars. ' +
1131
+ 'Compute the series inside the expression, e.g. () => ta.ema(close, 10).');
1132
+ }
1133
+ return value.toArray().slice();
1134
+ }
1135
+ /**
1136
+ * PineScript `request.security` for the chart symbol (`syminfo.tickerid`, `""`, `ticker.heikinashi(...)`,
1137
+ * `ticker.standard(...)`) and a timeframe equal to or higher than the chart's. The higher-timeframe bars are
1138
+ * built by grouping the chart bars, and `expression` runs on them (its `ta.*` calls, tuples and `timeframe.*`
1139
+ * see the higher timeframe). Other symbols need external data and throw; a lower timeframe throws.
1140
+ *
1141
+ * PineScript rules: lookahead off shows a period's value from the
1142
+ * bar that completes it; lookahead on from its first bar; gaps on keeps only the bar where the value appears.
1143
+ * Built bars can differ from the exchange's bars (official open / close, volume).
1144
+ */
1145
+ function security(symbol, timeframe, expression, gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off) {
1146
+ collector();
1147
+ const heikin = symbol.startsWith(HEIKIN_ASHI);
1148
+ const base = heikin ? symbol.slice(HEIKIN_ASHI.length) : symbol;
1149
+ if (base !== '' && base !== chartCtx.tickerid) {
1150
+ throw new Error(`request.security: "${symbol}" is not the chart symbol; other symbols need external data.`);
1151
+ }
1152
+ const chart = chartTimeframe();
1153
+ const tf = timeframeCore.info(timeframe || chart.period).period;
1154
+ if (timeframeCore.in_seconds(tf) < timeframeCore.in_seconds(chart.period)) {
1155
+ throw new Error(`request.security: timeframe "${tf}" is lower than the chart timeframe "${chart.period}".`);
1156
+ }
1157
+ const chartBars = ctxBars.bars;
1158
+ const times = chartBars.map(barTime);
1159
+ let htf;
1160
+ let group;
1161
+ let latest;
1162
+ if (tf === chart.period) {
1163
+ htf = chartBars;
1164
+ group = chartBars.map((_, i) => i);
1165
+ latest = group;
1166
+ }
1167
+ else {
1168
+ const { bars: loaded, regular } = sessionBars();
1169
+ // D / W / M periods follow the regular hours; intraday periods the loaded session
1170
+ const calendar = timeframeCore.info(tf).isdwm ? regular : loaded;
1171
+ const starts = times.map((t) => calendar.timeOf(t, tf));
1172
+ const dayPeriods = times.map((t, i) => {
1173
+ const at = loaded.calendar.locate(t);
1174
+ const periods = at ? calendar.calendar.periods(at.date) : [];
1175
+ return periods.length ? calendar.timeOf(periods[0][0], tf) : starts[i];
1176
+ });
1177
+ const reaches = times.map((t) => loaded.closeOf(t, chart.period) >= calendar.periodEnd(t, tf));
1178
+ ({ group, latest } = periodsOf(starts, dayPeriods, reaches));
1179
+ const unit = chartCtx.timeUnit === 'ms' ? 1 : 1000;
1180
+ // a higher-timeframe bar ends at the bar that completes it (no value from after the completion)
1181
+ const after = afterCompletion(group, latest);
1182
+ const kept = (_, i) => !after[i];
1183
+ htf = resample(chartBars.filter(kept), starts.map((s) => s / unit).filter(kept)).bars;
1184
+ }
1185
+ if (heikin)
1186
+ htf = heikinAshi(htf);
1187
+ const savedCtx = chartCtx;
1188
+ let result;
1189
+ let values;
1190
+ ctxBars.setAll(htf);
1191
+ chartCtx = { ...chartCtx, timeframe: tf };
1192
+ try {
1193
+ result = expression();
1194
+ const parts = Array.isArray(result) ? result : [result];
1195
+ values = parts.map((p) => valuesOf(p, htf.length));
1196
+ }
1197
+ finally {
1198
+ ctxBars.setAll(chartBars);
1199
+ chartCtx = savedCtx;
1200
+ }
1201
+ const mapped = values.map((v) => Series.fromArray(ctxBars, mapToChart(v, group, latest, lookahead === barmerge.lookahead_on, gaps === barmerge.gaps_on)));
1202
+ return (Array.isArray(result) ? mapped : mapped[0]);
1203
+ }
1204
+ /** PineScript `request.*`: `security` for the chart symbol (issue #101). */
1205
+ export const request = { security };
1206
+ // ── Drawing objects ──────────────────────────────────────────────────────────
1207
+ // The drawing namespaces come from this bundle so that they share the registry that
1208
+ // executeScript() resets. `line.all` etc. are read like PineScript variables.
1209
+ /** PineScript `line.*`; `line.all` lists the live lines in creation order. */
1210
+ export const line = {
1211
+ ...lineCore,
1212
+ get all() {
1213
+ return lineCore.all();
1214
+ },
1215
+ };
1216
+ /** PineScript `label.*`; `label.all` lists the live labels in creation order. */
1217
+ export const label = {
1218
+ ...labelCore,
1219
+ get all() {
1220
+ return labelCore.all();
1221
+ },
1222
+ };
1223
+ /** PineScript `box.*`; `box.all` lists the live boxes in creation order. */
1224
+ export const box = {
1225
+ ...boxCore,
1226
+ get all() {
1227
+ return boxCore.all();
1228
+ },
1229
+ };
1230
+ /** PineScript `linefill.*`; `linefill.all` lists the live linefills in creation order. */
1231
+ export const linefill = {
1232
+ ...linefillCore,
1233
+ get all() {
1234
+ return linefillCore.all();
1235
+ },
1236
+ };
1237
+ /** PineScript `polyline.*`; `polyline.all` lists the live polylines in creation order. */
1238
+ export const polyline = {
1239
+ ...polylineCore,
1240
+ get all() {
1241
+ return polylineCore.all();
1242
+ },
1243
+ };
1244
+ /** PineScript `text.format_*` constants. */
1245
+ export const text = { ...textCore };
1246
+ /**
1247
+ * PineScript `chart.point.*`. `chart.point.now(price?)` is the point of the current bar
1248
+ * (index, time, and `price`, default the close), so it runs inside eachBar().
1249
+ */
1250
+ export const chart = {
1251
+ point: {
1252
+ ...chartPointCore,
1253
+ now(price) {
1254
+ collector();
1255
+ if (currentBar < 0) {
1256
+ throw new Error('chart.point.now() needs a current bar: call it inside eachBar().');
1257
+ }
1258
+ const bar = ctxBars.bars[currentBar];
1259
+ return chartPointCore.new_point(barTime(bar), currentBar, price ?? bar.close);
1260
+ },
1261
+ },
1262
+ };
1263
+ /** Wraps a plain value array (e.g. a side output accumulated inside eachBar)
1264
+ * into a Series aligned with the current bars. */
1265
+ export function seriesOf(values) {
1266
+ collector();
1267
+ return Series.fromArray(ctxBars, values);
1268
+ }
1269
+ /** PineScript `alertcondition()` — collected for the host's alert engine. */
1270
+ export function alertcondition(condition, title, message) {
1271
+ const c = collector();
1272
+ const id = `alert${c.alertConfig.length}`;
1273
+ c.alertConfig.push({ id, title, message });
1274
+ const last = condition.length() ? condition.last() : NaN;
1275
+ c.alerts.push({ id, title, message, triggered: !isNA(last) && last !== 0 });
1276
+ }
1277
+ // ── Convenience re-exports ───────────────────────────────────────────────────
1278
+ export { Series, BarData, isNA as na, nz };
1279
+ export { STRATEGY_DEFAULTS } from '../strategy/index.js';
1280
+ /** PineScript `math.*`; `math.round_to_mintick(x)` uses `syminfo.mintick` of the chart context. */
1281
+ export const math = {
1282
+ ...mathCore,
1283
+ round_to_mintick: ((number, mintick) => {
1284
+ const tick = mintick ?? syminfo.mintick;
1285
+ return number instanceof Series ? mathCore.round_to_mintick(number, tick) : mathCore.round_to_mintick(number, tick);
1286
+ }),
1287
+ };
1288
+ export * as compare from '../compare/index.js';
1289
+ //# sourceMappingURL=index.js.map