Foreign Exchange
Converting between currencies: spot mechanics, settlement risk, and multi-currency ledgering.
Learning outcomes
Almost every payment that crosses a border, every balance held in more than one currency, and every business that buys or sells abroad runs into the same wall: a dollar is not a euro, and converting one into the other is not a fact you look up but a price someone quotes, with a spread, at a moment in time, that settles two days later and can fail in the gap. Foreign exchange is the largest market on earth by turnover, and almost none of its mechanics are intuitive on first contact. Get the mechanics right and cross-border money movement stops feeling like magic and starts looking like a small number of conventions applied consistently. Get them wrong and you will misquote a customer, leak value to rounding, or wire real money against a counterparty that never pays you back.
After studying this page, you can:
- Explain why an exchange rate is a price rather than a fact, and why two parties always see two different prices for the same pair at the same instant.
- Read any quote correctly: name the base and quote currency, say which one you are buying, and compute what a given amount converts to at the bid or the ask.
- Decompose the spread a customer pays into the interbank mid, the dealer spread, and the retail markup, and say who earns each piece.
- Distinguish spot, forward, and swap, and explain how a forward price comes from the spot price and the interest rate difference rather than from a forecast.
- Trace a spot trade through the T plus 2 settlement convention, name the settlement risk that lives in that window, and explain how CLS removes it with payment versus payment.
- Design multi-currency ledgering: why each currency is its own balance, why you never net across currencies, and how and when you revalue foreign balances into a reporting currency.
- Implement an FX conversion in code that applies a rate, a spread, and rounding while conserving value to the minor unit, and name the failure modes (settlement failure, rate staleness, rounding leakage) and the control that catches each.
Before we dive in
You need no trading background. We will use a small vocabulary and define each term the first time it appears.
A currency is money issued by a jurisdiction, identified by a three-letter ISO 4217 code: USD for the US dollar, EUR for the euro, JPY for the Japanese yen, GBP for the British pound. Foreign exchange, shortened to FX, is the act of converting one currency into another, and also the name of the global market where that conversion is priced and settled. An exchange rate is the price of one currency expressed in units of another. To settle a trade is to actually deliver the two currencies into the two parties’ accounts, which, as we will see, happens after the trade is agreed, not at the same moment.
A dealer (also called a market maker) is an institution, usually a large bank, that stands ready to both buy and sell a currency and earns the difference between its buying and selling price. A counterparty is the other side of your trade. The minor unit of a currency is its smallest indivisible amount: cents for USD (two decimal places), the yen itself for JPY (zero decimal places). Throughout, money is shown with decimals for readability, but a real system stores it as an integer count of minor units, for reasons the double-entry foundation already established and section ten will sharpen for FX.
One framing to carry the whole way down. There is no such thing as the exchange rate between two currencies in the way there is the boiling point of water. There is a price, and a price has two sides, a spread, a timestamp, and a counterparty. Every hard part of FX falls out of taking that sentence seriously.
Mental Model
The wrong model, and almost everyone arrives with it, is that an exchange rate is a fact you can look up, like a conversion factor between meters and feet. One euro is worth, say, 1.08 dollars, full stop, and converting is just multiplication. Apps and news tickers reinforce this by showing a single number with no spread, no side, and no time attached.
That model is wrong in three ways at once, and each one matters in production. First, a rate is a price set by supply and demand, so it moves continuously and is only true for an instant; the number you saw a second ago may not be the number you can trade at now. Second, a price has two sides: the dealer will buy the base currency from you at one price (the bid) and sell it to you at a higher price (the ask), and the gap between them is how the dealer gets paid, so there is no single rate that applies to both directions. Third, a rate without a counterparty and a settlement date is not tradeable; agreeing the price is only the start, and the currencies do not actually move until settlement, which is usually two business days later and can fail in between.
Here is the model to hold instead. Think of a currency as a commodity with a continuous, two-sided market, like a foreign-exchange booth at an airport that you can see straight through. The booth posts two prices, one to buy euros from you and a worse one to sell euros to you, and it pockets the gap. The prices on the board change every few seconds as the wholesale market moves. When you trade, you have not received your euros; you have agreed a price, and the booth and you each owe the other a delivery that completes later. Hold that picture, two-sided, always moving, settled in the future against a real counterparty, and the spot, forward, swap, settlement, and ledgering machinery below all become applications of it rather than separate facts to memorize.
Breaking it down
The core teaching runs in twelve steps. The first five build the market the way a trader or a treasurer understands it: what a rate is, how it is quoted, where the spread comes from, how the price forms, and the three instruments built on it. The next four follow the money once a trade is struck: how it settles, the risk in the settlement gap, how you hold many currencies on a ledger, and what a cross-border customer actually pays. The last three are the engineer’s: conserving value to the cent in code, the failure modes, and the line between fundamental principle and local convention.
1. Why a price for money in terms of money has to exist
Start from first principles. A US business wants to buy goods from a German supplier who will only accept euros. The American holds dollars; the German wants euros. Someone, at some point, has to give up dollars and receive euros, and someone else has to do the reverse. The exchange rate is simply the price at which those two willing parties agree to swap. It exists for the same reason any price exists: two parties want opposite things, and a price is what clears the imbalance between them.
Because it is a price and not a physical constant, it is set by supply and demand and moves continuously. If more people want euros than want dollars at the current price, the price of the euro rises until the flows balance. Trade flows, interest rate differences, central bank policy, capital flows, and speculation all push on it, second by second. There is no committee that sets the rate and no formula that derives it from fundamentals in real time; there is a market of buyers and sellers, and the rate is wherever they are currently willing to trade.
This is the single most important reframing on the page, and everything else depends on it. A rate is not looked up; it is quoted. It is not single; it has two sides. It is not permanent; it is true for an instant. And it is not abstract; it is a commitment between two specific parties to deliver real currency at a real time. Hold those four properties and the rest of FX is mechanics.
2. Currency pairs and how a quote is read
A rate is always about two currencies, so it is quoted as a pair. By universal market
convention a pair is written BASE/QUOTE, for example EUR/USD. The first currency is
the base; the second is the quote (also called the counter or terms currency). The
number attached to the pair is the price of one unit of the base, expressed in the quote
currency. So EUR/USD = 1.0850 means one euro costs 1.0850 US dollars. The base is the
thing being priced; the quote is the money you price it in.
This single rule removes most of the confusion in FX, because it tells you what a number means and which direction you are trading. To convert an amount of the base into the quote, you multiply by the rate; to go the other way, you divide. Buying the pair means buying the base and paying with the quote; selling the pair means the reverse.
Which currency is the base is itself a convention, not a law, and the conventions are worth knowing because getting them backwards inverts every number. The market orders pairs by a rough seniority: EUR is the base against almost everything; then GBP; then AUD and NZD; then USD against most of the rest of the world (USD/JPY, USD/CHF, USD/CAD). So the euro and the pound are quoted as dollars-per-unit, while the yen is quoted as yen-per-dollar. A pair where neither currency is the US dollar (EUR/JPY, GBP/JPY) is called a cross, and historically a cross rate was computed by chaining two dollar pairs, since the dollar is the market’s common leg.
A second convention is the pip, the smallest conventional increment of a quote. For most pairs that is the fourth decimal place (0.0001), so EUR/USD moving from 1.0850 to 1.0851 is a one-pip move; for yen pairs, quoted to two decimals, a pip is 0.01. Pips matter because the spread, the dealer’s margin, is measured in them.
3. The bid-ask spread and where the dealer earns
A dealer does not quote one number; it quotes two. The bid is the price at which the dealer will buy the base currency from you. The ask (or offer) is the higher price at which the dealer will sell the base currency to you. The gap between them is the bid-ask spread, and it is the dealer’s compensation for standing ready to trade, holding inventory, and bearing the risk that the price moves against it before it can offset the position. The average of the bid and the ask is the mid (or mid-market) rate; the mid is the closest thing to the single rate the public imagines, but you can almost never trade at it, because no dealer sells at the same price it buys.
You always trade on the side that is worse for you, which is the point. If you want to buy euros, you pay the ask (the higher number). If you want to sell euros, you receive the bid (the lower number). Cross a wide spread in both directions and you can lose value just by going out and coming straight back, having moved nothing in the market.
The size of the spread is not arbitrary. It is tighter when the dealer faces low risk and high competition, and wider otherwise. Liquidity is the main driver: EUR/USD, the most traded pair in the world, can quote a spread well under a pip in the wholesale market, while a thinly traded emerging-market pair can quote tens or hundreds of pips. Volatility widens spreads, because a dealer holding inventory through a fast-moving market demands more to bear the risk. Trade size matters in both directions: very large trades move the price against the dealer (market impact), and very small retail trades carry fixed handling costs, so both can be quoted wider than a mid-size wholesale ticket. Time of day matters too, because liquidity thins when the major financial centers are closed.
4. How a price is actually formed in the market
There is no single exchange where FX trades. The market is over the counter (OTC), meaning trades happen bilaterally between parties rather than on a central exchange, and it is organized in tiers. At the core is the interbank market: a small number of large dealer banks quoting each other continuously, where the tightest prices and the deepest liquidity live. Around that core, a wider ring of banks, hedge funds, corporates, and brokers trade with the core dealers and with each other. The price you see as a retail customer is derived from the interbank price with successive markups added at each tier outward.
Much of the wholesale market now trades on electronic communication networks (ECNs) and single-dealer platforms: venues that aggregate quotes from many dealers and match buy and sell interest electronically, often anonymously, in milliseconds. An ECN lets a participant see the best bid and best ask across many liquidity providers and trade against them, which tightens spreads through competition. Alongside the ECNs, large dealers run their own internal pricing: they match offsetting customer flow against itself (internalize it) and only send the residual imbalance out to the interbank market to offset, because every trip to the external market costs spread.
flowchart TB
subgraph core["Interbank core"]
A["Major dealer banks quote<br/>each other continuously<br/>tightest spreads deepest liquidity"]
end
subgraph venues["Electronic venues"]
B["ECNs and platforms aggregate<br/>many dealers best bid best ask<br/>matched anonymously in ms"]
end
subgraph clients["Client tiers"]
C["Banks funds corporates brokers<br/>trade against core dealers<br/>spread widens at each tier out"]
end
subgraph retail["Retail and SMB"]
D["Apps PSPs banks add a markup<br/>over the interbank mid<br/>this is the price the customer sees"]
end
core --> venues --> clients --> retailPrice formation, then, is a continuous negotiation. A dealer’s quoted bid and ask reflect its current inventory (a dealer long euros wants to sell, so it shades its quote to attract buyers), the flow it is seeing, the prices on the ECNs, and its view of where the market is going. There is no authoritative single price at any instant, only a tight cluster of slightly different two-sided quotes across many dealers and venues, and arbitrage keeps that cluster tight: if one dealer’s ask falls below another’s bid, someone trades the difference until the gap closes. The widely cited reference rates (a daily fixing, a central bank reference rate) are snapshots or averages of this market at a moment, useful for valuation and contracts, but they are summaries of the market, not the market itself.
5. Spot forward and swap as three uses of one rate
Three instruments cover most of FX, and they are not three different prices but three different settlement timings built on the same spot price.
A spot transaction is an agreement to exchange two currencies at the current rate, for delivery in the near future, conventionally two business days out. This is the base case and the price everyone quotes first.
A forward is an agreement to exchange two currencies at a rate fixed today, for delivery on a date further out than spot (a month, three months, a year). The crucial insight, and the place intuition usually fails, is that the forward rate is not a forecast of where spot will be. It is derived from today’s spot rate and the interest rate difference between the two currencies, by an arbitrage argument called covered interest parity. If you can earn a higher interest rate holding one currency than the other, then locking in a future exchange must compensate for that difference, or a risk-free profit would exist. So the forward rate is the spot rate adjusted by the interest rate gap over the period, no more and no less. A currency with a higher interest rate trades at a forward discount; the lower-rate currency trades at a forward premium.
flowchart LR S["Spot rate today<br/>EUR/USD 1.0850"] --> F["Forward rate<br/>= spot adjusted by<br/>interest rate difference"] R1["USD interest rate"] --> F R2["EUR interest rate"] --> F F --> O["Locked rate for<br/>delivery in 3 months<br/>(not a forecast)"]
A swap is the two combined: a spot transaction in one direction and a forward in the opposite direction, dealt together. For example, buy euros for dollars now (spot) and sell the euros back for dollars in three months (forward), at rates agreed today. An FX swap is how institutions move liquidity from one currency to another for a fixed period without taking on exchange-rate risk: you have the euros you need now and you have already locked the rate to unwind, so your net currency exposure is unchanged. Swaps are the workhorse of the market; far more is traded as swaps than as outright spot, because most large players are managing funding and liquidity rather than betting on direction.
The takeaway is structural. There is one underlying thing, the price of one currency in another, and the three instruments differ only in when delivery happens and whether the rate is for a single future date or two. Forwards and swaps are not predictions; they are the spot price plus the cost of money over time. A corporate treasurer hedging a future euro payable, a bank funding its euro book overnight, and a fund taking a directional view all reach into the same toolkit and pick the timing that matches their need.
6. The T plus 2 spot convention and why settlement takes time
Agreeing the price is not the same as moving the money. A spot trade conventionally settles on T plus 2 (written T+2): the trade is struck on trade date T, and the two currencies are actually delivered into the two parties’ accounts two business days later. Some pairs settle faster by convention (USD/CAD trades T+1), but T+2 is the standard, and the reason it exists is operational, not arbitrary.
Settling an FX trade means two separate payments in two separate currencies through two separate national payment systems, each of which only operates during its own country’s business hours and holidays. To deliver dollars you move money through the US payment system; to deliver euros you move money through the euro-area system. The two parties must confirm the trade, instruct their banks, and route the payments through correspondent banks where needed, and the books in the two countries must both be open. T+2 is the buffer that lets all of that happen reliably across time zones and holiday calendars. A trade struck Monday settles Wednesday; one struck Thursday, with a Friday holiday in one currency’s country, may settle the following Tuesday, because the count is in business days for both currencies.
sequenceDiagram participant A as Party A participant B as Party B participant USP as USD payment system participant EUP as EUR payment system Note over A,B: T (trade date): agree EUR/USD price and amounts A->>B: Confirm trade details Note over A,B: T+1: affirm, instruct banks, route via correspondents Note over A,B: T+2 (settlement): both legs delivered A->>EUP: Pay euros to B B->>USP: Pay dollars to A Note over USP,EUP: Two payments, two systems, two countries' hours
This delay is the source of the next problem. For the two business days between trade and settlement, each party is exposed to the other: the price is locked, but the money has not moved, and either side could fail before delivering. And worse, even on settlement day the two legs do not happen at the same instant by default, because they run through independent systems in different time zones. That gap, money owed but not yet exchanged, is where the most famous risk in FX lives.
7. Herstatt risk and the invention of payment versus payment
In June 1974, a German bank named Bankhaus Herstatt was shut down by regulators in the afternoon, Frankfurt time. Earlier that day, counterparties had paid Deutsche Marks to Herstatt in the European morning, expecting to receive US dollars in return when New York opened. By the time New York opened, Herstatt was closed. The counterparties had delivered one leg and never received the other. They lost the full principal of the trades, not a price movement on them, the entire amount, because they had paid away real money against a counterparty that failed before paying them back.
This is settlement risk, the risk that you deliver your side of an FX trade and the counterparty fails before delivering theirs, and in FX it is specifically called Herstatt risk after that failure. It is uniquely dangerous in FX because the two legs settle in different countries and time zones, so there is naturally a window where one party has paid and the other has not. And the exposure is the full principal, not a small price difference: if you wire ten million dollars expecting ten million dollars of euros back and the counterparty fails, you are down ten million, not down a few pips.
The fix is a settlement mechanism that makes the two legs conditional on each other, so that neither happens unless both happen. This is called payment versus payment (PvP): the dollar leg and the euro leg either both settle or neither does, eliminating the window where one side has paid and the other has not. The institution that operationalizes PvP for FX is CLS (Continuous Linked Settlement), launched in 2002. CLS holds accounts at the central banks of the major currencies it settles. On settlement day, each party pays its currency into CLS; CLS settles the two legs of each trade simultaneously across its books, paying out only when both incoming legs are present, and pays the net amounts back out. Because settlement is simultaneous and conditional, a counterparty failure means the trade simply does not settle and your principal is returned, rather than paid away into a void.
flowchart TB
subgraph without["Without PvP: Herstatt risk"]
A1["Party A pays EUR in the morning"] --> A2["Party B fails before US opens"]
A2 --> A3["A is out full principal<br/>never receives USD"]
end
subgraph with["With CLS: payment versus payment"]
B1["Both parties pay their<br/>currency into CLS"] --> B2["CLS settles both legs<br/>simultaneously across its books"]
B2 --> B3["Both legs settle together<br/>or neither does<br/>principal is never paid into a void"]
endPvP does not remove all risk. It removes settlement risk, the loss of principal in the gap, but the parties still bear replacement-cost risk: if a counterparty fails and the trade does not settle, you still have to go back to the market and redo the trade at whatever the rate is now, which may be worse. That is a price-movement loss, not a full-principal loss, and it is far smaller. The historical lesson is sharp: a market can run for decades on the assumption that the gap between the two legs is harmless, until one large failure on one afternoon proves it is not, and the infrastructure that prevents the next one (CLS) is built only after the loss is felt.
8. Multi-currency ledgering and revaluation
Now move from the market to the books. The cardinal rule of holding more than one currency on a ledger is simple and absolute: each currency is its own balance, and you never net across currencies. Ten thousand dollars and ten thousand euros are not twenty thousand of anything; they are two separate balances in two separate units that happen to both be money. The double-entry conservation law that says debits equal credits applies within a currency, not across currencies, because there is no exchange rate inside the conservation rule. A balanced transaction in dollars and a balanced transaction in euros are two transactions, even when they are the two legs of one conversion.
So a multi-currency account is really a set of single-currency sub-balances, one per currency, each maintained as an integer count of that currency’s minor units, each obeying double-entry on its own. When you convert, you are not moving value across the conservation boundary inside one transaction; you are debiting one currency’s balance and crediting another’s, and the exchange rate, the spread, and any conversion margin are recorded as their own postings so the two single-currency transactions each balance.
-- One balance per (account, currency). Never a single mixed balance.
CREATE TABLE postings (
id BIGINT PRIMARY KEY,
transaction_id BIGINT NOT NULL,
account_id BIGINT NOT NULL,
direction SMALLINT NOT NULL, -- +1 debit, -1 credit
amount BIGINT NOT NULL, -- minor units, integer, never a float
currency CHAR(3) NOT NULL, -- ISO 4217: balances are per-currency
created_at TIMESTAMPTZ NOT NULL
);
-- The balance is derived PER currency. Debits must equal credits within each currency.
SELECT account_id, currency, SUM(direction * amount) AS balance
FROM postings
WHERE account_id = $1
GROUP BY account_id, currency;
This creates a reporting problem. A business that holds dollars, euros, and yen still has to report a single net worth in one reporting currency (say USD), and the value of its euro and yen balances in dollars changes every second as the market moves, even though the underlying balances have not changed by a single minor unit. The act of restating foreign-currency balances into the reporting currency at the current rate is called revaluation (or remeasurement). You do not change the foreign balances; they are still exactly what they were. You compute what they are worth in the reporting currency now, and the change since the last revaluation, the unrealized FX gain or loss, is recorded against an FX revaluation account. It is unrealized because you have not actually converted; it becomes a realized gain or loss only when you do.
The engineering consequence is that a multi-currency ledger needs three things the single-currency ledger did not: a currency on every posting and balance, a separate rate store with timestamps, and a revaluation process that runs on a schedule (often daily, and at period close) to restate foreign balances and book the unrealized result. None of this relaxes double-entry; it applies double-entry once per currency and treats the rate as external data, which is exactly what it is.
9. FX inside a cross-border payment and the markup the customer pays
Now the customer’s view, which is where most of the value, and most of the hidden cost, lives. When someone sends money across a border, an FX conversion is almost always buried inside the payment, and the rate they receive is not the interbank mid they might see on a news app. It is the mid plus a markup, and the markup is frequently the largest part of what the transfer actually costs, larger than any visible flat fee.
The price a retail or small-business customer pays decomposes into layers. At the bottom is the interbank mid, the wholesale price between dealers. The dealer the provider trades with adds a dealer spread to that. The consumer-facing provider (a bank, a payment service provider, a remittance app) then adds its own retail markup on top, often expressed as a worse exchange rate rather than a separate fee, which is exactly why customers underestimate it: a rate that is 2 percent worse than mid on a 1,000 unit transfer is a 20 unit cost that never appears as a fee line. There may also be a visible flat fee, and there may be correspondent banking deductions along the way, where intermediary banks that relay the payment each take a cut.
This decomposition explains the entire competitive landscape of cross-border payments. Providers that advertise low or zero fees often make their money on the rate markup instead, and providers that advertise the mid-market rate make their money on a visible fee. Neither is free; the question is only where the margin is placed. The regulatory direction of travel, in many jurisdictions, is toward transparency: requiring providers to disclose the total cost including the FX markup, expressed against a reference rate, so customers can compare like for like rather than being steered by a headline fee that hides the rate. For an engineer building a cross-border product, the design implication is direct: you must source a defensible reference rate, apply your markup explicitly and consistently, and be able to show a customer the mid, your rate, and the difference, because that difference is increasingly something you are required to disclose and always something a competitor will disclose for you.
10. Engineering a conversion that conserves value to the minor unit
Here is where finance, regulation, and arithmetic meet a keyboard. Converting an amount in one currency to another in a ledger is not “multiply by the rate,” because that produces fractional minor units that do not exist, and rounding them carelessly leaks value, breaks the per-currency balance check, and over millions of conversions adds up to real money you cannot account for.
The constraints are concrete. Money is an integer count of minor units (cents, yen) and never a float, for the representation reasons the ledger foundation established: a binary float cannot hold most decimal fractions exactly, so floats drift. A rate has many more decimal places than money does (EUR/USD to 5 decimals, say 1.08503), so the multiplication produces a result with fractional cents that must be rounded to a whole minor unit. The rounding rule must be defined and consistent (round half to even, also called banker’s rounding, is common because it does not bias systematically up or down). And critically, the spread or markup and the rounding remainder must each be booked somewhere, so the two single-currency transactions both balance and no value is silently created or destroyed.
// Convert an integer source amount to a destination currency, applying a rate
// (as integer numerator/denominator to avoid floats), rounding to the minor unit,
// and capturing the remainder so nothing leaks.
type Rate struct {
Num, Den int64 // rate = Num/Den, e.g. 1.08503 -> Num=108503, Den=100000
}
// ConvertExact returns the destination minor units and the exact remainder in
// destination scaled units, so the caller can book the residual to a rounding account.
func ConvertExact(srcMinor int64, r Rate) (dstMinor int64, remainder int64) {
// scaled = srcMinor * Num : the destination amount times Den, with no rounding yet.
scaled := srcMinor * r.Num
dstMinor = scaled / r.Den // integer division: floor toward zero
remainder = scaled - dstMinor*r.Den // exact leftover, always 0 <= remainder < Den
return dstMinor, remainder
}
The function returns both the rounded destination amount and the exact remainder, and that second return value is the whole point. The customer is credited the rounded whole minor units; the remainder is not thrown away, it is booked to a rounding or conversion account, so the sum of what the customer receives plus what the rounding account absorbs exactly equals the converted value. That is what “conserve value to the minor unit” means in practice: every fraction of a cent is assigned to some account, never dropped, so both currencies’ books still balance and the trial balance still nets to zero.
The spread is handled the same way, explicitly. You source a mid rate, derive a customer rate by applying your markup, convert at the customer rate, and book the difference between converting at mid and converting at the customer rate to an FX revenue account. The customer transaction balances, the revenue transaction balances, and you can show, for any conversion, the mid, the applied rate, the markup earned, and the rounding residual, every minor unit accounted for.
11. Failure modes and the controls that catch them
An FX conversion looks like one multiplication, but it sits on top of a market, a settlement process, and a ledger, and it can fail in each of those layers. A senior engineer knows which control catches which failure, because no single mechanism catches them all.
The failure modes group cleanly. Settlement failure is the Herstatt problem: a counterparty fails between the two legs and you lose principal. The control is payment versus payment through CLS, which makes the legs conditional on each other, plus counterparty credit limits for trades that settle outside CLS. Rate staleness is honoring or applying a price the market has moved away from, whether because a quote lived too long or a cached rate was not refreshed. The control is a timestamp and a short validity window on every rate, re-pricing against a fresh source, and hedging the exposure you carry between quoting and converting. Rounding leakage is value lost when fractional minor units are dropped instead of booked. The control is integer arithmetic, a defined rounding rule, and booking the remainder so the per-currency books still balance. And mixing currencies is the quietly catastrophic one: adding or netting two balances in different currencies as if they were the same unit, which the conservation law cannot catch because it only operates within a currency. The control is a currency on every amount, type-level or schema-level enforcement that arithmetic only happens within one currency, and a balance check that runs per currency.
The pattern mirrors the ledger lesson exactly. Double-entry within a currency guarantees internal consistency, but it says nothing about whether the rate was current, whether the counterparty paid, or whether you accidentally added dollars to euros. Each of those needs its own control, layered on top of a ledger that is already balancing correctly within each currency.
12. Fundamental principles versus market conventions
A senior practitioner separates what is a law of the domain from what is merely how this market happens to do things, because the laws constrain every design and the conventions can differ by venue, currency, and era. Confusing the two leads to brittle systems that assume a convention is a rule.
The fundamental principles are few. An exchange rate is a price set by supply and demand, so it is two-sided, time-varying, and only true for an instant. Conservation of value holds within a currency but not across currencies, because there is no rate inside the conservation law, which is why you never net across currencies. Settlement is the actual delivery of currency and is distinct from agreeing the price, which is why a settlement gap and its risk exist at all. A forward price is the spot price adjusted by the interest rate difference, by arbitrage, not a forecast. And value must be conserved to the minor unit, every fraction assigned to some account. These do not change with the venue or the decade.
The conventions are many and movable. T+2 spot settlement is a convention, and some pairs settle T+1 (USD/CAD), and there are periodic efforts to shorten settlement cycles across markets. Which currency is the base in a pair is a convention (EUR is base against the dollar; the dollar is base against the yen). The pip as the fourth decimal place is a convention that differs for yen pairs. Quoting the markup as a worse rate rather than an explicit fee is a convention, and regulation is pushing it toward explicit disclosure. Even CLS, the settlement institution, is an institution-specific answer to a fundamental problem (settlement risk), and trades outside CLS still exist and still carry that risk managed other ways. When you build, anchor on the principles and treat every convention as a configurable parameter, a settlement lag, a base-currency rule, a rounding mode, a markup policy, because the moment you add a new currency, a new venue, or a new jurisdiction, the conventions will be different and the principles will not.
Mastery Questions
-
A product manager says your remittance app should advertise the mid-market rate and a zero markup to win customers, and make money purely on a small flat fee. An engineer objects that “the mid-market rate” is not a single thing you can actually trade at. Who is right, and how would you build a product that is both honest and viable?
Answer. The engineer is right about the mechanics, and that does not make the product manager wrong about the strategy; they are talking about different things. The mid-market rate is the average of the bid and the ask, and no dealer will trade with you at the mid, because the dealer earns the spread, so you cannot literally execute customer conversions at the mid. What you can do is source a defensible mid from a reputable venue, execute your own conversions at the slightly worse rate the market actually gives you (paying the dealer spread), and then choose to pass the mid through to the customer while recovering your costs and margin through a transparent flat fee instead of a hidden rate markup. That is honest: the customer sees the same reference rate you quote, plus a stated fee, and can compare it like for like against competitors who bury their margin in a worse rate. It is viable as long as the flat fee covers the real dealer spread you pay, your operational cost, and your margin, and as long as you manage the rate-staleness exposure between quoting the customer and actually converting (a short quote validity window and hedging). The deep point is that the margin has to live somewhere; the only real choice is whether to place it in the rate, where it is hidden, or in a fee, where it is disclosed, and regulation is steadily pushing toward the disclosed version.
-
Your ledger holds a customer’s balances in USD, EUR, and JPY. The per-currency trial balance nets to exactly zero in every currency, yet your finance team says the company’s reported net worth jumped overnight even though no customer moved any money. Is the ledger broken, and what is actually happening?
Answer. The ledger is not broken, and the per-currency trial balance netting to zero in each currency is exactly the proof of that: within each currency, debits equal credits and no value was created or destroyed. What changed is not the balances but their value in the reporting currency. The euro and yen balances are still the same number of euro cents and yen, but the exchange rates moved overnight, so when you revalue those foreign balances into the reporting currency (say USD) at the new rates, they are worth a different number of dollars than they were yesterday. That difference is an unrealized FX gain or loss: unrealized because nobody actually converted anything, so it would reverse if the rates reversed. It is booked against an FX revaluation account, not against any customer balance, which is why no customer moved money and yet the reported net worth changed. The lesson is that a multi-currency ledger has two distinct truths: the per-currency balances, which only change when money actually moves, and the reporting-currency valuation, which changes every time the market moves, and conflating them makes a perfectly correct ledger look broken.
-
A junior engineer implements currency conversion as
dst = round(src * rate)using floating-point math, ships it, and a month later the books in the destination currency will not balance by a few units and nobody can find the missing money. Diagnose every way this one line leaks value, and give the correct construction.Answer. That one line has three independent leaks. First, floating-point: representing money or the rate as a binary float means most decimal values are not held exactly, so the multiplication drifts by tiny amounts that accumulate across many conversions into balances that will not reconcile. Money must be an integer count of minor units and the rate must be applied as integer arithmetic (a numerator over a denominator), never as a float. Second, rounding without capturing the remainder: multiplying an integer amount by a rate produces a result with fractional minor units, and
roundthrows the fraction away. Across millions of conversions those discarded fractions are real money that has vanished from one side of the books, so the destination currency no longer balances. The fix is to compute the exact remainder and book it to a rounding account, so the customer’s credited whole units plus the rounding account exactly equal the converted value. Third, no place for the spread: if the rate already includes a markup, the difference between converting at mid and at the customer rate has to be booked to an FX revenue account, or that value is unaccounted for too. The correct construction keeps money as integers, applies the rate as integer numerator over denominator with a defined rounding rule, books the remainder to a rounding account and the markup to an FX revenue account, and posts each currency’s legs as its own balanced transaction. Then every minor unit is assigned to some account, both currencies’ books balance, and the trial balance nets to zero per currency, which is precisely the property the shipped code destroyed.
Sources & evidence18 claims · 10 cited
Grounded in standard FX market conventions (ISO 4217, T+2 spot, pip definitions), the documented 1974 Bankhaus Herstatt failure and CLS Bank's PvP settlement launched in 2002, covered interest parity for forward pricing, and engineering practice for integer minor-unit money and remainder-conserving conversion carried over from the ledger foundation. Specific live spread/markup numbers are illustrative examples, not quoted facts; exact CLS operational details and per-jurisdiction FX-disclosure rules are summarized at the principle level rather than cited to a specific regulation.
- An exchange rate is a price set by supply and demand, so it is two-sided (bid and ask), time-varying, and only true for an instant; there is no single authoritative rate.stable common knowledge
- Currency pairs are written BASE/QUOTE and the rate is the price of one unit of the base expressed in the quote currency; converting base to quote multiplies and quote to base divides.stable common knowledge
- Currencies are identified by three-letter ISO 4217 codes (USD, EUR, JPY, GBP) and each has a defined number of minor-unit decimal places (USD two, JPY zero).verified
- The bid is the price at which a dealer buys the base currency and the ask is the higher price at which it sells; the gap is the bid-ask spread and is the dealer's compensation, and the mid is their average.stable common knowledge
- A pip is conventionally the fourth decimal place of a quote (0.0001) for most pairs and the second decimal (0.01) for yen pairs.verified
- The FX market is over-the-counter and tiered, with an interbank core of dealer banks, electronic communication networks (ECNs) that aggregate and match quotes, and successive markups added at each tier out to retail.verified
- A forward rate is derived from the spot rate adjusted by the interest-rate difference between the two currencies via covered interest parity, not from a forecast; the higher-rate currency trades at a forward discount.stable common knowledge
- An FX swap combines a spot transaction with an opposite-direction forward dealt together, leaving net exchange-rate exposure unchanged, and swaps are the largest segment of the FX market by turnover.verified
- Spot FX conventionally settles on T+2 (two business days after trade date), with some pairs such as USD/CAD settling T+1, because two payments must clear through two national payment systems across time zones and holiday calendars.verified
- Bankhaus Herstatt was closed by German regulators on an afternoon in June 1974 after counterparties had paid Deutsche Marks in the European morning and not yet received US dollars, losing the full principal; this gave settlement risk in FX the name Herstatt risk.verified
- CLS (Continuous Linked Settlement) launched in 2002 and settles FX trades on a payment-versus-payment basis using central-bank accounts, settling both legs simultaneously and only when both incoming legs are present, eliminating principal settlement risk.verified
- Payment versus payment removes principal settlement risk but not replacement-cost risk: if a trade fails to settle the party must re-trade at the current rate, a price-movement loss rather than a full-principal loss.verified
- In a multi-currency ledger each currency is its own balance and value is never netted across currencies, because double-entry conservation holds within a currency and there is no exchange rate inside the conservation law.internal reasoning
- Revaluation restates foreign-currency balances into a reporting currency at the current rate without changing the underlying foreign balances, booking the change since the last revaluation as an unrealized FX gain or loss that becomes realized only on actual conversion.stable common knowledge
- The rate a retail customer receives in a cross-border payment decomposes into the interbank mid, the dealer spread, and a retail markup often expressed as a worse rate rather than a fee, and the markup is frequently the largest part of the transfer's true cost.verified
- Money must be stored as an integer count of minor units rather than a binary float because floats cannot represent most decimal fractions exactly and drift across many operations.stable common knowledge
- A correct FX conversion applies the rate as integer numerator over denominator, rounds to the minor unit with a defined rule, and books the exact remainder and the markup to dedicated accounts so both currencies' books balance and value is conserved to the minor unit.internal reasoning
- FX failure modes map to distinct controls: settlement failure to PvP via CLS and credit limits, rate staleness to quote TTLs and re-pricing plus hedging, rounding leakage to integer arithmetic and remainder booking, and currency-mixing to enforcing arithmetic within one currency.internal reasoning
Cited sources
- Triennial Central Bank Survey of foreign exchange and OTC derivatives markets · Bank for International Settlements
- ISO 4217 Currency codes · International Organization for Standardization
- The foreign exchange market structure and electronic trading · Bank for International Settlements, Markets Committee
- Options, Futures, and Other Derivatives · John C. Hull
- FX swap market and turnover composition · Bank for International Settlements
- FX settlement conventions and the T+2 spot standard · Global Foreign Exchange Committee
- Settlement risk in foreign exchange transactions (Allsopp Report) and Herstatt risk · Bank for International Settlements, Committee on Payment and Settlement Systems
- CLS Bank and payment-versus-payment settlement for FX · CLS Group
- The Effects of Changes in Foreign Exchange Rates (IAS 21) · IFRS Foundation / IASB
- Cross-border retail payments and FX cost transparency · World Bank / Bank for International Settlements