Install & quickstart#
Requirements#
- Python 3.14 or later (pinned by pybrinson's
requires-python). - The Python standard library. That is all.
pybrinson has zero runtime dependencies. No pandas, no numpy, no polars — ever. This is a deliberate design rule, not an oversight.
Install#
Your first attribution#
from pybrinson import Segment, bhb
segments = [
Segment("UK Equity", 0.40, 0.40, 0.20, 0.10),
Segment("Japan Equity", 0.30, 0.20, -0.05, -0.04),
Segment("US Equity", 0.30, 0.40, 0.06, 0.08),
]
result = bhb(segments, period="2024-Q1")
print(f"Portfolio return: {result.portfolio_return:.2%}")
print(f"Benchmark return: {result.benchmark_return:.2%}")
print(f"Excess return: {result.excess_return:.2%}")
print()
print(f"Allocation: {result.allocation:.2%}")
print(f"Selection: {result.selection:.2%}")
print(f"Interaction: {result.interaction:.2%}")
Portfolio return: 8.30%
Benchmark return: 6.40%
Excess return: 1.90%
Allocation: -1.20%
Selection: 3.00%
Interaction: 0.10%
result is a frozen PeriodAttribution dataclass. Print it
directly for a fixed-width summary table; iterate result.by_segment
for the per-group breakdown.
The Segment input#
Segment(
name: str,
portfolio_weight: float, # fraction, e.g. 0.30 means 30%
benchmark_weight: float,
portfolio_return: float, # fraction, e.g. 0.05 means +5%
benchmark_return: float,
parent: str | None = None, # for hierarchies
local_return: float | None = None, # for currency attribution
currency_return: float | None = None,
)
Input validation#
pybrinson refuses to guess. It will raise AttributionError on:
- An empty
segmentslist. - Non-finite values (
NaN,±inf) anywhere in weights or returns. - Weight vectors that do not sum to 1 within \(10^{-8}\) (both portfolio and benchmark are checked independently).
- Segments with zero weight in both portfolio and benchmark (empty groups are a classification bug — fix upstream, do not silently drop).
- Attribution identity violations (
A + S + I != excess_returnbeyond \(10^{-9}\)). These only fire on numerical pathology, never on valid inputs.
No silent coercion, no warnings.warn, no imputation.
Next steps#
- If the vocabulary (allocation, selection, interaction) is new to you, read the primer first.
- For multiple quarters, compound via one of the linking methods.
- For classification depths beyond one level, read multi-level hierarchies.
- For multi-currency portfolios, read currency attribution.