EMA Trend Filter for Ichimoku Trading

EMA Trend Filter
The EMA 100 trend filter ensures we only trade in the direction of the prevailing trend

Ichimoku Trading Series: Part 4 of 10 | ← Previous | View Full Series

Why Add an EMA Filter?

The Ichimoku Cloud alone can generate signals in choppy markets. The EMA filter ensures we only trade when a clear trend is established.

The Rule: EMA 100

We use a 100-period Exponential Moving Average as our trend identifier.

Long Trend Conditions

Current candle + at least 5 previous candles ALL trading FULLY ABOVE the EMA

“Fully above” means:

  • Open > EMA
  • Close > EMA

Short Trend Conditions

Current candle + at least 5 previous candles ALL trading FULLY BELOW the EMA

Why 5+ Candles?

From the source material:

“We need the current candle plus at least five previous candles all trading fully above the EMA curve. Meaning both the open and close of each of these candles are above the line.”

This confirms we are in a sustained trend, not just a momentary spike.

Code Implementation

def MovingAverageSignal(df: pd.DataFrame, back_candles: int = 5) -> pd.DataFrame:
    """
    Add a single-column EMA trend signal to the DataFrame.

    Rules (evaluated per bar, using *only* current/past data):
      +1 (uptrend):   For the window [t-back_candles .. t], EVERY bar has
                      Open > EMA and Close > EMA.
      -1 (downtrend): For the same window, EVERY bar has
                      Open < EMA and Close < EMA.
       0 otherwise.
    """
    out = df.copy()
    
    # Window size: current bar + back_candles bars behind it
    w = int(back_candles) + 1
    
    # Booleans per-bar relative to EMA
    above = (out["Open"] > out["EMA"]) & (out["Close"] > out["EMA"])
    below = (out["Open"] < out["EMA"]) & (out["Close"] < out["EMA"])
    
    # "All true in the last w bars" via rolling sum == w
    above_all = (above.rolling(w, min_periods=w).sum() == w)
    below_all = (below.rolling(w, min_periods=w).sum() == w)
    
    # Single signal column
    signal = np.where(above_all, 1, np.where(below_all, -1, 0)).astype(int)
    out["EMA_signal"] = signal
    
    return out

# Usage: require 7 candles above/below EMA
df = MovingAverageSignal(df, back_candles=7)

Tuning the Parameter

Setting Effect
back_candles=5 More signals, less trend confirmation
back_candles=7 Balanced (recommended)
back_candles=10 Fewer signals, stronger trend confirmation

Coming Up Next: In Part 5, we will define our exact entry conditions — when the EMA trend is confirmed AND the Ichimoku cloud gives us a retracement signal. Continue to Part 5 →

CategoriesAI

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.