portfolio-rebalancer
You hand over a positions map plus book value, a per-name variance-
share cap, a per-name weight cap, and a max churn per rebalance. The
skill returns a specific trade-ticket list with dollar amounts,
weight deltas, and before/after variance-share readings.
risk-report tells you which name is driving the risk. This skill
tells you what to trim, by how much, and where to redistribute.
When to invoke
- After a risk-report run flags a name with variance share far
disproportionate to its weight
- Portfolio-review workflow, decision-support step
- The user says "rebalance", "trim my winners", "cut variance",
"what should I sell", "reduce concentration"
- Any time the operator wants an actionable answer, not a report
What you need
MASSIVE_API_KEY — Stocks Starter for daily aggs on every name +
benchmark
What you get back
Layer 1 JSON matching output-schema.json.
Per-name trade tickets sorted by absolute dollar amount, plus
portfolio-level before/after summary (vol, top-3 variance share,
Herfindahl, max variance share), constraint-satisfaction status.
Layer 2 rendered table. Before/after summary block, then a table
of trades, then a status line. See
references/rendering.md.
How it works
- Parse positions from either a comma-separated string
(
TICKER=WEIGHT) or a book JSON file. Same shape as risk-report
for consistency.
- Pull daily aggs for every position + benchmark over the
lookback_days window (default 252).
- Compute covariance: per-name annualized vol, shrinkage-
adjusted correlation, covariance matrix. Same machinery as
risk-report.
- Compute current variance shares via
w_i * (Σw)_i / total.
- Solve iteratively:
- For every over-cap name, trim by
sqrt(target/current) since
variance share scales roughly quadratically with weight.
- Redistribute freed weight to under-cap names in proportion to
their current weight.
- Enforce max_weight cap after distribution; clip and re-
redistribute if needed.
- Renormalize to preserve gross exposure.
- Iterate to convergence or max_iter.
- Apply churn cap: if the target rebalance exceeds
max_churn
one-way turnover, scale the delta vector down proportionally
until it fits. Emit a status flag when this happens.
- Emit trade tickets: delta_weight * book_value per name, drop
trades below
min_trade_dollar.
Endpoints used
GET /v2/aggs/ticker/{ticker}/range/1/day/{from}/{to} for every
position + benchmark
Doesn't handle (yet)
- Not tax-aware. Selling appreciated positions incurs capital
gains; the tool ignores this. Apply the trade list through a tax-
lot-aware execution layer if lots matter.
- Not liquidity-aware. Dollar amounts do not consider ADV, spread,
or market impact. Verify with slippage-cost before executing large
trades in illiquid names.
- Descriptive against a risk cap, not return-maximizing. The tool
does not use forward return estimates. It solves for a specified
risk-share target only.
- Covariance is estimated with shrinkage but still relies on the
last N trading days. Regime shifts can change covariance faster
than the estimator adapts.
- Single-asset-class only. Multi-asset books (equities + fixed
income + crypto) need the correlation panel to align across asset
types — not handled in v1.
1---2name: portfolio-rebalancer3description: Decision layer on top of risk-report. Takes positions with weights and outputs specific trade tickets to bring every name under a variance-share cap while respecting weight and churn limits. Turns "ALLO carries 66% of portfolio variance at 18% weight" into "sell $65k of ALLO, redistribute, portfolio vol drops from 21% to 15%." Not tax-aware, not liquidity-aware in v1 — honest about both. Use when the operator asks "so what should I change?" after a risk-report.4---56# portfolio-rebalancer78You hand over a positions map plus book value, a per-name variance-9share cap, a per-name weight cap, and a max churn per rebalance. The10skill returns a specific trade-ticket list with dollar amounts,11weight deltas, and before/after variance-share readings.1213risk-report tells you which name is driving the risk. This skill14tells you what to trim, by how much, and where to redistribute.1516## When to invoke1718- After a risk-report run flags a name with variance share far19 disproportionate to its weight20- Portfolio-review workflow, decision-support step21- The user says "rebalance", "trim my winners", "cut variance",22 "what should I sell", "reduce concentration"23- Any time the operator wants an actionable answer, not a report2425## What you need2627- `MASSIVE_API_KEY` — Stocks Starter for daily aggs on every name +28 benchmark2930## What you get back3132**Layer 1 JSON** matching [`output-schema.json`](./output-schema.json).33Per-name trade tickets sorted by absolute dollar amount, plus34portfolio-level before/after summary (vol, top-3 variance share,35Herfindahl, max variance share), constraint-satisfaction status.3637**Layer 2 rendered table**. Before/after summary block, then a table38of trades, then a status line. See39[`references/rendering.md`](./references/rendering.md).4041## How it works42431. **Parse positions** from either a comma-separated string44 (`TICKER=WEIGHT`) or a book JSON file. Same shape as risk-report45 for consistency.462. **Pull daily aggs** for every position + benchmark over the47 `lookback_days` window (default 252).483. **Compute covariance**: per-name annualized vol, shrinkage-49 adjusted correlation, covariance matrix. Same machinery as50 risk-report.514. **Compute current variance shares** via `w_i * (Σw)_i / total`.525. **Solve iteratively**:53 - For every over-cap name, trim by `sqrt(target/current)` since54 variance share scales roughly quadratically with weight.55 - Redistribute freed weight to under-cap names in proportion to56 their current weight.57 - Enforce max_weight cap after distribution; clip and re-58 redistribute if needed.59 - Renormalize to preserve gross exposure.60 - Iterate to convergence or max_iter.616. **Apply churn cap**: if the target rebalance exceeds `max_churn`62 one-way turnover, scale the delta vector down proportionally63 until it fits. Emit a status flag when this happens.647. **Emit trade tickets**: delta_weight * book_value per name, drop65 trades below `min_trade_dollar`.6667## Endpoints used6869- `GET /v2/aggs/ticker/{ticker}/range/1/day/{from}/{to}` for every70 position + benchmark7172## Doesn't handle (yet)7374- **Not tax-aware.** Selling appreciated positions incurs capital75 gains; the tool ignores this. Apply the trade list through a tax-76 lot-aware execution layer if lots matter.77- **Not liquidity-aware.** Dollar amounts do not consider ADV, spread,78 or market impact. Verify with slippage-cost before executing large79 trades in illiquid names.80- **Descriptive against a risk cap, not return-maximizing.** The tool81 does not use forward return estimates. It solves for a specified82 risk-share target only.83- **Covariance is estimated with shrinkage but still relies on the84 last N trading days.** Regime shifts can change covariance faster85 than the estimator adapts.86- **Single-asset-class only.** Multi-asset books (equities + fixed87 income + crypto) need the correlation panel to align across asset88 types — not handled in v1.