Returns & Metrics Analytics
Relevant source files
The following files were used as context for generating this wiki page:
Returns and metrics analytics within the vectorbt framework provide a high-performance system for evaluating the risk and performance of trading strategies. This system is built upon a modular architecture of mixins that allow for the dynamic calculation, filtering, and aggregation of performance statistics across multi-column, vectorized data. The core objective is to transform raw simulation data—such as order records and price series—into actionable insights like Sharpe ratios, drawdown profiles, and trade-level statistics.
The analytics engine leverages Numba and an optional Rust engine to accelerate mathematical kernels, ensuring that even large-scale parameter sweeps can be analyzed in seconds. It provides a standardized interface via the .stats() and .plots() methods, which are available across various objects including portfolios, trades, and drawdowns.
Sources: vectorbt/portfolio/base.py:1-68, README.md
Analytics Architecture
The metrics system is powered by the StatsBuilderMixin, which implements a flexible framework for defining and computing performance metrics. This architecture allows developers to request specific metrics by name or tag, apply custom filters, and aggregate results across groups or assets.
Calculation Logic Flow
When a user calls .stats(), the system follows a structured pipeline:
- Defaults Resolution: Merges global settings with method-specific overrides.
- Metric Selection: Filters the requested metrics based on provided tags (e.g., "returns", "trades") or predefined boolean checks (e.g.,
check_has_freq). - Argument Resolution: Dynamically maps required arguments (like
group_by,freq, orinit_cash) to the calculation functions. - Execution: Computes the values, utilizing a built-in cache to prevent redundant calculations of overlapping metrics.
- Post-processing & Aggregation: Applies transformations (e.g., multiplying by 100 for percentages) and aggregates multiple columns into a single summary series if required.
Sources: vectorbt/generic/stats_builder.py:91-380
The following diagram illustrates the metric calculation pipeline within StatsBuilderMixin:
The system manages metrics through a Config object that defines the logic for each performance indicator.
| Component | Description | Source |
|---|---|---|
metrics | A Config dictionary mapping metric names to their calculation logic. | stats_builder.py:64-77 |
calc_func | The core function (or attribute path) used to compute the specific metric. | stats_builder.py:116-128 |
agg_func | Function used to aggregate metrics across columns (defaults to np.mean). | stats_builder.py:186-193 |
tags | Associations used to group metrics for easy selection (e.g., "risk", "portfolio"). | stats_builder.py:108-110 |
Portfolio Performance Metrics
The Portfolio class defines an extensive suite of metrics derived from simulated order history and asset valuation. These are categorized into general performance, risk-adjusted returns, and exposure metrics.
Key Performance Indicators
- Total Return: Calculated as the final portfolio value relative to initial cash.
- Benchmark Return: The return achieved by a buy-and-hold strategy on the same asset.
- Max Drawdown: The largest peak-to-trough decline in portfolio value.
- Sharpe/Sortino Ratios: Risk-adjusted performance measures that require a defined frequency for annualization.
Sources: vectorbt/portfolio/base.py:1584-1715
Exposure and Flow Analysis
The analytics engine tracks how capital and assets flow through the strategy:
- Asset Flow: Total transacted amount of assets at each time step.
- Cash Flow: The movement of cash, including "free cash" which accounts for locked capital during shorting.
- Gross Exposure: The sum of absolute position values divided by total portfolio value.
Sources: vectorbt/portfolio/base.py:1330-1425
Trade & Position Analytics
Metrics can be computed specifically for "Trades" (individual entry/exit pairs) or "Positions" (continuous periods in the market). The Trades class extends the generic Ranges system to provide specialized profitability metrics.
Profitability Metrics
| Metric | Calculation Logic | Source |
|---|---|---|
| Win Rate | winning.count() / total.count() | trades.py:201-207 |
| Profit Factor | total_win_pnl / abs(total_loss_pnl) | trades.py:210-221 |
| Expectancy | (win_rate * avg_win) - (loss_rate * avg_loss) | trades.py:224-234 |
| SQN | sqrt(count) * mean_pnl / std_pnl | trades.py:237-243 |
Streak Analysis
The system tracks winning and losing streaks at each trade point to assess strategy consistency. These are implemented using optimized kernels (optionally in Rust for speed).
Sources: vectorbt/portfolio/trades.py:190-199, rust/src/portfolio.rs:608-646
The following class diagram shows the relationship between trade-related record containers and the metrics system:
Visualization Analytics
The PlotsBuilderMixin provides a parallel infrastructure to the stats system for generating interactive Plotly visualizations. It allows for the construction of multi-panel figures where each subplot visualizes a different aspect of strategy performance.
Standard Subplots
- Orders: Price chart with buy/sell markers.
- Trade PnL: Distribution of profit and loss across trades.
- Cumulative Returns: Comparison of strategy returns vs. benchmark.
- Underwater Plot: Visualization of drawdowns over time.
Sources: vectorbt/portfolio/base.py:1865-1970, vectorbt/generic/plots_builder.py:72-132
Visualization Logic
The plotting engine automatically manages:
- Shared X-Axes: Synchronizing time axes across multiple subplots.
- Legend Grouping: Consolidating identical labels from different subplots.
- Automatic Sizing: Scaling the figure height based on the number of requested subplots.
Sources: vectorbt/generic/plots_builder.py:280-360
Mathematical Kernels
The precision of metrics analytics depends on underlying mathematical kernels. vectorbt uses high-precision routines for return calculations, ensuring stability even with zero or negative values.
Return Calculation
Returns are calculated as (output_value - input_value) / input_value. The system handles edge cases where input_value is zero by returning inf with the appropriate sign to maintain numerical consistency during vectorization.
Sources: rust/src/portfolio.rs:77-88
# Example of return calculation logic in the Rust engine
def get_return(input_value, output_value):
if input_value == 0.0:
if output_value == 0.0:
return 0.0
return float('inf') * np.sign(output_value)
r = (output_value - input_value) / input_value
if input_value < 0.0:
r *= -1.0
return r
Sources: rust/src/portfolio.rs:77-88
Summary
Returns & Metrics Analytics in vectorbt transforms large-scale simulation data into structured performance summaries and interactive visualizations. By utilizing a mixin-based architecture (StatsBuilderMixin and PlotsBuilderMixin), the project provides a unified interface for calculating everything from basic returns to complex risk-adjusted ratios and trade streaks. The integration of high-performance Rust and Numba kernels ensures that these analytics remain efficient even when processing thousands of strategy iterations simultaneously.