StrategiesTax-Aware Direct Indexing

Tax-Aware Direct Indexing

Track a benchmark. Harvest losses lot by lot. Respect wash sales.

Net exposure
100%
Tracking error
Priced, no hard cap
Role
Standalone book
Results · coming soon

Backtest figures will appear here once results on real data are published. Until then, this page sets out the method.

Results · coming soon

Backtest results are coming soon.

Backtest results on real data will be published with a forthcoming paper on SSRN, a preprint server for research papers. The paper describes the methodology and compares a CPU solver with a GPU solver on real data. Until then, this site explains the method, and the tools show results on sample portfolios.

When they land, this section will chart the strategy's after-tax growth against its benchmark and its drawdowns, with tracking error, turnover and harvested losses alongside.

The idea

An index fund holds the index for you as a single position. Direct indexing holds the same stocks directly, so any stock that drops can be sold to bank a tax loss against your other gains, then replaced with a similar stock so the portfolio keeps tracking the index.

The objective
Subject to
Σ wᵢ = 1Fully invested — weights (cash included) sum to 1
wᵢ ≥ 0Long-only
c_min ≤ w_cash ≤ c_maxHard cash buffer (0.25–0.5% of NAV)
|wᵢ − w_b,ᵢ| ≤ band (soft)Per-name and per-sector drift is free inside the band, linearly penalized outside it — no hard name cap or tracking-error cap

Minimize the weighted sum of two things: (i) the portfolio's factor distance from the benchmark, measured under the risk model Σ, and (ii) the tax cost on realized gains, net of the tax saved on realized losses. Both are in the same units: with λ_te = λ_tax = 1, (1% tracking error)² costs as much as 1% of the portfolio's value in tax. The two weights λ_te and λ_tax set the balance: push λ_tax up and the optimizer harvests harder at the cost of wider tracking error; push λ_te up and the portfolio hugs the index more tightly.

In the backtest, this is solved as a portfolio-optimization problem at each rebalance, written in CVXPY (an open-source modelling library) and solved by a CPU-based conic solver. The solver searches the portfolios the constraints allow and returns the weights that minimise the objective. The forthcoming paper on the methodology compares a CPU solver with a GPU solver on real data. Nothing runs on this site: everything is computed offline.

What goes in, what comes out
Inputs
  • Holdings + lots

    Per-account lot-level positions with acquisition date, cost basis, and quantity.

  • Benchmark weights

    Target weights from the chosen benchmark index (a broad US or global equity index).

  • Prices + risk model

    Daily prices and the factor risk model that drives the tracking-error metric.

  • Constraints

    Cash buffer, soft per-name and per-sector bands, exclusions, and any other customization knobs.

Outputs
  • Trade list

    Lot-level buys and sells for the day, each identified by the lot it touches.

  • New weight vector

    Target weights w* after the solve — what the portfolio should hold tomorrow.

  • Realized P/L

    Per-lot realized gain/loss for the day, split into short-term and long-term buckets.

Customization · Coming soon

Factor tilt

A factor tilt lets the optimizer hold more of the names that score well on a chosen factor — quality, value, momentum, or low-volatility — and less of the names that score poorly. The portfolio still tracks the benchmark, but with a measurable lean toward the chosen factor.

How the optimizer applies it

B_f is the column of factor loadings for the chosen factor from the risk model. The constraint forces the portfolio's active exposure to that factor to be at least t_f standard deviations above the benchmark. The optimizer redistributes weight within the tracking-error budget to satisfy it — buying high-scoring names, underweighting low-scoring ones.

The trade-off

You consume part of your tracking-error budget on the tilt. Less budget remains for tax-loss harvesting, so factor tilts typically reduce expected harvest activity slightly. The factor's own active return is the offset.

 Long/Short Tax-AwareMarket-Neutral Pair SleeveTax-Aware Direct Indexing
Net exposure100%0%100%
Factor exposureTrackedPinned to zeroTracked
Source of returnIndex + tax + activeCross-sectional alphaIndex + tax alpha
RoleStandalone bookCompanion sleeveStandalone book