Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

Engulfing Pattern Trading with Python

Engulfing Pattern Trading

The engulfing pattern trading is a popular candlestick pattern used by traders to signal potential reversals in price trends. This pattern consists of two candlesticks, where the body of the second candle completely engulfs the body of the first candle.

The engulfing pattern can be either bullish or bearish, depending on the direction of the price trend prior to the pattern formation. A bullish engulfing pattern occurs after a downtrend and indicates a potential reversal to an uptrend. On the other hand, a bearish engulfing pattern occurs after an uptrend and indicates a potential reversal to a downtrend.

To identify a bullish engulfing pattern, the first candlestick should have a small body with a long lower wick, indicating that bears had control of the market for most of the day but lost control towards the end. The second candlestick should have a large body that completely engulfs the first candlestick’s body, indicating that bulls have taken control of the market. The opposite is true for a bearish engulfing pattern.

The engulfing pattern is considered a strong reversal signal when it occurs after a significant trend. Traders often use additional technical indicators, such as volume and support/resistance levels, to confirm the pattern’s validity. If confirmed, traders may enter a trade in the direction of the engulfing pattern and place stop-loss orders below the low of the pattern’s bullish candlestick or above the high of the pattern’s bearish candlestick.

It’s worth noting that, like all technical indicators, the engulfing pattern is not foolproof and should not be used as the sole basis for trading decisions. It’s important to consider other factors, such as fundamental analysis and market sentiment, before making any trades.

An engulfing pattern is a useful tool for traders to identify potential reversals in price trends. It’s easy to recognize and can be a strong signal when used in conjunction with other technical indicators. However, traders should always use caution and consider all factors before making any trading decisions.

Python Implementation

Now let’s see how we can implement a simple Engulfing Pattern in Python.

Our strategy will be very simple so that we can understand the core concept behind Engulfing Pattern Strategy and see how we can utilize Python language to help us. The strategy will be as follows;

  • SMA(20-50) – Simple Moving Average(20-50): We will use SMA to identify the general market trend direction so that we can look for the reversal patterns
  • Bullish Engulfing Candle:
    • If the previous candle is Red
    • If the current candle is Green
    • If the body of the Green candle is greater than the Red candle
    • If the Green High is greater than the Red High

for Bearish Engulfing Candle we will be looking for the opposite setup. In addition to that, we will also add two Simple Moving Averages 20 and 50 so that we can identify the current market trend easily. The rule for that is simple: If 20 SMA is above 50 SMA then we will consider this market trend as Bullish and if vice versa then Bearish. Let’s see the code and the resulting graph:

ticker = "AMZN"
interval = "1d"

stock = yf.Ticker(ticker)

end_date = datetime.now().strftime('%Y-%m-%d')
stock_history = stock.history(start='2019-01-01',end=end_date)

stock_history["BodyDiff"] = abs(stock_history["Open"] - stock_history["Close"])
stock_history["CandleStickType"] = np.where(stock_history["Open"] < stock_history["Close"], "Green", "Red")

stock_history["RSI"] = stock_history.ta.rsi()
stock_history["SMA_20"] = stock_history.ta.sma(length=20)
stock_history["SMA_50"] = stock_history.ta.sma(length=50)


def isEngulfing(df):
    df_len = len(df)
    signal = [0] * df_len
    
    body_diff = df["BodyDiff"]
    high_price = df["High"]
    low_price = df["Low"]
    close_price = df["Close"]
    candle_stick_type = df["CandleStickType"]
    
    rsi = stock_history["RSI"]
    sma_20 = stock_history["SMA_20"]
    sma_50 = stock_history["SMA_50"]
    
    for row in range(1, df_len):
        if body_diff[row] > body_diff[row-1] and candle_stick_type[row-1] == "Red" \
                                and candle_stick_type[row] == "Green" and high_price[row] > high_price[row-1] \
                                and sma_50[row] > sma_20[row] and sma_20[row] > close_price[row]:
            signal[row] = "BUY"
        elif body_diff[row] > body_diff[row-1] and candle_stick_type[row-1] == "Green" \
                                and candle_stick_type[row] == "Red" and low_price[row-1] < low_price[row] \
                                and sma_20[row] > sma_50[row] and sma_20[row] < close_price[row]:
            signal[row] = "SELL"
    
    return signal

stock_history["TradeAlert"] = isEngulfing(stock_history)


buy_trades = stock_history[stock_history["TradeAlert"] == "BUY"]
sell_trades = stock_history[stock_history["TradeAlert"] == "SELL"]

fig = go.Figure(data=[go.Candlestick(
                x=stock_history.index,
                open=stock_history['Open'],
                high=stock_history['High'],
                low=stock_history['Low'],
                close=stock_history['Close'])
                     ])

fig.add_trace(go.Scatter(
        x=buy_trades.index,
        y=buy_trades.Close,
        mode="markers",
        customdata=trades,
        marker_symbol="diamond-dot",
        marker_size=13,
        marker_line_width=2,
        marker_color="rgba(255,165,0,1)",
        hovertemplate="Entry Time: %{x}<br>" +\
                    "Entry Price: %{y:.2f}"
        ))

fig.add_trace(go.Scatter(
        x=sell_trades.index,
        y=sell_trades.Close,
        mode="markers",
        customdata=trades,
        marker_symbol="diamond-dot",
        marker_size=13,
        marker_line_width=2,
        marker_color="rgba(255,255,0,1)",
        hovertemplate="Entry Time: %{x}<br>" +\
                    "Entry Price: %{y:.2f}"
        ))

fig.update_layout(xaxis_rangeslider_visible=False)
fig.show()

Simple right?

Of course, we can add a few more features such as Holding a position unless we see a reverse signal or add one more technical indicator to filter some of those losing trades, etc. But for now, we will stop here for this post and we will dive into more advanced strategies and Python implementations in the future