Hidden Markov Models (HMMs) show up everywhere from speech recognition to genetics to finance, but most explanations jump straight into notation before explaining why any of it matters. This post is my attempt to build up the idea from scratch, starting with plain Markov chains, then adding the “hidden” twist, and ending with the three core problems every HMM implementation needs to solve.
Markov Chains
Markov chains are a mathematical model that let us describe how a system moves from one state to another when that movement is random.
A Markov chain has two main components:
- States — snapshots of the different situations or conditions a system can occupy.
- Transition probabilities — the probability of moving from one state to another.
These transitions follow one governing rule: the Markov property (also called the memoryless property). It states that the future depends only on the current state, not on the full history that came before it.
A simple example is weather prediction. We might define states like sunny, windy, gloomy, and rainy. These are the situations the weather can be in at a given time. A Markov chain can be used to determine tomorrow’s likely weather based only on today’s weather and the transition probabilities, ignoring what the weather was like last week.
In a nutshell:
Markov chain = states + transition probabilities, where transitions obey the Markov property.
This basic version is where the next state depends on exactly one previous state. This is called a first-order Markov chain. Later, we’ll see that some systems (like financial markets) may need to remember more than just one step back, which leads to higher-order chains.
Markov chains are one of the simplest tools for modeling stochastic (random) systems that evolve over time, and they show up everywhere from weather modeling to genetics to as we’ll get into finance.
Hidden Markov Models
In a plain Markov chain, the states themselves are the data — we directly observe that today is rainy or sunny. A Hidden Markov Model (HMM) adds a twist: there are two parallel layers instead of one.
- A hidden Markov chain, whose states we never directly observe, evolving according to transition probabilities.
- An observable output at each time step, whose distribution depends on the current hidden state. This is called the emission.
Why bother hiding anything? Because often the thing we actually care about isn’t directly measurable. In financial markets, we might believe there’s some underlying “regimes” such as bullish, bearish, choppy which are driving how prices move, but we can never observe that regime directly. All we see is the price. The hidden state is our attempt to infer that unseen regime from what we can see.
An HMM has four core components:
- Hidden state — the true, unobservable condition of the system at a given time.
- Observation — the visible data or output generated by the hidden state.
- Transition probabilities — the odds of moving from one hidden state to another.
- Emission probabilities — the odds of producing a specific observation given a hidden state.
And two core assumptions:
- Markov property (hidden layer) — the next hidden state depends only on the current hidden state.
- Output independence — the observation at any time step depends only on the hidden state at that same time step, not on past states or past observations. Also called the emission assumption.
The standard notation for an HMM is:
λ = (A, B, π)
- A — the transition matrix (hidden state → hidden state)
- B — the emission distribution (hidden state → observation)
- π — the initial state distribution: the probability of starting in each state at time 1, i.e. π_i = P(i₁ = i) — not the states themselves, but the odds of each one being the starting point.
One more distinction worth knowing: if the observations come from a finite set of possibilities (like coin flip outcomes) then B really is a matrix of probabilities, and this is a discrete HMM. But if observations are real numbers (like a stock’s daily return), is instead a probability density function per state and this is called a continuous HMM, and it’s what we’ll be using when we get to stock prediction, where each hidden state’s emissions are modeled with a Gaussian Mixture rather than a simple lookup table.
Why Hidden States, and Not Just Observable Ones?
A natural question at this point is: why bother with a hidden layer at all, why not just use a plain Markov chain over states we can directly observe? The answer is that HMMs exist specifically for situations where the thing actually driving the system isn’t measurable, only its effects are.
In speech recognition, for example, the hidden states might represent the words someone intends to say, while all we ever observe are sound waves. In financial markets, the hidden state might represent an underlying “regime” such as bullish, bearish, choppy that no one directly announces; we only see prices move.
Even if we tried to label such states ourselves (e.g., “this month felt bearish”), that labeling would be subjective and retroactive. An HMM instead lets the data discover these latent states as a byproduct of fitting the model, without needing labeled examples.
If a system’s states truly are directly observable, there’s no benefit to hiding them, you’d just use a regular Markov chain. The hidden layer is a deliberate modeling choice for exactly one situation: you believe there’s an unobserved driver behind what you’re seeing, and you only have indirect, noisy evidence of it.
The Three Classic HMM Problems
Once you have an HMM, there are three distinct questions you can ask of it. They’re often introduced together because Rabiner’s classic HMM tutorial frames them this way — and it’s a favorite in technical interviews.
These problems are distinct in what they compute, but they aren’t fully independent in practice. There’s a natural order to how you’d actually use them: you almost always need to solve Learning first (to get a trained model λ), and only then does it make sense to ask Evaluation or Decoding questions of that model. So the relationship is less “three unrelated problems” and more: Learning produces the model, and Evaluation and Decoding are two different things you can then do with it, in whichever order you like.
1. Evaluation: “How likely is this data, given this model?”
Formally: given a model λ = (A, B, π) and an observation sequence O = (o₁, …, o_T), compute P(O | λ).
This is solved using the Forward algorithm, which efficiently sums over all possible hidden state paths that could have produced O, without literally enumerating every path (which would be exponentially expensive).
Simple example: Suppose you’ve trained two different HMMs — one on “bull market” price behavior and one on “bear market” price behavior. Given a new 30-day stretch of returns, you can ask each model “how likely is it that you generated this data?” and compare the two scores. Whichever model gives a higher P(O | λ) is the better explanation for what you’re seeing.
2. Decoding: “What hidden state sequence best explains this data?”
Formally: given λ and O, find the single most likely hidden state sequence I = (i₁, …, i_T) that could have produced it.
This is solved using the Viterbi algorithm, a dynamic programming method that finds the single best path through the hidden states — as opposed to the Forward algorithm, which sums over all paths to get a total probability, Viterbi picks out the one best path.
Simple example: Say your HMM has three hidden states you’ve come to interpret as “rising,” “falling,” and “flat” regimes. Given the last 300 days of a stock’s returns, Viterbi tells you which regime the model believes each of those days belonged to — e.g., “days 1–40 were probably regime 2 (rising), days 41–55 were probably regime 0 (falling),” and so on.
3. Learning: “What model parameters best explain this data?”
Formally: given only the observations O (and a chosen number of hidden states N), find the parameters λ = (A, B, π) that maximize P(O | λ).
This is solved using the Baum-Welch algorithm, a specific application of the more general Expectation-Maximization (EM) algorithm. It works iteratively: first, using the current guess of the parameters, estimate how likely each hidden state is at each time step (the “E-step”); then, using those estimates, re-compute better parameter values (the “M-step”). You repeat this back-and-forth until the parameters stop changing much.
Simple example: You don’t tell the model in advance what “bull,” “bear,” or “flat” regimes look like statistically, you just feed it years of daily returns and ask it to find, say, 3 hidden states that best explain the data. Baum-Welch converges on transition probabilities and emission distributions on its own; interpreting what those states mean (e.g., which one corresponds to rising prices) is a separate step done afterward by inspecting the data.
In Part 2, we’ll build on this foundation to look at high-order HMMs — models that remember more than just one previous state — and how they’re used to build an actual trading strategy on stock index data.