@backtest-kit/pinets 3.0.2 → 3.0.3
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 +32 -3
- package/build/index.mjs +33 -4
- package/package.json +1 -1
- 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');
|
|
@@ -82,6 +83,7 @@ const { provide, inject, init, override } = diKit.createActivator("pine");
|
|
|
82
83
|
|
|
83
84
|
const baseServices = {
|
|
84
85
|
loggerService: Symbol("loggerService"),
|
|
86
|
+
contextService: Symbol("contextService"),
|
|
85
87
|
};
|
|
86
88
|
const providerServices$1 = {
|
|
87
89
|
axisProviderService: Symbol("axisProviderService"),
|
|
@@ -230,9 +232,28 @@ class AxisProviderService {
|
|
|
230
232
|
}
|
|
231
233
|
}
|
|
232
234
|
|
|
235
|
+
const ContextService = diScoped.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 (ContextService.hasContext()) {
|
|
243
|
+
return await backtestKit.Exchange.getRawCandles(symbol, interval, self.contextService.context, limit, sDate, eDate);
|
|
244
|
+
}
|
|
245
|
+
if (!backtestKit.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 (!backtestKit.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 backtestKit.getRawCandles(symbol, interval, limit, sDate, eDate);
|
|
252
|
+
};
|
|
233
253
|
class CandleProviderService {
|
|
234
254
|
constructor() {
|
|
235
255
|
this.loggerService = inject(TYPES.loggerService);
|
|
256
|
+
this.contextService = inject(TYPES.contextService);
|
|
236
257
|
}
|
|
237
258
|
async getMarketData(tickerId, timeframe, limit, sDate, eDate) {
|
|
238
259
|
this.loggerService.log("candleProviderService getMarketData", {
|
|
@@ -245,7 +266,7 @@ class CandleProviderService {
|
|
|
245
266
|
const symbol = tickerId
|
|
246
267
|
.toUpperCase()
|
|
247
268
|
.replace(/^BINANCE:|^BYBIT:|^OKX:/, "");
|
|
248
|
-
const rawCandles = await
|
|
269
|
+
const rawCandles = await GET_RAW_CANDLES_FN(this, symbol, timeframe, limit, sDate, eDate);
|
|
249
270
|
const candles = rawCandles.map((c) => ({
|
|
250
271
|
openTime: c.timestamp,
|
|
251
272
|
open: c.open,
|
|
@@ -553,6 +574,7 @@ class PineMarkdownService {
|
|
|
553
574
|
|
|
554
575
|
{
|
|
555
576
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
577
|
+
provide(TYPES.contextService, () => new ContextService());
|
|
556
578
|
}
|
|
557
579
|
{
|
|
558
580
|
provide(TYPES.axisProviderService, () => new AxisProviderService());
|
|
@@ -576,6 +598,7 @@ class PineMarkdownService {
|
|
|
576
598
|
|
|
577
599
|
const commonServices = {
|
|
578
600
|
loggerService: inject(TYPES.loggerService),
|
|
601
|
+
contextService: inject(TYPES.contextService),
|
|
579
602
|
};
|
|
580
603
|
const providerServices = {
|
|
581
604
|
axisProviderService: inject(TYPES.axisProviderService),
|
|
@@ -626,7 +649,13 @@ const GET_SOURCE_FN$1 = async (source) => {
|
|
|
626
649
|
}
|
|
627
650
|
throw new Error("Source must be a File or Code instance");
|
|
628
651
|
};
|
|
629
|
-
async
|
|
652
|
+
const RUN_INFERENCE_FN = async (script, symbol, timeframe, limit, exchangeName) => {
|
|
653
|
+
if (exchangeName) {
|
|
654
|
+
return await ContextService.runInContext(async () => await pine.pineJobService.run(script, symbol, timeframe, limit), { exchangeName });
|
|
655
|
+
}
|
|
656
|
+
return await pine.pineJobService.run(script, symbol, timeframe, limit);
|
|
657
|
+
};
|
|
658
|
+
async function run(source, { symbol, timeframe, limit }, exchangeName) {
|
|
630
659
|
pine.loggerService.info(METHOD_NAME_RUN$2, {
|
|
631
660
|
source,
|
|
632
661
|
symbol,
|
|
@@ -634,7 +663,7 @@ async function run(source, { symbol, timeframe, limit }) {
|
|
|
634
663
|
limit,
|
|
635
664
|
});
|
|
636
665
|
const script = await GET_SOURCE_FN$1(source);
|
|
637
|
-
const { plots } = await
|
|
666
|
+
const { plots } = await RUN_INFERENCE_FN(script, symbol, timeframe, limit, exchangeName);
|
|
638
667
|
return plots;
|
|
639
668
|
}
|
|
640
669
|
|
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';
|
|
@@ -79,6 +80,7 @@ const { provide, inject, init, override } = createActivator("pine");
|
|
|
79
80
|
|
|
80
81
|
const baseServices = {
|
|
81
82
|
loggerService: Symbol("loggerService"),
|
|
83
|
+
contextService: Symbol("contextService"),
|
|
82
84
|
};
|
|
83
85
|
const providerServices$1 = {
|
|
84
86
|
axisProviderService: Symbol("axisProviderService"),
|
|
@@ -227,9 +229,28 @@ class AxisProviderService {
|
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
231
|
|
|
232
|
+
const ContextService = scoped(class {
|
|
233
|
+
constructor(context) {
|
|
234
|
+
this.context = context;
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
const GET_RAW_CANDLES_FN = async (self, symbol, interval, limit, sDate, eDate) => {
|
|
239
|
+
if (ContextService.hasContext()) {
|
|
240
|
+
return await Exchange.getRawCandles(symbol, interval, self.contextService.context, limit, sDate, eDate);
|
|
241
|
+
}
|
|
242
|
+
if (!MethodContextService.hasContext()) {
|
|
243
|
+
throw new Error("MethodContextService context is required to get market data for pinets if exchangeName?: string is not specified");
|
|
244
|
+
}
|
|
245
|
+
if (!ExecutionContextService.hasContext()) {
|
|
246
|
+
throw new Error("ExecutionContextService context is required to get market data for pinets if exchangeName?: string is not specified");
|
|
247
|
+
}
|
|
248
|
+
return await getRawCandles(symbol, interval, limit, sDate, eDate);
|
|
249
|
+
};
|
|
230
250
|
class CandleProviderService {
|
|
231
251
|
constructor() {
|
|
232
252
|
this.loggerService = inject(TYPES.loggerService);
|
|
253
|
+
this.contextService = inject(TYPES.contextService);
|
|
233
254
|
}
|
|
234
255
|
async getMarketData(tickerId, timeframe, limit, sDate, eDate) {
|
|
235
256
|
this.loggerService.log("candleProviderService getMarketData", {
|
|
@@ -242,7 +263,7 @@ class CandleProviderService {
|
|
|
242
263
|
const symbol = tickerId
|
|
243
264
|
.toUpperCase()
|
|
244
265
|
.replace(/^BINANCE:|^BYBIT:|^OKX:/, "");
|
|
245
|
-
const rawCandles = await
|
|
266
|
+
const rawCandles = await GET_RAW_CANDLES_FN(this, symbol, timeframe, limit, sDate, eDate);
|
|
246
267
|
const candles = rawCandles.map((c) => ({
|
|
247
268
|
openTime: c.timestamp,
|
|
248
269
|
open: c.open,
|
|
@@ -550,6 +571,7 @@ class PineMarkdownService {
|
|
|
550
571
|
|
|
551
572
|
{
|
|
552
573
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
574
|
+
provide(TYPES.contextService, () => new ContextService());
|
|
553
575
|
}
|
|
554
576
|
{
|
|
555
577
|
provide(TYPES.axisProviderService, () => new AxisProviderService());
|
|
@@ -573,6 +595,7 @@ class PineMarkdownService {
|
|
|
573
595
|
|
|
574
596
|
const commonServices = {
|
|
575
597
|
loggerService: inject(TYPES.loggerService),
|
|
598
|
+
contextService: inject(TYPES.contextService),
|
|
576
599
|
};
|
|
577
600
|
const providerServices = {
|
|
578
601
|
axisProviderService: inject(TYPES.axisProviderService),
|
|
@@ -623,7 +646,13 @@ const GET_SOURCE_FN$1 = async (source) => {
|
|
|
623
646
|
}
|
|
624
647
|
throw new Error("Source must be a File or Code instance");
|
|
625
648
|
};
|
|
626
|
-
async
|
|
649
|
+
const RUN_INFERENCE_FN = async (script, symbol, timeframe, limit, exchangeName) => {
|
|
650
|
+
if (exchangeName) {
|
|
651
|
+
return await ContextService.runInContext(async () => await pine.pineJobService.run(script, symbol, timeframe, limit), { exchangeName });
|
|
652
|
+
}
|
|
653
|
+
return await pine.pineJobService.run(script, symbol, timeframe, limit);
|
|
654
|
+
};
|
|
655
|
+
async function run(source, { symbol, timeframe, limit }, exchangeName) {
|
|
627
656
|
pine.loggerService.info(METHOD_NAME_RUN$2, {
|
|
628
657
|
source,
|
|
629
658
|
symbol,
|
|
@@ -631,7 +660,7 @@ async function run(source, { symbol, timeframe, limit }) {
|
|
|
631
660
|
limit,
|
|
632
661
|
});
|
|
633
662
|
const script = await GET_SOURCE_FN$1(source);
|
|
634
|
-
const { plots } = await
|
|
663
|
+
const { plots } = await RUN_INFERENCE_FN(script, symbol, timeframe, limit, exchangeName);
|
|
635
664
|
return plots;
|
|
636
665
|
}
|
|
637
666
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backtest-kit/pinets",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
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",
|
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 IContext {
|
|
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): 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 contextService: {
|
|
148
|
+
readonly context: IContext;
|
|
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
|
+
contextService: {
|
|
198
|
+
readonly context: IContext;
|
|
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 };
|