Rebalancing without the tax bill
/v1/portfolio/rebalance computes the trades that
restore target weights — and, with tax_aware, the realized gain
those sells would trigger plus a contributions-first plan that steers new
cash to the underweights instead. Where do the targets come from? An age-based
/v1/portfolio/glidepath feeds straight in.
1 · Make the call
A $100,000 four-fund portfolio, 5% drift bands, $10,000 of new cash to invest.
curl -X POST https://api.numeratica.com/v1/portfolio/rebalance \
-H "Authorization: Bearer nmr_sk_test_xxx" \
-H "Content-Type: application/json" \
-d '{
"holdings": [
{"label": "us_stocks", "value": 45000, "target_weight": 0.40, "cost_basis": 30000},
{"label": "intl_stocks", "value": 20000, "target_weight": 0.20, "cost_basis": 15000},
{"label": "bonds", "value": 25000, "target_weight": 0.30, "cost_basis": 24000},
{"label": "reits", "value": 10000, "target_weight": 0.10, "cost_basis": 8000}
],
"new_contribution": 10000,
"band": 0.05,
"tax_aware": true
}'2 · The response
{
"result_id": "rebalance_3e03c2cec19f1743",
"engine_version": "rebalance-1.0.0",
"result": {
"total_current": 100000,
"investable_total": 110000, /* holdings + the new contribution */
"trades": [
{ "label": "us_stocks", "current_weight": 0.45, "target_weight": 0.40,
"drift": 0.05, "trade": -1000, "action": "sell" },
{ "label": "intl_stocks", "drift": 0, "trade": 2000, "action": "buy",
"contribution": 1818.18 },
{ "label": "bonds", "drift": -0.05, "trade": 8000, "action": "buy",
"contribution": 7272.73 },
{ "label": "reits", "drift": 0, "trade": 1000, "action": "buy",
"contribution": 909.09 }
],
"max_drift": 0.05,
"needs_rebalance": false, /* nothing outside the 5% band — yet */
"estimated_realized_gain": 333.33, /* if the us_stocks sell executes */
"contributions_first": {
"contribution_allocated": 10000,
"max_drift_after": 0.0091, /* 5% drift → 0.9% with zero selling */
"fully_rebalanced": false
}
},
"disclaimer": "Calculation engine output for informational purposes only; not financial or investment advice."
}A full rebalance would sell $1,000 of US stocks and realize a $333 gain. Contributions-first allocates the $10,000 to the underweights instead — max drift falls from 5% to 0.9% with zero selling and zero realized gain. In taxable accounts, that's the default move; sell only what new cash can't fix.
3 · Where the targets come from
A 40-year-old on a linear target-date glide from 80/20 to 40/60 at retirement (65),
continuing "through" to 30/70 at 80: /v1/portfolio/glidepath
returns the year-by-year path (result_id
glidepath_dbd27f8f170dac0d) — this year's row is exactly the
target_weight input above. Pair with
/v1/capital-market-assumptions to price the blended
return/volatility of any point on the path.
4 · Render it
Before/after drift bars — the case for contributions-first in one glance.
<div style="font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;color:#1a2230;max-width:600px">
<div style="font-size:14px;color:#5b6675;margin-bottom:8px">$100k portfolio + $10k new cash · drift from target, before → after contributions-first</div>
<div style="display:grid;grid-template-columns:90px 1fr 1fr;gap:6px;font-size:13px;align-items:center">
<div></div><div style="color:#5b6675;font-size:12px">Before</div><div style="color:#5b6675;font-size:12px">After (no sells)</div>
<div>US stocks</div>
<div style="background:#e8edf8;border-radius:4px"><div style="width:100%;background:#b45309;height:14px;border-radius:4px"></div></div>
<div style="background:#e8edf8;border-radius:4px"><div style="width:18%;background:#16a34a;height:14px;border-radius:4px"></div></div>
<div>Bonds</div>
<div style="background:#e8edf8;border-radius:4px"><div style="width:100%;background:#b45309;height:14px;border-radius:4px"></div></div>
<div style="background:#e8edf8;border-radius:4px"><div style="width:18%;background:#16a34a;height:14px;border-radius:4px"></div></div>
<div>Intl / REITs</div>
<div style="background:#e8edf8;border-radius:4px"><div style="width:4%;background:#16a34a;height:14px;border-radius:4px"></div></div>
<div style="background:#e8edf8;border-radius:4px"><div style="width:4%;background:#16a34a;height:14px;border-radius:4px"></div></div>
</div>
<div style="margin-top:12px;display:grid;grid-template-columns:1fr 1fr;gap:10px">
<div style="border:1px solid #e6e9ef;border-radius:10px;padding:12px">
<div style="font-size:12px;color:#5b6675">Full rebalance</div>
<div style="font-size:18px;font-weight:700">$333 realized gain</div>
</div>
<div style="border:2px solid #16a34a;border-radius:10px;padding:12px">
<div style="font-size:12px;color:#16a34a;font-weight:600">Contributions-first</div>
<div style="font-size:18px;font-weight:700">$0 sold · drift 5% → 0.9%</div>
</div>
</div>
<div style="color:#5b6675;font-size:12px;margin-top:6px">result_id rebalance_3e03c2cec19f1743 · not investment advice</div>
</div>
The taxable-account companions:
gain & loss harvesting for what to sell when you must,
and /v1/tax/asset-location for which account each asset belongs
in to begin with.