Contents Lesson 7 of 16

7 min read · foundations

Your tickers, in one call

Time to replace the demo list with your own instruments and make the whole thing cost one request.

The list is a file you edit

In the starter, your watchlist lives in src/lib/watchlist.ts:

export const WATCHLIST: string[] = [
  "AAPL.US",
  "MSFT.US",
  "NVDA.US",
  "SPY.US",
  "BTC-USD.CC",
];

A file, not a database, and deliberately so. You are one person watching your own instruments; a database would be a second thing to run, back up and pay for, in exchange for a convenience you do not yet need. When editing a file stops being enough, because you want to add a symbol from your phone, that is a real reason to add storage, and it arrives in a later course.

Ticker format, and the part that surprises people

EODHD identifiers are SYMBOL.EXCHANGE:

Ticker What it is
AAPL.US Apple, US listing
VOD.LSE Vodafone, London
SAP.XETRA SAP, Frankfurt
BTC-USD.CC Bitcoin against the dollar
EURUSD.FOREX Euro against the dollar

The exchange suffix is part of the identity, not decoration: the same company listed in two places is two tickers with two prices, often in two currencies. Vodafone is pence in London and dollars in New York; SAP is euros on both Xetra and Frankfurt. Different price either way, and the currency is the trap you have to check rather than assume.

And the currency is not in the response. VOD.LSE quotes in pence, not pounds, a London convention that has produced more wrong dashboards than any other single fact in this course. If you mix AAPL.US and VOD.LSE in one column and sum them, you have added dollars to pence and produced a number that means nothing. Either keep one currency per view, or label the column per row. Do not silently total a mixed list.

One request, whatever the length

The endpoint takes the first ticker in the path and the rest in s:

const [first, ...rest] = tickers;
const params = rest.length ? `?s=${rest.join(",")}` : "";
const res = await fetch(`/api/proxy/real-time/${first}${params}`);

Five instruments, one request. Twenty instruments, still one request — but twenty calls, because /real-time is priced per symbol. The saving is in round trips, not in quota, and there is a second saving worth more than it looks: every row in one response was taken at the same moment, so your table shows one snapshot rather than twenty arriving at twenty different times.

Your watchlist therefore costs list length × page loads. Both numbers are yours to choose, and the wall in unit 4 is where they meet your allowance.

Handle both response shapes, because you now know about the bare object:

const body: unknown = await res.json();
const rows = Array.isArray(body) ? body : [body];

Trust the fields, verify the values

From a live response on 2026-08-25:

{"code":"AAPL.US","timestamp":1787603280,"close":310.34,
 "previousClose":309.35,"change":0.99,"change_p":0.32,"volume":32510925}

change is close - previousClose: 310.34 minus 309.35 is 0.99. Correct. change_p is that as a percentage of previousClose: 0.99 / 309.35 = 0.32%. Correct.

Do that arithmetic once, by hand, on a real response. It takes a minute and it tells you what the field means, which is the difference between using an API and hoping.

Note what change is not: it is not the move since the open, and it is not the move over 24 hours. It is measured from the previous session's close. Once Monday is trading, change spans the weekend gap — but before the open, which is when this tool was planned to run, the pair is still Friday's close against Thursday's, so the figure is Friday's session move and contains no weekend at all.

Render numbers so they can be read

Two rules, both cheap, both the difference between a tool and a toy:

Tabular figures. font-variant-numeric: tabular-nums makes every digit the same width, so a column of prices lines up. Without it, 1,234.56 and 987.65 are ragged and your eye cannot scan them.

The sign carries the direction, not just the colour. Print +0.99 and -6.24, then colour them. Colour alone fails for a colour-blind reader, a bad screen, and a printout, and you will read this tool on a phone in sunlight.

Try it now

Put your real instruments in src/lib/watchlist.ts, including at least one that is not US-listed. Then verify the arithmetic yourself: pick a row, take close and previousClose from the raw response, and check that change and change_p are what you would compute. If your list has both a US and a London name, look at the two prices side by side and say out loud what units each is in.