Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Chapter 6 — Trading Indicators as Filters

In the previous chapter, we studied smoothing methods designed to reduce noise and reveal underlying structure.

Many popular trading indicators are built on exactly the same idea.

They attempt to:

This chapter introduces several widely used technical indicators:

The emphasis is practical and intuition-first.

We interpret these indicators not as mysterious trading formulas, but as statistical filtering tools.


Learning Objectives

By the end of this chapter, you should be able to:


6.1 Why Trading Indicators Exist

Financial prices contain substantial noise.

Daily fluctuations may reflect:

Traders therefore attempt to extract useful signals from noisy data.

Most indicators attempt to identify:


6.2 Trend Following vs Mean Reversion

Many trading indicators implicitly rely on one of two ideas.

Trend Following

Prices that rise may continue rising.

Prices that fall may continue falling.

Examples:

Mean Reversion

Prices that move too far away from normal levels may eventually reverse.

Examples:


6.3 Moving Averages Revisited

Recall from the previous chapter that moving averages smooth noisy fluctuations.

For trading applications, moving averages are often interpreted dynamically.

Traders compare:


6.4 Moving Average Crossover Systems

One of the simplest trading systems uses two moving averages:

Basic Logic

Bullish Signal

If the short moving average rises above the long moving average:

Buy signal

Bearish Signal

If the short moving average falls below the long moving average:

Sell signal

6.5 Example: Moving Average Crossover vs. MACD

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# --- Generate synthetic price data ---
np.random.seed(42)

dates = pd.date_range(start="2024-01-01", periods=200)

prices = np.cumsum(np.random.randn(200)) + 100

df = pd.DataFrame(
    {"Close": prices},
    index=dates
)

# --- Moving Averages ---
df["MA12"] = df["Close"].rolling(window=12).mean()

df["MA26"] = df["Close"].rolling(window=26).mean()

# --- Trading Signals ---
df["Signal"] = np.where(
    df["MA12"] > df["MA26"],
    1,
    -1
)

df["Crossover"] = df["Signal"].diff()

# --- MACD Calculation ---
df["EMA12"] = df["Close"].ewm(
    span=12,
    adjust=False
).mean()

df["EMA26"] = df["Close"].ewm(
    span=26,
    adjust=False
).mean()

df["MACD"] = df["EMA12"] - df["EMA26"]

df["SignalLine"] = df["MACD"].ewm(
    span=9,
    adjust=False
).mean()

df["Histogram"] = (
    df["MACD"] - df["SignalLine"]
)

# --- Plot Figure ---
plt.figure(figsize=(12,8))

# ==================================================
# Top Panel: Prices and Moving Averages
# ==================================================

plt.subplot(2,1,1)

plt.plot(
    df.index,
    df["Close"],
    label="Close Price",
    color="black",
    alpha=0.7
)

plt.plot(
    df.index,
    df["MA12"],
    label="MA12",
    linewidth=2
)

plt.plot(
    df.index,
    df["MA26"],
    label="MA26",
    linewidth=2
)

# Buy Signals
buy = df[df["Crossover"] == 2]

plt.scatter(
    buy.index,
    buy["Close"],
    marker="^",
    s=100,
    label="Buy Signal"
)

# Sell Signals
sell = df[df["Crossover"] == -2]

plt.scatter(
    sell.index,
    sell["Close"],
    marker="v",
    s=100,
    label="Sell Signal"
)

plt.title("Moving Average Crossover Strategy")

plt.legend()

# ==================================================
# Bottom Panel: MACD
# ==================================================

plt.subplot(2,1,2)

plt.plot(
    df.index,
    df["MACD"],
    label="MACD",
    linewidth=2
)

plt.plot(
    df.index,
    df["SignalLine"],
    label="Signal Line",
    linewidth=2
)

plt.bar(
    df.index,
    df["Histogram"],
    alpha=0.5,
    label="Histogram"
)

plt.axhline(
    0,
    linestyle="--",
    linewidth=1
)

plt.title("MACD Indicator")

plt.legend()

plt.tight_layout()

plt.savefig("figs/ch6/MACD.png", dpi=300, bbox_inches="tight")
plt.close()   # replace with plt.show()
MACD

However, crossover systems may also generate false signals during sideways markets.


6.6 Golden Cross and Death Cross

Two famous crossover patterns are:

Golden Cross

Occurs when:

Often interpreted as bullish.

Death Cross

Occurs when:

Often interpreted as bearish.

This creates a trade-off:


6.7 MACD: Moving Average Convergence Divergence

MACD is one of the most widely used momentum indicators.

It compares:

MACD Formula

The MACD line is:

MACDt=EMAshort,tEMAlong,tMACD_t = EMA_{short,t} - EMA_{long,t}

Common choices are:

Signal Line

A second moving average is then applied to MACD itself.

This is called the:

signal line

6.8 MACD in Python

We now compute and visualize the MACD indicator.

import yfinance as yf
import matplotlib.pyplot as plt

# Download data
sp500 = yf.download(
    "SPY",
    start="2020-01-01",
    auto_adjust=False
)

# Adjusted closing prices
prices = sp500["Adj Close"]

# Exponential moving averages
ema12 = prices.ewm(
    span=12,
    adjust=False
).mean()

ema26 = prices.ewm(
    span=26,
    adjust=False
).mean()

# MACD line
macd = ema12 - ema26

# Signal line
signal = macd.ewm(
    span=9,
    adjust=False
).mean()

# Plot
plt.figure(figsize=(10,5))

plt.plot(
    macd,
    label="MACD",
    linewidth=2
)

plt.plot(
    signal,
    label="Signal Line",
    linewidth=2
)

plt.axhline(
    0,
    linestyle="--",
    linewidth=1
)

plt.title("MACD Indicator")

plt.legend()

plt.show()

6.9 Relative Strength Index (RSI)

RSI is a momentum oscillator.

It attempts to measure the speed and magnitude of recent price movements.

RSI usually ranges between:

0 and 1000 \text{ and } 100

Basic Interpretation

RSIInterpretation
above 70potentially overbought
below 30potentially oversold

6.10 RSI Formula

RSI is computed from average gains and losses.

The standard formula is:

RSI=1001001+RSRSI = 100 - \frac{100}{1+RS}

where:

RS=Average GainAverage LossRS = \frac{\text{Average Gain}}{\text{Average Loss}}

6.11 RSI in Python

import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt

sp500 = yf.download("SPY", start="2020-01-01", auto_adjust=False)

prices = sp500["Adj Close"]

delta = prices.diff()

up = delta.clip(lower=0)
down = -delta.clip(upper=0)

roll_up = up.rolling(14).mean()
roll_down = down.rolling(14).mean()

rs = roll_up / roll_down

rsi = 100 - (100 / (1 + rs))

plt.figure(figsize=(10,4))

plt.plot(rsi)

plt.axhline(70, linestyle="--")
plt.axhline(30, linestyle="--")

plt.title("Relative Strength Index (RSI)")

plt.savefig("figs/ch6/rsi.png", dpi=300, bbox_inches="tight")
plt.close()   # replace with plt.show()
RSI

6.12 Bollinger Bands

Bollinger Bands combine:

The idea is simple.

If prices move unusually far from their recent average, the movement may be statistically unusual.

Construction

Bollinger Bands use:

Formula

Upper band:

MAt+2σtMA_t + 2\sigma_t

Lower band:

MAt2σtMA_t - 2\sigma_t

6.13 Bollinger Bands in Python

# import yfinance as yf
# import matplotlib.pyplot as plt

# sp500 = yf.download("SPY", start="2020-01-01", auto_adust=False)

# prices = sp500["Adj Close"]

ma20 = prices.rolling(20).mean()
std20 = prices.rolling(20).std()

upper = ma20 + 2 * std20
lower = ma20 - 2 * std20

plt.figure(figsize=(10,5))

plt.plot(prices, label="Price")
plt.plot(ma20, label="20-Day MA")
plt.plot(upper, label="Upper Band")
plt.plot(lower, label="Lower Band")

plt.legend()

plt.title("Bollinger Bands")

plt.savefig("figs/ch6/BB.png", dpi=300, bbox_inches="tight")
plt.close()   # replace with plt.show()
Bollinger Bands

6.14 Indicators as Filters

All of these indicators can be interpreted as filters.

Moving Averages

Filter short-run noise.

MACD

Filters trend changes and momentum.

RSI

Filters extreme short-run movements.

Bollinger Bands

Filter deviations from recent averages relative to volatility.


6.15 Why Indicators Sometimes Fail

Trading indicators are not magic forecasting machines.

They may fail because:


6.16 Trend-Following vs Sideways Markets

Many trend-following indicators perform best when strong trends exist.

However, during sideways markets:

This phenomenon is often called:

whipsaw

6.17 Backtesting

Backtesting evaluates how a trading strategy would have performed historically.

Typical steps include:

Historical success may reflect:


6.18 Simple Backtest Example

import yfinance as yf
import pandas as pd
import numpy as np

sp500 = yf.download("SPY", start="2020-01-01", auto_adjust=False)

prices = sp500["Adj Close"]

ma50 = prices.rolling(50).mean()
ma200 = prices.rolling(200).mean()

signal = np.where(ma50 > ma200, 1, 0)

returns = prices.pct_change()

strategy_returns = signal[:-1] * returns[1:]

cumulative = (1 + strategy_returns).cumprod()

cumulative.plot(figsize=(10,4), title="Simple MA Strategy")
Backtest

6.19 Long and Short Positions

Some trading systems allow:

Long Position

Profits when prices rise.

Short Position

Profits when prices fall.



6.20 Adjusted Prices in Trading Systems

Trading systems should usually use:

Adjusted Close

rather than raw closing prices.


6.21 Overfitting in Trading Strategies

A strategy may fit historical data extremely well while performing poorly in the future.

This is called:

overfitting

6.22 Transaction Costs

Real trading involves costs such as:

These costs may substantially reduce profitability.


6.23 Gretl Example: Moving Average Indicator

Gretl can construct moving averages easily.


Step 1 — Open Financial Data

Load a price series.


Step 2 — Generate Moving Average

Menu:

Add → Moving average

Choose the desired window length.


[GRETL Screenshot Placeholder: Moving average indicator]

6.24 Gretl Example: Bollinger Bands

Menu:

Variable → Time series plot

Then add:


[GRETL Screenshot Placeholder: Bollinger Bands]

6.25 Common Mistakes


6.26 Looking Ahead

This chapter introduced technical indicators as statistical filters.

The next part of the book begins developing the core theoretical foundations of time series analysis.

We now move toward:

Key Takeaways

Concept Check

Basic

  1. What is a trading indicator?

  2. What is the purpose of using indicators in financial markets?

  3. What is a moving average crossover?


Intuition

  1. Why do traders use rules (e.g., buy/sell signals) instead of raw data?

  2. What does it mean for an indicator to “filter” a time series?

  3. Why might indicators give different signals on the same data?


Intermediate

  1. What is the difference between:

    • trend-following indicators

    • momentum indicators

  2. What does the RSI measure?

  3. What do Bollinger Bands capture?


Finance Insight

  1. Why might simple rules (like moving averages) sometimes work in financial markets?

  2. Why might these rules stop working over time?


Challenge

  1. Suppose many traders use the same indicator.


Interpretation & Practice

  1. A moving average crossover generates a Buy signal.

    • What does this suggest about recent price behavior?

    • What assumption is the trader making about the future?


  1. A trader uses a very short moving average.

    • What type of signals will they get?

    • What problem might arise?


  1. A trader uses a very long moving average.

    • What type of signals will they get?

    • What opportunities might they miss?


  1. RSI indicates an asset is “overbought.”

    • What does this mean?

    • Does it guarantee that the price will fall?


  1. Bollinger Bands widen significantly.

    • What does this indicate about the market?

    • What might a trader infer?


  1. A price repeatedly crosses above and below a moving average.

    • What kind of market condition does this suggest?

    • Why might trading strategies perform poorly here?


Behavioral Insight

  1. A trader observes a strong Buy signal and enters the market.

    Shortly after, the price reverses.

    • What type of risk is this?

    • Why do such “false signals” occur?


  1. A strategy performs well historically but fails in recent data.

    • What might explain this?

    • What does this suggest about financial markets?


Challenge

  1. Suppose a price series is purely random (no real trend).

    • What signals would trading indicators produce?

    • Why is this dangerous?


  1. A trader combines multiple indicators (MA, RSI, Bollinger Bands).


Numerical Practice

Extracting Trading Signals

Consider the following data:

tPriceMA(3)
1100
2102
3101101.0
4105102.7
5107104.3
6104105.3
7103104.7
8108105.0

Moving Average Signal

Rule:

  1. For periods t = 3 to 8:

    • Identify Buy / Sell signals.

  2. At which time does the trend appear strongest?


Crossover Strategy

Suppose we also have:

tMA(3)MA(5)
5104.3103.0
6105.3103.8
7104.7104.2
8105.0104.8

Rule:

  1. Identify crossover signals.

  2. Why might crossover signals lag behind price movements?


RSI Interpretation (Conceptual)

Suppose:

tRSI
130
225
328
440
560
675
780

Rule:


  1. Identify Buy / Sell signals.

  2. Why might RSI produce false signals in trending markets?


Challenge

  1. Suppose a price rises steadily:

    100 → 102 → 104 → 106 → 108

    • What signals would MA and RSI produce?

    • Why might both methods struggle in this case?


  1. Suppose price fluctuates randomly with no trend.

    • What problem might arise when applying trading rules?

    • What does this suggest about overtrading?


Appendix 6A — Why Exponential Averages Matter in Trading

Exponential moving averages place larger weights on recent observations.

This makes them:

However, increased responsiveness also increases sensitivity to noise.



Appendix 6B — Trend Following vs Mean Reversion

Many trading strategies rely implicitly on one of two beliefs.


Trend Following

Prices continue moving in the same direction.


Mean Reversion

Prices eventually return toward historical averages.


Financial markets may alternate between:

This helps explain why no single indicator works perfectly in all market conditions.