Numba Computation Engine
Relevant source files
The following files were used as context for generating this wiki page:
The Numba Computation Engine is the core performance layer of vectorbt, utilizing Just-In-Time (JIT) compilation to accelerate data-heavy trading strategy simulations and financial analytics. It provides a library of high-performance kernels that operate directly on NumPy arrays, circumventing Python's overhead for tight loops and complex mathematical operations.
This engine serves as the primary acceleration backend, though it works in tandem with an optional Rust engine. Users typically interact with these kernels through high-level accessors or indicator factories, while the internal architecture uses a dispatch system to choose between Numba and other available backends based on configuration and data compatibility.
Sources: README.md, vectorbt/_engine.py
Architecture and Dispatch Logic
The Numba engine is structured around specialized modules (typically suffixed with nb.py) containing njit-decorated functions. A centralized resolver manages the execution flow, determining whether to trigger a Numba kernel or an alternative backend.
Engine Resolution
The engine supports multiple execution modes: auto, numba, and rust. In auto mode, the system prioritizes the fastest available engine that supports the specific operation and input data types. If a specific engine is forced (e.g., engine="numba"), the resolver ensures the requested backend is used or raises an error if unavailable.
The diagram above illustrates how the resolve_engine function determines the execution path for a computation.
Sources: vectorbt/_engine.py:166-224, vectorbt/records/dispatch.py:20-30
Flexible Selection and Broadcasting
Numba kernels in vectorbt are designed to handle "flexible" data structures. The flex_select_auto_nb utility allows kernels to work with data that may be 0-dim (scalars), 1-dim (per-column parameters), or 2-dim (element-wise data) without pre-broadcasting them to the full input shape, significantly reducing memory consumption.
Sources: vectorbt/portfolio/nb.py:840-850, vectorbt/portfolio/nb.py:910-915
Portfolio Simulation Engine
The portfolio simulation module contains complex Numba kernels for executing orders, managing cash, and tracking positions across multiple assets and timeframes.
Order Processing Logic
The simulation engine processes orders through several stages: state validation, size resolution (handling targets, percentages, and amounts), and finally, execution against available cash and positions.
| Function | Purpose |
|---|---|
execute_order_nb | Core logic for calculating order outcomes based on state and constraints. |
buy_nb / sell_nb | Specialized kernels for long and short side executions. |
process_order_nb | Higher-level wrapper that manages logging and record-keeping during execution. |
update_value_nb | Updates the valuation price and total value of a position. |
Sources: vectorbt/portfolio/nb.py:65-350
Execution State Data Structures
Numba-compatible named tuples are used to track the simulation state efficiently.
- ExecuteOrderState: Tracks
cash,position,debt, andfree_cash. - ProcessOrderState: Extends the execution state with
val_price,value,oidx(order index), andlidx(log index).
Sources: vectorbt/portfolio/nb.py:270-300
This sequence shows the internal flow of a single order processing step within the Numba engine.
Sources: vectorbt/portfolio/nb.py:445-515
Generic and Returns Analytics
Beyond simulation, the Numba engine provides a suite of generic array processing and financial returns calculation functions.
Cumulative and Annualized Metrics
The returns engine implements standard financial formulas optimized for NumPy arrays.
@njit(cache=True)
def annualized_return_1d_nb(returns: tp.Array1d, ann_factor: float) -> float:
"""Mean annual growth rate of returns."""
if returns.shape[0] == 0:
return np.nan
end_value = cum_returns_final_1d_nb(returns, 1.0)
return end_value ** (ann_factor / returns.shape[0]) - 1
Sources: vectorbt/returns/nb.py:102-108
Key Analytics Kernels
| Module | Core Kernels |
|---|---|
| Generic | fillna_nb, bfill_nb, ffill_nb, rolling_mean_nb, expanding_max_nb |
| Returns | get_return_nb, sharpe_ratio_nb, sortino_ratio_nb, max_drawdown_nb |
| Portfolio | asset_flow_nb, trade_winning_streak_nb, get_positions_nb |
Sources: vectorbt/generic/nb.py, vectorbt/returns/nb.py, vectorbt/portfolio/nb.py
Performance Benchmarking
The project includes a dedicated benchmarking suite to compare Numba kernels against Rust implementations. Parity is maintained between engines to ensure identical results regardless of the backend.
- Check Parity: Benchmark cases verify output equivalence using
assert_allclosebefore timing. - Speedup Calculation:
speedup = numba_s / rust_s. Values above 1.0 indicate Rust is faster, while values below 1.0 indicate Numba superiority for that specific kernel. - Warmup: kernels are called untimed during a warmup phase to ensure JIT compilation overhead is not included in measurements.
Sources: benchmarks/bench_engine.py:1085-1125
Conclusion
The Numba Computation Engine provides the high-performance backbone for vectorbt. By leveraging JIT compilation and memory-efficient broadcasting techniques like flexible indexing, it enables large-scale backtesting and analytics that would be prohibitively slow in pure Python. The engine's architecture allows it to coexist seamlessly with other backends, providing a reliable fallback and reference implementation for the project's performance-critical paths.