Turnover, Transaction Costs, and Net Performance

Measuring portfolio turnover and how modeled transaction costs change the wealth path

Investment Methods
Portfolio Methods
Intermediate
A practical guide to drift-aware portfolio turnover, transaction-cost conventions, and how modeled trading costs translate before-cost performance into net portfolio performance.

QM009 · Investment Methods · Portfolio Methods · Intermediate

Core idea. Transaction costs in a backtest should be applied to the trades implied by the rebalance. That requires measuring turnover from the drifted pre-trade portfolio to the new target, declaring what the turnover statistic counts, and applying a cost rate to the same traded-notional convention.

Use it for. Turning a before-cost portfolio backtest into an explicitly cost-adjusted backtest when the trading rule, rebalance schedule, and proportional transaction-cost model are specified.

It does not establish. Actual implementation shortfall, market impact, capacity, or cost-optimal portfolio weights. A constant-basis-point cost model is a transparent modeling assumption, not a universal execution model.

The Question

A strategy can have attractive performance before trading frictions and still be difficult to implement. One of the first quantities to examine is turnover.

But the word is not enough. A backtest needs to answer three separate questions:

  1. What portfolio exists immediately before the trade?
  2. How much does the strategy trade to reach the new target?
  3. What cost rate is applied, and what definition of traded notional does that rate price?

The central question is therefore:

Given a trading rule, how much turnover does it generate, and what happens to the wealth path under a declared transaction-cost model?

The portfolio timeline follows QM007 — Portfolio Backtesting and Rebalancing. Returns during the holding period change the portfolio weights before the next rebalance. The resulting drifted pre-trade portfolio is the state from which rebalancing begins. The rebalance then moves that portfolio toward the new target.

Why It Matters

Transaction-cost analysis can go wrong even when the cost rate itself looks reasonable.

Suppose a backtest says turnover is 10% and assumes 10 basis points of transaction cost. That still does not tell us the cost deduction. The turnover figure might refer to purchases only, purchases plus sales, an annual regulatory ratio, or an average across rebalance dates. Likewise, a 10-basis-point cost assumption is meaningful only when we know which measure of traded notional it applies to.

A second problem is timing. The amount traded is generally not the difference between the new target and the previous target. Asset returns have changed the portfolio weights since the previous rebalance. This is also the convention used by DeMiguel, Garlappi, and Uppal, who measure turnover relative to the portfolio weights immediately before rebalancing (DeMiguel et al. 2009).

A third problem is terminology. The U.S. Securities and Exchange Commission’s mutual-fund Portfolio Turnover Rate is a particular annual disclosure ratio based on the lesser of purchases or sales relative to the prescribed average value of portfolio securities, subject to specified exclusions (U.S. Securities and Exchange Commission 2025). It is not interchangeable with the rebalance-date weight-space turnover used in this article.

Start from the Drifted Portfolio

Let \(\widetilde w_{i,t}\) be asset \(i\)’s weight immediately before rebalancing at date \(t\). These are the weights after returns over the preceding holding period have caused the portfolio to drift.

Let \(w_{i,t}\) be the desired post-rebalance target weight. Define the trade in weight space as

\[ \Delta w_{i,t} = w_{i,t}-\widetilde w_{i,t}. \]

A positive \(\Delta w_{i,t}\) is a modeled purchase; a negative value is a modeled sale.

We define full-L1 turnover as

\[ TO_t^{L1} = \sum_{i=1}^{N} \left|\Delta w_{i,t}\right| = \sum_{i=1}^{N} \left|w_{i,t}-\widetilde w_{i,t}\right|. \]

This statistic counts the absolute size of both purchase and sale legs in units of pre-cost portfolio wealth.

WarningDo not compute turnover from target to target

The previous target \(\mathbf w_{t-1}\) is generally not the portfolio that exists at the next rebalance. Relative asset returns move the portfolio to \(\widetilde{\mathbf w}_t\). Turnover is measured from that drifted state to the new target.

Full-L1 and One-Way Turnover

For a long-only, fully invested portfolio with no external flows,

\[ \sum_i \widetilde w_{i,t} = \sum_i w_{i,t} =1. \]

The total weight purchased therefore equals the total weight sold. Under this specific setup,

\[ TO_t^{1w} = \frac{1}{2}TO_t^{L1}. \]

Under this convention, the half-L1 statistic equals both the modeled purchase weight and the modeled sale weight. We refer to this quantity as one-way turnover.

The factor of one-half is not a universal definition. With external cash flows, leverage, short positions, or other changes in net exposure, purchases and sales need not be equal.

For example, if full-L1 turnover is 20%, the corresponding one-way turnover is 10%. Both numbers can describe the same rebalance. Reporting only “turnover = 10%” without defining the measure leaves the underlying traded notional ambiguous.

Match the Cost Rate to the Turnover Measure

Let \(c_t\) denote the assumed proportional cost per dollar of modeled trade notional, measured relative to pre-cost portfolio wealth. Under the symmetric base convention, the modeled cost fraction is

\[ C_t = c_t TO_t^{L1}. \]

Because \(TO_t^{L1}=2TO_t^{1w}\) in the fully invested/no-flow case,

\[ C_t = 2c_tTO_t^{1w}. \]

The factor of two comes from the combination of two conventions: turnover is being reported on a one-way basis, while the cost rate is charged on both modeled purchase and sale notional. It is not a universal transaction-cost adjustment.

Suppose one-way turnover is 10% and the cost quote is 10 basis points per modeled buy-or-sell dollar. Since

\[ 10\text{ bps}=0.001, \]

full-L1 turnover is 20%, and

\[ C_t = 0.001\times0.20 = 0.0002. \]

The modeled debit is therefore 2 basis points of pre-cost portfolio wealth, not 1 basis point.

ImportantA basis-point assumption needs a denominator

A cost rate is not self-contained. State whether it applies to full buy-plus-sell notional, a one-way turnover measure, or another explicitly defined trading base. The formula must change when the quote convention changes.

From Performance Before Costs to Net Wealth

Let \(V_{t-1}^{+}\) be wealth immediately after the previous rebalance and cost debit. Let \(R_{p,t}^{\text{pre-cost}}\) be the portfolio return earned during holding period \(t\) before the modeled transaction cost at the next rebalance.

Pre-cost wealth is

\[ V_t^{-} = V_{t-1}^{+} (1+R_{p,t}^{\text{pre-cost}}). \]

After the proportional cost debit,

\[ V_t^{+} = V_t^{-}(1-C_t). \]

Combining the two steps gives

\[ V_t^{+} = V_{t-1}^{+} (1+R_{p,t}^{\text{pre-cost}}) (1-c_tTO_t^{L1}). \]

This multiplicative wealth accounting is consistent with the proportional transaction-cost treatment in DeMiguel, Garlappi, and Uppal (DeMiguel et al. 2009).

The corresponding return from one post-cost state to the next is

\[ R_{p,t}^{net} = (1+R_{p,t}^{\text{pre-cost}})(1-C_t)-1. \]

Equivalently,

\[ R_{p,t}^{net} = R_{p,t}^{\text{pre-cost}} -C_t -R_{p,t}^{\text{pre-cost}}C_t. \]

The familiar shortcut

\[ R_{p,t}^{\text{pre-cost}}-C_t \]

omits the cross term. With small costs the numerical difference may be small, but the two accounting rules are not algebraically identical.

Why the wording “before modeled transaction costs” matters

Gross-of-fees should not be used as a synonym for “before transaction costs.” Under the GIPS Standards, transaction costs are reflected in both gross-of-fees and net-of-fees returns; the distinction concerns investment-management fees rather than whether trading costs are deducted (CFA Institute 2020).

For this reason, the article uses the following labels:

  • performance before modeled transaction costs; and
  • performance net of modeled transaction costs.

These labels also make the model boundary visible: commissions, spreads, taxes, financing, market impact, and other implementation effects are included only if the stated cost model explicitly includes them.

Numerical Illustration: Drift, Turnover, and Cost

Consider an already established three-asset portfolio with initial wealth 100 and weights

\[ \mathbf w_0=(0.50,0.30,0.20). \]

During the first holding period, asset returns are

\[ (10\%,0\%,-5\%). \]

The portfolio return before modeled transaction costs is 4%, so pre-cost wealth becomes

\[ V_1^{-}=100(1.04)=104. \]

After these returns, the portfolio weights drift to

\[ \widetilde{\mathbf w}_1 \approx (0.528846,0.288462,0.182692). \]

Suppose the new target is

\[ \mathbf w_1=(0.40,0.40,0.20). \]

The correct drift-aware full-L1 turnover is

\[ TO_1^{L1} \approx 0.257692, \]

or 25.7692%. One-way turnover is 12.8846%.

By contrast, comparing the new target directly with the previous target gives only

\[ |0.40-0.50| +|0.40-0.30| +|0.20-0.20| =0.20. \]

The 20% target-to-target calculation misses the additional trading required because the portfolio has drifted.

Using the 10-bps-per-traded-dollar convention defined above,

\[ C_1 = 0.001\times0.257692 \approx 0.000257692. \]

Post-cost wealth is therefore

\[ V_1^{+} = 104(1-0.000257692) =103.9732. \]

Under this model, the period return net of modeled transaction costs is 3.9732%.

The full four-period illustration is deliberately small enough to inspect by hand:

Period Rebalance? Return before modeled costs Full-L1 turnover One-way turnover Net return Net wealth
1 Yes 4.0000% 25.7692% 12.8846% 3.9732% 103.9732
2 No 1.2000% 0.0000% 0.0000% 1.2000% 105.2209
3 Yes -0.1028% 29.7658% 14.8829% -0.1325% 105.0815
4 Yes 0.2000% 10.8982% 5.4491% 0.1891% 105.2801
NoteNumerical illustration — not empirical evidence

The returns, targets, and 10-basis-point cost assumption are chosen to expose accounting differences. They do not estimate the trading costs, turnover, or performance of a real strategy.

Aggregating Turnover and Cost Drag

Turnover statistics also need a time-aggregation convention.

For a set of rebalance dates \(\mathcal T\) within a chosen sample or calendar period, one transparent summary is the sum of rebalance-date turnover:

\[ TO_{\mathcal T}^{L1} = \sum_{t\in\mathcal T}TO_t^{L1}. \]

In the four-period illustration, recurring full-L1 turnover sums to approximately

\[ 0.664332, \]

and recurring one-way turnover sums to approximately

\[ 0.332166. \]

Initial portfolio formation is excluded from these recurring-turnover summaries. If an analysis wants to charge an inception trade from cash into the initial portfolio, that transaction should be stated separately because its denominator and cash-leg convention can differ from ordinary rebalancing.

Cost fractions also compound. The exact cumulative retention due solely to the sequence of modeled cost debits is

\[ \prod_{t\in\mathcal T}(1-C_t), \]

so the exact cumulative cost drag fraction is

\[ 1- \prod_{t\in\mathcal T}(1-C_t). \]

It is not exactly equal to \(\sum_{t\in\mathcal T}C_t\). In the illustration,

\[ \sum_{t\in\mathcal T}C_t \approx 0.000664332, \]

while the exact compounded drag is approximately

\[ 0.000664195. \]

The difference is tiny here because the modeled costs are small, but the accounting distinction is still real.

Implementation Pattern

A transparent implementation keeps the portfolio state, turnover calculation, and cost debit separate:

weights = initial_weights
wealth = initial_wealth

for t in periods:
    holding_growth_factor = sum(
        w * (1 + r)
        for w, r in zip(weights, returns[t])
    )

    pre_cost_wealth = wealth * holding_growth_factor
    drifted_weights = [
        w * (1 + r) / holding_growth_factor
        for w, r in zip(weights, returns[t])
    ]

    if is_rebalance_date(t):
        target = target_weights[t]
        turnover_l1 = sum(
            abs(target_i - drifted_i)
            for target_i, drifted_i in zip(target, drifted_weights)
        )
        cost_fraction = cost_rate[t] * turnover_l1
        wealth = pre_cost_wealth * (1 - cost_fraction)
        weights = target
    else:
        turnover_l1 = 0.0
        cost_fraction = 0.0
        wealth = pre_cost_wealth
        weights = drifted_weights

This is a reduced-form proportional-cost backtest. The trade vector is measured from the drifted pre-trade portfolio to the desired target using pre-cost wealth as the denominator. The scalar cost deduction is then applied to wealth. Because transaction costs are applied as a scalar wealth deduction, the example does not solve the more detailed self-financing execution problem in which trading costs can alter the exact post-trade holdings.

Hands-on Lab: Change the Cost Assumption

The lab uses the same four-period three-asset path and lets you change the proportional cost assumption while keeping the trading rule fixed.

Run it yourself. Start with the lab guide. For a self-contained copy, use the complete lab bundle. Direct source: Python · R.

python labs/python/qm009_hands_on.py 10

Try 0, 10, and 25 bps. Turnover should not change, because the targets and return path are unchanged. Terminal net wealth should change, because the same modeled trade notional is being charged at a different rate.

What a Transaction-Cost Backtest Should State

Item Minimum declaration
Pre-trade state Drifted pre-trade weights or another explicitly defined portfolio state
Trade vector Exact formula mapping the pre-trade portfolio to the target
Turnover Full-L1, one-way/half-L1, regulatory ratio, or another named convention
Cost quote Basis points or other rate, plus the traded-notional denominator it prices
Timing Whether the cost is charged at the rebalance, during execution, or under another convention
Performance labels Before modeled transaction costs versus net of modeled transaction costs
Inception Whether initial portfolio formation is included or reported separately
Aggregation Sum, average, calendar-year sum, or another explicitly defined time summary; label any frequency scaling
Frictions included Commissions, bid-ask spreads, taxes, market impact, financing, or other components actually modeled
Frictions omitted Important costs that the reported net result does not include

Common Mistakes

1. Computing turnover from the previous target

Asset returns change portfolio weights between rebalances even when no trade occurs. The previous target is therefore not generally the portfolio that exists when the next order is placed.

2. Reporting “turnover” without the formula

Full-L1 and one-way turnover differ by a factor of two under the fully invested/no-flow convention used here. Regulatory portfolio turnover is a separate statistic (U.S. Securities and Exchange Commission 2025).

3. Applying a both-legs cost rate directly to one-way turnover

If the cost rate prices each dollar bought and sold, the full-L1 traded-notional base must be used, or the factor-of-two mapping must be applied explicitly.

4. Treating passive weight drift as a trade

On a non-rebalance date, drift changes weights but does not create strategy-driven turnover. Cost should not appear merely because prices moved.

5. Mixing initial formation with recurring turnover

A cash-to-portfolio inception trade is not automatically comparable with later rebalances. State the inception convention separately.

6. Calling \(\sum_{t\in\mathcal T}C_t\) the exact cumulative drag

The exact retention is multiplicative: \(\prod_{t\in\mathcal T}(1-C_t)\).

7. Calling a fixed-bps cost model “actual execution cost”

Implementation shortfall is broader than a simple turnover-linked debit (Perold 1988; Kritzman et al. 2006). Execution models can include spread, market impact, execution speed, liquidity, and risk trade-offs; Almgren and Chriss provide a classic example of that richer problem (Almgren and Chriss 2001).

8. Assuming ex-post cost deduction makes the portfolio cost-optimal

An ex-post cost adjustment evaluates a target that has already been chosen. A cost-aware optimizer would place turnover, transaction-cost terms, or trading constraints inside the portfolio-choice problem and may choose a different target.

9. Letting transaction-cost realism hide an information leak

Charging a cost does not repair a timing error. If a target uses information that would not have been available before the trade generating the subsequent return, the backtest still has an information-timing problem. The timing discipline described in QM007 still applies.

When This Setup Needs to Be Extended

The proportional-cost model is most useful when the goal is transparent sensitivity analysis under a simple, declared cost assumption. Extend the model when the implementation problem materially depends on:

  • bid-ask spreads or commissions that vary by asset and date;
  • nonlinear market impact or trade size relative to liquidity;
  • execution delay, partial fills, or opportunity cost from unexecuted orders;
  • asymmetric buy and sell costs;
  • taxes or tax-lot constraints and realization rules;
  • leverage, shorting, margin, or financing costs;
  • derivatives, contract rolls, or changing notionals;
  • external deposits and withdrawals;
  • changing universes and forced exits; or
  • optimization that chooses targets jointly with trading costs.

Perold’s implementation-shortfall framework and later transaction-cost analysis emphasize the gap between a paper portfolio and the implemented outcome (Perold 1988; Kritzman et al. 2006). Almgren and Chriss show why market impact and execution risk can make optimal trading a separate problem from portfolio-weight accounting (Almgren and Chriss 2001).

Reproducibility

The article, Python example, base-R implementation, and hands-on lab all use the same deterministic three-asset path. Their outputs are cross-checked for drift-aware turnover, the one-way/full-L1 conversion, zero turnover on non-rebalance dates, multiplicative cost accounting, and cumulative modeled cost drag.

References

Almgren, Robert, and Neil Chriss. 2001. “Optimal Execution of Portfolio Transactions.” The Journal of Risk 3 (2): 5–39. https://doi.org/10.21314/JOR.2001.041.
CFA Institute. 2020. GIPS Standards Handbook for Firms. https://www.gipsstandards.org/standards/gips-standards-for-firms/gips-standards-handbook-for-firms/.
DeMiguel, Victor, Lorenzo Garlappi, and Raman Uppal. 2009. “Optimal Versus Naive Diversification: How Inefficient Is the 1/n Portfolio Strategy?” The Review of Financial Studies 22 (5): 1915–53. https://doi.org/10.1093/rfs/hhm075.
Kritzman, Mark, Simon Myrgren, and Sébastien Page. 2006. “Implementation Shortfall.” The Journal of Portfolio Management 33 (1): 25–30. https://doi.org/10.3905/jpm.2006.661367.
Perold, André F. 1988. “The Implementation Shortfall: Paper Versus Reality.” The Journal of Portfolio Management 14 (3): 4–9. https://doi.org/10.3905/jpm.1988.409150.
U.S. Securities and Exchange Commission. 2025. Form n-1A: Registration Statement Under the Securities Act of 1933 and/or the Investment Company Act of 1940. https://www.sec.gov/files/form-n-1a.pdf.