oakscriptjs 0.10.1 → 0.11.1

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 (271) hide show
  1. package/dist/cjs/array/index.d.ts +8 -2
  2. package/dist/cjs/array/index.d.ts.map +1 -1
  3. package/dist/cjs/array/index.js +2 -1
  4. package/dist/cjs/array/index.js.map +2 -2
  5. package/dist/cjs/box/index.d.ts.map +1 -1
  6. package/dist/cjs/box/index.js +7 -1
  7. package/dist/cjs/box/index.js.map +2 -2
  8. package/dist/cjs/callsite/index.d.ts +73 -32
  9. package/dist/cjs/callsite/index.d.ts.map +1 -1
  10. package/dist/cjs/callsite/index.js +69 -65
  11. package/dist/cjs/callsite/index.js.map +2 -2
  12. package/dist/cjs/drawing/registry.d.ts +84 -0
  13. package/dist/cjs/drawing/registry.d.ts.map +1 -1
  14. package/dist/cjs/drawing/registry.js +153 -6
  15. package/dist/cjs/drawing/registry.js.map +2 -2
  16. package/dist/cjs/index.d.ts +8 -2
  17. package/dist/cjs/index.d.ts.map +1 -1
  18. package/dist/cjs/index.js +33 -1
  19. package/dist/cjs/index.js.map +2 -2
  20. package/dist/cjs/input.d.ts +9 -1
  21. package/dist/cjs/input.d.ts.map +1 -1
  22. package/dist/cjs/input.js +16 -0
  23. package/dist/cjs/input.js.map +2 -2
  24. package/dist/cjs/label/index.d.ts.map +1 -1
  25. package/dist/cjs/label/index.js +3 -0
  26. package/dist/cjs/label/index.js.map +2 -2
  27. package/dist/cjs/line/index.d.ts +10 -27
  28. package/dist/cjs/line/index.d.ts.map +1 -1
  29. package/dist/cjs/line/index.js +11 -22
  30. package/dist/cjs/line/index.js.map +2 -2
  31. package/dist/cjs/linefill/index.d.ts +3 -0
  32. package/dist/cjs/linefill/index.d.ts.map +1 -1
  33. package/dist/cjs/linefill/index.js +15 -1
  34. package/dist/cjs/linefill/index.js.map +3 -3
  35. package/dist/cjs/math/index.d.ts.map +1 -1
  36. package/dist/cjs/math/index.js +2 -0
  37. package/dist/cjs/math/index.js.map +2 -2
  38. package/dist/cjs/polyline/index.d.ts.map +1 -1
  39. package/dist/cjs/polyline/index.js +3 -0
  40. package/dist/cjs/polyline/index.js.map +2 -2
  41. package/dist/cjs/runtime/adapters/SimpleInputAdapter.js +1 -1
  42. package/dist/cjs/runtime/adapters/SimpleInputAdapter.js.map +2 -2
  43. package/dist/cjs/runtime/index.d.ts +1 -1
  44. package/dist/cjs/runtime/index.d.ts.map +1 -1
  45. package/dist/cjs/runtime/index.js +1 -0
  46. package/dist/cjs/runtime/index.js.map +2 -2
  47. package/dist/cjs/runtime/inputs.d.ts +9 -0
  48. package/dist/cjs/runtime/inputs.d.ts.map +1 -1
  49. package/dist/cjs/runtime/inputs.js +8 -0
  50. package/dist/cjs/runtime/inputs.js.map +2 -2
  51. package/dist/cjs/runtime/types.d.ts +1 -1
  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 +91 -21
  55. package/dist/cjs/script/index.d.ts.map +1 -1
  56. package/dist/cjs/script/index.js +207 -19
  57. package/dist/cjs/script/index.js.map +3 -3
  58. package/dist/cjs/security/other.d.ts +92 -0
  59. package/dist/cjs/security/other.d.ts.map +1 -0
  60. package/dist/cjs/security/other.js +164 -0
  61. package/dist/cjs/security/other.js.map +7 -0
  62. package/dist/cjs/session/bars.d.ts +24 -1
  63. package/dist/cjs/session/bars.d.ts.map +1 -1
  64. package/dist/cjs/session/bars.js +56 -7
  65. package/dist/cjs/session/bars.js.map +3 -3
  66. package/dist/cjs/session/calendar.d.ts +13 -2
  67. package/dist/cjs/session/calendar.d.ts.map +1 -1
  68. package/dist/cjs/session/calendar.js +39 -9
  69. package/dist/cjs/session/calendar.js.map +2 -2
  70. package/dist/cjs/session/context.d.ts +76 -0
  71. package/dist/cjs/session/context.d.ts.map +1 -0
  72. package/dist/cjs/session/context.js +114 -0
  73. package/dist/cjs/session/context.js.map +7 -0
  74. package/dist/cjs/str/floatingdecimal.d.ts +31 -0
  75. package/dist/cjs/str/floatingdecimal.d.ts.map +1 -0
  76. package/dist/cjs/str/floatingdecimal.js +298 -0
  77. package/dist/cjs/str/floatingdecimal.js.map +7 -0
  78. package/dist/cjs/str/index.d.ts +4 -1
  79. package/dist/cjs/str/index.d.ts.map +1 -1
  80. package/dist/cjs/str/index.js +2 -1
  81. package/dist/cjs/str/index.js.map +2 -2
  82. package/dist/cjs/str/numberformat.d.ts +7 -3
  83. package/dist/cjs/str/numberformat.d.ts.map +1 -1
  84. package/dist/cjs/str/numberformat.js +4 -3
  85. package/dist/cjs/str/numberformat.js.map +2 -2
  86. package/dist/cjs/ta/index.d.ts +67 -34
  87. package/dist/cjs/ta/index.d.ts.map +1 -1
  88. package/dist/cjs/ta/index.js +202 -145
  89. package/dist/cjs/ta/index.js.map +2 -2
  90. package/dist/cjs/ta/limits.d.ts +35 -0
  91. package/dist/cjs/ta/limits.d.ts.map +1 -0
  92. package/dist/cjs/ta/limits.js +64 -0
  93. package/dist/cjs/ta/limits.js.map +7 -0
  94. package/dist/cjs/ta/running-sum.d.ts +0 -16
  95. package/dist/cjs/ta/running-sum.d.ts.map +1 -1
  96. package/dist/cjs/ta/running-sum.js +2 -0
  97. package/dist/cjs/ta/running-sum.js.map +2 -2
  98. package/dist/cjs/ta-series.d.ts +8 -8
  99. package/dist/cjs/ta-series.d.ts.map +1 -1
  100. package/dist/cjs/ta-series.js +10 -8
  101. package/dist/cjs/ta-series.js.map +2 -2
  102. package/dist/cjs/table/index.d.ts +3 -1
  103. package/dist/cjs/table/index.d.ts.map +1 -1
  104. package/dist/cjs/table/index.js +1 -0
  105. package/dist/cjs/table/index.js.map +3 -3
  106. package/dist/cjs/time/index.d.ts +5 -2
  107. package/dist/cjs/time/index.d.ts.map +1 -1
  108. package/dist/cjs/time/index.js +2 -2
  109. package/dist/cjs/time/index.js.map +2 -2
  110. package/dist/cjs/time/session.d.ts +26 -1
  111. package/dist/cjs/time/session.d.ts.map +1 -1
  112. package/dist/cjs/time/session.js +94 -12
  113. package/dist/cjs/time/session.js.map +3 -3
  114. package/dist/cjs/time/timezone.d.ts +6 -1
  115. package/dist/cjs/time/timezone.d.ts.map +1 -1
  116. package/dist/cjs/time/timezone.js +2 -2
  117. package/dist/cjs/time/timezone.js.map +2 -2
  118. package/dist/cjs/types/metadata.d.ts +28 -4
  119. package/dist/cjs/types/metadata.d.ts.map +1 -1
  120. package/dist/cjs/types/metadata.js.map +1 -1
  121. package/dist/esm/array/index.d.ts +8 -2
  122. package/dist/esm/array/index.d.ts.map +1 -1
  123. package/dist/esm/array/index.js +12 -3
  124. package/dist/esm/array/index.js.map +1 -1
  125. package/dist/esm/box/index.d.ts.map +1 -1
  126. package/dist/esm/box/index.js +8 -2
  127. package/dist/esm/box/index.js.map +1 -1
  128. package/dist/esm/callsite/index.d.ts +73 -32
  129. package/dist/esm/callsite/index.d.ts.map +1 -1
  130. package/dist/esm/callsite/index.js +143 -106
  131. package/dist/esm/callsite/index.js.map +1 -1
  132. package/dist/esm/drawing/registry.d.ts +84 -0
  133. package/dist/esm/drawing/registry.d.ts.map +1 -1
  134. package/dist/esm/drawing/registry.js +260 -6
  135. package/dist/esm/drawing/registry.js.map +1 -1
  136. package/dist/esm/index.d.ts +8 -2
  137. package/dist/esm/index.d.ts.map +1 -1
  138. package/dist/esm/index.js +13 -2
  139. package/dist/esm/index.js.map +1 -1
  140. package/dist/esm/input.d.ts +9 -1
  141. package/dist/esm/input.d.ts.map +1 -1
  142. package/dist/esm/input.js +16 -0
  143. package/dist/esm/input.js.map +1 -1
  144. package/dist/esm/label/index.d.ts.map +1 -1
  145. package/dist/esm/label/index.js +4 -1
  146. package/dist/esm/label/index.js.map +1 -1
  147. package/dist/esm/line/index.d.ts +10 -27
  148. package/dist/esm/line/index.d.ts.map +1 -1
  149. package/dist/esm/line/index.js +22 -60
  150. package/dist/esm/line/index.js.map +1 -1
  151. package/dist/esm/linefill/index.d.ts +3 -0
  152. package/dist/esm/linefill/index.d.ts.map +1 -1
  153. package/dist/esm/linefill/index.js +20 -1
  154. package/dist/esm/linefill/index.js.map +1 -1
  155. package/dist/esm/math/index.d.ts.map +1 -1
  156. package/dist/esm/math/index.js +3 -0
  157. package/dist/esm/math/index.js.map +1 -1
  158. package/dist/esm/polyline/index.d.ts.map +1 -1
  159. package/dist/esm/polyline/index.js +5 -1
  160. package/dist/esm/polyline/index.js.map +1 -1
  161. package/dist/esm/runtime/adapters/SimpleInputAdapter.js +1 -1
  162. package/dist/esm/runtime/adapters/SimpleInputAdapter.js.map +1 -1
  163. package/dist/esm/runtime/index.d.ts +1 -1
  164. package/dist/esm/runtime/index.d.ts.map +1 -1
  165. package/dist/esm/runtime/index.js +1 -1
  166. package/dist/esm/runtime/index.js.map +1 -1
  167. package/dist/esm/runtime/inputs.d.ts +9 -0
  168. package/dist/esm/runtime/inputs.d.ts.map +1 -1
  169. package/dist/esm/runtime/inputs.js +15 -0
  170. package/dist/esm/runtime/inputs.js.map +1 -1
  171. package/dist/esm/runtime/types.d.ts +1 -1
  172. package/dist/esm/runtime/types.d.ts.map +1 -1
  173. package/dist/esm/script/index.d.ts +91 -21
  174. package/dist/esm/script/index.d.ts.map +1 -1
  175. package/dist/esm/script/index.js +259 -28
  176. package/dist/esm/script/index.js.map +1 -1
  177. package/dist/esm/security/other.d.ts +92 -0
  178. package/dist/esm/security/other.d.ts.map +1 -0
  179. package/dist/esm/security/other.js +211 -0
  180. package/dist/esm/security/other.js.map +1 -0
  181. package/dist/esm/session/bars.d.ts +24 -1
  182. package/dist/esm/session/bars.d.ts.map +1 -1
  183. package/dist/esm/session/bars.js +75 -6
  184. package/dist/esm/session/bars.js.map +1 -1
  185. package/dist/esm/session/calendar.d.ts +13 -2
  186. package/dist/esm/session/calendar.d.ts.map +1 -1
  187. package/dist/esm/session/calendar.js +54 -10
  188. package/dist/esm/session/calendar.js.map +1 -1
  189. package/dist/esm/session/context.d.ts +76 -0
  190. package/dist/esm/session/context.d.ts.map +1 -0
  191. package/dist/esm/session/context.js +124 -0
  192. package/dist/esm/session/context.js.map +1 -0
  193. package/dist/esm/str/floatingdecimal.d.ts +31 -0
  194. package/dist/esm/str/floatingdecimal.d.ts.map +1 -0
  195. package/dist/esm/str/floatingdecimal.js +272 -0
  196. package/dist/esm/str/floatingdecimal.js.map +1 -0
  197. package/dist/esm/str/index.d.ts +4 -1
  198. package/dist/esm/str/index.d.ts.map +1 -1
  199. package/dist/esm/str/index.js +9 -2
  200. package/dist/esm/str/index.js.map +1 -1
  201. package/dist/esm/str/numberformat.d.ts +7 -3
  202. package/dist/esm/str/numberformat.d.ts.map +1 -1
  203. package/dist/esm/str/numberformat.js +11 -5
  204. package/dist/esm/str/numberformat.js.map +1 -1
  205. package/dist/esm/ta/index.d.ts +67 -34
  206. package/dist/esm/ta/index.d.ts.map +1 -1
  207. package/dist/esm/ta/index.js +284 -240
  208. package/dist/esm/ta/index.js.map +1 -1
  209. package/dist/esm/ta/limits.d.ts +35 -0
  210. package/dist/esm/ta/limits.d.ts.map +1 -0
  211. package/dist/esm/ta/limits.js +67 -0
  212. package/dist/esm/ta/limits.js.map +1 -0
  213. package/dist/esm/ta/running-sum.d.ts +0 -16
  214. package/dist/esm/ta/running-sum.d.ts.map +1 -1
  215. package/dist/esm/ta/running-sum.js +2 -0
  216. package/dist/esm/ta/running-sum.js.map +1 -1
  217. package/dist/esm/ta-series.d.ts +8 -8
  218. package/dist/esm/ta-series.d.ts.map +1 -1
  219. package/dist/esm/ta-series.js +11 -8
  220. package/dist/esm/ta-series.js.map +1 -1
  221. package/dist/esm/table/index.d.ts +3 -1
  222. package/dist/esm/table/index.d.ts.map +1 -1
  223. package/dist/esm/table/index.js +6 -1
  224. package/dist/esm/table/index.js.map +1 -1
  225. package/dist/esm/time/index.d.ts +5 -2
  226. package/dist/esm/time/index.d.ts.map +1 -1
  227. package/dist/esm/time/index.js +6 -3
  228. package/dist/esm/time/index.js.map +1 -1
  229. package/dist/esm/time/session.d.ts +26 -1
  230. package/dist/esm/time/session.d.ts.map +1 -1
  231. package/dist/esm/time/session.js +141 -16
  232. package/dist/esm/time/session.js.map +1 -1
  233. package/dist/esm/time/timezone.d.ts +6 -1
  234. package/dist/esm/time/timezone.d.ts.map +1 -1
  235. package/dist/esm/time/timezone.js +8 -2
  236. package/dist/esm/time/timezone.js.map +1 -1
  237. package/dist/esm/types/metadata.d.ts +28 -4
  238. package/dist/esm/types/metadata.d.ts.map +1 -1
  239. package/package.json +1 -1
  240. package/src/array/index.ts +11 -3
  241. package/src/box/index.ts +8 -2
  242. package/src/callsite/index.ts +150 -100
  243. package/src/drawing/registry.ts +278 -5
  244. package/src/index.ts +44 -1
  245. package/src/input.ts +18 -1
  246. package/src/label/index.ts +4 -1
  247. package/src/line/index.ts +22 -64
  248. package/src/linefill/index.ts +20 -1
  249. package/src/math/index.ts +2 -0
  250. package/src/polyline/index.ts +3 -1
  251. package/src/runtime/adapters/SimpleInputAdapter.ts +1 -1
  252. package/src/runtime/index.ts +1 -0
  253. package/src/runtime/inputs.ts +16 -0
  254. package/src/runtime/types.ts +1 -1
  255. package/src/script/index.ts +355 -34
  256. package/src/security/other.ts +269 -0
  257. package/src/session/bars.ts +70 -6
  258. package/src/session/calendar.ts +60 -10
  259. package/src/session/context.ts +162 -0
  260. package/src/str/floatingdecimal.ts +268 -0
  261. package/src/str/index.ts +8 -2
  262. package/src/str/numberformat.ts +13 -6
  263. package/src/ta/index.ts +304 -248
  264. package/src/ta/limits.ts +74 -0
  265. package/src/ta/running-sum.ts +2 -0
  266. package/src/ta-series.ts +19 -16
  267. package/src/table/index.ts +4 -1
  268. package/src/time/index.ts +6 -3
  269. package/src/time/session.ts +137 -15
  270. package/src/time/timezone.ts +9 -2
  271. package/src/types/metadata.ts +28 -4
@@ -0,0 +1,74 @@
1
+ /**
2
+ * History limits of the window functions.
3
+ *
4
+ * PineScript stops a script when `ta.highest` / `ta.lowest` / `ta.highestbars` / `ta.lowestbars` ask for more than
5
+ * 15,000 bars (runtime error RE10004): with a constant length on the first bar, with a length that changes on the
6
+ * bar where it passes the limit. `math.sum`, `ta.sma`, `ta.variance`, `ta.stdev` and `ta.bb` have the same error
7
+ * above 5,000 bars; the message names the function that keeps the window ('stdev'->'variance', 'bb'->'sma').
8
+ */
9
+
10
+ /** Largest length of `ta.highest` / `ta.lowest` / `ta.highestbars` / `ta.lowestbars`. */
11
+ export const MAX_WINDOW_LENGTH = 15000;
12
+
13
+ /** Largest length of `math.sum` / `ta.sma` / `ta.variance` / `ta.stdev` / `ta.bb`. */
14
+ export const MAX_SUM_LENGTH = 5000;
15
+
16
+ /** Names of the PineScript message for the functions with the 5,000 limit ("a->b": a calls b). */
17
+ export const SUM_FUNCTIONS: Record<string, string> = {
18
+ 'math.sum': 'sum',
19
+ 'ta.sma': 'sma',
20
+ 'ta.variance': 'variance',
21
+ 'ta.stdev': 'stdev->variance',
22
+ 'ta.bb': 'bb->sma',
23
+ };
24
+
25
+ /**
26
+ * PineScript's runtime error RE10004 text; `bar` is the bar index of the call when it is known. `name` is the
27
+ * function, or a call path "stdev->variance" (printed 'stdev'->'variance').
28
+ */
29
+ export function windowError(name: string, length: number, bar?: number, max = MAX_WINDOW_LENGTH): string {
30
+ const fn = name.split('->').map((part) => `'${part}'`).join('->');
31
+ return (
32
+ (bar === undefined ? '' : `Error on bar ${bar}: `) +
33
+ `The ${fn} function references too many historical candles (${length}), the limit is ${max}.`
34
+ );
35
+ }
36
+
37
+ /** Throws RE10004 when the (truncated) length of a window function is above the limit. */
38
+ export function checkWindowLength(name: string, length: number, bar?: number, max = MAX_WINDOW_LENGTH): void {
39
+ const len = Math.trunc(length);
40
+ if (len <= 0) throw new Error(lengthError(name, len, bar));
41
+ if (len > max) throw new Error(windowError(name, len, bar, max));
42
+ }
43
+
44
+ /** Throws RE10004 for a function of {@link SUM_FUNCTIONS} ("ta.sma", ...) with a length above 5,000. */
45
+ export function checkSumLength(name: string, length: number, bar?: number): void {
46
+ const fn = SUM_FUNCTIONS[name];
47
+ if (fn === undefined) return;
48
+ // RE10001 names 'bb' itself, RE10004 its inner 'sma'
49
+ checkPositiveLength(name === 'ta.bb' ? 'bb' : fn, length, bar);
50
+ checkWindowLength(fn, length, bar, MAX_SUM_LENGTH);
51
+ }
52
+
53
+ /**
54
+ * PineScript's runtime error RE10001 text for a length that is 0 or negative. `name` is the function, or a call path
55
+ * "atr->rma" (printed 'atr'->'rma'); the value prints as a float ("0.0", "-1.0").
56
+ */
57
+ export function lengthError(name: string, value: number, bar?: number, arg = 'length'): string {
58
+ const fn = name.split('->').map((part) => `'${part}'`).join('->');
59
+ const text = Number.isInteger(value) ? value.toFixed(1) : String(value);
60
+ return (
61
+ (bar === undefined ? '' : `Error on bar ${bar}: `) +
62
+ `Invalid value of the '${arg}' argument (${text}) in the ${fn} function. It must be > 0.`
63
+ );
64
+ }
65
+
66
+ /**
67
+ * Throws RE10001 when the (truncated) length is 0 or negative, as PineScript does for every window function on the
68
+ * bar of the call (#175): `ta.sma(close, 0)` stops on bar 0, a series length that becomes 0 on the bar where it
69
+ * does. `ta.hma(src, 1)` stops in its inner `wma(src, 0)`. An na length is not checked here.
70
+ */
71
+ export function checkPositiveLength(name: string, length: number, bar?: number, arg = 'length'): void {
72
+ const len = Math.trunc(length);
73
+ if (len <= 0) throw new Error(lengthError(name, len, bar, arg));
74
+ }
@@ -14,6 +14,7 @@
14
14
  *
15
15
  * @internal
16
16
  */
17
+ import { checkSumLength } from './limits.js';
17
18
 
18
19
  /**
19
20
  * Whether the compensation `c` is (partly) lost when it is applied to `x`: `x + |c|` in floating point moves `x` by
@@ -176,6 +177,7 @@ function seriesLengths(lengths: ArrayLike<number>, count: number, name: string):
176
177
  }
177
178
  return Array.from({ length: count }, (_, i) => {
178
179
  const len = Math.floor(lengths[i]!);
180
+ checkSumLength(name, len, i);
179
181
  if (!(len >= 1)) throw new Error(`${name}: length must be at least 1 (bar ${i}: ${lengths[i]})`);
180
182
  return len;
181
183
  });
package/src/ta-series.ts CHANGED
@@ -40,10 +40,10 @@ export function ema(source: Series, length: number): Series {
40
40
  * @param length - Period length
41
41
  * @returns Series with WMA values
42
42
  */
43
- export function wma(source: Series, length: number): Series {
43
+ export function wma(source: Series, length: number | Series): Series {
44
44
  const bars = source.bars as Bar[];
45
45
  const sourceValues = source.toArray();
46
- const result = taCore.wma(sourceValues, length);
46
+ const result = taCore.wma(sourceValues, length instanceof Series ? length.toArray() : length);
47
47
  return Series.fromArray(bars, result);
48
48
  }
49
49
 
@@ -66,10 +66,11 @@ export function rma(source: Series, length: number): Series {
66
66
  * @param length - Period length
67
67
  * @returns Series with RSI values
68
68
  */
69
- export function rsi(source: Series, length: number): Series {
69
+ export function rsi(source: Series, length: number | Series): Series {
70
70
  const bars = source.bars as Bar[];
71
71
  const sourceValues = source.toArray();
72
- const result = taCore.rsi(sourceValues, length);
72
+ // a Series as second argument: PineScript v4 rsi(x, y) of two averages (#180)
73
+ const result = length instanceof Series ? taCore.rsi(sourceValues, length.toArray()) : taCore.rsi(sourceValues, length);
73
74
  return Series.fromArray(bars, result);
74
75
  }
75
76
 
@@ -333,10 +334,10 @@ export function roc(source: Series, length: number): Series {
333
334
  * @param length - Period length
334
335
  * @returns Series with highest values
335
336
  */
336
- export function highest(source: Series, length: number): Series {
337
+ export function highest(source: Series, length: number | Series): Series {
337
338
  const bars = source.bars as Bar[];
338
339
  const sourceValues = source.toArray();
339
- const result = taCore.highest(sourceValues, length);
340
+ const result = taCore.highest(sourceValues, length instanceof Series ? length.toArray() : length);
340
341
  return Series.fromArray(bars, result);
341
342
  }
342
343
 
@@ -346,10 +347,10 @@ export function highest(source: Series, length: number): Series {
346
347
  * @param length - Period length
347
348
  * @returns Series with lowest values
348
349
  */
349
- export function lowest(source: Series, length: number): Series {
350
+ export function lowest(source: Series, length: number | Series): Series {
350
351
  const bars = source.bars as Bar[];
351
352
  const sourceValues = source.toArray();
352
- const result = taCore.lowest(sourceValues, length);
353
+ const result = taCore.lowest(sourceValues, length instanceof Series ? length.toArray() : length);
353
354
  return Series.fromArray(bars, result);
354
355
  }
355
356
 
@@ -688,9 +689,10 @@ export function hma(source: Series, length: number): Series {
688
689
  * @returns Series with the pivot high value on the bar where the pivot is confirmed,
689
690
  * `rightbars` bars after the pivot bar (as in PineScript), NaN elsewhere
690
691
  */
691
- export function pivothigh(source: Series, leftbars: number, rightbars: number): Series {
692
+ export function pivothigh(source: Series, leftbars: number | Series, rightbars: number | Series): Series {
692
693
  const bars = source.bars as Bar[];
693
- const result = taCore.pivothigh(source.toArray(), leftbars, rightbars);
694
+ const arr = (v: number | Series) => (v instanceof Series ? v.toArray() : v);
695
+ const result = taCore.pivothigh(source.toArray(), arr(leftbars), arr(rightbars));
694
696
  return Series.fromArray(bars, result);
695
697
  }
696
698
 
@@ -702,9 +704,10 @@ export function pivothigh(source: Series, leftbars: number, rightbars: number):
702
704
  * @returns Series with the pivot low value on the bar where the pivot is confirmed,
703
705
  * `rightbars` bars after the pivot bar (as in PineScript), NaN elsewhere
704
706
  */
705
- export function pivotlow(source: Series, leftbars: number, rightbars: number): Series {
707
+ export function pivotlow(source: Series, leftbars: number | Series, rightbars: number | Series): Series {
706
708
  const bars = source.bars as Bar[];
707
- const result = taCore.pivotlow(source.toArray(), leftbars, rightbars);
709
+ const arr = (v: number | Series) => (v instanceof Series ? v.toArray() : v);
710
+ const result = taCore.pivotlow(source.toArray(), arr(leftbars), arr(rightbars));
708
711
  return Series.fromArray(bars, result);
709
712
  }
710
713
 
@@ -861,9 +864,9 @@ export function kcw(bars: Bar[], source: Series, length: number = 20, mult: numb
861
864
  * @param length - Period length
862
865
  * @returns Series with bar offsets to highest value
863
866
  */
864
- export function highestbars(source: Series, length: number): Series {
867
+ export function highestbars(source: Series, length: number | Series): Series {
865
868
  const bars = source.bars as Bar[];
866
- const result = taCore.highestbars(source.toArray(), length);
869
+ const result = taCore.highestbars(source.toArray(), length instanceof Series ? length.toArray() : length);
867
870
  return Series.fromArray(bars, result);
868
871
  }
869
872
 
@@ -873,9 +876,9 @@ export function highestbars(source: Series, length: number): Series {
873
876
  * @param length - Period length
874
877
  * @returns Series with bar offsets to lowest value
875
878
  */
876
- export function lowestbars(source: Series, length: number): Series {
879
+ export function lowestbars(source: Series, length: number | Series): Series {
877
880
  const bars = source.bars as Bar[];
878
- const result = taCore.lowestbars(source.toArray(), length);
881
+ const result = taCore.lowestbars(source.toArray(), length instanceof Series ? length.toArray() : length);
879
882
  return Series.fromArray(bars, result);
880
883
  }
881
884
 
@@ -12,6 +12,7 @@
12
12
  * - `table.cell_set_*` changes one property of a cell (a cell that was not defined is created)
13
13
  * - a column or row outside the table is a runtime error
14
14
  * - a deleted table is `na`: its functions do nothing
15
+ * - one live table per position: `table.new` at the position of a live table deletes that table (#176)
15
16
  *
16
17
  * @version 6
17
18
  */
@@ -25,7 +26,8 @@ type VAlign = 'top' | 'center' | 'bottom';
25
26
  type FontFamily = 'default' | 'monospace';
26
27
 
27
28
  /**
28
- * Creates a new table (PineScript `table.new`).
29
+ * Creates a new table (PineScript `table.new`). A live table at the same position is deleted, as PineScript keeps
30
+ * one table per position (#176).
29
31
  *
30
32
  * @example
31
33
  * ```typescript
@@ -44,6 +46,7 @@ export function new_table(
44
46
  border_width?: number,
45
47
  force_overlay?: boolean
46
48
  ): Table {
49
+ for (const old of allDrawings('table')) if (old.position === position) remove('table', old);
47
50
  return register('table', {
48
51
  position,
49
52
  columns,
package/src/time/index.ts CHANGED
@@ -156,8 +156,11 @@ export function second(time: int, timezone: string): int {
156
156
  * ":" (1 = Sunday ... 7 = Saturday), e.g. "0930-1600:23456" or "1000-1100,1400-1500".
157
157
  * Without days, one period covers every day and several periods cover Monday to Friday.
158
158
  * A period includes its start and excludes its end. An overnight period ("1800-0930")
159
- * belongs to the day it ends. "0000-0000" and "24x7" cover the whole day.
159
+ * belongs to the day it ends. "0000-0000" and "24x7" cover the whole day. A period that ends at 0000 ends at 24:00 of
160
+ * the day it starts. On the days around a clock change the periods are placed as PineScript places them (see
161
+ * time/session.ts); `barMs`, the duration of the bars in ms, is needed for one of these rules (the day before the
162
+ * clocks go back).
160
163
  */
161
- export function inSession(time: int, session: string, timezone: string): boolean {
162
- return sessionContains(time, session, timezone);
164
+ export function inSession(time: int, session: string, timezone: string, barMs?: number): boolean {
165
+ return sessionContains(time, session, timezone, barMs);
163
166
  }
@@ -12,11 +12,15 @@
12
12
  * - a trailing ",", ":" or "|" ends its list ("1100-1400," is "1100-1400" Monday to Friday)
13
13
  * - an end before the start is an overnight run that belongs to the day it ends; equal ends are 24 hours;
14
14
  * "0000-0000" and "24x7" are the whole day, every day
15
+ * - a run that ends at 0000 ("2000-0000") ends at 24:00 of the day it starts and belongs to that day
16
+ * ("2000-0000:6" is Friday 20:00 to midnight)
17
+ * - "F" after the start moves it one day before the day the run ends on ("1700F-1900:2": Sunday 17:00 to Monday
18
+ * 19:00; "1900-1900:3456|1700F-1900:2" is the TVC:DXY symbol session) (#173)
15
19
  * - a string that is empty or does not start with a digit ("regular", "extended") is the symbol's own session
16
20
  * - a malformed string ("1100 -1400", "0930-16", ":8") is an error, as the PineScript runtime error
17
21
  */
18
22
 
19
- import { zonedFields } from './timezone.js';
23
+ import { zoneOffset, zonedFields, zonedToUnix } from './timezone.js';
20
24
 
21
25
  const MINUTES_PER_DAY = 1440;
22
26
  const WEEKDAYS = [2, 3, 4, 5, 6];
@@ -27,17 +31,27 @@ export interface SessionRange {
27
31
  start: number;
28
32
  end: number;
29
33
  days: Set<number>;
34
+ /** Days between the start and the day the run ends on, given by "F" after the start (absent otherwise) */
35
+ startDays?: number;
30
36
  }
31
37
 
32
38
  function invalid(session: string): SyntaxError {
33
39
  return new SyntaxError(`Invalid session "${session}": expected "HHMM-HHMM[,HHMM-HHMM...][:days][|...]"`);
34
40
  }
35
41
 
36
- function parseRanges(text: string, session: string): Array<[number, number]> {
42
+ function parseRanges(text: string, session: string): Array<[number, number, number?]> {
37
43
  if (!text) return [];
38
44
  const entries = text.split(',');
39
45
  if (entries.length > 1 && entries[entries.length - 1] === '') entries.pop();
40
- return entries.map((entry) => {
46
+ return entries.map((entry): [number, number, number?] => {
47
+ // "HHMMF-HHMM": the start is one day before the day the run ends on
48
+ const f = /^(\d{4})F-(\d{4})$/.exec(entry);
49
+ if (f) {
50
+ const minutes = (hhmm: string): number => Number(hhmm.slice(0, 2)) * 60 + Number(hhmm.slice(2, 4));
51
+ const [start, end] = [minutes(f[1]!), minutes(f[2]!)];
52
+ if (start >= MINUTES_PER_DAY || end >= MINUTES_PER_DAY) throw invalid(session);
53
+ return [start, end, 1];
54
+ }
41
55
  if (!/^\d{4}-\d{4}$/.test(entry)) throw invalid(session);
42
56
  let start = Number(entry.slice(0, 2)) * 60 + Number(entry.slice(2, 4));
43
57
  let end = Number(entry.slice(5, 7)) * 60 + Number(entry.slice(7, 9));
@@ -58,6 +72,9 @@ function parseDays(text: string, session: string): Set<number> {
58
72
 
59
73
  const parsed = new Map<string, SessionRange[] | null>();
60
74
 
75
+ const range = (start: number, end: number, days: Set<number>, startDays?: number): SessionRange =>
76
+ startDays === undefined ? { start, end, days } : { start, end, days, startDays };
77
+
61
78
  /**
62
79
  * Runs of a PineScript session string, or null for the symbol's own session (empty or not starting with a digit).
63
80
  * @throws SyntaxError when the string is malformed (a PineScript runtime error)
@@ -72,7 +89,7 @@ export function parsePineSession(session: string): SessionRange[] | null {
72
89
  } else if (spec === '24x7') {
73
90
  out = [{ start: 0, end: 0, days: new Set(ALL_DAYS) }];
74
91
  } else if (!/[:,|]/.test(spec)) {
75
- out = parseRanges(spec, session).map(([start, end]) => ({ start, end, days: new Set(ALL_DAYS) }));
92
+ out = parseRanges(spec, session).map(([start, end, startDays]) => range(start, end, new Set(ALL_DAYS), startDays));
76
93
  } else {
77
94
  const sections = spec.split('|');
78
95
  if (sections.length > 1 && sections[sections.length - 1] === '') sections.pop();
@@ -97,33 +114,138 @@ export function parsePineSession(session: string): SessionRange[] | null {
97
114
  items.forEach((it, i) => {
98
115
  if (it.days === null) for (const d of WEEKDAYS) if (!claimed.has(d)) own[i]!.add(d);
99
116
  });
100
- out = items.flatMap((it, i) => (own[i]!.size ? it.ranges.map(([start, end]) => ({ start, end, days: own[i]! })) : []));
117
+ out = items.flatMap((it, i) => (own[i]!.size ? it.ranges.map(([start, end, startDays]) => range(start, end, own[i]!, startDays)) : []));
101
118
  }
102
119
  parsed.set(session, out);
103
120
  return out;
104
121
  }
105
122
 
123
+ const MS_PER_MINUTE = 60_000;
124
+ const MS_PER_HOUR = 3_600_000;
125
+ const MS_PER_DAY = 86_400_000;
126
+ /** A clock change is looked for this far on each side of the tested time. */
127
+ const CHANGE_WINDOW = 36 * MS_PER_HOUR;
128
+
129
+ /** The clock change of `timezone` within 36 hours of `time`: its UNIX time and the offsets (ms) around it. */
130
+ function clockChangeNear(time: number, timezone: string): { at: number; before: number; after: number } | null {
131
+ let lo = time - CHANGE_WINDOW;
132
+ let hi = time + CHANGE_WINDOW;
133
+ const before = zoneOffset(lo, timezone);
134
+ const after = zoneOffset(hi, timezone);
135
+ if (before === after) return null;
136
+ while (hi - lo > MS_PER_MINUTE) {
137
+ const mid = Math.floor((lo + hi) / 2 / MS_PER_MINUTE) * MS_PER_MINUTE;
138
+ if (zoneOffset(mid, timezone) === before) lo = mid;
139
+ else hi = mid;
140
+ }
141
+ return { at: hi, before, after };
142
+ }
143
+
106
144
  /**
107
145
  * True when `time` falls inside `session`, with the session hours read in `timezone`.
108
146
  * A run includes its start minute and excludes its end minute.
147
+ *
148
+ * On the days around a clock change PineScript does not read the wall clock of each bar; it places each run of
149
+ * each local day (measured on 15- and 5-minute bars, clocks going forward and back, four time zones):
150
+ * - a wall time of the day is placed with the offset before the change when it is before the wall time of the
151
+ * change (02:00 for 02:00 -> 03:00, 03:00 for 03:00 -> 02:00), with the offset after it otherwise. Forward
152
+ * change: "0100-0300" lasts one hour and "0130-0230" is empty; back change: "0230-0330" lasts two hours
153
+ * - a run that ends exactly on the wall time of the change is placed with the offset after the change at both ends
154
+ * (forward change: "0100-0200" is one hour earlier than the wall clock says)
155
+ * - clocks going back: a run that ends inside the repeated hour also covers its second pass
156
+ * - clocks going back, the day BEFORE the change: a run with a start or an end on the wall time of the change is
157
+ * also true one hour (the amount of the change) later, from one bar after its usual end. This needs the bar
158
+ * duration `barMs`; without it the rule is not applied
159
+ *
160
+ * @param barMs - Duration of the bars in ms (the chart timeframe); only used by the last rule
109
161
  * @throws Error for the symbol's own session ("regular", "extended", ""), which this function does not know: use
110
162
  * `time(timeframe, session)` in a script with the chart session
111
163
  */
112
- export function inSession(time: number, session: string, timezone: string): boolean {
113
- if (Number.isNaN(time)) return false;
164
+ export function inSession(time: number, session: string, timezone: string, barMs?: number): boolean {
165
+ return sessionRun(time, session, timezone, barMs) !== null;
166
+ }
167
+
168
+ /**
169
+ * The run of `session` that contains `time`, as [start, end) UNIX times (ms), or null outside the session; rules in
170
+ * {@link inSession}. PineScript aligns the intraday periods of `time(tf, session)` on the start of this run (#173).
171
+ */
172
+ export function sessionRun(time: number, session: string, timezone: string, barMs?: number): [number, number] | null {
173
+ if (Number.isNaN(time)) return null;
114
174
  const ranges = parsePineSession(session);
115
175
  if (ranges === null) throw new Error(`Session "${session}" is the symbol session: it needs the chart session (time(timeframe, session) in a script)`);
176
+ const change = clockChangeNear(time, timezone);
116
177
  const f = zonedFields(time, timezone);
117
178
  const minute = f.hour * 60 + f.minute;
118
179
  const nextDay = (f.dayOfWeek % 7) + 1;
119
- for (const { start, end, days } of ranges) {
120
- if (start < end || (start === 0 && end === 0)) {
121
- if (minute >= start && (minute < end || end === 0) && days.has(f.dayOfWeek)) return true;
122
- } else {
123
- // Overnight (24 hours when start === end): the part from `start` belongs to the next day.
124
- if (minute >= start && days.has(nextDay)) return true;
125
- if (minute < end && days.has(f.dayOfWeek)) return true;
180
+ for (const { start, end: rawEnd, days, startDays } of ranges) {
181
+ if (startDays !== undefined) {
182
+ // "F": from `start` of `startDays` days before the end day to `end` of the end day, wall times read in the zone
183
+ for (let k = 0; k <= startDays + 1; k++) {
184
+ const endDay = Date.UTC(f.year, f.month - 1, f.day + k);
185
+ if (!days.has(new Date(endDay).getUTCDay() + 1)) continue;
186
+ const d = new Date(endDay);
187
+ const at = (dayShift: number, minutes: number): number =>
188
+ zonedToUnix(timezone, d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate() - dayShift, Math.floor(minutes / 60), minutes % 60);
189
+ const from = at(startDays, start);
190
+ const to = at(0, rawEnd);
191
+ if (time >= from && time < to) return [from, to];
192
+ }
193
+ continue;
194
+ }
195
+ if (start === rawEnd) {
196
+ // 24 hours: the run belongs to the day it ends ("0000-0000": the day itself)
197
+ if (days.has(start === 0 || minute < start ? f.dayOfWeek : nextDay)) {
198
+ const from = time - ((minute - start + MINUTES_PER_DAY) % MINUTES_PER_DAY) * MS_PER_MINUTE - f.second * 1000 - (time % 1000);
199
+ return [from, from + MS_PER_DAY];
200
+ }
201
+ continue;
202
+ }
203
+ // a run that ends at 0000 ends at 24:00 of the day it starts
204
+ const end = rawEnd === 0 ? MINUTES_PER_DAY : rawEnd;
205
+ const overnight = start > end;
206
+ if (!change) {
207
+ // the wall-clock minute of the bar: the run is `start` to `end` minutes of the same offset
208
+ const midnight = time - minute * MS_PER_MINUTE - f.second * 1000 - (time % 1000);
209
+ if (!overnight) {
210
+ if (minute >= start && minute < end && days.has(f.dayOfWeek)) return [midnight + start * MS_PER_MINUTE, midnight + end * MS_PER_MINUTE];
211
+ } else {
212
+ // the part from `start` belongs to the next day
213
+ if (minute >= start && days.has(nextDay)) return [midnight + start * MS_PER_MINUTE, midnight + (end + MINUTES_PER_DAY) * MS_PER_MINUTE];
214
+ if (minute < end && days.has(f.dayOfWeek)) return [midnight + (start - MINUTES_PER_DAY) * MS_PER_MINUTE, midnight + end * MS_PER_MINUTE];
215
+ }
216
+ continue;
217
+ }
218
+ // local days as naive instants (wall clock read as UTC)
219
+ const changeWall = change.at + change.before;
220
+ const place = (naive: number): number => (naive < changeWall ? naive - change.before : naive - change.after);
221
+ const today = Math.floor((time + change.before) / MS_PER_DAY);
222
+ for (let day = today - 1; day <= today + 1; day++) {
223
+ if (!days.has(((day + 4) % 7) + 1)) continue; // 01/01/1970 is a Thursday (5)
224
+ const from = day * MS_PER_DAY + (overnight ? start - MINUTES_PER_DAY : start) * MS_PER_MINUTE;
225
+ const to = day * MS_PER_DAY + end * MS_PER_MINUTE;
226
+ if (to === changeWall) {
227
+ if (time >= from - change.after && time < to - change.after) return [from - change.after, to - change.after];
228
+ continue;
229
+ }
230
+ if (time >= place(from) && time < place(to)) return [place(from), place(to)];
231
+ // clocks going back: the second pass of the repeated hour
232
+ const repeated = change.at + change.after;
233
+ if (change.after < change.before && to < changeWall && to > repeated) {
234
+ if (time >= Math.max(from, repeated) - change.after && time < to - change.after) return [place(from), to - change.after];
235
+ }
236
+ }
237
+ // clocks going back, the day before: a run with an end on the wall time of the change is also true one change
238
+ // later, from one bar after its usual end
239
+ if (barMs !== undefined && change.after < change.before) {
240
+ const day = Math.floor(changeWall / MS_PER_DAY) - 1;
241
+ const wallMinute = (changeWall - (day + 1) * MS_PER_DAY) / MS_PER_MINUTE;
242
+ if ((start === wallMinute || end === wallMinute) && days.has(((day + 4) % 7) + 1)) {
243
+ const from = day * MS_PER_DAY + (overnight ? start - MINUTES_PER_DAY : start) * MS_PER_MINUTE - change.before;
244
+ const to = day * MS_PER_DAY + end * MS_PER_MINUTE - change.before;
245
+ const shift = change.before - change.after;
246
+ if (time >= from + shift && time < to + shift && time >= to + barMs) return [from + shift, to + shift];
247
+ }
126
248
  }
127
249
  }
128
- return false;
250
+ return null;
129
251
  }
@@ -177,6 +177,11 @@ export function civilToUnix(year: number, month: number, day: number, hour = 0,
177
177
  return days * MS_PER_DAY + Date.UTC(1970, 0, 1, hour, minute, second);
178
178
  }
179
179
 
180
+ /**
181
+ * UNIX time (ms) of a wall-clock date in `timezone`. A wall time skipped by a clock change is read with the offset
182
+ * before the change (02:30 on a 02:00 -> 03:00 night is 03:30 after it); a wall time that occurs twice gives the
183
+ * later instant, or the earlier one with `earlier`.
184
+ */
180
185
  export function zonedToUnix(
181
186
  timezone: string,
182
187
  year: number,
@@ -184,7 +189,8 @@ export function zonedToUnix(
184
189
  day: number,
185
190
  hour: number = 0,
186
191
  minute: number = 0,
187
- second: number = 0
192
+ second: number = 0,
193
+ earlier: boolean = false
188
194
  ): number {
189
195
  const zone = resolveZone(timezone);
190
196
  const local = civilToUnix(year, month, day, hour, minute, second);
@@ -195,6 +201,7 @@ export function zonedToUnix(
195
201
  const before = offsetAt(zone, local - MS_PER_DAY);
196
202
  const after = offsetAt(zone, local + MS_PER_DAY);
197
203
  const candidates = [local - before, local - after].filter((t) => local - offsetAt(zone, t) === t);
198
- if (candidates.length) return Math.max(...candidates);
204
+ // a wall time that occurs twice: the later instant, or the earlier one with `earlier`
205
+ if (candidates.length) return earlier ? Math.min(...candidates) : Math.max(...candidates);
199
206
  return local - before;
200
207
  }
@@ -86,7 +86,7 @@ export interface FillOptions {
86
86
  /**
87
87
  * Input parameter type
88
88
  */
89
- export type InputType = 'int' | 'float' | 'bool' | 'string' | 'source' | 'color' | 'timeframe' | 'session' | 'time';
89
+ export type InputType = 'int' | 'float' | 'bool' | 'string' | 'source' | 'color' | 'timeframe' | 'session' | 'time' | 'symbol';
90
90
 
91
91
  /**
92
92
  * Input parameter metadata
@@ -431,17 +431,20 @@ export interface LabelData {
431
431
  /** Price; not used with yloc 'abovebar' / 'belowbar' */
432
432
  price: number;
433
433
  text: string;
434
- /** Background, border and arrow colour */
434
+ /** Background, border and arrow colour. Omitted: #2962FF (color.blue; #2196F3 in a v4 script) */
435
435
  color?: string;
436
+ /** Omitted: #FFFFFF in a v6 script, #363A45 in v4 and v5 (the result does not carry the version) */
436
437
  textColor?: string;
437
- /** 'none': text only, no background (PineScript label.style_none) */
438
+ /** 'none': text only, no background (PineScript label.style_none). Omitted: 'label_down' */
438
439
  style?: LabelStyle;
440
+ /** Omitted: 'normal' */
439
441
  size?: PineSize | number;
440
442
  /**
441
443
  * PineScript yloc: 'price' (default) places the label at `price`; 'abovebar' / 'belowbar' place it above the bar
442
444
  * high / below the bar low and ignore `price` (the renderer reads the bar at `time`).
443
445
  */
444
446
  yloc?: 'price' | 'abovebar' | 'belowbar';
447
+ /** Omitted: 'center' */
445
448
  textAlign?: 'left' | 'center' | 'right';
446
449
  tooltip?: string;
447
450
  fontFamily?: 'default' | 'monospace';
@@ -459,8 +462,11 @@ export interface LineDrawingData {
459
462
  price1: number;
460
463
  time2: number;
461
464
  price2: number;
465
+ /** Omitted: #2962FF (color.blue; #2196F3 in a v4 script) */
462
466
  color?: string;
467
+ /** Omitted: 1. A width of 0 is kept (PineScript `width = 0`) */
463
468
  width?: number;
469
+ /** Omitted: 'solid' */
464
470
  style?: 'solid' | 'dashed' | 'dotted' | 'arrow_left' | 'arrow_right' | 'arrow_both';
465
471
  extend?: 'none' | 'left' | 'right' | 'both';
466
472
  /** PineScript force_overlay = true: the line of a non-overlay indicator is drawn on the price pane */
@@ -475,14 +481,22 @@ export interface BoxData {
475
481
  price1: number;
476
482
  time2: number;
477
483
  price2: number;
484
+ /** Omitted: #2962FF (color.blue; #2196F3 in a v4 script) */
478
485
  bgColor?: string;
486
+ /** Omitted: #2962FF (color.blue; #2196F3 in a v4 script) */
479
487
  borderColor?: string;
488
+ /** Omitted: 1. A width of 0 is no border (PineScript `border_width = 0`) */
480
489
  borderWidth?: number;
490
+ /** Omitted: 'solid' */
481
491
  borderStyle?: 'solid' | 'dashed' | 'dotted';
482
492
  text?: string;
493
+ /** Omitted: #FFFFFF in a v6 script, #363A45 in v5 (the result does not carry the version) */
483
494
  textColor?: string;
495
+ /** Omitted: 'auto' */
484
496
  textSize?: PineSize | number;
497
+ /** Omitted: 'center' */
485
498
  textHAlign?: 'left' | 'center' | 'right';
499
+ /** Omitted: 'center' */
486
500
  textVAlign?: 'top' | 'center' | 'bottom';
487
501
  textWrap?: 'none' | 'auto';
488
502
  fontFamily?: 'default' | 'monospace';
@@ -512,10 +526,12 @@ export interface PolylineData {
512
526
  curved?: boolean;
513
527
  /** The last point is connected to the first */
514
528
  closed?: boolean;
529
+ /** Omitted: #2962FF (color.blue) */
515
530
  lineColor?: string;
516
- /** Fill of the area inside the polyline */
531
+ /** Fill of the area inside the polyline. Omitted: no fill */
517
532
  fillColor?: string;
518
533
  lineStyle?: 'solid' | 'dotted' | 'dashed' | 'arrow_left' | 'arrow_right' | 'arrow_both';
534
+ /** Omitted: 1 */
519
535
  lineWidth?: number;
520
536
  /** PineScript force_overlay = true: the polyline of a non-overlay indicator is drawn on the price pane */
521
537
  forceOverlay?: boolean;
@@ -540,8 +556,11 @@ export interface TableCellData {
540
556
  row: number;
541
557
  column: number;
542
558
  text: string;
559
+ /** Omitted: no background */
543
560
  bgColor?: string;
561
+ /** Omitted: #363A45 (in v4, v5 and v6 scripts) */
544
562
  textColor?: string;
563
+ /** Omitted: 'auto' */
545
564
  textSize?: PineSize | number;
546
565
  /** Width in % of the chart width; 0 fits the text */
547
566
  width?: number;
@@ -575,10 +594,15 @@ export interface TableData {
575
594
  rows: number;
576
595
  cells: TableCellData[];
577
596
  merges?: TableMergeData[];
597
+ /** Omitted: no background */
578
598
  bgColor?: string;
599
+ /** Omitted: no frame */
579
600
  frameColor?: string;
601
+ /** Omitted: 0 */
580
602
  frameWidth?: number;
603
+ /** Omitted: no cell borders */
581
604
  borderColor?: string;
605
+ /** Omitted: 0 */
582
606
  borderWidth?: number;
583
607
  /** PineScript force_overlay = true: the table of a non-overlay indicator is drawn on the price pane */
584
608
  forceOverlay?: boolean;