PineForge unreleased
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
exit_activation.cpp
Go to the documentation of this file.
3
4#include <cmath>
5#include <stdexcept>
6
8
10 : evidence_(std::move(evidence)) {
11 const auto& value = *evidence_;
12 if (value.position_cycle <= 0 || value.entry_bar < 0
13 || (value.direction != 1 && value.direction != -1)
14 || !std::isfinite(value.cursor_price)) {
15 throw coded<std::invalid_argument>(RunFailureCode::engine_invariant, {},
16 "invalid Pine exit placement evidence");
17 }
18}
19
20bool ExitActivationPolicy::holds_stop() const noexcept {
21 return evidence_ && !std::isnan(evidence_->stop_level)
22 && (evidence_->direction > 0 ? evidence_->cursor_price <= evidence_->stop_level
23 : evidence_->cursor_price >= evidence_->stop_level);
24}
25
26bool ExitActivationPolicy::holds_limit() const noexcept {
27 return evidence_ && !evidence_->limit_continuation
28 && !std::isnan(evidence_->limit_level)
29 && (evidence_->direction > 0 ? evidence_->cursor_price >= evidence_->limit_level
30 : evidence_->cursor_price <= evidence_->limit_level);
31}
32
34 return evidence_ && evidence_->limit_continuation
35 && evidence_->limit_continuation->cause == LimitContinuationCause::LaterSameOpen;
36}
37
39 int owner_entry_bar) const {
40 const int first = owner_entry_bar;
41 return {owner_cycle, first + (holds_stop() ? 1 : 0), first + (holds_limit() ? 1 : 0)};
42}
43
45 double stop, double limit,
46 const ExitActivationContext& context) {
47 if (!context.fill_recalc || !context.scheduler || !std::isfinite(context.cursor_price)
48 || context.cycle <= 0 || context.position_open_bar != context.bar_index
49 || (context.direction != 1 && context.direction != -1)) {
50 return {};
51 }
52 const bool limit_marketable = !std::isnan(limit)
53 && (context.direction > 0 ? context.cursor_price >= limit
54 : context.cursor_price <= limit);
55 std::optional<LimitContinuation> continuation;
56 const bool historical_reach = historical_cascade_reach(request.birth_reach);
57 if (!context.magnifier && historical_reach
58 && context.after_first_open_fill
59 && context.recalc_leg == 0 && (!std::isnan(stop) || !std::isnan(limit))
60 && !request.requested_trailing && limit_marketable) {
62 context.current_fill};
63 } else if (!context.magnifier && !context.process_on_close && !context.warmup
64 && context.stream_idle && historical_reach
65 && request.full_quantity && !request.requested_trailing
66 && !context.historical_segment && context.at_extreme
67 && context.historical_point == 1 && context.recalc_leg == 1
68 && context.market_recalc_incarnation != 0
69 && context.market_recalc_fill == context.current_fill
70 && context.direction > 0 && context.position_entry_count == 1
71 && context.pyramiding == 0 && context.lot_count == 1
73 && request.has_from_entry
74 && request.from_entry == context.first_lot_id
75 && std::isfinite(request.quantity)
76 && std::abs(request.quantity - context.position_quantity) <= 1e-9
77 && context.pending_empty && request.oca_name.empty()
78 && context.slippage == 0 && context.pointvalue == 1.0
79 && context.account_fx == 1.0 && context.fx_series_empty
80 && limit_marketable && context.bar_path_high_first
81 && context.cursor_price == context.tick_high
82 && context.bar.low < limit && limit < context.bar.high
83 && (std::isnan(stop) || stop < context.bar.low)) {
85 context.current_fill};
86 }
87 const bool opening_stop_continuation = request.from_fill
88 && context.first_open_fill && !context.magnifier
89 && !request.requested_trailing && std::isfinite(stop)
90 && (context.direction > 0 ? stop > context.cursor_price
91 : stop < context.cursor_price);
92 const double held_stop = opening_stop_continuation
93 ? std::numeric_limits<double>::quiet_NaN() : stop;
94 return ExitActivationPolicy({context.cycle, context.position_open_bar,
95 context.direction, context.cursor_price,
96 held_stop, limit, continuation});
97}
98
99} // namespace pineforge::compat::pine
ExitLegActivationBounds resolve(std::int64_t owner_cycle, int owner_entry_bar) const
const std::optional< ExitPlacementEvidence > & evidence() const noexcept
bool historical_cascade_reach(HistoricalBirthReach reach) noexcept
ExitActivationPolicy select_exit_activation(const ExitActivationRequest &request, double stop, double limit, const ExitActivationContext &context)
double low
Definition bar.hpp:7
double high
Definition bar.hpp:7