Portfolio performance attribution
Skill ternary-ai/skills/skills/advanced/portfolio-performance-attribution
A collection of agent skills for investment finance
npx -y skills add ternary-ai/skills --skill portfolio-performance-attributionAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Delegate to the existing performance-attribution-error-analysis skill per holding, then roll up into a portfolio-level summary showing which positions contributed positively/negatively, factor attribution, and decision error patterns.
SKILL.md
6.7 KB, as published. Nobody here has run it
Portfolio Performance Attribution
Purpose: Decompose portfolio returns into per-holding contributions, factor exposures, and decision errors to understand what drove performance.
Trigger: User asks "portfolio performance", "what drove my returns", "attribution analysis", or uses /portfolio-performance-attribution.
Data Flow
1. Load Portfolio & Determine Time Period
- Check
<current_portfolio>first — skip tool call if present. - Otherwise:
load_portfolio(portfolio_id). - Extract holdings with cost basis and current shares.
Time Period:
- If user specifies "YTD", "last month", "last quarter", "last year" → parse and use.
- Default if unspecified: YTD (year-to-date) from Jan 1 to today.
2. Fetch Historical Prices for Each Holding
- For each ticker: call
PRICE_HISTORY(ticker, start=period_start, end=today)to get daily OHLCV. - For each ticker: call
GLOBAL_QUOTE(ticker)to get current price. - Batch in parallel — single plan step for all price fetches.
3. Compute Per-Holding Returns
For each holding:
price_start = closing price on period_start date (or avg_cost if later)
price_end = current_price
total_return = (price_end - price_start) / price_start × 100
contribution = (shares × price_end - shares × price_start) / total_portfolio_value_start × 100
Holding contribution to portfolio return = contribution %.
4. Factor Attribution — Call Existing Skill
For each holding, delegate to performance-attribution-error-analysis skill:
- Call
read_skill("performance-attribution-error-analysis"). - Execute the skill for each ticker over the same time period.
- Tool will return:
- Market factor contribution (beta × market return).
- Sector factor contribution.
- Alpha (stock-specific return).
- Decision errors (if buy/sell signals were evaluated).
Batch skill execution in a single plan step — "Run performance attribution for all N holdings."
5. Aggregate Portfolio-Level Attribution
Sum contributions across all holdings:
Total Portfolio Return = sum(contribution for all holdings)
Market Factor = sum(market_contribution for all holdings)
Sector Factor = sum(sector_contribution for all holdings)
Alpha = sum(alpha for all holdings)
Residual = Total Return - (Market + Sector + Alpha).
6. Render Output
Per-Holding Performance Table — use render_table():
| Ticker | Start Price | End Price | Total Return % | Contribution to Portfolio % | Market Factor | Alpha |
|---|---|---|---|---|---|---|
| AAPL | $170.00 | $185.00 | +8.8% | +4.3% | +3.5% | +5.3% |
| MSFT | $350.00 | $380.00 | +8.6% | +4.2% | +3.5% | +5.1% |
| TSLA | $200.00 | $175.00 | -12.5% | -1.2% | +3.5% | -16.0% |
| Total | — | — | +7.8% | +7.3% | +10.5% | -5.6% |
Factor Attribution Summary:
- Market Factor: +10.5% (beta-weighted S&P 500 return).
- Sector Factor: +2.4% (overweight Technology vs benchmark).
- Alpha (Stock Selection): -5.6% (underperformance vs sector).
- Residual: +0.5% (unexplained).
Top Contributors:
- AAPL: +4.3% (strong alpha, +5.3%).
- MSFT: +4.2% (strong alpha, +5.1%).
- Cash: +0.0% (no contribution).
Top Detractors:
- TSLA: -1.2% (negative alpha, -16.0%).
Chart — use generate_chart():
- Type:
bar - Series: Contribution % by holding
- X-axis: Ticker
- Y-axis: Contribution %
- Title: "{Portfolio Name} — Performance Contribution ({Period})"
- Colour: Green for positive, red for negative.
7. Decision Error Analysis (Optional)
If the performance-attribution-error-analysis skill identifies decision errors for individual holdings:
- Aggregate error types across all holdings:
- Confirmation bias (held losers too long).
- Recency bias (chased momentum).
- Premature exit (sold winners too early).
- Report the most common error pattern.
Example:
- Most common error: Premature exit (sold 2 winners early, left $X on table).
- Worst single error: Held TSLA through -16% decline (cost $Y).
8. Thesis Upsert — MANDATORY
This is an advanced skill → append performance attribution to portfolio thesis. ⚠️ Extended thinking is discarded — copy the complete report into the thesis field; it is the ONLY output that reaches the Thesis panel.
Thesis structure:
## Portfolio Performance Attribution — {Period} — {Date}
**Total Portfolio Return**: +{X}% (${Y})
{Per-holding performance table}
{Chart spec}
### Factor Attribution
- **Market Factor**: +{A}% (portfolio beta × S&P 500 return)
- **Sector Factor**: +{B}% (overweight {sector})
- **Alpha (Stock Selection)**: +{C}%
- **Residual**: +{D}%
### Top Contributors
1. {ticker}: +{X}% contribution ({reason})
2. {ticker}: +{Y}% contribution ({reason})
### Top Detractors
1. {ticker}: -{X}% contribution ({reason})
### Decision Errors
- {Most common error pattern}
- {Costliest single error}
**Key Insight**: {One sentence — e.g. "Strong market factor offset by weak stock selection; TSLA drag was largest single detractor."}
9. Chat Response
State in chat field:
- Time period analysed.
- Total portfolio return ($ and %).
- Market factor contribution vs alpha.
- Top contributor and top detractor.
- Decision error summary (if any).
- Tools used:
load_portfolio,PRICE_HISTORY(N times),GLOBAL_QUOTE,read_skill(performance-attribution-error-analysis),render_table,generate_chart.
Cost Controls
- Skip
load_portfolio()if<current_portfolio>is present. - Batch
PRICE_HISTORY()calls in parallel — single plan step for all holdings. - Reuse session cache — don't refetch price data already in
<acquired_data>. - Delegate to existing skill — don't reimplement performance attribution logic; use
performance-attribution-error-analysisper holding.
Error Handling
- If
PRICE_HISTORY(ticker)fails for a holding, useavg_costas start price and current quote as end price; note estimation inchat. - If
performance-attribution-error-analysisskill fails for a ticker, compute simple return attribution only (no factor decomposition) and continue. - If period_start predates the holding's
added_atdate, useadded_atas start and note partial period inchat.
Output Standards
- All percentages with one decimal: 12.3%.
- Dollar amounts formatted with commas: $1,234.56.
- Table must include a Total row summarising portfolio-level metrics.
- Chart must show both positive and negative contributions.
- Factor attribution must sum to Total Return (within ±1% residual tolerance).