In the moving-average lessons, we kept asking one kind of question:
Where is the average price level?
We took several prices, combined them, and made a smoother line.
Now we are going to ask a different question:
How much did price change?
That small change in the question takes us from moving averages to momentum.
1. Start with the Idea We Already Know
A moving average transforms several prices into an average.
prices
↓
average them
↓
smoother price level
That helps us see the broad direction without reacting to every small move.
But averaging is only one way to transform price.
We can also compare two prices directly.
price now
-
price before
=
price change
That is the basic idea behind momentum.
2. Begin with One Tiny Example
Imagine a stock closed at:
10 trading days ago: 100
today: 106
The change is:
106 - 100 = +6
So 10-day momentum is +6.
If today's Close were 96 instead:
96 - 100 = -4
Then 10-day momentum would be -4.
Nothing mysterious happened. We only subtracted one old price from one new price.
3. The Momentum Formula
We can write the idea as:
Momentum now
=
Price now
-
Price N periods ago
If we choose:
N = 10
each momentum value compares today's Close with the Close 10 trading rows earlier.
This gives us three simple cases:
Momentum > 0
→ price is higher than N periods ago
Momentum < 0
→ price is lower than N periods ago
Momentum = 0
→ price is unchanged from N periods ago
The zero line therefore has a natural meaning.
4. Moving Average and Momentum Ask Different Questions
This is the most important idea in this lesson.
Moving Average
many prices
→ average
→ smoother level
Momentum
two prices
→ difference
→ change
Both calculations start from the same Close prices.
In our chart, we will keep SMA 20 and EMA 20 on the price panel so you can keep the moving-average idea in view while we add momentum below it.
same Close prices
↓
SMA 20 / EMA 20
→ smoother level
same Close prices
↓
Momentum 10
→ price change
But the transformation changes what we can see.
This is a useful way to think about every technical indicator:
same raw data
+
different calculation
=
different view of the market
5. Build Momentum from Scratch
We only need one new Learning Block.
def momentum(values, lookback):
momentum_values = [None] * lookback
for i in range(lookback, len(values)):
price_now = float(values[i])
price_before = float(values[i - lookback])
change = price_now - price_before
momentum_values.append(change)
return momentum_values
Read the loop slowly.
take the current price
↓
find the price N rows before
↓
subtract
↓
save the change
↓
move to the next row
That is the entire calculation.
6. Why Do the First Values Return None?
Suppose we want 10-day momentum.
On the first row, there is no price from 10 rows earlier.
The same is true for rows 2 through 10.
So the code starts with:
momentum_values = [None] * lookback
The missing values are not errors.
They mean:
not enough past data yet
You already saw the same idea when we built a Simple Moving Average.
7. Reuse the Blocks We Already Know
We do not need to rebuild the moving-average or candlestick code.
We already learned:
simple_moving_average()
exponential_moving_average()
draw_candlesticks()
So Phase 3-9 reuses those Frozen Learning Blocks without changing them.
KNOWN BLOCK
simple_moving_average()
↓
SMA 20
KNOWN BLOCK
exponential_moving_average()
↓
EMA 20
KNOWN BLOCK
draw_candlesticks()
↓
price candles
NEW BLOCK
momentum()
↓
Momentum 10
This gives us a useful comparison.
upper panel
→ candles + SMA 20 + EMA 20
lower panel
→ Momentum 10
We are not throwing away the moving-average ideas. We are placing a new transformation next to them.
8. Build the Smallest Reusable Plot Block
For the first time, our chart needs more than one panel.
We could write the full plt.subplots(...) command every time.
But we already know something about the future of this course:
today
2 panels
later
3 panels
4 panels
...
7 panels
So this is a good moment to make one very small plotting Building Block:
def create_stacked_panels(
panel_count,
height_ratios,
figure_width=12,
figure_height=9,
figure_dpi=100,
):
fig, axes = plt.subplots(
panel_count,
1,
figsize=(figure_width, figure_height),
dpi=figure_dpi,
sharex=True,
gridspec_kw={
"height_ratios": height_ratios,
},
)
return fig, axes
This function does not draw candles. It does not calculate SMA, EMA, Momentum, RSI, or MACD.
Its job is much smaller:
make empty panels
↓
stack them vertically
↓
make them share the same x-axis
↓
return the figure and axes
Think of it as building the empty rooms before we decide what to put inside each room.
What Does panel_count Mean?
panel_count tells Matplotlib how many vertical plotting areas we want.
In this lesson:
panel_count = 2
so Matplotlib gives us two axes:
axes[0]
→ upper panel
axes[1]
→ lower panel
We give them names so the code becomes easier to read:
ax_price = axes[0]
ax_momentum = axes[1]
Now the variable names tell us what each room is for.
What Does height_ratios Mean?
We do not want the price panel and momentum panel to have the same height.
Price needs more room, so we use:
height_ratios = [3, 1]
Read this as:
upper panel → 3 parts
lower panel → 1 part
The exact pixel height is not important. The ratio between the panels is what matters.
Why Is the Second Number in plt.subplots() Equal to 1?
plt.subplots(
panel_count,
1,
...
)
The first number means rows. The second number means columns.
We want panels stacked from top to bottom, not side by side.
2 rows × 1 column
[ price ]
[ momentum ]
Later, if panel_count = 4, the same idea becomes:
4 rows × 1 column
[ price ]
[ momentum ]
[ RSI ]
[ ATR ]
Why Use sharex=True?
Every panel represents the same trading dates.
So we want one horizontal time position to mean the same date in every panel.
sharex=True
same x position
↓
same date
↓
all panels line up vertically
This becomes more useful as the number of indicators grows.
If a price event happens at one x position, you can look straight down and inspect Momentum, RSI, MACD, or another indicator at the same time.
What Are fig and axes?
Matplotlib returns two useful objects:
fig
→ the entire figure
axes
→ the individual plotting panels
The figure is the whole page. Each axis is one panel inside that page.
That is why our function returns both:
return fig, axes
We need axes to draw inside each panel,
and we need fig later when we adjust spacing or save the entire image.
How Will This Grow Later?
The useful part is that the function itself does not need to know which indicators we add.
Three panels could be:
fig, axes = create_stacked_panels(
panel_count=3,
height_ratios=[3, 1, 1],
)
axes[0] → price
axes[1] → momentum
axes[2] → RSI
Four panels could be:
fig, axes = create_stacked_panels(
panel_count=4,
height_ratios=[3, 1, 1, 1],
)
axes[0] → price
axes[1] → momentum
axes[2] → RSI
axes[3] → ATR
And one day, seven panels could still use exactly the same Building Block:
fig, axes = create_stacked_panels(
panel_count=7,
height_ratios=[3, 1, 1, 1, 1, 1, 1],
)
The layout block stays small. We only add new calculations and new drawing instructions around it.
That is exactly what a Frozen Learning Block should do: solve one small problem well, then stay familiar while the rest of the program grows.
9. Why Put Momentum Below Price?
Price and raw momentum use different units on the vertical axis.
So we keep them in two panels:
top
→ OHLC candlesticks
→ SMA 20
→ EMA 20
bottom
→ Momentum 10
The two panels use the same dates.
That makes it easy to ask:
What was price doing
when momentum moved above zero?
What was price doing
when momentum moved below zero?
When did momentum become larger
or smaller?
Notice the wording.
We are observing. We are not creating a buy or sell rule yet.
10. Read the Chart in the Right Order
When the chart opens, start with price.
1. Read the candles.
2. Look at SMA 20 and EMA 20.
3. Ask what they say about the smoother price level.
4. Move down to the momentum panel.
5. Check whether momentum is positive or negative.
6. Look at how large the change is.
7. Ask which old price is being compared.
The last question matters because momentum always depends on the lookback.
11. The Lookback Changes the Question
If:
lookback = 5
we ask:
How much did price change
over roughly one trading week?
If:
lookback = 20
we ask about a much longer comparison.
So changing the lookback does not merely change a chart setting.
It changes the time distance between the two prices being compared.
12. Momentum Is Not a Prediction
Suppose 10-day momentum is strongly positive.
We can say:
price now
is much higher than
10 trading days ago
We cannot automatically say:
price must rise tomorrow
Momentum is calculated from prices that already happened.
past price
+
current price
↓
measured change
Whether that change contains a useful trading edge is a later research question.
13. One Important Limitation of Raw Momentum
Raw momentum is measured in price units.
For example:
Stock A
100 → 105
momentum = +5
Stock B
1,000 → 1,005
momentum = +5
The raw momentum number is the same.
But the size of the move relative to each starting price is very different.
That gives us the next question:
How can we express price change
relative to the old price?
That idea leads naturally to Rate of Change.
14. Try One Small Experiment
Start with:
momentum_lookback_days = 10
Then try:
momentum_lookback_days = 5
and:
momentum_lookback_days = 20
Run the file again each time and ask:
Does the zero-crossing date change?
Which setting reacts to shorter moves?
Which setting stays positive or negative longer?
Which old price is each value comparing?
The goal is not to find the best number.
The goal is to understand what the lookback means.
Check Your Understanding
You are ready to move on if you can explain these ideas in your own words:
- A moving average summarizes price level, while momentum measures price change.
- Raw momentum is current price minus the price N periods ago.
- Positive momentum means price is higher than N periods ago.
- Negative momentum means price is lower than N periods ago.
- The first N momentum values are unavailable because there is not enough history yet.
- The lookback changes which two points in time are being compared.
- Momentum describes a completed price change; it does not automatically predict the next move.
- Raw momentum is measured in price units, which makes cross-price comparisons difficult.
create_stacked_panels()creates reusable vertically stacked axes with one shared time axis.- The same plot block can grow from 2 panels to 3, 4, or more by changing
panel_countandheight_ratios.
What You Just Learned
Close prices
↓
choose a lookback
↓
Price now - Price before
↓
Momentum
↓
positive / zero / negative
↓
measure price change
If one idea stays in your head after this lesson, let it be this:
A moving average asks where price has been. Momentum asks how price is changing.
And now we have a new limitation to solve.
A five-dollar move does not mean the same thing for every price level.
The next logical step is to turn the change into a relative number: a percentage.