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",
""});
64 spec.
fee_kind = pineforge::NativeFeeKind::CashPerExecution;
66 spec.
close_execution = pineforge::NativeCloseExecution::NextEligiblePoint;
73 {100.0, 102.0, 99.0, 101.0, 4.0, 0},
74 {102.0, 103.0, 101.0, 102.0, 4.0, 300000},
75 {103.0, 104.0, 102.0, 103.5, 4.0, 600000},
76 {103.5, 104.0, 103.0, 103.5, 4.0, 900000},
77 {104.0, 105.0, 103.5, 104.0, 4.0, 1200000},
83 if (state.kind == pineforge::NativeLifecycleKind::Failed) {
84 std::cerr << where <<
": Failed code="
85 <<
static_cast<int>(state.failure.code)
86 <<
" op=" <<
static_cast<int>(state.failure.operation)
110 NativeMarketExample batch;
111 const auto setup = batch.configure_native(spec);
112 if (setup.status != pineforge::NativeSetupStatus::Applied) {
113 std::cerr <<
"configure: " << batch.last_error() <<
'\n';
117 if (failed(batch,
"run()"))
return 1;
118 if (batch.native_state().kind != pineforge::NativeLifecycleKind::Completed) {
119 std::cerr <<
"run() not completed: " << batch.last_error() <<
'\n';
123 NativeMarketExample batch_tf;
124 if (batch_tf.configure_native(spec).status != pineforge::NativeSetupStatus::Applied)
127 if (failed(batch_tf,
"run(tf)") ||
128 batch_tf.native_state().kind != pineforge::NativeLifecycleKind::Completed) {
129 std::cerr <<
"run(tf) " << batch_tf.last_error() <<
'\n';
135 bool accepted =
false;
137 for (
const auto& event : batch.native_events(0)) {
138 if (!event.command)
continue;
139 if (std::holds_alternative<pineforge::native_order::AcceptedEvent>(*event.command))
141 if (std::holds_alternative<pineforge::native_order::ExecutionAppliedEvent>(*event.command))
144 if (!accepted || !filled) {
145 std::cerr <<
"expected AcceptedEvent and ExecutionAppliedEvent\n";
148 if (batch.physical_position().signed_units != 0.0) {
149 std::cerr <<
"expected flat book after flatten fill\n";
155 NativeMarketExample stream;
156 if (stream.configure_native(spec).status != pineforge::NativeSetupStatus::Applied)
158 if (!stream.stream_begin(
kBars, 1,
"5",
"5")) {
159 std::cerr <<
"stream_begin: " << stream.last_error() <<
'\n';
163 if (!stream.stream_push_bar(
kBars[i])) {
164 std::cerr <<
"stream_push_bar: " << stream.last_error() <<
'\n';
168 if (!stream.stream_end()) {
169 std::cerr <<
"stream_end: " << stream.last_error() <<
'\n';
172 if (failed(stream,
"stream") ||
173 stream.native_state().kind != pineforge::NativeLifecycleKind::Completed) {
174 std::cerr <<
"stream not completed: " << stream.last_error() <<
'\n';
178 std::cout <<
"batch closed trades: " << batch.trade_count()
179 <<
" stream closed trades: " << stream.trade_count() <<
'\n';
const std::string & last_error() const
The public native host: an abstract subclass of BacktestEngine with no PineScript on it.
NativeStateView native_state() const
The whole run state as one owning read.
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