{"id":50657377,"url":"https://github.com/pineforge-4pass/pineforge-engine","last_synced_at":"2026-06-08T00:11:25.379Z","repository":{"id":356161651,"uuid":"1229472500","full_name":"pineforge-4pass/pineforge-engine","owner":"pineforge-4pass","description":"Deterministic PineScript v6 backtest runtime. Validated trade-for-trade against TradingView.","archived":false,"fork":false,"pushed_at":"2026-05-31T19:46:28.000Z","size":1654,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T20:24:03.685Z","etag":null,"topics":["algorithmic-trading","algotrading","backtest","backtesting","c-api","cpp","cpp17","crypto","deterministic","ffi","finance","ohlcv","pine-script","pinescript","python-bindings","quantitative-finance","static-library","technical-analysis","trading-strategies","tradingview"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pineforge-4pass.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-05T04:38:45.000Z","updated_at":"2026-05-31T19:46:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pineforge-4pass/pineforge-engine","commit_stats":null,"previous_names":["fullpass-4pass/pineforge-engine","pineforge-4pass/pineforge-engine"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/pineforge-4pass/pineforge-engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pineforge-4pass%2Fpineforge-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pineforge-4pass%2Fpineforge-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pineforge-4pass%2Fpineforge-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pineforge-4pass%2Fpineforge-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pineforge-4pass","download_url":"https://codeload.github.com/pineforge-4pass/pineforge-engine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pineforge-4pass%2Fpineforge-engine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34042763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-07T02:00:07.652Z","response_time":124,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithmic-trading","algotrading","backtest","backtesting","c-api","cpp","cpp17","crypto","deterministic","ffi","finance","ohlcv","pine-script","pinescript","python-bindings","quantitative-finance","static-library","technical-analysis","trading-strategies","tradingview"],"created_at":"2026-06-08T00:11:24.868Z","updated_at":"2026-06-08T00:11:25.370Z","avatar_url":"https://github.com/pineforge-4pass.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\".github/assets/pineforge-banner.jpg\" alt=\"PineScript backtests, deterministic, on your data — v0.8.0 · 93.06% line coverage · 245/246 strict TV parity · 0 engine bugs\" width=\"900\"\u003e\n\n# PineForge\n[![CI](https://img.shields.io/github/actions/workflow/status/pineforge-4pass/pineforge-engine/ci.yml?branch=main\u0026label=ci\u0026logo=github)](https://github.com/pineforge-4pass/pineforge-engine/actions)\n[![Docs](https://img.shields.io/badge/docs-cdocs.pineforge.dev-1565c0?logo=readthedocs\u0026logoColor=white)](https://cdocs.pineforge.dev)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)\n[![Language](https://img.shields.io/badge/C%2B%2B-17-00599C.svg?logo=cplusplus\u0026logoColor=white)](#)\u003cbr\u003e\n[![Parity](https://img.shields.io/badge/TV%20parity-245%2F246-brightgreen)](#cross-engine-comparison)\n[![Speed](https://img.shields.io/badge/median%20104%C3%97%20vs%20PyneCore%20%2899%20strategies%29-success)](benchmarks/results/speed.md)\u003cbr\u003e\n[![codegen on PyPI](https://img.shields.io/pypi/v/pineforge-codegen?label=codegen\u0026logo=pypi\u0026logoColor=white)](https://pypi.org/project/pineforge-codegen/)\n[![MCP server](https://img.shields.io/badge/MCP-server-1565c0?logo=docker\u0026logoColor=white)](https://github.com/pineforge-4pass/pineforge-codegen-mcp)\n\n**[🌐 pineforge.dev](https://www.pineforge.dev) · [🐳 Run locally (Docker MCP)](https://github.com/pineforge-4pass/pineforge-codegen-mcp) · [📦 Transpiler (pip)](https://github.com/pineforge-4pass/pineforge-codegen-oss)**\u003cbr\u003e\n**[📖 API Documentation](https://cdocs.pineforge.dev) · [⚡ 60-second Tutorial](tutorial/) · [🧪 Coverage Map](docs/coverage.md) · [🔬 Benchmarks](benchmarks/)**\n\n\u003c/div\u003e\n\n---\n\n## Backtest PineScript with AI — no build step\n\n\u003cdiv align=\"center\"\u003e\n\n![PineForge MCP demo — an AI agent transpiling, backtesting, and sweeping a PineScript strategy in the terminal](.github/assets/demo.gif)\n\n\u003c/div\u003e\n\nThe fastest way to use PineForge: let your AI agent write, run, and optimize\nstrategies for you via the **[`pineforge-codegen-mcp`](https://github.com/pineforge-4pass/pineforge-codegen-mcp)**\ncontainer — a single self-contained image with the transpiler **and** the engine\nbundled in-process. Pull it, mount a working dir, done. **No host build step, no\ndocker-in-docker, no API key — nothing leaves the box.**\n\nA language model can't accurately backtest a PineScript v6 strategy by reasoning\nabout it — Pine's series semantics, intrabar fills, look-ahead rules, and\n`strategy.*` order logic don't reproduce from approximation, so a hand-simulated\ntrade list or P\u0026L is unreliable and won't match TradingView. This engine runs the\nreal deterministic computation instead: **245/246 reference strategies at strict\nTradingView parity, 0 engine bugs** ([methodology \u0026 validation](https://pineforge.dev/en/methodology/),\nas of 2026-06-03). That is why an agent asked to \"backtest this Pine / check if\nit's profitable / reproduce my TradingView results\" should call the MCP tools\nrather than approximate the run.\n\n**The workflow (fully local — source never leaves your machine):**\n1. Agent writes (or you paste) PineScript v6 source\n2. The container transpiles Pine → C++ in-process with the bundled\n   [`pineforge-codegen`](https://github.com/pineforge-4pass/pineforge-codegen-oss) transpiler\n3. Engine compiles + runs inside the same container — microsecond-class, bit-reproducible results\n4. Agent reads the trade list, suggests improvements, sweeps parameters\n\n**Prerequisites:** Docker only (plus outbound network for the Binance fetch\ntools). The MCP server *is* the container — there's no separate Node process and\nno host Docker daemon called from inside it.\n\nMount a directory at `/work` and point the OHLCV paths there. `-i` is required;\nnever add `-t` (a TTY corrupts the stdio JSON-RPC stream).\n\n### Claude Code (one command)\n\n```bash\nclaude mcp add pineforge-codegen \\\n  -- docker run --rm -i -v \"$PWD:/work\" ghcr.io/pineforge-4pass/pineforge-codegen-mcp:latest\n```\n\n### Claude Desktop / Cursor / any MCP client\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"pineforge-codegen\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"--rm\", \"-i\",\n        \"-v\", \"${workspaceFolder}:/work\",\n        \"ghcr.io/pineforge-4pass/pineforge-codegen-mcp:latest\"\n      ]\n    }\n  }\n}\n```\n\nOnce connected, your AI agent can:\n\n| What to ask | Tool used |\n|---|---|\n| \"Fetch BTC/USDT 15m data for the last 30 days\" | `fetch_binance_ohlcv` |\n| \"List BTC USDT-perp symbols\" | `binance_symbols` |\n| \"Backtest this SMA-cross strategy on that data\" | `backtest_pine` |\n| \"Sweep fast length 8–21, slow 21–55, rank by net PnL\" | `backtest_pine_grid` |\n| \"What broker overrides are available?\" | `list_engine_params` |\n\nSee the [server README](https://github.com/pineforge-4pass/pineforge-codegen-mcp)\nfor the full tool catalog, request schemas, and env vars (`PINEFORGE_ALLOW_ANYWHERE`,\n`PINEFORGE_IMAGE`, …).\n\n\u003e **Transpiler is open.** The Pine → C++ transpiler is source-available\n\u003e (`pip install pineforge-codegen`, [repo](https://github.com/pineforge-4pass/pineforge-codegen-oss)) and ships inside the container — so the whole transpile→backtest loop runs on your machine.\n\n\u003e **The npm package** [`@pineforge/codegen-mcp`](https://www.npmjs.com/package/@pineforge/codegen-mcp)\n\u003e mirrors the same server for discoverability; the container above is the\n\u003e recommended way to run it (engine bundled in-process, one image, no host setup).\n\n---\n\n## Why PineForge?\n\n- 🎯 **TradingView-exact.** 245 of 246 reference strategies match TV trade-for-trade. The lone outlier is a stress probe at the 1× margin boundary where TV's broker emulator is non-deterministic — engine is correct. **100 of 100** PineForge excellent vs PyneCore + PineTS on the public three-way benchmark (~167,000 TV trades; PyneCore: 85 of 100; PineTS indicator-only).\n- ⚡ **Microsecond-class.** Median **104× faster than PyneCore** across 99 commonly-timed strategies (full 41,307-bar OHLCV via dlopen+run; see [benchmarks/results/speed.md](benchmarks/results/speed.md)). Parameter sweeps load one `.so` and re-run with new inputs — no recompile, no fork, no IPC.\n- 🔒 **Stable C ABI.** 10 functions, 6 POD types, one header (`\u003cpineforge/pineforge.h\u003e`). Append-only across minor versions, `static_assert`-pinned struct layouts, hidden-visibility hygiene. Drop a strategy `.so` in any harness; it just runs.\n- 🧪 **Reproducible to the bit.** Deterministic float ordering, deterministic bar magnifier, no internal RNG seeded from time. Two runs with the same inputs produce bit-identical trade lists.\n- 🧰 **FFI-friendly.** Call from Python (`ctypes`), Rust (`libloading`), Go (`cgo`), Node, Julia. Worked examples for [pure C](https://cdocs.pineforge.dev/examples_c.html), [Python sweep](https://cdocs.pineforge.dev/examples_python_sweep.html), [Rust](https://cdocs.pineforge.dev/examples_rust.html), [multi-strategy harness](https://cdocs.pineforge.dev/examples_multi.html), and [magnifier A/B](https://cdocs.pineforge.dev/examples_magnifier.html) ship in the docs.\n- 🌍 **Cross-platform CI.** Linux + macOS × Release + Debug. Universal mac binary. Static library, no runtime DSO surprises at deploy time.\n\n---\n\n## For developers: embed the runtime directly\n\nPineForge ships as a static C library (`libpineforge.a`) with a stable 10-symbol C ABI. Call from C, Python, Rust, Go, Node, Julia — one harness, swap strategies forever.\n\n### See it in 30 seconds\n\n```c\n#include \u003cpineforge/pineforge.h\u003e\n\nint main(void) {\n    pf_strategy_t s = strategy_create(NULL);\n    pf_bar_t bars[] = { /* OHLCV ... */ };\n    pf_report_t r = {0};\n\n    run_backtest(s, bars, sizeof(bars)/sizeof(*bars), \u0026r);\n\n    printf(\"%d trades, net %.2f\\n\", r.trades_len, r.net_profit);\n\n    report_free(\u0026r);\n    strategy_free(s);\n    return 0;\n}\n```\n\nThat's the entire integration. Every PineForge-compiled strategy `.so` exports the same 10 symbols — write your harness once, swap strategies forever.\n\n```bash\ncmake -B build -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j\nctest --test-dir build --output-on-failure   # 39 tests, ~1 s\nbash tutorial/run.sh                          # MACD backtest end-to-end\n```\n\n## Documentation\n\n| Resource | What it covers |\n| --- | --- |\n| 📖 **[cdocs.pineforge.dev](https://cdocs.pineforge.dev)** | Full C ABI reference, lifecycle, report schema, configuration knobs, magnifier, FFI bindings, ABI stability contract |\n| 🚀 **[Getting Started](https://cdocs.pineforge.dev/getting_started.html)** | 60-second build + install + smoke test |\n| 🧪 **[Tutorial: MACD on BTC/USDT](https://cdocs.pineforge.dev/tutorial_macd.html)** | End-to-end annotated walkthrough |\n| 🔌 **[FFI from Python](https://cdocs.pineforge.dev/ffi_python.html)** | Complete `ctypes` mirror — paste-ready |\n| 🦀 **[Calling from Rust](https://cdocs.pineforge.dev/examples_rust.html)** | Idiomatic `libloading` wrapper |\n| 🧰 **[CMake integration](https://cdocs.pineforge.dev/integration_cmake.html)** | `find_package(PineForge)` recipe |\n| 🔒 **[ABI stability](https://cdocs.pineforge.dev/abi_stability.html)** | Versioning contract + symbol inventory |\n| 🗺️ **[Pine v6 coverage map](https://cdocs.pineforge.dev/coverage.html)** | What's implemented, what's not, and why |\n\nThe site auto-rebuilds on every push to `main` and every release tag.\n\n---\n\n## What is PineForge?\n\nPineForge is the **C++ runtime** that PineForge-compiled strategies link against. It implements PineScript v6 strategy semantics — order matching, fills, the magnifier, technical indicators, time/session math — as a static C++ library with a stable C ABI.\n\nThe runtime is parity-tested **trade-for-trade against TradingView's \"List of Trades\" CSV exports** on a reference corpus: **245 excellent + 1 documented anomaly = 246 strategies** under the canonical verifier. The corpus ships as a **public Apache-2.0 submodule**.\n\nThis repository ships:\n\n- `libpineforge.a` — the static runtime library\n- `\u003cpineforge/pineforge.h\u003e` — the public C ABI (the canonical, stability-pinned consumer surface)\n- `\u003cpineforge/*.hpp\u003e` — the internal C++ headers (the PineForge transpiler emits against these; not part of the stability guarantee)\n- A 39-binary ctest suite (38 C++ + 1 pure-C ABI sanity test) that runs in CI on every commit (~81% line coverage of `src/` measured via `bash scripts/coverage.sh`)\n- `**corpus/`** (**public git submodule**) — **246 reference strategies** under a single `corpus/validation/` tree. Each folder ships `strategy.pine`, `generated.cpp`, `tv_trades.csv`, and `engine_trades.csv`. Run `bash scripts/run_corpus.sh` after `git submodule update --init corpus`.\n- `[benchmarks/](benchmarks/)` — **three-way engine comparison** (PineForge ↔ [PyneCore](https://github.com/PyneSys/pynecore) ↔ [PineTS](https://github.com/LuxAlgo/PineTS)) on 100 strategies (50 public + 50 promoted corpus probes) and 10 canonical indicators. The harness code and reports live here; **fixtures** (pinned OHLCV, every `strategies/`* folder with TV exports and trade CSVs) ship via the optional **`benchmarks/assets` submodule** — a separate optional **public** submodule (Apache-2.0). With that init’d, `bash benchmarks/run_all.sh` reproduces the headline numbers with zero external API calls. PyneCore Python is official cloud-compiler output (no hand-ports). Headline: PineForge hits canonical *excellent* tier on **50/50** strategies (first 50) vs PyneCore’s 47/50; on the expanded **100-strategy suite (~167,000 TV trades verified)**, PineForge holds **100/100 excellent** vs PyneCore’s 85/100. Median speedup: 104× vs PyneCore across 99 commonly-timed strategies.\n\n## Coverage\n\n`**[docs/coverage.md](docs/coverage.md)`** is the complete, current map\nof which Pine v6 surface this runtime covers — every TA class, every\norder primitive, every `request.security()` semantic, plus a structured\ninventory of what's deliberately not implemented (with feasibility tags\nfor each gap). Read it before integrating PineForge as a backend or\nauditing the parity claim.\n\n## Timezones and Day Boundaries (\"The Bandage\")\n\nOn TradingView, some day-boundary operations (such as `max_intraday_filled_orders` daily cap checks or regular-session intraday state rollovers) rely on the exchange timezone (`syminfo.timezone`), while other calculations are tied to the chart timezone. Under the PineForge validator workflow, the default chart timezone is auto-derived from the input CSV file's timestamp/timezone profile.\n\nIf you encounter day-boundary alignment issues or want to force the engine to process intraday bar rollovers using a specific timezone (such as UTC or the exchange's native zone), you can apply **\"the bandage\"** (the validator-level override key):\n- Add `\"engine_chart_timezone\": \"\u003cIANA_TZ_NAME\u003e\"` (or `\"\"` for UTC/no conversion) in your test/validation schema (`inputs.json`).\n- This overrides the auto-derived chart timezone at the validator level and forces the backtest engine to align day boundaries exactly with the specified timezone.\n\n## What this is, and what it isn't\n\n**This is the runtime, not the compiler.** PineForge's PineScript-to-C++ transpiler ships separately as [`pineforge-codegen`](https://github.com/pineforge-4pass/pineforge-codegen-oss) (source-available, `pip install pineforge-codegen`) and is bundled inside the engine Docker image. This library is what every compiled strategy `.so` links against: it provides the implementations of `ta.ema`, `strategy.entry`, `request.security`, the bar magnifier, and so on, behind a stable C ABI.\n\n**This is a backtest engine, not a charting library.** PineScript drawing primitives (`plot`, `bgcolor`, `label`, …) compile cleanly but do nothing at runtime. The runtime computes trade execution and reports — it does not render.\n\n**This is not a TradingView clone.** PineForge intentionally diverges from TradingView in a handful of places where TV's behaviour is undocumented or platform-specific (the bar magnifier, deterministic float ordering). Where it converges, it converges **exactly** on the reference corpus (`245/246` excellent + 1 documented anomaly. Init the public `corpus` submodule per `[CONTRIBUTING.md](CONTRIBUTING.md)`). Where it diverges, it documents the divergence.\n\n## Quickstart\n\n### Prerequisites\n\n- CMake ≥ 3.16\n- A C++17 compiler (GCC ≥ 9, Clang ≥ 10, Apple Clang ≥ 12)\n- [Eigen 3.3+](https://eigen.tuxfamily.org/) — used for matrix-typed PineScript. The build will fetch Eigen via CMake `FetchContent` if no system install is found.\n\n### Build + test\n\n```bash\ncmake -B build -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j\nctest --test-dir build --output-on-failure\n```\n\nExpect 39 tests to pass. The largest (`test_integration`, `test_request_security`) take a few hundred milliseconds; everything else completes faster.\n\n### Install\n\n```bash\ncmake --install build --prefix /usr/local\n```\n\nInstalls:\n\n- `lib/libpineforge.a`\n- `include/pineforge/*.hpp` and `include/pineforge/pineforge.h`\n\n---\n\n## Validating Performance \u0026 Optimizations\n\nWe recently achieved over **10× speedup** on hot-loop outlier bottlenecks (such as `19-scalping-wunder-bots`) by implementing:\n1. **Global Static Inputs Caching:** We group and evaluate non-source global inputs once inside a first-bar initialization block, completely eliminating redundant string-keyed map lookups inside the strategy's C++ `on_bar()` loop.\n2. **Thread-Local Timestamp Caching:** We cache inputs and outputs of `timestamp()` and timezone-aware date conversions in `thread_local` structures, reducing costly libc calendar lookups (`timegm` / `mktime`) to simple integer comparisons.\n3. **Lazy Timezone Caching:** We optimized the C++ `ScopedTimezone` implementation to lazy-cache active timezone environments across executions, avoiding redundant environment mutations (`setenv`) and parsing overhead (`tzset`) on every bar.\n\n### Validate Throughput \u0026 Parameter Sweeps (Local Reproduction Package)\n\nTo easily reproduce and validate these throughput distribution and optimization claims locally without external API dependencies:\n\n```bash\n# 1. Navigate to the reproduction package\ncd performance\n\n# 2. Run the automated reproduction script\n./reproduce.sh\n```\n\nThis script will compile all 100 benchmark strategies, execute Google Benchmark throughput sweeps, compute the distribution quartiles, render a high-quality boxplot to `throughput_quartiles.png`, and execute an in-memory 27-combination parameter grid search on `19-scalping-wunder-bots` using high-speed ctypes FFI (verifying that the best parameter configuration is Fast MA = 11, Slow MA = 23, Risk:Reward = 2.5 with a Net Profit of 790.02).\n\n### Validate Full Engine Speed Table\n\nTo run the complete three-way engine speed sweep (PineForge vs PyneCore vs PineTS) and regenerate the benchmark speed table:\n\n```bash\n# 1. Build speed benchmarks\ncmake -B build -DPINEFORGE_BUILD_SPEED_BENCH=ON\ncmake --build build --target pineforge_bench -j\n\n# 2. Run the end-to-end timing runner and regenerate the speed report\nSKIP_PYNE=1 SKIP_PINETS=1 SKIP_PINEFORGE=1 SKIP_REPORTS=1 ./benchmarks/run_all.sh\n\n# 3. View the updated speed table\ncat benchmarks/results/speed.md\n```\n- `lib/cmake/PineForge/PineForge{Config,Targets,ConfigVersion}.cmake`\n\n### Use from another CMake project\n\n```cmake\nfind_package(PineForge 0.1 REQUIRED)\ntarget_link_libraries(my_target PRIVATE PineForge::pineforge)\n```\n\n```c\n#include \u003cpineforge/pineforge.h\u003e\n\nint main(void) {\n    pf_version_t v = pf_version_get();\n    /* ... */\n}\n```\n\n## Public C ABI (the stability surface)\n\n`\u003cpineforge/pineforge.h\u003e` is the **single canonical consumer header**. Every compiled PineForge strategy `.so` exports exactly the 10 symbols declared there:\n\n\n| Symbol                                   | Role                                         |\n| ---------------------------------------- | -------------------------------------------- |\n| `strategy_create`                        | Allocate a strategy instance                 |\n| `strategy_free`                          | Release the instance                         |\n| `run_backtest`                           | Run with auto-detected timeframe             |\n| `run_backtest_full`                      | Run with timeframe + magnifier configuration |\n| `report_free`                            | Free arrays inside a filled `pf_report_t`    |\n| `strategy_set_input`                     | Override a Pine `input.*()` value            |\n| `strategy_set_override`                  | Override a `strategy(...)` declaration param |\n| `strategy_set_magnifier_volume_weighted` | Toggle volume-weighted magnifier             |\n| `strategy_set_trace_enabled`             | Toggle per-bar trace recording               |\n| `pf_version_get`                         | Runtime version                              |\n\n\nPOD types (`pf_bar_t`, `pf_trade_t`, `pf_report_t`, `pf_security_diag_t`, `pf_trace_entry_t`, `pf_version_t`) and the `pf_magnifier_distribution_t` enum complete the surface.\n\n**Stability guarantee:** within the same `PINEFORGE_VERSION_MAJOR`, struct layouts and `extern \"C\"` signatures are append-only. New fields may be appended; existing fields are never reordered, removed, or retyped. New functions may be added; existing functions are never removed or signature-changed. Compile-time `static_assert`s in `src/c_abi.cpp` pin the layouts against drift.\n\nThe C++ headers (`\u003cpineforge/engine.hpp\u003e`, `\u003cpineforge/ta.hpp\u003e`, ...) are *internal* implementation surface — what the PineForge transpiler emits against, not part of the stability guarantee, and not recommended for external consumption.\n\n## Repository layout\n\n```\ninclude/pineforge/      - public C ABI + internal C++ headers\nsrc/                    - implementation (~25 .cpp files split by concern)\n  ├── c_abi.cpp                       runtime-side C ABI implementations + layout asserts\n  ├── engine_*.cpp                    BacktestEngine implementation, split by concern:\n  │   ├── engine_path_resolve.cpp     intra-bar OHLC path-resolution helpers\n  │   ├── engine_lower_tf.cpp         lower-timeframe emulation\n  │   ├── engine_orders.cpp           execute_market_*, partial exits\n  │   ├── engine_fills.cpp            process_pending_orders fill loop\n  │   ├── engine_security.cpp         request.security registration\n  │   ├── engine_run.cpp              run() entrypoints, magnified bar loop\n  │   ├── engine_report.cpp           fill_report, trace recording\n  │   ├── engine_strategy_commands.cpp strategy.entry/exit/close/cancel/order\n  │   ├── engine_trade_accessors.cpp  strategy.opentrades.*\n  │   └── engine_risk.cpp             risk gates + per-trade extremes\n  ├── engine_internal.hpp             private cross-TU header (path-resolve helpers, types)\n  ├── ta_*.cpp                        66 indicator classes split by category:\n  │   ├── ta_moving_averages.cpp      RMA, SMA, EMA, WMA, HMA, VWMA, ALMA, SWMA\n  │   ├── ta_oscillators.cpp          RSI, Stoch, CCI, MFI, CMO, TSI, WPR, COG, RCI, ...\n  │   ├── ta_volatility_trend.cpp     ATR, BB, KC, MACD, DMI, SAR, Supertrend, ...\n  │   ├── ta_extremes_volume.cpp      Highest/Lowest, OBV, AccDist, NVI/PVI/PVT, VWAP, ...\n  │   └── ta_misc.cpp                 Linreg, PercentRank, BarsSince, ValueWhen, ...\n  └── magnifier.cpp / matrix.cpp / session_time.cpp / str_utils.cpp / timeframe.cpp / timezone.cpp / math.cpp\ntests/                  - 39 ctest binaries (38 C++ + 1 pure-C ABI sanity)\ncorpus/                 - public submodule: 246 strategies; see CONTRIBUTING.md\n  ├── data/             - reference 36k-bar OHLCV feed (Binance ETH/USDT:USDT 15m)\n  └── CMakeLists.txt    - opt-in subproject that compiles every generated.cpp into strategy.so\nbenchmarks/             - three-way comparison harness vs PyneCore + PineTS\n  ├── assets/           - public submodule: data/ (OHLCV) + strategies/ (100 folders, TV-linked CSVs + generated.cpp + strategy_pyne.py)\n  ├── runners/          - 3 runtime runners (run_pynecore.py + run_pinets_canonical.mjs + run_pineforge_canonical.cpp)\n  ├── speed/            - Google Benchmark harness + subprocess timers + aggregator\n  ├── results/          - summary.md, trade_comparison.md, indicator_comparison.md, speed.md\n  ├── compare.py        - 3-way trade-list comparator (mirrors scripts/verify_corpus.py)\n  └── run_all.sh        - one-shot reproducer: cmake build + run all 3 engines + diff (zero API keys)\nscripts/                - reproducibility tooling\n  ├── run_strategy.py   - load any strategy.so via ctypes, write engine_trades.csv\n  ├── run_corpus.sh     - one-shot: build all 246 .so + run + verify\n  └── verify_corpus.py  - diff each engine_trades.csv against its tv_trades.csv\ncmake/                  - PineForgeConfig.cmake.in for downstream find_package()\ncmake/smoke_consumer/   - Minimal find_package(PineForge) CI smoke project\n.github/workflows/      - CI: Linux + macOS × Release + Debug\n```\n\n## Visibility hygiene\n\nEvery compiled strategy `.so` that statically links `libpineforge.a` exports **exactly the 10 documented C ABI symbols** and zero internal C++ symbols. This is enforced at the library level:\n\n- `libpineforge.a` is built with `-fvisibility=hidden -fvisibility-inlines-hidden`\n- Public symbols are tagged `PF_API` (visibility=default)\n- Internal C++ classes (`BacktestEngine`, `ta::`*, `pineforge::internal::`*) are not tagged, so they stay hidden in any final `.so`\n- CI runs `scripts/check_c_abi_runtime.py` (runtime `PF_API` split vs transpiler-emitted symbols). Full trade-list parity sweeps use the public `corpus` submodule locally; CI runs the engine-only ctest set, not the full corpus parity sweep (~3 min full sweep is run-locally-or-on-release territory).\n\n## Versioning\n\nPineForge follows **semantic versioning** at the C ABI level:\n\n- `PATCH`: implementation changes that don't affect ABI\n- `MINOR`: append-only ABI additions (new functions, new struct fields appended to existing structs)\n- `MAJOR`: breaking ABI changes\n\nA pre-compiled strategy `.so` against runtime `0.X.Y` will keep working against any later runtime within `0.X.Z`. Across major versions, all bets are off.\n\n## Reproducing the corpus run end-to-end\n\nThe validation corpus lets anyone rebuild and rerun every compiled\nPineForge strategy from a fresh clone — now genuinely **from source**:\nthe transpiler ([`pineforge-codegen`](https://github.com/pineforge-4pass/pineforge-codegen-oss))\nis bundled in the engine Docker image, so each `generated.cpp` can be\nre-derived from its `strategy.pine`. The committed `generated.cpp` still\nships, so the build also works with just a C++17 compiler and no Docker.\n\n**Scale:** 246 strategies × ~375,000 trades verified trade-for-trade against TradingView.\n\n```bash\ngit clone https://github.com/pineforge-4pass/pineforge-engine.git\ncd pineforge-engine\ngit submodule update --init corpus\n\n# (Optional) Reproduce the C++ from strategy.pine via the engine image.\n# VERIFY=1 proves the shipped generated.cpp is byte-identical to the\n# transpiler output (drift guard, no overwrite); drop it to regenerate.\ndocker pull ghcr.io/pineforge-4pass/pineforge-engine:latest\nVERIFY=1 scripts/regen_corpus_cpp.sh\n\n# Build + run + verify TV parity. (Add REGEN=1 to regenerate the C++\n# from strategy.pine via the image first — needs Docker.)\nJOBS=8 scripts/run_corpus.sh\n\n# Optional: regen the report\npython3 scripts/regen_validation_report.py\n```\n\nThat builds `libpineforge.a` plus one `strategy.so` per probe, runs each\nagainst the reference OHLCV feed, rewrites each `engine_trades.csv`,\nand prints the canonical corpus summary described in\n`corpus/README.md`. Headline result: **245 / 246 excellent + 1 documented TV-side anomaly** (`anomaly-equity-mirror-strategy-equity-01`, TV broker non-deterministic at 1× equity boundary). Total trades: TV 375,453, engine 375,548 (`+95` ≈ 0.03 % over TV).\n\n## Cross-engine comparison\n\n`[benchmarks/](benchmarks/)` runs **100 strategies** through PineForge, PyneCore, and PineTS to spot engine-specific defects vs TV-side semantics. Strategy folders + the 53,930-bar Binance ETH/USDT-USDT 15m OHLCV live under the [`benchmarks/assets`](https://github.com/pineforge-4pass/pineforge-benchmarks-assets) public submodule. PyneCore Python sources are official PyneSys cloud-compiler output (no hand-ports). PineTS handles indicators only — their strategy backtester is upstream roadmap.\n\n**Scale:** 100 strategies × ~167,000 TV trades verified.\n\n```bash\ngit submodule update --init benchmarks/assets        # public submodule with 100 strategies + OHLCV\ncmake -B build -DPINEFORGE_BUILD_BENCH_STRATEGIES=ON # build engine + 100 bench dylibs\ncmake --build build --target pineforge bench_strategies -j\ncd benchmarks \u0026\u0026 uv sync \u0026\u0026 npm install \u0026\u0026 cd ..      # bench Python + Node deps\nbash benchmarks/run_all.sh                            # ~5 min; no API keys\ncat benchmarks/results/summary.md\n```\n\nCurrent standings (canonical align-then-trim window, 4-dimension diff vs TV):\n\n| | PineForge | PyneCore | TV ground truth |\n|---|---:|---:|---:|\n| Strategies | 100 | 100 | 100 |\n| Trades emitted | 167,381 | 253,031 | 167,301 |\n| 🟢 excellent | **100 / 100** | 85 / 100 | — |\n| 🟢 strong | 0 / 100 | 2 / 100 | — |\n| 🟡 moderate | 0 / 100 | 10 / 100 | — |\n| 🟠 weak | 0 / 100 | 3 / 100 | — |\n\nThe 15 PyneCore-only outliers from excellent involve `strategy.exit(stop=…, limit=…)` brackets, `trail_*` exits, `strategy.close(qty_percent=…)` partial exits, and bar-magnifier paths — categories where PyneCore's broker emulator differs from TV and PineForge does not. See [`benchmarks/results/summary.md`](benchmarks/results/summary.md) for the per-strategy table and methodology.\n\nLast refresh: **2026-05-26** against engine v0.6.0, PyneCore 6.4.6, PineTS 0.9.16. Per-strategy speed table at [`benchmarks/results/speed.md`](benchmarks/results/speed.md) — median **104× faster than PyneCore** on 99 commonly-timed strategies.\n\n## Status\n\n- v0.6.0 — Performance Optimization Sprint. Grouped and cached global static inputs to avoid string-keyed map getters on every bar. Implemented highly optimized thread-local timestamp caching, accelerating backtest throughput by over 13x (up to 6.7M bars/sec). Added end-to-end performance reproduction package and strict input.source() chart series validation.\n- v0.5.0 — Pine v6 HIGH+MEDIUM sprint. Resolved 20 critical compatibility issues across symbol mappings, constant namespaces, timezone-aware timestamp overloads, collection sorting, and bare TA property reads. Corpus expanded to 234 probes (233 excellent + 1 documented anomaly). Expanded ctest suite to 39 binaries.\n- v0.4.1 — corpus rewritten as 228 clean-room probes; corpus submodule flipped public; 5 engine bug fixes (OCA same-direction RAW_ORDER, intraday-cap latch, etc.) + chart-TZ infra + 5 new ctests. **227 excellent + 1 documented anomaly = 228/228 strong-or-better**.\n- v0.1 — initial public release. C ABI defined and pinned. Reported **165 strict-excellent + 2 strong = 167/168** TV parity on the internal corpus (then-private submodule, since made public; 168 strategies including 5 parity probes + 1 anomaly probe); the lone outlier is a 1×-margin stress probe on an undocumented TV edge case. 48/50 strategies hit canonical *excellent* tier in the three-way benchmark. CI runs on Ubuntu + macOS (ctest + install smoke; no corpus).\n- v0.2 — same-id stop/replace deferred to post-bar OHLC resolution (PR #13); RMA warmup seed aligned to Pine reference formula, `-ffp-contract=off` build flag added (PR #14).\n- v0.3 — magnifier wrong-side gap fill fixed for entry bar; directional mintick rounding in `apply_slippage` (PR #15). ctest suite expanded to 30 binaries.\n\n## License\n\nApache License 2.0. See [LICENSE](LICENSE). Third-party notices: [NOTICE](NOTICE). Extended licensing notes (optional benchmark AGPL deps, trademarks): [LEGAL.md](LEGAL.md). Community standards: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Security contact: [SECURITY.md](SECURITY.md).\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) (includes the **Apache-2.0** contribution license grant). The short version:\n\n1. Every contribution must keep the parity test green.\n2. Public-API changes (anything exported from `\u003cpineforge/pineforge.h\u003e`) require a major-version bump.\n3. Internal C++ helpers can change freely as long as the ABI surface stays put.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpineforge-4pass%2Fpineforge-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpineforge-4pass%2Fpineforge-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpineforge-4pass%2Fpineforge-engine/lists"}