Python TA-Lib Engulfing Pattern Error — Need Help!

Hey @Imranali sir :waving_hand:
Advanced Algo Trading Series | Episode 2 I’m working on a stock data scanner using Python, and TA-Lib indicators.

While calculating the Engulfing Pattern (CDLENGULFING), I’m getting unexpected behaviour and want to confirm if others have faced this issue.

Here’s what I’m doing:

data["ENGULFING"] = talib.CDLENGULFING(
    data["Open"], data["High"], data["Low"], data["Close"]
)

But the output seems inconsistent — sometimes it doesn’t detect the engulfing candle even when it’s clearly visible on the chart.
I want to understand:

  • Is TA-Lib’s definition of Engulfing Pattern stricter (based only on candle body, not wicks)?
  • Does it require a specific trend before the pattern forms?
  • How exactly does TA-Lib internally calculate CDLENGULFING?

If anyone has faced this or has verified TA-Lib’s engulfing logic (maybe compared with Trading View or excel calculations), please share your experience or fix :folded_hands:

Thanks in advance!
#Python #AlgoTrading #TA-Lib #EngulfingPattern #TechnicalAnalysis

Datetime Open High Low Close Volume rsi ENGULFING candle
2025-10-13 15:00:00 25250.30 25251.40 25215.25 25220.45 0 49.95 -100
2025-10-13 14:00:00 25184.85 25222.40 25183.85 25207.50 0 48.02 100
2025-10-13 13:45:00 25198.80 25217.00 25176.65 25185.65 0 40.14 -100
2025-10-13 11:45:00 25179.20 25198.95 25175.20 25198.70 0 40.68 100
2025-10-10 14:30:00 25310.00 25310.95 25297.00 25305.55 0 64.29 -100
2025-10-10 13:45:00 25318.05 25324.60 25303.50 25304.95 0 64.74 -100
2025-10-10 12:30:00 25282.20 25305.95 25275.00 25303.75 0 68.72 100
2025-10-10 11:45:00 25284.80 25290.65 25274.80 25277.65 0 65.07 -100
2025-10-10 11:15:00 25310.35 25315.20 25274.95 25282.55 0 66.79 -100
2025-10-10 10:15:00 25262.45 25299.05 25262.20 25276.20 0 74.31 80

Hi @radhey ,

If the TA-Lib Engulfing pattern doesn’t align with expectations, we can define our own custom formula to detect the Engulfing pattern.
Use the function below and pass your DataFrame as an argument.

Do try this code, and let us know if it works for you.

def detect_engulfing(df):
    df = df.copy()
    df['prev_open'] = df['open'].shift(1)
    df['prev_close'] = df['close'].shift(1)

    # Bullish engulfing
    bullish = (
        (df['prev_close'] < df['prev_open']) &
        (df['close'] > df['open']) &
        (df['close'] >= df['prev_open']) &
        (df['open'] <= df['prev_close'])
    )

    # Bearish engulfing
    bearish = (
        (df['prev_close'] > df['prev_open']) &
        (df['close'] < df['open']) &
        (df['open'] >= df['prev_close']) &
        (df['close'] <= df['prev_open'])
    )

    df['engulfing_type'] = None
    df.loc[bullish, 'engulfing_type'] = 'Bullish'
    df.loc[bearish, 'engulfing_type'] = 'Bearish'

    return df

# Usage
df = detect_engulfing(df)