38 const Bar*
data() const noexcept {
return data_; }
39 std::size_t
size() const noexcept {
return size_; }
40 bool empty() const noexcept {
return size_ == 0; }
41 const Bar&
operator[](std::size_t i)
const noexcept {
return data_[i]; }
42 const Bar&
front() const noexcept {
return data_[0]; }
43 const Bar&
back() const noexcept {
return data_[size_ - 1]; }
44 const Bar*
begin() const noexcept {
return data_ ? data_ : &empty_bar_; }
47 const Bar* data_ =
nullptr;
48 std::size_t size_ = 0;
49 inline static constexpr Bar empty_bar_{};
76 bool is_first_tick() const noexcept {
return language_.is_first_tick_; }
77 bool is_last_tick() const noexcept {
return language_.is_last_tick_; }
80 return language_.is_first_tick_ && language_.history_slot_is_new_;
83 return language_.history_slot_is_new_;
91 const std::vector<PyramidEntry>& lots);
97 if (retained_.is_stream || retained_.bar_magnifier
98 || (!retained_.input_tf.empty() && !retained_.script_tf.empty()
99 && retained_.input_tf != retained_.script_tf)
100 || interval_index < 0
101 || interval_index + 1 >=
static_cast<int>(retained_.bars.size())) {
104 return retained_.bars[
static_cast<std::size_t
>(interval_index + 1)];
110 if (input_index < 0)
return std::nullopt;
111 for (std::size_t i =
static_cast<std::size_t
>(input_index) + 1; i < retained_.bars.size(); ++i) {
112 if (retained_.bars[i].timestamp >= at_or_after)
return retained_.bars[i];
124 std::numeric_limits<std::int64_t>::min()) noexcept {
125 if (!retained_.is_stream)
return;
126 if (
bar.timestamp == script_open_ms) {
127 bool replaced =
false;
128 for (std::size_t index = 0; index < confirmed_open_input_count_; ++index) {
129 if (confirmed_open_input_bars_[index].timestamp ==
bar.timestamp) {
130 confirmed_open_input_bars_[index] =
bar;
136 confirmed_open_input_bars_[confirmed_open_input_next_] =
bar;
137 confirmed_open_input_next_ =
138 (confirmed_open_input_next_ + 1) % confirmed_open_input_bars_.size();
139 confirmed_open_input_count_ =
140 std::min(confirmed_open_input_count_ + 1, confirmed_open_input_bars_.size());
143 for (std::size_t index = 0; index < confirmed_input_count_; ++index) {
144 auto& existing = confirmed_input_bars_[index];
145 if (existing.timestamp ==
bar.timestamp) {
150 confirmed_input_bars_[confirmed_input_next_] =
bar;
151 confirmed_input_next_ = (confirmed_input_next_ + 1) % confirmed_input_bars_.size();
152 confirmed_input_count_ = std::min(confirmed_input_count_ + 1, confirmed_input_bars_.size());
156 for (std::size_t index = 0; index < confirmed_input_count_; ++index) {
157 if (confirmed_input_bars_[index].timestamp == timestamp)
158 return confirmed_input_bars_[index];
160 for (std::size_t index = 0; index < confirmed_open_input_count_; ++index) {
161 if (confirmed_open_input_bars_[index].timestamp == timestamp)
162 return confirmed_open_input_bars_[index];
167 return context.script_interval.last_traded_close_ms > context.script_interval.open_ms
168 && context.input_interval.last_traded_close_ms
169 >= context.script_interval.last_traded_close_ms;
176 return retained_.input_tf.empty() || retained_.script_tf.empty()
177 || retained_.input_tf == retained_.script_tf;
181 if (last_published_script_open_ms_ == std::numeric_limits<std::int64_t>::min())
183 return last_published_script_open_ms_;
186 return expected_source_bars_ > 0 && source_bar_count_ >= expected_source_bars_;
203 return current_script_bar_valid_ ? ¤t_script_bar_ :
nullptr;
222 const auto& bars = retained_.bars;
223 const std::size_t n = bars.size();
225 if (broker_bar_cursor < n && bars[broker_bar_cursor].timestamp == context.sub_bar_open_ms) {
226 return bars[broker_bar_cursor];
228 if (broker_bar_cursor >= n || bars[broker_bar_cursor].timestamp > context.sub_bar_open_ms) {
229 broker_bar_cursor = 0;
231 while (broker_bar_cursor < n && bars[broker_bar_cursor].timestamp < context.sub_bar_open_ms) {
234 if (broker_bar_cursor < n && bars[broker_bar_cursor].timestamp == context.sub_bar_open_ms) {
235 return bars[broker_bar_cursor];
237 const auto found = std::find_if(bars.begin(), bars.end(),
238 [&](
const Bar&
bar) { return bar.timestamp == context.sub_bar_open_ms; });
239 if (found != bars.end()) {
240 broker_bar_cursor =
static_cast<std::size_t
>(std::distance(bars.begin(), found));
244 if (retained_.is_stream && !input_is_observed_ticks_)
return std::nullopt;
245 return current_script_bar_valid_ ? std::optional<Bar>{current_script_bar_}
252 struct RetainedBegin {
254 std::vector<Bar> owned;
255 std::string input_tf;
256 std::string script_tf;
257 bool bar_magnifier =
false;
258 int magnifier_samples = 4;
260 bool volume_weighted =
false;
261 int volume_weighted_min_samples = 2;
262 int volume_weighted_max_samples = 64;
263 bool is_stream =
false;
265 bool simple_run =
false;
269 void update_source_series(
const Bar&);
270 void reset_language();
272 void reset_consumed_digests() noexcept;
273 void fold_consumed_digests() const noexcept;
278 struct DeferredBoundaryInput {
280 std::int64_t next_input_ms = 0;
281 std::int64_t prior_script_open_ms = 0;
282 bool calling_bar_complete =
false;
283 bool all_security_states =
false;
290 mutable std::size_t broker_bar_cursor = 0;
295 mutable std::unique_ptr<ScriptBucketCursor> input_script_cursor;
298 PineLanguageState language_;
299 RetainedBegin retained_;
302 std::size_t retained_n_ = 0;
303 std::int64_t current_script_open_ms_ = 0;
304 Bar current_script_bar_{};
305 bool current_script_bar_valid_ =
false;
306 bool saw_open_fill_ =
false;
307 int open_point_fills_ = 0;
308 int source_bar_count_ = 0;
309 int expected_source_bars_ = 0;
310 std::uint64_t applied_cursor_ = 0;
311 std::int64_t coof_callback_script_open_ = std::numeric_limits<std::int64_t>::min();
312 std::int64_t last_published_script_open_ms_ =
313 std::numeric_limits<std::int64_t>::min();
314 std::int64_t prior_input_script_open_ms_ = std::numeric_limits<std::int64_t>::min();
315 std::int64_t awaiting_legacy_script_open_ms_ = std::numeric_limits<std::int64_t>::min();
316 std::int64_t last_stream_input_open_ms_ = std::numeric_limits<std::int64_t>::min();
319 std::size_t input_script_size_ = 0;
320 bool uses_aux_security_feed_ =
false;
321 bool input_is_observed_ticks_ =
false;
322 std::array<Bar, 8> confirmed_input_bars_{};
323 std::size_t confirmed_input_next_ = 0;
324 std::size_t confirmed_input_count_ = 0;
325 std::array<Bar, 2> confirmed_open_input_bars_{};
326 std::size_t confirmed_open_input_next_ = 0;
327 std::size_t confirmed_open_input_count_ = 0;
328 DeferredBoundaryInput deferred_boundary_input_{};
333 mutable std::size_t consumed_bars_folded_ = 0;
334 mutable std::uint64_t consumed_bars_digest_ = 1469598103934665603ULL;
335 mutable std::size_t consumed_completes_folded_ = 0;
336 mutable std::uint64_t consumed_completes_digest_ = 1469598103934665603ULL;
337 mutable std::size_t consumed_boundaries_folded_ = 0;
338 mutable std::uint64_t consumed_boundaries_digest_ = 1469598103934665603ULL;
339 mutable std::unique_ptr<ScriptBucketCursor> consumed_script_cursor_;
One accepted realtime print before native matching at its current decision point.