oakscriptjs 0.11.5 → 0.11.6

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.
@@ -136,6 +136,11 @@ export interface ScriptRunResult {
136
136
  barColorConfig: BarColorConfig[];
137
137
  /** plotcandle() / plotbar() declarations */
138
138
  candleConfig: CandleConfig[];
139
+ /**
140
+ * The plot(), plotshape(), plotchar(), plotarrow(), plotcandle() and plotbar() declarations in the order the
141
+ * script made them (the id of each in its own config). PineScript numbers a script's outputs in this order.
142
+ */
143
+ outputs: ScriptOutput[];
139
144
  defaultInputs: Record<string, unknown>;
140
145
  alertConfig: AlertConditionConfig[];
141
146
  /** Strategy properties (declared values, else the PineScript defaults) when the script declares strategy(). */
@@ -143,9 +148,10 @@ export interface ScriptRunResult {
143
148
  /**
144
149
  * The renderable output: plots keyed by plotConfig ids, plot-pair fills, markers, arrows, background and bar
145
150
  * colours, candles and bars, and the drawings (labels, lines, boxes, linefills, polylines, tables) alive after the
146
- * last bar.
151
+ * last bar. `outputValues`: per plotshape() / plotchar() / plotarrow() id, the value of its series on each bar where
152
+ * it is not na (a condition gives 1 or 0), at the bar it was computed on (the offset not applied).
147
153
  */
148
- result: IndicatorResult & { alerts?: AlertState[]; alertCalls?: AlertCall[] };
154
+ result: IndicatorResult & { alerts?: AlertState[]; alertCalls?: AlertCall[]; outputValues?: Record<string, TimeValue[]> };
149
155
  /** The script called alert() during the run (PineScript `hasAlertFunction` is known at compile time: a host that
150
156
  * needs it before any bar runs reads the source). */
151
157
  hasAlertFunction: boolean;
@@ -177,6 +183,14 @@ export interface AlertCall {
177
183
  freq: AlertFrequency;
178
184
  }
179
185
 
186
+ /** One output declaration of a script: plot(), plotshape() ('shape'), plotchar() ('char'), plotarrow() ('arrow'),
187
+ * plotcandle() ('candle') or plotbar() ('bar'), with its id in plotConfig / shapeConfig / arrowConfig / candleConfig. */
188
+ export interface ScriptOutput {
189
+ kind: 'plot' | 'shape' | 'char' | 'arrow' | 'candle' | 'bar';
190
+ id: string;
191
+ title?: string;
192
+ }
193
+
180
194
  /** Handle returned by plot()/hline() so fill() can reference them. */
181
195
  export interface PlotHandle {
182
196
  id: string;
@@ -201,6 +215,7 @@ interface Collector {
201
215
  fillConfig: FillConfig[];
202
216
  shapeConfig: ShapeConfig[];
203
217
  markers: MarkerData[];
218
+ outputValues: Record<string, TimeValue[]>;
204
219
  arrowConfig: ArrowConfig[];
205
220
  arrows: ArrowData[];
206
221
  barColorConfig: BarColorConfig[];
@@ -209,6 +224,7 @@ interface Collector {
209
224
  candleConfig: CandleConfig[];
210
225
  plotCandles: Record<string, PlotCandleData[]>;
211
226
  plotBars: Record<string, PlotBarData[]>;
227
+ outputs: ScriptOutput[];
212
228
  alertConfig: AlertConditionConfig[];
213
229
  alerts: AlertState[];
214
230
  alertCalls: AlertCall[];
@@ -257,6 +273,7 @@ function freshCollector(inputValues: Record<string, unknown>): Collector {
257
273
  fillConfig: [],
258
274
  shapeConfig: [],
259
275
  markers: [],
276
+ outputValues: {},
260
277
  arrowConfig: [],
261
278
  arrows: [],
262
279
  barColorConfig: [],
@@ -265,6 +282,7 @@ function freshCollector(inputValues: Record<string, unknown>): Collector {
265
282
  candleConfig: [],
266
283
  plotCandles: {},
267
284
  plotBars: {},
285
+ outputs: [],
268
286
  alertConfig: [],
269
287
  alerts: [],
270
288
  alertCalls: [],
@@ -343,6 +361,7 @@ export function executeScript(
343
361
  arrowConfig: c.arrowConfig,
344
362
  barColorConfig: c.barColorConfig,
345
363
  candleConfig: c.candleConfig,
364
+ outputs: c.outputs,
346
365
  defaultInputs: c.defaultInputs,
347
366
  alertConfig: c.alertConfig,
348
367
  strategyConfig: c.strategy?.properties,
@@ -351,6 +370,7 @@ export function executeScript(
351
370
  plots: c.plots,
352
371
  fills: c.fills.length ? c.fills : undefined,
353
372
  markers: c.markers.length ? c.markers : undefined,
373
+ outputValues: Object.keys(c.outputValues).length ? c.outputValues : undefined,
354
374
  arrows: c.arrows.length ? c.arrows : undefined,
355
375
  bgColors: c.bgColors.length ? c.bgColors : undefined,
356
376
  barColors: c.barColors.length ? c.barColors : undefined,
@@ -690,6 +710,7 @@ function plotImpl(series: Series, title?: string, options: ScriptPlotOptions = {
690
710
  histbase: options.histbase,
691
711
  forceOverlay: options.force_overlay,
692
712
  });
713
+ c.outputs.push({ kind: 'plot', id, title: title ?? id });
693
714
  const values = series.toArray();
694
715
  const b = bars();
695
716
  const data: TimeValue[] = [];
@@ -899,6 +920,18 @@ function markerPosition(location: MarkerLocation, shape: ShapeStyle | undefined)
899
920
  /** Default colour of plotshape / plotchar markers. */
900
921
  const MARKER_COLOR = '#2962FF';
901
922
 
923
+ /** The value of an output's series on each bar where it is not na (a condition: 1 or 0), at the bar it was computed
924
+ * on: what PineScript gives for the output in an alert message. */
925
+ function outputSeries(values: ArrayLike<unknown>, b: readonly Bar[]): TimeValue[] {
926
+ const series: TimeValue[] = [];
927
+ for (let i = 0; i < b.length; i++) {
928
+ const v = values[i];
929
+ if (typeof v === 'number' && Number.isFinite(v)) series.push({ time: b[i]!.time, value: v });
930
+ else if (typeof v === 'boolean') series.push({ time: b[i]!.time, value: v ? 1 : 0 });
931
+ }
932
+ return series;
933
+ }
934
+
902
935
  /** Shared emitter for plotshape()/plotchar(). Emits one marker per bar where
903
936
  * the condition is truthy (not na, not 0). A plotchar marker has the shape 'circle' and its character in `char`. */
904
937
  function emitMarkers(
@@ -926,6 +959,7 @@ function emitMarkers(
926
959
  offset: options.offset,
927
960
  forceOverlay: options.force_overlay,
928
961
  });
962
+ c.outputs.push({ kind, id, title });
929
963
  const shapeStyle = kind === 'shape' ? (style as ShapeStyle) : undefined;
930
964
  const template: Omit<MarkerData, 'time'> = {
931
965
  position: markerPosition(location, shapeStyle),
@@ -942,6 +976,7 @@ function emitMarkers(
942
976
  const values = condition.toArray();
943
977
  const b = bars();
944
978
  const off = options.offset ?? 0;
979
+ c.outputValues[id] = outputSeries(values, b);
945
980
  for (let i = 0; i < b.length; i++) {
946
981
  const v = values[i];
947
982
  if (v === undefined || Number.isNaN(v) || v === 0) continue;
@@ -1001,9 +1036,11 @@ export function plotarrow(series: Series, title?: string, options: PlotArrowOpti
1001
1036
  display: options.display,
1002
1037
  forceOverlay: options.force_overlay,
1003
1038
  });
1039
+ c.outputs.push({ kind: 'arrow', id, title });
1004
1040
  const values = series.toArray();
1005
1041
  const b = bars();
1006
1042
  const off = options.offset ?? 0;
1043
+ c.outputValues[id] = outputSeries(values, b);
1007
1044
  for (let i = 0; i < b.length; i++) {
1008
1045
  const v = values[i];
1009
1046
  if (v === undefined || Number.isNaN(v) || v === 0) continue;
@@ -1135,6 +1172,7 @@ export function plotcandle(
1135
1172
  display: options.display,
1136
1173
  forceOverlay: options.force_overlay,
1137
1174
  });
1175
+ c.outputs.push({ kind: 'candle', id, title });
1138
1176
  const b = bars();
1139
1177
  c.plotCandles[id] = ohlcRows(open, high, low, close).map(({ i, ...ohlc }) => {
1140
1178
  const candle: PlotCandleData = { time: b[i]!.time, ...ohlc };
@@ -1171,6 +1209,7 @@ export function plotbar(
1171
1209
  display: options.display,
1172
1210
  forceOverlay: options.force_overlay,
1173
1211
  });
1212
+ c.outputs.push({ kind: 'bar', id, title });
1174
1213
  const b = bars();
1175
1214
  c.plotBars[id] = ohlcRows(open, high, low, close).map(({ i, ...ohlc }) => {
1176
1215
  const bar: PlotBarData = { time: b[i]!.time, ...ohlc };