Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Nautechsystems Nautilus trader PortfolioAnalyzer Calculate Statistics

From Leeroopedia


Field Value
sources https://github.com/nautechsystems/nautilus_trader , https://nautilustrader.io/docs/
domains performance analysis, portfolio management, risk assessment
last_updated 2026-02-10 12:00 GMT

Overview

Concrete tool for computing post-trade portfolio performance statistics provided by NautilusTrader.

Description

The PortfolioAnalyzer class tracks account balances, positions, realized PnLs, and returns. Its calculate_statistics method is the primary entry point: given an Account and a list of Position objects, it captures starting and current balances, iterates over positions to accumulate realized PnL per currency and realized returns per timestamp, and sorts the return series chronologically. The analyzer supports a plugin registry of PortfolioStatistic objects; query methods (get_performance_stats_pnls, get_performance_stats_returns, get_performance_stats_general) iterate the registered statistics and produce dictionaries of computed values. Both Python and Rust (PyO3) statistic implementations are supported, with automatic type conversion between pandas Series and lists/dicts.

Usage

The PortfolioAnalyzer is typically accessed through engine.kernel.portfolio.analyzer after a backtest run. You can also instantiate it independently for custom analysis workflows.

Code Reference

  • Source location: nautilus_trader/analysis/analyzer.py, lines 33--525
  • Signature:
class PortfolioAnalyzer:
    def __init__(self) -> None

    def calculate_statistics(
        self,
        account: Account,
        positions: list[Position],
    ) -> None
  • Import:
from nautilus_trader.analysis.analyzer import PortfolioAnalyzer

I/O Contract

Inputs (calculate_statistics):

Parameter Type Required Description
account Account Yes The account object providing starting balances (via account.starting_balances()) and current total balances (via account.balances_total()).
positions list[Position] Yes List of positions (open and/or closed) to analyze. Each position provides realized_pnl, realized_return, and ts_closed.

Outputs / Side Effects:

Output Type Description
None (return) None Method populates internal state for subsequent queries.
_account_balances_starting dict[Currency, Money] Starting balances captured from the account.
_account_balances dict[Currency, Money] Current total balances captured from the account.
_realized_pnls dict[Currency, pd.Series] Per-currency realized PnL series indexed by position ID.
_returns pd.Series Time-indexed series of realized returns, sorted chronologically.

Key query methods after calculation:

Method Return Type Description
total_pnl(currency) float Total PnL (ending balance - starting balance + optional unrealized PnL).
total_pnl_percentage(currency) float Total PnL as a percentage of starting balance.
realized_pnls(currency) None Per-position realized PnL series for the given currency.
returns() pd.Series Raw returns time series.
get_performance_stats_pnls(currency) dict[str, float] All registered PnL-based statistics plus total PnL and total PnL%.
get_performance_stats_returns() dict[str, Any] All registered return-based statistics.
get_performance_stats_general() dict[str, Any] All registered position-based statistics.

Usage Examples

Accessing analysis after a backtest run:

from nautilus_trader.backtest.engine import BacktestEngine

engine = BacktestEngine()
# ... setup and run ...
engine.run()

# Access the analyzer through the portfolio
analyzer = engine.kernel.portfolio.analyzer

# Get PnL statistics for a specific currency
from nautilus_trader.model.currencies import USD
stats_pnl = analyzer.get_performance_stats_pnls(USD)
print(f"Total PnL: {stats_pnl['PnL (total)']}")
print(f"Total PnL%: {stats_pnl['PnL% (total)']}")

# Get return-based statistics
stats_returns = analyzer.get_performance_stats_returns()
for name, value in stats_returns.items():
    print(f"{name}: {value}")

Standalone usage with custom statistics:

from nautilus_trader.analysis.analyzer import PortfolioAnalyzer
from nautilus_trader.analysis.statistics.sharpe_ratio import SharpeRatio
from nautilus_trader.analysis.statistics.win_rate import WinRate

analyzer = PortfolioAnalyzer()
analyzer.register_statistic(SharpeRatio())
analyzer.register_statistic(WinRate())

# account and positions obtained from cache or engine
analyzer.calculate_statistics(account, positions)

# Query total PnL
total = analyzer.total_pnl()
total_pct = analyzer.total_pnl_percentage()
print(f"Total PnL: {total}, Total PnL%: {total_pct}%")

# Query registered return-based statistics
returns_stats = analyzer.get_performance_stats_returns()
print(f"Sharpe Ratio: {returns_stats.get('Sharpe Ratio')}")

Getting formatted output for logging:

for line in analyzer.get_stats_pnls_formatted(USD):
    print(line)

for line in analyzer.get_stats_returns_formatted():
    print(line)

for line in analyzer.get_stats_general_formatted():
    print(line)

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment