Python for programmers, prompts for data analysts.
Every article in this series has trusted the numbers it pulled. That's mostly fine — but raw price data carries traps that look exactly
like real market events. A stock can appear to lose 95% of its value overnight when nothing happened to the company at all.
This one is about checking the data before believing the story it tells. Let's find a crash that never happened, and see which column of
the same dataset tells the truth.
Want to try this yourself? The EODHD MCP Server is what pulled the data above — connect it to Claude and ask your own questions (affiliate link).
New here? The Setup covers
everything you need before your first prompt.
Find the crash
🟧 PROMPT
Use the eodhd MCP to get AMZN's daily closing
prices from June 1 to June 8, 2022, and tell me
the biggest one-day change.
The biggest one-day move in that window: Friday, June 3, 2022, AMZN closed at $2,447.00. The next trading day, Monday, June 6, it
closed at $124.79. That's a drop of 94.9% in a single session.
Read that at face value and it's one of the worst days any major stock has ever had: a trillion-dollar company losing nearly all its
value between Friday and Monday. Except nothing like that happened. There was no collapse in the news that weekend, no panic, no
headline. Amazon was fine.
The same dataset has a second price column, and it tells a very different story:
Adjusted close, same two days: $122.35 on June 3, $124.79 on June 6. A gain of 2.0%.
Same stock, same two days, same data provider. One column says the stock lost 95%. The other says it gained 2%.
Ask why the two columns disagree
🟧 PROMPT
Use the eodhd MCP to check AMZN's split history.
Did anything happen on June 6, 2022?
Yes. On June 6, 2022, Amazon executed a 20-for-1 stock split. Every existing share became twenty shares, each worth one-twentieth of
the old price. A shareholder with one share worth $2,447 on Friday owned twenty shares worth about $124.79 each on Monday, roughly $2,
496 in total.The raw "close" column records the price per share exactly as it traded that day, so it shows the drop from $2,447 to $124.79. The
"adjusted close" column rewrites all earlier prices as if the split had always been in effect: $2,447 divided by 20 is $122.35. Divide
one Friday price by the other and you get exactly 20.0, the split ratio.
Nothing about Amazon's value changed that weekend. What changed was the unit of measurement: more, smaller slices of the same company.
The raw close is historically accurate about the price printed on each day, and completely misleading as a record of what an owner
actually gained or lost.
That's the trap. Any calculation that runs across a split on raw closes — a return, a chart, a moving average, a backtest like Part 25 —
inherits a 95% crash that never happened. Adjusted close exists to prevent exactly that. It also folds in dividends for companies that
pay them, which is why every return calculation in this series has used it.
A word of honesty
Adjusted close fixes one problem and quietly creates another: it rewrites history. Every time a company splits or pays a dividend, the
provider recalculates every earlier adjusted price. A number you saved from last year's adjusted series won't match the same date in
today's download, even though nothing about that day changed. Raw close never moves after the fact; adjusted close is only correct
relative to the moment you pulled it. The robust fix, as a reader pointed out, is to store the raw close together with the split and
dividend events and rebuild the adjusted series whenever you need it. Research databases like CRSP keep the raw price and its adjustment
factor in separate fields for exactly this reason, and EODHD exposes the same building blocks: raw prices, split history, and dividend
history.
Neither column is simply "right." Raw close is the truth about what a share actually traded for on a given day, which is why the options
articles in this series used real, unadjusted strike and spot prices. Adjusted close is the truth about what an owner gained or lost
over time. The mistake isn't choosing one; it's using the wrong one for the question you're asking.
Even the corporate-action records deserve a glance. EODHD lists Amazon's January 1999 split as 959,692 for 319,897, a ratio of 3.000003
rather than a clean 3-for-1. The difference is tiny, but it's a reminder that the data behind the adjustments is itself data, entered
and stored by someone, and worth a sanity check before you build on it.
And this is one pitfall out of many. Missing trading days, companies that vanished from a dataset, prices recorded in the wrong currency
or time zone: each can produce a result that looks precise and is simply wrong. The title of Alexander Hübbert's article "Six ways to
clean your trading data into the wrong answer" puts it well — the danger isn't dirty data, it's data that looks clean. Not investment
advice.
Final Thoughts
This is the thirty-third article in the series Unlock Real-Time Market Intelligence with EODHD and Claude, and the first one about the data itself rather
than what it says. Every earlier part trusted the numbers it pulled; this one checked whether they deserved it.
Two prompts found a crash, then found out it never happened.
So here's what they showed: on June 6, 2022, Amazon's raw closing price fell 94.9% overnight, while its adjusted close rose 2.0% — the
same stock, the same day, the same dataset. The difference was a 20-for-1 split, and dividing one Friday price by the other gives
exactly 20. Nothing was wrong with either column. What would have been wrong is feeding the raw one into a return, a chart, or a
backtest without asking what it measures. Clean-looking data is still worth one question before you trust it: which number is this, and
is it the one my question needs?
If this made you curious, the MCP Server is free to try — The Setup walks you through it.
← Part 32: “The Market” Isn't One Thing: Watching Sectors Take Turns
Top comments (9)
The futures version of this bit me last week. Public 1-minute bars from Yahoo passed my fill-inside-bar check for every bar they had: 233 of my partner's 293 entries sat inside their bar at the right clock offset, so I trusted them. The result still flipped sign when she exported her own bars from NinjaTrader. The missing 60 weren't random, the feed started on September 3 and only carried the front month.
So next to "which column tells the truth" I'd add "which rows aren't there at all", because a check can only score what exists. Does the adjusted close you're using handle contract rolls for futures too, or is that equities only?
"Which rows aren't there at all" is a better second question than anything in my article. A check can only score what exists, and the missing 60 weren't random: a late start plus front-month only removes a specific slice of trades, so the survivors aren't a fair sample of the original.
To your question: the adjusted close I used is equities only. It folds in splits and dividends, which is a per-share bookkeeping problem. Futures rolls are a different problem: there's no single "true" continuous price, only a choice of how to stitch contracts together (back-adjusted, ratio-adjusted, or unadjusted with roll dates), and each one distorts something else: levels, percentage moves, or continuity. So for futures the question isn't just "is it adjusted?" but "adjusted how, and when does it roll?", and that has to match how the trades were actually placed. Your NinjaTrader export matching her real fills is exactly the right reference. Thanks for the follow-up!
Your "which rows aren't there at all" question made it into the follow-up piece. All five series I checked had exactly the same 3,207 trading days, so none had a gap the others didn't, but I noted that this is only a relative check: a day missing from every series at once would pass it silently. Thanks again for pushing on that: dev.to/jaroslav_marda_9f25d4d9c/ev...
The 3.000003 ratio is a nice catch, and it points at a check that's cheap to automate: for every split in the corporate-action table, compare it with the raw price ratio across the split date. Here 2,447 / 124.79 is about 19.6, within that day's 2% move of 20, so the record agrees with the market.
The reverse direction is the one that finds real problems. Scan raw daily returns for moves whose ratio lands near a simple fraction (1/2, 1/3, 1/20, 3/2...) and look for a matching split. A big jump with no split behind it is either news or a missing record. A split whose ratio never shows up in the prices is often a record stored the wrong way round, a 1-for-20 reverse split entered as 20-for-1, and that one is nasty because the adjusted series comes out perfectly smooth while every price before that date is off by a factor of 400. Adjusted close hides it; the raw column is what lets you catch it, which is one more reason to keep both, as you say.
Thank you, this turns my one-off observation into an actual procedure. The forward check (record vs. raw price ratio) is the easy half; the reverse scan is the clever part, because it catches exactly the errors that adjusted close is built to hide. The reversed reverse split is a nasty example: a perfectly smooth adjusted series, with every earlier price off by a factor of 400. I may turn this into a follow-up piece and run that reverse scan on real data to see what it finds. Thanks for taking the time to write it up so clearly.
Following up: I took your forward-and-reverse split check and ran it on five large stocks since 2014. All nine recorded splits showed up in the raw prices, and every one-day move over 30% landed on a recorded split. The most useful part was a near-miss: a tight "close to a simple fraction" filter would have flagged Tesla's 2020 split as missing, because the stock also rallied 12.6% that day. Write-up here, with credit to your idea: dev.to/jaroslav_marda_9f25d4d9c/ev...
Thanks for running it, and for the credit. The Tesla near-miss is a good argument for scaling the tolerance to the stock instead of fixing it. Compare the log of (raw ratio / split ratio) with a few times the stock's own recent daily volatility. On 31 August 2020 the raw ratio was 0.2251 against a split of 1/5, a log gap of 0.118, while Tesla's daily volatility over the previous 60 trading days was 4.6%. Three times that is 0.138, so a volatility-scaled band keeps the split, while a fixed band tight enough for a quiet utility drops it.
Futures version of the same trap, from this week. I replayed my partner's 293 MNQ/MES entries against fixed take-profit/stop brackets, first on public 1-minute bars (Yahoo), then on her own bars exported from NinjaTrader. The public bars passed every sanity check I had: each fill sat inside the high-low of the bar it happened in. The problem wasn't a bad bar, it was missing bars: the feed only carried the front-month contract and started a few days late, so 60 of her entries silently fell out of the replay. On the 233 that remained, her hand exits beat the best bracket out of sample. On all 293 with her own bars, the bracket beat her exits. Same code, opposite sign. Your split example is a wrong column; mine was a right column with holes in it, and the second kind doesn't throw an error anywhere.
This is a better example than mine, honestly. A wrong column at least leaves a fingerprint: a 95% drop that never happened is loud once you look. Missing bars leave nothing. Every check you run passes on the rows that survived, and the rows that didn't survive aren't there to fail. Losing 60 of 293 entries and getting the opposite answer is a perfect illustration of why "did anything drop out?" deserves to be its own check, separate from "is each row valid?". Thanks for sharing the real numbers.