openpinescript 0.0.0-stage → 0.1.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/LICENSE +674 -0
- package/README.md +346 -2
- package/dist/cli.mjs +108686 -0
- package/dist/index.cjs +108670 -0
- package/dist/index.mjs +108624 -0
- package/dist/types/index.d.ts +31 -0
- package/dist/types/parser/v1/generated/PineV1Lexer.d.ts +66 -0
- package/dist/types/parser/v1/generated/PineV1Parser.d.ts +555 -0
- package/dist/types/parser/v1/generated/PineV1ParserVisitor.d.ts +318 -0
- package/dist/types/parser/v1/index.d.ts +39 -0
- package/dist/types/parser/v2/generated/PineV2Lexer.d.ts +67 -0
- package/dist/types/parser/v2/generated/PineV2Parser.d.ts +568 -0
- package/dist/types/parser/v2/generated/PineV2ParserVisitor.d.ts +325 -0
- package/dist/types/parser/v2/index.d.ts +2 -0
- package/dist/types/parser/v3/generated/PineV3Lexer.d.ts +67 -0
- package/dist/types/parser/v3/generated/PineV3Parser.d.ts +568 -0
- package/dist/types/parser/v3/generated/PineV3ParserVisitor.d.ts +325 -0
- package/dist/types/parser/v3/index.d.ts +2 -0
- package/dist/types/parser/v4/generated/PineV4Lexer.d.ts +86 -0
- package/dist/types/parser/v4/generated/PineV4Parser.d.ts +673 -0
- package/dist/types/parser/v4/generated/PineV4ParserVisitor.d.ts +367 -0
- package/dist/types/parser/v4/index.d.ts +2 -0
- package/dist/types/parser/v5/generated/PineV5Lexer.d.ts +95 -0
- package/dist/types/parser/v5/generated/PineV5Parser.d.ts +964 -0
- package/dist/types/parser/v5/generated/PineV5ParserVisitor.d.ts +521 -0
- package/dist/types/parser/v5/index.d.ts +2 -0
- package/dist/types/parser/v6/generated/PineV6Lexer.d.ts +98 -0
- package/dist/types/parser/v6/generated/PineV6Parser.d.ts +984 -0
- package/dist/types/parser/v6/generated/PineV6ParserVisitor.d.ts +528 -0
- package/dist/types/parser/v6/index.d.ts +2 -0
- package/dist/types/runtime/v1/Series.d.ts +61 -0
- package/dist/types/runtime/v1/broker/Broker.d.ts +325 -0
- package/dist/types/runtime/v1/broker/index.d.ts +158 -0
- package/dist/types/runtime/v1/broker/val.d.ts +28 -0
- package/dist/types/runtime/v1/constDefault.d.ts +11 -0
- package/dist/types/runtime/v1/context.d.ts +1705 -0
- package/dist/types/runtime/v1/footprint.d.ts +32 -0
- package/dist/types/runtime/v1/index.d.ts +7 -0
- package/dist/types/runtime/v1/language-spec.d.ts +12 -0
- package/dist/types/runtime/v1/openTrades.d.ts +12 -0
- package/dist/types/runtime/v1/palette.d.ts +18 -0
- package/dist/types/runtime/v1/session.d.ts +482 -0
- package/dist/types/runtime/v1/sessions.d.ts +31 -0
- package/dist/types/runtime/v1/stateClone.d.ts +19 -0
- package/dist/types/runtime/v1/stdlib/alerts.d.ts +31 -0
- package/dist/types/runtime/v1/stdlib/arrays.d.ts +133 -0
- package/dist/types/runtime/v1/stdlib/barmerge.d.ts +27 -0
- package/dist/types/runtime/v1/stdlib/barstate.d.ts +79 -0
- package/dist/types/runtime/v1/stdlib/cast.d.ts +81 -0
- package/dist/types/runtime/v1/stdlib/chart.d.ts +283 -0
- package/dist/types/runtime/v1/stdlib/color.d.ts +51 -0
- package/dist/types/runtime/v1/stdlib/core.d.ts +162 -0
- package/dist/types/runtime/v1/stdlib/dataset.d.ts +36 -0
- package/dist/types/runtime/v1/stdlib/display.d.ts +50 -0
- package/dist/types/runtime/v1/stdlib/drawings.d.ts +407 -0
- package/dist/types/runtime/v1/stdlib/errors.d.ts +21 -0
- package/dist/types/runtime/v1/stdlib/font.d.ts +20 -0
- package/dist/types/runtime/v1/stdlib/footprint.d.ts +76 -0
- package/dist/types/runtime/v1/stdlib/format.d.ts +57 -0
- package/dist/types/runtime/v1/stdlib/index.d.ts +71 -0
- package/dist/types/runtime/v1/stdlib/input.d.ts +14 -0
- package/dist/types/runtime/v1/stdlib/inputs.d.ts +60 -0
- package/dist/types/runtime/v1/stdlib/late_members.d.ts +97 -0
- package/dist/types/runtime/v1/stdlib/logging.d.ts +31 -0
- package/dist/types/runtime/v1/stdlib/maps.d.ts +55 -0
- package/dist/types/runtime/v1/stdlib/math.d.ts +71 -0
- package/dist/types/runtime/v1/stdlib/matrix.d.ts +201 -0
- package/dist/types/runtime/v1/stdlib/metadata.d.ts +14 -0
- package/dist/types/runtime/v1/stdlib/mtf.d.ts +15 -0
- package/dist/types/runtime/v1/stdlib/renames.d.ts +117 -0
- package/dist/types/runtime/v1/stdlib/renames5.d.ts +113 -0
- package/dist/types/runtime/v1/stdlib/renames6.d.ts +81 -0
- package/dist/types/runtime/v1/stdlib/request.d.ts +207 -0
- package/dist/types/runtime/v1/stdlib/scale.d.ts +19 -0
- package/dist/types/runtime/v1/stdlib/session.d.ts +113 -0
- package/dist/types/runtime/v1/stdlib/sort_field.d.ts +12 -0
- package/dist/types/runtime/v1/stdlib/sources.d.ts +24 -0
- package/dist/types/runtime/v1/stdlib/str.d.ts +117 -0
- package/dist/types/runtime/v1/stdlib/strategy.d.ts +314 -0
- package/dist/types/runtime/v1/stdlib/syminfo.d.ts +209 -0
- package/dist/types/runtime/v1/stdlib/ta.d.ts +409 -0
- package/dist/types/runtime/v1/stdlib/time.d.ts +158 -0
- package/dist/types/runtime/v1/stdlib/trades.d.ts +108 -0
- package/dist/types/runtime/v1/stdlib/ui.d.ts +196 -0
- package/dist/types/runtime/v1/stdlib/v6_members.d.ts +68 -0
- package/dist/types/runtime/v1/timeframes.d.ts +139 -0
- package/dist/types/runtime/v1/zones.d.ts +30 -0
- package/dist/types/transpiler/common/index.d.ts +51 -0
- package/dist/types/transpiler/common/libraries.d.ts +29 -0
- package/dist/types/transpiler/common/parseErrors.d.ts +38 -0
- package/dist/types/transpiler/common/passes/ScopeAnalysis.d.ts +158 -0
- package/dist/types/transpiler/common/passes/TypeRules.d.ts +26 -0
- package/dist/types/transpiler/common/profiles/index.d.ts +96 -0
- package/dist/types/transpiler/common/version.d.ts +40 -0
- package/dist/types/transpiler/v1/ToJsVisitor.d.ts +720 -0
- package/dist/types/transpiler/v2/ToJsVisitor.d.ts +72 -0
- package/dist/types/transpiler/v3/ToJsVisitor.d.ts +87 -0
- package/dist/types/transpiler/v4/ToJsVisitor.d.ts +263 -0
- package/dist/types/transpiler/v5/ToJsVisitor.d.ts +1101 -0
- package/dist/types/transpiler/v6/ToJsVisitor.d.ts +237 -0
- package/dist/types/transpiler/v6/rules.d.ts +94 -0
- package/dist/types/utils/v2/common.d.ts +4 -0
- package/package.json +92 -4
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Footprint construction for `request.footprint()` — the rows, POC, Value Area
|
|
3
|
+
* and imbalances, from the volume-per-level a host supplies.
|
|
4
|
+
*
|
|
5
|
+
* Outside stdlib/ deliberately: every export of a stdlib module is published
|
|
6
|
+
* as a Pine built-in, and this is a helper. The documented rules, and the
|
|
7
|
+
* undocumented choices made here, are listed in ./stdlib/footprint.ts.
|
|
8
|
+
*/
|
|
9
|
+
/** One price level as the host supplies it. */
|
|
10
|
+
export interface FootprintLevel {
|
|
11
|
+
price: number;
|
|
12
|
+
buy: number;
|
|
13
|
+
sell: number;
|
|
14
|
+
}
|
|
15
|
+
export interface Row {
|
|
16
|
+
__builtin: "volume_row";
|
|
17
|
+
down: number;
|
|
18
|
+
up: number;
|
|
19
|
+
buy: number;
|
|
20
|
+
sell: number;
|
|
21
|
+
buyImbalance: boolean;
|
|
22
|
+
sellImbalance: boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface Footprint {
|
|
25
|
+
__builtin: "footprint";
|
|
26
|
+
rows: Row[];
|
|
27
|
+
poc: Row;
|
|
28
|
+
vah: Row;
|
|
29
|
+
val: Row;
|
|
30
|
+
}
|
|
31
|
+
/** Groups levels into rows and derives the footprint, or null when empty. */
|
|
32
|
+
export declare function buildFootprint(levels: readonly FootprintLevel[], rowSize: number, vaPercent: number, imbalancePercent: number): Footprint | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Context } from "./context.js";
|
|
2
|
+
export { Context };
|
|
3
|
+
export declare function run(jsCode: string, ctx: Context, sandbox: any): any;
|
|
4
|
+
export declare function compile(jsCode: string, ctx: Context, sandbox: any): () => any;
|
|
5
|
+
export { Session, runScript, buildRenderModel, PROTOCOL_VERSION, ENGINE_VERSION } from "./session.js";
|
|
6
|
+
export type { Compiled, SimResult, RenderSeries, RenderDelta, EngineError, InputView, Candle, ChartSettings, RunOptions } from "./session.js";
|
|
7
|
+
export type { Drawing, LogEntry, PlotData, FillData, ScriptMeta, SecurityCandle, InputDef, Trade, Position } from "./context.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PineVersion } from "../../transpiler/common/version.js";
|
|
2
|
+
export interface LanguageSpec {
|
|
3
|
+
version: PineVersion;
|
|
4
|
+
/** Reserved words this version recognises, cumulative. */
|
|
5
|
+
keywords: string[];
|
|
6
|
+
/** Every built-in name, including dotted members like `ta.sma`. */
|
|
7
|
+
builtins: string[];
|
|
8
|
+
/** The leading segment of every dotted name — `ta`, `strategy`, `color`. */
|
|
9
|
+
namespaces: string[];
|
|
10
|
+
}
|
|
11
|
+
/** What `version` knows. Sorted, so the output is stable to diff. */
|
|
12
|
+
export declare function languageSpec(version: PineVersion): LanguageSpec;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The open trades: one per filled entry that has not been fully closed.
|
|
3
|
+
*
|
|
4
|
+
* `strategy.opentrades` is their count and `strategy.opentrades.*(n)` index
|
|
5
|
+
* the same list, oldest first, so both read it from here. It is the broker's
|
|
6
|
+
* `position.entries`; a position with no entries recorded (one a test or a
|
|
7
|
+
* host built by hand) is a single trade described by the position itself.
|
|
8
|
+
*
|
|
9
|
+
* Lives outside ./stdlib/ because every export there becomes a Pine built-in.
|
|
10
|
+
*/
|
|
11
|
+
import type { Context, OpenEntry } from "./context.js";
|
|
12
|
+
export declare function openTrades(ctx: Context): readonly OpenEntry[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runtime/v1/palette.ts
|
|
3
|
+
* Colour defaults that depend on the script's version. Lives outside stdlib/ so
|
|
4
|
+
* it is not mistaken for a function scripts can call.
|
|
5
|
+
*/
|
|
6
|
+
import type { Context } from "./context.js";
|
|
7
|
+
/**
|
|
8
|
+
* A default that Pine documents as a colour constant (`color = color.blue`,
|
|
9
|
+
* `textcolor = color.black`), in the PALETTE OF THE SCRIPT'S OWN VERSION.
|
|
10
|
+
* every version carries its own profile palette (v4 blue #2196F3, v5/v6 blue
|
|
11
|
+
* #2962FF, v5 black #363A45, v1–v3 pure RGB), core.ts's values being only a fallback, exactly as a script's own
|
|
12
|
+
* `color.blue` resolves — see createStdlib in stdlib/index.ts.
|
|
13
|
+
*
|
|
14
|
+
* Evidence for v5: TradingView drew `label.new(x, y, "default colours", style =
|
|
15
|
+
* label.style_label_down)` with a #2962FF bubble and dark text (OpenChartingView
|
|
16
|
+
* e2e/tradingview-drawings/page2.png, targets.json "default colours").
|
|
17
|
+
*/
|
|
18
|
+
export declare function paletteColor(ctx: Context, name: "blue" | "black" | "white"): string;
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import type { PineVersion } from "../../transpiler/common/version.js";
|
|
2
|
+
import type { Context as Ctx, ScriptMeta, SecurityCandle, Drawing, LogEntry, Position, EquityPoint } from "./context.js";
|
|
3
|
+
export declare const PROTOCOL_VERSION = 1;
|
|
4
|
+
export declare const ENGINE_VERSION: "v2";
|
|
5
|
+
export interface EngineError {
|
|
6
|
+
phase: "parse" | "transpile" | "runtime";
|
|
7
|
+
/**
|
|
8
|
+
* The Pine source line and column, 1-based line and 0-based column as the
|
|
9
|
+
* compile errors report them. For a runtime error, where the call that
|
|
10
|
+
* raised it is; absent when the error was raised outside any call.
|
|
11
|
+
*/
|
|
12
|
+
line?: number;
|
|
13
|
+
col?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Set when a runtime error was raised inside an imported library: its
|
|
16
|
+
* alias, and the library's own line and column. `line` and `col` then
|
|
17
|
+
* name the call in the user's script that led there.
|
|
18
|
+
*/
|
|
19
|
+
library?: {
|
|
20
|
+
alias: string;
|
|
21
|
+
line: number;
|
|
22
|
+
col: number;
|
|
23
|
+
};
|
|
24
|
+
message: string;
|
|
25
|
+
/** For a runtime error from `runHistory`: the bar (0-based index) it was raised on. */
|
|
26
|
+
bar?: number;
|
|
27
|
+
/** The parser's own text, when `message` was rewritten to say what is wrong. */
|
|
28
|
+
detail?: string;
|
|
29
|
+
severity: "error" | "warning";
|
|
30
|
+
}
|
|
31
|
+
export interface InputView {
|
|
32
|
+
id: string;
|
|
33
|
+
title: string;
|
|
34
|
+
type: string;
|
|
35
|
+
default: any;
|
|
36
|
+
current: any;
|
|
37
|
+
overridden: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The rest of what `input()` was told, so a host can build the control the
|
|
40
|
+
* script asked for rather than guessing one from the type.
|
|
41
|
+
*
|
|
42
|
+
* `input.int(14, "Length", minval = 2, maxval = 50)` is a bounded spinner;
|
|
43
|
+
* `input.string(s, options = [...])` is a dropdown and nothing else will
|
|
44
|
+
* do. The engine has always recorded these — it clamps `minval` and falls
|
|
45
|
+
* back outside `options` — and simply did not pass them on, so every host
|
|
46
|
+
* rendered a bare text box and learnt the bounds by having its value
|
|
47
|
+
* silently changed underneath it.
|
|
48
|
+
*/
|
|
49
|
+
minval?: number;
|
|
50
|
+
maxval?: number;
|
|
51
|
+
step?: number;
|
|
52
|
+
options?: any[];
|
|
53
|
+
tooltip?: string;
|
|
54
|
+
/** `group` and `inline` lay the dialog out; they carry no value. */
|
|
55
|
+
group?: string;
|
|
56
|
+
inline?: string;
|
|
57
|
+
confirm?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/** A `strategy()` / `indicator()` argument a host may override. */
|
|
60
|
+
export interface PropertyView {
|
|
61
|
+
key: string;
|
|
62
|
+
title: string;
|
|
63
|
+
type: "float" | "integer" | "string";
|
|
64
|
+
current: number | string;
|
|
65
|
+
declared: number | string;
|
|
66
|
+
/** The only values a string property accepts, for a dropdown. */
|
|
67
|
+
options?: string[];
|
|
68
|
+
/** A unit to show beside the control — "%", "ticks", "contracts". */
|
|
69
|
+
unit?: string;
|
|
70
|
+
minval?: number;
|
|
71
|
+
/** Which block of TradingView's properties tab the row belongs to. */
|
|
72
|
+
group?: string;
|
|
73
|
+
}
|
|
74
|
+
export interface Compiled {
|
|
75
|
+
protocolVersion: number;
|
|
76
|
+
engineVersion: typeof ENGINE_VERSION;
|
|
77
|
+
meta: ScriptMeta | null;
|
|
78
|
+
inputs: InputView[];
|
|
79
|
+
/** Declaration arguments a host may override; empty for a study. */
|
|
80
|
+
properties: PropertyView[];
|
|
81
|
+
errors: EngineError[];
|
|
82
|
+
}
|
|
83
|
+
type SeriesType = "line" | "candle" | "marker" | "arrow" | "bgcolor" | "barcolor";
|
|
84
|
+
/**
|
|
85
|
+
* One drawable point. `color` is present only where the script set a DIFFERENT
|
|
86
|
+
* colour on that bar than the series default — `plot(close, color = close >
|
|
87
|
+
* open ? green : red)` is ordinary Pine, and a per-series colour cannot express
|
|
88
|
+
* it. A host that ignores the field still draws the right shape in the series
|
|
89
|
+
* colour; one that reads it draws what TradingView draws.
|
|
90
|
+
*/
|
|
91
|
+
export type RenderPoint = {
|
|
92
|
+
value: number;
|
|
93
|
+
color?: string;
|
|
94
|
+
} | {
|
|
95
|
+
open: number;
|
|
96
|
+
high: number;
|
|
97
|
+
low: number;
|
|
98
|
+
close: number;
|
|
99
|
+
color?: string;
|
|
100
|
+
} | {
|
|
101
|
+
color: string;
|
|
102
|
+
} | null;
|
|
103
|
+
export interface RenderSeries {
|
|
104
|
+
id: string;
|
|
105
|
+
title: string;
|
|
106
|
+
type: SeriesType;
|
|
107
|
+
pane: "main" | "sub";
|
|
108
|
+
timeframe?: string;
|
|
109
|
+
color?: string;
|
|
110
|
+
style?: string | number;
|
|
111
|
+
linewidth?: number;
|
|
112
|
+
/**
|
|
113
|
+
* Where a marker sits: `abovebar`, `belowbar`, `top`, `bottom` or
|
|
114
|
+
* `absolute` — `plotshape`'s own `location` argument. Absent for every
|
|
115
|
+
* other series type. Without it a host cannot place a shape, because the
|
|
116
|
+
* `value` of `plotshape(close > open)` is 1, not a price.
|
|
117
|
+
*/
|
|
118
|
+
location?: string;
|
|
119
|
+
/** `plotshape`/`plotchar` text, and its size, when the script set them. */
|
|
120
|
+
text?: string;
|
|
121
|
+
size?: string;
|
|
122
|
+
/**
|
|
123
|
+
* Colour of a marker's text. `plotshape`/`plotchar` `textcolor`, or
|
|
124
|
+
* TradingView's default `color.blue` in the script's own palette when the
|
|
125
|
+
* script gave none (TradingView drew plotshape text with no textcolor in
|
|
126
|
+
* #2962FF on v5; OpenChartingView e2e/tradingview-drawings/page3.png).
|
|
127
|
+
* Present on marker series only.
|
|
128
|
+
*/
|
|
129
|
+
textcolor?: string;
|
|
130
|
+
/**
|
|
131
|
+
* The `offset` the script gave `plot`/`plotshape`/`plotchar`, in bars
|
|
132
|
+
* (negative = left). Present only when it is non-zero.
|
|
133
|
+
*
|
|
134
|
+
* INFORMATIONAL: `data` is already shifted. The value computed on bar `n`
|
|
135
|
+
* sits at index `n + offset`, so a negative offset leaves the last
|
|
136
|
+
* |offset| entries null and a positive one extends `data` past the last
|
|
137
|
+
* bar. A host draws `data[i]` at bar `i` and must not shift it again.
|
|
138
|
+
*/
|
|
139
|
+
offset?: number;
|
|
140
|
+
data: RenderPoint[];
|
|
141
|
+
}
|
|
142
|
+
export interface SimResult {
|
|
143
|
+
protocolVersion: number;
|
|
144
|
+
engineVersion: typeof ENGINE_VERSION;
|
|
145
|
+
meta: ScriptMeta | null;
|
|
146
|
+
barsProcessed: number;
|
|
147
|
+
series: RenderSeries[];
|
|
148
|
+
fills: Array<{
|
|
149
|
+
plotId1: string;
|
|
150
|
+
plotId2: string;
|
|
151
|
+
color: string;
|
|
152
|
+
title: string;
|
|
153
|
+
/**
|
|
154
|
+
* The fill's colour BAR BY BAR, present only when the script gave it
|
|
155
|
+
* more than one.
|
|
156
|
+
*
|
|
157
|
+
* `fill(a, b, color = spanA > spanB ? green : red)` is how every
|
|
158
|
+
* Ichimoku cloud is written, and a fill carrying one colour cannot
|
|
159
|
+
* express it — the model reported whichever colour happened to come
|
|
160
|
+
* first and the cloud drew in that one colour for the whole chart.
|
|
161
|
+
* `null` at a bar means the fill is not drawn there.
|
|
162
|
+
*/
|
|
163
|
+
colors?: Array<string | null>;
|
|
164
|
+
/**
|
|
165
|
+
* `fill(show_last = N)`: the fill covers only the last N bars. Already
|
|
166
|
+
* applied to `colors`, where every earlier bar is `null`; present for
|
|
167
|
+
* a host that wants the number.
|
|
168
|
+
*/
|
|
169
|
+
showLast?: number;
|
|
170
|
+
/**
|
|
171
|
+
* The gradient overload, `fill(a, b, top_value, bottom_value, top_color,
|
|
172
|
+
* bottom_color)`: a vertical gradient between the two plots, `top_color`
|
|
173
|
+
* at the price `top_value` and `bottom_color` at `bottom_value`, each
|
|
174
|
+
* bar's own. The arrays are per bar, `null` where the fill is not
|
|
175
|
+
* drawn. `color` means nothing on a gradient fill.
|
|
176
|
+
*/
|
|
177
|
+
gradient?: true;
|
|
178
|
+
topValues?: Array<number | null>;
|
|
179
|
+
bottomValues?: Array<number | null>;
|
|
180
|
+
topColors?: Array<string | null>;
|
|
181
|
+
bottomColors?: Array<string | null>;
|
|
182
|
+
}>;
|
|
183
|
+
trades: any[];
|
|
184
|
+
/**
|
|
185
|
+
* The position still OPEN at the last bar, which `trades` by definition
|
|
186
|
+
* does not contain — it holds closed trades only. A strategy that is in
|
|
187
|
+
* the market when the data ends has an entry a host should still draw.
|
|
188
|
+
* `size` is 0 while flat.
|
|
189
|
+
*/
|
|
190
|
+
position: Position;
|
|
191
|
+
summary: {
|
|
192
|
+
netProfit: number;
|
|
193
|
+
closedTrades: number;
|
|
194
|
+
winRate: number;
|
|
195
|
+
} | null;
|
|
196
|
+
/**
|
|
197
|
+
* The full performance report, split all / long / short — the rows of
|
|
198
|
+
* TradingView's performance summary tab. Null for a study.
|
|
199
|
+
*/
|
|
200
|
+
performance: Performance | null;
|
|
201
|
+
/**
|
|
202
|
+
* Account value at every bar's close, which is what the overview tab
|
|
203
|
+
* plots. Empty for a study.
|
|
204
|
+
*/
|
|
205
|
+
equity: EquityPoint[];
|
|
206
|
+
/**
|
|
207
|
+
* Every `line`, `box`, `label`, `table`, `polyline` and `linefill` the
|
|
208
|
+
* script created, in creation order, with the bar each was created on.
|
|
209
|
+
*
|
|
210
|
+
* A host draws these itself — they are objects with coordinates, not a
|
|
211
|
+
* series with one value per bar, so they cannot be expressed as a
|
|
212
|
+
* `RenderSeries`. `props` carries the drawing's own fields verbatim
|
|
213
|
+
* (`x1`/`y1`/`x2`/`y2` for a line, `text`/`style`/`color` for a label).
|
|
214
|
+
*/
|
|
215
|
+
drawings: Drawing[];
|
|
216
|
+
/**
|
|
217
|
+
* Everything the script wrote with `log.info` / `log.warning` /
|
|
218
|
+
* `log.error`, each tagged with the bar and timestamp it was emitted on so
|
|
219
|
+
* a host can align it to the chart.
|
|
220
|
+
*/
|
|
221
|
+
logs: LogEntry[];
|
|
222
|
+
alerts: any[];
|
|
223
|
+
errors: EngineError[];
|
|
224
|
+
/**
|
|
225
|
+
* Arguments the script passed that this engine does not implement, and so
|
|
226
|
+
* ignored, as `"function(parameter)"` -- `"fill(display)"`. Empty when the
|
|
227
|
+
* run honoured everything it was given. A host can say so beside a result
|
|
228
|
+
* that differs from TradingView's.
|
|
229
|
+
*/
|
|
230
|
+
droppedArguments: string[];
|
|
231
|
+
/**
|
|
232
|
+
* Things the host got wrong or left unsaid that change what the script
|
|
233
|
+
* computed, in words a person can act on. Empty when there are none.
|
|
234
|
+
* Today: the chart's timeframe and symbol were never set (`Session.setChart`),
|
|
235
|
+
* and a `request.security` / `security_lower_tf` for data the host never
|
|
236
|
+
* supplied (`Session.provideData`), one note per symbol and timeframe.
|
|
237
|
+
*/
|
|
238
|
+
warnings: string[];
|
|
239
|
+
}
|
|
240
|
+
export interface RenderDelta {
|
|
241
|
+
barIndex: number;
|
|
242
|
+
time: number;
|
|
243
|
+
provisional: true;
|
|
244
|
+
series: Array<{
|
|
245
|
+
id: string;
|
|
246
|
+
value?: number;
|
|
247
|
+
ohlc?: [number, number, number, number];
|
|
248
|
+
color?: string;
|
|
249
|
+
}>;
|
|
250
|
+
}
|
|
251
|
+
export interface Candle {
|
|
252
|
+
time: number;
|
|
253
|
+
open: number;
|
|
254
|
+
high: number;
|
|
255
|
+
low: number;
|
|
256
|
+
close: number;
|
|
257
|
+
volume: number;
|
|
258
|
+
}
|
|
259
|
+
/** Options for `Session.runHistory`. */
|
|
260
|
+
export interface RunOptions {
|
|
261
|
+
/**
|
|
262
|
+
* Called as the run advances: `done` bars of `total` have been processed.
|
|
263
|
+
* Roughly every 1% of the bars, and once more at the end. A callback that
|
|
264
|
+
* throws is ignored: a host's progress display cannot fail the run. With
|
|
265
|
+
* no callback the run does nothing extra.
|
|
266
|
+
*/
|
|
267
|
+
onProgress?: (done: number, total: number) => void;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* One column of TradingView's performance summary, which reports every figure
|
|
271
|
+
* three times: over all trades, over the long ones and over the short ones.
|
|
272
|
+
*
|
|
273
|
+
* Where TradingView publishes a definition this follows it:
|
|
274
|
+
*
|
|
275
|
+
* Profit factor gross profit / gross loss
|
|
276
|
+
* Max drawdown the largest peak-to-trough decline
|
|
277
|
+
* % profitable winning trades / total closed trades
|
|
278
|
+
* Sharpe (MR - RFR) / SD, MR the mean return over a monthly
|
|
279
|
+
* trading period and RFR the `risk_free_rate` argument,
|
|
280
|
+
* 2% a year by default
|
|
281
|
+
*
|
|
282
|
+
* Sortino is the same ratio against downside deviation alone, which is the
|
|
283
|
+
* only part of it TradingView states. A column's run-up and drawdown are
|
|
284
|
+
* measured on the cumulative P&L of that column's trades, so the long column
|
|
285
|
+
* answers "how deep did the long side go" rather than restating the whole
|
|
286
|
+
* account's worst moment three times.
|
|
287
|
+
*/
|
|
288
|
+
export interface PerformanceStats {
|
|
289
|
+
netProfit: number;
|
|
290
|
+
netProfitPercent: number;
|
|
291
|
+
grossProfit: number;
|
|
292
|
+
grossLoss: number;
|
|
293
|
+
maxRunup: number;
|
|
294
|
+
maxDrawdown: number;
|
|
295
|
+
maxRunupPercent: number;
|
|
296
|
+
maxDrawdownPercent: number;
|
|
297
|
+
profitFactor: number;
|
|
298
|
+
commissionPaid: number;
|
|
299
|
+
closedTrades: number;
|
|
300
|
+
winningTrades: number;
|
|
301
|
+
losingTrades: number;
|
|
302
|
+
evenTrades: number;
|
|
303
|
+
percentProfitable: number;
|
|
304
|
+
avgTrade: number;
|
|
305
|
+
avgWinningTrade: number;
|
|
306
|
+
avgLosingTrade: number;
|
|
307
|
+
ratioAvgWinAvgLoss: number;
|
|
308
|
+
largestWinningTrade: number;
|
|
309
|
+
largestLosingTrade: number;
|
|
310
|
+
avgBarsInTrades: number;
|
|
311
|
+
avgBarsInWinningTrades: number;
|
|
312
|
+
avgBarsInLosingTrades: number;
|
|
313
|
+
}
|
|
314
|
+
export interface Performance {
|
|
315
|
+
all: PerformanceStats;
|
|
316
|
+
long: PerformanceStats;
|
|
317
|
+
short: PerformanceStats;
|
|
318
|
+
/** Figures that belong to the account rather than to a side of it. */
|
|
319
|
+
initialCapital: number;
|
|
320
|
+
openPL: number;
|
|
321
|
+
openTrades: number;
|
|
322
|
+
maxContractsHeld: number;
|
|
323
|
+
buyHoldReturn: number;
|
|
324
|
+
buyHoldReturnPercent: number;
|
|
325
|
+
sharpeRatio: number;
|
|
326
|
+
sortinoRatio: number;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Sharpe and Sortino over the equity curve.
|
|
330
|
+
*
|
|
331
|
+
* TradingView states the ratio as `(MR - RFR) / SD` with MR "the average
|
|
332
|
+
* return for a monthly trading period", so the curve is reduced to one
|
|
333
|
+
* return per calendar month before anything is averaged. `risk_free_rate` is
|
|
334
|
+
* an ANNUAL percentage — 2 by default — so a month's share of it is
|
|
335
|
+
* `rate / 100 / 12`.
|
|
336
|
+
*
|
|
337
|
+
* Sortino replaces SD with the DOWNSIDE deviation — the same sum of squares,
|
|
338
|
+
* but counting only the shortfall below zero, and still divided by every
|
|
339
|
+
* month rather than by the losing ones. Fewer than two months of data leaves
|
|
340
|
+
* both undefined rather than zero: a single return has no deviation to
|
|
341
|
+
* divide by, and reporting 0 there would read as "no risk".
|
|
342
|
+
*
|
|
343
|
+
* Exported for its own tests. Reaching it through a strategy means finding a
|
|
344
|
+
* fixture whose months are a mix of winners and losers, and the two divisors
|
|
345
|
+
* agree exactly when they are not — so a test driven that way can pass with
|
|
346
|
+
* either formula in place.
|
|
347
|
+
*/
|
|
348
|
+
export declare function riskRatios(curve: EquityPoint[], annualRatePercent: number): {
|
|
349
|
+
sharpeRatio: number;
|
|
350
|
+
sortinoRatio: number;
|
|
351
|
+
};
|
|
352
|
+
export declare function buildRenderModel(ctx: Ctx): Omit<SimResult, "protocolVersion" | "engineVersion" | "errors" | "warnings">;
|
|
353
|
+
/**
|
|
354
|
+
* What the host knows about the chart the script is running on, and the engine
|
|
355
|
+
* cannot learn from OHLCV bars: its timeframe and the symbol's facts.
|
|
356
|
+
*
|
|
357
|
+
* `timeframe` is Pine's own spelling — "1", "5", "60", "240", "D", "W", "M",
|
|
358
|
+
* "12M", "1S" — NOT a charting library's ("5m", "1H"). Everything else is
|
|
359
|
+
* optional and falls back to the engine's defaults (see Context.provideSymbolInfo).
|
|
360
|
+
*/
|
|
361
|
+
export interface ChartSettings {
|
|
362
|
+
symbol: string;
|
|
363
|
+
timeframe: string;
|
|
364
|
+
mintick?: number;
|
|
365
|
+
type?: string;
|
|
366
|
+
currency?: string;
|
|
367
|
+
basecurrency?: string;
|
|
368
|
+
description?: string;
|
|
369
|
+
/** The exchange's IANA zone; `time(tf, session)` evaluates sessions in it. */
|
|
370
|
+
timezone?: string;
|
|
371
|
+
pointvalue?: number;
|
|
372
|
+
session?: string;
|
|
373
|
+
mincontract?: number;
|
|
374
|
+
root?: string;
|
|
375
|
+
}
|
|
376
|
+
/** Message carried by `SimResult.warnings` when the host never called `setChart`. */
|
|
377
|
+
export declare const CHART_NOT_SET_WARNING = "chart not set: timeframe defaults to D and symbol to SYMBOL \u2014 call Session.setChart";
|
|
378
|
+
export declare class Session {
|
|
379
|
+
private js;
|
|
380
|
+
private meta;
|
|
381
|
+
private inputValues;
|
|
382
|
+
private propertyValues;
|
|
383
|
+
private securities;
|
|
384
|
+
private ctx;
|
|
385
|
+
private exec;
|
|
386
|
+
private profile;
|
|
387
|
+
/** Pine Script version detected in the last compile(). */
|
|
388
|
+
pineVersion: PineVersion;
|
|
389
|
+
private chart;
|
|
390
|
+
/**
|
|
391
|
+
* Tell the engine which chart it is running on: the timeframe and the
|
|
392
|
+
* symbol's facts. A host MUST call this — none of it can be derived from
|
|
393
|
+
* bars, and scripts branch on it (`timeframe.period`, `syminfo.type`,
|
|
394
|
+
* session windows in the exchange's `timezone`). It applies to the compile
|
|
395
|
+
* dry run and every `runHistory`; call it again to change the chart.
|
|
396
|
+
* Throws on a timeframe that is not in Pine's format.
|
|
397
|
+
*/
|
|
398
|
+
setChart(chart: ChartSettings): void;
|
|
399
|
+
/**
|
|
400
|
+
* Transpile + validate; a 1-bar dry run on a throwaway context discovers inputs + metadata.
|
|
401
|
+
*
|
|
402
|
+
* `opts.libraries`: sources for the libraries the script imports, keyed by
|
|
403
|
+
* `user/name/version` (see `requiredLibraries` for finding which). An
|
|
404
|
+
* import with no source is a compile error naming the library.
|
|
405
|
+
*/
|
|
406
|
+
compile(source: string, opts?: {
|
|
407
|
+
libraries?: Readonly<Record<string, string>>;
|
|
408
|
+
}): Compiled;
|
|
409
|
+
setInputs(values: Record<string, any>): void;
|
|
410
|
+
/**
|
|
411
|
+
* Override `strategy()` declaration arguments — starting capital,
|
|
412
|
+
* pyramiding — the way TradingView's properties panel does.
|
|
413
|
+
*
|
|
414
|
+
* Unlike `setInputs`, this cannot be applied to a run already in progress:
|
|
415
|
+
* `cash` moves with the first fill, so it is seeded when the script
|
|
416
|
+
* declares itself and never afterwards. The next `runHistory` picks it up.
|
|
417
|
+
*/
|
|
418
|
+
setProperties(values: Record<string, any>): void;
|
|
419
|
+
private currencyRates;
|
|
420
|
+
/**
|
|
421
|
+
* Supplies the daily conversion rate from one currency to another (what
|
|
422
|
+
* `request.currency_rate(from, to)` answers), as `{ time, value }` samples
|
|
423
|
+
* where `time` is the start of the day in ms. A strategy whose
|
|
424
|
+
* `strategy(currency = to)` differs from `syminfo.currency` (= `from`)
|
|
425
|
+
* books its closed trades at the rate in effect at the exit bar.
|
|
426
|
+
*/
|
|
427
|
+
provideCurrencyRate(from: string, to: string, samples: Array<{
|
|
428
|
+
time: number;
|
|
429
|
+
value: number;
|
|
430
|
+
}>): void;
|
|
431
|
+
provideData(symbol: string, resolution: string, candles: SecurityCandle[]): void;
|
|
432
|
+
/**
|
|
433
|
+
* Full historical pass; returns the render model. Builds a FRESH context so
|
|
434
|
+
* the sandbox's series references always match (ctx.reset() would re-create
|
|
435
|
+
* the base series and orphan the sandbox bindings).
|
|
436
|
+
*/
|
|
437
|
+
runHistory(candles: Candle[], opts?: RunOptions): SimResult;
|
|
438
|
+
/** One pass of `runHistory`; null when it must start over (see there). */
|
|
439
|
+
private runHistoryOnce;
|
|
440
|
+
/** The forming bar's latest tick, replayed by `commit()` when no final candle is given. */
|
|
441
|
+
private lastTick;
|
|
442
|
+
/** Live tick on the forming bar (P3). Honors calc_on_every_tick. */
|
|
443
|
+
tick(candle: Candle): RenderDelta;
|
|
444
|
+
/**
|
|
445
|
+
* Close the forming bar. TradingView runs the script one more time as the bar
|
|
446
|
+
* closes: a rollback re-execution on the bar's FINAL candle with
|
|
447
|
+
* `barstate.isconfirmed` true and `isnew` false (rt-confirmed-v6/v5 probes).
|
|
448
|
+
* `finalCandle` is that final OHLCV; without it the last tick's values are used
|
|
449
|
+
* (a bar that never ticked gets no closing execution). A strategy with
|
|
450
|
+
* calc_on_every_tick off executes only here, so this is its first execution
|
|
451
|
+
* (`isnew` true) as well as its confirmed one.
|
|
452
|
+
*/
|
|
453
|
+
commit(finalCandle?: Candle): {
|
|
454
|
+
barIndex: number;
|
|
455
|
+
};
|
|
456
|
+
private deltaForFormingBar;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* `let` declarations in the emitted JS as `var`, and nothing else.
|
|
460
|
+
*
|
|
461
|
+
* A scanner, not a regex: string literals, comments and template literals
|
|
462
|
+
* (including code inside `${…}`) are tracked, and only a whole identifier
|
|
463
|
+
* `let` in code is rewritten -- not `$let`, not `x.let`, not the "let it be"
|
|
464
|
+
* in a script's or an inlined library's string.
|
|
465
|
+
*/
|
|
466
|
+
export declare function letToVar(js: string): string;
|
|
467
|
+
/** One-shot convenience: compile + runHistory. */
|
|
468
|
+
export declare function runScript(source: string, opts?: {
|
|
469
|
+
candles: Candle[];
|
|
470
|
+
inputs?: Record<string, any>;
|
|
471
|
+
properties?: Record<string, any>;
|
|
472
|
+
securities?: Array<{
|
|
473
|
+
symbol: string;
|
|
474
|
+
resolution: string;
|
|
475
|
+
candles: SecurityCandle[];
|
|
476
|
+
}>;
|
|
477
|
+
/** Library sources by import path, as for `Session.compile`. */
|
|
478
|
+
libraries?: Readonly<Record<string, string>>;
|
|
479
|
+
/** The chart, as for `Session.setChart`. Without it the result carries a warning. */
|
|
480
|
+
chart?: ChartSettings;
|
|
481
|
+
}): SimResult;
|
|
482
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where one trading session ends and the next begins.
|
|
3
|
+
*
|
|
4
|
+
* Lives outside `stdlib/` deliberately: everything in that directory is scanned
|
|
5
|
+
* by scripts/common/generate-metadata.ts and anything taking a `ctx` first
|
|
6
|
+
* parameter becomes a BUILT-IN. `opensDay` is a shared helper, not a name any
|
|
7
|
+
* Pine script may call, so it cannot live there.
|
|
8
|
+
*
|
|
9
|
+
* Two built-ins need the same answer and must not drift apart:
|
|
10
|
+
*
|
|
11
|
+
* - `session.isfirstbar` / `session.islastbar`
|
|
12
|
+
* - `ta.vwap`, which restarts its accumulation every session
|
|
13
|
+
*
|
|
14
|
+
* ── Day boundaries ──────────────────────────────────────────────────────────
|
|
15
|
+
*
|
|
16
|
+
* "the day's session" is a calendar day in the EXCHANGE's timezone, and this
|
|
17
|
+
* engine has no timezone. It compares UTC dates, matching ./stdlib/time.ts,
|
|
18
|
+
* whose header states the same convention and the same remedy: a host that
|
|
19
|
+
* supplies bar timestamps already shifted to the exchange timezone gets
|
|
20
|
+
* agreement.
|
|
21
|
+
*
|
|
22
|
+
* This models a 24-hour session, which is right for crypto and wrong for an
|
|
23
|
+
* equity whose session opens at 09:30 — there, an intraday VWAP would restart
|
|
24
|
+
* at midnight instead of at the open. On DAILY and higher timeframes the
|
|
25
|
+
* question does not arise: every bar falls on its own calendar day, so every
|
|
26
|
+
* bar opens a session, and that falls out of the date comparison rather than
|
|
27
|
+
* being special-cased.
|
|
28
|
+
*/
|
|
29
|
+
import { Context } from "./context.js";
|
|
30
|
+
/** Is this bar on a different calendar day from the one before it? */
|
|
31
|
+
export declare function opensDay(ctx: Context): boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copies a built-in's persistent state for the per-bar rollback point.
|
|
3
|
+
*
|
|
4
|
+
* Every stateful call site is snapshotted on every bar (see `call` in
|
|
5
|
+
* ./context.ts), and a state is usually a rolling buffer: `ta.sma` keeps up to
|
|
6
|
+
* 5,000 values. `structuredClone` of that, once per site per bar, was most of
|
|
7
|
+
* the run on a 110,000-bar chart (70% for a script with a few moving averages).
|
|
8
|
+
*
|
|
9
|
+
* States are plain data, so a plain copy does the same job: objects of
|
|
10
|
+
* primitives, arrays of primitives, and those nested. Anything else — a Map, a
|
|
11
|
+
* class instance, a function (which `structuredClone` refuses, and the caller
|
|
12
|
+
* reports), a value reachable twice (whose sharing `structuredClone` keeps) —
|
|
13
|
+
* hands the WHOLE value to `structuredClone`, so what it copies, and what it
|
|
14
|
+
* throws on, is unchanged.
|
|
15
|
+
*
|
|
16
|
+
* Not in stdlib/, where every export becomes a Pine built-in.
|
|
17
|
+
*/
|
|
18
|
+
/** What `structuredClone(v)` returns, faster for plain data. */
|
|
19
|
+
export declare function cloneState<T>(v: T): T;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `alert.*` constants.
|
|
3
|
+
*
|
|
4
|
+
* ── Why they are not in ui.ts beside alert() ────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* Pine spells `alert` as BOTH a function and a namespace — `alert(msg, freq)`
|
|
7
|
+
* and `alert.freq_all`. The registry generator takes a namespace from the NAME
|
|
8
|
+
* of an exported object, and one module cannot export both a function and an
|
|
9
|
+
* object called `alert`.
|
|
10
|
+
*
|
|
11
|
+
* So the pair is split across two files, exactly as `input` already is:
|
|
12
|
+
* ./input.ts holds `input()` and ./inputs.ts holds the `input` object. The
|
|
13
|
+
* merge in ./index.ts then hangs these members off the function object, which
|
|
14
|
+
* is what makes `alert.freq_all` resolvable at the same time as `alert(…)`.
|
|
15
|
+
*
|
|
16
|
+
* ── What the values mean ────────────────────────────────────────────────────
|
|
17
|
+
*
|
|
18
|
+
* They select how often ONE alert() call may re-fire within a single realtime
|
|
19
|
+
* bar. They are recorded on the alert rather than enforced — see the note on
|
|
20
|
+
* alert() in ./ui.ts for why that depends on a tick feed the host supplies.
|
|
21
|
+
*
|
|
22
|
+
* Source: https://www.tradingview.com/pine-script-docs/v4/essential/alerts/
|
|
23
|
+
*/
|
|
24
|
+
export declare const alert: {
|
|
25
|
+
/** Only the first call per realtime bar triggers. TradingView's default. */
|
|
26
|
+
freq_once_per_bar: string;
|
|
27
|
+
/** Triggers only when the realtime bar closes. */
|
|
28
|
+
freq_once_per_bar_close: string;
|
|
29
|
+
/** Every call during the realtime bar triggers. */
|
|
30
|
+
freq_all: string;
|
|
31
|
+
};
|