Research, Data and Risk Platforms · Technology
22Post-Trade Systems
On 28 May 2024 most US securities trades began to settle one business day after the trade date instead of two. The rule that made the change also required brokers to have agreements or policies aimed at completing allocations, confirmations and affirmations by the end of the trade date, and the industry’s plan moved the affirmation cut-off of the central matching service from 11:30 a.m. on the day after the trade to 9:00 p.m. on the trade date itself. For the operations team that fixes a trade whose confirmation does not agree with the firm’s booking, the time available went from a working day to an evening. This chapter builds the systems that decide how many trades need fixing — matching, settlement instructions, reconciliation — and measures what the shorter cycle does to the ones that remain.
22.1 From booked trade to settled trade
Chapter 21 ended with a booked trade in the canonical model. Between booking and settlement (Book 1, chapter 5) the trade must be agreed with the counterparty, instructed to the agents who move the securities and cash, settled, and then checked against what the custodian actually holds. Every step compares two records of the same thing, and every comparison that fails is a piece of manual work with a deadline.
Definition 22.1 (Trade confirmation, affirmation)
A trade confirmation is the executing party’s statement of a trade’s terms — security, side, quantity, price, trade and settlement dates, accounts — sent to its counterparty. Affirmation is the counterparty’s (for an institutional trade, the investment manager’s or its custodian’s) agreement that the confirmation is right, after which the trade can be settled without further intervention.
Definition 22.2 (Settlement instruction, standard settlement instruction)
A settlement instruction tells a settlement agent to deliver or receive a security against payment, with the quantity, amount, settlement date and both parties’ accounts. A standard settlement instruction (SSI) is the account details a counterparty uses for a given market, kept once as reference data so that each trade’s instruction is generated rather than typed.
The chapter’s week is a model, and every number in it comes from the model: 500 institutional equity trades a day, executed by eight brokers for five funds, each trade booked in the firm’s canonical model. The brokers’ confirmations carry discrepancies planted at stated rates: a wrong price for 1% of trades, a wrong settlement date for 1%, a wrong account for 1.5%, a wrong quantity for 0.5%, and no confirmation at all for 1%. Three of the eight brokers also round the average price to four decimals, which is not an error at all.
22.2 Confirmation and affirmation
Definition 22.3 (Confirmation matching, matching tolerance)
Confirmation matching pairs each booked trade with a confirmation that agrees on key fields (security, side, counterparty, trade date, account holder) and then compares the other fields; a matching tolerance is the largest difference in a compared field that still counts as agreement. A pair within every tolerance is matched; a pair outside some is a partial match, reported with the fields that differ; a trade with no candidate is unmatched.
def match(ours: list, theirs: list, keys: tuple, tolerances: dict) -> MatchResult:
"""Pair each trade with the confirmation that agrees on the keys and differs in the
fewest fields (ties: the first); all within tolerance is a match, else partial."""
res = MatchResult()
pool: dict = {}
for i, t in enumerate(theirs):
pool.setdefault(tuple(t[k] for k in keys), []).append(i)
used = set()
for o in ours:
cands = [i for i in pool.get(tuple(o[k] for k in keys), []) if i not in used]
if not cands:
res.ours_only.append(o)
continue
best = min(cands, key=lambda i: (len(_differs(o, theirs[i], tolerances)), i))
used.add(best)
diff = _differs(o, theirs[best], tolerances)
if diff:
score = 1 - len(diff) / len(tolerances)
res.partial.append((o, theirs[best], score, diff))
else:
res.matched.append((o, theirs[best]))
res.theirs_only = [t for i, t in enumerate(theirs) if i not in used]
return res
The key fields must be exact, because they decide which record is compared with which; the tolerances apply to what is compared. Quantities, dates and accounts have no tolerance: a trade for 9 500 shares is not a trade for 9 400. The price is the one field where a tolerance makes sense, because the firm and the broker compute an average price over many fills and may carry it to different precision.
fig_posttrade.py.Figure 22.2 shows the two ways to get a tolerance wrong. Too tight, and the rounding convention of three brokers becomes 177 breaks on Monday that nobody needs to fix: a strict match rate of 60.4%. Too loose, and a wrong price of a few cents is matched, and the error is found — if at all — when the cash does not agree. Between the two lies a plateau from half a unit in the fourth decimal to a cent, where the match rate is 95.8% and every remaining break is a real one. The right tolerance is the plateau’s lower end, derived from the precision each counterparty is known to use, and recorded per counterparty in reference data rather than chosen globally.
22.3 Settlement instructions
Once affirmed, each trade becomes an instruction: for Monday’s first trade, a sale of 9 400 shares at $97.586941, a deliver versus payment of $917 317.25 on the settlement date, from the fund’s custody account to the broker’s agent and account taken from the SSI table. Nothing in the instruction is typed; every field comes from the canonical trade or from reference data. That is the point of the SSI table: a wrong account on one confirmation is a break on one trade, but a wrong account in the SSI table is a fail on every trade with that counterparty in that market until someone notices, so SSI changes go through the same approval as the parameter changes of chapter 16 — proposed, checked by a second person, effective from a stated date, never edited in place.
In the model, wrong accounts are the most common discrepancy: 43 of the week’s 138 breaks, against 32 missing confirmations, 27 wrong settlement dates, 26 wrong prices and 10 wrong quantities (Figure 22.3). They are also the kind a firm can remove at the source, by maintaining SSIs once and sharing them with its counterparties instead of letting each side key them.
22.4 Reconciliation and breaks
Definition 22.4 (Reconciliation, reconciliation break)
Reconciliation is the periodic comparison of two records that should agree — the firm’s positions or cash against a custodian’s or prime broker’s statement, the firm’s trades against a clearing broker’s — item by item. A reconciliation break is an item on which they differ: present on one side only, or present on both with different values.
def reconcile(ours: dict, theirs: dict, groups: dict | None = None,
opened: float = 0.0) -> list[Break]:
"""Compare quantities by key; `groups` maps a custodian key to several of ours
(a block the firm allocated)."""
ours, theirs = dict(ours), dict(theirs)
for tk, oks in (groups or {}).items():
total = sum(ours.pop(k, 0) for k in oks)
ours[tk] = ours.get(tk, 0) + total
out = []
for k in sorted(set(ours) | set(theirs), key=str):
a, b = ours.get(k), theirs.get(k)
if a != b:
x, y = (a if a is not None else 0), (b if b is not None else 0)
out.append(Break(classify(a, b), k, x, y, opened))
return out
The difficulty of reconciliation is rarely the comparison; it is the keys. The custodian may report one position where the firm holds five allocations (a one-to-many group), a cash movement may be the sum of a day’s trades (an aggregate), and identifiers may differ between the two sides, so the reference data of chapter 6 decides whether a difference is real. A break then needs three more things before it is useful: a kind (missing on one side, a quantity difference), an owner, and an age.
Definition 22.5 (Break ageing)
Break ageing is the classification of open breaks by the time since they were opened, in buckets (under a day, one to three days, three to seven, more), reported daily with the owner of each break; the old buckets are where risk hides, because a break that survives several reconciliations is one that nobody understands.
22.5 Operating under a short settlement cycle
The model’s operations team is three people. Breaks are worked largest value first, each taking a random time whose average depends on the kind (30 minutes for a settlement date, 45 for a price or a quantity, an hour for an account, an hour and a half to chase a missing confirmation). The window is where the two cycles differ. Under T+2 the model gives the team the next working day, 08:00 to 17:00, before a trade can no longer be settled on time; under T+1 it gives the evening of the trade date, 17:00 to the 21:00 affirmation cut-off. These windows are the model’s choices, set on the cut-offs quoted in the hook; a real team also works during the trading day, which helps both cycles equally.
def resolve(brks: list[dict], cycle: str, seed: int = 0,
staff: int = STAFF) -> tuple[list, list]:
"""The team fixes breaks, largest value first, inside the window; (fixed, failed)."""
rng = np.random.default_rng(seed)
start, end = WINDOWS[cycle]
free = [start] * staff
order = sorted(brks, key=lambda b: -b["trade"]["qty"] * b["trade"]["price"])
fixed, failed = [], []
for b in order:
k = int(np.argmin(free))
took = float(rng.exponential(FIX_MINUTES[b["kind"]])) / 60.0
if free[k] + took <= end:
free[k] += took
fixed.append(b)
else:
failed.append(b)
return fixed, failed
| cycle | breaks | fixed | failed | value failed | recon breaks | aged 1–3 days | aged 3–7 days |
|---|---|---|---|---|---|---|---|
| T+2 | 138 | 128 | 10 | $2.74m | 4 | 4 | 0 |
| T+1 | 138 | 91 | 47 | $19.17m | 24 | 12 | 5 |
The breaks are the same under both cycles — they come from the confirmations, not the calendar — but the work they need does not fit in the evening. The week’s breaks need about 26 hours of work a day on average; the next working day gives three people 27 hours, the evening 12. Under T+2 ten trades fail in the week, $2.74 million of value; under T+1 forty-seven fail, $19.17 million, and the Friday reconciliation finds six times as many position breaks (Table 22.1). A failed trade is not lost — it settles later — but the fund does not have the securities or the cash it expected, the position service of chapter 17 must carry settled and unsettled positions separately, and some markets charge for the fail: Book 2, chapter 5, describes the fails charge in the Treasury market.
fig_posttrade.py.There are two ways back to the fails of the longer cycle, and Figure 22.4 compares them. The first is people: with seven in operations instead of three the evening absorbs the work, and the week’s fails fall to 11. The second is fewer breaks: halving the rate of wrong accounts and missing confirmations — SSIs maintained once and shared, allocations sent to the broker as soon as they are decided — brings the fails to 13 with the same three people. The second is cheaper and it lasts, which is why the move to T+1 was prepared as much in reference data and allocation workflows as in staffing.
fig_posttrade.py.The general lesson is the one of chapter 21: post-trade cost is set upstream. Every break the pipeline creates is paid for by a person against a deadline, and a shorter cycle shortens the deadline without changing the number of breaks. The measure to watch is the share of trades that go from booking to settlement untouched — the straight-through rate — by counterparty and by kind of break, together with the age of what is left.
As of September 2026 — The US move to T+1
SEC Release 34-96930 (2023) amended Rule 15c6-1 to shorten the standard settlement cycle for most broker-dealer transactions from T+2 to T+1, with a compliance date of 28 May 2024, the day after a Federal holiday. New Rule 15c6-2 requires brokers to have agreements or policies aimed at completing allocations, confirmations and affirmations as soon as technologically practicable and no later than the end of the trade date; new Rule 17Ad-27 requires clearing agencies that provide a central matching service to facilitate straight-through processing and report on it each year. The release cites the industry’s T+1 Report, which moved the affirmation cut-off from 11:30 a.m. ET on the day after the trade to 9:00 p.m. ET on the trade date.
22.6 Tutorial: a week of confirmations under two cycles
Goal. Match a week of trades with planted discrepancies, instruct, reconcile and age the breaks, then replay the week under T+1. End state: Figure 22.2 and Table 22.1.
- Trades and confirmations:
pl_posttrade.trades(0, 1)andconfirms(ours); count the planted kinds. - Matching:
match_rates(tols=…)over tolerances from to . - Instructions: build an
SSITablefor the eight brokers and generate the instruction of every matched trade. - Breaks and fixes:
week("T+2")andweek("T+1"). - Reconciliation:
custodian_recon(cycle), the breaks and their ageing.
What to change next. Add a cash reconciliation (the day’s net payments per fund against the custodian’s cash statement) with aggregate matching; let the team work part of the trading day and see whether T+1 still needs more people.
22.7 Build: post-trade
Purpose. Agree every trade with its counterparty, instruct it, and prove afterwards that the books agree with the custodian, with every exception in one queue.
Interface. match, match_rate, MatchResult, SSITable.instruction, reconcile (with groups), Break, classify, age.
Rules. Keys exact, tolerances per field and recorded; instructions generated from SSIs, never typed; SSI changes approved and dated; every break has a kind, an owner and an opening time; ageing reported daily.
Acceptance tests. code/firm/posttrade/tests/: matched, partial and unmatched trades on both sides; the best candidate chosen among several; an instruction from the SSI table and a missing SSI; one-to-many reconciliation and the ageing buckets.
Stretch. Cash and trade reconciliation with aggregate matching; an affirmation workflow with cut-off times and escalation; a straight-through rate report by counterparty.
Sources and further reading
- US Securities and Exchange Commission, Shortening the Securities Transaction Settlement Cycle, Release No. 34-96930, 2023.
- One Quant Book 1, chapter 5 (settlement, the settlement cycle, fails, delivery versus payment); Book 2, chapter 5 (the fails charge); Book 16, chapter 4 (the custodian).
22.8 Exercises
Exercise 22.1 ★
Why are the key fields matched exactly and only the other fields with a tolerance?
Solution
Solution of Exercise 22.1.
The keys decide which confirmation is compared with which trade; a tolerance there would pair a trade with someone else’s confirmation and then report a false difference, or a false match. The compared fields are where a difference is information — and only the price has a legitimate reason (precision) to differ slightly.
Exercise 22.2 ★
A broker rounds prices to four decimals. What is the smallest price tolerance at which its correct confirmations always match?
Solution
Solution of Exercise 22.2.
Rounding to four decimals moves the price by at most half a unit in the fourth decimal, $0.00005; at that tolerance every correct confirmation matches, which is where the plateau of the chapter’s figure begins.
Exercise 22.3 ★
Under T+1, how many of the week’s breaks were fixed, and what share of the breaks failed?
Solution
Solution of Exercise 22.3.
91 of the 138 breaks were fixed in the evening windows; 47 failed, 34%.
Exercise 22.4 ★★
Why is a wrong account in the SSI table worse than a wrong account on one confirmation?
Solution
Solution of Exercise 22.4.
A wrong account on one confirmation breaks one trade and is caught by matching. A wrong account in the SSI table is copied into every instruction for that counterparty and market, matches on both sides because both use it, and fails every such trade until the agent rejects them.
Exercise 22.5 ★★
The custodian reports one position of 3 000 shares where the firm holds allocations of 1 000 and 2 000 to two funds under the same account. How does the reconciliation avoid three breaks?
Solution
Solution of Exercise 22.5.
By a one-to-many group: the custodian’s key is mapped to the two allocations, whose quantities are summed to 3 000 before the comparison, so the two sides agree and no break is raised.
Exercise 22.6 ★★
Why does the Friday reconciliation find only 4 position breaks under T+2 when 10 trades failed?
Solution
Solution of Exercise 22.6.
Because only trades due to settle by Friday are in Friday’s positions. Under T+2 the trades of Thursday and Friday settle the next week, and 6 of the 10 fails were among them; the other 4 each made one position break.
Exercise 22.7 ★★★
Coding. Rerun week("T+1", staff=s) for from 3 to 8 and find the smallest team that fails no more trades than T+2 with three people.
Solution
Solution of Exercise 22.7.
47, 35, 22, 14, 11 and 10 fails for 3 to 8 people: eight people are needed to match T+2’s 10 exactly, seven to come within one.
Exercise 22.8 ★★★
Find the flaw. "Our match rate went from 95.8% to 96.8% this month after we widened the price tolerance to five cents: operations is doing better."
Solution
Solution of Exercise 22.8.
The extra percentage point is five wrong prices now accepted as matches: the breaks did not go away, they were hidden until the cash fails to agree. A match rate is only meaningful at a tolerance derived from the counterparties’ precision, and should be reported with the number of breaks found later by reconciliation.
22.9 Problem: One Evening Instead of a Day
Problem 22.1
Weekend problem — one evening instead of two days
The chapter’s week: 500 trades a day, eight brokers, five funds, planted discrepancies, three people in operations.
Part I — Agreeing the trade.
- What is compared between a booked trade and a confirmation, and what must be exact?
- What does affirmation add to matching?
- Why do three brokers produce breaks at a tight tolerance, and how many trades match at $0.0000001?
- Where is the plateau of the match rate, and what is the rate there?
- What happens at a tolerance of five cents?
Part II — Instructing and reconciling.
- What does the settlement instruction of Monday’s first trade contain, and where does each field come from?
- How should SSI changes be controlled?
- What makes reconciliation hard in practice?
- What does a break need beyond the difference itself?
- Why are the old ageing buckets the ones to watch?
Part III — The two cycles.
- What window does the model give the team under each cycle, and why?
- How much work do the breaks need per day, and how much does each window give?
- How many trades fail under each cycle, and for how much value?
- Which kinds of break fail most under T+1?
- What does the Friday reconciliation find under each cycle?
Part IV — The verdict.
- State the named result: the share of trades matched automatically at each tolerance, the breaks remaining at the affirmation cut-off under a two-day and a one-day cycle, and the fails that follow.
- How many people does T+1 need to fail no more trades than T+2 with three?
- What does halving wrong accounts and missing confirmations achieve?
- Which of the two would you fund, and why?
- In one sentence: what does a shorter settlement cycle change?
Solution
Solution of Problem 22.1.
- Security, side, counterparty, trade date and fund are keys and must be exact; price, quantity, settlement date and account are compared, the price within a tolerance.
- The investment manager’s agreement that the terms are right, which lets the trade settle without further intervention.
- They round the average price to four decimals, so their correct prices differ from the firm’s by up to $0.00005; at $0.0000001, 60.4% of trades match.
- From $0.00005 to $0.01, at 95.8%.
- Five wrong prices are accepted, and the rate rises to 96.8%.
- A deliver versus payment of 9 400 shares for $917 317.25 on the settlement date: security, quantity, amount and date from the trade, the fund’s account from the canonical model, the broker’s agent and account from the SSI table.
- Proposed, approved by a second person, effective from a date, never edited in place.
- The keys: one-to-many and aggregated positions and identifiers that differ between the two sides.
- A kind, an owner and an age.
- A break that survives several reconciliations is one nobody understands, and it is where losses and misstatements accumulate.
- The next working day (08:00–17:00) under T+2, the trade date’s evening (17:00–21:00) under T+1: the cut-offs quoted in the chapter.
- About 26 hours a day; the day gives three people 27, the evening 12.
- 10 trades, $2.74 million, under T+2; 47, $19.17 million, under T+1.
- Wrong accounts and missing confirmations, 18 each.
- 4 position breaks, all one to three days old, under T+2; 24 under T+1, 7 under a day, 12 one to three days and 5 three to seven.
- Named result. At a price tolerance of $0.0000001, 60.4% of trades match automatically, from $0.00005 to $0.01 95.8%, at $0.05 96.8% with five wrong prices accepted. Of 138 breaks in the week, 10 remain unfixed at the cut-off under a two-day cycle and 47 under a one-day cycle, failing $2.74 million and $19.17 million of trades.
- Seven people bring the fails to 11, eight to 10.
- Fails fall to 13 with the same three people.
- Halving the errors: it costs reference-data and workflow work once, instead of four more salaries every year, and it lowers every later cost of the breaks, not only the fails.
- It shortens the time to fix a break without changing how many there are.
22.10 Interview questions
Interview question 22.1 ★ developer
What is a reconciliation break, and what would you put in a break report?
Solution
Solution of Interview question 22.1.
An item on which two records that should agree differ. The report gives the key, both values, the kind, the owner, when it was opened and its age bucket, sorted by value and age.
What the interviewer is looking for: Kind, owner, age; value first.
Interview question 22.2 ★★ developer
How do you choose the tolerances of a confirmation-matching engine?
Solution
Solution of Interview question 22.2.
Exact keys; zero tolerance on quantities, dates and accounts; a price tolerance per counterparty from the precision it uses; then check the match rate against the breaks found later, to make sure the tolerance does not hide errors.
What the interviewer is looking for: Tolerance from precision, per counterparty.
Interview question 22.3 ★★ developer
Your custodian reports positions by account and your books hold them by fund and strategy. Design the reconciliation.
Solution
Solution of Interview question 22.3.
Map each fund and strategy position to the custodian account through reference data, sum the firm’s positions into the custodian’s keys (one-to-many), compare, and raise breaks with owners; keep the mapping versioned so yesterday’s reconciliation can be rerun.
What the interviewer is looking for: Key mapping and one-to-many groups.
Interview question 22.4 ★★ developer
The market moves to a one-day settlement cycle. What changes in your post-trade systems and team?
Solution
Solution of Interview question 22.4.
Allocation, confirmation and affirmation move to the trade date; the time to fix a break shrinks to hours, so fewer breaks (SSIs, early allocation) matter more than more people; the position service must track settled and unsettled positions and funding moves forward a day.
What the interviewer is looking for: Fewer breaks, earlier.
Interview question 22.5 ★★★ developer
Design the post-trade platform of a firm that trades equities with thirty brokers for a hundred funds.
Solution
Solution of Interview question 22.5.
The canonical trade from booking; a matching engine with per-counterparty tolerances; affirmation tracking against the cut-off; an approved, dated SSI store generating instructions; reconciliations of positions, cash and trades with one-to-many and aggregate matching; one break queue with kinds, owners and ageing; a straight-through rate by counterparty as the measure.
What the interviewer is looking for: One break queue, measured upstream.