Performance Attribution#

The top-level orchestration module. Its main() function coordinates the full attribution workflow: loading market and portfolio data, aligning date ranges, executing Brinson-Fachler and/or factor-model attribution, and optionally launching the interactive dashboard.

Performance Attribution Pipeline#

Main orchestration module for running multi-method portfolio performance attribution analysis.

This module provides the top-level main function that coordinates the full attribution workflow: loading market and portfolio data, aligning date ranges, executing Brinson-Fachler and/or factor-model attribution, and optionally launching an interactive dashboard.

Notes

The pipeline currently supports two attribution methodologies that can be enabled independently via the Configuration object:

  • Brinson-Fachler – decomposes active return into allocation and selection effects using sector/asset weights.

  • Factor Model – regresses portfolio returns against user-supplied factor return series and decomposes performance into factor exposures plus a residual (alpha).

All intermediate computations use PyArrow columnar tables for memory efficiency and vectorized operations.

Examples

>>> from kaxanuk.attribution_analysis.entities.configuration import Configuration
>>> from kaxanuk.attribution_analysis.performance_attribution import main
>>>
>>> config = Configuration(
...     input_directory="data/input",
...     weights_portfolio_directory="weights/portfolio",
...     weights_benchmark_directory="weights/benchmark",
...     benchmark_returns_directory="returns/benchmark",
...     investable_assets_directory="data/prices",
...     factor_returns_by_factor_directory="data/factors",
...     portfolio_file_name="portfolio_weights.csv",
...     benchmark_file_name="benchmark_weights.csv",
...     benchmark_return_file_name="benchmark_returns.csv",
...     user_column_date="date",
...     user_column_price="close",
...     market_data_input_format="csv",
...     portfolio_input_format="csv",
...     start_date="auto",
...     end_date="auto",
...     brinson_fachler_method=True,
...     factor_model_method=True,
... )
>>> main(config, launch_dashboard=True, dashboard_port=8050)
main(configuration: Configuration, *, launch_dashboard: bool = True, dashboard_port: int) → None[source]#

Run the full performance attribution pipeline.

Orchestrates data loading, date-range alignment, attribution computation, and optional dashboard visualisation for a portfolio defined by configuration.

Parameters:
  • configuration (Configuration) –

    Frozen dataclass holding all runtime settings including:

    • Directory paths – input_directory, weights_portfolio_directory, weights_benchmark_directory, benchmark_returns_directory, investable_assets_directory, factor_returns_by_factor_directory.

    • File names – portfolio_file_name, benchmark_file_name, benchmark_return_file_name.

    • Column mappings – user_column_date, user_column_price.

    • Input formats – market_data_input_format ("csv" | "parquet"), portfolio_input_format ("csv" | "excel").

    • Date range – start_date, end_date (datetime.date | "auto").

    • Method flags – brinson_fachler_method, factor_model_method (both bool).

  • launch_dashboard (bool, default True) – If True and the factor-model method is enabled, launch a Dash web application displaying interactive attribution charts and summary statistics. When False, static matplotlib plots are generated instead.

  • dashboard_port (int) – TCP port on which the Dash server listens when launch_dashboard=True. Required (no default); typically read from the configuration via ExcelConfigurator.get_dashboard_port().

Returns:

All outputs are side-effects: log messages, plots, and/or a running Dash server.

Return type:

None

Raises:
  • LicenseError – Raised before anything is read when the license does not validate (services.license_validator.validate_license()): one of LicenseNotFoundError, LicenseValidationError, LicenseServerError or LicenseConfigurationError.

  • FileNotFoundError – If any configured data directory or file does not exist.

  • ConfigurationError – If configuration contains invalid field values (raised during Configuration.__post_init__).

Notes

The function aligns all input tables (asset returns, portfolio weights, benchmark weights, benchmark returns, and factor returns) to the intersection of their date ranges before running any attribution calculation. This prevents shape mismatches and ensures consistent time-series indexing across methods.

The pipeline proceeds in four stages:

  1. Data loading – market prices, portfolio/benchmark weights, benchmark returns, and per-factor return series are read from disk using the appropriate input handlers.

  2. Date alignment – the common start/end dates across all tables are computed and each table is filtered accordingly.

  3. Attribution – enabled methods (Brinson-Fachler, Factor Model) are executed sequentially.

  4. Visualisation – results are either plotted (matplotlib) or served via an interactive Dash dashboard.

Examples

Run attribution without the dashboard (useful in batch/CI contexts):

>>> main(config, launch_dashboard=False)

Run only the Brinson-Fachler method with the dashboard disabled:

>>> config = Configuration(..., brinson_fachler_method=True,
...                        factor_model_method=False)
>>> main(config, launch_dashboard=False)