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.
- package/README.md +1 -1
- package/dist/cjs/array/index.d.ts +93 -50
- package/dist/cjs/array/index.d.ts.map +1 -1
- package/dist/cjs/array/index.js +239 -78
- package/dist/cjs/array/index.js.map +3 -3
- package/dist/cjs/callsite/index.d.ts +81 -2
- package/dist/cjs/callsite/index.d.ts.map +1 -1
- package/dist/cjs/callsite/index.js +62 -1
- package/dist/cjs/callsite/index.js.map +2 -2
- package/dist/cjs/color/index.d.ts +7 -3
- package/dist/cjs/color/index.d.ts.map +1 -1
- package/dist/cjs/color/index.js +6 -1
- package/dist/cjs/color/index.js.map +2 -2
- package/dist/cjs/drawing/bar-time.d.ts +24 -0
- package/dist/cjs/drawing/bar-time.d.ts.map +1 -0
- package/dist/cjs/drawing/bar-time.js +47 -0
- package/dist/cjs/drawing/bar-time.js.map +7 -0
- package/dist/cjs/drawing/output.d.ts +32 -0
- package/dist/cjs/drawing/output.d.ts.map +1 -0
- package/dist/cjs/drawing/output.js +184 -0
- package/dist/cjs/drawing/output.js.map +7 -0
- package/dist/cjs/drawing/registry.d.ts +5 -4
- package/dist/cjs/drawing/registry.d.ts.map +1 -1
- package/dist/cjs/drawing/registry.js +11 -2
- package/dist/cjs/drawing/registry.js.map +2 -2
- package/dist/cjs/index.d.ts +6 -3
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +9 -2
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/label/index.d.ts.map +1 -1
- package/dist/cjs/label/index.js +2 -1
- package/dist/cjs/label/index.js.map +2 -2
- package/dist/cjs/linefill/index.d.ts.map +1 -1
- package/dist/cjs/linefill/index.js +1 -0
- package/dist/cjs/linefill/index.js.map +2 -2
- package/dist/cjs/math/index.d.ts +76 -21
- package/dist/cjs/math/index.d.ts.map +1 -1
- package/dist/cjs/math/index.js +155 -41
- package/dist/cjs/math/index.js.map +3 -3
- package/dist/cjs/matrix/index.d.ts.map +1 -1
- package/dist/cjs/matrix/index.js +42 -36
- package/dist/cjs/matrix/index.js.map +2 -2
- package/dist/cjs/polyline/index.d.ts +3 -5
- package/dist/cjs/polyline/index.d.ts.map +1 -1
- package/dist/cjs/polyline/index.js +0 -5
- package/dist/cjs/polyline/index.js.map +2 -2
- package/dist/cjs/runtime/series.d.ts +9 -0
- package/dist/cjs/runtime/series.d.ts.map +1 -1
- package/dist/cjs/runtime/series.js +16 -2
- package/dist/cjs/runtime/series.js.map +2 -2
- package/dist/cjs/runtime/types.d.ts +22 -0
- package/dist/cjs/runtime/types.d.ts.map +1 -1
- package/dist/cjs/runtime/types.js.map +1 -1
- package/dist/cjs/script/index.d.ts +97 -36
- package/dist/cjs/script/index.d.ts.map +1 -1
- package/dist/cjs/script/index.js +173 -26
- package/dist/cjs/script/index.js.map +3 -3
- package/dist/cjs/session/calendar.d.ts.map +1 -1
- package/dist/cjs/session/calendar.js +15 -2
- package/dist/cjs/session/calendar.js.map +2 -2
- package/dist/cjs/str/index.d.ts +50 -38
- package/dist/cjs/str/index.d.ts.map +1 -1
- package/dist/cjs/str/index.js +43 -15
- package/dist/cjs/str/index.js.map +2 -2
- package/dist/cjs/str/messageformat.d.ts +2 -1
- package/dist/cjs/str/messageformat.d.ts.map +1 -1
- package/dist/cjs/str/messageformat.js +4 -1
- package/dist/cjs/str/messageformat.js.map +2 -2
- package/dist/cjs/str/numberformat.d.ts +4 -0
- package/dist/cjs/str/numberformat.d.ts.map +1 -1
- package/dist/cjs/str/numberformat.js +26 -4
- package/dist/cjs/str/numberformat.js.map +3 -3
- package/dist/cjs/ta/index.d.ts +86 -43
- package/dist/cjs/ta/index.d.ts.map +1 -1
- package/dist/cjs/ta/index.js +173 -267
- package/dist/cjs/ta/index.js.map +3 -3
- package/dist/cjs/ta/running-sum.d.ts +54 -2
- package/dist/cjs/ta/running-sum.d.ts.map +1 -1
- package/dist/cjs/ta/running-sum.js +132 -52
- package/dist/cjs/ta/running-sum.js.map +2 -2
- package/dist/cjs/ta-series.d.ts +4 -4
- package/dist/cjs/ta-series.d.ts.map +1 -1
- package/dist/cjs/ta-series.js +4 -3
- package/dist/cjs/ta-series.js.map +2 -2
- package/dist/cjs/table/index.d.ts +87 -0
- package/dist/cjs/table/index.d.ts.map +1 -0
- package/dist/cjs/table/index.js +150 -0
- package/dist/cjs/table/index.js.map +7 -0
- package/dist/cjs/text/index.d.ts +17 -2
- package/dist/cjs/text/index.d.ts.map +1 -1
- package/dist/cjs/text/index.js +15 -1
- package/dist/cjs/text/index.js.map +2 -2
- package/dist/cjs/time/datestring.d.ts +1 -0
- package/dist/cjs/time/datestring.d.ts.map +1 -1
- package/dist/cjs/time/datestring.js +7 -0
- package/dist/cjs/time/datestring.js.map +2 -2
- package/dist/cjs/time/index.d.ts.map +1 -1
- package/dist/cjs/time/index.js +2 -1
- package/dist/cjs/time/index.js.map +2 -2
- package/dist/cjs/time/session.d.ts +28 -9
- package/dist/cjs/time/session.d.ts.map +1 -1
- package/dist/cjs/time/session.js +74 -28
- package/dist/cjs/time/session.js.map +2 -2
- package/dist/cjs/time/timezone.d.ts +5 -0
- package/dist/cjs/time/timezone.d.ts.map +1 -1
- package/dist/cjs/time/timezone.js +15 -1
- package/dist/cjs/time/timezone.js.map +2 -2
- package/dist/cjs/types/index.d.ts +30 -1
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js +12 -0
- package/dist/cjs/types/index.js.map +2 -2
- package/dist/cjs/types/metadata.d.ts +258 -26
- package/dist/cjs/types/metadata.d.ts.map +1 -1
- package/dist/cjs/types/metadata.js.map +1 -1
- package/dist/esm/array/index.d.ts +93 -50
- package/dist/esm/array/index.d.ts.map +1 -1
- package/dist/esm/array/index.js +383 -133
- package/dist/esm/array/index.js.map +1 -1
- package/dist/esm/callsite/index.d.ts +81 -2
- package/dist/esm/callsite/index.d.ts.map +1 -1
- package/dist/esm/callsite/index.js +145 -3
- package/dist/esm/callsite/index.js.map +1 -1
- package/dist/esm/color/index.d.ts +7 -3
- package/dist/esm/color/index.d.ts.map +1 -1
- package/dist/esm/color/index.js +15 -3
- package/dist/esm/color/index.js.map +1 -1
- package/dist/esm/drawing/bar-time.d.ts +24 -0
- package/dist/esm/drawing/bar-time.d.ts.map +1 -0
- package/dist/esm/drawing/bar-time.js +44 -0
- package/dist/esm/drawing/bar-time.js.map +1 -0
- package/dist/esm/drawing/output.d.ts +32 -0
- package/dist/esm/drawing/output.d.ts.map +1 -0
- package/dist/esm/drawing/output.js +190 -0
- package/dist/esm/drawing/output.js.map +1 -0
- package/dist/esm/drawing/registry.d.ts +5 -4
- package/dist/esm/drawing/registry.d.ts.map +1 -1
- package/dist/esm/drawing/registry.js +12 -2
- package/dist/esm/drawing/registry.js.map +1 -1
- package/dist/esm/index.d.ts +6 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +7 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/label/index.d.ts.map +1 -1
- package/dist/esm/label/index.js +2 -1
- package/dist/esm/label/index.js.map +1 -1
- package/dist/esm/linefill/index.d.ts.map +1 -1
- package/dist/esm/linefill/index.js +3 -0
- package/dist/esm/linefill/index.js.map +1 -1
- package/dist/esm/math/index.d.ts +76 -21
- package/dist/esm/math/index.d.ts.map +1 -1
- package/dist/esm/math/index.js +227 -61
- package/dist/esm/math/index.js.map +1 -1
- package/dist/esm/matrix/index.d.ts.map +1 -1
- package/dist/esm/matrix/index.js +57 -43
- package/dist/esm/matrix/index.js.map +1 -1
- package/dist/esm/polyline/index.d.ts +3 -5
- package/dist/esm/polyline/index.d.ts.map +1 -1
- package/dist/esm/polyline/index.js +3 -9
- package/dist/esm/polyline/index.js.map +1 -1
- package/dist/esm/runtime/series.d.ts +9 -0
- package/dist/esm/runtime/series.d.ts.map +1 -1
- package/dist/esm/runtime/series.js +18 -1
- package/dist/esm/runtime/series.js.map +1 -1
- package/dist/esm/runtime/types.d.ts +22 -0
- package/dist/esm/runtime/types.d.ts.map +1 -1
- package/dist/esm/script/index.d.ts +97 -36
- package/dist/esm/script/index.d.ts.map +1 -1
- package/dist/esm/script/index.js +211 -22
- package/dist/esm/script/index.js.map +1 -1
- package/dist/esm/session/calendar.d.ts.map +1 -1
- package/dist/esm/session/calendar.js +22 -2
- package/dist/esm/session/calendar.js.map +1 -1
- package/dist/esm/str/index.d.ts +50 -38
- package/dist/esm/str/index.d.ts.map +1 -1
- package/dist/esm/str/index.js +103 -52
- package/dist/esm/str/index.js.map +1 -1
- package/dist/esm/str/messageformat.d.ts +2 -1
- package/dist/esm/str/messageformat.d.ts.map +1 -1
- package/dist/esm/str/messageformat.js +7 -2
- package/dist/esm/str/messageformat.js.map +1 -1
- package/dist/esm/str/numberformat.d.ts +4 -0
- package/dist/esm/str/numberformat.d.ts.map +1 -1
- package/dist/esm/str/numberformat.js +38 -4
- package/dist/esm/str/numberformat.js.map +1 -1
- package/dist/esm/ta/index.d.ts +86 -43
- package/dist/esm/ta/index.d.ts.map +1 -1
- package/dist/esm/ta/index.js +296 -348
- package/dist/esm/ta/index.js.map +1 -1
- package/dist/esm/ta/running-sum.d.ts +54 -2
- package/dist/esm/ta/running-sum.d.ts.map +1 -1
- package/dist/esm/ta/running-sum.js +166 -71
- package/dist/esm/ta/running-sum.js.map +1 -1
- package/dist/esm/ta-series.d.ts +4 -4
- package/dist/esm/ta-series.d.ts.map +1 -1
- package/dist/esm/ta-series.js +5 -4
- package/dist/esm/ta-series.js.map +1 -1
- package/dist/esm/table/index.d.ts +87 -0
- package/dist/esm/table/index.d.ts.map +1 -0
- package/dist/esm/table/index.js +169 -0
- package/dist/esm/table/index.js.map +1 -0
- package/dist/esm/text/index.d.ts +17 -2
- package/dist/esm/text/index.d.ts.map +1 -1
- package/dist/esm/text/index.js +17 -2
- package/dist/esm/text/index.js.map +1 -1
- package/dist/esm/time/datestring.d.ts +1 -0
- package/dist/esm/time/datestring.d.ts.map +1 -1
- package/dist/esm/time/datestring.js +12 -0
- package/dist/esm/time/datestring.js.map +1 -1
- package/dist/esm/time/index.d.ts.map +1 -1
- package/dist/esm/time/index.js +3 -1
- package/dist/esm/time/index.js.map +1 -1
- package/dist/esm/time/session.d.ts +28 -9
- package/dist/esm/time/session.d.ts.map +1 -1
- package/dist/esm/time/session.js +113 -42
- package/dist/esm/time/session.js.map +1 -1
- package/dist/esm/time/timezone.d.ts +5 -0
- package/dist/esm/time/timezone.d.ts.map +1 -1
- package/dist/esm/time/timezone.js +21 -1
- package/dist/esm/time/timezone.js.map +1 -1
- package/dist/esm/types/index.d.ts +30 -1
- package/dist/esm/types/index.d.ts.map +1 -1
- package/dist/esm/types/index.js +14 -0
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/types/metadata.d.ts +258 -26
- package/dist/esm/types/metadata.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/array/index.ts +364 -150
- package/src/callsite/index.ts +147 -3
- package/src/color/index.ts +15 -5
- package/src/drawing/bar-time.ts +42 -0
- package/src/drawing/output.ts +214 -0
- package/src/drawing/registry.ts +16 -6
- package/src/index.ts +9 -3
- package/src/label/index.ts +2 -1
- package/src/linefill/index.ts +2 -0
- package/src/math/index.ts +256 -74
- package/src/matrix/index.ts +52 -52
- package/src/polyline/index.ts +3 -12
- package/src/runtime/series.ts +22 -1
- package/src/runtime/types.ts +23 -0
- package/src/script/index.ts +307 -25
- package/src/session/calendar.ts +22 -2
- package/src/str/index.ts +95 -51
- package/src/str/messageformat.ts +7 -2
- package/src/str/numberformat.ts +39 -4
- package/src/ta/index.ts +306 -386
- package/src/ta/running-sum.ts +187 -74
- package/src/ta-series.ts +8 -7
- package/src/table/index.ts +221 -0
- package/src/text/index.ts +18 -2
- package/src/time/datestring.ts +10 -0
- package/src/time/index.ts +3 -1
- package/src/time/session.ts +97 -47
- package/src/time/timezone.ts +21 -1
- package/src/types/index.ts +32 -1
- package/src/types/metadata.ts +325 -26
package/dist/esm/math/index.d.ts
CHANGED
|
@@ -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).
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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(
|
|
108
|
+
* math.round(-2.5) // Returns: -3
|
|
101
109
|
* math.round(4.567, 2) // Returns: 4.57
|
|
102
|
-
* math.round(
|
|
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
|
|
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
|
|
498
|
-
* - With
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
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(
|
|
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,
|
|
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.
|
|
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":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/math/index.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/math/index.js
CHANGED
|
@@ -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).
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
|
418
|
-
* - With
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
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(
|
|
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,
|
|
431
|
-
|
|
432
|
-
|
|
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
|
-
|
|
464
|
-
|
|
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
|
-
|
|
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
|
-
|
|
494
|
-
|
|
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.
|
|
666
|
+
export const rphi = 0.6180339887498948; // Reciprocal of golden ratio: 1 / phi
|
|
501
667
|
//# sourceMappingURL=index.js.map
|