Bar Conventions in the Engine: Label, Close, Fill and Time Zone
At what time does the Stochastly engine label and fill a price bar?
The resampler labels a left-closed aggregate at its interval start, while its final close becomes available only after the interval completes. A causal control shifts one position by a bar; actual fills require a test in the executable graph used.
The resampling code labels the opening time; final OHLC and executable fill timing require separate verification.

Evidence map
| Aspect | Finding |
|---|---|
| What it is | What the engine actually does with a bar, stated so that a custom node can be written to match it. |
| Key result / practice | Resampling uses a left label and left-closed interval. |
| Why it matters for backtesting | Treat an aggregate bar's timestamp as the opening label, not the moment its final close became available. |
What it is
These are conventions read from the code, not recommendations, and a node that contradicts them will produce results the rest of the system does not expect.
Key result / practice
A bar stamped at the interval start includes observations occurring after that timestamp and before the next interval start. Its final OHLC is therefore known only after the interval has completed. Open, high, low and close use first, maximum, minimum and last observed values. For volume, the current aggregation calls sum(min_count=max(1,len(series))): when any required source observation is missing, the aggregate is missing. This strict rule differs from summing all available observations, and users should inspect missingness before interpreting volume. Bars whose OHLC remain missing are dropped. The data-source code rejects source bars that straddle a target interval rather than splitting them. Input timestamps are normalized to UTC in the load path. A causal control example in engine_contract.py shifts a position by one bar; that example does not establish that every executable node or fill path automatically shifts positions.
Why it matters for backtesting
A rule using that close must delay its decision until the interval finishes, then check the actual order and fill convention of the execution path used in the run. Inspect missing volume rather than converting it to zero: a single missing source entry can make the aggregate missing under the current rule. Preserve gaps and rejected straddling bars when aligning signals; simply counting rows can misstate elapsed time. Keep UTC timestamps consistent when adding session rules. Finally, test a proposed custom node in a real graph and inspect order timing before describing its behavior as an engine-wide guarantee. The shift in a control example is a useful test pattern, not proof for every node.
Source
read from this application's engine: stochastly/data_source.py (resampling and aggregation), stochastly/executor.py (time zone handling), stochastly/engine_contract.py (the causal control example). Primary source