oakscriptjs 0.9.5 → 0.10.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 (256) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/array/index.d.ts +93 -50
  3. package/dist/cjs/array/index.d.ts.map +1 -1
  4. package/dist/cjs/array/index.js +239 -78
  5. package/dist/cjs/array/index.js.map +3 -3
  6. package/dist/cjs/callsite/index.d.ts +81 -2
  7. package/dist/cjs/callsite/index.d.ts.map +1 -1
  8. package/dist/cjs/callsite/index.js +62 -1
  9. package/dist/cjs/callsite/index.js.map +2 -2
  10. package/dist/cjs/color/index.d.ts +7 -3
  11. package/dist/cjs/color/index.d.ts.map +1 -1
  12. package/dist/cjs/color/index.js +6 -1
  13. package/dist/cjs/color/index.js.map +2 -2
  14. package/dist/cjs/drawing/bar-time.d.ts +24 -0
  15. package/dist/cjs/drawing/bar-time.d.ts.map +1 -0
  16. package/dist/cjs/drawing/bar-time.js +47 -0
  17. package/dist/cjs/drawing/bar-time.js.map +7 -0
  18. package/dist/cjs/drawing/output.d.ts +32 -0
  19. package/dist/cjs/drawing/output.d.ts.map +1 -0
  20. package/dist/cjs/drawing/output.js +184 -0
  21. package/dist/cjs/drawing/output.js.map +7 -0
  22. package/dist/cjs/drawing/registry.d.ts +5 -4
  23. package/dist/cjs/drawing/registry.d.ts.map +1 -1
  24. package/dist/cjs/drawing/registry.js +11 -2
  25. package/dist/cjs/drawing/registry.js.map +2 -2
  26. package/dist/cjs/index.d.ts +6 -3
  27. package/dist/cjs/index.d.ts.map +1 -1
  28. package/dist/cjs/index.js +9 -2
  29. package/dist/cjs/index.js.map +2 -2
  30. package/dist/cjs/label/index.d.ts.map +1 -1
  31. package/dist/cjs/label/index.js +2 -1
  32. package/dist/cjs/label/index.js.map +2 -2
  33. package/dist/cjs/linefill/index.d.ts.map +1 -1
  34. package/dist/cjs/linefill/index.js +1 -0
  35. package/dist/cjs/linefill/index.js.map +2 -2
  36. package/dist/cjs/math/index.d.ts +76 -21
  37. package/dist/cjs/math/index.d.ts.map +1 -1
  38. package/dist/cjs/math/index.js +155 -41
  39. package/dist/cjs/math/index.js.map +3 -3
  40. package/dist/cjs/matrix/index.d.ts.map +1 -1
  41. package/dist/cjs/matrix/index.js +42 -36
  42. package/dist/cjs/matrix/index.js.map +2 -2
  43. package/dist/cjs/polyline/index.d.ts +3 -5
  44. package/dist/cjs/polyline/index.d.ts.map +1 -1
  45. package/dist/cjs/polyline/index.js +0 -5
  46. package/dist/cjs/polyline/index.js.map +2 -2
  47. package/dist/cjs/runtime/series.d.ts +9 -0
  48. package/dist/cjs/runtime/series.d.ts.map +1 -1
  49. package/dist/cjs/runtime/series.js +16 -2
  50. package/dist/cjs/runtime/series.js.map +2 -2
  51. package/dist/cjs/runtime/types.d.ts +22 -0
  52. package/dist/cjs/runtime/types.d.ts.map +1 -1
  53. package/dist/cjs/runtime/types.js.map +1 -1
  54. package/dist/cjs/script/index.d.ts +97 -36
  55. package/dist/cjs/script/index.d.ts.map +1 -1
  56. package/dist/cjs/script/index.js +173 -26
  57. package/dist/cjs/script/index.js.map +3 -3
  58. package/dist/cjs/session/calendar.d.ts.map +1 -1
  59. package/dist/cjs/session/calendar.js +15 -2
  60. package/dist/cjs/session/calendar.js.map +2 -2
  61. package/dist/cjs/str/index.d.ts +50 -38
  62. package/dist/cjs/str/index.d.ts.map +1 -1
  63. package/dist/cjs/str/index.js +43 -15
  64. package/dist/cjs/str/index.js.map +2 -2
  65. package/dist/cjs/str/messageformat.d.ts +2 -1
  66. package/dist/cjs/str/messageformat.d.ts.map +1 -1
  67. package/dist/cjs/str/messageformat.js +4 -1
  68. package/dist/cjs/str/messageformat.js.map +2 -2
  69. package/dist/cjs/str/numberformat.d.ts +4 -0
  70. package/dist/cjs/str/numberformat.d.ts.map +1 -1
  71. package/dist/cjs/str/numberformat.js +26 -4
  72. package/dist/cjs/str/numberformat.js.map +3 -3
  73. package/dist/cjs/ta/index.d.ts +86 -43
  74. package/dist/cjs/ta/index.d.ts.map +1 -1
  75. package/dist/cjs/ta/index.js +173 -267
  76. package/dist/cjs/ta/index.js.map +3 -3
  77. package/dist/cjs/ta/running-sum.d.ts +54 -2
  78. package/dist/cjs/ta/running-sum.d.ts.map +1 -1
  79. package/dist/cjs/ta/running-sum.js +132 -52
  80. package/dist/cjs/ta/running-sum.js.map +2 -2
  81. package/dist/cjs/ta-series.d.ts +4 -4
  82. package/dist/cjs/ta-series.d.ts.map +1 -1
  83. package/dist/cjs/ta-series.js +4 -3
  84. package/dist/cjs/ta-series.js.map +2 -2
  85. package/dist/cjs/table/index.d.ts +87 -0
  86. package/dist/cjs/table/index.d.ts.map +1 -0
  87. package/dist/cjs/table/index.js +150 -0
  88. package/dist/cjs/table/index.js.map +7 -0
  89. package/dist/cjs/text/index.d.ts +17 -2
  90. package/dist/cjs/text/index.d.ts.map +1 -1
  91. package/dist/cjs/text/index.js +15 -1
  92. package/dist/cjs/text/index.js.map +2 -2
  93. package/dist/cjs/time/datestring.d.ts +1 -0
  94. package/dist/cjs/time/datestring.d.ts.map +1 -1
  95. package/dist/cjs/time/datestring.js +7 -0
  96. package/dist/cjs/time/datestring.js.map +2 -2
  97. package/dist/cjs/time/index.d.ts.map +1 -1
  98. package/dist/cjs/time/index.js +2 -1
  99. package/dist/cjs/time/index.js.map +2 -2
  100. package/dist/cjs/time/session.d.ts +28 -9
  101. package/dist/cjs/time/session.d.ts.map +1 -1
  102. package/dist/cjs/time/session.js +74 -28
  103. package/dist/cjs/time/session.js.map +2 -2
  104. package/dist/cjs/time/timezone.d.ts +5 -0
  105. package/dist/cjs/time/timezone.d.ts.map +1 -1
  106. package/dist/cjs/time/timezone.js +15 -1
  107. package/dist/cjs/time/timezone.js.map +2 -2
  108. package/dist/cjs/types/index.d.ts +30 -1
  109. package/dist/cjs/types/index.d.ts.map +1 -1
  110. package/dist/cjs/types/index.js +12 -0
  111. package/dist/cjs/types/index.js.map +2 -2
  112. package/dist/cjs/types/metadata.d.ts +258 -26
  113. package/dist/cjs/types/metadata.d.ts.map +1 -1
  114. package/dist/cjs/types/metadata.js.map +1 -1
  115. package/dist/esm/array/index.d.ts +93 -50
  116. package/dist/esm/array/index.d.ts.map +1 -1
  117. package/dist/esm/array/index.js +383 -133
  118. package/dist/esm/array/index.js.map +1 -1
  119. package/dist/esm/callsite/index.d.ts +81 -2
  120. package/dist/esm/callsite/index.d.ts.map +1 -1
  121. package/dist/esm/callsite/index.js +145 -3
  122. package/dist/esm/callsite/index.js.map +1 -1
  123. package/dist/esm/color/index.d.ts +7 -3
  124. package/dist/esm/color/index.d.ts.map +1 -1
  125. package/dist/esm/color/index.js +15 -3
  126. package/dist/esm/color/index.js.map +1 -1
  127. package/dist/esm/drawing/bar-time.d.ts +24 -0
  128. package/dist/esm/drawing/bar-time.d.ts.map +1 -0
  129. package/dist/esm/drawing/bar-time.js +44 -0
  130. package/dist/esm/drawing/bar-time.js.map +1 -0
  131. package/dist/esm/drawing/output.d.ts +32 -0
  132. package/dist/esm/drawing/output.d.ts.map +1 -0
  133. package/dist/esm/drawing/output.js +190 -0
  134. package/dist/esm/drawing/output.js.map +1 -0
  135. package/dist/esm/drawing/registry.d.ts +5 -4
  136. package/dist/esm/drawing/registry.d.ts.map +1 -1
  137. package/dist/esm/drawing/registry.js +12 -2
  138. package/dist/esm/drawing/registry.js.map +1 -1
  139. package/dist/esm/index.d.ts +6 -3
  140. package/dist/esm/index.d.ts.map +1 -1
  141. package/dist/esm/index.js +7 -3
  142. package/dist/esm/index.js.map +1 -1
  143. package/dist/esm/label/index.d.ts.map +1 -1
  144. package/dist/esm/label/index.js +2 -1
  145. package/dist/esm/label/index.js.map +1 -1
  146. package/dist/esm/linefill/index.d.ts.map +1 -1
  147. package/dist/esm/linefill/index.js +3 -0
  148. package/dist/esm/linefill/index.js.map +1 -1
  149. package/dist/esm/math/index.d.ts +76 -21
  150. package/dist/esm/math/index.d.ts.map +1 -1
  151. package/dist/esm/math/index.js +227 -61
  152. package/dist/esm/math/index.js.map +1 -1
  153. package/dist/esm/matrix/index.d.ts.map +1 -1
  154. package/dist/esm/matrix/index.js +57 -43
  155. package/dist/esm/matrix/index.js.map +1 -1
  156. package/dist/esm/polyline/index.d.ts +3 -5
  157. package/dist/esm/polyline/index.d.ts.map +1 -1
  158. package/dist/esm/polyline/index.js +3 -9
  159. package/dist/esm/polyline/index.js.map +1 -1
  160. package/dist/esm/runtime/series.d.ts +9 -0
  161. package/dist/esm/runtime/series.d.ts.map +1 -1
  162. package/dist/esm/runtime/series.js +18 -1
  163. package/dist/esm/runtime/series.js.map +1 -1
  164. package/dist/esm/runtime/types.d.ts +22 -0
  165. package/dist/esm/runtime/types.d.ts.map +1 -1
  166. package/dist/esm/script/index.d.ts +97 -36
  167. package/dist/esm/script/index.d.ts.map +1 -1
  168. package/dist/esm/script/index.js +211 -22
  169. package/dist/esm/script/index.js.map +1 -1
  170. package/dist/esm/session/calendar.d.ts.map +1 -1
  171. package/dist/esm/session/calendar.js +22 -2
  172. package/dist/esm/session/calendar.js.map +1 -1
  173. package/dist/esm/str/index.d.ts +50 -38
  174. package/dist/esm/str/index.d.ts.map +1 -1
  175. package/dist/esm/str/index.js +103 -52
  176. package/dist/esm/str/index.js.map +1 -1
  177. package/dist/esm/str/messageformat.d.ts +2 -1
  178. package/dist/esm/str/messageformat.d.ts.map +1 -1
  179. package/dist/esm/str/messageformat.js +7 -2
  180. package/dist/esm/str/messageformat.js.map +1 -1
  181. package/dist/esm/str/numberformat.d.ts +4 -0
  182. package/dist/esm/str/numberformat.d.ts.map +1 -1
  183. package/dist/esm/str/numberformat.js +38 -4
  184. package/dist/esm/str/numberformat.js.map +1 -1
  185. package/dist/esm/ta/index.d.ts +86 -43
  186. package/dist/esm/ta/index.d.ts.map +1 -1
  187. package/dist/esm/ta/index.js +296 -348
  188. package/dist/esm/ta/index.js.map +1 -1
  189. package/dist/esm/ta/running-sum.d.ts +54 -2
  190. package/dist/esm/ta/running-sum.d.ts.map +1 -1
  191. package/dist/esm/ta/running-sum.js +166 -71
  192. package/dist/esm/ta/running-sum.js.map +1 -1
  193. package/dist/esm/ta-series.d.ts +4 -4
  194. package/dist/esm/ta-series.d.ts.map +1 -1
  195. package/dist/esm/ta-series.js +5 -4
  196. package/dist/esm/ta-series.js.map +1 -1
  197. package/dist/esm/table/index.d.ts +87 -0
  198. package/dist/esm/table/index.d.ts.map +1 -0
  199. package/dist/esm/table/index.js +169 -0
  200. package/dist/esm/table/index.js.map +1 -0
  201. package/dist/esm/text/index.d.ts +17 -2
  202. package/dist/esm/text/index.d.ts.map +1 -1
  203. package/dist/esm/text/index.js +17 -2
  204. package/dist/esm/text/index.js.map +1 -1
  205. package/dist/esm/time/datestring.d.ts +1 -0
  206. package/dist/esm/time/datestring.d.ts.map +1 -1
  207. package/dist/esm/time/datestring.js +12 -0
  208. package/dist/esm/time/datestring.js.map +1 -1
  209. package/dist/esm/time/index.d.ts.map +1 -1
  210. package/dist/esm/time/index.js +3 -1
  211. package/dist/esm/time/index.js.map +1 -1
  212. package/dist/esm/time/session.d.ts +28 -9
  213. package/dist/esm/time/session.d.ts.map +1 -1
  214. package/dist/esm/time/session.js +113 -42
  215. package/dist/esm/time/session.js.map +1 -1
  216. package/dist/esm/time/timezone.d.ts +5 -0
  217. package/dist/esm/time/timezone.d.ts.map +1 -1
  218. package/dist/esm/time/timezone.js +21 -1
  219. package/dist/esm/time/timezone.js.map +1 -1
  220. package/dist/esm/types/index.d.ts +30 -1
  221. package/dist/esm/types/index.d.ts.map +1 -1
  222. package/dist/esm/types/index.js +14 -0
  223. package/dist/esm/types/index.js.map +1 -1
  224. package/dist/esm/types/metadata.d.ts +258 -26
  225. package/dist/esm/types/metadata.d.ts.map +1 -1
  226. package/package.json +1 -1
  227. package/src/array/index.ts +364 -150
  228. package/src/callsite/index.ts +147 -3
  229. package/src/color/index.ts +15 -5
  230. package/src/drawing/bar-time.ts +42 -0
  231. package/src/drawing/output.ts +214 -0
  232. package/src/drawing/registry.ts +16 -6
  233. package/src/index.ts +9 -3
  234. package/src/label/index.ts +2 -1
  235. package/src/linefill/index.ts +2 -0
  236. package/src/math/index.ts +256 -74
  237. package/src/matrix/index.ts +52 -52
  238. package/src/polyline/index.ts +3 -12
  239. package/src/runtime/series.ts +22 -1
  240. package/src/runtime/types.ts +23 -0
  241. package/src/script/index.ts +307 -25
  242. package/src/session/calendar.ts +22 -2
  243. package/src/str/index.ts +95 -51
  244. package/src/str/messageformat.ts +7 -2
  245. package/src/str/numberformat.ts +39 -4
  246. package/src/ta/index.ts +306 -386
  247. package/src/ta/running-sum.ts +187 -74
  248. package/src/ta-series.ts +8 -7
  249. package/src/table/index.ts +221 -0
  250. package/src/text/index.ts +18 -2
  251. package/src/time/datestring.ts +10 -0
  252. package/src/time/index.ts +3 -1
  253. package/src/time/session.ts +97 -47
  254. package/src/time/timezone.ts +21 -1
  255. package/src/types/index.ts +32 -1
  256. package/src/types/metadata.ts +325 -26
@@ -8,9 +8,10 @@
8
8
  *
9
9
  * Known difference: `log10`, `exp`, `log`, `pow`, `sin`, `cos`, `tan` use JavaScript's `Math`. PineScript uses
10
10
  * other algorithms, whose results differ by 1 or 2 units in the last place on part of the inputs (`log10` about 4 %,
11
- * `exp` about 9 %, `sin` / `cos` / `tan` about 3 %, `log` 0.4 %, `pow` 0.05 % of random inputs). A constant argument
12
- * (`math.log10(2)`) can differ by up to 3 units in the last place. This is visible only when a script amplifies
13
- * these tiny differences (e.g. `ma > ma[1]` on values of 1e195); `sqrt`, `atan`, `asin`, `acos` are equal.
11
+ * `exp` about 9 %, `sin` / `cos` / `tan` about 3 %, `log` 0.4 %, `pow` 0.05 % of random inputs). This is visible
12
+ * only when a script amplifies these tiny differences (e.g. `ma > ma[1]` on values of 1e195); `sqrt`, `atan`,
13
+ * `asin`, `acos` are equal. A constant argument (`math.log10(2)`) is computed before the script runs, with other
14
+ * rules: see `constant`.
14
15
  *
15
16
  * @version 6
16
17
  */
@@ -90,20 +91,55 @@ export declare function floor(value: float): int;
90
91
  * @remarks
91
92
  * - Rounds to nearest integer by default
92
93
  * - With precision, rounds to that many decimal places
93
- * - Uses "round half up" strategy (0.5 rounds to 1)
94
94
  * - If value is a Series, returns a Series; if value is a number, returns a number
95
95
  *
96
+ * PineScript rules:
97
+ * - ties go away from zero (2.5 -> 3, -2.5 -> -3, -0.5 -> -1)
98
+ * - without a precision, or with a precision <= 0, the result is the integer rounding (1234.5678 @ -2 -> 1235)
99
+ * - a positive precision rounds only the fraction: `int + round(frac * scale) / scale` with
100
+ * `scale = 1 / 10^-precision` (precision above 16 acts as 16); the tie is decided on the exact value of
101
+ * `frac * scale` with a 1e-10 tolerance (1.005 @ 2 -> 1.01, 0.285 @ 2 -> 0.29, -1.45 @ 1 -> -1.5)
102
+ * - an infinite value gives na
103
+ *
96
104
  * @example
97
105
  * ```typescript
98
106
  * math.round(4.2) // Returns: 4
99
107
  * math.round(4.5) // Returns: 5
100
- * math.round(4.8) // Returns: 5
108
+ * math.round(-2.5) // Returns: -3
101
109
  * math.round(4.567, 2) // Returns: 4.57
102
- * math.round(4.567, 1) // Returns: 4.6
110
+ * math.round(1.005, 2) // Returns: 1.01
103
111
  * ```
104
112
  */
105
113
  export declare function round(value: Series, precision?: int): Series;
106
114
  export declare function round(value: float, precision?: int): float;
115
+ /**
116
+ * Returns the value PineScript gives to a constant float expression (not a PineScript function).
117
+ *
118
+ * @param value - The result of the constant expression, computed in JavaScript (e.g. `1 / 255`)
119
+ * @returns The value of the same expression in a PineScript script
120
+ *
121
+ * @remarks
122
+ * PineScript computes a constant expression (only literals and constants: `1 / 255`, `0.1 * 3`,
123
+ * `math.sqrt(0.1)`) before the script runs, and the value is then rounded. JavaScript cannot tell a constant from a
124
+ * series value, so wrap the constant expressions of a script with this function.
125
+ * - |value| >= 0.001: the exact value of the double is rounded to 16 decimals, ties to even
126
+ * (`1 / 255` -> 0.003921568627451, `1 / 7` -> 0.1428571428571428)
127
+ * - |value| < 0.001, na and infinities: unchanged
128
+ * - the whole expression is computed first, then rounded once (`(1 / 7) * 7` is 1)
129
+ * - math functions of constants use JavaScript's `Math` there: `math.constant(math.sqrt(0.1))` is the PineScript
130
+ * value; `math.log10` of a constant is `math.log(x) / math.log(10)` there:
131
+ * `math.constant(math.log(2) / math.log(10))` -> 0.3010299956639811
132
+ * - the same expression with a series operand (`close / 255`) is not rounded: do not wrap it
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * // Pine: var const float i_255 = 1 / 255
137
+ * const i_255 = math.constant(1 / 255) // 0.003921568627451 (JavaScript: 0.00392156862745098)
138
+ * math.constant(1 / 7) // 0.1428571428571428 (JavaScript: 0.14285714285714285)
139
+ * math.constant(1 / 3) // 0.3333333333333333 (unchanged)
140
+ * ```
141
+ */
142
+ export declare function constant(value: float): float;
107
143
  /**
108
144
  * Returns the maximum value from the arguments.
109
145
  *
@@ -156,6 +192,8 @@ export declare function min(...values: (float | Series)[]): float | Series;
156
192
  * - Calculates sum of all values divided by count
157
193
  * - Returns NaN if no arguments provided (division by zero)
158
194
  * - If any argument is a Series, returns a Series; otherwise returns a number
195
+ * - PineScript rule: with 1 or 2 values the sum is plain; with 3 values or more it is a Kahan compensated sum whose
196
+ * pending correction is subtracted before the division (math.avg(0.1, 0.2, 0.3) = 0.19999999999999998)
159
197
  *
160
198
  * @example
161
199
  * ```typescript
@@ -170,7 +208,7 @@ export declare function avg(...values: (float | Series)[]): float | Series;
170
208
  * Returns the sum of values over a sliding window.
171
209
  *
172
210
  * @param source - Series of values or array
173
- * @param length - Window length for summation
211
+ * @param length - Window length for summation, or one length per bar (a series length: array or Series)
174
212
  * @returns Series or array with rolling sum values
175
213
  *
176
214
  * @remarks
@@ -180,6 +218,11 @@ export declare function avg(...values: (float | Series)[]): float | Series;
180
218
  * - A compensated running sum, as in PineScript, so the result can differ from the exact window sum in the last
181
219
  * bits (bit for bit with PineScript)
182
220
  * - When passed a Series, returns a Series; when passed an array, returns an array
221
+ * - With a series length, PineScript moves the running sum to the new length when the length changes, with Kahan
222
+ * steps of the raw values: a smaller length removes the values that leave the window (oldest first); a larger
223
+ * length adds back the values from the one before the old window down to the one `length` values back (newest
224
+ * first), then the usual step removes the stored value of the one `length` values back. A bar with an `na` value
225
+ * gives the sum of the last `length` earlier values
183
226
  *
184
227
  * @example
185
228
  * ```typescript
@@ -187,8 +230,8 @@ export declare function avg(...values: (float | Series)[]): float | Series;
187
230
  * // Explanation: [NaN, NaN, 1+2+3, 2+3+4, 3+4+5]
188
231
  * ```
189
232
  */
190
- export declare function sum(source: Series, length: simple_int): Series;
191
- export declare function sum(source: series_float, length: simple_int): series_float;
233
+ export declare function sum(source: Series, length: simple_int | ArrayLike<number> | Series): Series;
234
+ export declare function sum(source: series_float, length: simple_int | ArrayLike<number> | Series): series_float;
192
235
  /**
193
236
  * Returns the square root of a number.
194
237
  *
@@ -485,29 +528,36 @@ export declare function toradians(degrees: float): float;
485
528
  */
486
529
  export declare function todegrees(radians: Series): Series;
487
530
  export declare function todegrees(radians: float): float;
531
+ /**
532
+ * PineScript's seeded generator: Java's linear congruential generator (`java.util.Random`), `nextDouble()`.
533
+ * Each generator draws one number per call.
534
+ */
535
+ export declare function seededRandom(seed: int): (min?: float, max?: float) => float;
536
+ /** Starts every seeded sequence of `math.random` again (called at the start of a script run). */
537
+ export declare function resetRandom(): void;
488
538
  /**
489
539
  * Returns a pseudo-random number.
490
540
  *
491
- * @param min - Optional minimum value (inclusive)
492
- * @param max - Optional maximum value (exclusive)
493
- * @param seed - Optional seed for deterministic random
541
+ * @param min - Optional minimum value (inclusive), default 0
542
+ * @param max - Optional maximum value (exclusive), default 1
543
+ * @param seed - Optional seed: a repeatable sequence, as PineScript (Java's `java.util.Random`)
494
544
  * @returns A random number in the specified range, or [0, 1) if no range specified
495
545
  *
496
546
  * @remarks
497
- * - Without arguments: returns value in [0, 1)
498
- * - With min and max: returns value in [min, max)
499
- * - **WARNING**: The seed parameter is accepted for API compatibility but NOT currently implemented
500
- * - This implementation always generates non-deterministic random values
501
- * - PineScript's version supports deterministic seeding for repeatable sequences
547
+ * - Without a seed: `Math.random()`
548
+ * - With a seed: PineScript's sequence, one number per call (measured: the call on each bar draws the next number
549
+ * of `new java.util.Random(seed).nextDouble()` from the first bar of the history). PineScript keeps one generator
550
+ * per call site; here there is one generator per seed value (started again by `executeScript`): for two call sites
551
+ * with the same seed use `callsite.random(seed)`
502
552
  *
503
553
  * @example
504
554
  * ```typescript
505
555
  * math.random() // Returns: value between 0 and 1 (e.g., 0.234...)
506
556
  * math.random(0, 10) // Returns: value between 0 and 10 (e.g., 7.45...)
507
- * math.random(5, 15) // Returns: value between 5 and 15 (e.g., 11.82...)
557
+ * math.random(0, 1, 42) // Returns: 0.7275636800328681 on the first call, as PineScript
508
558
  * ```
509
559
  */
510
- export declare function random(min?: float, max?: float, _seed?: int): float;
560
+ export declare function random(min?: float, max?: float, seed?: int): float;
511
561
  /**
512
562
  * Returns the sign of a number.
513
563
  *
@@ -545,9 +595,14 @@ export declare function sign(value: float): int;
545
595
  * - **JavaScript signature**: Requires explicit `mintick` OR use `createContext()` with syminfo
546
596
  * - Rounds to the nearest value divisible by mintick
547
597
  * - Returns NaN for NaN input
548
- * - Ties round up (0.5 -> 1)
549
598
  * - If number is a Series, returns a Series; if number is a float, returns a float
550
599
  *
600
+ * PineScript rules:
601
+ * - mintick is `minmove / pricescale` (here rebuilt from `mintick`: the smallest power of 10 that makes it an
602
+ * integer); the position on the tick grid is `|number| * pricescale / minmove`
603
+ * - ties go away from zero, decided on the exact value of that product with a 1e-10 tolerance
604
+ * (-1.075 -> -1.08, 1.005 -> 1.01, 2.675 -> 2.68 at mintick 0.01)
605
+ *
551
606
  * @example
552
607
  * ```typescript
553
608
  * // Direct call with explicit mintick
@@ -564,5 +619,5 @@ export declare function round_to_mintick(number: float, mintick?: float): float;
564
619
  export declare const pi: number;
565
620
  export declare const e: number;
566
621
  export declare const phi = 1.618033988749895;
567
- export declare const rphi = 0.618033988749895;
622
+ export declare const rphi = 0.6180339887498948;
568
623
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/math/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/math/index.ts"],"names":[],"mappings":"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"}
@@ -8,14 +8,15 @@
8
8
  *
9
9
  * Known difference: `log10`, `exp`, `log`, `pow`, `sin`, `cos`, `tan` use JavaScript's `Math`. PineScript uses
10
10
  * other algorithms, whose results differ by 1 or 2 units in the last place on part of the inputs (`log10` about 4 %,
11
- * `exp` about 9 %, `sin` / `cos` / `tan` about 3 %, `log` 0.4 %, `pow` 0.05 % of random inputs). A constant argument
12
- * (`math.log10(2)`) can differ by up to 3 units in the last place. This is visible only when a script amplifies
13
- * these tiny differences (e.g. `ma > ma[1]` on values of 1e195); `sqrt`, `atan`, `asin`, `acos` are equal.
11
+ * `exp` about 9 %, `sin` / `cos` / `tan` about 3 %, `log` 0.4 %, `pow` 0.05 % of random inputs). This is visible
12
+ * only when a script amplifies these tiny differences (e.g. `ma > ma[1]` on values of 1e195); `sqrt`, `atan`,
13
+ * `asin`, `acos` are equal. A constant argument (`math.log10(2)`) is computed before the script runs, with other
14
+ * rules: see `constant`.
14
15
  *
15
16
  * @version 6
16
17
  */
17
18
  import { Series } from '../runtime/series.js';
18
- import { runningSum } from '../ta/running-sum.js';
19
+ import { runningSum, runningSumSeries } from '../ta/running-sum.js';
19
20
  export function abs(value) {
20
21
  if (value instanceof Series) {
21
22
  const bars = value.bars;
@@ -62,28 +63,118 @@ export function round(value, precision) {
62
63
  if (value instanceof Series) {
63
64
  const bars = value.bars;
64
65
  const valueArray = value.toArray();
65
- const length = bars.length;
66
66
  const result = [];
67
- if (precision === undefined) {
68
- for (let i = 0; i < length; i++) {
69
- const v = valueArray[i] ?? NaN;
70
- result.push(Math.round(v));
71
- }
72
- }
73
- else {
74
- const multiplier = Math.pow(10, precision);
75
- for (let i = 0; i < length; i++) {
76
- const v = valueArray[i] ?? NaN;
77
- result.push(Math.round(v * multiplier) / multiplier);
78
- }
67
+ for (let i = 0; i < bars.length; i++) {
68
+ result.push(roundValue(valueArray[i] ?? NaN, precision));
79
69
  }
80
70
  return Series.fromArray(bars, result);
81
71
  }
82
- if (precision === undefined) {
83
- return Math.round(value);
84
- }
85
- const multiplier = Math.pow(10, precision);
86
- return Math.round(value * multiplier) / multiplier;
72
+ return roundValue(value, precision);
73
+ }
74
+ /** `0.5 - 1e-10` as the exact fraction TIE_HALF / TIE_SCALE: the tie threshold of round / round_to_mintick. */
75
+ const TIE_SCALE = 10n ** 10n;
76
+ const TIE_HALF = 5n * 10n ** 9n - 1n;
77
+ /** From 2^52 up every double is an integer. */
78
+ const INT_LIMIT = 2 ** 52;
79
+ /** Exact value of a finite double >= 0 as `[numerator, denominator]`. */
80
+ function exactRatio(x) {
81
+ const view = new DataView(new ArrayBuffer(8));
82
+ view.setFloat64(0, x);
83
+ const hi = view.getUint32(0);
84
+ const lo = view.getUint32(4);
85
+ const expField = (hi >>> 20) & 0x7ff;
86
+ let mantissa = (BigInt(hi & 0xfffff) << 32n) | BigInt(lo);
87
+ let exp = -1074;
88
+ if (expField !== 0) {
89
+ mantissa |= 1n << 52n;
90
+ exp = expField - 1075;
91
+ }
92
+ return exp >= 0 ? [mantissa << BigInt(exp), 1n] : [mantissa, 1n << BigInt(-exp)];
93
+ }
94
+ /** True when `num / den - units` (exact) is >= 0.5 - 1e-10. */
95
+ function reachesTie(num, den, units) {
96
+ return (num - units * den) * TIE_SCALE >= TIE_HALF * den;
97
+ }
98
+ /** `10^-p`: the exact literal for an integer p (correctly rounded), Math.pow otherwise. */
99
+ function tenToMinus(p) {
100
+ return Number.isInteger(p) ? Number(`1e-${p}`) : Math.pow(10, -p);
101
+ }
102
+ /** PineScript math.round of one value (see `round`). */
103
+ function roundValue(value, precision) {
104
+ if (!Number.isFinite(value))
105
+ return NaN;
106
+ const negative = value < 0;
107
+ const magnitude = negative ? -value : value;
108
+ if (precision === undefined || Number.isNaN(precision) || precision <= 0) {
109
+ if (magnitude >= INT_LIMIT)
110
+ return value;
111
+ let units = Math.floor(magnitude);
112
+ if (magnitude - units >= 0.5)
113
+ units++;
114
+ return negative ? 0 - units : units;
115
+ }
116
+ const scale = 1 / tenToMinus(Math.min(precision, 16));
117
+ const fraction = magnitude % 1;
118
+ const scaled = fraction * scale;
119
+ let units = Math.floor(scaled);
120
+ const offset = scaled - units - 0.5;
121
+ // Only a near-tie needs the exact product; the window covers the double's own error.
122
+ const slack = 1e-9 + scaled * 1.8e-15;
123
+ if (-slack < offset && offset < slack) {
124
+ const [fn, fd] = exactRatio(fraction);
125
+ const [sn, sd] = exactRatio(scale);
126
+ if (reachesTie(fn * sn, fd * sd, BigInt(units)))
127
+ units++;
128
+ }
129
+ else if (offset > 0) {
130
+ units++;
131
+ }
132
+ const result = magnitude - fraction + units / scale;
133
+ return negative ? 0 - result : result;
134
+ }
135
+ /** 10^16: a constant keeps 16 decimals. */
136
+ const CONSTANT_SCALE = 10n ** 16n;
137
+ /**
138
+ * Returns the value PineScript gives to a constant float expression (not a PineScript function).
139
+ *
140
+ * @param value - The result of the constant expression, computed in JavaScript (e.g. `1 / 255`)
141
+ * @returns The value of the same expression in a PineScript script
142
+ *
143
+ * @remarks
144
+ * PineScript computes a constant expression (only literals and constants: `1 / 255`, `0.1 * 3`,
145
+ * `math.sqrt(0.1)`) before the script runs, and the value is then rounded. JavaScript cannot tell a constant from a
146
+ * series value, so wrap the constant expressions of a script with this function.
147
+ * - |value| >= 0.001: the exact value of the double is rounded to 16 decimals, ties to even
148
+ * (`1 / 255` -> 0.003921568627451, `1 / 7` -> 0.1428571428571428)
149
+ * - |value| < 0.001, na and infinities: unchanged
150
+ * - the whole expression is computed first, then rounded once (`(1 / 7) * 7` is 1)
151
+ * - math functions of constants use JavaScript's `Math` there: `math.constant(math.sqrt(0.1))` is the PineScript
152
+ * value; `math.log10` of a constant is `math.log(x) / math.log(10)` there:
153
+ * `math.constant(math.log(2) / math.log(10))` -> 0.3010299956639811
154
+ * - the same expression with a series operand (`close / 255`) is not rounded: do not wrap it
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * // Pine: var const float i_255 = 1 / 255
159
+ * const i_255 = math.constant(1 / 255) // 0.003921568627451 (JavaScript: 0.00392156862745098)
160
+ * math.constant(1 / 7) // 0.1428571428571428 (JavaScript: 0.14285714285714285)
161
+ * math.constant(1 / 3) // 0.3333333333333333 (unchanged)
162
+ * ```
163
+ */
164
+ export function constant(value) {
165
+ const magnitude = Math.abs(value);
166
+ // from 0.5 up, 16 decimals move a double by less than half its spacing: it stays the same
167
+ if (!(magnitude >= 1e-3 && magnitude < 0.5))
168
+ return value;
169
+ const [num, den] = exactRatio(magnitude);
170
+ const scaled = num * CONSTANT_SCALE;
171
+ let units = scaled / den;
172
+ const twiceRest = (scaled - units * den) * 2n;
173
+ if (twiceRest > den || (twiceRest === den && (units & 1n) === 1n))
174
+ units++;
175
+ const digits = units.toString().padStart(17, '0');
176
+ const result = Number(`${digits.slice(0, -16)}.${digits.slice(-16)}`);
177
+ return value < 0 ? -result : result;
87
178
  }
88
179
  /**
89
180
  * Returns the maximum value from the arguments.
@@ -175,6 +266,8 @@ export function min(...values) {
175
266
  * - Calculates sum of all values divided by count
176
267
  * - Returns NaN if no arguments provided (division by zero)
177
268
  * - If any argument is a Series, returns a Series; otherwise returns a number
269
+ * - PineScript rule: with 1 or 2 values the sum is plain; with 3 values or more it is a Kahan compensated sum whose
270
+ * pending correction is subtracted before the division (math.avg(0.1, 0.2, 0.3) = 0.19999999999999998)
178
271
  *
179
272
  * @example
180
273
  * ```typescript
@@ -188,8 +281,7 @@ export function avg(...values) {
188
281
  // Check if any value is a Series
189
282
  const hasSeries = values.some(v => v instanceof Series);
190
283
  if (!hasSeries) {
191
- // All scalars - calculate simple average
192
- return values.reduce((a, b) => a + b, 0) / values.length;
284
+ return avgOf(values);
193
285
  }
194
286
  // At least one Series - return a Series
195
287
  const firstSeries = values.find(v => v instanceof Series);
@@ -200,17 +292,36 @@ export function avg(...values) {
200
292
  const result = [];
201
293
  for (let i = 0; i < length; i++) {
202
294
  const nums = values.map((v, idx) => valueArrays[idx] ? valueArrays[idx][i] ?? NaN : v);
203
- const sum = nums.reduce((a, b) => a + b, 0);
204
- result.push(sum / nums.length);
295
+ result.push(avgOf(nums));
205
296
  }
206
297
  return Series.fromArray(bars, result);
207
298
  }
299
+ /** PineScript math.avg of numbers: plain sum up to 2 values, Kahan sum with the correction flushed from 3. */
300
+ function avgOf(nums) {
301
+ if (nums.length <= 2) {
302
+ let sum = 0;
303
+ for (const n of nums)
304
+ sum = sum + n;
305
+ return sum / nums.length;
306
+ }
307
+ let sum = 0;
308
+ let c = 0;
309
+ for (const n of nums) {
310
+ const y = n - c;
311
+ const t = sum + y;
312
+ c = t - sum - y;
313
+ sum = t;
314
+ }
315
+ return (sum - c) / nums.length;
316
+ }
208
317
  export function sum(source, length) {
209
318
  // Handle Series objects - extract to array first
210
319
  const sourceArray = source instanceof Series ? source.toArray() : source;
211
320
  // PineScript: the sum of the last `length` non-na values (also +/-Infinity skipped); an na bar keeps the previous
212
321
  // result. A compensated running sum, bit for bit as PineScript.
213
- const result = runningSum(sourceArray, length);
322
+ const result = typeof length === 'number'
323
+ ? runningSum(sourceArray, length)
324
+ : runningSumSeries(sourceArray, length instanceof Series ? length.toArray() : length, 'math.sum');
214
325
  // If input was a Series, return a Series
215
326
  if (source instanceof Series) {
216
327
  return Series.fromArray(source.bars, result);
@@ -405,31 +516,60 @@ export function todegrees(radians) {
405
516
  }
406
517
  return radians * (180 / Math.PI);
407
518
  }
519
+ /**
520
+ * PineScript's seeded generator: Java's linear congruential generator (`java.util.Random`), `nextDouble()`.
521
+ * Each generator draws one number per call.
522
+ */
523
+ export function seededRandom(seed) {
524
+ const mask = (1n << 48n) - 1n;
525
+ let state = (BigInt(Math.trunc(seed)) ^ 0x5deece66dn) & mask;
526
+ const next = (bits) => {
527
+ state = (0x5deece66dn * state + 11n) & mask;
528
+ return state >> (48n - bits);
529
+ };
530
+ return (min = 0, max = 1) => {
531
+ const hi = next(26n);
532
+ const lo = next(27n);
533
+ const unit = Number((hi << 27n) + lo) / 2 ** 53;
534
+ return min + unit * (max - min);
535
+ };
536
+ }
537
+ const seeded = new Map();
538
+ /** Starts every seeded sequence of `math.random` again (called at the start of a script run). */
539
+ export function resetRandom() {
540
+ seeded.clear();
541
+ }
408
542
  /**
409
543
  * Returns a pseudo-random number.
410
544
  *
411
- * @param min - Optional minimum value (inclusive)
412
- * @param max - Optional maximum value (exclusive)
413
- * @param seed - Optional seed for deterministic random
545
+ * @param min - Optional minimum value (inclusive), default 0
546
+ * @param max - Optional maximum value (exclusive), default 1
547
+ * @param seed - Optional seed: a repeatable sequence, as PineScript (Java's `java.util.Random`)
414
548
  * @returns A random number in the specified range, or [0, 1) if no range specified
415
549
  *
416
550
  * @remarks
417
- * - Without arguments: returns value in [0, 1)
418
- * - With min and max: returns value in [min, max)
419
- * - **WARNING**: The seed parameter is accepted for API compatibility but NOT currently implemented
420
- * - This implementation always generates non-deterministic random values
421
- * - PineScript's version supports deterministic seeding for repeatable sequences
551
+ * - Without a seed: `Math.random()`
552
+ * - With a seed: PineScript's sequence, one number per call (measured: the call on each bar draws the next number
553
+ * of `new java.util.Random(seed).nextDouble()` from the first bar of the history). PineScript keeps one generator
554
+ * per call site; here there is one generator per seed value (started again by `executeScript`): for two call sites
555
+ * with the same seed use `callsite.random(seed)`
422
556
  *
423
557
  * @example
424
558
  * ```typescript
425
559
  * math.random() // Returns: value between 0 and 1 (e.g., 0.234...)
426
560
  * math.random(0, 10) // Returns: value between 0 and 10 (e.g., 7.45...)
427
- * math.random(5, 15) // Returns: value between 5 and 15 (e.g., 11.82...)
561
+ * math.random(0, 1, 42) // Returns: 0.7275636800328681 on the first call, as PineScript
428
562
  * ```
429
563
  */
430
- export function random(min, max, _seed) {
431
- // TODO: Implement deterministic seeding to match PineScript behavior
432
- // Currently _seed parameter is ignored
564
+ export function random(min, max, seed) {
565
+ if (seed !== undefined && seed !== null && !Number.isNaN(seed)) {
566
+ let gen = seeded.get(seed);
567
+ if (!gen) {
568
+ gen = seededRandom(seed);
569
+ seeded.set(seed, gen);
570
+ }
571
+ return gen(min ?? 0, max ?? 1);
572
+ }
433
573
  const rand = Math.random();
434
574
  if (min !== undefined && max !== undefined) {
435
575
  return min + rand * (max - min);
@@ -454,28 +594,13 @@ export function round_to_mintick(number, mintick) {
454
594
  if (number instanceof Series) {
455
595
  const bars = number.bars;
456
596
  const valueArray = number.toArray();
457
- const length = bars.length;
458
597
  if (mintick === undefined) {
459
598
  throw new Error('math.round_to_mintick() requires mintick value. ' +
460
599
  'Either pass it explicitly or use createContext({ syminfo: { mintick } }) for implicit data.');
461
600
  }
462
601
  const result = [];
463
- if (mintick === 0) {
464
- // No rounding needed
465
- for (let i = 0; i < length; i++) {
466
- result.push(valueArray[i] ?? NaN);
467
- }
468
- }
469
- else {
470
- for (let i = 0; i < length; i++) {
471
- const v = valueArray[i];
472
- if (v === undefined || isNaN(v)) {
473
- result.push(NaN);
474
- }
475
- else {
476
- result.push(Math.round(v / mintick) * mintick);
477
- }
478
- }
602
+ for (let i = 0; i < bars.length; i++) {
603
+ result.push(roundToTick(valueArray[i] ?? NaN, mintick));
479
604
  }
480
605
  return Series.fromArray(bars, result);
481
606
  }
@@ -487,15 +612,56 @@ export function round_to_mintick(number, mintick) {
487
612
  throw new Error('math.round_to_mintick() requires mintick value. ' +
488
613
  'Either pass it explicitly or use createContext({ syminfo: { mintick } }) for implicit data.');
489
614
  }
490
- if (mintick === 0) {
615
+ return roundToTick(number, mintick);
616
+ }
617
+ /** `[minmove, pricescale]` of a mintick: pricescale is the smallest power of 10 (up to 1e15) giving an integer. */
618
+ function tickPair(mintick) {
619
+ for (let k = 0; k <= 15; k++) {
620
+ const pricescale = Number(`1e${k}`);
621
+ const scaled = mintick * pricescale;
622
+ const minmove = Math.round(scaled);
623
+ if (minmove >= 1 && Math.abs(scaled - minmove) <= 1e-9 * minmove)
624
+ return [minmove, pricescale];
625
+ }
626
+ return null;
627
+ }
628
+ /** PineScript math.round_to_mintick of one value (see `round_to_mintick`). */
629
+ function roundToTick(number, mintick) {
630
+ if (!Number.isFinite(number))
631
+ return NaN;
632
+ if (mintick === 0)
491
633
  return number;
492
- }
493
- // Round to nearest tick
494
- return Math.round(number / mintick) * mintick;
634
+ const pair = tickPair(mintick);
635
+ const negative = number < 0;
636
+ const magnitude = negative ? -number : number;
637
+ if (pair === null) {
638
+ // A tick that is no decimal fraction: the grid of the double mintick, ties away from zero.
639
+ const scaled = magnitude / mintick;
640
+ let units = Math.trunc(scaled);
641
+ if (scaled - units >= 0.5)
642
+ units++;
643
+ return (negative ? 0 - units : units) * mintick;
644
+ }
645
+ const [minmove, pricescale] = pair;
646
+ const scaled = (magnitude * pricescale) / minmove;
647
+ let units = Math.trunc(scaled);
648
+ const offset = scaled - units - 0.5;
649
+ const slack = 1e-6 + scaled * 1.8e-15;
650
+ if (-slack < offset && offset < slack) {
651
+ const [n, d] = exactRatio(magnitude);
652
+ const num = n * BigInt(pricescale);
653
+ const den = d * BigInt(minmove);
654
+ const whole = num / den;
655
+ units = Number(whole) + (reachesTie(num, den, whole) ? 1 : 0);
656
+ }
657
+ else if (offset > 0) {
658
+ units++;
659
+ }
660
+ return ((negative ? 0 - units : units) * minmove) / pricescale;
495
661
  }
496
662
  // Constants
497
663
  export const pi = Math.PI;
498
664
  export const e = Math.E;
499
665
  export const phi = 1.618033988749895; // Golden ratio
500
- export const rphi = 0.618033988749895; // Reciprocal of golden ratio
666
+ export const rphi = 0.6180339887498948; // Reciprocal of golden ratio: 1 / phi
501
667
  //# sourceMappingURL=index.js.map