#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *, const char *,
int, int,
struct strategy_so {
void *handle;
strategy_create_fn create;
strategy_free_fn free;
run_backtest_full_fn run_full;
pf_version_get_fn version_get;
};
static int load_strategy(const char *path, struct strategy_so *out)
{
out->handle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
if (!out->handle) { fprintf(stderr, "dlopen: %s\n", dlerror()); return -1; }
out->create = (strategy_create_fn) dlsym(out->handle, "strategy_create");
out->free = (strategy_free_fn) dlsym(out->handle, "strategy_free");
out->run_full = (run_backtest_full_fn) dlsym(out->handle, "run_backtest_full");
out->report_free = (report_free_fn) dlsym(out->handle, "report_free");
out->version_get = (pf_version_get_fn) dlsym(out->handle, "pf_version_get");
if (!out->create || !out->free || !out->run_full || !out->report_free) {
fprintf(stderr, "missing ABI symbol in %s\n", path);
return -1;
}
return 0;
}
static pf_bar_t *load_csv(
const char *path,
int *out_n)
{
FILE *f = fopen(path, "r");
if (!f) { perror(path); return NULL; }
char line[1024];
fgets(line, sizeof line, f);
size_t cap = 1024, n = 0;
pf_bar_t *bars = malloc(cap *
sizeof *bars);
while (fgets(line, sizeof line, f)) {
if (n == cap) {
cap *= 2;
bars = realloc(bars, cap * sizeof *bars);
}
sscanf(line, "%lld,%lf,%lf,%lf,%lf,%lf",
(long long *)&bars[n].timestamp,
&bars[n].open, &bars[n].high, &bars[n].low,
&bars[n].close, &bars[n].volume);
++n;
}
fclose(f);
*out_n = (int)n;
return bars;
}
int main(int argc, char **argv)
{
if (argc != 3) { fprintf(stderr, "usage: %s STRATEGY.so OHLCV.csv\n", argv[0]); return 2; }
struct strategy_so so;
if (load_strategy(argv[1], &so) < 0) return 1;
int n = 0;
if (!bars) return 1;
printf("PineForge %d.%d.%d (%s) — %d bars\n",
n);
so.run_full(s, bars, n,
"",
"",
0, 4,
&r);
printf(" %c %.4f -> %.4f pnl=%+.2f qty=%.4f\n",
}
so.report_free(&r);
so.free(s);
free(bars);
dlclose(so.handle);
return 0;
}
void report_free(pf_report_t *report)
Free heap arrays attached to a filled report.
pf_magnifier_distribution_t
Bar-magnifier sub-bar sampling distribution.
@ PF_MAGNIFIER_ENDPOINTS
Default — exact O,H,L,C points plus uniform fill between.
void * pf_strategy_t
Opaque handle to a compiled strategy instance.
Single OHLCV bar pushed into the engine.
Backtest report filled by run_backtest / run_backtest_full.
double net_profit
Sum of all closed-trade PnL.
int trades_len
Length of trades.
pf_trade_t * trades
Heap array of closed trades.
Closed-trade record returned in pf_report_t::trades.
double exit_price
Exit fill price (incl.
double pnl
Net realized PnL in account currency.
int is_long
1 if long, 0 if short.
double qty
Filled quantity.
double entry_price
Entry fill price (incl.
Runtime version descriptor returned by pf_version_get.
const char * commit_sha
Short git commit SHA, or "" if unknown.