Where you are. Sixteen lessons built the parts: two doors onto a company, a custody chain, a bond and its pricing, a curve, an auction, a book, a maker, and the cast who use all of it. This project runs them together as one system, and ends by naming the gap that the whole of module 5 exists to close.
The brief
Four things, in one script, over one seeded day.
Match. Drive the order book with a fixed tape: six limit orders that build the book, then a market buy of fifty and a market sell of sixty that consume it. The trade log must show price-time priority doing its work - two fills at 101 in arrival order, then a walk down through 100, 100 and 99.
Price. Round-trip fifty seeded bonds through the pricer: price from yield, recover yield from price, and check the worst error. It comes back around a ten-trillionth, which is far more precision than any market needs and exactly the point: the conversion is arithmetic, not opinion.
Settle. Move ten shares from a seller at one broker to a buyer at another, against a thousand of cash, as one act. The cash leg settles across two banks on the miniledger, exactly as module 1 taught. The ownership leg moves down the custody chain from lesson 3. Both, or neither.
Refuse. Attempt a trade the buyer cannot fund, and prove that nothing moved: not the cash, not the shares. Validation happens before any posting, which is module 1’s submit-and-settle discipline and module 3’s both-or-neither rule, applied to cash against an asset.
The idea in one paragraph
A market is not one mechanism but four, and the project’s value is in running them together rather than in any one of them. Matching decides who trades with whom and at what price. Pricing converts between a yield and a price without opinion entering anywhere. Settlement moves the cash and the ownership as a single act, so that no state exists in which one has moved and the other has not. And refusal is the same discipline stated negatively: a trade that cannot be funded changes nothing at all. Each was built alone in this module; the project checks that they compose without any of them quietly violating what the others assume.
Why the settlement leg is the point
The matching engine is the part that looks like a market. The settlement leg is the part that makes it real, and it is where this module hands over to the next.
When the buyer’s cash and the seller’s shares move as one act, neither party is ever exposed to the other. That is delivery versus payment, which module 3 built for currencies and this project applies to cash against a security. Inside one script it is easy: a single function sees both legs and commits them together.
Real markets do not settle in the same instant they trade. They settle a day or more later.
The gap that lag creates
Between the trade and its settlement, each party is relying on the other to be there tomorrow. The buyer might not pay. The seller might not deliver. For one day, everyone in the market is holding an unsecured promise from a counterparty they may never have met, on a price that has already moved.
That is counterparty risk, and you have met its cross-currency cousin: module 3’s Herstatt loss, where one leg settled and the other never came. The remedy there was to make both legs settle together. Here the legs are already together - the problem is that they are together tomorrow, and tomorrow is not now.
What module 5 does with this
The next module takes the one-day window and builds the machinery around it: margin posted against the risk, an institution inserted between buyer and seller so that neither depends on the other at all, and an agreed order of loss absorption for the day somebody genuinely fails. You have now met every ingredient it needs - collateral from module 1, netting from module 3, margin calls from lesson 15, and the leverage from lesson 14 that makes failure plausible.
Check yourself
1. The project settles cash and shares in one act. Why does that make counterparty risk disappear inside the script but not in a real market?
Because a single function can see both legs and commit them together, so no state exists in which one has moved without the other. Real markets separate the trade from its settlement by a day or more, so the legs are still linked but no longer simultaneous, and the gap between them is exactly where the risk lives.
2. What is the relationship between this lesson’s settlement window and module 3’s Herstatt loss?
They are the same problem in different dimensions. Herstatt was one currency leg settling while the other never arrived; here both legs settle together but a day after the trade, so each party depends on the other surviving the night. In both cases the danger is a period during which one side has committed and the other has not yet performed.
3. Why did shortening the settlement cycle take a decade of argument if faster is safer?
Because the shorter window removes time everyone was using: to fund the purchase, to borrow securities for delivery, to correct errors, and across borders to settle a currency leg in another time zone. The risk reduction is real and so are the operational costs, so the change required the whole market to re-tool rather than simply agreeing that less risk is better.
4. The refusal test checks that nothing moved. Why is that a stronger check than confirming the error was raised?
Because a failure that raises after moving one leg is worse than no check at all: it leaves the system in an inconsistent state while appearing to have been caught. Asserting that both the cash and the share positions are unchanged proves the validation ran before any posting, which is the property that actually matters.
Do this
Run the whole market once.
python3 code/project_market.py
The starter provides the engine, the pricer and the settlement function, and leaves you the driver: run the tape and record the trade log, round-trip fifty seeded bonds and record the worst error, settle the ten-share trade and record what moved, then attempt the unfundable trade and record that nothing did. The assertions check each of the five properties above. Success prints the trade log, the pricing error, the ownership trail and the line:
matched, priced, settled: the market ran end to end
The completed version is in solutions/project_market.py.
What you can now do. You can run a market: form a price from a queue, convert between price and yield in either direction, settle cash against ownership atomically, and refuse a trade that cannot complete without leaving a trace. You can also name what a real market does differently, which is to settle tomorrow rather than now, and say precisely what that costs. Module 5 spends itself on that one day.