|
PineForge v0.13.1-379-g9b50973
Deterministic PineScript v6 backtest runtime — C ABI reference
|
#include <timeframe.hpp>
Public Member Functions | |
| TimeframeAggregator () | |
| Default: passthrough mode (no aggregation). | |
| TimeframeAggregator (int ratio) | |
Ratio-based: every ratio input bars produce one output bar. | |
| TimeframeAggregator (const std::string &target_tf, const std::string &input_tf) | |
| Calendar-based: aggregate until day/week/month boundary. | |
| TimeframeAggregator (const std::string &target_tf, const std::string &input_tf, const std::string &tz, const std::string &session="") | |
| Calendar/ratio aggregation anchored on a symbol clock. | |
| AggregatedBar | feed (const Bar &input_bar) |
| Feed one input bar. Returns aggregation state. | |
| AggregatedBar | feed (const Bar &input_bar, int64_t next_input_ms) |
| feed() with the NEXT input bar's timestamp known (0 = unknown, the form above). | |
| AggregatedBar | feed (const Bar &input_bar, int64_t next_input_ms, int64_t calling_close_ms) |
| feed(bar, next_input_ms) with the CALLING chart bar's nominal close known (0 = unknown, the forms above): TradingView's time_close of the chart bar this input bar belongs to – the input bar's own end on a single-feed run, the native D/W/M chart bar's session close on the split-feed path, where a finer auxiliary slice advances request.security. | |
| Bar | current () const |
| Current in-progress bar. | |
| bool | has_pending_partial () const |
| RATIO (fixed intraday target) only: whether the bucket in progress holds sub-bars no completion has emitted yet – the tail of a chart bar whose last sub-bars never reached the bucket's count, real end or session close (the 21:57Z 3m bucket of OANDA:XAUUSD's Thanksgiving 2025-11-26 session holds only the 21:59Z minute). | |
| AggregatedBar | complete_pending_partial () |
| Finalize the pending partial bucket exactly as feed() finalizes a bucket – the sub-bars it holds ARE the bucket – and return it complete. | |
| Bar | last_completed () const |
| Last completed aggregated bar. | |
| bool | is_active () const |
| Whether aggregation is active (non-passthrough). | |
| CalendarPeriod | calendar_period () const |
| The D/W/M period a CALENDAR aggregator buckets on; NONE for RATIO and PASSTHROUGH. | |
| void | set_native_periods (std::vector< int64_t > stamps, std::vector< int64_t > trade_instants, CalendarPeriod feed_period) |
| TradingView's own period partition for a CALENDAR aggregator, from the native request.security feed of the aggregated timeframe: the stamps (Unix ms, strictly increasing) are the exchange's native bars' opens, and trade_instants[k] is an instant inside the session-day the k-th native bar COMPLETES on – its last input bar (the stamp itself when no input bar falls in the period), the trade date TradingView files the bar under. | |
| bool | has_native_periods () const |
| void | set_early_close_completes (bool on) |
| Whether a session ending BEFORE its nominal close completes the running D/W/M bucket on that session's actual last input bar (feed(bar, next_input_ms) seeing the next input bar open a new period) – true, the default – or the bucket waits for the period's nominal close (the 16:45 bar reaching 17:00, the last traded session-day's close) and, when no input bar reaches it, completes lazily on the next period's first bar (false) – unless the CALLING chart bar's nominal close reaches the period's (feed(bar,
next_input_ms, calling_close_ms): the 1D chart's early-close daily bar, whose time_close stays 17:00 ET). | |
| bool | early_close_completes () const |
| bool | period_changes (int64_t prev_ms, int64_t curr_ms) const |
CALENDAR: whether prev_ms and curr_ms lie in different periods of this aggregator – different native periods / W-M groups when native periods are installed, crosses_boundary on the nominal session calendar otherwise. | |
| int64_t | bucket_open_ms (int64_t ms) const |
Open (Unix ms) of the target-TF bucket an input bar stamped ms belongs to, on the aggregator's anchor clock (syminfo tz + session): CALENDAR -> session_period_open_ms of the bar's D/W/M period (the forex week opens Sunday 17:00 ET, its month on the session whose close date is the 1st); RATIO -> session_intraday_bucket_open_ms, the day-stamp-anchored grid bucket (the same key feed() splits on and time("<intraday tf>") reads); PASSTHROUGH, or a count-only ratio with no wall-clock width, -> ms itself. | |
| int64_t | bar_label_ms (int64_t ms) const |
Timestamp of the target-TF bar OPENED by an input bar stamped ms — what TradingView dates the aggregated bar, and what feed() stamps on every bucket it starts (finding 473). | |
Definition at line 288 of file timeframe.hpp.
| pineforge::TimeframeAggregator::TimeframeAggregator | ( | ) |
Default: passthrough mode (no aggregation).
|
explicit |
Ratio-based: every ratio input bars produce one output bar.
| pineforge::TimeframeAggregator::TimeframeAggregator | ( | const std::string & | target_tf, |
| const std::string & | input_tf ) |
Calendar-based: aggregate until day/week/month boundary.
| pineforge::TimeframeAggregator::TimeframeAggregator | ( | const std::string & | target_tf, |
| const std::string & | input_tf, | ||
| const std::string & | tz, | ||
| const std::string & | session = "" ) |
Calendar/ratio aggregation anchored on a symbol clock.
tz is the Pine syminfo.timezone (exchange tz); session the Pine session string ("0930-1600", "24x7", ...). Defaults reproduce the UTC/24x7 forms bit-for-bit, so every existing construction site compiles unchanged.
| AggregatedBar pineforge::TimeframeAggregator::feed | ( | const Bar & | input_bar | ) |
Feed one input bar. Returns aggregation state.
Referenced by pineforge::source::PineScheduler::run_begin().
| AggregatedBar pineforge::TimeframeAggregator::feed | ( | const Bar & | input_bar, |
| int64_t | next_input_ms ) |
feed() with the NEXT input bar's timestamp known (0 = unknown, the form above).
A historical run holds its whole feed, and on a declared exchange session TradingView finalizes a D/W/M bar on the period's actual last chart bar whatever the nominal calendar says that bar is: the 12:45 ET bar of a 13:00 half-day (NYSE:F Fri 2025-11-28), the Thursday 15:45 bar before a holiday Friday, the 15:45 CT bar closing an overnight CME session-day (lab tv wm-security-buckets tapes, 2026-09-05). CALENDAR mode therefore also completes the running bucket when the next input bar opens a new period. RATIO and PASSTHROUGH ignore the hint, and so do ""/"24x7" sessions (a data hole before a 24x7 midnight is not an early close), so every caller passing 0 and every session-less feed stay bit-identical. The rule applies where TradingView's session template knows the early close – exchange calendars; set_early_close_completes(false) switches a symbol whose template does not (OANDA's cfd / forex streams) back to the nominal close and the lazy completion on the next period's first bar.
| AggregatedBar pineforge::TimeframeAggregator::feed | ( | const Bar & | input_bar, |
| int64_t | next_input_ms, | ||
| int64_t | calling_close_ms ) |
feed(bar, next_input_ms) with the CALLING chart bar's nominal close known (0 = unknown, the forms above): TradingView's time_close of the chart bar this input bar belongs to – the input bar's own end on a single-feed run, the native D/W/M chart bar's session close on the split-feed path, where a finer auxiliary slice advances request.security.
Read only by the OTC rule (set_early_close_completes(false)): TradingView surfaces a D/W/M value on the chart bar whose time_close reaches the period's nominal close, and the daily bar of an early-close day keeps its nominal time_close – on the OANDA:XAUUSD 1D chart the Fri 2025-07-04 bar (data to 12:45 ET) still closes at 17:00 ET, so request.security(tickerid, "W", x) advances on it (cW 3336.61, the early close) exactly as on every regular Friday, and "D" is the chart bar itself there and on Mon 2026-02-16 (14:15 early close); on the 15m chart the 12:45 / 14:15 bar's own time_close falls short and the value waits for the next session's first bar (lab tv oanda1d-{jul,feb,novm,decm} beside the oanda 15m pin, 2026-09-05). So on an OTC stream a bucket the next input bar leaves completes on this input bar iff calling_close_ms reaches the period's nominal close (session_period_last_traded_close_ms); with 0 it waits, as before. Exchange kinds (early_close_completes) ignore the hint: the actual last bar completes the period either way.
| Bar pineforge::TimeframeAggregator::current | ( | ) | const |
Current in-progress bar.
| bool pineforge::TimeframeAggregator::has_pending_partial | ( | ) | const |
RATIO (fixed intraday target) only: whether the bucket in progress holds sub-bars no completion has emitted yet – the tail of a chart bar whose last sub-bars never reached the bucket's count, real end or session close (the 21:57Z 3m bucket of OANDA:XAUUSD's Thanksgiving 2025-11-26 session holds only the 21:59Z minute).
CALENDAR and PASSTHROUGH answer false; so does a count-only ratio with no wall-clock width.
| AggregatedBar pineforge::TimeframeAggregator::complete_pending_partial | ( | ) |
Finalize the pending partial bucket exactly as feed() finalizes a bucket – the sub-bars it holds ARE the bucket – and return it complete.
TradingView surfaces the LAST intrabar of a chart bar at that bar's close whatever its minute count (lab tv dca-ltf-last-intrabar, 2026-09-05), so a request.security evaluator served by a finer feed calls this when its calling chart bar completes. The bucket is emitted once: the next boundary resets it without re-emitting (current_emitted_complete), and a later sub-bar of the same bucket merges without completing it again, as after any early completion. Without a pending partial nothing changes and the current bar is returned incomplete.
| Bar pineforge::TimeframeAggregator::last_completed | ( | ) | const |
Last completed aggregated bar.
| bool pineforge::TimeframeAggregator::is_active | ( | ) | const |
Whether aggregation is active (non-passthrough).
| CalendarPeriod pineforge::TimeframeAggregator::calendar_period | ( | ) | const |
The D/W/M period a CALENDAR aggregator buckets on; NONE for RATIO and PASSTHROUGH.
| void pineforge::TimeframeAggregator::set_native_periods | ( | std::vector< int64_t > | stamps, |
| std::vector< int64_t > | trade_instants, | ||
| CalendarPeriod | feed_period ) |
TradingView's own period partition for a CALENDAR aggregator, from the native request.security feed of the aggregated timeframe: the stamps (Unix ms, strictly increasing) are the exchange's native bars' opens, and trade_instants[k] is an instant inside the session-day the k-th native bar COMPLETES on – its last input bar (the stamp itself when no input bar falls in the period), the trade date TradingView files the bar under.
Installed, they replace the nominal session calendar as the period key: an input bar belongs to the native bar whose stamp is the latest at or before it, so a D period is exactly that native bar's span. On CME_MINI:ES1! a holiday session that pauses at 12:00 CT and reopens at 17:00 the same day (Labor Day, Thanksgiving, Independence Day) is folded by TradingView into the NEXT trade date's daily bar with no stamp of its own (lab tv esd pin, 2026-09-05: the Sun 08-31 17:00 stamp runs to Tue 09-02 15:45 and is Tuesday's bar), so no D period closes at the pause, none opens at the reopen, and a data hole inside a native day is not a close. A W / M period groups the native days by the nominal week / month of their trade date (the holiday session belongs to the next trade date, so to its week). bar_label_ms is the stamp of the bar's native period, bucket_open_ms the group's first stamp, period_changes compares those, and feed(bar, next_input_ms) completes the running bucket on the last input bar before the next native stamp. The partition covers the feed: an input bar before the first stamp keeps the nominal key, and so does one at or after the LAST stamp's nominal period close (session_period_close_ms of feed_period, the feed's own timeframe – DAY for a daily feed), since without a next stamp nothing proves the last native bar reaches further; a chart day the feed does not hold stays a nominal session-day bucket with no native bar to substitute. Empty vectors (the default) leave every nominal rule bit-identical; RATIO / PASSTHROUGH ignore the call. Mismatched sizes or non-increasing stamps install nothing.
|
inline |
Definition at line 425 of file timeframe.hpp.
|
inline |
Whether a session ending BEFORE its nominal close completes the running D/W/M bucket on that session's actual last input bar (feed(bar, next_input_ms) seeing the next input bar open a new period) – true, the default – or the bucket waits for the period's nominal close (the 16:45 bar reaching 17:00, the last traded session-day's close) and, when no input bar reaches it, completes lazily on the next period's first bar (false) – unless the CALLING chart bar's nominal close reaches the period's (feed(bar, next_input_ms, calling_close_ms): the 1D chart's early-close daily bar, whose time_close stays 17:00 ET).
TradingView finalizes on the actual last bar only where its session template carries the early close: exchange calendars (stock / futures / index – NYSE:F's 13:00 half-days, CME's 12:00 CT early closes). OTC quote streams have no holiday template: on OANDA:XAUUSD 15m (cfd, 1800-1700 ET) the Fri 2025-07-04 session ends at the 12:45 ET bar, yet request.security(tickerid, "D", x) lookahead_off surfaces that day on Sun 07-06 18:00 – the next session's first bar – never on the 12:45 bar; so does the Mon 2026-02-16 day ending 14:15 (on Mon 18:00) and the week holding the 07-04 close (lab tv oanda-{jul,julw,feb,febw} pin, ledger log-20260905t034240z-30be11fe, 2026-09-05). The engine sets it from syminfo.type (BacktestEngine:: session_template_knows_early_close: false for forex / cfd / crypto). Read only by the CALENDAR next-input-bar rule without a native partition: ""/"24x7" sessions never reach that rule, the nominal rules are untouched, and an installed native period partition (set_native_periods) stays authoritative either way.
Definition at line 453 of file timeframe.hpp.
|
inline |
Definition at line 454 of file timeframe.hpp.
| bool pineforge::TimeframeAggregator::period_changes | ( | int64_t | prev_ms, |
| int64_t | curr_ms ) const |
CALENDAR: whether prev_ms and curr_ms lie in different periods of this aggregator – different native periods / W-M groups when native periods are installed, crosses_boundary on the nominal session calendar otherwise.
RATIO / PASSTHROUGH: false.
| int64_t pineforge::TimeframeAggregator::bucket_open_ms | ( | int64_t | ms | ) | const |
Open (Unix ms) of the target-TF bucket an input bar stamped ms belongs to, on the aggregator's anchor clock (syminfo tz + session): CALENDAR -> session_period_open_ms of the bar's D/W/M period (the forex week opens Sunday 17:00 ET, its month on the session whose close date is the 1st); RATIO -> session_intraday_bucket_open_ms, the day-stamp-anchored grid bucket (the same key feed() splits on and time("<intraday tf>") reads); PASSTHROUGH, or a count-only ratio with no wall-clock width, -> ms itself.
Pure function of the configuration: it neither reads nor advances the aggregation state, so callers may query it before feeding the bar.
| int64_t pineforge::TimeframeAggregator::bar_label_ms | ( | int64_t | ms | ) | const |
Timestamp of the target-TF bar OPENED by an input bar stamped ms — what TradingView dates the aggregated bar, and what feed() stamps on every bucket it starts (finding 473).
RATIO -> bucket_open_ms (the session-anchored grid open, whether or not the grid-opening sub-bar traded: a forex 1m tape that starts at 17:04 ET still yields the 17:00 chart bar); CALENDAR -> the day stamp of the session-day holding ms (the D/W/M bar is dated by its first TRADED session-day, so a holiday-Monday week stays Tuesday's bar, but never by a thin-open sub-bar inside that day; on OANDA 1800-1700 the stamp is 17:00 ET, an hour before the day trades); PASSTHROUGH -> ms. Gap-free feeds whose open is the stamp are bit-identical: there the first sub-bar IS the bucket open.