@backtest-kit/pinets 0.0.5 → 3.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 +52 -3
- package/build/index.cjs +15 -8
- package/build/index.mjs +15 -8
- package/package.json +3 -3
- package/types.d.ts +5 -4
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Run TradingView Pine Script strategies in Node.js self hosted enviroment. Execute your existing Pine Script indicators and generate trading signals - pure technical analysis with 1:1 syntax compatibility.
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|
|
|
7
7
|
[](https://deepwiki.com/tripolskypetr/backtest-kit)
|
|
8
8
|
[](https://npmjs.org/package/@backtest-kit/pinets)
|
|
@@ -29,7 +29,11 @@ Port your TradingView strategies to backtest-kit with zero rewrite. Powered by [
|
|
|
29
29
|
| Function | Description |
|
|
30
30
|
|----------|-------------|
|
|
31
31
|
| **`getSignal()`** | Run Pine Script and get structured `ISignalDto` (position, TP/SL, estimated time) |
|
|
32
|
-
| **`run()`** | Run Pine Script
|
|
32
|
+
| **`run()`** | Run Pine Script and return raw plot data |
|
|
33
|
+
| **`extract()`** | Extract values from plots with custom mapping |
|
|
34
|
+
| **`dumpPlotData()`** | Dump plot data to markdown files for debugging |
|
|
35
|
+
| **`usePine()`** | Register custom Pine constructor |
|
|
36
|
+
| **`setLogger()`** | Configure custom logger |
|
|
33
37
|
| **`File.fromPath()`** | Load Pine Script from `.pine` file |
|
|
34
38
|
| **`Code.fromString()`** | Use inline Pine Script code |
|
|
35
39
|
|
|
@@ -141,7 +145,7 @@ const plots = await run(source, {
|
|
|
141
145
|
limit: 200,
|
|
142
146
|
});
|
|
143
147
|
|
|
144
|
-
const data = extract(plots, {
|
|
148
|
+
const data = await extract(plots, {
|
|
145
149
|
// Simple: plot name -> number
|
|
146
150
|
rsi: 'RSI',
|
|
147
151
|
macd: 'MACD',
|
|
@@ -160,6 +164,51 @@ const data = extract(plots, {
|
|
|
160
164
|
// data = { rsi: 55.2, macd: 12.5, prevRsi: 52.1, trendStrength: 'strong' }
|
|
161
165
|
```
|
|
162
166
|
|
|
167
|
+
### Debug with Plot Dump
|
|
168
|
+
|
|
169
|
+
Dump plot data to markdown files for analysis and debugging:
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
import { File, run, dumpPlotData } from '@backtest-kit/pinets';
|
|
173
|
+
|
|
174
|
+
const source = File.fromPath('strategy.pine');
|
|
175
|
+
|
|
176
|
+
const plots = await run(source, {
|
|
177
|
+
symbol: 'BTCUSDT',
|
|
178
|
+
timeframe: '1h',
|
|
179
|
+
limit: 100,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Dump plots to ./dump/ta directory
|
|
183
|
+
await dumpPlotData('signal-001', plots, 'ema-cross', './dump/ta');
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Custom Pine Constructor
|
|
187
|
+
|
|
188
|
+
Register a custom Pine constructor for advanced configurations:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { usePine } from '@backtest-kit/pinets';
|
|
192
|
+
import { Pine } from 'pinets';
|
|
193
|
+
|
|
194
|
+
// Use custom Pine instance
|
|
195
|
+
usePine(Pine);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Custom Logger
|
|
199
|
+
|
|
200
|
+
Configure logging for debugging:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
import { setLogger } from '@backtest-kit/pinets';
|
|
204
|
+
|
|
205
|
+
setLogger({
|
|
206
|
+
log: (method, data) => console.log(`[${method}]`, data),
|
|
207
|
+
info: (method, data) => console.info(`[${method}]`, data),
|
|
208
|
+
error: (method, data) => console.error(`[${method}]`, data),
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
163
212
|
## 📜 Pine Script Conventions
|
|
164
213
|
|
|
165
214
|
For `getSignal()` to work, your Pine Script must include these plots:
|
package/build/index.cjs
CHANGED
|
@@ -690,26 +690,32 @@ function setLogger(logger) {
|
|
|
690
690
|
pine.loggerService.setLogger(logger);
|
|
691
691
|
}
|
|
692
692
|
|
|
693
|
-
function toSignalDto(data) {
|
|
693
|
+
function toSignalDto(id, data, priceOpen = data.priceOpen) {
|
|
694
694
|
if (data.position === 1) {
|
|
695
|
-
|
|
696
|
-
id:
|
|
695
|
+
const result = {
|
|
696
|
+
id: String(id),
|
|
697
697
|
position: "long",
|
|
698
|
-
priceOpen: data.priceOpen,
|
|
699
698
|
priceTakeProfit: data.priceTakeProfit,
|
|
700
699
|
priceStopLoss: data.priceStopLoss,
|
|
701
700
|
minuteEstimatedTime: data.minuteEstimatedTime,
|
|
702
701
|
};
|
|
702
|
+
if (priceOpen) {
|
|
703
|
+
Object.assign(result, { priceOpen });
|
|
704
|
+
}
|
|
705
|
+
return result;
|
|
703
706
|
}
|
|
704
707
|
if (data.position === -1) {
|
|
705
|
-
|
|
706
|
-
id:
|
|
708
|
+
const result = {
|
|
709
|
+
id: String(id),
|
|
707
710
|
position: "short",
|
|
708
|
-
priceOpen: data.priceOpen,
|
|
709
711
|
priceTakeProfit: data.priceTakeProfit,
|
|
710
712
|
priceStopLoss: data.priceStopLoss,
|
|
711
713
|
minuteEstimatedTime: data.minuteEstimatedTime,
|
|
712
714
|
};
|
|
715
|
+
if (priceOpen) {
|
|
716
|
+
Object.assign(result, { priceOpen });
|
|
717
|
+
}
|
|
718
|
+
return result;
|
|
713
719
|
}
|
|
714
720
|
return null;
|
|
715
721
|
}
|
|
@@ -744,8 +750,9 @@ async function getSignal(source, { symbol, timeframe, limit }) {
|
|
|
744
750
|
limit,
|
|
745
751
|
});
|
|
746
752
|
const { plots } = await pine.pineJobService.run(await GET_SOURCE_FN(source), symbol, timeframe, limit);
|
|
753
|
+
const resultId = functoolsKit.randomString();
|
|
747
754
|
const data = pine.pineDataService.extract(plots, SIGNAL_SCHEMA);
|
|
748
|
-
return toSignalDto(data);
|
|
755
|
+
return toSignalDto(resultId, data);
|
|
749
756
|
}
|
|
750
757
|
|
|
751
758
|
const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
|
package/build/index.mjs
CHANGED
|
@@ -687,26 +687,32 @@ function setLogger(logger) {
|
|
|
687
687
|
pine.loggerService.setLogger(logger);
|
|
688
688
|
}
|
|
689
689
|
|
|
690
|
-
function toSignalDto(data) {
|
|
690
|
+
function toSignalDto(id, data, priceOpen = data.priceOpen) {
|
|
691
691
|
if (data.position === 1) {
|
|
692
|
-
|
|
693
|
-
id:
|
|
692
|
+
const result = {
|
|
693
|
+
id: String(id),
|
|
694
694
|
position: "long",
|
|
695
|
-
priceOpen: data.priceOpen,
|
|
696
695
|
priceTakeProfit: data.priceTakeProfit,
|
|
697
696
|
priceStopLoss: data.priceStopLoss,
|
|
698
697
|
minuteEstimatedTime: data.minuteEstimatedTime,
|
|
699
698
|
};
|
|
699
|
+
if (priceOpen) {
|
|
700
|
+
Object.assign(result, { priceOpen });
|
|
701
|
+
}
|
|
702
|
+
return result;
|
|
700
703
|
}
|
|
701
704
|
if (data.position === -1) {
|
|
702
|
-
|
|
703
|
-
id:
|
|
705
|
+
const result = {
|
|
706
|
+
id: String(id),
|
|
704
707
|
position: "short",
|
|
705
|
-
priceOpen: data.priceOpen,
|
|
706
708
|
priceTakeProfit: data.priceTakeProfit,
|
|
707
709
|
priceStopLoss: data.priceStopLoss,
|
|
708
710
|
minuteEstimatedTime: data.minuteEstimatedTime,
|
|
709
711
|
};
|
|
712
|
+
if (priceOpen) {
|
|
713
|
+
Object.assign(result, { priceOpen });
|
|
714
|
+
}
|
|
715
|
+
return result;
|
|
710
716
|
}
|
|
711
717
|
return null;
|
|
712
718
|
}
|
|
@@ -741,8 +747,9 @@ async function getSignal(source, { symbol, timeframe, limit }) {
|
|
|
741
747
|
limit,
|
|
742
748
|
});
|
|
743
749
|
const { plots } = await pine.pineJobService.run(await GET_SOURCE_FN(source), symbol, timeframe, limit);
|
|
750
|
+
const resultId = randomString();
|
|
744
751
|
const data = pine.pineDataService.extract(plots, SIGNAL_SCHEMA);
|
|
745
|
-
return toSignalDto(data);
|
|
752
|
+
return toSignalDto(resultId, data);
|
|
746
753
|
}
|
|
747
754
|
|
|
748
755
|
const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtest-kit/pinets",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "3.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",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"worker-testbed": "1.0.12"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
|
-
"backtest-kit": "^
|
|
76
|
-
"pinets": "^0.8.
|
|
75
|
+
"backtest-kit": "^3.0.5",
|
|
76
|
+
"pinets": "^0.8.6",
|
|
77
77
|
"typescript": "^5.0.0"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
package/types.d.ts
CHANGED
|
@@ -83,12 +83,13 @@ interface IParams {
|
|
|
83
83
|
}
|
|
84
84
|
declare function getSignal(source: File | Code, { symbol, timeframe, limit }: IParams): Promise<ISignalDto | null>;
|
|
85
85
|
|
|
86
|
-
type ResultId$
|
|
87
|
-
declare function dumpPlotData(signalId: ResultId$
|
|
86
|
+
type ResultId$2 = string | number;
|
|
87
|
+
declare function dumpPlotData(signalId: ResultId$2, plots: PlotModel, taName: string, outputDir?: string): Promise<void>;
|
|
88
88
|
|
|
89
|
+
type ResultId$1 = string | number;
|
|
89
90
|
interface SignalData {
|
|
90
91
|
position: number;
|
|
91
|
-
priceOpen
|
|
92
|
+
priceOpen?: number;
|
|
92
93
|
priceTakeProfit: number;
|
|
93
94
|
priceStopLoss: number;
|
|
94
95
|
minuteEstimatedTime: number;
|
|
@@ -96,7 +97,7 @@ interface SignalData {
|
|
|
96
97
|
interface Signal extends ISignalDto {
|
|
97
98
|
id: string;
|
|
98
99
|
}
|
|
99
|
-
declare function toSignalDto(data: SignalData): Signal | null;
|
|
100
|
+
declare function toSignalDto(id: ResultId$1, data: SignalData, priceOpen?: number | null | undefined): Signal | null;
|
|
100
101
|
|
|
101
102
|
interface CandleModel {
|
|
102
103
|
openTime: number;
|