pinets 0.9.17 → 0.9.19
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/dist/pinets.min.browser.es.js +30 -30
- package/dist/pinets.min.browser.es.js.map +1 -1
- package/dist/pinets.min.browser.js +30 -30
- 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/namespaces/strategy/methods/avg_losing_trade_percent.d.ts +6 -2
- package/dist/types/namespaces/strategy/methods/convert_to_account.d.ts +10 -4
- package/dist/types/namespaces/strategy/methods/convert_to_symbol.d.ts +4 -1
- package/dist/types/namespaces/strategy/methods/margin_liquidation_price.d.ts +16 -6
- package/dist/types/namespaces/strategy/methods/max_drawdown_percent.d.ts +12 -3
- package/dist/types/namespaces/strategy/methods/max_runup_percent.d.ts +15 -3
- package/dist/types/namespaces/strategy/types.d.ts +11 -0
- package/dist/types/namespaces/strategy/utils.d.ts +95 -3
- package/dist/types/transpiler/settings.d.ts +1 -0
- package/package.json +3 -3
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Average per-trade loss (as a
|
|
3
|
-
* NaN when no losers yet.
|
|
2
|
+
* Average per-trade loss (as a SIGNED negative percent) across losing
|
|
3
|
+
* closed trades. NaN when no losers yet.
|
|
4
|
+
*
|
|
5
|
+
* Note: `strategy.avg_losing_trade` (the dollar version) is reported as
|
|
6
|
+
* a POSITIVE magnitude by Pine convention, but `_percent` is signed —
|
|
7
|
+
* negative values, since they represent losses.
|
|
4
8
|
*/
|
|
5
9
|
export declare function avg_losing_trade_percent(context: any): () => number;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Convert a value from the symbol's currency to the account currency.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Pine semantics:
|
|
5
|
+
* - same currency string → return the value unchanged (identity)
|
|
6
|
+
* - different currency strings → return `na` (NaN), since no FX
|
|
7
|
+
* rate is available. String equality is used, not economic
|
|
8
|
+
* equivalence — so nominally pegged pairs like USDC vs USD still
|
|
9
|
+
* return NaN when their currency strings differ.
|
|
10
|
+
*
|
|
11
|
+
* When `syminfo.currency` is undefined we fall back to identity rather
|
|
12
|
+
* than NaN, so synthetic / array-fed datasets without a syminfo block
|
|
13
|
+
* don't get poisoned.
|
|
8
14
|
*/
|
|
9
15
|
export declare function convert_to_account(context: any): (value: number) => number;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Inverse of convert_to_account: from account currency → symbol currency.
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Mirrors convert_to_account's TV-matching behavior: identity passthrough
|
|
5
|
+
* when account and symbol currencies are the same string, NaN when they
|
|
6
|
+
* differ. See convert_to_account.ts for the full rationale.
|
|
4
7
|
*/
|
|
5
8
|
export declare function convert_to_symbol(context: any): (value: number) => number;
|
|
@@ -2,12 +2,22 @@
|
|
|
2
2
|
* Price at which the current leveraged position would be force-liquidated.
|
|
3
3
|
* Returns NaN when flat or when the relevant margin% is 100 (no leverage).
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* short → entry_avg_price * (1 + margin_short / 100)
|
|
5
|
+
* Official TV formula, documented at
|
|
6
|
+
* https://www.tradingview.com/support/solutions/43000717375/ :
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* MarginLiquidationPriceRaw =
|
|
9
|
+
* ((InitialCapital + NetProfit) / (PointValue * AbsPositionSize)
|
|
10
|
+
* − Direction * EntryPrice)
|
|
11
|
+
* / (MarginPercent / 100 − Direction)
|
|
12
|
+
*
|
|
13
|
+
* Where:
|
|
14
|
+
* InitialCapital + NetProfit = realized account equity (initial cash
|
|
15
|
+
* plus closed-trade P&L; excludes openprofit)
|
|
16
|
+
* PointValue = syminfo.pointvalue (1 for crypto, varies
|
|
17
|
+
* for futures contracts)
|
|
18
|
+
* AbsPositionSize = |strategy.position_size|
|
|
19
|
+
* Direction = +1 for long, −1 for short
|
|
20
|
+
* EntryPrice = strategy.position_avg_price
|
|
21
|
+
* MarginPercent = margin_long for longs, margin_short for shorts
|
|
12
22
|
*/
|
|
13
23
|
export declare function margin_liquidation_price(context: any): () => number;
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Maximum drawdown
|
|
3
|
-
*
|
|
2
|
+
* Maximum drawdown percent. Pine's semantic is the RUNNING MAX of
|
|
3
|
+
* `(latched_drawdown / equity_at_that_latch) × 100` across all latch
|
|
4
|
+
* events over the strategy's lifetime — NOT a derived
|
|
5
|
+
* `(current_max_drawdown / current_equity_at_peak) × 100`. The two
|
|
6
|
+
* interpretations diverge when a later latch produces a larger absolute
|
|
7
|
+
* drawdown but a smaller percentage (because equity grew faster than
|
|
8
|
+
* the drawdown), in which case the earlier latch's higher ratio is the
|
|
9
|
+
* reported value.
|
|
10
|
+
*
|
|
11
|
+
* The running max is maintained in `updateEquityPeaks` (utils.ts) on
|
|
12
|
+
* every latch event; this getter is a pure read.
|
|
4
13
|
*/
|
|
5
|
-
export declare function max_drawdown_percent(context: any): () =>
|
|
14
|
+
export declare function max_drawdown_percent(context: any): () => any;
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Maximum equity run-up
|
|
3
|
-
*
|
|
2
|
+
* Maximum equity run-up percent. Mirrors the `max_drawdown_percent`
|
|
3
|
+
* semantic — TV reports the RUNNING MAX of the per-latch ratio,
|
|
4
|
+
* `(latched_runup / equity_at_that_latch) × 100`, across all latches
|
|
5
|
+
* in the strategy's lifetime.
|
|
6
|
+
*
|
|
7
|
+
* In most strategies the runup ratio grows monotonically with each
|
|
8
|
+
* latch, so this matches a derived `(current_max_runup /
|
|
9
|
+
* current_equity_at_runup_peak) × 100`. But in scenarios where a
|
|
10
|
+
* later latch produces a larger absolute runup yet a smaller
|
|
11
|
+
* percentage (because equity grew faster than the runup), TV keeps
|
|
12
|
+
* the highest ratio ever seen — same as the drawdown semantic.
|
|
13
|
+
*
|
|
14
|
+
* The running max is maintained in `updateEquityPeaks` whenever
|
|
15
|
+
* max_runup is latched to a new peak — see utils.ts.
|
|
4
16
|
*/
|
|
5
|
-
export declare function max_runup_percent(context: any): () =>
|
|
17
|
+
export declare function max_runup_percent(context: any): () => any;
|
|
@@ -111,6 +111,10 @@ export interface Order {
|
|
|
111
111
|
immediately?: boolean;
|
|
112
112
|
trail_peak?: number;
|
|
113
113
|
trail_armed?: boolean;
|
|
114
|
+
_isReversalEntry?: boolean;
|
|
115
|
+
_attachedAtReversal?: boolean;
|
|
116
|
+
_isPersistent?: boolean;
|
|
117
|
+
_callsiteId?: string;
|
|
114
118
|
}
|
|
115
119
|
/**
|
|
116
120
|
* Strategy state stored on the Context after a backtest run.
|
|
@@ -144,6 +148,10 @@ export interface StrategyState {
|
|
|
144
148
|
max_runup: number;
|
|
145
149
|
equity_peak: number;
|
|
146
150
|
equity_trough: number;
|
|
151
|
+
equity_at_runup_peak: number;
|
|
152
|
+
equity_at_drawdown_peak: number;
|
|
153
|
+
max_drawdown_percent_value: number;
|
|
154
|
+
max_runup_percent_value: number;
|
|
147
155
|
wintrades: number;
|
|
148
156
|
losstrades: number;
|
|
149
157
|
eventrades: number;
|
|
@@ -173,4 +181,7 @@ export interface StrategyState {
|
|
|
173
181
|
max_position_size?: number;
|
|
174
182
|
};
|
|
175
183
|
risk_halted: boolean;
|
|
184
|
+
_exit_call_history?: Map<string, number>;
|
|
185
|
+
_exit_fallback_counter?: number;
|
|
186
|
+
_exit_fallback_last_bar?: number;
|
|
176
187
|
}
|
|
@@ -3,6 +3,58 @@ import { Order, StrategyState } from './types';
|
|
|
3
3
|
* Parse strategy() function arguments
|
|
4
4
|
*/
|
|
5
5
|
export declare function parseStrategyOptions(args: any[]): any;
|
|
6
|
+
/**
|
|
7
|
+
* Round a stop/limit price to the symbol's mintick grid, AWAY from the
|
|
8
|
+
* reference price (typically the current bar's close at order placement).
|
|
9
|
+
*
|
|
10
|
+
* Pine's broker emulator places stop/limit orders on the mintick grid
|
|
11
|
+
* conservatively — a buy stop at 4188.4541 above current 4184 becomes
|
|
12
|
+
* 4188.46 (ceiling), not 4188.45. This makes the order trigger LATER
|
|
13
|
+
* (requires more price movement), mirroring real-broker order placement.
|
|
14
|
+
*
|
|
15
|
+
* The rule:
|
|
16
|
+
* price > referencePrice → ceil to mintick (push price UP)
|
|
17
|
+
* price < referencePrice → floor to mintick (push price DOWN)
|
|
18
|
+
* price === referencePrice → return as-is
|
|
19
|
+
*
|
|
20
|
+
* Covers all four cases naturally:
|
|
21
|
+
* - Buy stop above current → ceil
|
|
22
|
+
* - Sell stop below current → floor
|
|
23
|
+
* - Buy limit below current → floor
|
|
24
|
+
* - Sell limit above current → ceil
|
|
25
|
+
* - Long TP above entry / SL below entry → ceil / floor
|
|
26
|
+
* - Short TP below entry / SL above entry → floor / ceil
|
|
27
|
+
*
|
|
28
|
+
* For mintick === 0 or undefined (defensive), returns the price unchanged.
|
|
29
|
+
*/
|
|
30
|
+
export declare function roundToMintick(price: number, referencePrice: number, mintick: number): number;
|
|
31
|
+
/**
|
|
32
|
+
* Margin required to hold a position of `qty` contracts at `price`, given
|
|
33
|
+
* the `marginPct` (% of notional that must be posted as collateral). The
|
|
34
|
+
* pointValue factor converts price units to account-currency dollars
|
|
35
|
+
* (1 for crypto, varies for futures).
|
|
36
|
+
*
|
|
37
|
+
* Pine docs (strategy() declaration): `margin_long` / `margin_short` is
|
|
38
|
+
* the percentage of notional held as collateral. 100 = no leverage, 20 =
|
|
39
|
+
* 5× leverage, etc.
|
|
40
|
+
*/
|
|
41
|
+
export declare function computeRequiredMargin(qty: number, price: number, marginPct: number, pointValue: number): number;
|
|
42
|
+
/**
|
|
43
|
+
* Account equity computed AS IF the marketprice were `atPrice` — used to
|
|
44
|
+
* check what equity would be at a hypothetical intra-bar price (e.g. the
|
|
45
|
+
* bar's adverse extreme for a margin-call check).
|
|
46
|
+
*
|
|
47
|
+
* equity_at_price = initial_capital + netprofit + unrealizedPnL_at_price
|
|
48
|
+
*
|
|
49
|
+
* The mark-to-market is computed against EVERY open trade's entry price.
|
|
50
|
+
*/
|
|
51
|
+
export declare function computeEquityAtPrice(context: any, atPrice: number): number;
|
|
52
|
+
/**
|
|
53
|
+
* Total margin currently held by all open positions, valued at `atPrice`.
|
|
54
|
+
* Per-position margin uses `margin_long` for longs and `margin_short` for
|
|
55
|
+
* shorts (Pine semantic — see strategy() declaration).
|
|
56
|
+
*/
|
|
57
|
+
export declare function computeHeldMargin(context: any, atPrice: number): number;
|
|
6
58
|
/**
|
|
7
59
|
* Calculate order quantity based on strategy configuration
|
|
8
60
|
*/
|
|
@@ -51,14 +103,31 @@ export declare function evaluateCatastrophicRiskHalt(strategy: StrategyState): v
|
|
|
51
103
|
* @param price fill price
|
|
52
104
|
* @param time fill time (ms)
|
|
53
105
|
*/
|
|
54
|
-
export declare function openTrade(context: any, entryId: string, direction: number, qty: number, price: number, time: number): void;
|
|
106
|
+
export declare function openTrade(context: any, entryId: string, direction: number, qty: number, price: number, time: number, entryComment?: string, isReversalOpen?: boolean): void;
|
|
55
107
|
/**
|
|
56
108
|
* Close partial or full position.
|
|
57
109
|
*
|
|
58
110
|
* FIFO accounting: closes oldest open trades first. Splits a trade if the
|
|
59
111
|
* close qty is smaller than the trade's remaining qty.
|
|
60
112
|
*/
|
|
61
|
-
export
|
|
113
|
+
export interface CloseInfo {
|
|
114
|
+
/** Which exit leg triggered ('profit'/'loss'/'trailing'), null otherwise. */
|
|
115
|
+
triggerKind?: 'profit' | 'loss' | 'trailing' | null;
|
|
116
|
+
/** Exit order's id, set onto the closed trade as trade.exit_id. */
|
|
117
|
+
exitId?: string;
|
|
118
|
+
/** Resolved exit comment (the matching comment_profit/loss/trailing). */
|
|
119
|
+
exitComment?: string;
|
|
120
|
+
/**
|
|
121
|
+
* True when this close is part of a single REVERSAL order that will
|
|
122
|
+
* also open a new trade in the opposite direction. Affects
|
|
123
|
+
* `cash_per_order` commission: TV charges the flat fee ONCE per order
|
|
124
|
+
* placement, attributed to the new entry — the implicit close leg of
|
|
125
|
+
* the reversal does NOT incur a second flat charge. Per-leg types
|
|
126
|
+
* (percent, cash_per_contract) are unaffected by this flag.
|
|
127
|
+
*/
|
|
128
|
+
isImplicitReversal?: boolean;
|
|
129
|
+
}
|
|
130
|
+
export declare function closePartialPosition(context: any, qtyToClose: number, exitPrice: number, exitTime: number, closeInfo?: CloseInfo): void;
|
|
62
131
|
/**
|
|
63
132
|
* FIFO close of `qtyToClose` contracts from open trades, optionally filtered
|
|
64
133
|
* by `fromEntry` — when set, only trades whose `entry_id === fromEntry` are
|
|
@@ -67,7 +136,7 @@ export declare function closePartialPosition(context: any, qtyToClose: number, e
|
|
|
67
136
|
* Wraps `closePartialPosition` by temporarily reorganizing `opentrades` so
|
|
68
137
|
* the matching trades sit at the head of the FIFO queue.
|
|
69
138
|
*/
|
|
70
|
-
export declare function closeMatching(context: any, fromEntry: string | undefined, qtyToClose: number, exitPrice: number, exitTime: number): void;
|
|
139
|
+
export declare function closeMatching(context: any, fromEntry: string | undefined, qtyToClose: number, exitPrice: number, exitTime: number, closeInfo?: CloseInfo): void;
|
|
71
140
|
/**
|
|
72
141
|
* Process exit-category orders each bar (after entry-order fills, before the
|
|
73
142
|
* user script runs). Handles:
|
|
@@ -78,6 +147,29 @@ export declare function closeMatching(context: any, fromEntry: string | undefine
|
|
|
78
147
|
* peak (trade.trail_peak) is updated each bar even when not triggered.
|
|
79
148
|
*/
|
|
80
149
|
export declare function processExitOrders(context: any): void;
|
|
150
|
+
/**
|
|
151
|
+
* Margin-call check (TV broker emulator). After all entries and user-defined
|
|
152
|
+
* exits have processed for the bar, check whether the bar's INTRA-BAR
|
|
153
|
+
* adverse movement (low for longs, high for shorts) would have pushed
|
|
154
|
+
* account equity below required maintenance margin. If yes, FORCE LIQUIDATE
|
|
155
|
+
* all open positions at the bar's adverse extreme with exit_id="Margin call".
|
|
156
|
+
*
|
|
157
|
+
* The exit price is the bar's adverse extreme itself, NOT the theoretical
|
|
158
|
+
* threshold where equity would exactly equal required margin. This is the
|
|
159
|
+
* pessimistic broker model — the trader is assumed to be liquidated at
|
|
160
|
+
* the worst intra-bar price, since intra-bar tick order is unknown.
|
|
161
|
+
*
|
|
162
|
+
* Skipped entirely when the position's `margin_pct >= 100` (no leverage)
|
|
163
|
+
* or when there are no open positions.
|
|
164
|
+
*/
|
|
165
|
+
export declare function processMarginCall(context: any): void;
|
|
166
|
+
/**
|
|
167
|
+
* End-of-bar finalize: refresh equity at CLOSE and latch
|
|
168
|
+
* `strategy.max_drawdown` / `strategy.max_runup` using the bar's H/L. Runs
|
|
169
|
+
* UNCONDITIONALLY once per bar (after entry+exit fills are done), regardless
|
|
170
|
+
* of whether the strategy uses exit orders.
|
|
171
|
+
*/
|
|
172
|
+
export declare function finalizeStrategyBar(context: any): void;
|
|
81
173
|
/**
|
|
82
174
|
* Initialize strategy state
|
|
83
175
|
*/
|
|
@@ -2,6 +2,7 @@ export declare const KNOWN_NAMESPACES: string[];
|
|
|
2
2
|
export declare const NAMESPACES_LIKE: string[];
|
|
3
3
|
export declare const ASYNC_METHODS: string[];
|
|
4
4
|
export declare const VIEWPORT_DEPENDENT_BUILTINS: string[];
|
|
5
|
+
export declare const CALLSITE_ID_NAMESPACES: string[];
|
|
5
6
|
export declare const FACTORY_METHODS: string[];
|
|
6
7
|
export declare const NAMESPACE_COLLISION_NAMES: Set<string>;
|
|
7
8
|
export declare const JS_RESERVED_WORDS: Set<string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinets",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.19",
|
|
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",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
},
|
|
106
106
|
"repository": {
|
|
107
107
|
"type": "git",
|
|
108
|
-
"url": "git+https://github.com/
|
|
108
|
+
"url": "git+https://github.com/LuxAlgo/PineTS.git"
|
|
109
109
|
},
|
|
110
|
-
"homepage": "https://
|
|
110
|
+
"homepage": "https://luxalgo.com/"
|
|
111
111
|
}
|