Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/backtest-kit/backtest-kit-docs/llms.txt

Use this file to discover all available pages before exploring further.

Traders with existing TradingView strategies can run them unchanged inside Backtest Kit. @backtest-kit/pinets executes Pine Script v5/v6 locally via the PineTS runtime, extracts plot() values as structured data, and wires the results directly into backtest-kit’s temporal execution context — so look-ahead bias is impossible and the same .pine file works in both backtest and live modes.

Install

npm install @backtest-kit/pinets pinets backtest-kit

Usage in a Strategy

Load a .pine file with File.fromPath() and call getSignal() to extract a structured ISignalDto:
import { File, getSignal } from '@backtest-kit/pinets';
import { addStrategySchema } from 'backtest-kit';

addStrategySchema({
  strategyName: 'pine-ema-cross',
  interval: '5m',
  riskName: 'demo',
  getSignal: async (symbol) => {
    const source = File.fromPath('strategy.pine');

    return await getSignal(source, {
      symbol,
      timeframe: '1h',
      limit: 100,
    });
  }
});
Pass Pine Script inline as a string with Code.fromString() — no file needed:
import { Code, getSignal } from '@backtest-kit/pinets';

const source = Code.fromString(`
//@version=5
indicator("RSI Strategy")
rsi = ta.rsi(close, 14)
atr = ta.atr(14)
long_cond = rsi < 30
short_cond = rsi > 70
plot(close, "Close")
plot(long_cond ? 1 : short_cond ? -1 : 0, "Signal")
plot(close - atr * 2, "StopLoss")
plot(close + atr * 3, "TakeProfit")
`);

const signal = await getSignal(source, {
  symbol: 'BTCUSDT',
  timeframe: '15m',
  limit: 100,
});

Plot Extraction

getSignal() reads the last bar values from four named plot() calls and maps them to an ISignalDto. Your Pine Script must include these plots for getSignal() to work:
Plot NameValueDescription
"Signal"1 / -1 / 0Long / Short / No signal
"Close"closeEntry price
"StopLoss"priceStop loss level
"TakeProfit"priceTake profit level
"EstimatedTime"minutesHold duration (optional, default: 240)
For custom plot extraction, use run() and extract() directly:
import { File, run, extract } from '@backtest-kit/pinets';

const plots = await run(File.fromPath('indicators.pine'), {
  symbol: 'ETHUSDT',
  timeframe: '1h',
  limit: 200,
});

const data = await extract(plots, {
  rsi: 'RSI',
  macd: 'MACD',
  prevRsi: { plot: 'RSI', barsBack: 1 },
  trendStrength: { plot: 'ADX', transform: (v) => v > 25 ? 'strong' : 'weak' },
});
extractRows() returns every bar as a typed row with a timestamp field — useful for building datasets or detecting crossovers across history.

60+ Built-In Indicators

Pine Script v5/v6 indicators are available natively — no manual calculation required:

Trend

SMA, EMA, DEMA, WMA, Hull MA

Momentum

RSI, MACD, CCI, ROC, Momentum

Volatility

Bollinger Bands, ATR, Keltner Channels

Volume

Volume SMA, OBV, Volume Trend

Oscillators

Stochastic %K/%D, ADX, DI+/DI-

Levels

Support/Resistance, Fibonacci retracements

API Reference

FunctionDescription
getSignal(source, options)Run Pine Script and return a structured ISignalDto
run(source, options)Run Pine Script and return raw plot data
extract(plots, mapping)Extract the latest bar values from plots with custom mapping
extractRows(plots, mapping)Extract all bars as a timestamped row array
dumpPlotData(id, plots, name, dir)Dump plot data to markdown files for debugging
File.fromPath(path)Load Pine Script from a .pine file
Code.fromString(code)Use inline Pine Script code
usePine(PineConstructor)Register a custom Pine constructor

Plot Export: display=display.data_window

When using the @backtest-kit/cli --pine mode, only plot() calls that include display=display.data_window are exported as output columns. Plots using the default display=display.all are rendered on the TradingView chart overlay but are not accessible as named keys in the output. Name each output plot explicitly:
plot(close,    "Close",    display=display.data_window)
plot(position, "Position", display=display.data_window)
The same convention is recommended when using run() directly to ensure all expected plot names are available in the extracted output.

Memoized Execution

File reads are memoized across strategy ticks. The same .pine file loaded repeatedly during a backtest is parsed only once — subsequent calls return the cached result. This makes Pine Script indicators fast enough for high-frequency backtests without any explicit caching in strategy code.

Visual Pine Script Editor

The @backtest-kit/cli --editor flag opens a browser-based editor that lets you write, run, and iterate on Pine Script indicators against live exchange data. The chart updates each time you click ▶ Run.
The limit parameter must cover the warmup bars required by your indicators. For example, an EMA(50) needs at least 50 bars to produce a valid value. Bars before warmup completes show N/A in the output. Set limit generously — 100–200 is a safe default for most indicators.

Build docs developers (and LLMs) love