https://github.com/pineforge-4pass/pineforge-codegen-oss
PineScript v6 → C++ transpiler (source-available, PolyForm Noncommercial). Targets the pineforge-engine runtime.
https://github.com/pineforge-4pass/pineforge-codegen-oss
Last synced: 10 days ago
JSON representation
PineScript v6 → C++ transpiler (source-available, PolyForm Noncommercial). Targets the pineforge-engine runtime.
- Host: GitHub
- URL: https://github.com/pineforge-4pass/pineforge-codegen-oss
- Owner: pineforge-4pass
- License: other
- Created: 2026-06-03T16:09:14.000Z (15 days ago)
- Default Branch: main
- Last Pushed: 2026-06-03T19:33:04.000Z (15 days ago)
- Last Synced: 2026-06-03T21:12:58.700Z (14 days ago)
- Language: Python
- Size: 284 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# pineforge-codegen
> PineScript v6 → C++ transpiler that emits against the [pineforge-engine](https://github.com/pineforge-4pass/pineforge-engine) runtime.
[](https://pypi.org/project/pineforge-codegen/)
[](https://pypi.org/project/pineforge-codegen/)
[](LICENSE)
[](#license)
A pure-Python library that turns a PineScript v6 strategy into a complete C++
source file you can compile against the [`pineforge-engine`](https://github.com/pineforge-4pass/pineforge-engine)
runtime — a deterministic native backtester validated **trade-for-trade against
TradingView** (231/232 corpus parity).
It is **source-available and free for personal trading** — research, backtest,
and trade your own account with your own capital at no cost. See
[License](#license) for the line between personal and commercial use.
- **Pure Python, zero runtime dependencies** — one function, `transpile()`.
- **Fails loud, never silent** — a support checker rejects Pine the engine can't
faithfully run *before* codegen, with a `file:line:col` error. You never get
silently-wrong C++.
- First complete PineScript v6 → C++ transpiler with a real support checker (to
our knowledge).
---
## Install
```bash
pip install pineforge-codegen
```
Requires Python ≥ 3.11. No runtime dependencies.
From source (development / contributing):
```bash
git clone https://github.com/pineforge-4pass/pineforge-codegen-oss.git
cd pineforge-codegen-oss
pip install -e ".[dev]"
```
## Quick start
```python
from pineforge_codegen import transpile
pine = """
//@version=6
strategy("SMA cross", overlay=true)
fast = ta.sma(close, 10)
slow = ta.sma(close, 30)
if ta.crossover(fast, slow)
strategy.entry("long", strategy.long)
if ta.crossunder(fast, slow)
strategy.close("long")
"""
cpp = transpile(pine)
print(cpp) # complete C++ source string
```
The output `#include`s ``, ``, … and
compiles into a `.so` exposing the engine's documented C-ABI.
## Usage
### The `transpile()` function
```python
transpile(
pine_source: str,
*,
check_support: bool = True, # run the support checker before codegen
filename: str = "", # name used in error locations
) -> str
```
Returns the generated C++ source as a string. Raises
`pineforge_codegen.errors.CompileError` on any unsupported construct or syntax
error.
### Transpile a file to a `.cpp`
```python
from pathlib import Path
from pineforge_codegen import transpile
pine = Path("strategy.pine")
cpp = transpile(pine.read_text(), filename=pine.name) # filename → better errors
Path("strategy.generated.cpp").write_text(cpp)
```
### Handle unsupported features
The support checker raises a `CompileError` with the exact source location
instead of emitting broken C++:
```python
from pineforge_codegen import transpile
from pineforge_codegen.errors import CompileError
try:
transpile('//@version=6\nindicator("x")\n')
except CompileError as e:
print(e)
# :2:1: indicator() declarations are not supported; PineForge runs strategies only.
try:
transpile('//@version=6\nstrategy("x")\n'
'x = request.financial("AAPL", "REV", "FQ")\n')
except CompileError as e:
print(e)
# :3:22: request.financial(...) is not supported.
```
Pass `filename=` so the location points back at the user's file:
```python
transpile(src, filename="my_strategy.pine")
# raises e.g. my_strategy.pine:12:5: ...
```
### Skip the support checker
`check_support=False` bypasses the gate (intended only for tests of legacy
fixtures — it can produce C++ the engine won't accept):
```python
cpp = transpile(src, check_support=False)
```
### Trace intermediate expressions (`@pf-trace`)
A `// @pf-trace name=expr` comment makes the engine emit `name`'s per-bar value
in the backtest report — useful for debugging parity against TradingView:
```python
pine = """
//@version=6
strategy("traced")
// @pf-trace rsi=ta.rsi(close, 14)
e = ta.ema(close, 20)
if close > e
strategy.entry("L", strategy.long)
"""
cpp = transpile(pine) # emitted on_bar tail records `rsi` each bar
```
### Advanced: run the pipeline stages directly
`transpile()` is a thin wrapper over five passes. Drive them yourself to inspect
tokens, the AST, or the analyzer context:
```python
from pineforge_codegen import (
Lexer, Parser, Analyzer, CodeGen,
extract_pf_trace_pragmas, check_support_or_raise,
)
src = open("strategy.pine").read()
pragmas = extract_pf_trace_pragmas(src)
tokens = Lexer(src, filename="strategy.pine").tokenize()
ast = Parser(tokens, source=src, filename="strategy.pine").parse()
check_support_or_raise(ast, filename="strategy.pine")
ctx = Analyzer(ast, filename="strategy.pine").analyze()
ctx.pf_trace_pragmas = pragmas
cpp = CodeGen(ctx).generate()
```
## How it works
`transpile()` runs five passes, in order:
```
pine source
│
├─ 1. extract_pf_trace_pragmas // @pf-trace comments pulled out first
├─ 2. Lexer → Parser token stream → Pine v6 AST
├─ 3. support_checker reject anything the engine can't run faithfully
├─ 4. Analyzer type inference, scope resolution, TA bookkeeping
└─ 5. CodeGen → C++ source string
```
## Compile & run against the engine
The emitted C++ targets the C-ABI in ``. To build and run
a strategy:
```bash
# Get the runtime (Apache-2.0) next to this repo
git clone https://github.com/pineforge-4pass/pineforge-engine.git
```
Follow the engine's [`tutorial/`](https://github.com/pineforge-4pass/pineforge-engine/tree/main/tutorial)
to build `libpineforge.a`, compile your transpiled `.cpp` into a strategy `.so`,
feed it OHLCV, and read back the closed-trade list. The codegen version must
target a matching engine ABI (see [`VERSION`](VERSION)).
Prefer no local build? A hosted transpile API + MCP server is available so AI
agents can transpile and backtest for you — see .
## Running tests
```bash
pip install -e ".[dev]"
pytest
```
The pure-transpiler suite is fast (< 1 s) and has no native dependencies — it
checks token streams, parse trees, analyzer output, and canonical C++ strings
without invoking a C++ compiler.
Opt-in compile checks (`tests/test_compile_smoke.py`, `tests/test_compile_corpus.py`)
run `g++ -fsyntax-only` on transpiled C++ against the engine headers. They
auto-detect a sibling `../pineforge-engine` checkout, or set the path explicitly:
```bash
export PINEFORGE_ENGINE_INCLUDE=/path/to/pineforge-engine/include
pytest
```
Without an engine checkout these tests skip cleanly, so CI stays green.
## License
Source-available under the [PolyForm Noncommercial License 1.0.0](LICENSE), with
two supplemental terms (the `LICENSE` file is the controlling text):
- **Personal Trading exception** — free to research, backtest, and trade for your
own account with your own capital.
- **Commercial use** — companies, funds, managing third-party capital, embedding
in a product, or operating a hosted / public-facing service requires a
commercial license.
Competing hosted services are not permitted under the noncommercial terms. This
is source-available, not OSI open source.
### Buying a commercial license
Commercial licenses are available — flexible terms for funds, products, and
hosted/embedded use. Email **luis@4pass.com.tw** with your use case for a quote.