@backtest-kit/pinets 3.0.2 → 3.0.4
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/build/index.cjs +57 -7
- package/build/index.mjs +58 -8
- package/package.json +3 -3
- package/types.d.ts +13 -2
package/build/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var path = require('path');
|
|
4
4
|
var backtestKit = require('backtest-kit');
|
|
5
5
|
var diKit = require('di-kit');
|
|
6
|
+
var diScoped = require('di-scoped');
|
|
6
7
|
var functoolsKit = require('functools-kit');
|
|
7
8
|
var fs = require('fs/promises');
|
|
8
9
|
var module$1 = require('module');
|
|
@@ -80,9 +81,12 @@ class LoggerService {
|
|
|
80
81
|
|
|
81
82
|
const { provide, inject, init, override } = diKit.createActivator("pine");
|
|
82
83
|
|
|
83
|
-
const baseServices = {
|
|
84
|
+
const baseServices$1 = {
|
|
84
85
|
loggerService: Symbol("loggerService"),
|
|
85
86
|
};
|
|
87
|
+
const contextServices$1 = {
|
|
88
|
+
exchangeContextService: Symbol("exchangeContextService"),
|
|
89
|
+
};
|
|
86
90
|
const providerServices$1 = {
|
|
87
91
|
axisProviderService: Symbol("axisProviderService"),
|
|
88
92
|
candleProviderService: Symbol("candleProviderService"),
|
|
@@ -103,7 +107,8 @@ const markdownServices$1 = {
|
|
|
103
107
|
pineMarkdownService: Symbol("pineMarkdownService"),
|
|
104
108
|
};
|
|
105
109
|
const TYPES = {
|
|
106
|
-
...baseServices,
|
|
110
|
+
...baseServices$1,
|
|
111
|
+
...contextServices$1,
|
|
107
112
|
...providerServices$1,
|
|
108
113
|
...jobServices$1,
|
|
109
114
|
...dataServices$1,
|
|
@@ -230,9 +235,28 @@ class AxisProviderService {
|
|
|
230
235
|
}
|
|
231
236
|
}
|
|
232
237
|
|
|
238
|
+
const ExchangeContextService = diScoped.scoped(class {
|
|
239
|
+
constructor(context) {
|
|
240
|
+
this.context = context;
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const GET_RAW_CANDLES_FN = async (self, symbol, interval, limit, sDate, eDate) => {
|
|
245
|
+
if (ExchangeContextService.hasContext()) {
|
|
246
|
+
return await backtestKit.Exchange.getRawCandles(symbol, interval, self.exchangeContextService.context, limit, sDate, eDate);
|
|
247
|
+
}
|
|
248
|
+
if (!backtestKit.MethodContextService.hasContext()) {
|
|
249
|
+
throw new Error("MethodContextService context is required to get market data for pinets if exchangeName?: string is not specified");
|
|
250
|
+
}
|
|
251
|
+
if (!backtestKit.ExecutionContextService.hasContext()) {
|
|
252
|
+
throw new Error("ExecutionContextService context is required to get market data for pinets if exchangeName?: string is not specified");
|
|
253
|
+
}
|
|
254
|
+
return await backtestKit.getRawCandles(symbol, interval, limit, sDate, eDate);
|
|
255
|
+
};
|
|
233
256
|
class CandleProviderService {
|
|
234
257
|
constructor() {
|
|
235
258
|
this.loggerService = inject(TYPES.loggerService);
|
|
259
|
+
this.exchangeContextService = inject(TYPES.exchangeContextService);
|
|
236
260
|
}
|
|
237
261
|
async getMarketData(tickerId, timeframe, limit, sDate, eDate) {
|
|
238
262
|
this.loggerService.log("candleProviderService getMarketData", {
|
|
@@ -245,7 +269,7 @@ class CandleProviderService {
|
|
|
245
269
|
const symbol = tickerId
|
|
246
270
|
.toUpperCase()
|
|
247
271
|
.replace(/^BINANCE:|^BYBIT:|^OKX:/, "");
|
|
248
|
-
const rawCandles = await
|
|
272
|
+
const rawCandles = await GET_RAW_CANDLES_FN(this, symbol, timeframe, limit, sDate, eDate);
|
|
249
273
|
const candles = rawCandles.map((c) => ({
|
|
250
274
|
openTime: c.timestamp,
|
|
251
275
|
open: c.open,
|
|
@@ -554,6 +578,9 @@ class PineMarkdownService {
|
|
|
554
578
|
{
|
|
555
579
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
556
580
|
}
|
|
581
|
+
{
|
|
582
|
+
provide(TYPES.exchangeContextService, () => new ExchangeContextService());
|
|
583
|
+
}
|
|
557
584
|
{
|
|
558
585
|
provide(TYPES.axisProviderService, () => new AxisProviderService());
|
|
559
586
|
provide(TYPES.candleProviderService, () => new CandleProviderService());
|
|
@@ -574,9 +601,12 @@ class PineMarkdownService {
|
|
|
574
601
|
provide(TYPES.pineMarkdownService, () => new PineMarkdownService());
|
|
575
602
|
}
|
|
576
603
|
|
|
577
|
-
const
|
|
604
|
+
const baseServices = {
|
|
578
605
|
loggerService: inject(TYPES.loggerService),
|
|
579
606
|
};
|
|
607
|
+
const contextServices = {
|
|
608
|
+
exchangeContextService: inject(TYPES.exchangeContextService),
|
|
609
|
+
};
|
|
580
610
|
const providerServices = {
|
|
581
611
|
axisProviderService: inject(TYPES.axisProviderService),
|
|
582
612
|
candleProviderService: inject(TYPES.candleProviderService),
|
|
@@ -597,7 +627,8 @@ const markdownServices = {
|
|
|
597
627
|
pineMarkdownService: inject(TYPES.pineMarkdownService),
|
|
598
628
|
};
|
|
599
629
|
const pine = {
|
|
600
|
-
...
|
|
630
|
+
...contextServices,
|
|
631
|
+
...baseServices,
|
|
601
632
|
...providerServices,
|
|
602
633
|
...jobServices,
|
|
603
634
|
...dataServices,
|
|
@@ -626,7 +657,26 @@ const GET_SOURCE_FN$1 = async (source) => {
|
|
|
626
657
|
}
|
|
627
658
|
throw new Error("Source must be a File or Code instance");
|
|
628
659
|
};
|
|
629
|
-
async
|
|
660
|
+
const BASE_RUNNER_FN = async (script, symbol, timeframe, limit) => await pine.pineJobService.run(script, symbol, timeframe, limit);
|
|
661
|
+
const CREATE_INFERENCE_FN = (symbol, exchangeName, when) => {
|
|
662
|
+
let fn = () => BASE_RUNNER_FN;
|
|
663
|
+
if (exchangeName) {
|
|
664
|
+
fn = ExchangeContextService.runWithContext(fn, { exchangeName });
|
|
665
|
+
}
|
|
666
|
+
if (when) {
|
|
667
|
+
fn = backtestKit.ExecutionContextService.runWithContext(fn, {
|
|
668
|
+
when,
|
|
669
|
+
symbol,
|
|
670
|
+
backtest: true,
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
return fn();
|
|
674
|
+
};
|
|
675
|
+
const RUN_INFERENCE_FN = async (script, symbol, timeframe, limit, exchangeName, when) => {
|
|
676
|
+
const inference = CREATE_INFERENCE_FN(symbol, exchangeName, when);
|
|
677
|
+
return await inference(script, symbol, timeframe, limit);
|
|
678
|
+
};
|
|
679
|
+
async function run(source, { symbol, timeframe, limit }, exchangeName, when) {
|
|
630
680
|
pine.loggerService.info(METHOD_NAME_RUN$2, {
|
|
631
681
|
source,
|
|
632
682
|
symbol,
|
|
@@ -634,7 +684,7 @@ async function run(source, { symbol, timeframe, limit }) {
|
|
|
634
684
|
limit,
|
|
635
685
|
});
|
|
636
686
|
const script = await GET_SOURCE_FN$1(source);
|
|
637
|
-
const { plots } = await
|
|
687
|
+
const { plots } = await RUN_INFERENCE_FN(script, symbol, timeframe, limit, exchangeName, when);
|
|
638
688
|
return plots;
|
|
639
689
|
}
|
|
640
690
|
|
package/build/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
|
-
import { getDate,
|
|
2
|
+
import { getDate, Exchange, MethodContextService, ExecutionContextService, getRawCandles, Markdown, lib } from 'backtest-kit';
|
|
3
3
|
import { createActivator } from 'di-kit';
|
|
4
|
+
import { scoped } from 'di-scoped';
|
|
4
5
|
import { singleshot, memoize, randomString } from 'functools-kit';
|
|
5
6
|
import fs from 'fs/promises';
|
|
6
7
|
import { createRequire } from 'module';
|
|
@@ -77,9 +78,12 @@ class LoggerService {
|
|
|
77
78
|
|
|
78
79
|
const { provide, inject, init, override } = createActivator("pine");
|
|
79
80
|
|
|
80
|
-
const baseServices = {
|
|
81
|
+
const baseServices$1 = {
|
|
81
82
|
loggerService: Symbol("loggerService"),
|
|
82
83
|
};
|
|
84
|
+
const contextServices$1 = {
|
|
85
|
+
exchangeContextService: Symbol("exchangeContextService"),
|
|
86
|
+
};
|
|
83
87
|
const providerServices$1 = {
|
|
84
88
|
axisProviderService: Symbol("axisProviderService"),
|
|
85
89
|
candleProviderService: Symbol("candleProviderService"),
|
|
@@ -100,7 +104,8 @@ const markdownServices$1 = {
|
|
|
100
104
|
pineMarkdownService: Symbol("pineMarkdownService"),
|
|
101
105
|
};
|
|
102
106
|
const TYPES = {
|
|
103
|
-
...baseServices,
|
|
107
|
+
...baseServices$1,
|
|
108
|
+
...contextServices$1,
|
|
104
109
|
...providerServices$1,
|
|
105
110
|
...jobServices$1,
|
|
106
111
|
...dataServices$1,
|
|
@@ -227,9 +232,28 @@ class AxisProviderService {
|
|
|
227
232
|
}
|
|
228
233
|
}
|
|
229
234
|
|
|
235
|
+
const ExchangeContextService = scoped(class {
|
|
236
|
+
constructor(context) {
|
|
237
|
+
this.context = context;
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
const GET_RAW_CANDLES_FN = async (self, symbol, interval, limit, sDate, eDate) => {
|
|
242
|
+
if (ExchangeContextService.hasContext()) {
|
|
243
|
+
return await Exchange.getRawCandles(symbol, interval, self.exchangeContextService.context, limit, sDate, eDate);
|
|
244
|
+
}
|
|
245
|
+
if (!MethodContextService.hasContext()) {
|
|
246
|
+
throw new Error("MethodContextService context is required to get market data for pinets if exchangeName?: string is not specified");
|
|
247
|
+
}
|
|
248
|
+
if (!ExecutionContextService.hasContext()) {
|
|
249
|
+
throw new Error("ExecutionContextService context is required to get market data for pinets if exchangeName?: string is not specified");
|
|
250
|
+
}
|
|
251
|
+
return await getRawCandles(symbol, interval, limit, sDate, eDate);
|
|
252
|
+
};
|
|
230
253
|
class CandleProviderService {
|
|
231
254
|
constructor() {
|
|
232
255
|
this.loggerService = inject(TYPES.loggerService);
|
|
256
|
+
this.exchangeContextService = inject(TYPES.exchangeContextService);
|
|
233
257
|
}
|
|
234
258
|
async getMarketData(tickerId, timeframe, limit, sDate, eDate) {
|
|
235
259
|
this.loggerService.log("candleProviderService getMarketData", {
|
|
@@ -242,7 +266,7 @@ class CandleProviderService {
|
|
|
242
266
|
const symbol = tickerId
|
|
243
267
|
.toUpperCase()
|
|
244
268
|
.replace(/^BINANCE:|^BYBIT:|^OKX:/, "");
|
|
245
|
-
const rawCandles = await
|
|
269
|
+
const rawCandles = await GET_RAW_CANDLES_FN(this, symbol, timeframe, limit, sDate, eDate);
|
|
246
270
|
const candles = rawCandles.map((c) => ({
|
|
247
271
|
openTime: c.timestamp,
|
|
248
272
|
open: c.open,
|
|
@@ -551,6 +575,9 @@ class PineMarkdownService {
|
|
|
551
575
|
{
|
|
552
576
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
553
577
|
}
|
|
578
|
+
{
|
|
579
|
+
provide(TYPES.exchangeContextService, () => new ExchangeContextService());
|
|
580
|
+
}
|
|
554
581
|
{
|
|
555
582
|
provide(TYPES.axisProviderService, () => new AxisProviderService());
|
|
556
583
|
provide(TYPES.candleProviderService, () => new CandleProviderService());
|
|
@@ -571,9 +598,12 @@ class PineMarkdownService {
|
|
|
571
598
|
provide(TYPES.pineMarkdownService, () => new PineMarkdownService());
|
|
572
599
|
}
|
|
573
600
|
|
|
574
|
-
const
|
|
601
|
+
const baseServices = {
|
|
575
602
|
loggerService: inject(TYPES.loggerService),
|
|
576
603
|
};
|
|
604
|
+
const contextServices = {
|
|
605
|
+
exchangeContextService: inject(TYPES.exchangeContextService),
|
|
606
|
+
};
|
|
577
607
|
const providerServices = {
|
|
578
608
|
axisProviderService: inject(TYPES.axisProviderService),
|
|
579
609
|
candleProviderService: inject(TYPES.candleProviderService),
|
|
@@ -594,7 +624,8 @@ const markdownServices = {
|
|
|
594
624
|
pineMarkdownService: inject(TYPES.pineMarkdownService),
|
|
595
625
|
};
|
|
596
626
|
const pine = {
|
|
597
|
-
...
|
|
627
|
+
...contextServices,
|
|
628
|
+
...baseServices,
|
|
598
629
|
...providerServices,
|
|
599
630
|
...jobServices,
|
|
600
631
|
...dataServices,
|
|
@@ -623,7 +654,26 @@ const GET_SOURCE_FN$1 = async (source) => {
|
|
|
623
654
|
}
|
|
624
655
|
throw new Error("Source must be a File or Code instance");
|
|
625
656
|
};
|
|
626
|
-
async
|
|
657
|
+
const BASE_RUNNER_FN = async (script, symbol, timeframe, limit) => await pine.pineJobService.run(script, symbol, timeframe, limit);
|
|
658
|
+
const CREATE_INFERENCE_FN = (symbol, exchangeName, when) => {
|
|
659
|
+
let fn = () => BASE_RUNNER_FN;
|
|
660
|
+
if (exchangeName) {
|
|
661
|
+
fn = ExchangeContextService.runWithContext(fn, { exchangeName });
|
|
662
|
+
}
|
|
663
|
+
if (when) {
|
|
664
|
+
fn = ExecutionContextService.runWithContext(fn, {
|
|
665
|
+
when,
|
|
666
|
+
symbol,
|
|
667
|
+
backtest: true,
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
return fn();
|
|
671
|
+
};
|
|
672
|
+
const RUN_INFERENCE_FN = async (script, symbol, timeframe, limit, exchangeName, when) => {
|
|
673
|
+
const inference = CREATE_INFERENCE_FN(symbol, exchangeName, when);
|
|
674
|
+
return await inference(script, symbol, timeframe, limit);
|
|
675
|
+
};
|
|
676
|
+
async function run(source, { symbol, timeframe, limit }, exchangeName, when) {
|
|
627
677
|
pine.loggerService.info(METHOD_NAME_RUN$2, {
|
|
628
678
|
source,
|
|
629
679
|
symbol,
|
|
@@ -631,7 +681,7 @@ async function run(source, { symbol, timeframe, limit }) {
|
|
|
631
681
|
limit,
|
|
632
682
|
});
|
|
633
683
|
const script = await GET_SOURCE_FN$1(source);
|
|
634
|
-
const { plots } = await
|
|
684
|
+
const { plots } = await RUN_INFERENCE_FN(script, symbol, timeframe, limit, exchangeName, when);
|
|
635
685
|
return plots;
|
|
636
686
|
}
|
|
637
687
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtest-kit/pinets",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
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,13 +72,13 @@
|
|
|
72
72
|
"worker-testbed": "1.0.12"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
|
-
"backtest-kit": "^3.0.
|
|
75
|
+
"backtest-kit": "^3.0.9",
|
|
76
76
|
"pinets": "^0.8.6",
|
|
77
77
|
"typescript": "^5.0.0"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"di-kit": "^1.0.18",
|
|
81
|
-
"di-scoped": "^1.0.
|
|
81
|
+
"di-scoped": "^1.0.21",
|
|
82
82
|
"functools-kit": "^1.0.95",
|
|
83
83
|
"get-moment-stamp": "^1.1.1"
|
|
84
84
|
},
|
package/types.d.ts
CHANGED
|
@@ -42,12 +42,17 @@ interface IPine {
|
|
|
42
42
|
|
|
43
43
|
declare function usePine<T = TPineCtor>(ctor: T): void;
|
|
44
44
|
|
|
45
|
+
type ExchangeName = string;
|
|
46
|
+
interface IExchangeContext {
|
|
47
|
+
exchangeName: ExchangeName;
|
|
48
|
+
}
|
|
49
|
+
|
|
45
50
|
interface IRunParams {
|
|
46
51
|
symbol: string;
|
|
47
52
|
timeframe: CandleInterval;
|
|
48
53
|
limit: number;
|
|
49
54
|
}
|
|
50
|
-
declare function run(source: File | Code, { symbol, timeframe, limit }: IRunParams): Promise<PlotModel>;
|
|
55
|
+
declare function run(source: File | Code, { symbol, timeframe, limit }: IRunParams, exchangeName?: ExchangeName, when?: Date): Promise<PlotModel>;
|
|
51
56
|
|
|
52
57
|
type PlotExtractConfig<T = number> = {
|
|
53
58
|
plot: string;
|
|
@@ -138,7 +143,10 @@ declare class LoggerService implements ILogger {
|
|
|
138
143
|
}
|
|
139
144
|
|
|
140
145
|
declare class CandleProviderService implements IProvider {
|
|
141
|
-
|
|
146
|
+
readonly loggerService: LoggerService;
|
|
147
|
+
readonly exchangeContextService: {
|
|
148
|
+
readonly context: IExchangeContext;
|
|
149
|
+
};
|
|
142
150
|
getMarketData(tickerId: string, timeframe: string, limit?: number, sDate?: number, eDate?: number): Promise<any[]>;
|
|
143
151
|
getSymbolInfo(tickerId: string): Promise<any>;
|
|
144
152
|
}
|
|
@@ -186,6 +194,9 @@ declare const pine: {
|
|
|
186
194
|
axisProviderService: AxisProviderService;
|
|
187
195
|
candleProviderService: CandleProviderService;
|
|
188
196
|
loggerService: LoggerService;
|
|
197
|
+
exchangeContextService: {
|
|
198
|
+
readonly context: IExchangeContext;
|
|
199
|
+
};
|
|
189
200
|
};
|
|
190
201
|
|
|
191
202
|
export { AXIS_SYMBOL, type CandleModel, Code, File, type ILogger, type IPine, type IProvider, type PlotExtractConfig, type PlotMapping, type PlotModel, type PlotRecord, type SymbolInfoModel, type TPineCtor, dumpPlotData, extract, getSignal, pine as lib, run, setLogger, toMarkdown, toSignalDto, usePine };
|