pineforge-engine
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.
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.
PineForge
The open-source PineScript v6 backtest engine that reproduces TradingView trade-for-trade.
🌐 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
.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, 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.
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 |
|---|---|---|---|
| Public — open 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_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.
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, 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.
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)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi
