An open-source C++17 engine for backtesting and forward execution, with PineScript support through code generation.
π pineforge.dev Β· βοΈ Hosted MCP Β· π³ Docker MCP Β· π¦ Transpiler Β· π C ABI docs Β· π§ͺ Coverage map Β· π¬ Benchmarks
PineForge is a C++17 engine for backtesting and forward execution, with a C ABI for embedding. The engine has two layers:
- A generic kernel β a Pine-agnostic backtest and forward-execution state machine: order matching and fills, sizing, margin and settlement, the bar magnifier, indicator classes,
request.security(), time and session math. It knows nothing about Pine or TradingView. - A source-adapter parity runtime (
src/source/,PineExecutionAdapter+PineStrategyHost) β maps Pine/TradingView execution semantics onto that kernel. This is where TradingView parity lives.
The separate PineForge compiler, pineforge-codegen, translates a PineScript v6 script into a C++ strategy that attaches the engine's Pine execution adapter; it owns translation, not execution semantics. TradingView comparisons measure this Pine path under the tested configurations. The order model describes the current submodels and the remaining migration work; Architecture states the boundary.
- Proven, not promised. All 4,190 probes β 312 open reference strategies plus 413 real community scripts on 15 markets and timeframes β grade excellent or strong against TradingView's own trade lists: 4,182 excellent, 8 strong, zero moderate. The current full sweep evaluates 2,819,967 TradingView trades, with 2,818,237 matched by the verifier.
- Open runtime. The engine and native live runner are Apache-2.0. The separately distributed PineForge compiler uses PolyForm Noncommercial terms with additional personal-trading permission; commercial use requires a separate license. Public reference strategies, benchmarks and validation tooling are available in their respective repositories; the community-script test set is not redistributed.
- Fast. In-process, no interpreter: median 162Γ faster than PyneCore on 99 timed strategies. Parameter sweeps re-run a loaded
.sowith new inputs β no recompile, no fork. - Deterministic to the bit. Two runs with the same inputs produce identical trade lists. Same on Linux and macOS.
- Yours to embed. One header, 65
extern "C"functions, append-only ABI. Call it from C, Python, Rust, Go, Node, Julia β or let an AI agent drive it over MCP.
claude mcp add pineforge-backtest \
-- docker run --rm -i -v "$PWD:/work" ghcr.io/pineforge-4pass/pineforge-backtest-mcp:latestFor Claude Desktop, Cursor or any MCP client:
Then ask: "Fetch BTC/USDT 15m for the last 90 days and backtest this strategy" β the container transpiles Pine β C++ with the bundled pineforge-codegen, compiles, runs, and hands the agent the trade list. Nothing leaves your machine. Mount a directory at /work; -i is required and -t must not be added (a TTY corrupts the JSON-RPC stream).
| Ask | Tool |
|---|---|
| "Fetch BTC/USDT 15m data for the last 30 days" | fetch_binance_ohlcv |
| "Backtest this SMA-cross strategy on that data" | backtest_pine |
| "Sweep fast 8β21 Γ slow 21β55, rank by net PnL" | backtest_pine_grid |
| "What broker overrides are available?" | list_engine_params |
Prefer zero install? The hosted server at mcp.pineforge.dev/mcp (Streamable HTTP, no key) backtests against a sealed Binance spot + USDT-perp data lake, metered per IP. The npm package @pineforge/backtest-mcp mirrors the same server.
git clone https://github.com/pineforge-4pass/pineforge-engine.git && cd pineforge-engine
python3 scripts/ci_verify.py release --build-dir build --jobs 4
bash tutorial/run.sh # MACD on BTC/USDT, end to end
python3 tutorial/run_stream.py # OHLCV warm-up β realtime tradesThe shared local/CI verifier includes source guards, tests and installed-package smoke checks. Its ABI check links callers against both the current library and a separately built, pinned historical library. Preparation uses local Git history and the configured compiler; see the ABI fixture guide for shallow clones and repeated checks. CTest itself stays offline.
Prerequisites: CMake β₯ 3.16, a C++17 compiler (GCC β₯ 9, Clang β₯ 10, Apple Clang β₯ 12), Eigen 3.3+ (fetched automatically if absent), Python 3 for the tests (-DPINEFORGE_BUILD_TESTS=OFF for a library-only build). cmake --install build --prefix /usr/local installs lib/libpineforge.a, include/pineforge/, and the find_package(PineForge) config.
#include <pineforge/pineforge.h>
int main(void) {
pf_strategy_t s = strategy_create(NULL);
pf_bar_t bars[] = { /* OHLCV ... */ };
pf_report_t r = {0};
run_backtest(s, bars, sizeof(bars)/sizeof(*bars), &r);
printf("%d trades, net %.2f\n", r.trades_len, r.net_profit);
report_free(&r);
strategy_free(s);
return 0;
}Every PineForge-compiled strategy .so exports this same ABI β write the harness once, swap strategies forever. Worked examples for C, Python sweeps, Rust, multi-strategy and magnifier A/B are in the docs.
Lifecycle-aware compiled modules reset Pine variables, indicator/history buffers and the broker book before each batch run or strategy_stream_begin warmup. Inputs and runtime settings persist until changed; ticks within a stream continue its state. Regenerate and rebuild existing modules with current codegen and matching engine headers/archive to obtain this behavior; the internal C++ rebuild boundary is checked at compile/link time.
Use NativeStrategyHost with an explicit NativeRunSpec for native market
transactions, reductions and flatten requests. The native engine guide
provides a complete C++ batch/stream example, calendar and execution contracts,
and a runnable JSON configuration for the live runner.
The optional C++17 pineforge-live executable uses this engine's native
warmup-to-stream lifecycle. It accepts normalized ticks or confirmed OHLCV bars,
supports user-defined C++ parsers for broker/provider messages, and commits
inputs plus order-action webhooks to a durable SQLite ledger. Hand-written
C++ strategies use the native contract; generated Pine strategies retain their
compatibility path. Both expose the versioned C ABI used by the runner.
Build with -DPINEFORGE_BUILD_LIVE_RUNNER=ON; the option is off by default,
so core-only users do not acquire SQLite/libcurl/OpenSSL dependencies. See
the native runner guide for feed modes, symbol metadata,
parser ABI, recovery and execution limitations. The existing validation
scoreboard below describes batch backtests; it does not certify new native
live behavior or real broker fills.
Native policy refactoring Β· 2026-09-10: engine #234 and codegen #127 preserve 4,182 excellent / 8 strong. Both the old-engine/new-codegen and new-engine/new-codegen Cloud runs retain all 4,190 raw trade CSVs, counts and full grades unchanged. The target bands have zero entrants and zero leavers: net 0, no individual regression. These changes remove an unused source flag and give Pine cap behavior explicit ownership; they do not claim complete engine independence. The formal gates remain zero-improvement FAILs and the official baseline remains unchanged.
Round 39 Β· 2026-09-09: 4,182 excellent / 8 strong / zero moderate across all 4,190 scored probes. This round adds one excellent result, with zero regressions on any canonical metric.
| Board | Test set | Result | TradingView trades evaluated |
|---|---|---|---|
| Public β open corpus | 312 reference strategies, Apache-2.0, reproducible by anyone | 309/309 graded excellent (ETH/USDT-perp 15m; the corpus' declared engine-only / anomaly probes are not graded) | 429,866 |
| Closed test β the parity campaign | 413 community-shared TradingView scripts across 15 market/timeframe lanes: 3,881 script-lane probes β private under TradingView's Terms of Service | 3,873 excellent + 8 strong + zero moderate = 3,881/3,881 (100%) excellent-or-strong | 2,390,101 |
2,819,967 TradingView trades evaluated, 2,818,237 matched by the verifier (99.94%), from the round 39 full Cloud Run sweep. 18 TradingView-side anomalies remain excluded under the unchanged population; each was documented before exclusion. No scored probe remains below strong.
Round 39 extends the existing price-scale admission check to ordinary, fee-free fractional market entries when one minimum lot is worth at least one account unit. It shares the existing financial and order-book scope with the signal-cost check. A separately queued close still fills when the opening is declined, and entries placed after a close retain their established exception.
PK Willow Pulse UT Williams Live Movement on BINANCE:BTCUSDT 15m moves from strong to excellent: canonical match rises from 96.9% to 100%, with zero trade-count gap and zero entry-price, exit-price, PnL and quantity error at the 90th percentile. Independent comparison of the unfiltered files matches all 12,408 physical trade pairs on side, entry/exit times, prices and quantity, gaining 10,756 matches with none lost. Including the displayed PnL in the exact comparison gains 2,193 matches with none lost; the files use different PnL display precision.
The fix has no strategy, symbol or date lookup. TradingView controls pin both directions, flat entries, reversal/close ordering and funding boundaries. A Cloud diagnostic reproduces the original selected trade CSV across all six observed invocations and confirms that the engine passed signal-cost admission but skipped the price-scale check for a high-value fractional lot. The exact explicit-quantity reversal control exposed a separate gap that remains unchanged by this default-sizing fix. All 704 hard-surface probes retain their canonical grades, quantity metrics and trade CSVs; 4,189 of 4,190 CSVs are unchanged. Verifier code, grading rules, profile-selection code, reference tapes, feeds, input files and scored population are unchanged.
| Market Β· timeframe | Probes | Excellent | Strong | Moderate |
|---|---|---|---|---|
| BINANCE:ETHUSDT.P Β· 15m (hard lane: zero regression allowed) | 395 | 394 | 1 | β |
| BINANCE:BTCUSDT Β· 15m | 354 | 354 | β | β |
| BINANCE:BTCUSDT Β· 1D | 259 | 259 | β | β |
| CME_MINI:ES1! Β· 15m | 174 | 173 | 1 | β |
| CME_MINI:ES1! Β· 1D | 117 | 117 | β | β |
| CME_MINI:NQ1! Β· 15m | 174 | 174 | β | β |
| CME_MINI:NQ1! Β· 1D | 116 | 116 | β | β |
| NASDAQ:AAPL Β· 15m | 356 | 354 | 2 | β |
| NSE:NIFTY Β· 15m | 191 | 191 | β | β |
| NSE:NIFTY Β· 1D | 145 | 145 | β | β |
| NYSE:F Β· 15m | 340 | 338 | 2 | β |
| NYSE:F Β· 1D | 263 | 263 | β | β |
| OANDA:EURUSD Β· 15m | 373 | 372 | 1 | β |
| OANDA:XAUUSD Β· 15m | 376 | 375 | 1 | β |
| OANDA:XAUUSD Β· 1D | 248 | 248 | β | β |
| Total | 3,881 | 3,873 | 8 | 0 |
Every script is exported from TradingView as-is (its own inputs, its own defaults) with the chart's trade list at full precision, transpiled with pineforge-codegen, and run by this engine on the same OHLCV bars. The two trade lists are aligned trade-for-trade and graded by scripts/verify_corpus.py:
- excellent β the same number of trades, β₯ 99% of TradingView's trades matched, entry and exit prices within 0.01% and PnL within 1% at the 90th percentile (trailing-stop scripts are graded on the production profile: exits within 0.05%, since a trail fill depends on TradingView's sub-bar path);
- strong β β₯ 95% matched, trade count within 6%, entries within 0.1% and exits within 0.5% at p90;
- moderate / weak β β₯ 75% coverage, or less.
Published parity results use a fixed population and reproducible Cloud Run measurements. The formal gate requires no hard-surface regression and strictly positive pooled movement across the target excellent and excellent+strong bands. A documented native-correctness exception permits exactly zero target-band movement with no individual regression, after full comparison, independent review and CI; its actual FAIL remains recorded and baseline promotion is deferred. Negative movement is outside this exception. Baseline promotion requires a recorded PASS and an exact-head merge with green CI.
Every gap was closed by pinning the rule TradingView actually follows β never by loosening the grader. Each rule was isolated with sensor strategies exported from TradingView (capital sweeps, literal replays, per-bar state encoded into order comments) and landed with a replay test on the recorded bars. Among them: the broker carries money at ten significant digits (equity rounding, the whole-order drop band, the one-contract margin call, the raw lot floor on every lot-stepped symbol); a trailing stop restarts from the issuing bar's close when trail_points changes and never folds that bar's extreme; a zero-offset trail rides the raw running best and its arming open fills at the nearest-tick print; a reversal rejected at placement preserves standing exits and a separately queued strategy.close, while the distinct fill-time rejection rules govern stop, limit, and trailing legs; sparse ta.atr/ta.tr read the chart's previous close on every execution; pivot levels snap to the tick grid; early-close sessions complete their higher-timeframe bucket; and account-currency conversion is left out of the comparison entirely, because TradingView's FX series is a moving target no fixed table reproduces.
git submodule update --init corpus
docker pull ghcr.io/pineforge-4pass/pineforge-release:latest # optional: re-derive every generated.cpp
VERIFY=1 scripts/regen_corpus_cpp.sh # proves the shipped C++ is byte-identical
JOBS=8 scripts/run_corpus.sh # build 312 .so, run, grade vs TradingView
python3 scripts/regen_validation_report.py # optional: the corpus reportThe corpus feed is a 1-minute Binance ETH/USDT:USDT tape with the 15-minute bars derived from it (corpus/data/derived/). Every probe folder ships strategy.pine, generated.cpp, tv_trades.csv and engine_trades.csv. The probe once filed as a TradingView anomaly (anomaly-equity-mirror-strategy-equity-01) turned out to be TradingView's ten-significant-digit margin call; the rule is pinned and the probe matches trade-for-trade.
benchmarks/ runs 100 strategies (50 public + 50 promoted corpus probes, ~167,000 TV trades) through PineForge, PyneCore and PineTS on the same 53,930-bar Binance ETH/USDT 15m feed. PyneCore sources are official PyneSys cloud-compiler output (no hand-ports); PineTS runs indicators only (its strategy backtester is upstream roadmap). Fixtures live in the public benchmarks/assets submodule; bash benchmarks/run_all.sh reproduces everything with no API keys.
| PineForge | PyneCore | TV ground truth | |
|---|---|---|---|
| Strategies | 100 | 100 | 100 |
| Trades emitted | 167,381 | 253,031 | 167,301 |
| π’ excellent | 100 / 100 | 85 / 100 | β |
| π’ strong | 0 / 100 | 2 / 100 | β |
| π‘ moderate | 0 / 100 | 10 / 100 | β |
| π weak | 0 / 100 | 3 / 100 | β |
PyneCore's 15 non-excellent strategies involve strategy.exit(stop=β¦, limit=β¦) brackets, trail_* exits, strategy.close(qty_percent=β¦) partial exits and bar-magnifier paths β the categories where its broker emulator differs from TradingView. Last refresh 2026-06-11 (engine v0.9.0, PyneCore 6.4.6, PineTS 0.9.16); a refresh on the current engine and PyneCore, extended to the full corpus, is the next benchmark milestone. Per-strategy table: benchmarks/results/summary.md; speed: benchmarks/results/speed.md; throughput reproduction package: benchmarks/throughput/.
Pine v6 script
β pineforge-codegen (separate repo): Pine β C++ translation only
βΌ
GeneratedStrategy ββ indicator math + strategy.entry / exit / close calls
β attach_pine_execution_adapter()
βΌ
Source-adapter parity runtime src/source/, src/compat/pine/
PineStrategyHost, PineExecutionAdapter: Pine order lifecycle, bracket legs,
fill-price and slippage rules, POOC / calc_on_order_fills, margin revival,
trail and stop semantics
β generic orders, handles, callbacks
βΌ
Generic kernel src/engine_*, src/native_*, src/ta_*, magnifier, session_time, β¦
matching and fills, sizing, margin and settlement, bar magnifier,
indicators, request.security(), time and session math; Pine-agnostic
- codegen owns Pine β C++ translation: the
GeneratedStrategywith its indicator math andstrategy.*calls. It does not own execution, fill, bracket or margin semantics. - The source adapter owns TradingView parity: how Pine orders live, fill, bracket, revive and trail, expressed as ordinary kernel orders.
- The kernel stays Pine-agnostic. It changes only for a generic capability that carries a recorded ruling β for example per-lot excursion accounting exposed as a kernel capability, or a market-if-touched (fill-through) flag on a limit order. No Pine- or TradingView-specific rule belongs in the kernel; such a rule goes to the source adapter or to codegen.
Bare native engines (NativeStrategyHost) run the kernel without the Pine adapter. Pine frontends must attach it explicitly and follow the execution attachment and regeneration contract; cap-only generated constructors do not opt into the full adapter.
libpineforge.aβ the static runtime, in two layers:- generic kernel β order matching and fills, sizing, margin and settlement, the bar magnifier, 66 indicator classes,
request.security(), time and session math; - source-adapter parity runtime β
PineStrategyHostandPineExecutionAdapter(src/source/) plus the Pine policy helpers insrc/compat/pine/, which map Pine/TradingView execution semantics onto the kernel.
- generic kernel β order matching and fills, sizing, margin and settlement, the bar magnifier, 66 indicator classes,
<pineforge/pineforge.h>β the public C ABI, the stability-pinned consumer surface.<pineforge/*.hpp>,<pineforge/source/*.hpp>β internal C++ headers the transpiler emits against (generated code derives frompineforge::source::PineStrategyHost); not part of the stability guarantee.- C++ unit and recorded TradingView replay tests; CI on Linux + macOS Γ Release + Debug, sanitizers, and a
find_packagesmoke consumer. corpus/β the 312-strategy public validation corpus (submodule).benchmarks/β the three-way comparison harness and the throughput package.scripts/βrun_corpus.sh,verify_corpus.py,run_strategy.py(load any.sovia ctypes),regen_corpus_cpp.sh,coverage.sh.
This is the runtime, not the compiler. The PineScript β C++ transpiler is pineforge-codegen (pip install pineforge-codegen), bundled with the runtime in the pineforge-release image that the MCP server builds on. It is a backtest engine, not a chart: plot, label, bgcolor compile and do nothing. It is not a TradingView clone: where TradingView's behaviour is undocumented or platform-specific (the bar magnifier's intrabar path, float ordering) PineForge chooses deterministic rules and documents them; where it converges, it converges exactly.
Full coverage map β every TA class, every order primitive, every request.security() semantic, and what is deliberately not implemented: docs/coverage.md.
TradingView ties some day-boundary logic (intraday order caps, session rollovers) to syminfo.timezone and other calculations to the chart timezone. The validator derives the chart timezone from the input CSV; to force one, set "engine_chart_timezone": "<IANA name>" (or "" for UTC) in the probe's inputs.json.
<pineforge/pineforge.h> is the single canonical consumer header. It declares
exactly 65 public PF_API functions: 57 runtime implementations and eight
per-strategy generated exports. Every compiled strategy .so exports that
public set and no internal C++ symbol (-fvisibility=hidden, PF_API on the
public set, checked in CI by scripts/check_c_abi_runtime.py):
| Symbol | Role |
|---|---|
strategy_create / strategy_free |
Allocate / release a strategy instance |
run_backtest / run_backtest_full |
Run with auto-detected timeframe / with timeframe + magnifier configuration |
report_free |
Free arrays inside a filled pf_report_t |
strategy_closed_trade_entry_incarnation |
Per-run physical entry provenance of a closed trade |
strategy_set_input / strategy_set_override |
Override a Pine input.*() value / a strategy(...) declaration parameter |
strategy_set_magnifier_volume_weighted |
Toggle the volume-weighted magnifier |
strategy_set_trace_enabled |
Toggle per-bar trace recording |
strategy_set_trade_start_time |
Suppress historical order placement before a time |
strategy_stream_begin / _push_tick / _push_ticks / _advance_time / _end / _fill_report |
Warm on OHLCV, then run realtime on ordered trades |
strategy_stream_api_version / _push_bar / _order_actions_len / _order_action_get / _order_actions_clear / _state_hash |
Native live extension v1: confirmed input bars, physical fill events and observable replay state |
strategy_set_chart_timezone / strategy_set_syminfo_timezone / strategy_set_syminfo_session |
Chart and exchange time |
strategy_set_syminfo_mintick / _pointvalue / _metadata / _type / _string |
Symbol tick size, point value, numeric metadata, instrument class, string members |
strategy_set_native_security_feed / strategy_set_aux_security_feed |
Feed request.security() from a native higher-timeframe series / an auxiliary bar-aligned feed |
strategy_set_account_currency_fx_series |
Effective-time quote-to-account FX |
strategy_get_last_error |
The latest runtime error |
pf_version_get / pf_version_string / pf_abi_version |
Runtime version, version string, struct-layout version (PF_ABI_VERSION == 4) |
strategy_execution_contract / strategy_configure_native_v1 / strategy_configure_native_fx_curve_v1 |
Query Legacy vs NativeMarketV1; apply the versioned native run specification; stage or clear an immutable native FX curve |
strategy_request_abort / strategy_last_run_status |
Cooperative abort of a run in progress; 0=completed, 1=aborted |
strategy_set_realtime_tail |
Live-runtime surface (ABI v4): the array's last bar is a still-forming tail β barstate.islast=false, last_bar_index/last_bar_time frozen at the horizon bar, no range-end row |
strategy_set_probe_suppress_tail_logic |
ABI v4: the last bar runs only the broker's pre-on_bar steps (pending-order settlement, intraday-cap/loss checks) and returns β no on_bar, no margin-call / POOC second pass / bracket-reissue processing (the range-end row is strategy_set_realtime_tail's to skip; the flags are independent) |
strategy_set_path_order / strategy_last_bar_dual_entry_path |
ABI v4: force the intrabar OβH/LβC leg order (AUTO/HIGH_FIRST/LOW_FIRST) for path-dependent fill probing; read which side won a same-bar dual-entry-stop arbitration |
strategy_set_broker_state_hash_recording / strategy_broker_state_hash |
ABI v4: toggle a 64-bit broker-state hash appended per script bar to pf_report_t::broker_state_hash; read the final state's hash |
strategy_pending_orders_len / strategy_pending_order_get / strategy_pending_order_layout |
ABI v4: the resting pending-order book after the most recent run β count, a POD snapshot per order (pf_pending_order_v1_t), and the snapshot's self-describing field layout |
strategy_pending_order_fill_qty / _level_resolved / _effective_levels / strategy_trail_best_price |
ABI v4: engine-computed values for a resting order β the quantity it would open if filled at a given price, whether its relative offsets resolve yet, its resolved stop/limit/trail-activation levels, and the live position's trail extreme |
strategy_position_avg_price / strategy_position_cycle_seq / strategy_position_size |
ABI v4: the live position's volume-weighted average entry price, its cycle id, and its script-facing signed size |
strategy_closed_trade_entry_id / _exit_id / _exit_comment / _close_cause |
ABI v4: per-closed-trade id/comment strings and a close_cause enum (SCRIPT/BRACKET/MARGIN_CALL/INTRADAY_LOSS_CAP/INTRADAY_FILL_CAP/RANGE_END), indexed like strategy_closed_trade_entry_incarnation |
strategy_current_equity / strategy_script_bars_processed |
ABI v4: initial_capital + netprofit (not Pine's strategy.equity, which also adds open profit); total script bars dispatched by the most recent run |
POD types pf_bar_t, pf_trade_tick_t, pf_trade_t, pf_report_t, pf_security_diag_t, pf_trace_entry_t, pf_version_t, pf_trade_stats_t, pf_equity_stats_t, pf_metrics_t, pf_equity_point_t, pf_pending_order_v1_t, pf_field_desc_t and the pf_magnifier_distribution_t enum complete the surface. ABI v2 added computed trading metrics and a per-bar equity curve; ABI v3 added pf_trade_t::open_at_end, TradingView's range-end close of a position still open after the last bar; ABI v4 added the live-runtime accessors above plus pf_report_t::broker_state_hash / broker_state_hash_len (a per-script-bar broker-state hash array, appended after equity_curve_len, NULL/0-length unless strategy_set_broker_state_hash_recording is on) and the pf_pending_order_v1_t generated POD mirror of the engine's resting-order record. Check pf_abi_version() before running: the report struct is caller-allocated.
Full flag semantics, string lifetimes and the three L0 evidence lanes behind the ABI v4 live surface: docs/pages/live-surface.md.
Stability guarantee. Within a major version, struct layouts and extern "C" signatures are append-only β fields and functions are added, never reordered, removed or retyped; static_asserts in src/c_abi.cpp pin the layouts. Semantic versioning at the ABI level: PATCH never touches the ABI, MINOR appends, MAJOR breaks. A .so built against 0.X.Y keeps working on any later 0.X.Z.
include/pineforge/ public C ABI (pineforge.h) + internal C++ headers
βββ source/ Pine source-adapter headers (pine_adapter.hpp, pine_strategy_host.hpp, β¦)
βββ compat/pine/ Pine policy helper headers
src/ 48 .cpp files in two layers
β generic kernel (Pine-agnostic)
βββ c_abi.cpp C ABI implementations + layout asserts
βββ engine_*.cpp BacktestEngine: run loop, orders, execution, path resolution,
β lower-TF emulation, security + aux security, stream, consumer,
β metrics, report, trade accessors, state hash
βββ native_*.cpp native orders, run spec, calendar, FX curve, execution consumer
βββ market_admission / market_driver / pending_order_mirror / reservation_expansion
βββ ta_*.cpp 66 indicator classes (moving averages, oscillators,
β volatility/trend, extremes/volume, misc)
βββ magnifier / matrix / session_time / timeframe / timezone / math / str_utils
β source-adapter parity runtime (Pine / TradingView semantics)
βββ source/
β βββ pine_strategy_host.cpp PineStrategyHost: the base every GeneratedStrategy derives from
β βββ pine_adapter.cpp PineExecutionAdapter: Pine order lifecycle, brackets, fills, margin
β βββ pine_strategy_commands.cpp strategy.entry / order / exit / close / cancel lowering
β βββ pine_scheduler.cpp, pine_scheduler_native.cpp
β βββ pine_aux_security.cpp, pine_state_hash.cpp
βββ compat/pine/ exit_activation, exit_lifecycle, market_admission,
order_birth, order_priority, reservation_expansion
tests/ C++ unit, TradingView replay and pure-C ABI tests
corpus/ public submodule: 312 strategies + the 1-minute feed and derived 15m bars
benchmarks/ three-way comparison harness, throughput package, results/
scripts/ run_corpus.sh, verify_corpus.py, run_strategy.py, regen_corpus_cpp.sh, coverage.sh
tutorial/ MACD end-to-end + streaming walkthrough
docs/ coverage map, Pine v6 audit, Doxygen site (cdocs.pineforge.dev)
cmake/ PineForgeConfig.cmake.in + the find_package smoke consumer
Documentation: C ABI reference Β· Getting started Β· MACD tutorial Β· Streaming Β· Metrics reference Β· FFI from Python Β· Rust Β· CMake integration Β· ABI stability Β· Coverage. The site rebuilds on every push to main.
- Unreleased (branch
live/abi-v4) β ABI v4 live surface forpineforge-live: 24 new default-off exports (cooperative abort, realtime tail, probe-suppress tail logic, forced path order, a per-bar broker-state hash, the pending-order book as a generated POD mirror, closed-trade id/comment/close-cause, position and equity accessors). No flag changes a historical run:scripts/live_flags_off_identity.py(312 corpus probes, 0 differ vs the pre-v4 branch point),scripts/live_flags_lane.py(312 probes, 0 positives, 130 open-at-end trades subtracted), andscripts/bar_identity_lane.py(row 1: 222,295 bars compared, 2 explained open divergences, 0 else) all pass. 56 symbols. - v0.13.0 (2026-09-05) β the parity campaign, rounds 1β11: TradingView's broker rules pinned with sensor exports and landed with replay tests β ten-significant-digit money, trailing-stop restarts, zero-offset trails, declined-reversal bracket legs, the surviving
strategy.close, sparseta.atr/ta.tr, pivot tick snap, same-bar entry/close transactions, early-close higher-timeframe buckets, 64-bit epoch arrays. Closed test 3,880/3,881; corpus 309/309. ABI v3, 32 symbols, 198 tests. - v0.7 β v0.12 (JuneβAugust 2026) β native and auxiliary
request.security()feeds, ABI v2 metrics + equity curve, streaming mode, range-end accounting. See GitHub releases. - v0.6.0 β performance sprint: cached static inputs, thread-local timestamp caching, lazy timezone caching; up to 6.7M bars/s.
- v0.5.0 β Pine v6 compatibility sprint (symbol mappings, constant namespaces, timestamp overloads, collection sorting, bare TA property reads); corpus 234 probes.
- v0.4.1 β clean-room 228-probe corpus, submodule made public, five engine fixes.
- v0.1 β v0.3 β initial release with the pinned C ABI; same-id stop/replace resolution, RMA seed,
-ffp-contract=off; magnifier gap fills and directional mintick rounding.
Read CONTRIBUTING.md (includes the Apache-2.0 contribution grant). The short version: every change keeps the parity corpus green; anything exported from <pineforge/pineforge.h> needs a major-version bump; internal C++ can change freely. Bug reports with a Pine script, an OHLCV slice and TradingView's trade list are the most valuable thing you can send β that is exactly how every rule above was found.
Apache License 2.0 β LICENSE. Third-party notices: NOTICE. Licensing notes (optional AGPL benchmark deps, trademarks): LEGAL.md. Code of conduct Β· Security policy.

{ "mcpServers": { "pineforge-backtest": { "command": "docker", "args": ["run", "--rm", "-i", "-v", "${workspaceFolder}:/work", "ghcr.io/pineforge-4pass/pineforge-backtest-mcp:latest"] } } }