I keep meeting stacks where the rate is the least governed number in the building.
Everything else has an owner. The volatility surface has a committee. The credit assumption has a memo. The rate arrives as a column called rate holding 0.06, and it travels through ingestion, feature tables, an agent that drafts a mark, and a report that goes to the desk, without ever saying what kind of six percent it is. Nobody lies. Nobody checks. Two teams then produce two different marks on the same structure and spend a week arguing about the model.
The model was fine. The ruler was missing.
What a rate owes you that a float does not
Six percent is not a quantity until you say how it accrues and from when. Take 100 due in ten years and discount it three legal ways at the same six percent. Under simple interest you divide by 1.60 and get 62.50. Under annual compounding you divide by 1.06 to the tenth and get 55.84. Under continuous compounding you multiply by e to the minus 0.6 and get 54.88. Same instrument, same rate, same date, three answers spanning almost eight points of face.
The compounding frequency has the same property. Six percent nominal compounded monthly is 6.17 percent effective; compounded semiannually it is 6.09 percent. A pipeline that stores "6%" and lets each consumer assume its own frequency has not stored a rate. It has stored an opinion and thrown away the units.
Everything downstream inherits this. Present value, net present value of a cashflow stream, the equivalence of two streams, the internal rate of return that solves for the rate setting a signed stream to zero, all of them are statements relative to a declared convention and a decision clock. Two streams are equivalent under an ideal bank at a fixed frame. Change the frame and the equivalence quietly stops holding, but no exception is thrown, because nothing in the type system knew there was a frame to break.
So the object I want is not a better rate. It is a rate that carries its own metadata: accrual convention, compounding frequency, day count, and the as-of clock it was observed under. In the language this series keeps using, that is a DISCOUNT_FRAME card, and a job without one is untyped.
Why the silent conversion feels like rigor
Because the conversions are all correct. That is what makes this failure mode so durable.
Whoever wrote the continuous-compounding path was not sloppy, continuous discounting is the clean choice for anything that wants smooth calculus downstream. Whoever wrote the annual path matched the term sheet, which quotes annual coupons. Whoever wrote the simple-interest path was pricing a short money-market leg where simple accrual is the market standard. Each conversion is defensible in isolation. There is no bug to find. The failure is that the composition was never declared, so the system contains three rulers and calls all of them rate.
Silent conversion also survives review because it hides inside utility code. A helper named discount(cashflow, rate, t) is exactly the kind of function nobody reads twice. It compiles. It has a unit test with a round number. It becomes the shared floor two frames are built on, and the frame it encodes is whatever its author was thinking about that afternoon.
How this shows up in production
- Two teams, two marks, one structure. Research quotes off a continuous curve because their calibration code wanted it. The pricing service accrues annually because the term sheet does. Both are internally consistent. The marks differ, and the difference is attributed to "methodology" in a meeting where nobody names a convention.
- The agent inherits the ambiguity and sounds confident anyway. An LLM-driven analyst reads both feeds, sees two numbers, and writes a paragraph that reconciles them narratively. It has no field to check, so it does what text models do: it produces fluent agreement. Fluent agreement is the worst possible output here, because it removes the only signal that something was wrong.
- IRR as a free-floating number. Someone reports an internal rate of return without the accrual convention it was solved under. Comparing that to a quoted yield on another basis is comparing a metre to a yard. The comparison is what drives the ranking, and the ranking drives the trade.
- Frame drift across pipeline stages. The training table is built continuous. The live feature service is built annual because a later engineer matched the coupon calendar. Backtest and production now disagree by a wedge that grows with tenor, small at two years, most of a point at ten, and monitoring reads it as regime change.
- Midpoint peace. When two marks are both defensible and nobody can adjudicate the frame, the organisation averages them. That is the worst outcome, and it is the most common one, because averaging ends the meeting.
A walkthrough on CEH-001
Take the never-traded family again. CEH-001 has no tape, so every mark is a construction, which means every mark is a frame plus a model. One allowed setup, spread frame, annual accrual matching the coupon calendar, puts the mark near 1.50. Another allowed setup, curve frame, continuous discounting off the bootstrapped zero curve, puts it near 2.10. The desk has been treating that 0.60 gap as a modelling dispute for a month.
Now price the funding leg on its own: 100 of face at ten years, six percent, annual versus continuous. That single convention choice is worth 0.96 per hundred, larger than the whole 0.60 the desk is arguing about. The gap they are calling model risk is, at least in part, ruler risk, and it is sitting in a shared helper function nobody has opened.
Then Friday arrives. The report needs one number. Both frames are defensible, both owners are tired, and 1.80 is right in the middle. So 1.80 ships. Notice what just happened: 1.80 is not the output of either allowed setup. It is not a mark. It is a negotiated absence of a mark, and it is now the number that limits, P&L attribution and the next model's training labels will inherit. The midpoint is the only value in the room that no legal frame can produce, and it is the one that gets governance.
That is why this series denies 1.80 as a hard rule rather than a preference. Averaging two frames does not resolve a frame dispute; it launders it into a number that looks decided.
What stacks quietly assume
They assume a rate is a scalar. They assume conversions are lossless because they are reversible. They assume the tenor structure will keep the error small, true at the short end, false exactly where structured products live. They assume that if two independent teams agree to within a point, the number is probably fine, when in fact two-frame agreement to within a point on a ten-year leg is roughly what you would get from pure convention mismatch with no modelling skill at all.
And they assume the model will surface the problem. It will not. A model consumes whatever ruler you hand it and reports its own precision, not yours.
What a solution must do
If silent conventions are the failure, then declaring conventions has to be structural, not cultural. A real fix would make the frame a first-class field on the instrument, not a comment: accrual convention, compounding frequency, day count, as-of clock, all inside one hashed object, so that two stages using different rulers is a comparison failure at the boundary rather than a disagreement in a meeting. It would carry the full cashflow schedule and the credit assumption in the same hash, because a discount frame with an incomplete schedule is still an incomplete card. It would let an agent propose a frame and still refuse to spend when the frames on two sides of a pipeline do not match. And it would make the midpoint unreachable by construction, so that "both frames are defensible" resolves to two marks and an escalation instead of one invented number.
That object is the cashflow contract as an as-of hash, and it is where the next post goes.
Curious how others pin discount conventions across research and production without turning every pricing helper into a config debate, and whether anyone has managed to make the honest two-mark answer survive a Friday deadline.