Pattern Indicator Confluence System
Combine automated chart pattern detection with technical indicator readings to generate high-conviction trade signals that require both a recognized technical price pattern AND confirming indicator alignment before triggering an entry.
Pattern + Indicator Confluence System
Core Logic
This section describes the fundamental principles behind the Pattern + Indicator Confluence trading system, outlining how candlestick patterns are combined with technical indicators for signal generation.
Pattern + Indicator Confluence combines candlestick pattern signals with technical indicator confirmation, requiring both to agree before emitting a trade signal.
Logic:
- Detect hammer (bullish) and shooting star (bearish) single-candle patterns.
- Confirm with RSI: RSI < 40 confirms bullish patterns; RSI > 60 confirms bearish.
- Signal is only emitted when pattern AND indicator agree.
Limitation: This dual-confirmation approach reduces signal frequency significantly; a minimum dataset of 1000+ bars is recommended for statistical validity.
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplotsData Generation and Application
This section covers the generation of synthetic OHLCV data, which is then fed into the pattern_indicator_confluence_system function to produce trading signals. The output shows the counts of different patterns and signals detected.
def generate_data(periods: int) -> pd.DataFrame:
"""
Generate synthetic OHLCV price data using a geometric random walk.
Parameters
----------
periods : int
Number of 1-minute bars to generate.
Returns
-------
pd.DataFrame
DataFrame with columns: open, high, low, close, volume, datetime.
"""
start_date = pd.to_datetime("2024-01-01 00:00:00+00:00")
datetime_index = pd.date_range(start_date, periods=periods, freq="1min", tz="UTC")
price_data = []
last_close = 42000
for i in range(periods):
open_price = last_close + np.random.normal(0, last_close * 0.0005)
close_price = open_price + np.random.normal(0, last_close * 0.005)
body_high = max(open_price, close_price)
body_low = min(open_price, close_price)
high_price = max(body_high + abs(np.random.normal(0, last_close * 0.002)), open_price, close_price)
low_price = min(body_low - abs(np.random.normal(0, last_close * 0.002)), open_price, close_price)
if high_price < low_price:
high_price, low_price = low_price, high_price
price_data.append({
"open": max(1, int(open_price)),
"high": max(1, int(high_price)),
"low": max(1, int(low_price)),
"close": max(1, int(close_price)),
})
last_close = close_price
df = pd.DataFrame(price_data, index=datetime_index)
df.index.name = "datetime"
df["volume"] = np.random.uniform(100.0, 500.0, periods)
df["datetime"] = df.index.to_series()
return df.reset_index(drop=True)
df = generate_data(500)
display(df.head())| open | high | low | close | volume | datetime | |
|---|---|---|---|---|---|---|
| 0 | 42030 | 42101 | 41918 | 41934 | 286.774763 | 2024-01-01 00:00:00+00:00 |
| 1 | 41923 | 42234 | 41788 | 42229 | 328.672052 | 2024-01-01 00:01:00+00:00 |
| 2 | 42212 | 42278 | 41959 | 42036 | 112.342922 | 2024-01-01 00:02:00+00:00 |
| 3 | 42047 | 42150 | 41965 | 42090 | 220.524604 | 2024-01-01 00:03:00+00:00 |
| 4 | 42136 | 42142 | 41969 | 41994 | 406.657245 | 2024-01-01 00:04:00+00:00 |
Function
This section defines the pattern_indicator_confluence_system function, which implements the core logic described above. It takes OHLCV data and RSI parameters as input and returns a DataFrame with detected patterns, RSI values, and final trading signals.
def pattern_indicator_confluence_system(
df: pd.DataFrame,
rsi_period: int = 14,
rsi_bull_level: float = 40.0,
rsi_bear_level: float = 60.0,
) -> pd.DataFrame:
"""
Combine candlestick pattern detection with RSI confirmation.
Core logic
----------
1. Detect Hammer (bullish) and Shooting Star (bearish) candle patterns
using body/range and wick/body ratios.
2. Compute RSI for momentum confirmation.
3. Emit Buy (+1) only when a Hammer AND RSI < rsi_bull_level.
4. Emit Sell (-1) only when a Shooting Star AND RSI > rsi_bear_level.
Parameters
----------
df : pd.DataFrame OHLCV DataFrame.
rsi_period : int RSI calculation period.
rsi_bull_level : float RSI threshold for bullish confirmation.
rsi_bear_level : float RSI threshold for bearish confirmation.
Returns
-------
pd.DataFrame with: pattern, rsi, pattern_signal, rsi_signal, signal.
"""
df = df.copy().sort_values("datetime", ignore_index=True)
# ── Candle geometry ───────────────────────────────────────────────────────
df["body"] = (df["close"] - df["open"]).abs()
df["full_range"] = df["high"] - df["low"]
df["upper_wick"] = df["high"] - df[["open","close"]].max(axis=1)
df["lower_wick"] = df[["open","close"]].min(axis=1) - df["low"]
range_safe = df["full_range"].replace(0, np.nan)
body_safe = df["body"].replace(0, np.nan)
# ── Pattern detection ─────────────────────────────────────────────────────
hammer = (
(df["lower_wick"] >= 2 * body_safe) &
(df[["open","close"]].min(axis=1) > df["low"] + 0.7 * df["full_range"])
)
shooting_star = (
(df["upper_wick"] >= 2 * body_safe) &
(df[["open","close"]].max(axis=1) < df["low"] + 0.3 * df["full_range"])
)
df["pattern"] = "none"
df["pattern_signal"] = 0
df.loc[hammer, "pattern"] = "hammer"
df.loc[shooting_star, "pattern"] = "shooting_star"
df.loc[hammer, "pattern_signal"] = 1
df.loc[shooting_star, "pattern_signal"] = -1
# ── RSI ───────────────────────────────────────────────────────────────────
delta = df["close"].diff()
gain = delta.clip(lower=0).rolling(rsi_period).mean()
loss = (-delta.clip(upper=0)).rolling(rsi_period).mean()
df["rsi"] = 100 - 100 / (1 + gain / loss.replace(0, np.nan))
df["rsi_signal"] = np.where(df["rsi"] < rsi_bull_level, 1,
np.where(df["rsi"] > rsi_bear_level, -1, 0))
# ── Confluence signal ─────────────────────────────────────────────────────
df["signal"] = 0
df.loc[(df["pattern_signal"] == 1) & (df["rsi_signal"] == 1), "signal"] = 1
df.loc[(df["pattern_signal"] == -1) & (df["rsi_signal"] == -1), "signal"] = -1
return dfdf_signals = pattern_indicator_confluence_system(df)
print(df_signals["pattern"].value_counts())
print(df_signals["signal"].value_counts())pattern none 477 hammer 15 shooting_star 8 Name: count, dtype: int64 signal 0 493 -1 5 1 2 Name: count, dtype: int64
Explanation of Parameters
This section clarifies the significance of the parameters used in the pattern_indicator_confluence_system, particularly how the dual-condition gate and adjusted RSI thresholds influence signal generation.
- Dual-condition gate: Both
pattern_signal == Xandrsi_signal == Xmust be true simultaneously; a single condition is insufficient to trigger the final signal. - RSI thresholds of 40/60 (rather than the classic 30/70) are intentionally looser, increasing the number of qualifying RSI conditions to compensate for the rarity of confirmed candle patterns.
Visualization
This section provides the code to visualize the generated OHLCV data, overlaid with the detected buy and sell signals, and the corresponding RSI values. This plot helps in understanding the system's output visually.
buy_signals = df_signals[df_signals["signal"] == 1]
sell_signals = df_signals[df_signals["signal"] == -1]
fig = make_subplots(rows=2, cols=1, shared_xaxes=True,
subplot_titles=["Price + Confluence Signals", "RSI"],
row_heights=[0.65, 0.35])
fig.add_trace(go.Candlestick(x=df_signals["datetime"],
open=df_signals["open"], high=df_signals["high"],
low=df_signals["low"], close=df_signals["close"], name="Price"), row=1, col=1)
fig.add_trace(go.Scatter(x=buy_signals["datetime"], y=buy_signals["low"] * 0.999,
mode="markers", marker=dict(symbol="triangle-up", size=10, color="green"), name="Buy"), row=1, col=1)
fig.add_trace(go.Scatter(x=sell_signals["datetime"], y=sell_signals["high"] * 1.001,
mode="markers", marker=dict(symbol="triangle-down", size=10, color="red"), name="Sell"), row=1, col=1)
fig.add_trace(go.Scatter(x=df_signals["datetime"], y=df_signals["rsi"],
mode="lines", name="RSI", line=dict(color="purple")), row=2, col=1)
for lvl, clr in [(40, "green"), (60, "red")]:
fig.add_hline(y=lvl, line_dash="dot", line_color=clr, row=2, col=1)
fig.update_layout(title_text="Pattern + Indicator Confluence",
xaxis_rangeslider_visible=False, height=700, xaxis2_title="Datetime")
fig.show()Conclusion
This notebook demonstrates the Pattern + Indicator Confluence System, a trading strategy that combines candlestick pattern detection with RSI-based momentum confirmation.
Key Takeaways:
- Dual Confirmation Logic: The system explicitly requires both a candlestick pattern (Hammer for bullish, Shooting Star for bearish) and a confirming RSI level (below 40 for bullish, above 60 for bearish) to generate a trade signal.
- Signal Rarity: As expected with a dual-confirmation approach, the system generates a relatively low number of signals, even with synthetic data. Out of 500 generated bars, only 2 buy signals and 5 sell signals were emitted. This highlights the system's focus on high-conviction trades over frequency.
- Data Requirements: The low signal frequency reinforces the need for a large dataset (1000+ bars) to achieve statistical validity and adequately test the system's performance.
- Visualization Insights: The interactive Plotly chart visually confirms how signals are generated only when a pattern coincides with the appropriate RSI condition, providing a clear understanding of the system's mechanics. The RSI thresholds are intentionally set slightly wider (40/60) to increase the likelihood of indicator confirmation, given the strictness of the pattern detection.