Skip to content

Post-Trade TCA and Attribution: Measuring What Happened and Why

The point of post-trade TCA is not the report — it is the feedback loop: measure realized costs, decompose them, attribute them to broker/algo/venue, and feed the results back into the pre-trade model. Only when the loop closes does tomorrow's execution get better than today's.

10 of 12 ~14 min

You sent the order. The market moved. You got filled. Now what?

The “now what” is post-trade TCA: the morning-after analysis that tells you whether yesterday’s execution was any good, what it cost, and why. Pre-trade estimates are useful and real-time tracking is useful, but the actual learning happens in post-trade attribution — which is also where execution traders earn their keep or lose it. Harris (2003, Ch. 23) puts it starkly: post-trade TCA is the only feedback mechanism the buy-side has on execution quality. Without it, the desk is flying blind. With it but ignoring it, the desk holds the information and wastes it.

The hard part was never computing the numbers. TCA providers will gladly compute them for you, with pretty charts and a row of benchmarks. The hard part is two things: reading the numbers correctly, and feeding them back into tomorrow’s execution. The spine of this article is that loop — measure, decompose, attribute, calibrate, back to pre-trade — and the places on the loop where it tends to break. The biases of the benchmarks themselves (what VWAP rewards, what arrival punishes) got a full article of their own; this one assumes you are reading with those glasses on.

The Raw Material: What Is in a Post-Trade Report

A standard post-trade report gives you five layers per parent order: order metadata (stock, side, size, time sent and completed, broker, algo); fill-by-fill data (every child fill with timestamp, price, venue, contra-side); benchmark comparisons (average fill against arrival, VWAP, TWAP, close, and any custom benchmark); the cost decomposition (spread, impact, timing, opportunity); and context (the day’s volatility, the day’s volume, news events, peer comparison). Providers deliver it as PDF or API — the format does not matter. The interpretation does.

Headline Numbers Do Not Speak for Themselves

The most common mistake is reading the headline number and stopping. The headline says: “Order XYZ123, buy 50,000 shares of AAPL, average fill $195.47, arrival price $195.30, slippage +17 cents = +8.7 bps.”

That 8.7 bps looks bad. Is it? Without context the number is nothing. How volatile was the day — on a 2σ day, 8.7 bps might be normal. What was your participation rate — at 15% of volume, 8.7 bps is excellent. How wide was the spread — with the spread itself at 5 bps, only 3.7 bps sits beyond the spread, and that part is impact. Was there news — if AAPL reported earnings at 4:30 PM, the price moved because of earnings, not because of your order.

Context also hides a couple of technical traps that flip a reading outright. The benchmark window has to match the order’s working window: an order sent at 9:55 measured against 10:00-10:30 VWAP is measured wrong. Overnight gaps do not belong to the execution: a buy order sent at 9:30 AM measured against Friday’s close charges the gap to your account. Both sound elementary; both happen quietly and constantly in automated report pipelines.

The Decomposition: One Number into Four Causes

The standard decomposition is the same one from the pre-trade TCA article:

Cost=Spread cost+Impact+Timing+Opportunity\text{Cost} = \text{Spread cost} + \text{Impact} + \text{Timing} + \text{Opportunity}

The only difference post-trade is that each component is computed from realized fills and realized market data — known quantities, not estimates.

Spread cost books the half-spread at the moment of each fill, with passive fills booked as credits. For a buy order with a 2-cent spread (half-spread 1 cent), filling 60% of the volume at the offer and 40% at the bid, spread cost is 1×0.6−1×0.4=0.21 \times 0.6 - 1 \times 0.4 = 0.2 cents per share — fills at the offer pay the half-spread, fills at the bid earn it, and the two sides must net. Impact is the price concession attributable to your order itself, after removing spread and timing: impact = (average fill − arrival) − (the drift of the mid over the interval) − spread cost. Timing is the mid-price drift over the working interval applied to the filled size: if the stock drifted up 0.5% during your 30 minutes of work, timing cost is 0.5% on the filled portion. Opportunity is the price move on the shares you never filled: complete only 80%, and if the remaining 20% of the notional got 1% more expensive after you gave up, opportunity cost is roughly 1% × 20% × the order’s notional.

Two disciplines. First, the four components must sum to the total shortfall versus arrival — if they do not, the decomposition is wrong. Second, do not count the spread twice: if impact is already measured as fill price minus the mid at fill time, the half-spread cannot also be packed into another component — impact should be the concession beyond the spread.

Attribution: From Components to Causes

Decomposition answers “where did the money go”; attribution answers “whose account does it go on”. Of the 8.7 bps paid on AAPL yesterday, how much was the broker’s fault, how much the algo’s, how much the venue’s, and how much was simply the day’s? There are five dimensions, each worth pulling apart.

Which broker: compare fills on comparable orders across brokers — the broker that consistently delivers 1-2 bps less impact earns more flow. Which algo: when a broker offers VWAP, POV, and IS algos, you want to know which one is best for which stock under which conditions. Which venue: trace each fill to where the liquidity came from — lit exchanges, dark pools, and internalizers have different cost profiles. What time of day: orders worked at the open have a different cost distribution than orders worked mid-day, and you can only schedule better once you know the difference. What volatility regime: on high-vol days every cost rises together, so broker evaluation has to compare like with like.

“Like with like” deserves expansion, because it is the step in attribution most easily fudged. Averaging across all orders treats 50,000 shares of AAPL and 50,000 shares of a small-cap as the same object — different spreads, different depth, different impact profiles — and the average means nothing. The right construction is peer groups: small-cap orders against your firm’s other small-cap orders, large-cap against large-cap, with each broker’s performance judged inside the stock-size peer group. Most TCA providers offer peer-group comparison; use it. A broker that is good in small-caps and poor in large-caps is entirely possible, and “best broker” depends on what you are trading. The time dimension works the same way: Mondays tend to be more volatile (weekend news backlog), Fridays quieter, month-end carries rebalancing flow, pre-holiday sessions are thin. Control for day-of-week when comparing brokers — the one that handles Monday mornings well is worth more than the one that only looks good on Friday afternoons.

The most common concrete output of attribution is the broker scorecard. For each broker, tally per quarter the average IS across all orders, average spread cost, average impact, the variance of IS, fill rates, information-leakage indicators, and per-algo performance, then weight by order characteristics (size, urgency, stock type) into a comparable cross-section:

MetricBroker ABroker BBroker C
Avg IS (bps)4.25.86.1
Avg impact (bps)2.13.43.8
Avg timing (bps)1.31.51.7
Fill rate98%95%99%
Variance (bps²)122814
Order count1,2471,1891,098

The reading: Broker A is best on average; Broker C has the highest fill rate and the worst costs; Broker B has the widest variance — and for a risk-averse desk, variance is itself a cost.

Algo comparison carries its own dedicated trap. Within one broker you can compare VWAP, POV, IS, liquidity-seeking, and dark-only algos, but the right question is not “which is best overall” — it is “which is best for which kind of order”: VWAP for small, low-volume names with predictable volume; POV for liquid large-caps with no urgency; IS for high-alpha urgent orders; liquidity-seeking for hard-to-fill names. And the measuring stick pre-decides the winner: score every algo against arrival and the IS algo wins (it was designed to minimize arrival shortfall); score against VWAP and the VWAP algo wins. Benchmark choice determines the conclusion more often than algo choice does — which is exactly the previous article’s “no benchmark is neutral” coming home to roost in the attribution step.

Leakage Detection: The Hardest Attribution

One category of cost should not appear in any component: your order’s information escaping before you trade. The detection idea is to examine market behavior in the seconds to minutes before your order reaches the venue — persistent adverse price moves just before your fills, increased quoting activity from specific counterparties, volume spikes before your order arrives, and price reversion after you trade (the price walking back once you are done) are all signs that someone got there first.

def detect_leakage(fills, market_data, window_seconds=30):
    """Detect adverse price moves just before each fill."""
    flags = []
    for ts, price, side in fills:
        pre_window = market_data[(ts - window_seconds):ts]
        if side == 'buy' and pre_window['price'].pct_change().sum() > 0.001:
            flags.append((ts, 'adverse_pre_fill'))
    return flags

This is a toy. Real leakage detection uses fuller statistical tests and controls for the overall market move; commercial products (the Markit lineage, now folded into S&P Global after successive mergers) score every fill with a “leakage score” based on the price behavior around it. Once attribution points at leakage, the remedy is also the bluntest one available: change broker or venue, without sentiment.

Calibration: Feeding Post-Trade Back into Pre-Trade

Here is the critical jump in the loop. The simplest calibration tracks the realized-versus-predicted gap order by order:

Bias=Realized−Predicted\text{Bias} = \text{Realized} - \text{Predicted}

Persistently positive bias means the pre-trade model systematically underestimates costs; persistently negative means it overestimates. With a bit more machinery, regress realized cost on predicted cost plus stock-specific factors:

Realizedi=α+β⋅Predictedi+γ⋅Stocki+ϵi\text{Realized}_i = \alpha + \beta \cdot \text{Predicted}_i + \gamma \cdot \text{Stock}_i + \epsilon_i

Fit α\alpha, β\beta, γ\gamma on history; the fitted model is your updated pre-trade estimator. In practice α\alpha often comes out at a few bps — fixed costs the model does not cover, commissions and fees; β\beta near 1.0 says the model’s scale is roughly right; and γ\gamma varies by stock, because some names are just systematically more expensive to trade.

Set the calibration inside the full loop:

  1. Pre-trade: estimate order cost from the historical model.
  2. Real-time: track the working order against benchmarks.
  3. Post-trade: measure realized cost against the estimate, decompose, attribute.
  4. Calibrate: update the pre-trade model with realized costs.
  5. Broker feedback: share results with brokers, adjust allocations.
  6. Algo selection: update the algo-choice rules by what has actually worked.
  7. Back to pre-trade: the next order uses the updated model.

Skip step 4 and the loop is broken. Most shops break exactly there — not for lack of intent, but for lack of the data infrastructure that joins pre-trade predictions and post-trade realizations in one pipeline. The shops that have it hold a genuinely compounding edge: their pre-trade estimates improve with time, and their execution decisions improve with them. The edge is roughly quantifiable: a desk trading $5B a year at an average cost of 10 bps pays $5M a year in execution; a 2 bps improvement in execution quality is worth $1M a year, and the TCA infrastructure needed to capture it costs a fraction of that. Run it the other way and the cost of bad TCA is the cost of bad decisions: a scorecard ranked on the wrong benchmark routes flow to the wrong brokers; ignored leakage keeps a losing channel alive; and without the decomposition you cannot tell whether a bad day was your fault or the market’s.

The Recurring Faces of the Numbers

Once the loop is running, the post-trade numbers keep making a handful of recognizable faces, each pointing to an action. High impact with low spread cost: you are too aggressive, crossing the spread too often — slow down or post more passively. High timing cost with low impact: you waited too long, and the market moved against you while you were being patient — execute faster or start earlier. High opportunity cost: the order did not finish — either the size was too large for the horizon or the algo was too passive. Persistent positive shortfall against every benchmark: the broker is underperforming — investigate. High variance: some orders great, some terrible — either the algo is inconsistent or your order mix is heterogeneous and needs to be treated separately. Leakage indicators lighting up: as above — switch.

Honesty: Internal and External

The most useful post-trade report is the one that says “we got this wrong”; the least useful is the one built to excuse. A trader reporting “every order beat its benchmark” is either using the wrong benchmark or cherry-picking. A trader reporting “we averaged 3 bps of losses this quarter” is telling the truth — and truth-tellers improve over time. The implication for PMs is direct: reward honest reporting, do not punish it. Fire a trader for admitting a mistake and the next trader will not admit mistakes; the entire TCA function becomes theater.

The same standard applies externally. A good broker’s TCA numbers should reconcile with yours: they say 4 bps, you compute 6 bps from the same data, someone has a calculation error. A professional broker will reconcile with you; a bad one says “our numbers are right, yours are wrong” and offers no explanation — that is a red flag. A broker unwilling to reconcile is a broker to replace. Execution is hard enough without a counterparty whose numbers you cannot trust.

The Counterfactual Boundary

Post-trade TCA has an epistemological limit it cannot escape: it measures what you paid, not what you would have paid under a different strategy. An order can only be executed once; there is no replay with a different algo. All post-trade analysis is therefore observational, not experimental. The closest you can get to an experiment is parallel testing: split the same large order 50/50 between two brokers or two algos, run them simultaneously, compare. The drawback is obvious — each half runs at half size, which changes the dynamics — but even noisy, this is the cleanest controlled data available, and some shops have made it standing procedure.

Organization, Cadence, and Compliance

Assembling all of this into a working system, a serious buy-side desk needs six components, each feeding the next: a pre-trade cost estimator, a real-time TCA dashboard, a post-trade reporting system, a calibration engine, broker scorecards, and leakage detection. Real-time and post-trade serve different audiences — real-time is for the trader managing live orders, post-trade for the PM who wants to know what happened and the analyst who updates the models — and the two are integrated by the same data pipeline. Reporting cadence is layered by use: daily for traders to catch outliers, weekly for the head trader’s review, monthly for the PM’s view of execution quality, quarterly for broker scorecards and allocation decisions, annually for the CIO and compliance. Daily catches problems fast; quarterly catches structural ones.

Compliance is not a side effect. Under MiFID II in Europe and best-execution rules in the US, firms must be able to demonstrate best execution for clients, and post-trade TCA reports are the evidence: documented (retained at least 5 years), reviewed regularly (at least annually), actionable (actually used in broker allocation), and independent — broker-provided reports alone do not count. Most firms put this in the hands of a TCA team independent of the trading desk, and the independence is not bureaucratic decoration: traders reviewing their own execution is a plain conflict of interest.

At the level of an individual trader, all of this compresses into one morning routine: open the dashboard and review yesterday’s orders, flagging outliers; check the broker’s reports against your own fills and note discrepancies; review algo performance and consider switching anything that lagged; recalibrate when realized costs diverge from estimates; raise big problems with the PM, summarize otherwise. Traders who do this daily know what works and what does not. Traders who do not, react to the PM’s questions instead of anticipating them.

The Closing Checklist

Check your desk against this:

  1. Compute IS for every order, every day.
  2. Decompose into spread, impact, timing, opportunity.
  3. Attribute to broker, algo, venue.
  4. Compare within peer groups.
  5. Run leakage detection.
  6. Calibrate the pre-trade model quarterly.
  7. Update broker scorecards quarterly.
  8. Reconcile broker reports against your own.
  9. Document everything for compliance.
  10. Feed insights back to traders in real time.

Do all ten and you are in the top tier of desks. Do five and you are average. Fewer than three and you are flying blind.

References

  • Harris, L. (2003). Trading and Exchanges: Market Microstructure for Practitioners. Oxford University Press. Ch. 23. ISBN: 978-0-19-514470-3.
  • Perold, A. F. (1988). “The Implementation Shortfall: Paper Versus Reality.” Journal of Portfolio Management, 14(3), 4-9.
  • Almgren, R., & Chriss, N. (2000). “Optimal Execution of Portfolio Transactions.” Journal of Risk, 3(2), 5-39.
  • Bertsimas, D., & Lo, A. W. (1998). “Optimal Control of Execution Costs.” Journal of Financial Markets, 1(1), 1-50.
  • Kissell, R., Glantz, M., & Malamut, R. (2004). Optimal Trading Strategies. AMACOM.