Data types¶
The three first-class market-data containers. Each wraps a NumPy matrix and carries the symbol configuration used by the engines.
KlineData¶
KlineData
dataclass
¶
KlineData(symbol: str, data: ndarray, timeframe: 'int | str', tick_size: float = 0.01, tick_value: 'float | None' = None, contract_size: float = 1.0, digits: int | None = None, avg_spread: float = 0.0, volume_min: float = 0.01, volume_max: float = 100.0, volume_step: float = 0.01)
OHLC candle + turnover data for a symbol.
Attributes:
| Name | Type | Description |
|---|---|---|
symbol |
str
|
Symbol name |
data |
ndarray
|
[N x 7] array with columns: ts, open, high, low, close, volume, turnover (turnover may be NaN if unavailable) |
timeframe |
int | str
|
Candle duration. Accepts a timeframe string
('1m', '5m', '1h', '1d', etc.) or an integer number
of milliseconds, parsed via parse_timeframe(). The
standard recommended set is '1m', '15m', '1h',
'4h', '1d', '1w', '1mo' ('min'/'wk' are accepted
aliases for 'm'/'w'; 'mo' is a fixed 30-day month).
The normalized duration in ms is exposed read-only
as |
tick_size |
float
|
Minimum price step |
tick_value |
float
|
Monetary value per tick. Defaults to tick_size (so PnL per unit equals the price difference, like backtesting.py). |
contract_size |
float
|
Contract size |
digits |
int
|
Decimal places for price |
avg_spread |
float
|
Average spread in ticks |
Example
klines_btc = KlineData( symbol='BTCUSDT', data=btc_matrix, timeframe='5m', tick_size=0.01, ) klines_eth = KlineData( symbol='ETHUSDT', data=eth_matrix, timeframe=60_000, tick_size=0.01, ) bt = BacktestEngine.by_klines( MyStrategy(), data = (klines_btc, klines_eth), ) bt.run()
config
property
¶
Build SymbolConfig for passing to broker.add_symbol().
Returns:
| Name | Type | Description |
|---|---|---|
SymbolConfig |
SymbolConfig
|
Configuration object with this symbol's parameters |
interval_ms
property
¶
Candle duration in milliseconds (normalized from timeframe).
resample ¶
Resample candles to higher timeframe without mutating self.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timeframe
|
int or str
|
Target timeframe as a string ('1h', '4h', etc., standard set: '1m', '15m', '1h', '4h', '1d', '1w', '1mo') or an integer number of milliseconds. Must be a multiple of self.interval_ms; if not, adjusted to next multiple (with warning) |
required |
Returns:
| Name | Type | Description |
|---|---|---|
KlineData |
'KlineData'
|
New KlineData at higher interval, config propagated |
Example
klines_1h = klines_1m.resample('1h')
Source code in src/tradetropy/core/data_types.py
save ¶
Save klines to file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Destination file path. |
required | |
format
|
Output format ('csv', 'parquet', 'hdf5', 'npz'). None (default) infers from the extension, falling back to 'npz'. |
None
|
|
**kwargs
|
Extra arguments passed to save_klines() (ts_format, hdf5_key, compression, include_partial). |
{}
|
Returns:
| Type | Description |
|---|---|
|
pd.DataFrame: The saved kline data. |
Example
klines.save('btc_1h.h5') klines.resample('1h').save('btc_1h.parquet', format='parquet')
Source code in src/tradetropy/core/data_types.py
head ¶
tail ¶
filter ¶
filter(mask: 'np.ndarray | Callable | None' = None, *, start: 'str | int | None' = None, end: 'str | int | None' = None, idx_start: 'int | None' = None, idx_end: 'int | None' = None) -> 'KlineData'
Filter klines without mutating the original.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mask
|
'np.ndarray | Callable | None'
|
Boolean array [N] or callable |
None
|
start
|
'str | int | None'
|
Start date ('2024-01-01', '2024-01-01 10:30') or ms timestamp. |
None
|
end
|
'str | int | None'
|
End date (same format), inclusive. |
None
|
idx_start
|
int | None
|
Positional index range start, inclusive. |
None
|
idx_end
|
int | None
|
Positional index range end, exclusive. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
KlineData |
'KlineData'
|
New KlineData with the same metadata. |
Example
klines.filter(start='2024-01-01', end='2024-01-31') klines.filter(idx_start=1000, idx_end=2000) klines.filter(mask=klines.data[:, 5] > 100) klines.filter(lambda d: d[:, 4] > 50000)
Source code in src/tradetropy/core/data_types.py
to_df ¶
Build a pandas DataFrame of the candles (a fresh copy each call).
Returns:
| Type | Description |
|---|---|
|
pd.DataFrame: Columns OHLCV_TURNOVER_COLS (ts, open, high, low, close, volume, turnover) plus a 'datetime' column from 'ts'. |
Example
df = klines.to_df()
Source code in src/tradetropy/core/data_types.py
TickData¶
TickData
dataclass
¶
TickData(symbol: str, data: ndarray, tick_size: float = 0.01, tick_value: 'float | None' = None, contract_size: float = 1.0, digits: int | None = None, avg_spread: float = 0.0, volume_min: float = 0.01, volume_max: float = 100.0, volume_step: float = 0.01)
Tick data for a symbol.
Attributes:
| Name | Type | Description |
|---|---|---|
symbol |
str
|
Symbol name (e.g. 'BTCUSDT', 'MES') |
data |
ndarray
|
[N x 7] array with columns: ts, bid, ask, volume, flags, volume_real, price |
tick_size |
float
|
Minimum price step (e.g. 0.25 for MES, 0.01 for forex) |
tick_value |
float
|
Monetary value per tick per contract (e.g. 1.25 for MES). Defaults to tick_size (so PnL per unit equals the price difference, like backtesting.py). |
contract_size |
float
|
Contract size (1 for most) |
digits |
int
|
Decimal places for price normalization |
avg_spread |
float
|
Average spread in ticks |
Example
ticks = TickData( symbol='BTCUSDT', data=tick_matrix, tick_size=0.01, ) bt = BacktestEngine.by_ticks(MyStrategy(), data=(ticks,)) bt.run()
config
property
¶
Build SymbolConfig for passing to broker.add_symbol().
Returns:
| Name | Type | Description |
|---|---|---|
SymbolConfig |
SymbolConfig
|
Configuration object with this symbol's parameters |
to_klines ¶
to_klines(interval_ms, *, include_partial: bool = False, price_source: str = 'price', volume_source: str = 'volume') -> 'KlineData'
Convert ticks to KlineData without mutating self.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
interval_ms
|
int or str
|
Target duration in milliseconds or string format. Accepts ms (int) or str ('5m', '1h') |
required |
include_partial
|
bool
|
Include the current incomplete candle (default False) |
False
|
price_source
|
str
|
Price column - 'price' (default), 'mid' for (bid+ask)/2, or 'trade' to use the price column but first drop quote-only ticks (volume == 0), keeping only real trades |
'price'
|
volume_source
|
str
|
Volume column - 'volume' (default) or 'volume_real' |
'volume'
|
Returns:
| Name | Type | Description |
|---|---|---|
KlineData |
'KlineData'
|
New KlineData with candles, symbol config propagated |
Example
klines = ticks.to_klines('5m')
Source code in src/tradetropy/core/data_types.py
save ¶
Save ticks to file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Destination file path. |
required | |
format
|
Output format ('csv', 'parquet', 'hdf5', 'npz'). None (default) infers from the extension, falling back to 'npz'. |
None
|
|
**kwargs
|
Extra arguments passed to save_ticks() (ts_format, hdf5_key, compression). |
{}
|
Returns:
| Type | Description |
|---|---|
|
pd.DataFrame: The saved tick data. |
Example
ticks.save('btc_ticks.h5') ticks.save('btc_ticks.parquet', format='parquet')
Source code in src/tradetropy/core/data_types.py
head ¶
tail ¶
filter ¶
filter(mask: 'np.ndarray | Callable | None' = None, *, start: 'str | int | None' = None, end: 'str | int | None' = None, idx_start: 'int | None' = None, idx_end: 'int | None' = None) -> 'TickData'
Filter ticks without mutating the original.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mask
|
'np.ndarray | Callable | None'
|
Boolean array [N] or callable |
None
|
start
|
'str | int | None'
|
Start date ('2024-01-01', '2024-01-01 10:30') or ms timestamp. |
None
|
end
|
'str | int | None'
|
End date (same format), inclusive. |
None
|
idx_start
|
int | None
|
Positional index range start, inclusive. |
None
|
idx_end
|
int | None
|
Positional index range end, exclusive. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
TickData |
'TickData'
|
New TickData with the same metadata. |
Example
ticks.filter(start='2024-01-01', end='2024-01-31') ticks.filter(start='2024-01-01 10:00:00') ticks.filter(idx_start=1000, idx_end=2000) ticks.filter(mask=ticks.data[:, 3] > 0) ticks.filter(lambda d: d[:, 1] > 50000)
Source code in src/tradetropy/core/data_types.py
to_df ¶
Build a pandas DataFrame of the ticks (a fresh copy each call).
Returns:
| Type | Description |
|---|---|
|
pd.DataFrame: Columns TICK_COLS (ts, bid, ask, volume, flags, volume_real, price) plus a 'datetime' column derived from 'ts'. |
Example
df = ticks.to_df()
Source code in src/tradetropy/core/data_types.py
BookData¶
BookData
dataclass
¶
L2 order-book (depth) data for a symbol.
Stored as a flat [N x (2 + 4*levels)] matrix (mirroring TickData/KlineData's
flat layout) so it persists and replays the same way. Each row is one book
event in the layout described by :func:book_flat_columns.
Attributes:
| Name | Type | Description |
|---|---|---|
symbol |
str
|
Symbol name. |
data |
ndarray
|
[N x (2 + 4*levels)] flat book rows. |
levels |
int
|
Number of levels K retained per side. |
tick_size |
float
|
Minimum price step. |
Example
book = BookData('BTCUSDT', rows, levels=10, tick_size=0.01) book.bid_px[-1] # best-N bid prices of the last event
best_bid
property
¶
Best (top-of-book) bid price per event [N].
Level 0 is the best level in the flat layout, so this is the first bid column. NaN where the bid side is empty. Mirrors OrderbookProxy.best_bid as a full series.
best_ask
property
¶
Best (top-of-book) ask price per event [N].
Level 0 is the best level in the flat layout, so this is the first ask column. NaN where the ask side is empty. Mirrors OrderbookProxy.best_ask as a full series.
mid
property
¶
Mid price per event [N]: (best_bid + best_ask) / 2.
NaN where either side is missing (NumPy NaN propagation). Mirrors OrderbookProxy.mid as a full series.
spread
property
¶
Spread per event [N]: best_ask - best_bid.
NaN where either side is missing (NumPy NaN propagation). Mirrors OrderbookProxy.spread as a full series.
save ¶
Save order-book rows to file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Destination file path. |
required | |
format
|
Output format ('csv', 'parquet', 'hdf5', 'npz'). None (default) infers from the extension, falling back to 'npz'. |
None
|
|
**kwargs
|
Extra arguments passed to save_book() (layout, ts_format, hdf5_key, compression, metadata). |
{}
|
Returns:
| Type | Description |
|---|---|
|
pd.DataFrame: The saved book data. |
Example
book.save('btc_book.h5') book.save('btc_book.parquet', format='parquet') book.save('btc_bookdepth.csv', format='csv', layout='long')
Source code in src/tradetropy/core/data_types.py
to_df ¶
Build a pandas DataFrame of the book events (a fresh copy each call).
Returns:
| Type | Description |
|---|---|
|
pd.DataFrame: Columns from book_flat_columns(self.levels) (ts, kind, bid_px_/bid_sz_/ask_px_/ask_sz_) plus a 'datetime' column derived from 'ts'. |
Example
df = book.to_df()
Source code in src/tradetropy/core/data_types.py
head ¶
tail ¶
filter ¶
filter(mask: 'np.ndarray | Callable | None' = None, *, start: 'str | int | None' = None, end: 'str | int | None' = None, idx_start: 'int | None' = None, idx_end: 'int | None' = None) -> 'BookData'
Filter book events without mutating the original.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mask
|
'np.ndarray | Callable | None'
|
Boolean array [N] or callable |
None
|
start
|
'str | int | None'
|
Start date ('2024-01-01', '2024-01-01 10:30') or ms timestamp. |
None
|
end
|
'str | int | None'
|
End date (same format), inclusive. |
None
|
idx_start
|
int | None
|
Positional index range start, inclusive. |
None
|
idx_end
|
int | None
|
Positional index range end, exclusive. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
BookData |
'BookData'
|
New BookData with the same metadata (levels, tick_size). |
Example
book.filter(start='2024-01-01', end='2024-01-31') book.filter(idx_start=1000, idx_end=2000) book.filter(lambda d: d[:, 1] == 0) # snapshots only