Overview
tzutrader is an experimental C++ backtesting library for trading strategies. This documentation covers the public API and internal components.
Note: This is an experimental project. The API is subject to change as I explore and refine different design approaches.
Project Links
Library Components
Core Data Types (defs.h)
Defines fundamental data structures used throughout the library:
- Ohlcv: Open-High-Low-Close-Volume candlestick data
- Tick: Individual trade data points
- SingleValue: Generic time-series data
- Signal: Trading signals generated by strategies
- Side: Trade direction (BUY/SELL/NONE)
Indicators (indicators.h)
Technical indicators that process market data incrementally using circular buffers:
- SMA: Simple Moving Average
- EMA: Exponential Moving Average
- RSI: Relative Strength Index
- MACD: Moving Average Convergence Divergence
- MVar: Moving Variance
All indicators follow a consistent interface:
- get(): Returns the current indicator value
- update(value): Processes a new data point and returns updated value
Indicators return NaN until enough data has been collected to compute a valid result.
Strategies (strategies.h)
Trading strategies that generate buy/sell signals based on indicators:
- SMACrossover: Crossover strategy using two moving averages
- RSIStrat: RSI-based strategy with overbought/oversold thresholds
- MACDStrat: MACD line and signal line crossover strategy
Strategies implement the update() method which receives market data and returns a Signal object.
Portfolio Management (portfolios.h)
Portfolio classes that manage positions, cash, and risk:
- BasicPortfolio: Implements transaction costs, stop-loss, and take-profit
The portfolio receives signals from strategies and decides whether to execute trades, applying risk management rules and tracking performance metrics.
Data Streaming (streamers.h)
Input data parsers and streamers:
- Csv: Generic CSV file reader with specialized parsers via CsvParseTraits
Streamers provide STL-compatible iterators for processing data point-by-point without loading entire datasets into memory.
Runners (runners.h)
Orchestration classes that connect all components:
- BasicRunner: Coordinates data streaming, strategy updates, and portfolio management
The runner feeds data to the strategy, passes signals to the portfolio, and manages the backtesting loop.
Performance Statistics (stats.h)
Performance metric calculation:
- PortfolioStats: Computes returns, Sharpe ratio, max drawdown, win rate, etc.
Architecture Principles
Streaming Processing
The library processes data incrementally rather than loading everything into memory. This:
- Mimics real-world trading constraints
- Prevents look-ahead bias
- Keeps memory usage bounded
- Scales to large datasets
Composability
Components can be mixed and matched:
- Any strategy works with any portfolio
- Strategies combine multiple indicators
- Custom components follow the same interfaces
Static Polymorphism
The library uses templates and CRTP (Curiously Recurring Template Pattern) instead of virtual functions for zero-overhead abstraction.
Quick Start Example
int main() {
portfolio, strategy, csv
);
runner.run(false);
return 0;
}
Definition portfolios.h:35
Definition streamers.h:176
Definition strategies.h:68
Main header file for the tzutrader library.
Build and run:
cat data/prices.csv | ./my_backtest
Extending the Library
Custom Indicators
Inherit from Indicator<YourClass, InputType, OutputType> and implement:
- get() const noexcept: Return current value
- update(input): Process new data point
Custom Strategies
Inherit from Strategy<YourClass, DataType> and implement:
- update(const DataType& data): Generate trading signal
Custom Portfolios
Inherit from Portfolio<YourClass> and implement:
- update(const Signal& signal): Handle trading signals
Custom Data Sources
Create a class with begin() and end() methods that return iterators yielding data points. Optionally specialize CsvParseTraits for custom CSV formats.
Performance Characteristics
- Memory: O(window_size) for indicators, O(positions) for portfolio
- Time: O(1) per data point after indicator warmup
- Throughput: Processes millions of data points efficiently
Thread Safety
Components are not thread-safe and maintain mutable state. For parallel backtesting:
- Run separate instances in different threads
- Each instance has its own data streamer, strategy, and portfolio
- No shared state between instances
Known Limitations
As an experimental project:
- Single asset trading only
- All-in/all-out position management
- Market orders only (no limit/stop orders)
- No slippage modeling
- CSV input only currently
- Minimal error handling
These limitations help keep the core design simple and focused.
Getting Help
- Read the User Guide for tutorials and examples
- Check the Architecture Guide for design details
- Browse the header files - they contain detailed comments
- Look at examples in the examples/ directory
Contributing
This is an experimental project exploring backtesting library design. Feedback, suggestions, and criticism are welcome!
License
See the repository for license information.