PineForge unreleased
Deterministic PineScript v6 backtest runtime — C ABI reference
Loading...
Searching...
No Matches
pine_path_resolve.cpp
Go to the documentation of this file.
1/*
2 * pine_path_resolve.cpp — the TradingView half of the modeled OHLC path.
3 *
4 * Moved verbatim out of src/engine_path_resolve.cpp (R5 lane L12, 2.ii g).
5 * R5 lane N10 then deleted every symbol of that move whose only remaining
6 * references were its own declaration and the tests: the priced-entry
7 * activation, the cross-event list, the tick-quantized trail machinery and
8 * the whole exit-path resolver were a second fill simulation beside the
9 * kernel matcher (src/native_matching.hpp + NativeExecutionConsumer), which
10 * is what the adapter has resolved exits on since the R5 re-lowerings. What
11 * is left is the one function a live caller still reaches:
12 * `entry_stop_first_touch`, the direction-aware first-touch position a
13 * TradingView stop ENTRY fires at (pine_adapter.cpp), walked in the leg order
14 * its caller asked the kernel for (R5 lane F7 removed the overload that read
15 * the sampler's thread-local override instead). The generic helper it calls
16 * (`fill_bar_path_points_ordered`) stays in the kernel TU and is reached
17 * through the same engine_internal.hpp declaration as before.
18 */
19
20#include "../engine_internal.hpp"
21
22#include <algorithm>
23#include <cmath>
24
25namespace pineforge {
26namespace internal {
27
28// First path position where a stop ENTRY can fire, accounting for direction:
29// long stops only fire on up-segments (price rising through the stop), short
30// stops only fire on down-segments. The gap-fill shortcut uses non-strict
31// comparisons: when bar.open already sits at or beyond the stop level in the
32// firing direction the order fills at open (path position 0). For the
33// open-equals-stop case both legs return 0 simultaneously and the dual-stop
34// arbitration breaks the tie in favour of the long leg — this matches TV's
35// broker emulator on probe 83.
36bool entry_stop_first_touch(const Bar& bar, bool high_first, double stop_level,
37 bool is_long, double* out_pos) {
38 if (std::isnan(stop_level) || out_pos == nullptr) return false;
39
40 if (is_long) {
41 if (!(bar.high >= stop_level)) return false;
42 if (bar.open >= stop_level) {
43 *out_pos = 0.0;
44 return true;
45 }
46 } else {
47 if (!(bar.low <= stop_level)) return false;
48 if (bar.open <= stop_level) {
49 *out_pos = 0.0;
50 return true;
51 }
52 }
53
54 double path[4];
55 fill_bar_path_points_ordered(bar, high_first, path);
56
57 for (int i = 1; i < 4; ++i) {
58 double prev = path[i - 1];
59 double curr = path[i];
60 if (is_long) {
61 if (curr <= prev) continue;
62 } else {
63 if (curr >= prev) continue;
64 }
65 double lo = std::min(prev, curr);
66 double hi = std::max(prev, curr);
67 if (stop_level < lo || stop_level > hi) continue;
68
69 double pos = static_cast<double>(i - 1);
70 double denom = curr - prev;
71 if (std::abs(denom) > kSegmentDenomEps) {
72 pos += (stop_level - prev) / denom;
73 }
74 *out_pos = pos;
75 return true;
76 }
77
78 *out_pos = 0.0;
79 return true;
80}
81
82} // namespace internal
83} // namespace pineforge
bool entry_stop_first_touch(const Bar &bar, bool high_first, double stop_level, bool is_long, double *out_pos)
double open
Definition bar.hpp:7
double low
Definition bar.hpp:7
double high
Definition bar.hpp:7