Contents Lesson 6 of 16

4 min read · foundations

Why is there no row for the euro?

Search the FX symbol list for a plain EUR price and you will not find one — not because it is missing, but because it cannot exist. Every foreign exchange price is a ratio between two things that are both moving, and a ratio needs a denominator.

This is a familiar idea by now if you have read Foreign Exchange Foundations. What it does to a database schema is less obvious and much more likely to break something.

The primary key is a pair

In an equity table, a row is identified by (instrument, date). The instrument is a thing. In FX, the row is identified by (pair, date), and the pair is a relationship between two things.

That difference has teeth. Consider a table with the columns symbol, date, close — a perfectly reasonable schema that works for stocks. Load FX into it and the question "how did the euro do last year?" has no home. You can answer "how did EURUSD do", but the moment someone asks about the euro on its own, the schema quietly invites an answer it cannot support.

The euro can rise against the dollar and fall against the yen on the same afternoon. Both facts are true and neither is "the euro's performance".

The consistency you can test

Because pairs are relationships, they are not independent. Given EURUSD and USDJPY, EURJPY is determined: multiply the two and the dollar cancels.

Read live on 2026-07-28 from /eod/EURUSD.FOREX, the pair's close for 27 July was 1.1369 (by 28 September 2026 that bar had been restated to 1.1395, which is a lesson of its own about storing what you fetched). If your store also holds USDJPY and EURJPY for that same date, multiply the first two and compare with the third. A small gap sits inside the bid-ask spreads. A large gap does not mean you have found an arbitrage; it means your three snapshots were not taken at the same instant — which, for a market with no official close, is the default situation rather than the exception.

This is the cheapest data-quality test in FX and it costs three fetches.

The adjustment column that carries nothing

Every EOD row in this API has an adjusted_close. On equities it does real work: it folds splits and dividends back into the history, which is why the adjusted history of a dividend payer changes every quarter. Reading the Market covers that in depth.

On FX it does nothing. Pulled live for EURUSD.FOREX across 2026-07-10 to 2026-07-27 on 2026-07-28, all fifteen rows had adjusted_close exactly equal to close; re-pulled on 28 September 2026, when the window had grown to eighteen rows, all eighteen still did. Of course they did — a currency pair has no shares to split and no dividend to pay. The column is carried for schema uniformity and contains no information.

Two consequences. First, an "adjusted versus unadjusted" comparison on FX will always show zero difference, so if you are testing adjustment logic, FX is the wrong test case. Second, and more usefully: if you ever do see adjusted_close differ from close on an FX row, that is a data error worth reporting, not a corporate action.

Worked example: the same move, two denominators

Suppose over some period EURUSD goes from 1.1414 to 1.1369, the sample's first open and last close as it was pulled on 2026-07-28.

Change: (1.1369 − 1.1414) ÷ 1.1414 = −0.394%.

Now flip it. USD/EUR goes from 1 ÷ 1.1414 = 0.87611 to 1 ÷ 1.1369 = 0.87958.

Change: (0.87958 − 0.87611) ÷ 0.87611 = +0.396%.

Two numbers, opposite signs, and they are not equal in magnitude — 0.394 against 0.396. That asymmetry is not a rounding error; it is what happens when you take percentage changes of reciprocals. A store that holds both EURUSD and EUR will produce both numbers, and any aggregate that mixes them is arithmetic on double-counted, sign-flipped data.

Try it now

  1. Here are EURUSD, GBPUSD and EURGBP from one /real-time call, so the three quotes share a moment. Check the three timestamps, then check that EURUSD ÷ GBPUSD lands close to EURGBP. Write down how close, and keep that as your tolerance.
Live API response: mda22 eurusd gbpusd eurgbp quotes
Interactive line chart: EURGBP.FOREX (1Y)
  1. Here are three rows of /eod/EURUSD.FOREX?from=2026-07-01&to=2026-07-31: the first, the sixteenth and the last. Test whether adjusted_close == close on each. It should hold (on 28 September 2026 it held on all 30 rows of the month). Then run the same test on the dividend payer below it and watch it fail; that contrast is the whole point of the adjustment column.
Live API response: mda2 eurusd july 2026 adjusted
Live API response: mda2 aapl close vs adjusted 2026 07
3. Take the first and last EURUSD closes of July in step 2's table. Compute the percentage change on the pair, then on its reciprocal, and confirm the two magnitudes differ slightly. Then decide which one your system will store, and never store both.