1. Why TCA exists
A strategy that looks profitable on paper can be flat or negative in production. The gap is almost always execution cost: the spread you crossed, the impact your own order pushed into the book, the shares you never managed to fill, and the quiet bleed of trading against better-informed counterparties. As we argue in the illusion of backtesting, ignoring these costs is the single most common reason alpha evaporates on contact with a live market.
TCA is the discipline of measuring each of those costs against a well-defined benchmark, so you can attribute the gap, compare venues and algorithms, and feed the results back into how you trade. The whole field rests on one idea: pick a benchmark price, and measure everything as a signed deviation from it.
2. The cost stack at a glance
Every execution can be decomposed into the same layers. Each has its own benchmark, its own formula, and its own remedy.
| Layer | Benchmark | What it captures |
|---|---|---|
| Arrival slippage | Arrival mid | Total cost of the fills vs the price when the order arrived |
| Implementation shortfall | Decision price | Execution cost + opportunity cost of unfilled shares + fees |
| Effective spread | Quote mid | The half-spread actually paid to cross |
| Market impact | Pre-trade mid | How far your own order moved the price (temporary + permanent) |
| Adverse selection | Post-trade mid | Whether the counterparty knew more than you (markouts) |
3. Arrival slippage: the simplest benchmark
Start where every TCA report starts. The arrival price is the mid at the instant your order reaches the market; arrival slippage is the signed difference between what you actually paid on average and that price, usually expressed in basis points:
slippage_bps = d × ( avgFill − arrival ) / arrival × 104
Here d is +1 for a buy and −1 for a sell, so a positive number is always adverse — you paid up on a buy, or sold low on a sell. Arrival slippage is blunt but honest: it rolls spread, impact, and timing into a single number, which makes it the right headline metric and the wrong tool for attribution. To attribute, you need the layers below.
4. Implementation shortfall: the full decomposition
Arrival slippage only counts the shares you filled. But an order that fails to complete has a cost too — the shares you wanted and never got, while the price ran away from you. Perold's (1988) implementation shortfall is the framework that captures both, benchmarked against the decision price (the mid when the idea was formed):
IS = execution cost + opportunity cost + fees
The execution cost is the deviation of the average fill from the decision price, on the shares you executed. The opportunity cost prices the unfilled remainder at where the market ended up — the paper loss of not completing. Fees are explicit. A worked buy makes it concrete:
| Component | Calculation | Cost |
|---|---|---|
| Execution | (100.5 − 100) × 800 filled | 400 |
| Opportunity | (101 − 100) × 200 unfilled | 200 |
| Fees | explicit | 5 |
| Total shortfall | decide 100, fill 800/1000 @ 100.5, close 101 | 605 |
The power of the decomposition is diagnostic: a desk whose shortfall is mostly opportunity cost is trading too passively and missing fills; one whose shortfall is mostly execution cost is crossing too aggressively and paying impact. The remedy is different in each case — and you only know which by splitting the number.
5. The spread you cross
Zoom into a single fill and the first cost is the spread. The effective spread measures what you actually paid to cross relative to the quote mid at the moment of the trade; the realized spread measures what a liquidity provider kept after the price reverted. The difference between them is not noise — it is impact, which is the next layer. These spread measures, along with Kyle's lambda and Roll's estimator, turn individual prints into per-trade cost.
6. Market impact: your own footprint
Every order you send moves the price against you — a little for a small order, a lot for a large one. Impact splits into a temporary component (the price you push while trading, which reverts after you stop) and a permanent component (the lasting shift your information leaves behind). The empirical square-root law captures the first-order scaling — impact grows with volatility and the square root of your participation — while the Almgren-Chriss framework makes the temporary/permanent split explicit and lets you trade it off against timing risk.
Impact is the cost that couples directly to how you trade. Slice an order more finely and you pay less temporary impact but sit in the market longer, exposed to drift; cross aggressively and you pay more impact but less timing risk. That trade-off is the whole reason execution scheduling — TWAP, POV, and optimal trajectories — exists.
7. Adverse selection: the cost you can't see coming
The subtlest layer is who you traded against. If the counterparty knew something you didn't, the price keeps moving their way after the fill — and that drift is a pure cost, invisible to spread and impact accounting. The measure is the markout: the signed change in the mid over a horizon after the trade. Persistently positive markouts against your passive fills mean your quotes are being adversely selected. The forward-looking companion, VPIN, estimates that toxicity before you quote; both are driven by persistent order flow imbalance.
8. Closing the loop
TCA is only worth running if it changes behaviour. The output of a good cost model is not a scorecard — it is a set of decisions: widen quotes against toxic flow, slow down when opportunity cost is low and impact is high, route to the venue whose markouts are benign, and size orders to the participation the impact model can bear. Measuring the cost stack and feeding it back into execution and microstructure logic is what separates a desk that knows its costs from one that merely pays them.
9. Reference implementation
The entire cost stack is implemented in our open-source orderflow-metrics library — dependency-free, in both TypeScript and Python. A single fill's worth of TCA looks like this:
import {
arrivalSlippageBps,
implementationShortfall,
effectiveSpread,
squareRootImpact,
markout,
} from "orderflow-metrics";
// Headline: cost vs the arrival mid
arrivalSlippageBps("buy", 100, 100.5); // 50 bps
// Full decomposition vs the decision price
implementationShortfall("buy", 100, 100.5, 800, 1000, 101, 5);
// { execution: 400, opportunity: 200, fees: 5, total: 605 }
// Per-fill spread and impact
effectiveSpread(101, 100, "buy"); // 2 — cost vs the quote mid
squareRootImpact(0.02, 1_000, 1_000_000); // Y·σ·√(Q/V)
// Did we get picked off?
markout("buy", 100, 100.5); // +0.5 — informed flow
The same functions exist in the Python distribution in snake_case. Point them at a stream of fills, aggregate by venue, algo, size bucket, or time of day, and you have a full TCA pipeline in a few dozen lines and zero dependencies.
10. Conclusion
Execution cost is not a single number — it is a stack, and every layer has a benchmark, a formula, and a fix. Arrival slippage tells you the headline; implementation shortfall attributes it between trading and missing; spread, impact, and markouts explain the mechanics fill by fill. Measure all of them, and the invisible bleed that kills paper strategies becomes a set of levers you can actually pull. Explore each layer in depth across our quantitative research library, or read the code in our open-source metrics.