Finding charts that look like this one
Every charting tool eventually gets the same feature request: "show me other times this stock looked like this." It sounds like a lookup. It is not. The retrieval is the easy half. The hard half is that a correct implementation can still produce results that are quietly meaningless, and nothing in the code will tell you. Here is the method, and the failure modes worth knowing before you ship it.…
Every charting tool eventually gets the same feature request: show me other times this stock looked like this. It sounds like a lookup, but it's not. The retrieval is easy, but getting it right can be difficult and there are failure modes to be aware of before implementing it. This article explains the method and potential pitfalls.
The naive version takes the last 30 days of closing prices as a query vector, slides it across history, computes Euclidean distance, and returns the closest matches. However, this approach fails immediately. Every match comes from whatever period had a similar price level, regardless of the shape or scale. A stock that moved 2% over the window can be considered unrelated to one that moved 40% despite tracing the same shape.
To fix this, z-normalize each window independently. This removes the relative offsets and allows for a fair comparison. Z-normalization involves subtracting the mean and dividing by the standard deviation (plus a small constant to avoid division by zero) for each window. This ensures that squared Euclidean distance and Pearson correlation are equivalent measurements on z-normalized vectors.
When deciding whether to use prices or returns, log returns are recommended as the safer default. Prices are non-stationary, meaning their variance depends on when you're looking, while returns are closer to stationary. Normalizing returns before normalization compares how the stock moved rather than where it sat. The window length is a real parameter and should be adjustable to match the user's intent. Shorter windows find candlestick shapes and noise, while longer windows capture regime shifts but find very few matches.
Dynamic Time Warping (DTW) allows stretching along the time axis, but it is expensive and may not be desirable for financial series. DTW can match moves that took different amounts of time but have the same shape, which may not represent similar events. If using DTW, limit the warping window with a Sakoe–Chiba band to keep matches more meaningful.
The naive scan has an O(n·m) time complexity per query, which can be optimized by precomputing rolling statistics. Rolling mean and standard deviation can be calculated in O(n) total, eliminating per-comparison work. Alternatively, use the matrix profile, which uses an FFT-based approach to compute all pairwise window distances more efficiently.
For cross-ticker search at scale, normalize windows and store them in an approximate nearest neighbor (ANN) index like FAISS or HNSW. Approximate neighbors provide a suggestion rather than a definitive answer.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.