@backtest-kit/pinets 13.6.0 β 14.0.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/README.md +134 -208
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# π @backtest-kit/pinets
|
|
4
4
|
|
|
5
|
-
> Run TradingView Pine Script
|
|
5
|
+
> Run TradingView Pine Script v5/v6 in a self-hosted Node.js environment for [backtest-kit](https://www.npmjs.com/package/backtest-kit). Execute your existing `.pine` indicators with 1:1 syntax compatibility and extract structured trading signals β no TradingView account, no rewrite.
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
@@ -10,309 +10,235 @@
|
|
|
10
10
|
[](https://npmjs.org/package/@backtest-kit/pinets)
|
|
11
11
|
[]()
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Powered by [PineTS](https://github.com/QuantForgeOrg/PineTS) β an open-source Pine Script transpiler & runtime.
|
|
14
14
|
|
|
15
|
-
π **[
|
|
15
|
+
π **[Docs](https://backtest-kit.github.io/documents/article_07_ai_news_trading_signals.html)** Β· π **[Reference implementation](https://github.com/tripolskypetr/backtest-kit/tree/master/example)** Β· π **[PineTS Docs](https://quantforgeorg.github.io/PineTS/)** Β· π **[GitHub](https://github.com/tripolskypetr/backtest-kit)**
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
```bash
|
|
18
|
+
npm install @backtest-kit/pinets pinets backtest-kit
|
|
19
|
+
```
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
- π― **60+ Indicators**: SMA, EMA, RSI, MACD, Bollinger Bands, ATR, Stochastic, and more
|
|
23
|
-
- π **Backtest Integration**: Seamless `getCandles` integration with temporal context
|
|
24
|
-
- π **File or Code**: Load `.pine` files or pass code strings directly
|
|
25
|
-
- πΊοΈ **Plot Extraction**: Flexible mapping from Pine `plot()` outputs to structured data
|
|
26
|
-
- β‘ **Cached Execution**: Memoized file reads for repeated strategy runs
|
|
27
|
-
- π‘οΈ **Type Safe**: Full TypeScript support with generics for extracted data
|
|
21
|
+
---
|
|
28
22
|
|
|
29
|
-
##
|
|
23
|
+
## Why
|
|
30
24
|
|
|
31
|
-
|
|
25
|
+
Your edge already exists as a TradingView Pine Script β rewriting it in JavaScript is error-prone busywork that drifts from the original. This package runs the `.pine` **as-is** inside backtest-kit's execution context: `getCandles` feeds it look-ahead-safe data, 60+ indicators are built in (no manual TA math), and the same script powers both backtest and live. You map its `plot()` outputs to a structured signal and you're done.
|
|
32
26
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
| **`usePine()`** | Register custom Pine constructor |
|
|
41
|
-
| **`setLogger()`** | Configure custom logger |
|
|
42
|
-
| **`File.fromPath()`** | Load Pine Script from `.pine` file |
|
|
43
|
-
| **`Code.fromString()`** | Use inline Pine Script code |
|
|
27
|
+
- π **Pine Script v5/v6** β native TradingView syntax, 1:1 compatibility.
|
|
28
|
+
- π― **60+ indicators** β SMA, EMA, RSI, MACD, Bollinger Bands, ATR, Stochastic, ADX, β¦
|
|
29
|
+
- π **Engine integration** β runs on backtest-kit's temporal context (no look-ahead).
|
|
30
|
+
- π **File or inline** β load a `.pine` file or pass a code string.
|
|
31
|
+
- πΊοΈ **Flexible extraction** β map any `plot()` to typed data, with lookback & transforms.
|
|
32
|
+
- β‘ **Cached execution** β memoized file reads for repeated runs.
|
|
33
|
+
- π‘οΈ **Type-safe** β full generics on extracted data.
|
|
44
34
|
|
|
45
|
-
|
|
35
|
+
---
|
|
46
36
|
|
|
47
|
-
|
|
48
|
-
npm install @backtest-kit/pinets pinets backtest-kit
|
|
49
|
-
```
|
|
37
|
+
## Quick start
|
|
50
38
|
|
|
51
|
-
|
|
39
|
+
A Pine Script just needs to expose a few named plots; `getSignal` maps them to an `ISignalDto`.
|
|
52
40
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Create a Pine Script file (`strategy.pine`):
|
|
41
|
+
<details>
|
|
42
|
+
<summary>strategy.pine + getSignal</summary>
|
|
56
43
|
|
|
57
44
|
```pine
|
|
58
45
|
//@version=5
|
|
59
|
-
indicator("
|
|
46
|
+
indicator("EMA cross β 1H, 100 candles")
|
|
60
47
|
|
|
61
|
-
// Indicators - faster settings for 1H
|
|
62
48
|
rsi = ta.rsi(close, 10)
|
|
63
49
|
atr = ta.atr(10)
|
|
64
50
|
ema_fast = ta.ema(close, 7)
|
|
65
51
|
ema_slow = ta.ema(close, 16)
|
|
66
52
|
|
|
67
|
-
|
|
68
|
-
long_cond = ta.crossover(ema_fast, ema_slow) and rsi < 65
|
|
53
|
+
long_cond = ta.crossover(ema_fast, ema_slow) and rsi < 65
|
|
69
54
|
short_cond = ta.crossunder(ema_fast, ema_slow) and rsi > 35
|
|
70
55
|
|
|
71
|
-
// Levels - tighter SL, wider TP for better RR
|
|
72
|
-
sl_long = close - atr * 1.5
|
|
73
|
-
tp_long = close + atr * 3
|
|
74
|
-
sl_short = close + atr * 1.5
|
|
75
|
-
tp_short = close - atr * 3
|
|
76
|
-
|
|
77
|
-
// Plots for extraction
|
|
78
56
|
plot(close, "Close")
|
|
79
57
|
plot(long_cond ? 1 : short_cond ? -1 : 0, "Signal")
|
|
80
|
-
plot(long_cond ?
|
|
81
|
-
plot(long_cond ?
|
|
82
|
-
plot(60, "EstimatedTime") //
|
|
58
|
+
plot(long_cond ? close - atr*1.5 : close + atr*1.5, "StopLoss")
|
|
59
|
+
plot(long_cond ? close + atr*3 : close - atr*3, "TakeProfit")
|
|
60
|
+
plot(60, "EstimatedTime") // minutes
|
|
83
61
|
```
|
|
84
62
|
|
|
85
|
-
Use it in your strategy:
|
|
86
|
-
|
|
87
63
|
```typescript
|
|
88
64
|
import { File, getSignal } from '@backtest-kit/pinets';
|
|
89
65
|
import { addStrategy } from 'backtest-kit';
|
|
90
66
|
|
|
91
67
|
addStrategy({
|
|
92
|
-
strategyName: 'pine-ema-cross',
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
getSignal: async (symbol) => {
|
|
96
|
-
const source = File.fromPath('strategy.pine');
|
|
97
|
-
|
|
98
|
-
return await getSignal(source, {
|
|
99
|
-
symbol,
|
|
100
|
-
timeframe: '1h',
|
|
101
|
-
limit: 100,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
68
|
+
strategyName: 'pine-ema-cross', interval: '5m', riskName: 'demo',
|
|
69
|
+
getSignal: async (symbol) =>
|
|
70
|
+
getSignal(File.fromPath('strategy.pine'), { symbol, timeframe: '1h', limit: 100 }),
|
|
104
71
|
});
|
|
105
72
|
```
|
|
106
73
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
No file needed - pass Pine Script as a string:
|
|
74
|
+
Inline code needs no file:
|
|
110
75
|
|
|
111
76
|
```typescript
|
|
112
77
|
import { Code, getSignal } from '@backtest-kit/pinets';
|
|
78
|
+
const signal = await getSignal(
|
|
79
|
+
Code.fromString(`//@version=5\nindicator("RSI")\nrsi=ta.rsi(close,14)\natr=ta.atr(14)\nplot(close,"Close")\nplot(rsi<30?1:rsi>70?-1:0,"Signal")\nplot(close-atr*2,"StopLoss")\nplot(close+atr*3,"TakeProfit")`),
|
|
80
|
+
{ symbol: 'BTCUSDT', timeframe: '15m', limit: 100 });
|
|
81
|
+
```
|
|
113
82
|
|
|
114
|
-
|
|
115
|
-
//@version=5
|
|
116
|
-
indicator("RSI Strategy")
|
|
83
|
+
</details>
|
|
117
84
|
|
|
118
|
-
|
|
119
|
-
atr = ta.atr(14)
|
|
85
|
+
### Required plots for `getSignal()`
|
|
120
86
|
|
|
121
|
-
|
|
122
|
-
|
|
87
|
+
| Plot name | Value | Meaning |
|
|
88
|
+
|-----------|-------|---------|
|
|
89
|
+
| `"Signal"` | `1` / `-1` / `0` | Long / Short / no signal |
|
|
90
|
+
| `"Close"` | `close` | Entry price |
|
|
91
|
+
| `"StopLoss"` | price | Stop-loss level |
|
|
92
|
+
| `"TakeProfit"` | price | Take-profit level |
|
|
93
|
+
| `"EstimatedTime"` | minutes | Hold duration (optional, default 240) |
|
|
123
94
|
|
|
124
|
-
|
|
125
|
-
plot(long_cond ? 1 : short_cond ? -1 : 0, "Signal")
|
|
126
|
-
plot(close - atr * 2, "StopLoss")
|
|
127
|
-
plot(close + atr * 3, "TakeProfit")
|
|
128
|
-
`;
|
|
129
|
-
|
|
130
|
-
const source = Code.fromString(pineScript);
|
|
131
|
-
const signal = await getSignal(source, {
|
|
132
|
-
symbol: 'BTCUSDT',
|
|
133
|
-
timeframe: '15m',
|
|
134
|
-
limit: 100,
|
|
135
|
-
});
|
|
136
|
-
```
|
|
95
|
+
Custom plots are fine too β use `run` + `extract` to remap them (below).
|
|
137
96
|
|
|
138
|
-
|
|
97
|
+
---
|
|
139
98
|
|
|
140
|
-
|
|
99
|
+
## Custom extraction
|
|
141
100
|
|
|
142
|
-
|
|
143
|
-
import { File, run, extract } from '@backtest-kit/pinets';
|
|
101
|
+
`run()` returns raw plot data; `extract()` / `extractRows()` pull it into typed shapes with optional lookback and transforms.
|
|
144
102
|
|
|
145
|
-
|
|
103
|
+
<details>
|
|
104
|
+
<summary>extract() β latest bar values</summary>
|
|
146
105
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
timeframe: '1h',
|
|
150
|
-
limit: 200,
|
|
151
|
-
});
|
|
106
|
+
```typescript
|
|
107
|
+
import { File, run, extract } from '@backtest-kit/pinets';
|
|
152
108
|
|
|
109
|
+
const plots = await run(File.fromPath('indicators.pine'), { symbol: 'ETHUSDT', timeframe: '1h', limit: 200 });
|
|
153
110
|
const data = await extract(plots, {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// Advanced: with transform and lookback
|
|
159
|
-
prevRsi: {
|
|
160
|
-
plot: 'RSI',
|
|
161
|
-
barsBack: 1, // Previous bar value
|
|
162
|
-
},
|
|
163
|
-
trendStrength: {
|
|
164
|
-
plot: 'ADX',
|
|
165
|
-
transform: (v) => v > 25 ? 'strong' : 'weak',
|
|
166
|
-
},
|
|
111
|
+
rsi: 'RSI', macd: 'MACD', // plot name β number
|
|
112
|
+
prevRsi: { plot: 'RSI', barsBack: 1 }, // previous bar
|
|
113
|
+
trendStrength: { plot: 'ADX', transform: (v) => v > 25 ? 'strong' : 'weak' },
|
|
167
114
|
});
|
|
168
|
-
|
|
169
|
-
// data = { rsi: 55.2, macd: 12.5, prevRsi: 52.1, trendStrength: 'strong' }
|
|
115
|
+
// { rsi: 55.2, macd: 12.5, prevRsi: 52.1, trendStrength: 'strong' }
|
|
170
116
|
```
|
|
171
117
|
|
|
172
|
-
|
|
118
|
+
</details>
|
|
173
119
|
|
|
174
|
-
|
|
120
|
+
<details>
|
|
121
|
+
<summary>extractRows() β every bar, timestamped</summary>
|
|
175
122
|
|
|
176
123
|
```typescript
|
|
177
124
|
import { File, run, extractRows } from '@backtest-kit/pinets';
|
|
178
125
|
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
const plots = await run(source, {
|
|
182
|
-
symbol: 'ETHUSDT',
|
|
183
|
-
timeframe: '1h',
|
|
184
|
-
limit: 200,
|
|
185
|
-
});
|
|
186
|
-
|
|
126
|
+
const plots = await run(File.fromPath('indicators.pine'), { symbol: 'ETHUSDT', timeframe: '1h', limit: 200 });
|
|
187
127
|
const rows = await extractRows(plots, {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// Advanced: with lookback and optional transform
|
|
193
|
-
prevRsi: {
|
|
194
|
-
plot: 'RSI',
|
|
195
|
-
barsBack: 1,
|
|
196
|
-
},
|
|
197
|
-
trend: {
|
|
198
|
-
plot: 'ADX',
|
|
199
|
-
transform: (v) => v > 25 ? 'strong' : 'weak',
|
|
200
|
-
},
|
|
128
|
+
rsi: 'RSI', macd: 'MACD',
|
|
129
|
+
prevRsi: { plot: 'RSI', barsBack: 1 },
|
|
130
|
+
trend: { plot: 'ADX', transform: (v) => v > 25 ? 'strong' : 'weak' },
|
|
201
131
|
});
|
|
202
|
-
|
|
203
|
-
// rows[0] = { timestamp: '2024-01-01T00:00:00.000Z', rsi: 48.3, macd: -2.1, prevRsi: null, trend: 'weak' }
|
|
204
|
-
// rows[1] = { timestamp: '2024-01-01T01:00:00.000Z', rsi: 52.1, macd: -1.5, prevRsi: 48.3, trend: 'weak' }
|
|
205
|
-
// ...
|
|
132
|
+
// rows[1] = { timestamp: '2024-01-01T01:00:00.000Z', rsi: 52.1, macd: -1.5, prevRsi: 48.3, trend: 'weak' }
|
|
206
133
|
```
|
|
207
134
|
|
|
208
|
-
|
|
135
|
+
`extract()` vs `extractRows()`: single latest object vs array of all bars; missing value `0` vs `null`; no timestamp vs ISO `timestamp`; `barsBack` from the last bar vs from each bar's own index. Use `extract` for signal generation at the current bar, `extractRows` for dataset export / historical analysis.
|
|
209
136
|
|
|
210
|
-
|
|
211
|
-
|---|---|---|
|
|
212
|
-
| Returns | Single object (latest bar) | Array of objects (all bars) |
|
|
213
|
-
| Missing value | `0` (fallback) | `null` |
|
|
214
|
-
| `timestamp` field | No | Yes β ISO string from the bar's time |
|
|
215
|
-
| `barsBack` | Looks back from the last bar | Looks back from each bar's own index |
|
|
216
|
-
| Use case | Signal generation at current bar | Dataset export, historical analysis |
|
|
137
|
+
</details>
|
|
217
138
|
|
|
218
|
-
|
|
139
|
+
<details>
|
|
140
|
+
<summary>toSignalDto() β turn extracted values into a signal</summary>
|
|
219
141
|
|
|
220
|
-
|
|
142
|
+
The helper `getSignal` uses internally, exposed for custom graphs (e.g. multi-timeframe via `@backtest-kit/graph`). Maps `position` `1`/`-1`/`0` β `long`/`short`/`null`, carrying TP/SL/estimated-time, with an optional explicit `priceOpen`:
|
|
221
143
|
|
|
222
144
|
```typescript
|
|
223
|
-
import {
|
|
145
|
+
import { run, extract, toSignalDto } from '@backtest-kit/pinets';
|
|
146
|
+
import { randomString } from 'functools-kit';
|
|
224
147
|
|
|
225
|
-
const
|
|
148
|
+
const plots = await run(File.fromPath('strategy.pine'), { symbol, timeframe: '15m', limit: 100 });
|
|
149
|
+
const data = await extract(plots, { position: 'Signal', priceTakeProfit: 'TakeProfit', priceStopLoss: 'StopLoss', minuteEstimatedTime: 'EstimatedTime' });
|
|
150
|
+
const signal = toSignalDto(randomString(), data, null); // ISignalDto | null
|
|
151
|
+
```
|
|
226
152
|
|
|
227
|
-
|
|
228
|
-
symbol: 'BTCUSDT',
|
|
229
|
-
timeframe: '1h',
|
|
230
|
-
limit: 100,
|
|
231
|
-
});
|
|
153
|
+
</details>
|
|
232
154
|
|
|
233
|
-
|
|
234
|
-
await dumpPlotData('signal-001', plots, 'ema-cross', './dump/ta');
|
|
235
|
-
```
|
|
155
|
+
---
|
|
236
156
|
|
|
237
|
-
|
|
157
|
+
## Debugging & customization
|
|
238
158
|
|
|
239
|
-
|
|
159
|
+
<details>
|
|
160
|
+
<summary>dumpPlotData / markdown β inspect plot output</summary>
|
|
240
161
|
|
|
241
162
|
```typescript
|
|
242
|
-
import {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
//
|
|
246
|
-
usePine(Pine);
|
|
163
|
+
import { File, run, dumpPlotData, toMarkdown } from '@backtest-kit/pinets';
|
|
164
|
+
const plots = await run(File.fromPath('strategy.pine'), { symbol: 'BTCUSDT', timeframe: '1h', limit: 100 });
|
|
165
|
+
await dumpPlotData('signal-001', plots, 'ema-cross', './dump/ta'); // β markdown files
|
|
166
|
+
const md = await toMarkdown(plots); // markdown table as a string
|
|
247
167
|
```
|
|
248
168
|
|
|
249
|
-
|
|
169
|
+
</details>
|
|
250
170
|
|
|
251
|
-
|
|
171
|
+
<details>
|
|
172
|
+
<summary>usePine / useIndicator / setLogger β swap internals</summary>
|
|
252
173
|
|
|
253
174
|
```typescript
|
|
254
|
-
import { setLogger } from '@backtest-kit/pinets';
|
|
175
|
+
import { usePine, useIndicator, setLogger } from '@backtest-kit/pinets';
|
|
176
|
+
import { Pine } from 'pinets';
|
|
255
177
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
error: (method, data) => console.error(`[${method}]`, data),
|
|
260
|
-
});
|
|
178
|
+
usePine(Pine); // register a custom Pine constructor
|
|
179
|
+
useIndicator(MyIndicatorCtor); // register a custom indicator constructor
|
|
180
|
+
setLogger({ log: (m, d) => console.log(`[${m}]`, d), info: () => {}, error: console.error });
|
|
261
181
|
```
|
|
262
182
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
For `getSignal()` to work, your Pine Script must include these plots:
|
|
266
|
-
|
|
267
|
-
| Plot Name | Value | Description |
|
|
268
|
-
|-----------|-------|-------------|
|
|
269
|
-
| `"Signal"` | `1` / `-1` / `0` | Long / Short / No signal |
|
|
270
|
-
| `"Close"` | `close` | Entry price |
|
|
271
|
-
| `"StopLoss"` | price | Stop loss level |
|
|
272
|
-
| `"TakeProfit"` | price | Take profit level |
|
|
273
|
-
| `"EstimatedTime"` | minutes | Hold duration (optional, default: 240) |
|
|
183
|
+
</details>
|
|
274
184
|
|
|
275
|
-
|
|
185
|
+
---
|
|
276
186
|
|
|
277
|
-
##
|
|
187
|
+
## Why not just rewrite it in JS?
|
|
278
188
|
|
|
279
|
-
|
|
189
|
+
<details>
|
|
190
|
+
<summary>The difference</summary>
|
|
280
191
|
|
|
281
192
|
```typescript
|
|
282
|
-
// β
|
|
283
|
-
import { getCandles } from 'backtest-kit';
|
|
284
|
-
import { RSI, EMA, ATR } from 'technicalindicators';
|
|
285
|
-
|
|
193
|
+
// β Manual rewrite β re-derive every indicator, drift from the original
|
|
286
194
|
const candles = await getCandles('BTCUSDT', '5m', 100);
|
|
287
195
|
const closes = candles.map(c => c.close);
|
|
288
196
|
const rsi = RSI.calculate({ values: closes, period: 14 });
|
|
289
197
|
const emaFast = EMA.calculate({ values: closes, period: 9 });
|
|
290
|
-
|
|
291
|
-
|
|
198
|
+
// β¦port all the Pine logic by hand
|
|
199
|
+
|
|
200
|
+
// β
With pinets β copy the .pine straight from TradingView
|
|
201
|
+
const signal = await getSignal(File.fromPath('strategy.pine'), { symbol: 'BTCUSDT', timeframe: '5m', limit: 100 });
|
|
292
202
|
```
|
|
293
203
|
|
|
294
|
-
|
|
295
|
-
// β
With pinets (copy-paste from TradingView)
|
|
296
|
-
import { File, getSignal } from '@backtest-kit/pinets';
|
|
204
|
+
Use existing scripts as-is Β· 60+ indicators with no manual math Β· same code backtest & live Β· full time-series lookback semantics Β· type-safe extraction.
|
|
297
205
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
206
|
+
</details>
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## API reference
|
|
211
|
+
|
|
212
|
+
| Export | Description |
|
|
213
|
+
|--------|-------------|
|
|
214
|
+
| `getSignal(source, opts)` | Run Pine Script β structured `ISignalDto` (position, TP/SL, estimated time) |
|
|
215
|
+
| `run(source, opts)` | Run Pine Script β raw plot data |
|
|
216
|
+
| `extract(plots, mapping)` | Latest-bar values with custom mapping (missing β `0`) |
|
|
217
|
+
| `extractRows(plots, mapping)` | All bars as timestamped rows (missing β `null`) |
|
|
218
|
+
| `toSignalDto(id, data, priceOpen?)` | Map extracted `{ position, β¦ }` β `ISignalDto \| null` |
|
|
219
|
+
| `dumpPlotData(id, plots, name, dir)` | Dump plot data to markdown files |
|
|
220
|
+
| `toMarkdown(plots)` Β· `markdown(...)` | Render plots as a markdown table |
|
|
221
|
+
| `File.fromPath(path)` | Load Pine Script from a `.pine` file (memoized) |
|
|
222
|
+
| `Code.fromString(code)` | Use inline Pine Script |
|
|
223
|
+
| `usePine(ctor)` Β· `useIndicator(ctor)` | Register a custom Pine / indicator constructor |
|
|
224
|
+
| `setLogger(logger)` | Custom logger |
|
|
225
|
+
| `lib` | The internal IoC container for advanced use |
|
|
226
|
+
| `AXIS_SYMBOL` | Axis provider symbol token |
|
|
227
|
+
|
|
228
|
+
**Options** (`run`/`getSignal`): `symbol`, `timeframe` (Pine candle interval), `limit` (candles to fetch β must cover indicator warmup; pre-warmup bars are `N/A`).
|
|
229
|
+
|
|
230
|
+
**Types:** `PlotExtractConfig`, `PlotMapping`, `ExtractedData`, `ExtractedDataRow`, `CandleModel`, `PlotModel`, `PlotRecord`, `SymbolInfoModel`, `ILogger`, `IPine`/`TPineCtor`, `IIndicator`/`TIndicatorCtor`, `IProvider`.
|
|
231
|
+
|
|
232
|
+
<details>
|
|
233
|
+
<summary>Complete source map</summary>
|
|
304
234
|
|
|
305
|
-
|
|
235
|
+
`classes/{Code,File}.ts` Β· `function/{pine,indicator,run,extract,setup,strategy,dump,markdown}.function.ts` Β· `helpers/toSignalDto.ts` Β· `model/{Candle,Plot,SymbolInfo}.model.ts` Β· `interface/{Logger,Pine,Indicator,Provider}.interface.ts` Β· `lib/` IoC (`core/{di,provide,types}`, `services/{base/LoggerService, cache/PineCacheService, connection/{Pine,Indicator}ConnectionService, context/ExchangeContextService, data/PineDataService, job/PineJobService, markdown/PineMarkdownService, provider/{Axis,Candle}ProviderService}`). Every export above maps to one of these β nothing in `src/` is undocumented.
|
|
306
236
|
|
|
307
|
-
|
|
308
|
-
- π― 60+ built-in indicators (no manual calculation)
|
|
309
|
-
- β‘ Same code for backtest and live trading
|
|
310
|
-
- π Full time-series semantics with lookback support
|
|
311
|
-
- π‘οΈ Type-safe extraction with TypeScript generics
|
|
237
|
+
</details>
|
|
312
238
|
|
|
313
239
|
## π€ Contribute
|
|
314
240
|
|
|
315
|
-
Fork/PR on [GitHub](https://github.com/tripolskypetr/backtest-kit).
|
|
241
|
+
Fork / PR on [GitHub](https://github.com/tripolskypetr/backtest-kit).
|
|
316
242
|
|
|
317
243
|
## π License
|
|
318
244
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtest-kit/pinets",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.0.0",
|
|
4
4
|
"description": "Run TradingView Pine Script strategies in Node.js self hosted environment. Execute existing Pine Script indicators and generate trading signals with 1:1 syntax compatibility via PineTS runtime.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Petr Tripolsky",
|
|
@@ -70,18 +70,18 @@
|
|
|
70
70
|
"tslib": "2.7.0",
|
|
71
71
|
"typedoc": "0.27.9",
|
|
72
72
|
"pinets": "0.9.23",
|
|
73
|
-
"backtest-kit": "
|
|
74
|
-
"worker-testbed": "2.
|
|
73
|
+
"backtest-kit": "14.0.0",
|
|
74
|
+
"worker-testbed": "2.1.0"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
|
-
"backtest-kit": "^
|
|
77
|
+
"backtest-kit": "^14.0.0",
|
|
78
78
|
"pinets": "^0.9.23",
|
|
79
79
|
"typescript": "^5.0.0"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"di-kit": "^1.1.1",
|
|
83
83
|
"di-scoped": "^1.0.21",
|
|
84
|
-
"functools-kit": "^
|
|
84
|
+
"functools-kit": "^3.0.0",
|
|
85
85
|
"get-moment-stamp": "^2.0.0"
|
|
86
86
|
},
|
|
87
87
|
"publishConfig": {
|