@backtest-kit/pinets 5.9.0 → 5.10.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/build/index.cjs CHANGED
@@ -361,10 +361,47 @@ const GET_VALUE_FN = (plots, name, barsBack = 0) => {
361
361
  const idx = data.length - 1 - barsBack;
362
362
  return idx >= 0 ? (data[idx]?.value ?? 0) : 0;
363
363
  };
364
+ const GET_VALUE_AT_FN = (plots, name, i, barsBack = 0) => {
365
+ const data = plots[name]?.data;
366
+ if (!data)
367
+ return null;
368
+ const idx = i - barsBack;
369
+ return idx >= 0 ? (data[idx]?.value ?? null) : null;
370
+ };
364
371
  class PineDataService {
365
372
  constructor() {
366
373
  this.loggerService = inject(TYPES.loggerService);
367
374
  }
375
+ extractRows(plots, mapping) {
376
+ this.loggerService.log("pineDataService extractRows", {
377
+ plotCount: Object.keys(plots).length,
378
+ mapping,
379
+ });
380
+ const entries = Object.entries(mapping);
381
+ const plotNames = entries.map(([, config]) => typeof config === "string" ? config : config.plot);
382
+ const dataLength = plotNames
383
+ .map((name) => plots[name]?.data?.length ?? 0)
384
+ .reduce((acm, cur) => Math.max(acm, cur), 0);
385
+ const rows = [];
386
+ for (let i = 0; i < dataLength; i++) {
387
+ const row = {};
388
+ for (const [key, config] of entries) {
389
+ if (typeof config === "string") {
390
+ row[key] = GET_VALUE_AT_FN(plots, config, i);
391
+ }
392
+ else {
393
+ const raw = GET_VALUE_AT_FN(plots, config.plot, i, config.barsBack ?? 0);
394
+ row[key] = (raw !== null && config.transform ? config.transform(raw) : raw);
395
+ }
396
+ }
397
+ const firstPlot = plots[plotNames[0]]?.data?.[i];
398
+ row.timestamp = firstPlot?.time
399
+ ? new Date(firstPlot.time).toISOString()
400
+ : "";
401
+ rows.push(row);
402
+ }
403
+ return rows;
404
+ }
368
405
  extract(plots, mapping) {
369
406
  this.loggerService.log("pineDataService extract", {
370
407
  plotCount: Object.keys(plots).length,
@@ -731,7 +768,7 @@ function useIndicator(ctor) {
731
768
  pine.indicatorConnectionService.useIndicator(ctor);
732
769
  }
733
770
 
734
- const METHOD_NAME_RUN$2 = "run.run";
771
+ const METHOD_NAME_RUN$1 = "run.run";
735
772
  const GET_SOURCE_FN$2 = async (source) => {
736
773
  if (File.isFile(source)) {
737
774
  const code = await pine.pineCacheService.readFile(source.path, source.baseDir);
@@ -770,7 +807,7 @@ const RUN_INFERENCE_FN$1 = async (script, symbol, timeframe, limit, inputs, exch
770
807
  return await inference();
771
808
  };
772
809
  async function run(source, { symbol, timeframe, limit, inputs = {} }, exchangeName, when) {
773
- pine.loggerService.info(METHOD_NAME_RUN$2, {
810
+ pine.loggerService.info(METHOD_NAME_RUN$1, {
774
811
  source,
775
812
  symbol,
776
813
  timeframe,
@@ -781,9 +818,16 @@ async function run(source, { symbol, timeframe, limit, inputs = {} }, exchangeNa
781
818
  return plots;
782
819
  }
783
820
 
784
- const METHOD_NAME_RUN$1 = "extract.extract";
821
+ const METHOD_NAME_EXTRACT = "extract.extract";
822
+ const METHOD_NAME_EXTRACT_ROWS = "extractRows.extractRows";
823
+ async function extractRows(plots, mapping) {
824
+ pine.loggerService.info(METHOD_NAME_EXTRACT_ROWS, {
825
+ mapping,
826
+ });
827
+ return pine.pineDataService.extractRows(plots, mapping);
828
+ }
785
829
  async function extract(plots, mapping) {
786
- pine.loggerService.info(METHOD_NAME_RUN$1, {
830
+ pine.loggerService.info(METHOD_NAME_EXTRACT, {
787
831
  mapping,
788
832
  });
789
833
  return pine.pineDataService.extract(plots, mapping);
@@ -934,6 +978,7 @@ exports.Code = Code;
934
978
  exports.File = File;
935
979
  exports.dumpPlotData = dumpPlotData;
936
980
  exports.extract = extract;
981
+ exports.extractRows = extractRows;
937
982
  exports.getSignal = getSignal;
938
983
  exports.lib = pine;
939
984
  exports.markdown = markdown;
package/build/index.mjs CHANGED
@@ -358,10 +358,47 @@ const GET_VALUE_FN = (plots, name, barsBack = 0) => {
358
358
  const idx = data.length - 1 - barsBack;
359
359
  return idx >= 0 ? (data[idx]?.value ?? 0) : 0;
360
360
  };
361
+ const GET_VALUE_AT_FN = (plots, name, i, barsBack = 0) => {
362
+ const data = plots[name]?.data;
363
+ if (!data)
364
+ return null;
365
+ const idx = i - barsBack;
366
+ return idx >= 0 ? (data[idx]?.value ?? null) : null;
367
+ };
361
368
  class PineDataService {
362
369
  constructor() {
363
370
  this.loggerService = inject(TYPES.loggerService);
364
371
  }
372
+ extractRows(plots, mapping) {
373
+ this.loggerService.log("pineDataService extractRows", {
374
+ plotCount: Object.keys(plots).length,
375
+ mapping,
376
+ });
377
+ const entries = Object.entries(mapping);
378
+ const plotNames = entries.map(([, config]) => typeof config === "string" ? config : config.plot);
379
+ const dataLength = plotNames
380
+ .map((name) => plots[name]?.data?.length ?? 0)
381
+ .reduce((acm, cur) => Math.max(acm, cur), 0);
382
+ const rows = [];
383
+ for (let i = 0; i < dataLength; i++) {
384
+ const row = {};
385
+ for (const [key, config] of entries) {
386
+ if (typeof config === "string") {
387
+ row[key] = GET_VALUE_AT_FN(plots, config, i);
388
+ }
389
+ else {
390
+ const raw = GET_VALUE_AT_FN(plots, config.plot, i, config.barsBack ?? 0);
391
+ row[key] = (raw !== null && config.transform ? config.transform(raw) : raw);
392
+ }
393
+ }
394
+ const firstPlot = plots[plotNames[0]]?.data?.[i];
395
+ row.timestamp = firstPlot?.time
396
+ ? new Date(firstPlot.time).toISOString()
397
+ : "";
398
+ rows.push(row);
399
+ }
400
+ return rows;
401
+ }
365
402
  extract(plots, mapping) {
366
403
  this.loggerService.log("pineDataService extract", {
367
404
  plotCount: Object.keys(plots).length,
@@ -728,7 +765,7 @@ function useIndicator(ctor) {
728
765
  pine.indicatorConnectionService.useIndicator(ctor);
729
766
  }
730
767
 
731
- const METHOD_NAME_RUN$2 = "run.run";
768
+ const METHOD_NAME_RUN$1 = "run.run";
732
769
  const GET_SOURCE_FN$2 = async (source) => {
733
770
  if (File.isFile(source)) {
734
771
  const code = await pine.pineCacheService.readFile(source.path, source.baseDir);
@@ -767,7 +804,7 @@ const RUN_INFERENCE_FN$1 = async (script, symbol, timeframe, limit, inputs, exch
767
804
  return await inference();
768
805
  };
769
806
  async function run(source, { symbol, timeframe, limit, inputs = {} }, exchangeName, when) {
770
- pine.loggerService.info(METHOD_NAME_RUN$2, {
807
+ pine.loggerService.info(METHOD_NAME_RUN$1, {
771
808
  source,
772
809
  symbol,
773
810
  timeframe,
@@ -778,9 +815,16 @@ async function run(source, { symbol, timeframe, limit, inputs = {} }, exchangeNa
778
815
  return plots;
779
816
  }
780
817
 
781
- const METHOD_NAME_RUN$1 = "extract.extract";
818
+ const METHOD_NAME_EXTRACT = "extract.extract";
819
+ const METHOD_NAME_EXTRACT_ROWS = "extractRows.extractRows";
820
+ async function extractRows(plots, mapping) {
821
+ pine.loggerService.info(METHOD_NAME_EXTRACT_ROWS, {
822
+ mapping,
823
+ });
824
+ return pine.pineDataService.extractRows(plots, mapping);
825
+ }
782
826
  async function extract(plots, mapping) {
783
- pine.loggerService.info(METHOD_NAME_RUN$1, {
827
+ pine.loggerService.info(METHOD_NAME_EXTRACT, {
784
828
  mapping,
785
829
  });
786
830
  return pine.pineDataService.extract(plots, mapping);
@@ -926,4 +970,4 @@ async function markdown(signalId, source, { symbol, timeframe, limit, inputs = {
926
970
  return await pine.pineMarkdownService.getReport(signalId, plots, mapping, Number.POSITIVE_INFINITY);
927
971
  }
928
972
 
929
- export { AXIS_SYMBOL, Code, File, dumpPlotData, extract, getSignal, pine as lib, markdown, run, setLogger, toMarkdown, toSignalDto, useIndicator, usePine };
973
+ export { AXIS_SYMBOL, Code, File, dumpPlotData, extract, extractRows, getSignal, pine as lib, markdown, run, setLogger, toMarkdown, toSignalDto, useIndicator, usePine };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backtest-kit/pinets",
3
- "version": "5.9.0",
3
+ "version": "5.10.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",
@@ -69,12 +69,12 @@
69
69
  "ts-morph": "27.0.2",
70
70
  "tslib": "2.7.0",
71
71
  "typedoc": "0.27.9",
72
- "backtest-kit": "5.9.0",
72
+ "backtest-kit": "5.10.0",
73
73
  "worker-testbed": "1.0.12"
74
74
  },
75
75
  "peerDependencies": {
76
- "backtest-kit": "^5.9.0",
77
- "pinets": "^0.9.7",
76
+ "backtest-kit": "^5.10.0",
77
+ "pinets": "^0.9.8",
78
78
  "typescript": "^5.0.0"
79
79
  },
80
80
  "dependencies": {
package/types.d.ts CHANGED
@@ -74,11 +74,18 @@ type PlotMapping = {
74
74
  type ExtractedData<M extends PlotMapping> = {
75
75
  [K in keyof M]: M[K] extends PlotExtractConfig<infer R> ? R : M[K] extends string ? number : never;
76
76
  };
77
+ type ExtractedDataRow<M extends PlotMapping> = {
78
+ [K in keyof M]: M[K] extends PlotExtractConfig<infer R> ? R | null : M[K] extends string ? number | null : never;
79
+ } & {
80
+ timestamp: string;
81
+ };
77
82
  declare class PineDataService {
78
83
  private readonly loggerService;
84
+ extractRows<M extends PlotMapping>(plots: PlotModel, mapping: M): ExtractedDataRow<M>[];
79
85
  extract<M extends PlotMapping>(plots: PlotModel, mapping: M): ExtractedData<M>;
80
86
  }
81
87
 
88
+ declare function extractRows<M extends PlotMapping>(plots: PlotModel, mapping: M): Promise<ExtractedDataRow<M>[]>;
82
89
  declare function extract<M extends PlotMapping>(plots: PlotModel, mapping: M): Promise<ExtractedData<M>>;
83
90
 
84
91
  interface ILogger {
@@ -226,4 +233,4 @@ declare const pine: {
226
233
  };
227
234
  };
228
235
 
229
- export { AXIS_SYMBOL, type CandleModel, Code, File, type IIndicator, type ILogger, type IPine, type IProvider, type PlotExtractConfig, type PlotMapping, type PlotModel, type PlotRecord, type SymbolInfoModel, type TIndicatorCtor, type TPineCtor, dumpPlotData, extract, getSignal, pine as lib, markdown, run, setLogger, toMarkdown, toSignalDto, useIndicator, usePine };
236
+ export { AXIS_SYMBOL, type CandleModel, Code, type ExtractedData, type ExtractedDataRow, File, type IIndicator, type ILogger, type IPine, type IProvider, type PlotExtractConfig, type PlotMapping, type PlotModel, type PlotRecord, type SymbolInfoModel, type TIndicatorCtor, type TPineCtor, dumpPlotData, extract, extractRows, getSignal, pine as lib, markdown, run, setLogger, toMarkdown, toSignalDto, useIndicator, usePine };