In the previous lesson, we measured price change with Momentum.
Momentum
=
Price now
-
Price N periods ago
That gave us a useful new view of price.
But it also created a problem.
Stock A
100 → 105
Momentum = +5
Stock B
1,000 → 1,005
Momentum = +5
Both stocks moved by five price units.
Did they really make the same size move?
No.
This lesson solves that problem.
1. Absolute Change Is Not Enough
Momentum tells us the distance between two prices.
105 - 100
=
+5
But the number +5 does not tell us how large that move was
compared with the starting price.
For a 100-dollar price:
5 / 100
=
0.05
=
5%
For a 1,000-dollar price:
5 / 1000
=
0.005
=
0.5%
The dollar change was the same. The relative change was very different.
2. Turn Momentum into a Relative Number
We already know the numerator:
Price now - Price before
That is Momentum.
Now divide that change by the earlier price:
Price now - Price before
────────────────────────
Price before
Then multiply by 100:
ROC (%)
=
(Price now - Price before)
──────────────────────────
Price before
× 100
ROC stands for Rate of Change.
3. Momentum and ROC Are Closely Related
This is the key connection.
Momentum
=
absolute change
ROC
=
absolute change
÷ old price
× 100
So we do not throw away what we learned in Phase 3-9.
We build directly on it.
Price now - Price before
↓
Momentum
↓
divide by Price before
↓
ROC (%)
This is how indicators should become easier over time: one known idea becomes part of the next idea.
4. A Small Example by Hand
Suppose:
10 days ago: 200
today: 210
First calculate Momentum:
210 - 200 = +10
Then calculate ROC:
10 / 200 × 100
=
5%
Now the two numbers answer different questions:
Momentum = +10
→ How many price units did it move?
ROC = +5%
→ How large was the move
relative to the earlier price?
5. Build ROC from Scratch
We need only one new Learning Block.
def rate_of_change(values, lookback):
roc_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
roc = change / price_before * 100
roc_values.append(roc)
return roc_values
Read the new part carefully.
change = price_now - price_before
roc = change / price_before * 100
The first line is the same idea as Momentum.
The second line turns that absolute change into a relative percentage.
6. Why Does the Function Check for Zero?
The full Python file contains one extra safety check:
if price_before == 0:
roc_values.append(None)
continue
Division by zero is undefined.
A normal stock price should not be zero, but a reusable function should still protect itself from an impossible denominator.
This is a small example of an important programming habit:
understand the formula
↓
find the dangerous operation
↓
handle the edge case
7. Reuse Every Block We Already Know
Phase 3-10 does not rewrite our earlier functions.
simple_moving_average()
→ REUSE
exponential_moving_average()
→ REUSE
momentum()
→ REUSE
draw_candlesticks()
→ REUSE
create_stacked_panels()
→ REUSE
rate_of_change()
→ NEW
This is the Frozen Learning Blocks idea in action.
8. The Plot Block Grows from Two Panels to Three
In Phase 3-9 we used:
fig, axes = create_stacked_panels(
panel_count=2,
height_ratios=[3, 1],
)
We needed two rooms:
axes[0] → price
axes[1] → momentum
Now we need one more room.
We do not change the function.
We only change its inputs:
fig, axes = create_stacked_panels(
panel_count=3,
height_ratios=[3, 1, 1],
)
The returned axes now become:
axes[0] → price
axes[1] → momentum
axes[2] → ROC
This is exactly why we made the plot function small.
same function
+
different arguments
=
larger chart structure
9. What Do the Three Panels Mean?
Panel 1
Candles + SMA 20 + EMA 20
→ Where is price moving?
Panel 2
Momentum 10
→ How many price units did it change?
Panel 3
ROC 10
→ How large was that change in percent?
All three panels start from the same price data.
Each transformation answers a different question.
10. Momentum and ROC Often Turn at the Same Places
For ordinary positive market prices, Momentum and ROC use the same numerator:
Price now - Price before
ROC divides that number by a positive earlier price.
So if Momentum is positive, ROC is also positive.
If Momentum is negative, ROC is also negative.
Momentum > 0
→ ROC > 0
Momentum < 0
→ ROC < 0
With the same lookback, their zero crossings therefore occur at the same places as long as the earlier price is positive.
The important difference is the scale:
Momentum
→ price units
ROC
→ percent
11. Why Percentage Change Helps Comparison
Return to our first example.
100 → 105
Momentum = +5
ROC = +5%
1,000 → 1,005
Momentum = +5
ROC = +0.5%
ROC immediately shows that the first move was much larger relative to its price level.
This idea is called normalization in a broad sense: we scale a raw number by something that gives it context.
You will see this idea again and again in technical indicators.
12. ROC Is Still Not a Prediction
A ROC of +8% means:
price is 8% higher
than it was N periods ago
It does not mean:
price will rise another 8%
ROC is still calculated from completed price data.
Whether high or low ROC contains useful information about the future is a separate hypothesis that we can test later.
13. Change One Thing Yourself
First keep:
change_lookback_days = 10
Change only the symbol.
Compare:
Momentum 10
versus
ROC 10
Ask:
Which number is easier to compare
across different price levels?
Then try:
change_lookback_days = 5
and:
change_lookback_days = 20
The goal is not to find the best lookback.
The goal is to understand what changes when the time distance changes.
14. What New Idea Did We Really Learn?
ROC is useful, but the deeper idea is more important.
raw number
↓
divide by a reference
↓
relative number
↓
easier comparison
We have started moving from simple transformations toward normalized indicators.
That idea will become very important when we reach indicators such as RSI.
Check Your Understanding
- Momentum measures absolute price change in price units.
- ROC measures the same change relative to the earlier price.
- ROC is usually expressed as a percentage.
- With positive prices and the same lookback, Momentum and ROC have the same sign.
- The first N values are unavailable because there is not enough history yet.
- Dividing by the earlier price makes comparisons across different price levels easier.
- ROC describes past percentage change; it does not guarantee future movement.
create_stacked_panels()did not change when the chart grew from two panels to three.
What You Just Learned
Price
↓
difference
↓
Momentum
↓
divide by old price
↓
ROC
↓
relative change (%)
If one idea stays in your head after this lesson, let it be this:
Momentum tells us how far price moved. ROC tells us how large that move was relative to where price started.
We now have another powerful idea: normalization.
That gives us a natural path toward indicators that compare different kinds of recent movement on a common scale.