31 no::RequestHandle entry_;
32 tk::BracketReceipt legs_;
34 void on_native_run_begin()
override { bars_ = 0; }
36 void on_native_bar(
const pineforge::Bar&,
37 const pineforge::NativeDecisionContext&)
override {
39 if (bars_ != 1)
return;
41 const auto placed =
submit({no::Transact{2.0},
"entry",
"bracket"});
42 if (placed.status != no::SubmitStatus::Accepted || !placed.handle)
return;
43 entry_ = *placed.handle;
46 no::Request take_profit{no::Reduce{no::OwnerOpenedUnits{}},
"take-profit",
"bracket"};
47 take_profit.trigger = no::Limit{0.0};
48 take_profit.anchor = no::FromOwnerFill{+12.0,
true};
49 no::Request stop_loss{no::Reduce{no::OwnerOpenedUnits{}},
"stop-loss",
"bracket"};
50 stop_loss.trigger = no::Stop{0.0};
51 stop_loss.anchor = no::FromOwnerFill{-8.0,
true};
53 tk::BracketSpec bracket;
54 bracket.parent = entry_;
55 bracket.take_profit = take_profit;
56 bracket.stop_loss = stop_loss;
57 bracket.anchor_rounding = no::NativeAnchorRounding::Directional;
58 bracket.visibility = no::NativeArmVisibility::PendingUntilArmed;
59 legs_ = tk::submit_bracket(*
this, bracket);
63 std::cout <<
"working before the fill: " << native_working_requests().size() <<
'\n';
69 std::optional<double> resolve_anchored_level(
70 const pineforge::NativeAnchoredLevelView& view)
const override {
71 std::printf(
"arm: %s leg of owner %llu, fill %.4f, offset %+.4f, kernel level %.4f\n",
72 view.
trigger == pineforge::NativeAnchoredTrigger::Limit ?
"limit" :
"stop",
78 void on_native_applied(
const no::ExecutionAppliedEvent& event,
79 const pineforge::NativeDecisionContext&)
override {
80 if (event.definition && event.definition->handle == entry_) {
82 std::cout <<
"working after the fill: " << native_working_requests().size() <<
'\n';
105 spec.
fee_kind = pineforge::NativeFeeKind::Percent;
115 {100.00, 100.50, 99.75, 100.10, 4.0, 0},
116 {100.10, 101.00, 100.00, 100.90, 4.0, 300000},
117 {100.90, 103.60, 100.80, 103.20, 4.0, 600000},
118 {103.20, 103.40, 102.90, 103.00, 4.0, 900000},
126 if (host.configure_native(
make_spec()).status
127 != pineforge::NativeSetupStatus::Applied) {
128 std::cerr <<
"configure: " << host.last_error() <<
'\n';
133 if (host.native_state().kind != pineforge::NativeLifecycleKind::Completed) {
134 std::cerr <<
"run: " << host.last_error() <<
'\n';
139 for (
const auto& event : host.native_events(0)) {
140 if (!event.command)
continue;
141 const auto* armed = std::get_if<no::ArmedEvent>(&*event.command);
142 if (!armed || !armed->definition)
continue;
143 const auto& request = armed->definition->request;
144 if (
const auto* limit = std::get_if<no::Limit>(&request.trigger)) {
145 std::cout <<
"armed " << request.label <<
" at " << limit->price <<
'\n';
146 }
else if (
const auto* stop = std::get_if<no::Stop>(&request.trigger)) {
147 std::cout <<
"armed " << request.label <<
" at " << stop->price <<
'\n';
151 std::cout <<
"closed trades: " << host.trade_count() <<
'\n';
152 for (
int i = 0; i < host.trade_count(); ++i) {
153 const auto& trade = host.get_trade(i);
154 std::cout <<
" " << (trade.is_long ?
"long " :
"short")
155 <<
" qty=" << trade.qty
156 <<
" entry=" << trade.entry_price
157 <<
" exit=" << trade.exit_price
158 <<
" pnl=" << trade.pnl <<
'\n';
160 return host.trade_count() > 0 ? 0 : 1;
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)
static void submit(struct host_state *state, uint32_t intent, double value, uint32_t trigger, double price, const char *label)
NativeAnchoredTrigger trigger
native_order::RequestHandle owner
One complete setup value, staged/copied by NativeStrategyHost before it is applied at begin.
native_order::RunIdentity identity