PineForge v0.13.1-379-g9b50973
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
hello_kernel_c.c
Go to the documentation of this file.
1/* hello, kernel — from C.
2 *
3 * The same host as hello_kernel.cpp, written against the C API instead of
4 * subclassing NativeStrategyHost: hand the runtime a callback table, describe
5 * the run once, feed it bars, read the closed trades back. No PineScript, no
6 * codegen, no dlopen, and no C++ in this file.
7 *
8 * cc -std=c11 hello_kernel_c.c -lpineforge -lstdc++ -o hello_kernel_c
9 */
10
11#include <pineforge/pineforge.h>
12
13#include <stdio.h>
14#include <string.h>
15
16/* open, high, low, close, volume, timestamp (Unix milliseconds). */
17static const pf_bar_t kBars[] = {
18 {100.0, 102.0, 99.0, 101.0, 4.0, 0},
19 {102.0, 103.0, 101.0, 102.0, 4.0, 300000},
20 {103.0, 104.0, 102.0, 103.5, 4.0, 600000},
21 {103.5, 105.0, 103.0, 104.0, 4.0, 900000}
22};
23enum { kBarCount = 4 };
24
25struct host_state {
26 pf_strategy_t handle;
27 int bars;
28};
29
30/* One calculation point per closed script bar. Requests submitted here are
31 * matched from the next eligible point on, never on the bar just closed. */
32static int on_bar(void* user, const pf_bar_t* bar, const pf_native_decision_v1* at) {
33 struct host_state* state = (struct host_state*)user;
35 (void)bar;
36 (void)at;
37
38 ++state->bars;
39 if (state->bars != 1 && state->bars != 3) return 0;
40
41 memset(&request, 0, sizeof(request));
42 request.struct_size = (uint32_t)sizeof(request);
44 if (state->bars == 1) {
46 request.intent_value = 1.0;
47 request.label = "hello-long";
48 } else {
50 request.label = "hello-flat";
51 }
52 /* Returning non-zero here would end the run Failed with
53 * PF_NATIVE_FAILURE_CALLBACK, so report the refusal and keep going. */
54 if (strategy_native_submit_v1(state->handle, &request, NULL, NULL) != PF_NATIVE_OK) {
55 fprintf(stderr, "submit refused at bar %d\n", state->bars);
56 }
57 return 0;
58}
59
60/* Nothing is inferred: the spec names the clock, the instrument and the
61 * account. Validation refuses an incomplete value at configure time. */
64 memset(&spec, 0, sizeof(spec));
65 spec.struct_size = (uint32_t)sizeof(spec);
66 spec.session_key = "hello-kernel-c";
67 spec.run_number = 1;
68 spec.input_tf = "5";
69 spec.script_tf = "5";
70 spec.ticker = "MOCK";
71 spec.tickerid = "TEST:MOCK";
72 spec.type = "crypto";
73 spec.currency = "USDT";
74 spec.basecurrency = "ETH";
75 spec.description = "";
76 spec.volumetype = "";
77 spec.timezone = "UTC";
78 spec.session = "24x7";
79 spec.chart_timezone = "";
80 spec.initial_capital = 10000.0;
81 spec.point_value = 1.0;
82 spec.account_fx = 1.0;
83 spec.price_tick = 0.01;
84 spec.fee_kind = 0; /* Percent */
85 spec.fee_value = 0.0;
86 spec.close_execution = 0; /* NextEligiblePoint */
87 spec.allowed_open_directions = 3; /* Both */
88 return spec;
89}
90
91int main(void) {
92 struct host_state state;
93 pf_native_callbacks_v1 callbacks;
95 pf_report_t report;
96 int i;
97
98 memset(&state, 0, sizeof(state));
99 memset(&report, 0, sizeof(report));
100
101 memset(&callbacks, 0, sizeof(callbacks));
102 callbacks.struct_size = (uint32_t)sizeof(callbacks);
103 callbacks.version = PF_NATIVE_API_VERSION;
104 callbacks.user = &state;
105 callbacks.on_bar = on_bar;
106
107 state.handle = strategy_native_host_create_v1(&callbacks);
108 if (!state.handle) {
109 fprintf(stderr, "create: the runtime refused the callback table\n");
110 return 1;
111 }
112
113 if (strategy_configure_native_v1(state.handle, &spec) != 0) {
114 fprintf(stderr, "configure: %s\n", strategy_get_last_error(state.handle));
115 strategy_native_host_free(state.handle);
116 return 1;
117 }
118
119 if (strategy_native_run_v1(state.handle, kBars, kBarCount, &report) != PF_NATIVE_OK) {
120 fprintf(stderr, "run: %s\n", strategy_get_last_error(state.handle));
122 strategy_native_host_free(state.handle);
123 return 1;
124 }
125
126 printf("closed trades: %d\n", report.total_trades);
127 for (i = 0; i < report.total_trades; ++i) {
128 const pf_trade_t* trade = &report.trades[i];
129 printf(" %s qty=%g entry=%g exit=%g pnl=%g\n",
130 trade->is_long ? "long " : "short", trade->qty,
131 trade->entry_price, trade->exit_price, trade->pnl);
132 }
133
134 {
135 const int trades = report.total_trades;
137 strategy_native_host_free(state.handle);
138 return trades > 0 ? 0 : 1;
139 }
140}
const char * strategy_get_last_error(pf_strategy_t s)
Returns the error message captured by the most recent run_backtest / run_backtest_full call on this s...
int strategy_configure_native_v1(pf_strategy_t s, const pf_native_run_spec_v1 *spec)
Apply a native v1 specification.
int strategy_native_run_v1(pf_strategy_t s, const pf_bar_t *bars, int n, pf_report_t *out)
Run n bars as one batch and fill out.
void strategy_native_host_free(pf_strategy_t s)
Release a handle from strategy_native_host_create_v1.
pf_strategy_t strategy_native_host_create_v1(const pf_native_callbacks_v1 *callbacks)
Allocate a native host that forwards every kernel callback to callbacks.
int strategy_native_submit_v1(pf_strategy_t s, const pf_native_request_v1 *request, uint64_t *incarnation, uint32_t *reject)
Submit request.
void strategy_native_report_free_v1(pf_report_t *report)
Free the heap arrays inside a report filled by strategy_native_run_v1.
@ PF_NATIVE_INTENT_TRANSACT
intent_value signed units.
@ PF_NATIVE_INTENT_FLATTEN
Close the whole book.
#define PF_NATIVE_OK
Success.
static const pf_bar_t kBars[]
static pf_native_run_spec_v1 make_spec(void)
static int on_bar(void *user, const pf_bar_t *bar, const pf_native_decision_v1 *at)
@ kBarCount
int main(void)
#define PF_NATIVE_API_VERSION
Monotonic version of this header's native-C layouts.
void * pf_strategy_t
Opaque handle to a compiled strategy instance.
Definition pineforge.h:433
Single OHLCV bar pushed into the engine.
Definition pineforge.h:127
The C host's strategy logic.
Where the kernel is, presented to every callback.
One order request.
uint32_t struct_size
sizeof(pf_native_request_v1).
uint32_t intent
pf_native_intent_t.
uint32_t version
PF_NATIVE_API_VERSION.
double intent_value
The intent's own scalar; see pf_native_intent_t.
Versioned native run specification.
Definition pineforge.h:469
const char * tickerid
Definition pineforge.h:473
uint32_t allowed_open_directions
Definition pineforge.h:477
const char * volumetype
Definition pineforge.h:473
const char * basecurrency
Definition pineforge.h:473
const char * input_tf
Definition pineforge.h:472
const char * session_key
Definition pineforge.h:471
const char * type
Definition pineforge.h:473
const char * script_tf
Definition pineforge.h:472
const char * chart_timezone
Definition pineforge.h:474
const char * timezone
Definition pineforge.h:474
const char * ticker
Definition pineforge.h:473
const char * session
Definition pineforge.h:474
const char * description
Definition pineforge.h:473
const char * currency
Definition pineforge.h:473
Backtest report filled by run_backtest / run_backtest_full.
Definition pineforge.h:365
int total_trades
Closed-trade count (== trades_len), including the range-end close of a position still open after the ...
Definition pineforge.h:367
pf_trade_t * trades
Heap array of closed trades; script-driven exits first, then the range-end rows (open_at_end=1).
Definition pineforge.h:370
Closed-trade record returned in pf_report_t::trades.
Definition pineforge.h:153
double exit_price
Exit fill price (incl.
Definition pineforge.h:157
double pnl
Net realized PnL in account currency (commission-inclusive).
Definition pineforge.h:158
int is_long
1 if long, 0 if short.
Definition pineforge.h:167
double qty
Filled quantity.
Definition pineforge.h:170
double entry_price
Entry fill price (incl.
Definition pineforge.h:156