Traders who have already built and validated strategies in TradingView’s Pine Script can run them unchanged inside Backtest Kit — no rewrite required. TheDocumentation 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.
@backtest-kit/pinets package embeds the open-source PineTS runtime, which provides 1:1 Pine Script v5/v6 syntax compatibility with 60+ built-in indicators. Your .pine file is loaded as-is; getSignal receives the computed plot outputs and translates them into standard Backtest Kit position parameters.
Backtest results (December 2025)
The strategy ran on the first half of December 2025 against a choppy BTC market that oscillated between ~94k with sharp intra-day reversals.| Metric | Value |
|---|---|
| Period | Dec 1 – Dec 15, 2025 (first half only) |
| Net PNL | **+900 deployed |
| Sharpe ratio | 0.06 |
| Total trades | 9 (6 LONG / 3 SHORT) |
| Win rate | 66.7% (6 / 9) |
| Best trade | +1.61% (Dec 1 SHORT) |
| Worst trade | −2.41% (Dec 5 SHORT — false breakout) |
| Worst drawdown | −2.35% per position |
| Avg hold time | ~20 hours |
| Exit method | Fixed ±2% TP/SL bracket |
Install dependencies
How it works
Step 1 — Pine Script file runs on 1h candles each tick
Step 1 — Pine Script file runs on 1h candles each tick
The strategy registers on a
1h interval. On each tick, it calls run(File.fromPath(...), options) from @backtest-kit/pinets, which executes btc_dec2025_range.pine inside the PineTS runtime. The result is an array of bar-by-bar output objects, one per candle, each containing the values of all plot() calls defined in the Pine Script file.Execution can be cached per hour via Cache.fn from backtest-kit — wrapping the run() call so the Pine Script executes only once per hour boundary, not once per minute, which keeps backtest speed high even with a large candle window.Step 2 — Plot extraction maps Pine outputs to strategy variables
Step 2 — Plot extraction maps Pine outputs to strategy variables
The
Only
run() call returns a plot data structure. extract() reads the latest bar values from named plots. The strategy extracts six values:| Plot name | Description |
|---|---|
bbUpper / bbLower / bbBasis | Bollinger Bands (20-period, 2σ) |
rangeHigh / rangeLow | Detected horizontal range boundaries |
signal | +1 = bullish breakout, −1 = bearish breakout, 0 = no signal |
isRanging | 1 = price still inside range → skip signal |
volSpike | 1 = volume confirmation present |
signal and isRanging gate trade entry. volSpike is tracked in the log but not used as a hard filter — the one trade without volume confirmation (trade #6) still hit take-profit.Step 3 — Entry filter: skip stale signals and ranging markets
Step 3 — Entry filter: skip stale signals and ranging markets
Even when
signal !== 0, two additional checks prevent entering on moves that have already run:- LONG (
signal === 1): skip ifcurrentPrice > plot.close— the breakout has already extended beyond where the signal fired. - SHORT (
signal === -1): skip ifcurrentPrice < plot.close— the breakdown has already run. - Both: skip if
isRanging === 1— price is still consolidating within the detected range and has not confirmed a breakout.
Step 4 — Fixed bracket exit: ±2% TP and SL, no DCA
Step 4 — Fixed bracket exit: ±2% TP and SL, no DCA
Valid signals open a
Position.bracket with a symmetric ±2% take-profit and stop-loss. There is no trailing stop, no DCA, and no time-based exit — positions either hit +2% (take-profit) or −2% (stop-loss). The minuteEstimatedTime: Infinity flag ensures the position is held until one of the two exits fires, regardless of how long it takes.This simplicity keeps the strategy easy to reason about: every trade risks exactly 2, and the edge comes entirely from signal accuracy (66.7% win rate in December).Pine Script indicator file
The indicator computes Bollinger Bands, detects a horizontal range, and emits a directional breakout signal. All outputs that the strategy needs to read must be declared withdisplay=display.data_window.
Strategy code
Plot extraction
run() returns an array of objects where each key matches the second argument of a plot() call in the Pine Script. For the breakout indicator:
plot(value, "name", ...). When using the @backtest-kit/cli --pine mode, only plots declared with display=display.data_window are exported as output columns — see the Tip at the bottom of this page for details.
60+ built-in indicators
The PineTS runtime bundles the same indicator library available in TradingView. You can use any of these directly in your.pine file:
| Category | Available indicators |
|---|---|
| Moving averages | SMA, EMA, WMA, VWMA, DEMA, TEMA, HMA, ALMA |
| Oscillators | RSI, MACD, Stochastic, CCI, Williams %R, MFI |
| Volatility | Bollinger Bands, ATR, Keltner Channels, Donchian |
| Trend | ADX, Aroon, PSAR, Ichimoku, SuperTrend |
| Volume | OBV, VWAP, CMF, Force Index |