oakscriptjs 0.13.2 → 0.14.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/AGENTS.md +6 -1
- package/README.md +1 -1
- package/bin/oakscript.mjs +5 -0
- package/dist/cjs/check/checks.d.ts +78 -0
- package/dist/cjs/check/checks.d.ts.map +1 -0
- package/dist/cjs/check/checks.js +109 -0
- package/dist/cjs/check/checks.js.map +7 -0
- package/dist/cjs/check/format.d.ts +26 -0
- package/dist/cjs/check/format.d.ts.map +1 -0
- package/dist/cjs/check/format.js +106 -0
- package/dist/cjs/check/format.js.map +7 -0
- package/dist/cjs/check/harness.d.ts +94 -0
- package/dist/cjs/check/harness.d.ts.map +1 -0
- package/dist/cjs/check/harness.js +302 -0
- package/dist/cjs/check/harness.js.map +7 -0
- package/dist/cjs/check/index.d.ts +253 -0
- package/dist/cjs/check/index.d.ts.map +1 -0
- package/dist/cjs/check/index.js +466 -0
- package/dist/cjs/check/index.js.map +7 -0
- package/dist/cjs/check/node.d.ts +53 -0
- package/dist/cjs/check/node.d.ts.map +1 -0
- package/dist/cjs/check/node.js +318 -0
- package/dist/cjs/check/node.js.map +7 -0
- package/dist/cjs/check/spec.d.ts +44 -0
- package/dist/cjs/check/spec.d.ts.map +1 -0
- package/dist/cjs/check/spec.js +199 -0
- package/dist/cjs/check/spec.js.map +7 -0
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/runtime/series.d.ts +6 -0
- package/dist/cjs/runtime/series.d.ts.map +1 -1
- package/dist/cjs/runtime/series.js +15 -0
- package/dist/cjs/runtime/series.js.map +2 -2
- package/dist/cjs/script/constants.d.ts +200 -0
- package/dist/cjs/script/constants.d.ts.map +1 -0
- package/dist/cjs/script/constants.js +217 -0
- package/dist/cjs/script/constants.js.map +7 -0
- package/dist/cjs/script/drawing-args.d.ts +25 -0
- package/dist/cjs/script/drawing-args.d.ts.map +1 -0
- package/dist/cjs/script/drawing-args.js +203 -0
- package/dist/cjs/script/drawing-args.js.map +7 -0
- package/dist/cjs/script/globals.d.ts +127 -0
- package/dist/cjs/script/globals.d.ts.map +1 -0
- package/dist/cjs/script/globals.js +17 -0
- package/dist/cjs/script/globals.js.map +7 -0
- package/dist/cjs/script/index.d.ts +499 -166
- package/dist/cjs/script/index.d.ts.map +1 -1
- package/dist/cjs/script/index.js +236 -96
- package/dist/cjs/script/index.js.map +3 -3
- package/dist/esm/check/checks.d.ts +78 -0
- package/dist/esm/check/checks.d.ts.map +1 -0
- package/dist/esm/check/checks.js +95 -0
- package/dist/esm/check/checks.js.map +1 -0
- package/dist/esm/check/format.d.ts +26 -0
- package/dist/esm/check/format.d.ts.map +1 -0
- package/dist/esm/check/format.js +105 -0
- package/dist/esm/check/format.js.map +1 -0
- package/dist/esm/check/harness.d.ts +94 -0
- package/dist/esm/check/harness.d.ts.map +1 -0
- package/dist/esm/check/harness.js +317 -0
- package/dist/esm/check/harness.js.map +1 -0
- package/dist/esm/check/index.d.ts +253 -0
- package/dist/esm/check/index.d.ts.map +1 -0
- package/dist/esm/check/index.js +470 -0
- package/dist/esm/check/index.js.map +1 -0
- package/dist/esm/check/node.d.ts +53 -0
- package/dist/esm/check/node.d.ts.map +1 -0
- package/dist/esm/check/node.js +347 -0
- package/dist/esm/check/node.js.map +1 -0
- package/dist/esm/check/spec.d.ts +44 -0
- package/dist/esm/check/spec.d.ts.map +1 -0
- package/dist/esm/check/spec.js +198 -0
- package/dist/esm/check/spec.js.map +1 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/runtime/series.d.ts +6 -0
- package/dist/esm/runtime/series.d.ts.map +1 -1
- package/dist/esm/runtime/series.js +14 -0
- package/dist/esm/runtime/series.js.map +1 -1
- package/dist/esm/script/constants.d.ts +200 -0
- package/dist/esm/script/constants.d.ts.map +1 -0
- package/dist/esm/script/constants.js +151 -0
- package/dist/esm/script/constants.js.map +1 -0
- package/dist/esm/script/drawing-args.d.ts +25 -0
- package/dist/esm/script/drawing-args.d.ts.map +1 -0
- package/dist/esm/script/drawing-args.js +171 -0
- package/dist/esm/script/drawing-args.js.map +1 -0
- package/dist/esm/script/globals.d.ts +127 -0
- package/dist/esm/script/globals.d.ts.map +1 -0
- package/dist/esm/script/globals.js +28 -0
- package/dist/esm/script/globals.js.map +1 -0
- package/dist/esm/script/index.d.ts +499 -166
- package/dist/esm/script/index.d.ts.map +1 -1
- package/dist/esm/script/index.js +256 -83
- package/dist/esm/script/index.js.map +1 -1
- package/package.json +31 -1
- package/skills/oakscript/SKILL.md +62 -26
- package/skills/oakscript/examples/ma-cross.js +2 -2
- package/skills/oakscript/examples/mtf-trend-filter.js +3 -3
- package/skills/oakscript/reference/check.md +150 -0
- package/skills/oakscript/reference/errors.md +31 -7
- package/skills/oakscript/reference/pine-differences.md +17 -16
- package/skills/oakscript/reference/plotting.md +25 -19
- package/skills/oakscript/reference/script-structure.md +8 -5
- package/skills/oakscript/reference/timeframes-symbols.md +5 -1
- package/skills/oakscript/spec.schema.json +199 -0
- package/src/check/checks.ts +175 -0
- package/src/check/format.ts +117 -0
- package/src/check/harness.ts +372 -0
- package/src/check/index.ts +708 -0
- package/src/check/node.ts +368 -0
- package/src/check/spec.ts +200 -0
- package/src/index.ts +1 -1
- package/src/runtime/series.ts +19 -0
- package/src/script/constants.ts +169 -0
- package/src/script/drawing-args.ts +179 -0
- package/src/script/globals.ts +129 -0
- package/src/script/index.ts +457 -81
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview PineScript constant namespaces of the script API: `shape.*`, `location.*`, `size.*`, `xloc.*`,
|
|
3
|
+
* `yloc.*`, `extend.*`, `display.*`, `format.*`, `font.*`, `scale.*`, `order.*`, `currency.*`, `adjustment.*`, and the
|
|
4
|
+
* `label.style_*`, `line.style_*`, `dayofweek.*` members. Each constant is the string (or number) the functions take,
|
|
5
|
+
* so `plotshape(cond, "Buy", { style: shape.triangleup })` and `{ style: "triangleup" }` are the same.
|
|
6
|
+
*
|
|
7
|
+
* @module script/constants
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** PineScript `shape.*`: the shapes of plotshape(). */
|
|
11
|
+
export const shape = {
|
|
12
|
+
xcross: 'xcross',
|
|
13
|
+
cross: 'cross',
|
|
14
|
+
triangleup: 'triangleup',
|
|
15
|
+
triangledown: 'triangledown',
|
|
16
|
+
flag: 'flag',
|
|
17
|
+
circle: 'circle',
|
|
18
|
+
arrowup: 'arrowup',
|
|
19
|
+
arrowdown: 'arrowdown',
|
|
20
|
+
labelup: 'labelup',
|
|
21
|
+
labeldown: 'labeldown',
|
|
22
|
+
square: 'square',
|
|
23
|
+
diamond: 'diamond',
|
|
24
|
+
} as const;
|
|
25
|
+
|
|
26
|
+
/** PineScript `location.*`: where plotshape() / plotchar() draw. */
|
|
27
|
+
export const location = {
|
|
28
|
+
abovebar: 'abovebar',
|
|
29
|
+
belowbar: 'belowbar',
|
|
30
|
+
top: 'top',
|
|
31
|
+
bottom: 'bottom',
|
|
32
|
+
absolute: 'absolute',
|
|
33
|
+
} as const;
|
|
34
|
+
|
|
35
|
+
/** PineScript `size.*`: sizes of shapes, characters, labels and table texts. */
|
|
36
|
+
export const size = {
|
|
37
|
+
auto: 'auto',
|
|
38
|
+
tiny: 'tiny',
|
|
39
|
+
small: 'small',
|
|
40
|
+
normal: 'normal',
|
|
41
|
+
large: 'large',
|
|
42
|
+
huge: 'huge',
|
|
43
|
+
} as const;
|
|
44
|
+
|
|
45
|
+
/** PineScript `xloc.*`: the x coordinate of drawings (bar index or UNIX time in ms). */
|
|
46
|
+
export const xloc = {
|
|
47
|
+
bar_index: 'bar_index',
|
|
48
|
+
bar_time: 'bar_time',
|
|
49
|
+
} as const;
|
|
50
|
+
|
|
51
|
+
/** PineScript `yloc.*`: the y position of labels. */
|
|
52
|
+
export const yloc = {
|
|
53
|
+
price: 'price',
|
|
54
|
+
abovebar: 'abovebar',
|
|
55
|
+
belowbar: 'belowbar',
|
|
56
|
+
} as const;
|
|
57
|
+
|
|
58
|
+
/** PineScript `extend.*`: line extension. */
|
|
59
|
+
export const extend = {
|
|
60
|
+
none: 'none',
|
|
61
|
+
left: 'left',
|
|
62
|
+
right: 'right',
|
|
63
|
+
both: 'both',
|
|
64
|
+
} as const;
|
|
65
|
+
|
|
66
|
+
/** PineScript `display.*`: where a plot or input is shown. */
|
|
67
|
+
export const display = {
|
|
68
|
+
none: 'none',
|
|
69
|
+
all: 'all',
|
|
70
|
+
data_window: 'data_window',
|
|
71
|
+
status_line: 'status_line',
|
|
72
|
+
pane: 'pane',
|
|
73
|
+
} as const;
|
|
74
|
+
|
|
75
|
+
/** PineScript `format.*`: the number format of indicator() and str.tostring(). */
|
|
76
|
+
export const format = {
|
|
77
|
+
inherit: 'inherit',
|
|
78
|
+
price: 'price',
|
|
79
|
+
volume: 'volume',
|
|
80
|
+
percent: 'percent',
|
|
81
|
+
mintick: 'mintick',
|
|
82
|
+
} as const;
|
|
83
|
+
|
|
84
|
+
/** PineScript `font.*`: font families of labels, boxes and table cells. */
|
|
85
|
+
export const font = {
|
|
86
|
+
family_default: 'default',
|
|
87
|
+
family_monospace: 'monospace',
|
|
88
|
+
} as const;
|
|
89
|
+
|
|
90
|
+
/** PineScript `scale.*`: the price scale of indicator() (`scale` option). */
|
|
91
|
+
export const scale = {
|
|
92
|
+
right: 'right',
|
|
93
|
+
left: 'left',
|
|
94
|
+
none: 'none',
|
|
95
|
+
} as const;
|
|
96
|
+
|
|
97
|
+
/** PineScript `order.*`: sort order of array.sort() / array.sort_indices() / matrix.sort(). */
|
|
98
|
+
export const order = {
|
|
99
|
+
ascending: 'ascending',
|
|
100
|
+
descending: 'descending',
|
|
101
|
+
} as const;
|
|
102
|
+
|
|
103
|
+
/** PineScript `adjustment.*`: price adjustment of a ticker. */
|
|
104
|
+
export const adjustment = {
|
|
105
|
+
none: 'none',
|
|
106
|
+
splits: 'splits',
|
|
107
|
+
dividends: 'dividends',
|
|
108
|
+
} as const;
|
|
109
|
+
|
|
110
|
+
const CURRENCIES = [
|
|
111
|
+
'AED', 'ARS', 'AUD', 'BDT', 'BHD', 'BRL', 'BTC', 'CAD', 'CHF', 'CLP', 'CNY', 'COP', 'CZK', 'DKK', 'EGP', 'ETH',
|
|
112
|
+
'EUR', 'GBP', 'GEL', 'HKD', 'HUF', 'IDR', 'ILS', 'INR', 'ISK', 'JPY', 'KES', 'KRW', 'KWD', 'LKR', 'MAD', 'MXN',
|
|
113
|
+
'MYR', 'NGN', 'NOK', 'NZD', 'PEN', 'PHP', 'PKR', 'PLN', 'QAR', 'RON', 'RSD', 'RUB', 'SAR', 'SEK', 'SGD', 'THB',
|
|
114
|
+
'TND', 'TRY', 'TWD', 'USD', 'USDT', 'VES', 'VND', 'ZAR',
|
|
115
|
+
] as const;
|
|
116
|
+
|
|
117
|
+
type CurrencyCode = (typeof CURRENCIES)[number];
|
|
118
|
+
|
|
119
|
+
/** PineScript `currency.*`: currency codes (`strategy(..., { currency })`, `syminfo.currency`); `currency.NONE` is na. */
|
|
120
|
+
export const currency = {
|
|
121
|
+
...(Object.fromEntries(CURRENCIES.map((c) => [c, c])) as { readonly [K in CurrencyCode]: K }),
|
|
122
|
+
NONE: 'NONE',
|
|
123
|
+
} as const;
|
|
124
|
+
|
|
125
|
+
/** PineScript `label.style_*`. */
|
|
126
|
+
export const labelStyles = {
|
|
127
|
+
style_none: 'none',
|
|
128
|
+
style_xcross: 'xcross',
|
|
129
|
+
style_cross: 'cross',
|
|
130
|
+
style_triangleup: 'triangleup',
|
|
131
|
+
style_triangledown: 'triangledown',
|
|
132
|
+
style_flag: 'flag',
|
|
133
|
+
style_circle: 'circle',
|
|
134
|
+
style_arrowup: 'arrowup',
|
|
135
|
+
style_arrowdown: 'arrowdown',
|
|
136
|
+
style_label_up: 'label_up',
|
|
137
|
+
style_label_down: 'label_down',
|
|
138
|
+
style_label_left: 'label_left',
|
|
139
|
+
style_label_right: 'label_right',
|
|
140
|
+
style_label_lower_left: 'label_lower_left',
|
|
141
|
+
style_label_lower_right: 'label_lower_right',
|
|
142
|
+
style_label_upper_left: 'label_upper_left',
|
|
143
|
+
style_label_upper_right: 'label_upper_right',
|
|
144
|
+
style_label_center: 'label_center',
|
|
145
|
+
style_square: 'square',
|
|
146
|
+
style_diamond: 'diamond',
|
|
147
|
+
style_text_outline: 'text_outline',
|
|
148
|
+
} as const;
|
|
149
|
+
|
|
150
|
+
/** PineScript `line.style_*` (lines, boxes, polylines). */
|
|
151
|
+
export const lineStyles = {
|
|
152
|
+
style_solid: 'solid',
|
|
153
|
+
style_dotted: 'dotted',
|
|
154
|
+
style_dashed: 'dashed',
|
|
155
|
+
style_arrow_left: 'arrow_left',
|
|
156
|
+
style_arrow_right: 'arrow_right',
|
|
157
|
+
style_arrow_both: 'arrow_both',
|
|
158
|
+
} as const;
|
|
159
|
+
|
|
160
|
+
/** PineScript `dayofweek.*`: the values of `dayofweek` (1 = Sunday ... 7 = Saturday). */
|
|
161
|
+
export const daysOfWeek = {
|
|
162
|
+
sunday: 1,
|
|
163
|
+
monday: 2,
|
|
164
|
+
tuesday: 3,
|
|
165
|
+
wednesday: 4,
|
|
166
|
+
thursday: 5,
|
|
167
|
+
friday: 6,
|
|
168
|
+
saturday: 7,
|
|
169
|
+
} as const;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Arguments of the drawing functions of the script API, as PineScript writes them:
|
|
3
|
+
*
|
|
4
|
+
* - **Named arguments**: a last argument that is an object of PineScript parameter names, e.g.
|
|
5
|
+
* `label.new(c.i, c.high, "A", { style: label.style_label_down, textcolor: color.white })`, or every argument by
|
|
6
|
+
* name: `line.new({ x1, y1, x2, y2, extend: extend.right })`. An unknown name throws with the closest names.
|
|
7
|
+
* - **Series arguments**: inside a bar loop a Series argument (`bar_index`, `high`, `ta.sma(...)`) is its value on the
|
|
8
|
+
* current bar, as PineScript reads a series in a call; outside a loop it throws (a drawing takes one value).
|
|
9
|
+
*
|
|
10
|
+
* @module script/drawing-args
|
|
11
|
+
*/
|
|
12
|
+
import { Series } from '../runtime/series.js';
|
|
13
|
+
|
|
14
|
+
/** PineScript parameters of the drawing constructors, in their positional order (coordinates, then chart points). */
|
|
15
|
+
export const DRAWING_PARAMETERS: Record<string, { coords: readonly string[]; point?: readonly string[] }> = {
|
|
16
|
+
'label.new': {
|
|
17
|
+
coords: ['x', 'y', 'text', 'xloc', 'yloc', 'color', 'style', 'textcolor', 'size', 'textalign', 'tooltip', 'text_font_family', 'force_overlay', 'text_formatting'],
|
|
18
|
+
point: ['point', 'text', 'xloc', 'yloc', 'color', 'style', 'textcolor', 'size', 'textalign', 'tooltip', 'text_font_family', 'force_overlay', 'text_formatting'],
|
|
19
|
+
},
|
|
20
|
+
'line.new': {
|
|
21
|
+
coords: ['x1', 'y1', 'x2', 'y2', 'xloc', 'extend', 'color', 'style', 'width', 'force_overlay'],
|
|
22
|
+
point: ['first_point', 'second_point', 'xloc', 'extend', 'color', 'style', 'width', 'force_overlay'],
|
|
23
|
+
},
|
|
24
|
+
'box.new': {
|
|
25
|
+
coords: [
|
|
26
|
+
'left', 'top', 'right', 'bottom', 'border_color', 'border_width', 'border_style', 'extend', 'xloc', 'bgcolor', 'text',
|
|
27
|
+
'text_size', 'text_color', 'text_halign', 'text_valign', 'text_wrap', 'text_font_family', 'force_overlay', 'text_formatting',
|
|
28
|
+
],
|
|
29
|
+
point: [
|
|
30
|
+
'top_left', 'bottom_right', 'border_color', 'border_width', 'border_style', 'extend', 'xloc', 'bgcolor', 'text',
|
|
31
|
+
'text_size', 'text_color', 'text_halign', 'text_valign', 'text_wrap', 'text_font_family', 'force_overlay', 'text_formatting',
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
'table.new': {
|
|
35
|
+
coords: ['position', 'columns', 'rows', 'bgcolor', 'frame_color', 'frame_width', 'border_color', 'border_width', 'force_overlay'],
|
|
36
|
+
},
|
|
37
|
+
'table.cell': {
|
|
38
|
+
coords: [
|
|
39
|
+
'table_id', 'column', 'row', 'text', 'width', 'height', 'text_color', 'text_halign', 'text_valign', 'text_size', 'bgcolor',
|
|
40
|
+
'tooltip', 'text_font_family', 'text_formatting',
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
'polyline.new': {
|
|
44
|
+
coords: ['points', 'curved', 'closed', 'xloc', 'line_color', 'fill_color', 'line_style', 'line_width', 'force_overlay'],
|
|
45
|
+
},
|
|
46
|
+
'linefill.new': { coords: ['line1', 'line2', 'color'] },
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** Parameters that take an object: a plain object there is the argument, not named arguments. */
|
|
50
|
+
const OBJECT_PARAMETERS = new Set(['point', 'first_point', 'second_point', 'top_left', 'bottom_right', 'table_id', 'line1', 'line2', 'points']);
|
|
51
|
+
|
|
52
|
+
/** A plain object (an object literal): named arguments, not a Series, an array or a class instance. */
|
|
53
|
+
export const isPlainObject = (v: unknown): v is Record<string, unknown> =>
|
|
54
|
+
typeof v === 'object' && v !== null && !Array.isArray(v) && !(v instanceof Series) &&
|
|
55
|
+
(Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null);
|
|
56
|
+
|
|
57
|
+
/** A chart point (`chart.point.*`): its keys are index / time / price. */
|
|
58
|
+
const isChartPoint = (v: Record<string, unknown>): boolean => {
|
|
59
|
+
const keys = Object.keys(v);
|
|
60
|
+
return keys.length > 0 && keys.every((k) => k === 'index' || k === 'time' || k === 'price');
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
function closest(name: string, names: readonly string[]): string[] {
|
|
64
|
+
const n = name.toLowerCase();
|
|
65
|
+
const dist = (a: string, b: string): number => {
|
|
66
|
+
const row = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
67
|
+
for (let i = 1; i <= a.length; i++) {
|
|
68
|
+
let diag = row[0]!;
|
|
69
|
+
row[0] = i;
|
|
70
|
+
for (let j = 1; j <= b.length; j++) {
|
|
71
|
+
const up = row[j]!;
|
|
72
|
+
row[j] = Math.min(up + 1, row[j - 1]! + 1, diag + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
73
|
+
diag = up;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return row[b.length]!;
|
|
77
|
+
};
|
|
78
|
+
return names
|
|
79
|
+
.map((k) => ({ k, d: dist(n, k) }))
|
|
80
|
+
.filter(({ k, d }) => d <= Math.max(2, Math.floor(name.length / 3)) || k.includes(n) || n.includes(k))
|
|
81
|
+
.sort((a, b) => a.d - b.d)
|
|
82
|
+
.slice(0, 3)
|
|
83
|
+
.map(({ k }) => k);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** The error of an unknown named argument, with the closest names and the list of the arguments. */
|
|
87
|
+
export function unknownArgument(name: string, key: string, list: readonly string[]): TypeError {
|
|
88
|
+
const near = closest(key, list);
|
|
89
|
+
return new TypeError(
|
|
90
|
+
`${name}(): unknown argument "${key}".` + (near.length ? ` Did you mean ${near.join(', ')}?` : '') +
|
|
91
|
+
` The arguments are: ${list.join(', ')}.`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The positional arguments of a call to a function of PineScript parameters `list`, whose last argument may be an
|
|
97
|
+
* object of named arguments (`request.security(sym, "D", () => close, { lookahead: barmerge.lookahead_on })`, or every
|
|
98
|
+
* argument by name). An unknown name throws with the closest names; a name given by position too throws.
|
|
99
|
+
*/
|
|
100
|
+
export function namedArguments(name: string, list: readonly string[], args: readonly unknown[]): unknown[] {
|
|
101
|
+
const last = args[args.length - 1];
|
|
102
|
+
if (!isPlainObject(last)) return [...args];
|
|
103
|
+
const positional = args.slice(0, -1);
|
|
104
|
+
const out = [...positional];
|
|
105
|
+
for (const [key, value] of Object.entries(last)) {
|
|
106
|
+
const index = list.indexOf(key);
|
|
107
|
+
if (index < 0) throw unknownArgument(name, key, list);
|
|
108
|
+
if (index < positional.length && positional[index] !== undefined) {
|
|
109
|
+
throw new TypeError(`${name}(): "${key}" is given twice (by position and by name).`);
|
|
110
|
+
}
|
|
111
|
+
out[index] = value;
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** The positional arguments of a call whose last argument may be named arguments. */
|
|
117
|
+
export function positionalArguments(name: string, args: readonly unknown[]): unknown[] {
|
|
118
|
+
const params = DRAWING_PARAMETERS[name];
|
|
119
|
+
if (!params) return [...args];
|
|
120
|
+
const last = args[args.length - 1];
|
|
121
|
+
if (!isPlainObject(last) || isChartPoint(last)) return [...args];
|
|
122
|
+
// an object at a parameter that takes one (a chart point, a drawing, the points) is that argument
|
|
123
|
+
const at = args.length - 1;
|
|
124
|
+
const firstArg = args[0];
|
|
125
|
+
const positionalList =
|
|
126
|
+
params.point !== undefined && typeof firstArg === 'object' && firstArg !== null && !(firstArg instanceof Series) && at > 0
|
|
127
|
+
? params.point
|
|
128
|
+
: params.coords;
|
|
129
|
+
if (at > 0 && OBJECT_PARAMETERS.has(positionalList[at] ?? '')) return [...args];
|
|
130
|
+
const positional = args.slice(0, -1);
|
|
131
|
+
const first = positional.length ? positional[0] : last.point ?? last.first_point ?? last.top_left;
|
|
132
|
+
const usesPoint = params.point !== undefined && typeof first === 'object' && first !== null && !(first instanceof Series);
|
|
133
|
+
const list = usesPoint ? params.point! : params.coords;
|
|
134
|
+
const out = [...positional];
|
|
135
|
+
for (const [key, value] of Object.entries(last)) {
|
|
136
|
+
const index = list.indexOf(key);
|
|
137
|
+
if (index < 0) throw unknownArgument(name, key, list);
|
|
138
|
+
if (index < positional.length && positional[index] !== undefined) {
|
|
139
|
+
throw new TypeError(`${name}(): "${key}" is given twice (by position and by name).`);
|
|
140
|
+
}
|
|
141
|
+
out[index] = value;
|
|
142
|
+
}
|
|
143
|
+
return out;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** The value of each Series argument on the current bar (inside a bar loop); throws outside a loop. */
|
|
147
|
+
export function barValues(name: string, args: unknown[], currentBar: number): unknown[] {
|
|
148
|
+
return args.map((a, k) => {
|
|
149
|
+
if (!(a instanceof Series)) return a;
|
|
150
|
+
if (currentBar < 0) {
|
|
151
|
+
throw new TypeError(
|
|
152
|
+
`${name}(): argument ${k + 1} is a Series, a drawing takes one value: call ${name}() inside eachBar() ` +
|
|
153
|
+
'(e.g. label.new(c.i, c.high, ...)) or pass a number.'
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
const v = a.toArray()[currentBar];
|
|
157
|
+
return v === undefined ? NaN : v;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Wraps the functions of a drawing namespace (`label`, `line`, `box`, `table`, `polyline`, `linefill`): named
|
|
163
|
+
* arguments for the constructors and `table.cell`, Series arguments read on the current bar for every function.
|
|
164
|
+
*/
|
|
165
|
+
export function drawingNamespace<T extends Record<string, unknown>>(namespace: string, members: T, currentBar: () => number): T {
|
|
166
|
+
const out: Record<string, unknown> = {};
|
|
167
|
+
for (const [key, value] of Object.entries(members)) {
|
|
168
|
+
if (typeof value !== 'function') {
|
|
169
|
+
out[key] = value;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const name = `${namespace}.${key}`;
|
|
173
|
+
const fn = value as (...args: unknown[]) => unknown;
|
|
174
|
+
out[key] = function (this: unknown, ...args: unknown[]) {
|
|
175
|
+
return fn.apply(this, barValues(name, positionalArguments(name, args), currentBar()));
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return out as T;
|
|
179
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type declarations of the script globals, for type-checking a script source (plain JavaScript)
|
|
3
|
+
* before it runs. A script body uses every value export of `oakscriptjs/script` but `executeScript` (the host
|
|
4
|
+
* entry) as a global; these declarations give each global its type, so the TypeScript checker reports the
|
|
5
|
+
* mistakes of a script with their line: `close - open` (operators on a Series), a misspelt name (`ta.smaa`), a
|
|
6
|
+
* wrong argument or option, a bad shape or style string.
|
|
7
|
+
*
|
|
8
|
+
* In a project that runs scripts, a `tsconfig.json` next to the scripts, then `npx tsc -p .`:
|
|
9
|
+
*
|
|
10
|
+
* ```json
|
|
11
|
+
* {
|
|
12
|
+
* "compilerOptions": {
|
|
13
|
+
* "allowJs": true, "checkJs": true, "noEmit": true, "strict": true, "noImplicitAny": false,
|
|
14
|
+
* "target": "ES2022", "module": "ESNext", "moduleResolution": "bundler", "moduleDetection": "force",
|
|
15
|
+
* "lib": ["ES2022"], "types": ["oakscriptjs/script/globals"]
|
|
16
|
+
* },
|
|
17
|
+
* "include": ["*.js"]
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* - `lib` leaves out `DOM`: its `open`, `close` and `alert` are other globals.
|
|
22
|
+
* - `moduleDetection: "force"`: each script has its own top-level names (a script has no import or export).
|
|
23
|
+
* - `noImplicitAny: false`: the parameters of a script's own functions have no types (plain JavaScript).
|
|
24
|
+
*
|
|
25
|
+
* @module script/globals
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import type * as S from './index.js';
|
|
29
|
+
|
|
30
|
+
declare global {
|
|
31
|
+
const executeIntrabar: typeof S.executeIntrabar;
|
|
32
|
+
const varip: typeof S.varip;
|
|
33
|
+
const indicator: typeof S.indicator;
|
|
34
|
+
const fixnan: typeof S.fixnan;
|
|
35
|
+
const fill: typeof S.fill;
|
|
36
|
+
const plotshape: typeof S.plotshape;
|
|
37
|
+
const plotchar: typeof S.plotchar;
|
|
38
|
+
const plotarrow: typeof S.plotarrow;
|
|
39
|
+
const bgcolor: typeof S.bgcolor;
|
|
40
|
+
const barcolor: typeof S.barcolor;
|
|
41
|
+
const plotcandle: typeof S.plotcandle;
|
|
42
|
+
const plotbar: typeof S.plotbar;
|
|
43
|
+
const eachBar: typeof S.eachBar;
|
|
44
|
+
const timestamp: typeof S.timestamp;
|
|
45
|
+
const inSession: typeof S.inSession;
|
|
46
|
+
const seriesOf: typeof S.seriesOf;
|
|
47
|
+
const alertcondition: typeof S.alertcondition;
|
|
48
|
+
const holdDrawing: typeof S.holdDrawing;
|
|
49
|
+
const releaseDrawing: typeof S.releaseDrawing;
|
|
50
|
+
const varDrawing: typeof S.varDrawing;
|
|
51
|
+
const StrategyRecorder: typeof S.StrategyRecorder;
|
|
52
|
+
const input: typeof S.input;
|
|
53
|
+
const open: typeof S.open;
|
|
54
|
+
const high: typeof S.high;
|
|
55
|
+
const low: typeof S.low;
|
|
56
|
+
const close: typeof S.close;
|
|
57
|
+
const volume: typeof S.volume;
|
|
58
|
+
const hl2: typeof S.hl2;
|
|
59
|
+
const hlc3: typeof S.hlc3;
|
|
60
|
+
const ohlc4: typeof S.ohlc4;
|
|
61
|
+
const hlcc4: typeof S.hlcc4;
|
|
62
|
+
const ta: typeof S.ta;
|
|
63
|
+
const color: typeof S.color;
|
|
64
|
+
const DEFAULT_OUTPUT_TITLES: typeof S.DEFAULT_OUTPUT_TITLES;
|
|
65
|
+
const plot: typeof S.plot;
|
|
66
|
+
const hline: typeof S.hline;
|
|
67
|
+
const DEFAULT_CANDLE_COLORS: typeof S.DEFAULT_CANDLE_COLORS;
|
|
68
|
+
const strategy: typeof S.strategy;
|
|
69
|
+
const MissingSymbolDataError: typeof S.MissingSymbolDataError;
|
|
70
|
+
const timeframe: typeof S.timeframe;
|
|
71
|
+
const syminfo: typeof S.syminfo;
|
|
72
|
+
const year: typeof S.year;
|
|
73
|
+
const month: typeof S.month;
|
|
74
|
+
const weekofyear: typeof S.weekofyear;
|
|
75
|
+
const dayofmonth: typeof S.dayofmonth;
|
|
76
|
+
const dayofweek: typeof S.dayofweek;
|
|
77
|
+
const hour: typeof S.hour;
|
|
78
|
+
const minute: typeof S.minute;
|
|
79
|
+
const second: typeof S.second;
|
|
80
|
+
const str: typeof S.str;
|
|
81
|
+
const timenow: typeof S.timenow;
|
|
82
|
+
const time: typeof S.time;
|
|
83
|
+
const time_close: typeof S.time_close;
|
|
84
|
+
const time_tradingday: typeof S.time_tradingday;
|
|
85
|
+
const barstate: typeof S.barstate;
|
|
86
|
+
const session: typeof S.session;
|
|
87
|
+
const barmerge: typeof S.barmerge;
|
|
88
|
+
const ticker: typeof S.ticker;
|
|
89
|
+
const request: typeof S.request;
|
|
90
|
+
const line: typeof S.line;
|
|
91
|
+
const label: typeof S.label;
|
|
92
|
+
const box: typeof S.box;
|
|
93
|
+
const linefill: typeof S.linefill;
|
|
94
|
+
const polyline: typeof S.polyline;
|
|
95
|
+
const table: typeof S.table;
|
|
96
|
+
const position: typeof S.position;
|
|
97
|
+
const text: typeof S.text;
|
|
98
|
+
const chart: typeof S.chart;
|
|
99
|
+
const alert: typeof S.alert;
|
|
100
|
+
const Series: typeof S.Series;
|
|
101
|
+
const BarData: typeof S.BarData;
|
|
102
|
+
const na: typeof S.na;
|
|
103
|
+
const nz: typeof S.nz;
|
|
104
|
+
const STRATEGY_DEFAULTS: typeof S.STRATEGY_DEFAULTS;
|
|
105
|
+
const math: typeof S.math;
|
|
106
|
+
const bar_index: typeof S.bar_index;
|
|
107
|
+
const last_bar_index: typeof S.last_bar_index;
|
|
108
|
+
const shape: typeof S.shape;
|
|
109
|
+
const location: typeof S.location;
|
|
110
|
+
const size: typeof S.size;
|
|
111
|
+
const xloc: typeof S.xloc;
|
|
112
|
+
const yloc: typeof S.yloc;
|
|
113
|
+
const extend: typeof S.extend;
|
|
114
|
+
const display: typeof S.display;
|
|
115
|
+
const format: typeof S.format;
|
|
116
|
+
const font: typeof S.font;
|
|
117
|
+
const scale: typeof S.scale;
|
|
118
|
+
const order: typeof S.order;
|
|
119
|
+
const currency: typeof S.currency;
|
|
120
|
+
const adjustment: typeof S.adjustment;
|
|
121
|
+
const compare: typeof S.compare;
|
|
122
|
+
const isInputActive: typeof S.isInputActive;
|
|
123
|
+
/** A Series of the script (`close`, the result of `ta.*`...), for JSDoc types: `@type {Series}`. */
|
|
124
|
+
type Series = S.Series;
|
|
125
|
+
/** The bar handed to an `eachBar()` callback, for JSDoc types. */
|
|
126
|
+
type BarContext = S.BarContext;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export {};
|