Library / Using Stochastly

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.

Source candles for GBPUSD and XAUUSD are read from the same bars used by this app run.
Source candles for GBPUSD and XAUUSD are read from the same bars used by this app run.

Evidence map

AspectFinding
What it isWhat the engine actually does with a bar, stated so that a custom node can be written to match it.
Key result / practiceResampling uses a left label and left-closed interval.
Why it matters for backtestingTreat 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

Related in the library