pinets 0.9.15 → 0.9.16

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.
@@ -66,6 +66,8 @@ export declare class Context {
66
66
  sDate: number;
67
67
  eDate: number;
68
68
  fullContext: Context;
69
+ viewportLeft: number | undefined;
70
+ viewportRight: number | undefined;
69
71
  pineTSCode: Function | String;
70
72
  inputs: Record<string, any>;
71
73
  constructor({ marketData, source, tickerId, timeframe, limit, sDate, eDate, fullContext, inputs, }: {
@@ -144,11 +146,13 @@ export declare class Context {
144
146
  */
145
147
  iter(source: any): any;
146
148
  /**
147
- * Resolve an iterable yielding [index, value] tuples for `for [i, x] in collection`
149
+ * Resolve an iterable yielding [key, value] tuples for `for [k, v] in collection`
148
150
  * destructuring codegen. PineArrayObject's [Symbol.iterator] yields scalar values, so
149
- * we must explicitly call `.entries()` on the underlying array.
151
+ * we must explicitly call `.entries()` on the underlying array. PineMapObject stores
152
+ * its data on `.map` (a JS Map) — without this branch the fallthrough returned an
153
+ * empty iterator and `for [k,v] in map` silently iterated 0 times.
150
154
  */
151
- entries(source: any): IterableIterator<[number, any]>;
155
+ entries(source: any): IterableIterator<[any, any]>;
152
156
  private _callStack;
153
157
  /**
154
158
  * Cumulative call-path stack. Each entry is the full path from the root to
@@ -57,6 +57,56 @@ export declare class PineTS {
57
57
  * @param mode Alert firing mode
58
58
  */
59
59
  setAlertMode(mode: 'realtime' | 'all'): void;
60
+ private _viewportLeft;
61
+ private _viewportRight;
62
+ private _usesVisibleRange;
63
+ private _lastRunViewport;
64
+ private _lastResult;
65
+ private _lastPineTSCode;
66
+ /**
67
+ * Set the visible range of bars from the host (e.g. chart UI viewport).
68
+ * Affects `chart.left_visible_bar_time` and `chart.right_visible_bar_time`.
69
+ * Defaults derive from `marketData[0]/[last].openTime` if never called.
70
+ *
71
+ * The setter only stores values; it does NOT trigger a re-run. Call
72
+ * `update()` afterwards to apply the change. For scripts that don't
73
+ * reference visible-range built-ins, `update()` is a no-op.
74
+ *
75
+ * @param left openTime of the leftmost visible bar
76
+ * @param right openTime of the rightmost visible bar
77
+ */
78
+ setVisibleRange(left: number, right: number): void;
79
+ /**
80
+ * Whether the loaded script references any visible-range built-in
81
+ * (e.g. `chart.left_visible_bar_time`). Detected statically during
82
+ * transpile. Consumers fanning viewport changes across many indicators
83
+ * should skip non-tagged instances to avoid unnecessary re-runs.
84
+ */
85
+ usesVisibleRange(): boolean;
86
+ /** Current viewport left (undefined if setter never called). */
87
+ get visibleRangeLeft(): number | undefined;
88
+ /** Current viewport right (undefined if setter never called). */
89
+ get visibleRangeRight(): number | undefined;
90
+ /**
91
+ * Smart re-run: executes `run()` only if a re-run is actually needed.
92
+ *
93
+ * - First call: behaves like `run()` (always executes).
94
+ * - Subsequent calls: returns the cached previous result UNLESS the script
95
+ * is viewport-dependent (`usesVisibleRange()`) AND the viewport has
96
+ * changed since the last cached run.
97
+ *
98
+ * The typical pattern for a chart consumer with multiple indicators:
99
+ *
100
+ * // user pans the chart
101
+ * for (const p of indicators) {
102
+ * p.setVisibleRange(left, right);
103
+ * await p.update(code); // no-op for non-viewport indicators
104
+ * }
105
+ *
106
+ * The pineTSCode argument is optional after the first call — the same code
107
+ * is reused. Pass it again only when the script source itself has changed.
108
+ */
109
+ update(pineTSCode?: Indicator | Function | String): Promise<Context>;
60
110
  constructor(source: IProvider | any[], tickerId?: string, timeframe?: string, limit?: number, sDate?: number, eDate?: number);
61
111
  setDebugSettings({ ln, debug }: {
62
112
  ln: boolean;
@@ -98,6 +148,16 @@ export declare class PineTS {
98
148
  * Run the script completely and return the final context (backward compatible behavior)
99
149
  * @private
100
150
  */
151
+ /**
152
+ * Run an already-transpiled PineTS function in this instance — no
153
+ * additional transpile/parse pass. Used by `request.security_lower_tf`'s
154
+ * slow path to execute the slice produced at primary-transpile time
155
+ * (a truncated body containing only the prefix up to the call). The
156
+ * caller is responsible for ensuring `transpiledFn` was produced by
157
+ * this transpiler against the same source — calling this with an
158
+ * arbitrary function is unsafe.
159
+ */
160
+ runPretranspiled(transpiledFn: Function, inputs?: Record<string, any>, periods?: number): Promise<Context>;
101
161
  private _runComplete;
102
162
  /**
103
163
  * Run the script with pagination, yielding results page by page
@@ -186,6 +246,21 @@ export declare class PineTS {
186
246
  * @private
187
247
  */
188
248
  private _transpileCode;
249
+ /**
250
+ * Static analysis on the transpiled function body to detect references to
251
+ * host-bound built-ins (currently visible-range; extensible via
252
+ * VIEWPORT_DEPENDENT_BUILTINS). Comments are stripped during pine2js, so
253
+ * scanning the post-transpile output is comment-safe.
254
+ *
255
+ * Why post-transpile (not regex on Pine source): a `chart.left_visible_bar_time`
256
+ * literal inside a // comment would be a false positive at the source level.
257
+ * After pine2js, only live code remains.
258
+ *
259
+ * Why regex (not AST visitor): `chart` is a reserved namespace in
260
+ * KNOWN_NAMESPACES — Pine scripts cannot shadow it with a local identifier,
261
+ * so a whole-word match on `chart.<prop>` is unambiguous.
262
+ */
263
+ private _detectViewportUsage;
189
264
  /**
190
265
  * Execute iterations from startIdx to endIdx, updating the context
191
266
  * @private
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Pine Script `ticker.*` namespace.
3
+ *
4
+ * The methods here construct "ticker ID" strings that are passed to
5
+ * `request.security` / `request.security_lower_tf` to fetch data for a
6
+ * specific symbol — potentially with extra modifiers (session,
7
+ * adjustment, non-standard chart type). PineTS' data providers serve
8
+ * standard candles only; chart-type modifiers (Heikin-Ashi, Renko,
9
+ * Kagi, Line Break, Point & Figure) are silently dropped at the
10
+ * `request.security` boundary, since we can't render alternative
11
+ * bar-construction algorithms from the raw OHLCV feed.
12
+ *
13
+ * For the plain "no-modifier" cases — which cover virtually every
14
+ * real-world Pine script — the returned tickerid strings match
15
+ * TradingView's exact log output, so automation tests pass strictly.
16
+ * Non-default `adjustment` values trigger TV's encoded
17
+ * `={"adjustment":"…","symbol":"…"}` form; PineTS only emits the
18
+ * plain symbol there (since `request.security` doesn't honor
19
+ * adjustment either). Document as a known divergence.
20
+ */
21
+ export declare class Ticker {
22
+ private context;
23
+ constructor(context: any);
24
+ /**
25
+ * Type B param wrapper — extract scalar from series/primitive.
26
+ * Used by the transpiler to wrap ticker.* arguments.
27
+ */
28
+ param(source: any, index?: number, _name?: string): any;
29
+ /**
30
+ * ticker.inherit(from_tickerid, symbol) → simple string
31
+ *
32
+ * Returns a ticker ID that uses `symbol` and inherits modifier
33
+ * settings (session, currency, adjustment, chart type) from
34
+ * `from_tickerid`. For data-fetching purposes the result is
35
+ * effectively `symbol` — modifiers can't be honored without a TV
36
+ * datafeed, and `symbol` is what `request.security` needs.
37
+ */
38
+ inherit(_from_tickerid: any, symbol: any): string;
39
+ /**
40
+ * ticker.new(prefix, ticker, session?, adjustment?, ...) → simple string
41
+ *
42
+ * Returns "prefix:ticker". Modifier arguments are accepted but
43
+ * ignored — see class-level note. Returns an empty string if
44
+ * either prefix or ticker is empty (matches TV).
45
+ */
46
+ new(prefix: any, ticker: any, _session?: any, _adjustment?: any, _backadjustment?: any, _settlement_as_close?: any): string;
47
+ /**
48
+ * ticker.modify(tickerid, session?, adjustment?, ...) → simple string
49
+ *
50
+ * Returns the tickerid unchanged — modifier args are accepted but
51
+ * ignored.
52
+ */
53
+ modify(tickerid: any, _session?: any, _adjustment?: any, _backadjustment?: any, _settlement_as_close?: any): string;
54
+ /**
55
+ * ticker.standard(symbol?) → simple string
56
+ *
57
+ * Returns the symbol stripped of any non-standard chart-type
58
+ * modifiers. Since PineTS doesn't synthesise non-standard chart
59
+ * types in the first place, this is effectively a pass-through
60
+ * (the standard form IS what our providers serve). If `symbol` is
61
+ * undefined, falls back to `syminfo.tickerid`.
62
+ */
63
+ standard(symbol?: any): string;
64
+ /**
65
+ * ticker.heikinashi(symbol) → simple string
66
+ *
67
+ * In TV this returns an encoded tickerid that instructs the
68
+ * datafeed to deliver Heikin-Ashi bars. PineTS' providers don't
69
+ * synthesise HA candles, so we return the plain symbol — downstream
70
+ * `request.security` fetches standard candles, NOT HA-transformed
71
+ * ones. Behavior diverges from TV when the script depends on the
72
+ * HA values matching TV's HA computation. Documented limitation.
73
+ */
74
+ heikinashi(symbol: any): string;
75
+ /**
76
+ * ticker.renko(symbol, style?, param?, request_wicks?, source?) → simple string
77
+ *
78
+ * Stub: returns the plain symbol. See heikinashi() note.
79
+ */
80
+ renko(symbol: any, _style?: any, _param?: any, _request_wicks?: any, _source?: any): string;
81
+ /**
82
+ * ticker.kagi(symbol, reversal) → simple string
83
+ *
84
+ * Stub: returns the plain symbol. See heikinashi() note.
85
+ */
86
+ kagi(symbol: any, _reversal?: any): string;
87
+ /**
88
+ * ticker.linebreak(symbol, number_of_lines) → simple string
89
+ *
90
+ * Stub: returns the plain symbol. See heikinashi() note.
91
+ */
92
+ linebreak(symbol: any, _number_of_lines?: any): string;
93
+ /**
94
+ * ticker.pointfigure(symbol, source, style, param, reversal) → simple string
95
+ *
96
+ * Stub: returns the plain symbol. See heikinashi() note.
97
+ */
98
+ pointfigure(symbol: any, _source?: any, _style?: any, _param?: any, _reversal?: any): string;
99
+ /**
100
+ * Coerce a runtime value to a plain string. Handles Series wrappers
101
+ * (used by the transpiler), `na`/null/undefined, and primitives.
102
+ */
103
+ private _coerce;
104
+ }
@@ -1,6 +1,7 @@
1
1
  export declare const KNOWN_NAMESPACES: string[];
2
2
  export declare const NAMESPACES_LIKE: string[];
3
3
  export declare const ASYNC_METHODS: string[];
4
+ export declare const VIEWPORT_DEPENDENT_BUILTINS: string[];
4
5
  export declare const FACTORY_METHODS: string[];
5
6
  export declare const NAMESPACE_COLLISION_NAMES: Set<string>;
6
7
  export declare const JS_RESERVED_WORDS: Set<string>;
@@ -0,0 +1 @@
1
+ export declare function buildLtfSlices(ast: any): Record<string, Function>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinets",
3
- "version": "0.9.15",
3
+ "version": "0.9.16",
4
4
  "description": "Run Pine Script anywhere. PineTS is an open-source transpiler and runtime that brings Pine Script logic to Node.js and the browser with 1:1 syntax compatibility. Reliably write, port, and run indicators or strategies on your own infrastructure.",
5
5
  "keywords": [
6
6
  "Pine Script",