28 void on_native_run_begin()
override { bars_ = 0; }
30 void on_native_bar(
const pineforge::Bar&,
31 const pineforge::NativeDecisionContext&)
override {
33 if (bars_ == 1 && physical_position().signed_units == 0.0) {
34 submit_market({pineforge::order_action::Transact{1.0},
"native-open",
""});
35 }
else if (bars_ == 4 && physical_position().signed_units != 0.0) {
36 submit_market({pineforge::execution::Flatten{},
"native-flat",
""});
68 spec.
fee_kind = pineforge::NativeFeeKind::CashPerExecution;
70 spec.
close_execution = pineforge::NativeCloseExecution::NextEligiblePoint;
77 {100.0, 102.0, 99.0, 101.0, 4.0, 0},
78 {102.0, 103.0, 101.0, 102.0, 4.0, 300000},
79 {103.0, 104.0, 102.0, 103.5, 4.0, 600000},
80 {103.5, 104.0, 103.0, 103.5, 4.0, 900000},
81 {104.0, 105.0, 103.5, 104.0, 4.0, 1200000},
86 const auto state =
host.native_state();
87 if (state.kind == pineforge::NativeLifecycleKind::Failed) {
88 std::cerr << where <<
": Failed code="
89 <<
static_cast<int>(state.failure.code)
90 <<
" op=" <<
static_cast<int>(state.failure.operation)
91 <<
" " <<
host.last_error() <<
'\n';
114 NativeMarketExample batch;
115 const auto setup = batch.configure_native(spec);
116 if (setup.status != pineforge::NativeSetupStatus::Applied) {
117 std::cerr <<
"configure: " << batch.last_error() <<
'\n';
121 if (failed(batch,
"run()"))
return 1;
122 if (batch.native_state().kind != pineforge::NativeLifecycleKind::Completed) {
123 std::cerr <<
"run() not completed: " << batch.last_error() <<
'\n';
127 NativeMarketExample batch_tf;
128 if (batch_tf.configure_native(spec).status != pineforge::NativeSetupStatus::Applied)
131 if (failed(batch_tf,
"run(tf)") ||
132 batch_tf.native_state().kind != pineforge::NativeLifecycleKind::Completed) {
133 std::cerr <<
"run(tf) " << batch_tf.last_error() <<
'\n';
139 bool accepted =
false;
141 for (
const auto& event : batch.native_events(0)) {
142 if (!event.command)
continue;
143 if (std::holds_alternative<pineforge::native_order::AcceptedEvent>(*event.command))
145 if (std::holds_alternative<pineforge::native_order::ExecutionAppliedEvent>(*event.command))
148 if (!accepted || !filled) {
149 std::cerr <<
"expected AcceptedEvent and ExecutionAppliedEvent\n";
152 if (batch.physical_position().signed_units != 0.0) {
153 std::cerr <<
"expected flat book after flatten fill\n";
159 NativeMarketExample stream;
160 if (stream.configure_native(spec).status != pineforge::NativeSetupStatus::Applied)
162 if (!stream.stream_begin(
kBars, 1,
"5",
"5")) {
163 std::cerr <<
"stream_begin: " << stream.last_error() <<
'\n';
167 if (!stream.stream_push_bar(
kBars[i])) {
168 std::cerr <<
"stream_push_bar: " << stream.last_error() <<
'\n';
172 if (!stream.stream_end()) {
173 std::cerr <<
"stream_end: " << stream.last_error() <<
'\n';
176 if (failed(stream,
"stream") ||
177 stream.native_state().kind != pineforge::NativeLifecycleKind::Completed) {
178 std::cerr <<
"stream not completed: " << stream.last_error() <<
'\n';
182 std::cout <<
"batch closed trades: " << batch.trade_count()
183 <<
" stream closed trades: " << stream.trade_count() <<
'\n';
The public native host: an abstract subclass of BacktestEngine with no PineScript on it.
static const pf_bar_t kBars[]
static pf_native_run_spec_v1 make_spec(void)
int native_market_example_abi_version()
One-line C ABI export for a hand-written NativeStrategyHost.
#define PINEFORGE_EXPORT_NATIVE_STRATEGY(Class)
Define the loadable-module C ABI for one NativeStrategyHost subclass.
One complete setup value, staged/copied by NativeStrategyHost before it is applied at begin.
NativeCloseExecution close_execution
NativeOpenDirections allowed_open_directions
std::string chart_timezone
native_order::RunIdentity identity
std::uint32_t slippage_ticks
NativeEventRetention event_retention
What native_events() can still return; see NativeEventRetention.