PineForge v0.1.2-11-ga87241d
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
pineforge.h
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: Apache-2.0
3 *
4 * pineforge.h — public C ABI for the PineForge runtime.
5 *
6 * This header is the single source of truth for the harness ↔ compiled-
7 * strategy boundary. Every PineForge-generated .so exports a fixed set
8 * of C symbols declared below; the Python harness (validate_detailed_
9 * report.py) and any C/C++/FFI consumer of compiled strategies links
10 * against this contract.
11 *
12 * STABILITY GUARANTEE
13 * ───────────────────
14 * Within the same PINEFORGE_VERSION_MAJOR, this header's POD struct
15 * layouts and `extern "C"` symbol signatures are append-only. Fields
16 * are never reordered, removed, or retyped; new fields may only be
17 * appended at the end of structs. New functions may be added; existing
18 * functions are not removed or signature-changed.
19 *
20 * Across major versions all bets are off. Bump
21 * PINEFORGE_VERSION_MAJOR when breaking the ABI.
22 *
23 * SCOPE — WHAT THIS HEADER COVERS
24 * ───────────────────────────────
25 * ✓ Lifecycle of a compiled strategy (create / destroy)
26 * ✓ Running a backtest (auto-detect or fully configured)
27 * ✓ Per-strategy configuration (inputs, overrides, magnifier, trace)
28 * ✓ The shape of the report returned to the harness
29 *
30 * SCOPE — WHAT THIS HEADER DOES NOT COVER (BY DESIGN)
31 * ───────────────────────────────────────────────────
32 * ✗ The contract between codegen-emitted strategy code and the runtime
33 * internals (TA classes, math, series, strategy commands). That
34 * contract stays C++ — codegen and runtime ship together and are
35 * versioned in lockstep within the closed transpiler.
36 * ✗ Source-compiling strategies. Use the closed transpiler binary.
37 *
38 * The C++ headers under `<pineforge/engine.hpp>` etc. are *internal*
39 * implementation surface — not part of this stability guarantee.
40 */
41
42#ifndef PINEFORGE_H
43#define PINEFORGE_H
44
45#include <stdint.h>
46#include <stddef.h>
47
48/* ── Version ─────────────────────────────────────────────────────── */
49
50/* Macros (PINEFORGE_VERSION_MAJOR / _MINOR / _PATCH / _STRING / _FULL,
51 * PINEFORGE_GIT_SHA) live in the generated <pineforge/version.h>. */
52#include <pineforge/version.h>
53
54/* ── Visibility ──────────────────────────────────────────────────── */
55
56#if defined(_WIN32) || defined(__CYGWIN__)
57 #if defined(PINEFORGE_BUILD_SHARED)
58 #define PF_API __declspec(dllexport)
59 #else
60 #define PF_API __declspec(dllimport)
61 #endif
62#elif defined(__GNUC__) || defined(__clang__)
63 #define PF_API __attribute__((visibility("default")))
64#else
65 #define PF_API
66#endif
67
68#ifdef __cplusplus
69extern "C" {
70#endif
71
72/** @defgroup pf_types Types
73 * @brief POD types and enums passed across the C ABI.
74 * @{
75 */
76
77/** Bar-magnifier sub-bar sampling distribution.
78 *
79 * Selects how intra-bar synthetic ticks are placed when the bar
80 * magnifier is enabled in #run_backtest_full. Layout-compatible with the
81 * internal C++ `pineforge::MagnifierDistribution` enum class — a
82 * `static_assert` in `c_abi.cpp` guarantees the integer values match. */
83typedef enum pf_magnifier_distribution_e {
84 PF_MAGNIFIER_UNIFORM = 0, /**< Uniform spacing across the parent bar. */
85 PF_MAGNIFIER_COSINE = 1, /**< Cosine-tapered density. */
86 PF_MAGNIFIER_TRIANGLE = 2, /**< Triangle-tapered density. */
87 PF_MAGNIFIER_ENDPOINTS = 3, /**< Default — exact O,H,L,C points plus uniform fill between. */
88 PF_MAGNIFIER_FRONT_LOADED = 4, /**< Sample density biased toward bar open. */
89 PF_MAGNIFIER_BACK_LOADED = 5 /**< Sample density biased toward bar close. */
91
92/** Single OHLCV bar pushed into the engine.
93 *
94 * Layout-compatible with the internal C++ `pineforge::Bar` struct. */
95typedef struct pf_bar_s {
96 double open; /**< Open price. */
97 double high; /**< High price. */
98 double low; /**< Low price. */
99 double close; /**< Close price. */
100 double volume; /**< Bar volume. */
101 int64_t timestamp; /**< Bar open time, Unix milliseconds. */
102} pf_bar_t;
103
104/** Closed-trade record returned in pf_report_t::trades.
105 *
106 * Layout-compatible with internal `pineforge::TradeC`. */
107typedef struct pf_trade_s {
108 int64_t entry_time; /**< Entry fill time (Unix ms). */
109 int64_t exit_time; /**< Exit fill time (Unix ms). */
110 double entry_price; /**< Entry fill price (incl. slippage). */
111 double exit_price; /**< Exit fill price (incl. slippage). */
112 double pnl; /**< Net realized PnL in account currency. */
113 double pnl_pct; /**< Net realized PnL as a percentage of entry capital. */
114 int is_long; /**< 1 if long, 0 if short. */
115 double max_runup; /**< Peak favorable price travel during the trade ($/unit qty). */
116 double max_drawdown; /**< Peak adverse price travel during the trade ($/unit qty). */
117 double qty; /**< Filled quantity. */
118} pf_trade_t;
119
120/** Per-`request.security()` site diagnostic counters.
121 *
122 * Layout-compatible with internal `pineforge::SecurityDiagC`. */
123typedef struct pf_security_diag_s {
124 int sec_id; /**< Stable id for the request.security site. */
125 int64_t feed_count; /**< Higher-TF feed bars consumed. */
126 int64_t complete_count; /**< Evaluations on completed parent bars. */
127 int64_t partial_count; /**< Evaluations on still-forming parent bars. */
129
130/** Single per-bar trace entry.
131 *
132 * Emitted when the source script contains `// @pf-trace name=expr`
133 * pragmas and tracing is enabled via #strategy_set_trace_enabled.
134 * Layout-compatible with internal `pineforge::TraceEntryC`. */
135typedef struct pf_trace_entry_s {
136 int64_t timestamp; /**< Bar timestamp (Unix ms). */
137 int32_t bar_index; /**< Zero-based bar index. */
138 int32_t name_id; /**< Index into pf_report_t::trace_names. */
139 double value; /**< Traced expression value on this bar. */
141
142/** Backtest report filled by #run_backtest / #run_backtest_full.
143 *
144 * Layout-compatible with internal `pineforge::ReportC`.
145 *
146 * ### Ownership and lifetime
147 * The struct itself is caller-owned (typically stack). The embedded
148 * arrays (`trades`, `security_diag`, `trace`, `trace_names`) are
149 * heap-allocated by the runtime; the caller must invoke #report_free
150 * exactly once on each filled report. `trace_names` string pointers
151 * remain owned by the strategy handle until #strategy_free. */
152
153typedef struct pf_report_s {
154 /* Trades */
155 int total_trades; /**< Closed-trade count (== trades_len). */
156 pf_trade_t* trades; /**< Heap array of closed trades. */
157 int trades_len; /**< Length of #trades. */
158 double net_profit; /**< Sum of all closed-trade PnL. */
159
160 /* Bar processing counts */
161 int64_t input_bars_processed; /**< Source-feed bars consumed. */
162 int64_t script_bars_processed; /**< Script-timeframe bars evaluated. */
163
164 /* Security diagnostics */
165 int64_t security_feeds_total; /**< Total higher-TF feed bars across all security sites. */
166 int64_t security_complete_total; /**< Total complete-bar evals across all security sites. */
167 int64_t security_partial_total; /**< Total partial-bar evals across all security sites. */
168
169 /* Bar magnifier diagnostics */
170 int64_t magnifier_sub_bars_total; /**< Sub-bars synthesized by the magnifier. */
171 int64_t magnifier_sample_ticks_total; /**< Sample ticks visited by the magnifier. */
172
173 /* Timeframe metadata */
174 int input_tf_seconds; /**< Detected/configured input timeframe (seconds). */
175 int script_tf_seconds; /**< Script timeframe (seconds). */
176 int script_tf_ratio; /**< script_tf_seconds / input_tf_seconds. */
177 int needs_aggregation; /**< 1 if input → script TF aggregation was performed. */
178 int bar_magnifier_enabled; /**< 1 if magnifier was active for this run. */
179
180 /* Per-security feed/eval counters */
181 pf_security_diag_t* security_diag; /**< One entry per request.security site. */
182 int security_diag_len; /**< Length of #security_diag. */
183
184 /* Per-bar trace records */
185 pf_trace_entry_t* trace; /**< Per-bar trace records (empty unless tracing enabled). */
186 int trace_len; /**< Length of #trace. */
187 const char** trace_names; /**< Names indexed by pf_trace_entry_t::name_id. */
188 int trace_names_len; /**< Length of #trace_names. */
190
191/** @} */ /* end of pf_types */
192
193/** Opaque handle to a compiled strategy instance. */
194typedef void* pf_strategy_t;
195
196/* ───────────────────────────────────────────────────────────────────
197 * STRATEGY .SO EXPORTS — implemented per compiled strategy
198 * ───────────────────────────────────────────────────────────────────
199 *
200 * Each .so emitted by the codegen exports the following symbols. The
201 * runtime library itself does NOT define them — they are per-strategy
202 * implementations generated by the transpiler.
203 *
204 * Note on naming: these are the legacy unprefixed names retained for
205 * backward compatibility with the existing harness. Future major
206 * versions may introduce `pf_`-prefixed equivalents and deprecate the
207 * unprefixed forms.
208 */
209
210/** @defgroup pf_lifecycle Strategy lifecycle
211 * @brief Create, run, and destroy a compiled strategy instance.
212 * @{
213 */
214
215/** Allocate a new strategy instance.
216 *
217 * @param params_json Currently ignored; pass `NULL`.
218 * @return Strategy handle, or `NULL` on allocation failure.
219 *
220 * Caller owns the returned handle and must release it via #strategy_free. */
221PF_API pf_strategy_t strategy_create(const char* params_json);
222
223/** Release a strategy handle previously returned by #strategy_create.
224 *
225 * Safe to call with `NULL`. Invalidates any `pf_report_t::trace_names`
226 * pointers obtained from this strategy. */
228
229/** Run a backtest with auto-detected timeframe and no bar magnifier.
230 *
231 * @param s Strategy handle from #strategy_create.
232 * @param bars Non-NULL pointer to OHLCV bars (length @p n).
233 * @param n Bar count (>= 0).
234 * @param out Non-NULL output report. Fields are populated with heap
235 * allocations the caller must release via #report_free. */
237 pf_bar_t* bars,
238 int n,
239 pf_report_t* out);
240
241/** Run a backtest with explicit timeframe and magnifier configuration.
242 *
243 * @param s Strategy handle.
244 * @param bars Bar feed.
245 * @param n Bar count.
246 * @param input_tf Input timeframe ("1", "5", "15", "60", "1D", ...).
247 * Empty string → auto-detect from bar timestamps.
248 * @param script_tf Script timeframe. Empty string → defaults to @p input_tf.
249 * @param bar_magnifier Boolean (0 / non-zero) — enable bar magnifier.
250 * @param magnifier_samples Sub-bar samples per parent bar (typical: 4).
251 * @param magnifier_dist Sampling distribution (see #pf_magnifier_distribution_t).
252 * @param out Output report. Free with #report_free. */
254 pf_bar_t* bars,
255 int n,
256 const char* input_tf,
257 const char* script_tf,
258 int bar_magnifier,
259 int magnifier_samples,
260 pf_magnifier_distribution_t magnifier_dist,
261 pf_report_t* out);
262
263/** Free heap arrays attached to a filled report.
264 *
265 * Idempotent. Safe to call with `NULL` or an already-freed report.
266 * The `pf_report_t` struct itself is caller-owned. */
268
269/** @} */ /* end of pf_lifecycle */
270
271/** @defgroup pf_config Per-strategy configuration
272 * @brief Override @c input.*() values, `strategy(...)` params, and runtime knobs.
273 * @{
274 */
275
276/** Override a Pine @c input.*() value before the next run.
277 *
278 * @param s Strategy handle.
279 * @param key The input's title (or fallback identifier).
280 * @param value Serialized value — numbers as decimal strings,
281 * booleans as `"true"` / `"false"`.
282 *
283 * Calls after #run_backtest are accepted but only take effect on
284 * subsequent runs. */
286 const char* key,
287 const char* value);
288
289/** Override a `strategy(...)` declaration parameter.
290 *
291 * Recognised @p key values: `initial_capital`, `commission_value`,
292 * `default_qty_value`, `pyramiding`, `slippage`,
293 * `process_orders_on_close`, `close_entries_rule`, `default_qty_type`,
294 * `commission_type`. */
296 const char* key,
297 const char* value);
298
299/** Toggle volume-weighted bar-magnifier sampling.
300 *
301 * Has no effect unless the bar magnifier is enabled in
302 * #run_backtest_full. */
304 int on);
305
306/* ───────────────────────────────────────────────────────────────────
307 * RUNTIME LIBRARY EXPORTS — implemented in libruntime
308 * ─────────────────────────────────────────────────────────────────── */
309
310/** Toggle per-bar trace recording. Default off (zero-cost when off).
311 *
312 * Enables capture for `// @pf-trace name=expr` pragmas already compiled
313 * into the strategy `.so`. Trace records appear in pf_report_t::trace. */
315
316/** Set the earliest Unix-ms timestamp at which strategy order commands
317 * may fire.
318 *
319 * Earlier bars still execute user code and warm TA/series state, but
320 * `strategy.entry/order/exit/close` commands are ignored. */
322
323/** @} */ /* end of pf_config */
324
325/** @defgroup pf_version Version query
326 * @brief Runtime version metadata.
327 * @{
328 */
329
330/** Runtime version descriptor returned by #pf_version_get. */
331typedef struct pf_version_s {
332 int major; /**< Major version. */
333 int minor; /**< Minor version. */
334 int patch; /**< Patch version. */
335 const char* commit_sha; /**< Short git commit SHA, or `""` if unknown. */
337
338/** @return Linked runtime version. */
340
341/** Full git-derived version descriptor.
342 *
343 * Returns `"MAJOR.MINOR.PATCH[-N-gSHA[-dirty]]"` for git checkouts, or
344 * plain `"MAJOR.MINOR.PATCH"` for tarball builds. The pointer is to a
345 * static string with program lifetime; do not free. */
346PF_API const char* pf_version_string(void);
347
348/** @} */ /* end of pf_version */
349
350#ifdef __cplusplus
351} /* extern "C" */
352#endif
353
354#endif /* PINEFORGE_H */
void strategy_set_override(pf_strategy_t s, const char *key, const char *value)
Override a strategy(...) declaration parameter.
void strategy_set_input(pf_strategy_t s, const char *key, const char *value)
Override a Pine input.
void strategy_set_magnifier_volume_weighted(pf_strategy_t s, int on)
Toggle volume-weighted bar-magnifier sampling.
void strategy_set_trade_start_time(pf_strategy_t s, int64_t timestamp_ms)
Set the earliest Unix-ms timestamp at which strategy order commands may fire.
void strategy_set_trace_enabled(pf_strategy_t s, int on)
Toggle per-bar trace recording.
pf_strategy_t strategy_create(const char *params_json)
Allocate a new strategy instance.
void run_backtest(pf_strategy_t s, pf_bar_t *bars, int n, pf_report_t *out)
Run a backtest with auto-detected timeframe and no bar magnifier.
void strategy_free(pf_strategy_t s)
Release a strategy handle previously returned by strategy_create.
void report_free(pf_report_t *report)
Free heap arrays attached to a filled report.
void run_backtest_full(pf_strategy_t s, pf_bar_t *bars, int n, const char *input_tf, const char *script_tf, int bar_magnifier, int magnifier_samples, pf_magnifier_distribution_t magnifier_dist, pf_report_t *out)
Run a backtest with explicit timeframe and magnifier configuration.
pf_magnifier_distribution_t
Bar-magnifier sub-bar sampling distribution.
Definition pineforge.h:83
@ PF_MAGNIFIER_FRONT_LOADED
Sample density biased toward bar open.
Definition pineforge.h:88
@ PF_MAGNIFIER_COSINE
Cosine-tapered density.
Definition pineforge.h:85
@ PF_MAGNIFIER_ENDPOINTS
Default — exact O,H,L,C points plus uniform fill between.
Definition pineforge.h:87
@ PF_MAGNIFIER_BACK_LOADED
Sample density biased toward bar close.
Definition pineforge.h:89
@ PF_MAGNIFIER_TRIANGLE
Triangle-tapered density.
Definition pineforge.h:86
@ PF_MAGNIFIER_UNIFORM
Uniform spacing across the parent bar.
Definition pineforge.h:84
pf_version_t pf_version_get(void)
const char * pf_version_string(void)
Full git-derived version descriptor.
void * pf_strategy_t
Opaque handle to a compiled strategy instance.
Definition pineforge.h:194
#define PF_API
Definition pineforge.h:65
Single OHLCV bar pushed into the engine.
Definition pineforge.h:95
double volume
Bar volume.
Definition pineforge.h:100
double high
High price.
Definition pineforge.h:97
double low
Low price.
Definition pineforge.h:98
double close
Close price.
Definition pineforge.h:99
double open
Open price.
Definition pineforge.h:96
int64_t timestamp
Bar open time, Unix milliseconds.
Definition pineforge.h:101
Backtest report filled by run_backtest / run_backtest_full.
Definition pineforge.h:153
int input_tf_seconds
Detected/configured input timeframe (seconds).
Definition pineforge.h:174
int security_diag_len
Length of security_diag.
Definition pineforge.h:182
int64_t security_feeds_total
Total higher-TF feed bars across all security sites.
Definition pineforge.h:165
int bar_magnifier_enabled
1 if magnifier was active for this run.
Definition pineforge.h:178
pf_trace_entry_t * trace
Per-bar trace records (empty unless tracing enabled).
Definition pineforge.h:185
int trace_names_len
Length of trace_names.
Definition pineforge.h:188
int64_t input_bars_processed
Source-feed bars consumed.
Definition pineforge.h:161
int script_tf_seconds
Script timeframe (seconds).
Definition pineforge.h:175
double net_profit
Sum of all closed-trade PnL.
Definition pineforge.h:158
int trades_len
Length of trades.
Definition pineforge.h:157
int trace_len
Length of trace.
Definition pineforge.h:186
int64_t script_bars_processed
Script-timeframe bars evaluated.
Definition pineforge.h:162
int64_t magnifier_sample_ticks_total
Sample ticks visited by the magnifier.
Definition pineforge.h:171
int total_trades
Closed-trade count (== trades_len).
Definition pineforge.h:155
int64_t security_partial_total
Total partial-bar evals across all security sites.
Definition pineforge.h:167
pf_security_diag_t * security_diag
One entry per request.security site.
Definition pineforge.h:181
int64_t magnifier_sub_bars_total
Sub-bars synthesized by the magnifier.
Definition pineforge.h:170
const char ** trace_names
Names indexed by pf_trace_entry_t::name_id.
Definition pineforge.h:187
int64_t security_complete_total
Total complete-bar evals across all security sites.
Definition pineforge.h:166
int script_tf_ratio
script_tf_seconds / input_tf_seconds.
Definition pineforge.h:176
int needs_aggregation
1 if input → script TF aggregation was performed.
Definition pineforge.h:177
pf_trade_t * trades
Heap array of closed trades.
Definition pineforge.h:156
Per-request.security() site diagnostic counters.
Definition pineforge.h:123
int sec_id
Stable id for the request.security site.
Definition pineforge.h:124
int64_t feed_count
Higher-TF feed bars consumed.
Definition pineforge.h:125
int64_t complete_count
Evaluations on completed parent bars.
Definition pineforge.h:126
int64_t partial_count
Evaluations on still-forming parent bars.
Definition pineforge.h:127
Single per-bar trace entry.
Definition pineforge.h:135
double value
Traced expression value on this bar.
Definition pineforge.h:139
int64_t timestamp
Bar timestamp (Unix ms).
Definition pineforge.h:136
int32_t name_id
Index into pf_report_t::trace_names.
Definition pineforge.h:138
int32_t bar_index
Zero-based bar index.
Definition pineforge.h:137
Closed-trade record returned in pf_report_t::trades.
Definition pineforge.h:107
double pnl_pct
Net realized PnL as a percentage of entry capital.
Definition pineforge.h:113
double exit_price
Exit fill price (incl.
Definition pineforge.h:111
double pnl
Net realized PnL in account currency.
Definition pineforge.h:112
int is_long
1 if long, 0 if short.
Definition pineforge.h:114
double max_drawdown
Peak adverse price travel during the trade ($/unit qty).
Definition pineforge.h:116
double qty
Filled quantity.
Definition pineforge.h:117
double max_runup
Peak favorable price travel during the trade ($/unit qty).
Definition pineforge.h:115
int64_t entry_time
Entry fill time (Unix ms).
Definition pineforge.h:108
double entry_price
Entry fill price (incl.
Definition pineforge.h:110
int64_t exit_time
Exit fill time (Unix ms).
Definition pineforge.h:109
Runtime version descriptor returned by pf_version_get.
Definition pineforge.h:331
int patch
Patch version.
Definition pineforge.h:334
int minor
Minor version.
Definition pineforge.h:333
int major
Major version.
Definition pineforge.h:332
const char * commit_sha
Short git commit SHA, or "" if unknown.
Definition pineforge.h:335