pinets 0.9.22 → 0.9.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/pinets.min.browser.es.js +28 -28
- package/dist/pinets.min.browser.es.js.map +1 -1
- package/dist/pinets.min.browser.js +28 -28
- package/dist/pinets.min.browser.js.map +1 -1
- package/dist/pinets.min.cjs +28 -28
- package/dist/pinets.min.cjs.map +1 -1
- package/dist/pinets.min.es.js +28 -28
- package/dist/pinets.min.es.js.map +1 -1
- package/dist/types/Indicator/Indicator.class.d.ts +7 -6
- package/dist/types/Indicator/inputProxy.d.ts +9 -5
- package/dist/types/Indicator/keyedProxy.d.ts +8 -0
- package/dist/types/Indicator/types.d.ts +1 -0
- package/dist/types/namespaces/color/PineColor.d.ts +23 -0
- package/dist/types/namespaces/input/types.d.ts +7 -0
- package/dist/types/namespaces/strategy/types.d.ts +12 -0
- package/dist/types/namespaces/strategy/utils.d.ts +74 -12
- package/package.json +1 -1
|
@@ -59,16 +59,17 @@ export declare class Indicator {
|
|
|
59
59
|
/** True iff the script references any built-in in `VIEWPORT_DEPENDENT_BUILTINS`. */
|
|
60
60
|
usesVisibleRange(): boolean;
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
* Input override map used by the runtime (read by
|
|
63
63
|
* `input.utils.resolveInput`). Composed at call time so live mutations
|
|
64
64
|
* to `.input` between `pine.run()` calls are picked up automatically.
|
|
65
65
|
*
|
|
66
|
-
*
|
|
67
|
-
* 1. Legacy constructor `inputs`
|
|
68
|
-
* 2. Explicit
|
|
66
|
+
* Keys are mixed by design and resolved in this precedence by the runtime:
|
|
67
|
+
* 1. Legacy constructor `inputs` map — TITLE-keyed (back-compat)
|
|
68
|
+
* 2. Explicit `.input[...]` writes — VARID-keyed (canonical);
|
|
69
|
+
* resolveInput checks varId before title, so these take priority.
|
|
69
70
|
*
|
|
70
|
-
* Defaults are NOT included — the runtime falls back to `defval` when
|
|
71
|
-
*
|
|
71
|
+
* Defaults are NOT included — the runtime falls back to `defval` when no
|
|
72
|
+
* override key matches.
|
|
72
73
|
*/
|
|
73
74
|
getRuntimeInputs(): Record<string, unknown>;
|
|
74
75
|
/**
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import type { IPineInput } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Build the live `.input` view exposed on an `Indicator` instance.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Keyed by **varId** (the assigned variable name) as the canonical, primary
|
|
6
|
+
* override key, with the input's **title** registered as a secondary alias.
|
|
7
|
+
* This makes every input overridable by a stable, unique handle — robust to
|
|
8
|
+
* empty or duplicated titles — while `.input['Title']` keeps working for the
|
|
9
|
+
* common case (unique, non-empty titles). When two inputs share a title, the
|
|
10
|
+
* title aliases the first; the second is reachable only by its varId.
|
|
7
11
|
*
|
|
8
12
|
* Backing machinery lives in `keyedProxy.ts` and is shared with `.prop`.
|
|
9
13
|
*/
|
|
10
|
-
export declare function buildInputProxy(metas: IPineInput[], onSet?: (
|
|
14
|
+
export declare function buildInputProxy(metas: IPineInput[], onSet?: (key: string) => void): {
|
|
11
15
|
proxy: Record<string, unknown>;
|
|
12
16
|
values: Record<string, unknown>;
|
|
13
|
-
|
|
17
|
+
metaByKey: Map<string, IPineInput>;
|
|
14
18
|
};
|
|
@@ -20,6 +20,14 @@ export interface KeyedSchemaEntry {
|
|
|
20
20
|
options?: unknown[];
|
|
21
21
|
minval?: number;
|
|
22
22
|
maxval?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Secondary keys that also resolve to this entry (e.g. an input's title
|
|
25
|
+
* aliasing its varId). The canonical `key` always takes priority; an alias
|
|
26
|
+
* is registered only if not already claimed by a canonical key or an
|
|
27
|
+
* earlier entry. Values/overrides are stored under the canonical key, so
|
|
28
|
+
* reading or writing via an alias hits the same slot.
|
|
29
|
+
*/
|
|
30
|
+
aliases?: string[];
|
|
23
31
|
}
|
|
24
32
|
export interface BuildKeyedProxyResult {
|
|
25
33
|
proxy: Record<string, unknown>;
|
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve any static color value to its `[r, g, b, a]` components (a in
|
|
3
|
+
* 0..1). Accepts:
|
|
4
|
+
* - `#RRGGBB` / `#RRGGBBAA` hex
|
|
5
|
+
* - `rgb(r,g,b)` / `rgba(r,g,b,a)` strings
|
|
6
|
+
* - a named constant, with or without the namespace: `color.red` / `red`
|
|
7
|
+
* Returns null for anything it can't parse as a color.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveColorToRgba(value: unknown): [number, number, number, number] | null;
|
|
10
|
+
/**
|
|
11
|
+
* Format `[r, g, b, a]` (a in 0..1) as a canonical 8-digit RGBA hex string
|
|
12
|
+
* `#RRGGBBAA` (uppercase, alpha byte ALWAYS present — `FF` = fully opaque).
|
|
13
|
+
*/
|
|
14
|
+
export declare function rgbaToHex8(r: number, g: number, b: number, a: number): string;
|
|
15
|
+
/**
|
|
16
|
+
* Normalize any color value to a canonical 8-digit RGBA hex string
|
|
17
|
+
* `#RRGGBBAA` (see {@link rgbaToHex8}). Accepts every shape a color input
|
|
18
|
+
* can carry (hex, rgb()/rgba(), named constant). Values it can't parse as
|
|
19
|
+
* a color are returned unchanged, so non-color data passes through
|
|
20
|
+
* untouched. Used by `Indicator.getInputsMeta()` to present color-input
|
|
21
|
+
* defaults in a single canonical form.
|
|
22
|
+
*/
|
|
23
|
+
export declare function normalizeColorToRgbaHex(value: unknown): unknown;
|
|
1
24
|
/**
|
|
2
25
|
* PineColor implements the Pine Script `color` namespace.
|
|
3
26
|
*
|
|
@@ -11,4 +11,11 @@ export type InputOptions = {
|
|
|
11
11
|
confirm?: boolean;
|
|
12
12
|
display?: string;
|
|
13
13
|
active?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Transpiler-injected handle: the variable the input is assigned to
|
|
16
|
+
* (`len = input.int(…)` → "len"). Popped from the call args by
|
|
17
|
+
* parseInputOptions and used as the PRIMARY override key by resolveInput
|
|
18
|
+
* (title is the secondary fallback). Absent for non-transpiled JS calls.
|
|
19
|
+
*/
|
|
20
|
+
__varId?: string;
|
|
14
21
|
};
|
|
@@ -68,6 +68,14 @@ export interface Trade {
|
|
|
68
68
|
max_drawdown?: number;
|
|
69
69
|
max_runup?: number;
|
|
70
70
|
status: 'open' | 'closed';
|
|
71
|
+
/**
|
|
72
|
+
* PHYSICAL entry price of this lot, immutable — used to compute
|
|
73
|
+
* per-lot exit-bracket levels (strategy.exit profit/loss ticks).
|
|
74
|
+
* Distinct from `entry_price`, which is the LEDGER value and can be
|
|
75
|
+
* swapped by FIFO entry/exit pairing when a newer lot's bracket fills
|
|
76
|
+
* before an older lot's (TV ledger convention).
|
|
77
|
+
*/
|
|
78
|
+
_bracket_entry?: number;
|
|
71
79
|
}
|
|
72
80
|
/**
|
|
73
81
|
* A pending or filled order tracked internally by the engine.
|
|
@@ -153,6 +161,10 @@ export interface StrategyState {
|
|
|
153
161
|
equity_at_drawdown_peak: number;
|
|
154
162
|
max_drawdown_percent_value: number;
|
|
155
163
|
max_runup_percent_value: number;
|
|
164
|
+
sharpe_ratio: number;
|
|
165
|
+
sortino_ratio: number;
|
|
166
|
+
_monthly_equity?: number[];
|
|
167
|
+
_last_month_key?: number;
|
|
156
168
|
wintrades: number;
|
|
157
169
|
losstrades: number;
|
|
158
170
|
eventrades: number;
|
|
@@ -136,7 +136,7 @@ export declare function closePartialPosition(context: any, qtyToClose: number, e
|
|
|
136
136
|
* Wraps `closePartialPosition` by temporarily reorganizing `opentrades` so
|
|
137
137
|
* the matching trades sit at the head of the FIFO queue.
|
|
138
138
|
*/
|
|
139
|
-
export declare function closeMatching(context: any, fromEntry: string | undefined, qtyToClose: number, exitPrice: number, exitTime: number, closeInfo?: CloseInfo): void;
|
|
139
|
+
export declare function closeMatching(context: any, fromEntry: string | undefined, qtyToClose: number, exitPrice: number, exitTime: number, closeInfo?: CloseInfo, specificTradeId?: string): void;
|
|
140
140
|
/**
|
|
141
141
|
* Process exit-category orders each bar (after entry-order fills, before the
|
|
142
142
|
* user script runs). Handles:
|
|
@@ -146,18 +146,57 @@ export declare function closeMatching(context: any, fromEntry: string | undefine
|
|
|
146
146
|
* triggers evaluated against current bar's high/low. Trailing-stop
|
|
147
147
|
* peak (trade.trail_peak) is updated each bar even when not triggered.
|
|
148
148
|
*/
|
|
149
|
-
export declare function processExitOrders(context: any): void;
|
|
149
|
+
export declare function processExitOrders(context: any, phase?: 'open' | 'intrabar'): void;
|
|
150
|
+
/**
|
|
151
|
+
* Apply a SECOND margin call scheduled by the phantom re-check (see
|
|
152
|
+
* processMarginCall). TV books that fill at the PREVIOUS bar's close,
|
|
153
|
+
* AFTER the script's on-close evaluation — so the script and any order
|
|
154
|
+
* it queued saw the pre-MC#2 position. PineTS mirrors this by booking
|
|
155
|
+
* the fill at the very start of the NEXT bar, before entries process:
|
|
156
|
+
* a reversal queued at the MC bar's close (qty frozen at queue time)
|
|
157
|
+
* then naturally overshoots by exactly q2, reproducing TV's phantom
|
|
158
|
+
* opposite-side position (xlsx-confirmed: 2021-10-02 reversal long
|
|
159
|
+
* 5.263108 = 5 + 0.263108).
|
|
160
|
+
*
|
|
161
|
+
* Same-direction (non-reversal) entries queued on the MC bar are
|
|
162
|
+
* CANCELED — TV's transient post-MC state rejects them (2022-04-19: the
|
|
163
|
+
* add queued at the 04-18 close never filled; the next add was accepted
|
|
164
|
+
* a bar later). Opposite-direction reversals are unaffected (E1), and a
|
|
165
|
+
* close-MC that flattens the position leaves nothing to gate (IC=900k
|
|
166
|
+
* experiment: next-open entry from flat was admitted).
|
|
167
|
+
*/
|
|
168
|
+
export declare function applyPendingCloseMarginCall(context: any): void;
|
|
150
169
|
/**
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
|
|
170
|
+
* True when the bar's first intra-bar move is ADVERSE for the current
|
|
171
|
+
* position (TV broker-emulator path assumption: open closer to high →
|
|
172
|
+
* open→high→low→close; open closer to low → open→low→high→close).
|
|
173
|
+
* Used to path-order the margin-call checkpoint against exit fills.
|
|
174
|
+
*/
|
|
175
|
+
export declare function isAdverseFirstBar(context: any): boolean;
|
|
176
|
+
/**
|
|
177
|
+
* Margin-call check (TV broker emulator) at one of two intra-bar
|
|
178
|
+
* CHECKPOINTS along the assumed price path:
|
|
179
|
+
*
|
|
180
|
+
* 'open' — right after entries fill at the bar's open: equity and
|
|
181
|
+
* required margin evaluated AT THE OPEN, liquidation fills
|
|
182
|
+
* at the open price.
|
|
183
|
+
* 'extreme' — at the bar's adverse extreme (low for longs, high for
|
|
184
|
+
* shorts), liquidation fills at the extreme itself — the
|
|
185
|
+
* pessimistic broker model (intra-bar tick order unknown).
|
|
186
|
+
* 'close' — at the bar's close, after all exits: if the (possibly
|
|
187
|
+
* already-trimmed) position still breaches at the closing
|
|
188
|
+
* price, another partial liquidation fills at the close.
|
|
189
|
+
* Evidence: 2021-10-01 (profit QA) shows TWO same-bar MC
|
|
190
|
+
* prices — 4×cover at the high, then a further 0.263108
|
|
191
|
+
* at 48,147.38 (the close).
|
|
156
192
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
193
|
+
* TV checks margin along the path, interleaved with exit fills — proven
|
|
194
|
+
* by the MC-ordering probe (BTCUSDT 1D, 2026-02-05): a 5-lot short
|
|
195
|
+
* entered at the open was split within one bar into MC 0.00228 at the
|
|
196
|
+
* OPEN price, MC 0.0888 at the high, then a TP fill of 4.90892 at the
|
|
197
|
+
* lows. The caller orders the 'extreme' checkpoint BEFORE exit
|
|
198
|
+
* processing on adverse-first bars and AFTER it on favorable-first bars
|
|
199
|
+
* (favorable exits free margin before the adverse extreme is reached).
|
|
161
200
|
*
|
|
162
201
|
* Runs for ALL margin percentages including 100%. At 100% margin the
|
|
163
202
|
* trader still needs full notional collateral; adverse price movement
|
|
@@ -166,7 +205,7 @@ export declare function processExitOrders(context: any): void;
|
|
|
166
205
|
* (the "Margin calls" stat in the Strategy Tester is non-zero on 100%
|
|
167
206
|
* margin runs whenever a position's mark-to-market loss exceeds equity).
|
|
168
207
|
*/
|
|
169
|
-
export declare function processMarginCall(context: any): void;
|
|
208
|
+
export declare function processMarginCall(context: any, checkpoint?: 'open' | 'extreme' | 'close'): void;
|
|
170
209
|
/**
|
|
171
210
|
* End-of-bar finalize: refresh equity at CLOSE and latch
|
|
172
211
|
* `strategy.max_drawdown` / `strategy.max_runup` using the bar's H/L. Runs
|
|
@@ -174,6 +213,29 @@ export declare function processMarginCall(context: any): void;
|
|
|
174
213
|
* of whether the strategy uses exit orders.
|
|
175
214
|
*/
|
|
176
215
|
export declare function finalizeStrategyBar(context: any): void;
|
|
216
|
+
/**
|
|
217
|
+
* End-of-run finalize: compute the risk-adjusted performance ratios
|
|
218
|
+
* (Sharpe / Sortino) from the monthly equity curve captured during the
|
|
219
|
+
* run. Called ONCE after the last bar (see PineTS.class.ts).
|
|
220
|
+
*
|
|
221
|
+
* TV broker-emulator formula (confirmed against the Help Center docs and
|
|
222
|
+
* reverse-engineered to the third decimal across 7 QA datasets,
|
|
223
|
+
* 2026-06-15):
|
|
224
|
+
* - Sample the MARK-TO-MARKET equity at each calendar month's close.
|
|
225
|
+
* - Monthly simple returns rᵢ = Eᵢ / Eᵢ₋₁ − 1, anchored at the initial
|
|
226
|
+
* capital (the first return runs from initial_capital to month 1).
|
|
227
|
+
* - MR = mean(rᵢ); RFR = risk_free_rate / 100 / 12 (annual % → monthly).
|
|
228
|
+
* - Sharpe = (MR − RFR) / SD, SD = √(Σ(rᵢ − MR)² / N) (population).
|
|
229
|
+
* - Sortino = (MR − RFR) / DD, DD = √(Σ min(0, rᵢ − RFR)² / N)
|
|
230
|
+
* (downside deviation over ALL N returns, target = RFR — per TV's
|
|
231
|
+
* documented DD = sqrt(sum(min(0, Xᵢ − T))² / N)).
|
|
232
|
+
* - No annualization.
|
|
233
|
+
*
|
|
234
|
+
* Note: the ratios are only as accurate as the bar-by-bar equity path;
|
|
235
|
+
* they ride on the strategy engine's mark-to-market fidelity. With < 2
|
|
236
|
+
* monthly returns (very short backtests) they are left at 0.
|
|
237
|
+
*/
|
|
238
|
+
export declare function finalizeStrategyRun(context: any): void;
|
|
177
239
|
/**
|
|
178
240
|
* Initialize strategy state
|
|
179
241
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinets",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.23",
|
|
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",
|