Calculate the Brinson-Fachler attribution of the portfolio’s return over the benchmark, by sector, over the Toolkit’s date range. The excess return is split into three effects per sector:

  • Allocation: the reward for overweighting sectors that beat the benchmark (and underweighting those that lagged).
  • Selection: the reward for holding better stocks than the benchmark within a sector.
  • Interaction: the combined effect of both decisions.

The portfolio’s sector returns come from its holdings (buy and hold from the start date). The benchmark’s sector weights come from the benchmark fund and its sector returns from the Select Sector SPDR funds (XLK, XLF, XLV, …), which track the sectors of the S&P 500.

For more information, see the following papers:

  • Brinson, G.P. and Fachler, N. (1985). “Measuring Non-US Equity Portfolio Performance.” The Journal of Portfolio Management, 11(3), 73-76.
  • Brinson, G.P., Hood, L.R. and Beebower, G.L. (1986). “Determinants of Portfolio Performance.” Financial Analysts Journal, 42(4), 39-44.

Also known as: performance attribution, BHB attribution, sector attribution.

Brinson Attribution in Python or via the MCP

Install the Finance Toolkit with:

pip install financetoolkit -U

Then call get_brinson_attribution as shown below.

from financetoolkit import Toolkit

toolkit = Toolkit(
    ["AAPL", "MSFT", "JNJ", "XOM", "JPM"],
    api_key="FINANCIAL_MODELING_PREP_KEY",
    start_date="2025-01-01",
    end_date="2025-12-31",
)

toolkit.portfolio.get_brinson_attribution()

Or, after setting up the Finance Toolkit MCP, ask:

Which sector allocation and stock selection effects explain how an equal-weight portfolio of Apple, Microsoft, Johnson & Johnson, ExxonMobil and JPMorgan Chase did against the S&P 500 in 2025?

Which returns:

Sector Portfolio Weight Benchmark Weight Portfolio Return Benchmark Return Allocation Effect Selection Effect Interaction Effect Total Effect
Basic Materials 0 0.017 nan 0.1115 0.0012 0 -0 0.0012
Communication Services 0 0.0923 nan 0.2249 -0.0042 0 -0 -0.0042
Consumer Cyclical 0 0.0896 nan 0.0881 0.0082 0 -0 0.0082
Consumer Defensive 0 0.0495 nan 0.0183 0.008 0 -0 0.008
Energy 0.2 0.0373 0.1625 0.0661 -0.0185 0.0036 0.0157 0.0008
Financial Services 0.2 0.1208 0.371 0.152 -0.0022 0.0265 0.0173 0.0416
Healthcare 0.2 0.0994 0.4809 0.1447 -0.0035 0.0334 0.0338 0.0637
Industrials 0 0.0803 nan 0.1976 -0.0014 0 -0 -0.0014
Real Estate 0 0.0175 nan 0.036 0.0025 0 -0 0.0025
Technology 0.4 0.3758 0.1419 0.2489 0.0017 -0.0402 -0.0026 -0.0411
Utilities 0 0.0204 nan 0.1511 0.0006 0 -0 0.0006
Total 1 1 0.2596 0.1798 -0.0077 0.0233 0.0642 0.0798

Parameters

get_brinson_attribution accepts the following parameters.

ParameterTypeDescriptionExample
weightsdict[str, float] | NoneThe weight per asset at the start of the date range. Defaults to None, which uses the latest weights of the Portfolio the Toolkit came from, or equal weights.None, which uses the latest weights of the Portfolio the Toolkit came from, or equal weights
roundingint | NoneThe number of decimals to round the results to. Defaults to None, which uses the Toolkit’s rounding.2
Share