Bar utilities
Utilities for preparing and transforming historical price bars before using them with indicators.
Use alternate price
bars.Use() selects which price element to analyze before most indicator calls — for example the median (HL2) or typical (HLC3) price instead of Close. It cannot be used with indicators that require the full OHLCV bar profile.
// median price (HL2) into an SMA
var results = bars
.Use(CandlePart.HL2)
.ToSma(20);candlePart — the price element to use for calculations.
CandlePart enum options
| enum | int | description |
|---|---|---|
CandlePart.Open | 0 | Open price |
CandlePart.High | 1 | High price |
CandlePart.Low | 2 | Low price |
CandlePart.Close | 3 | Close price |
CandlePart.Volume | 4 | Volume |
CandlePart.HL2 | 5 | (High+Low)/2 |
CandlePart.HLC3 | 6 | (High+Low+Close)/3 |
CandlePart.OC2 | 7 | (Open+Close)/2 |
CandlePart.OHL3 | 8 | (Open+High+Low)/3 |
CandlePart.OHLC4 | 9 | (Open+High+Low+Close)/4 |
🚩 Incompatible indicators
Some indicators require the full OHLCV bar profile and cannot be used with .Use():
- Indicators that explicitly use multiple price points (ATR, Stochastic, etc.)
- Volume-based indicators (OBV, CMF, etc.) unless using
CandlePart.Volume - Candlestick pattern indicators
The bar-part selector also has incremental and live streaming variants that emit TimeValue results:
// BufferList — incremental, single-threaded
BarPartList parts = bars.ToBarPartList(CandlePart.HL2);
// StreamHub — chain into a live pipeline
BarHub barHub = new();
BarPartHub partHub = barHub.ToBarPartHub(CandlePart.HLC3);
EmaHub emaHub = partHub.ToEmaHub(20); // chain downstream indicatorsSee Buffer lists and Stream hubs for full usage guides.
Sort bars
bars.ToSortedList() sorts any collection of TBar (or ISeries) and returns an IReadOnlyList ordered by ascending Timestamp. Library indicators expect chronological bars, so use this when you cannot guarantee the sort order from your data source.
// sort, then use inline with indicators
var results = bars
.ToSortedList()
.ToRsi(14);Pre-sorted data
Most providers already return bars in chronological order. Sorting large datasets has a cost, so skip this step when the order is guaranteed.
Validate bar history
bars.Validate() is an advanced check of your IReadOnlyList<IBar>. It detects duplicate timestamps and out-of-sequence (non-ascending) dates, throwing an InvalidBarsException if either is found. On success it returns the validated collection, so it can be used inline.
try
{
var results = bars
.Validate()
.ToRsi(14);
}
catch (InvalidBarsException ex)
{
Console.WriteLine($"Invalid bars: {ex.Message}");
}When to use
.Validate() performs thorough checks and has a cost. Use it when data quality is uncertain — importing from untrusted sources, production data-quality gates, or debugging unexpected results — but avoid re-validating the same dataset repeatedly. To simply fix ordering, use Sort bars instead.
Resize bar history
bars.Aggregate() combines intraday bars into larger timeframes — minute to hourly, hourly to daily, or any custom TimeSpan.
// using the BarInterval enum
IReadOnlyList<Bar> hourlyBars = minuteBars.Aggregate(BarInterval.OneHour);
// using a custom TimeSpan
IReadOnlyList<Bar> customBars = minuteBars.Aggregate(TimeSpan.FromMinutes(45));| param | type | description |
|---|---|---|
newSize | BarInterval | Target period size: Month, Week, Day, FourHours, TwoHours, OneHour, ThirtyMinutes, FifteenMinutes, FiveMinutes, ThreeMinutes, TwoMinutes, OneMinute. |
timeSpan | TimeSpan | Any value greater than TimeSpan.Zero, for custom periods. |
Each aggregated bar takes the first Open, highest High, lowest Low, last Close, summed Volume, and the period's starting Timestamp.
🚩 Partially populated periods
Partial period windows at the start, end, or market open/close can be misleading. For example, a lone 4:00pm minute bar aggregated into 15-minute bars yields a 4:00pm bar holding just one minute of data, while the prior 3:45pm bar holds the full 15 minutes. Filter out partial periods if they could skew your analysis.
Streaming aggregator hubs
For live feeds, the aggregator hubs convert small bars or raw ticks into larger period bars in real time. Both accept a BarInterval or custom TimeSpan (BarInterval.Month is not supported in streaming — use the TimeSpan overload):
// bar → bar (e.g. 1-minute bars to 5-minute bars)
BarHub barHub = new();
BarAggregatorHub fiveMinHub = barHub.ToBarAggregatorHub(BarInterval.FiveMinutes);
// tick → bar (raw trades to 1-minute OHLCV)
TradeTickHub tickHub = new();
TradeTickAggregatorHub oneMinHub = tickHub.ToTradeTickAggregatorHub(BarInterval.OneMinute);Both aggregator hubs accept an optional fillGaps flag (default false): when true, synthetic zero-volume bars bridge silent buckets, carrying the prior bar's Close into Open, High, Low, and Close. Consumers needing a different gap policy should pre-process the upstream stream; a native GapFillMode enum is on the v3.1 roadmap.
Extended candle properties
bar.ToCandle() and bars.ToCandles() convert a bar into an extended CandleProperties format with additional calculated candle measurements (body size, wicks, etc.).
// single bar
CandleProperties candle = bar.ToCandle();
// collection of bars
IReadOnlyList<CandleProperties> candles = bars.ToCandles();
// access extended properties
decimal? bodySize = candle.Body;
decimal? upperWick = candle.UpperWick;
bool isBullish = candle.IsBullish;CandleProperties
The CandleProperties record class extends the basic Bar type with calculated properties.
| property | type | description |
|---|---|---|
Timestamp | DateTime | Close date |
Open | decimal | Open price |
High | decimal | High price |
Low | decimal | Low price |
Close | decimal | Close price |
Volume | decimal | Volume |
Size | decimal | High-Low |
Body | decimal | |Open-Close| |
UpperWick | decimal | Upper wick size |
LowerWick | decimal | Lower wick size |
BodyPct | double | Body/Size |
UpperWickPct | double | UpperWick/Size |
LowerWickPct | double | LowerWick/Size |
IsBullish | bool | Close>Open direction |
IsBearish | bool | Close<Open direction |
See also
- Result utilities — work with indicator results after calculation
- Additional helper utilities — math and numerical methods for custom indicators
- Indicator catalog — discover indicator metadata programmatically