pineforge-engine

mcp
Guvenlik Denetimi
Uyari
Health Gecti
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Community trust — 181 GitHub stars
Code Uyari
  • process.env — Environment variable access in .github/workflows/promote-baseline.yml
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Open-source PineScript v6 backtest engine that reproduces TradingView trade-for-trade: 4,189/4,190 probes excellent-or-strong (312 open corpus + 413 community scripts on 15 markets), 2.8M trades matched. C++17, stable C ABI, Apache-2.0.

README.md
PineForge — TradingView-exact PineScript backtests, open source, on your own data

PineForge

The open-source PineScript v6 backtest engine that reproduces TradingView trade-for-trade.

CI
Parity
Trades
Speed

License
Language
Docs
codegen on PyPI
MCP server

🌐 pineforge.dev · ☁️ Hosted MCP · 🐳 Docker MCP · 📦 Transpiler · 📖 C ABI docs · 🧪 Coverage map · 🔬 Benchmarks


Why PineForge

TradingView's strategy tester is the reference every Pine author trusts, and nothing outside TradingView reproduced it — until now. PineForge is a C++17 runtime with a stable C ABI that runs PineScript v6 strategies exactly the way TradingView's broker emulator does: same fills, same sizing, same margin calls, same trailing stops, same request.security() buckets, on any OHLCV you give it, in microseconds per bar.

  • Proven, not promised. 4,189 of 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. 2.82 million TradingView trades measured, 2.815 million matched row-for-row.
  • Open. Engine, transpiler, corpus, benchmarks and the validation tooling are all public and Apache-2.0. The only thing you cannot download is the closed test set, because TradingView's Terms of Service forbid redistributing community scripts.
  • Fast. In-process, no interpreter: median 162× faster than PyneCore on 99 timed strategies. Parameter sweeps re-run a loaded .so with 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, 32 extern "C" functions, append-only ABI. Call it from C, Python, Rust, Go, Node, Julia — or let an AI agent drive it over MCP.

Get a backtest in 60 seconds

With an AI agent (MCP, Docker only)

claude mcp add pineforge-backtest \
  -- docker run --rm -i -v "$PWD:/work" ghcr.io/pineforge-4pass/pineforge-backtest-mcp:latest

For Claude Desktop, Cursor or any MCP client:

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

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.

Real backtest on Claude in 60 seconds

From source

git clone https://github.com/pineforge-4pass/pineforge-engine.git && cd pineforge-engine
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
ctest --test-dir build --output-on-failure     # 198 tests
bash tutorial/run.sh                            # MACD on BTC/USDT, end to end
python3 tutorial/run_stream.py                  # OHLCV warm-up → realtime trades

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.

Embedded in your own harness

#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.


Validation scoreboard

Board Test set Result Trades verified
Publicopen corpus 312 reference strategies, Apache-2.0, reproducible by anyone 309/309 graded excellent trade-for-trade (ETH/USDT-perp 15m; the corpus' declared engine-only / anomaly probes are not graded) ~430k
Closed test — the parity campaign 413 community-shared TradingView scripts × 15 market/timeframe lanes = 3,881 script-lane probes — private under TradingView's Terms of Service 3,825 excellent + 55 strong + 1 moderate = 3,880/3,881 (99.97%) excellent-or-strong ~2.4M

2.82 million TradingView trades measured, 2.815 million matched row-for-row (99.8%), as of 2026-09-06. 18 TradingView-side anomalies were found on the way (all on the ETH 15m lane), each confirmed with a purpose-built sensor script exported from TradingView and documented before exclusion. The one probe below strong is a verifier-harness limitation on a range-start chart trim, not an engine divergence.

The closed test, lane by lane

Market · timeframe Probes Excellent Strong Moderate
BINANCE:ETHUSDT.P · 15m (hard lane: zero regression allowed) 395 393 2
BINANCE:BTCUSDT · 15m 354 341 13
BINANCE:BTCUSDT · 1D 259 258 1
CME_MINI:ES1! · 15m 174 173 1
CME_MINI:ES1! · 1D 117 116 1
CME_MINI:NQ1! · 15m 174 174
CME_MINI:NQ1! · 1D 116 116
NASDAQ:AAPL · 15m 356 352 4
NSE:NIFTY · 15m 191 190 1
NSE:NIFTY · 1D 145 145
NYSE:F · 15m 340 331 9
NYSE:F · 1D 263 262 1
OANDA:EURUSD · 15m 373 356 17
OANDA:XAUUSD · 15m 376 370 5 1
OANDA:XAUUSD · 1D 248 248
Total 3,881 3,825 55 1

How a probe is graded

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.

A grade is never one lucky run. Every candidate build is measured over the whole population on a reproducible cloud pipeline, each graded snapshot is published by content hash, and a build ships only through a deterministic gate: no regression on any metric of any ETH 15m probe, and, pooled over the other lanes, strictly more probes entering the excellent and excellent+strong bands than leaving them. Merges are fast-forwarded, so the commit that was gated is the commit on main.

What the closed test taught the engine

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 declined all-in reversal kills a bracket's stop and limit legs but never its trail leg, and a strategy.close queued beside a dropped reversal still fills; 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.

Reproduce the public board yourself

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 report

The 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.


Cross-engine comparison

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/.


What ships here

  • libpineforge.a — the static runtime: order matching and fills, sizing and margin, the bar magnifier, 66 indicator classes, request.security(), time and session math.
  • <pineforge/pineforge.h> — the public C ABI, the stability-pinned consumer surface.
  • <pineforge/*.hpp> — internal C++ headers the transpiler emits against (not part of the stability guarantee).
  • 198 ctest cases, most of them replays of recorded TradingView bars; CI on Linux + macOS × Release + Debug, sanitizers, and a find_package smoke 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 .so via 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.

Timezones and day boundaries

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.


Public C ABI

<pineforge/pineforge.h> is the single canonical consumer header. Every compiled strategy .so exports exactly these 32 symbols 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_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 == 3)

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 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. Check pf_abi_version() before running: the report struct is caller-allocated.

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.


Repository layout

include/pineforge/      public C ABI + internal C++ headers
src/                    26 .cpp files split by concern
  ├── c_abi.cpp                       C ABI implementations + layout asserts
  ├── engine_*.cpp                    BacktestEngine: path resolution, lower-TF emulation, orders,
  │                                   fills, security, run loop, report, strategy commands, risk
  ├── ta_*.cpp                        66 indicator classes (moving averages, oscillators,
  │                                   volatility/trend, extremes/volume, misc)
  └── magnifier / matrix / session_time / timeframe / timezone / math / str_utils
tests/                  198 ctest cases (C++ unit + TradingView replay tests, 1 pure-C ABI check)
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.


Releases

  • 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, sparse ta.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.

Contributing

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.

License

Apache License 2.0 — LICENSE. Third-party notices: NOTICE. Licensing notes (optional AGPL benchmark deps, trademarks): LEGAL.md. Code of conduct · Security policy.

Yorumlar (0)

Sonuc bulunamadi