5.0 KiB
TBarSeries: OHLCV Data Container
| Property | Value |
|---|---|
| Category | Core |
| Inputs | OHLCV bar (TBar) |
| Parameters | None |
| Outputs | Multiple series (Open, High, Low, Close, Volume) |
| Output range | Varies (see docs) |
| Warmup | 1 bar |
TBarSeriesis a high-performance collection of OHLCV bars.- No configurable parameters; computation is stateless per bar.
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
What It Does
TBarSeries is a high-performance collection of OHLCV bars. It is the primary data structure for managing historical and real-time market data in QuanTAlib. It uses a Structure of Arrays (SoA) layout to optimize memory access and enable efficient SIMD operations across individual price components.
Design Philosophy
A naive implementation of a bar series would be a List<TBar>. However, this is inefficient for technical analysis. Most indicators only need one component at a time (e.g., SMA uses Close prices). Iterating over a List<TBar> to get Close prices loads unnecessary Open, High, Low, and Volume data into the CPU cache, wasting bandwidth.
TBarSeries solves this by storing each component in its own contiguous array. This allows:
- Component Views: You can access
Closeprices as aTSerieswithout copying data. - Cache Efficiency: Iterating over
Closeprices loads only Close prices. - Unified Time: All component series share a single Time array, ensuring synchronization.
How It Works
Internally, TBarSeries maintains six parallel lists:
_t(Time)_o(Open)_h(High)_l(Low)_c(Close)_v(Volume)
It exposes these internal lists as TSeries properties (Open, High, Low, Close, Volume), which act as read-only views into the master data.
Structure
Definition
public class TBarSeries : IReadOnlyList<TBar>
{
// Component Views (TSeries)
public TSeries Open { get; }
public TSeries High { get; }
public TSeries Low { get; }
public TSeries Close { get; }
public TSeries Volume { get; }
// Aliases
public TSeries O => Open;
public TSeries H => High;
public TSeries L => Low;
public TSeries C => Close;
public TSeries V => Volume;
}
Core Methods
| Method | Description |
|---|---|
Add(TBar bar, bool isNew) |
Adds a bar or updates the last one. |
Add(DateTime time, double o, double h, double l, double c, double v) |
Adds raw values directly. |
Count |
Returns the number of bars. |
Last |
Returns the most recent TBar. |
Usage
Creating and Populating
var bars = new TBarSeries();
// Add a new bar
bars.Add(new TBar(DateTime.UtcNow, 100, 105, 95, 102, 1000));
// Add raw values
bars.Add(DateTime.UtcNow, 100, 105, 95, 102, 1000);
Accessing Data
// Get the last full bar
TBar lastBar = bars.Last;
// Get the Close series (Zero-Copy)
TSeries closes = bars.Close;
// Calculate SMA on Close prices
var sma = new Sma(14);
var result = sma.Calculate(bars.Close);
Streaming Updates
// New minute starts
bars.Add(newBar, isNew: true);
// Price updates within the same minute
bars.Add(updatedBar, isNew: false); // Updates the last bar in place
Performance Profile
Operation Count (Streaming Mode)
TBarSeries stores OHLCV as separate List fields (SoA layout) for cache-friendly sequential access.
| Operation | Count | Cost (cycles) | Subtotal |
|---|---|---|---|
| Add new TBar (5 List.Add calls) | 5 | 3 cy | ~15 cy |
| Access span for SIMD | 1 | 2 cy | ~2 cy |
| Pub event fire | 1 | 5 cy | ~5 cy |
| Total per bar | O(1) | — | ~22 cy |
SoA layout enables SIMD processing: each field array is contiguous in memory. CollectionsMarshal.AsSpan avoids copying.
- Memory Layout: SoA (Structure of Arrays).
- Component Access: Zero-copy
TSeriesviews. - Iteration: Cache-friendly for single-component analysis.
Integration
TBarSeries is the standard input for multi-input indicators (like ATR, ADX) and the primary data source for trading strategies.
- Indicators: Can be passed to indicators that require full bar data.
- Strategies: Provides the historical context needed for signal generation.
Architecture Notes
- Shared Storage: The
TSeriesviews (Open,Close, etc.) do not own their data; they point to the internal lists of theTBarSeries. This means modifying theTBarSeriesautomatically updates all views. - Synchronization: Because all views share the same
_t(Time) list, they are guaranteed to be perfectly synchronized.