AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Portfolio Attribution

skill-brainbytes-dev-everything-claude-trading-portfolio-attribution · by brainbytes-dev

A Claude skill from brainbytes-dev/everything-claude-trading.

No reviews yet
0 installs
15 views
0.0% view→install

Install

$ agentstack add skill-brainbytes-dev-everything-claude-trading-portfolio-attribution

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-brainbytes-dev-everything-claude-trading-portfolio-attribution)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Portfolio Attribution? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Portfolio Performance Attribution

> Decomposing portfolio returns into allocation, selection, and factor contributions.

When to Activate

  • User needs to explain why a portfolio outperformed or underperformed its benchmark
  • Implementing Brinson-Fachler attribution for equity portfolios
  • Building factor-based attribution using regression or risk models
  • Performing fixed income attribution (duration, credit, curve)
  • Linking single-period attribution across multiple periods

Core Concepts

What Is Attribution?

Attribution decomposes the active return (portfolio return minus benchmark return) into components that explain where and how value was added or lost. Two major frameworks:

  1. Holdings-based (Brinson): uses portfolio and benchmark weights and returns by sector/region
  2. Returns-based (factor regression): regresses portfolio returns on factor returns to identify exposures
  3. Risk-model-based: uses a multi-factor risk model to decompose returns into factor and specific components

Brinson-Fachler Attribution

Decomposes active return into three effects for each sector s:

Allocation Effect: did the manager overweight sectors that outperformed?

AE_s = (w_p,s - w_b,s) * (R_b,s - R_b)

Selection Effect: did the manager pick better stocks within each sector?

SE_s = w_b,s * (R_p,s - R_b,s)

Interaction Effect: combined effect of overweighting sectors where stock picks were also good

IE_s = (w_p,s - w_b,s) * (R_p,s - R_b,s)

Total active return: Rp - Rb = ΣAEs + ΣSEs + ΣIE_s

Where:

  • wp,s, wb,s: portfolio and benchmark weight in sector s
  • Rp,s, Rb,s: portfolio and benchmark return in sector s
  • R_b: total benchmark return

Factor-Based Attribution

Uses a multi-factor risk model (e.g., Barra, Axioma, Northfield):

R_p - R_f = Σ (β_p,k - β_b,k) * f_k + α_specific

Where βp,k is the portfolio's exposure to factor k, and fk is the factor return. Decomposes into:

  • Factor timing: return from active factor bets
  • Specific return: stock-level alpha (idiosyncratic return)

Methodology

Step 1: Brinson Attribution Implementation

import pandas as pd
import numpy as np

def brinson_fachler(portfolio_weights, benchmark_weights,
                     portfolio_returns, benchmark_returns):
    """
    Single-period Brinson-Fachler attribution by sector.

    All inputs are Series indexed by sector.
    """
    total_bench_return = (benchmark_weights * benchmark_returns).sum()

    allocation = (portfolio_weights - benchmark_weights) * (benchmark_returns - total_bench_return)
    selection = benchmark_weights * (portfolio_returns - benchmark_returns)
    interaction = (portfolio_weights - benchmark_weights) * (portfolio_returns - benchmark_returns)

    result = pd.DataFrame({
        'port_weight': portfolio_weights,
        'bench_weight': benchmark_weights,
        'port_return': portfolio_returns,
        'bench_return': benchmark_returns,
        'allocation': allocation,
        'selection': selection,
        'interaction': interaction,
        'total_active': allocation + selection + interaction
    })

    # Verify: sum of total_active should equal portfolio return - benchmark return
    port_return = (portfolio_weights * portfolio_returns).sum()
    bench_return = (benchmark_weights * benchmark_returns).sum()
    assert abs(result['total_active'].sum() - (port_return - bench_return)) 8.2%}
    Benchmark Return:     {bench_ret:>8.2%}
    Active Return:        {active_ret:>8.2%}

    --- Decomposition by Sector ---
    {'Sector':8} {'Select':>8} {'Inter':>8} {'Total':>8}
    {'-'*60}
    """
    for sector, row in attribution_df.iterrows():
        report += f"    {sector:8.2%} {row['selection']:>8.2%} "
        report += f"{row['interaction']:>8.2%} {row['total_active']:>8.2%}\n"

    report += f"    {'-'*60}\n"
    report += f"    {'TOTAL':8.2%} "
    report += f"{attribution_df['selection'].sum():>8.2%} "
    report += f"{attribution_df['interaction'].sum():>8.2%} "
    report += f"{attribution_df['total_active'].sum():>8.2%}\n"

    return report

Examples

Equity Attribution by Sector

# Sector weights and returns
sectors = ['Technology', 'Healthcare', 'Financials', 'Energy', 'Consumer']
port_w = pd.Series([0.35, 0.20, 0.15, 0.10, 0.20], index=sectors)
bench_w = pd.Series([0.28, 0.15, 0.18, 0.12, 0.27], index=sectors)
port_r = pd.Series([0.08, 0.05, 0.03, -0.02, 0.04], index=sectors)
bench_r = pd.Series([0.06, 0.04, 0.04, -0.01, 0.03], index=sectors)

result = brinson_fachler(port_w, bench_w, port_r, bench_r)
# Allocation to Tech (overweight in strong sector) = positive
# Selection in Tech (8% vs 6%) = positive

Interpreting Results

Key insights to surface:

  • Was alpha from sector allocation (top-down) or stock selection (bottom-up)?
  • Which sectors had the largest attribution? Is it consistent over time or a one-off?
  • Is the interaction effect large? If so, the manager may be making correlated allocation and selection bets
  • Does attribution match the stated investment process? (A bottom-up manager should show selection, not allocation)

Quality Gate

  • [ ] Attribution sums exactly to total active return (no residual beyond rounding)
  • [ ] Multi-period attribution uses a proper linking method (Carino, GRAP, or Menchero)
  • [ ] Sector/region classification is consistent between portfolio and benchmark
  • [ ] Transaction effects excluded from holdings-based attribution (or accounted for separately)
  • [ ] Currency effects separated from local returns for international portfolios
  • [ ] Factor-based attribution uses a risk model consistent with the portfolio's universe
  • [ ] Interaction effect interpreted correctly — not lumped into allocation or selection arbitrarily
  • [ ] Reported at multiple levels: total, sector, country, and individual security
  • [ ] For fixed income: duration, curve, and spread effects isolated before reporting selection
  • [ ] Attribution is stable and explainable — large unexplained residuals indicate model problems

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.