Apps & Running Sessions

Configure PineScript

Define a native Pine indicator and expose named Buy and Sell arrows to SJS.

This guide creates an indicator that plots signals. SJS will own order placement. Native Pine is saved in the app's pinescript field.

For native runtime support, inputs, signal timing, and strategy-intent limitations, read the Pine Script guides.

For saved configuration, launch choices, and session controls, follow Apps & Running Sessions. Check monitoring after startup and stopping and restarting when changing a running candidate.

1. Create or open an app

Open your workspace in the console and create or edit an app. Choose its app type, instrument, and interval. For your first run, use Stage Session (SSS) with historical data available for that instrument.

Open the PineScript editor. Keep the SJS, L3, and SQL/SQX editors empty until the chart behaves as expected. This gives you one signal source to inspect.

2. Define the indicator

Paste this into PineScript:

PineScript
//@version=5
indicator("Tutorial: range breakout", overlay=true)

length = input.int(15, "Range bars", minval=2)
rangeHigh = ta.highest(high, length)[1]
rangeLow = ta.lowest(low, length)[1]

buySignal = barstate.isconfirmed and ta.crossover(close, rangeHigh)
sellSignal = barstate.isconfirmed and ta.crossunder(close, rangeLow)

plot(rangeHigh, title="Range high", color=color.blue)
plot(rangeLow, title="Range low", color=color.orange)
plotshape(buySignal, title="Buy",
  style=shape.triangleup, location=location.belowbar,
  color=color.lime, size=size.small)
plotshape(sellSignal, title="Sell",
  style=shape.triangledown, location=location.abovebar,
  color=color.red, size=size.small)

The previous range uses [1], so the current candle does not move its own breakout threshold. Confirmation keeps this example focused on completed bars. It needs enough input bars to initialize the range and crossover calculation.

3. Save and inspect the chart

Save the app and run a historical window with more than 15 bars. Look for two range lines and arrows named Buy and Sell. A quiet window may have no breakouts; the absence of arrows alone is not an error.

An indicator's arrows are chart output. They do not place orders by themselves.

4. Read the arrows in SJS

Pine chart series are exposed through:

const series = context.pineState?.chartData?.series ?? [];
const buyPlot = series.find((item) => item.name === "Buy");
const latestPoint = buyPlot?.data?.at(-1);

Points may be arrays such as [time, value] or objects with x/time and y. Match the point's timestamp to new Date(bar.date).getTime() and reject missing values. An old arrow can remain the last point in a series after its signal has passed.

Native Pine runs after SJS in the shared frame, so a strict same-timestamp reader can reject the previous frame's output. See Signals in SJS for an explicit recent-event observer.

Keep plot titles and lookup names identical for a chart-series reader. The complete Pine signals to SJS orders tutorial uses the separate EMA indicator and its numeric pine.signal plot; use that paired source rather than connecting its reader directly to the Buy/Sell arrows above.

5. Choose one order owner

This tutorial uses indicator() plus SJS orders. Native Pine also supports strategy order intents through functions such as strategy.entry and strategy.close. If you use that path, do not also have SJS submit the same trades from arrows.

Troubleshooting

SymptomCheck
No range linesPine compilation, input bars, selected instrument and interval
Lines but no arrowsA confirmed breakout must occur after the lookback initializes
Arrows but no ordersAdd the SJS reader; indicators only plot signals
Stale or repeated entriesCompare signal and bar timestamps, and deduplicate execution attempts
Live startup differs from the testCheck warmup and whether the current bar is confirmed

Live Pine sessions default to one hour of warmup unless configured otherwise. Historical in-memory runs use their selected data window and do not fetch external warmup. Choose an interval and window that supply enough bars for your indicator.

On this page