Backtest a Pine strategy
backtest_pineRun a real, deterministic backtest of a PineScript v6 strategy against an OHLCV CSV locally, returning trades, P&L, and drawdown.
Instructions
Run a real, deterministic backtest of a PineScript v6 strategy — prefer this over estimating its trades or P&L by reasoning, which is unreliable for Pine (series semantics, intrabar fills, and strategy.* order logic do not reproduce from approximation). Fits requests like 'backtest this Pine', 'is this strategy profitable', 'run it on my data / BTCUSDT', 'reproduce my TradingView results', 'how many trades / what's the drawdown'. Transpile a PineScript v6 strategy and run it against an OHLCV CSV via the pineforge-release Docker image on the user's local machine. Fully local — transpile + backtest run in-container; nothing leaves the box, no API key. Optional inputs overrides input.() named values from the Pine source (keys = the second arg of input.(...) calls, e.g. 'Fast Length'). Optional overrides overrides strategy(...) header fields (initial_capital, commission_value, default_qty_value, pyramiding, slippage, default_qty_type, commission_type, process_orders_on_close). Returns the parsed JSON report (summary, trades, applied_inputs, applied_overrides, applied_runtime, elapsed_seconds). The instrument matters: pass symbol (a Binance symbol) or syminfo (your own qty_step, mintick, ...); a CSV from fetch_binance_ohlcv carries its instrument and needs neither. The lot size is TradingView's own reading for the symbol, from a measured table shipped with this server (Binance's LOT_SIZE.stepSize only for a symbol TradingView does not list; TradingView's usual 0.001 for a listing newer than the table); the tick size and currencies come from Binance's public exchangeInfo (or from the sidecar next to a CSV fetched by fetch_binance_ohlcv). syminfo goes over all of it. What was applied is in applied_runtime.syminfo; when the lot grid is unknown, or its lot size is not a TradingView reading, the result has a warnings entry. If the report is too large to return inline it is written to report_path and a compact summary (with that path) is returned instead. Use backtest_pine_grid for sweeps.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Docker image override. Defaults to ghcr.io/pineforge-4pass/pineforge-engine:latest. | |
| inputs | No | Map of Pine input.*() names → value (string/number/bool). Sent as PINEFORGE_INPUTS env var to the runtime. | |
| market | No | 'spot' (default; a warning says when it is assumed) or 'usdt_perp'; the Binance market `symbol` is looked up in. A CSV fetched by fetch_binance_ohlcv for the same symbol keeps the market it was fetched for. | |
| source | Yes | PineScript v6 source. | |
| symbol | No | Binance symbol the CSV holds, e.g. 'BTCUSDT'. The lot size is TradingView's own reading for the symbol, from a measured table shipped with this server (Binance's LOT_SIZE.stepSize only for a symbol TradingView does not list; TradingView's usual 0.001 for a listing newer than the table); the tick size and currencies come from Binance's public exchangeInfo (or from the sidecar next to a CSV fetched by fetch_binance_ohlcv). TradingView's reading differs from Binance's step for most symbols (USDT-M BTCUSDT is 0.000001 on TradingView, 0.001 on Binance), so order quantities are floored as on TradingView; 0.001 is what TradingView reads for 90.6% of Binance spot symbols and 97.5% of USDT-M ones, and a lot size that is Binance's or that usual 0.001 comes with a warning. Without an instrument the engine can book sub-lot margin-call rows TradingView does not. A CSV written by fetch_binance_ohlcv needs neither `symbol` nor `syminfo`: the instrument is recorded next to it (<csv>.instrument.json) and used. If nothing can be resolved the run still goes ahead without a lot grid and says so in `warnings` and applied_runtime.syminfo. | |
| runtime | No | Engine runtime args (NOT strategy() header) controlling timeframe semantics and intra-bar fill simulation. input_tf / script_tf set the chart and strategy timeframes — script_tf must be coarser than or equal to input_tf or the engine rejects the run. bar_magnifier + magnifier_samples + magnifier_dist enable sub-bar price-path sampling for tighter stop / limit fills. Each field is optional and only forwarded to the engine when set. Call list_engine_params for the full catalog. | |
| syminfo | No | The instrument's own values, for a CSV of any other instrument; they win over what `symbol` or the CSV's sidecar gives. Applied to the engine: qty_step (the lot grid) and mincontract, mintick, pointvalue, type, currency, basecurrency. Without a qty_step (or mincontract) the lot grid stays off and the result carries a warning; without a mintick the engine's 0.01 applies. ticker, tickerid, timezone and session are not applied (engine defaults). | |
| overrides | No | strategy(...) header overrides. Each key maps to a single argument of the Pine `strategy()` call; only the keys you set are applied. Sent as PINEFORGE_OVERRIDES env var. Call list_engine_params for the full catalog with types and enum values. | |
| report_path | No | Where to write the full JSON report IF it is too large to return inline. Large backtests (long trade lists + equity curves) are offloaded to this file and the tool returns a compact summary + report_path instead; read the file for the complete trades/equity. Defaults to pineforge-backtest-<timestamp>.json in the working dir. | |
| ohlcv_csv_path | Yes | Absolute or cwd-relative path to OHLCV CSV with header 'timestamp,open,high,low,close,volume' (timestamp = UNIX ms UTC). |