Signal quality

MQL5 SMC Confluence Filter

AlgoSpecial8 November 202613 min read

A confluence filter does not create a new structure event. It decides whether an existing break deserves display, an alert or an EA signal. The filter must be computed from the same closed bar as the break, otherwise it can repaint the decision.

1. Candle confluence compares wick lengths

The reference confluence filter compares the upper wick with the lower wick. It is not a prediction; it rejects a break when the rejection wick on the wrong side dominates. The comparison is strict, so equal wicks fail.

bool BullishConfluence(const MqlRates &r[], int i)
{
   double upper = r[i].high - MathMax(r[i].open, r[i].close);
   double lower = MathMin(r[i].open, r[i].close) - r[i].low;
   return upper < lower;
}

bool BearishConfluence(const MqlRates &r[], int i)
{
   double upper = r[i].high - MathMax(r[i].open, r[i].close);
   double lower = MathMin(r[i].open, r[i].close) - r[i].low;
   return upper > lower;
}

Use the same function on the closed break bar for history and for the live decision. Do not compute a different proxy in the EA.

2. Level equality must match the structure definition

A break is stronger when the level has already been tested. But “equal” needs a tolerance. A fixed price tolerance fails across instruments; an ATR-normalised tolerance adapts to volatility.

bool NearLevel(double a, double b, double tolerance)
{
   return MathAbs(a - b) < tolerance;
}

double tolerance = atr * 0.10;

The reference uses ATR(200) and a strict < comparison. A difference exactly equal to the tolerance is not equal. The same boundary rule must appear in drawing, alerts and tests.

3. Internal/swing agreement is a context filter

A swing bullish BOS while the internal trend is bearish can still be valid, but it means the market is pulling back inside a larger move. The filter can require internal alignment, or it can display both states without rejecting the event.

  • Strict: swing event only when internal trend agrees.
  • Contextual: draw the event but label the conflict.
  • Never: silently replace the swing trend with the internal trend.

For an EA, expose both trends. A strategy can require alignment; a research tool should not hide the conflict.

4. A filter should not change the event timestamp

Keep the break event on its original bar. If the confluence filter fails, mark the event as filtered; do not move it to a later bar. Moving events makes parity tests fail and makes historical charts look better than real-time behaviour.

if(bullishBreak && !BullishConfluence(rates, bar))
{
   event.filtered = true;
   event.reason = "weak bullish confluence";
}
else if(bullishBreak)
{
   event.filtered = false;
   event.reason = "confirmed break";
}

5. Test cases

CaseExpected
Lower wick larger than upper wickBullish confluence passes
Upper wick larger than lower wickBearish confluence passes
Upper and lower wicks equalBoth comparisons fail because they are strict
Level difference exactly at toleranceRejected under the strict < rule
Internal and swing conflictDo not silently overwrite swing trend
Filter failsEvent remains on its original bar and is marked filtered

Test the filter with the Order Block Filter and the Object Parity Checker before wiring it to an EA.

FAQ

Is confluence necessary?

No. It is a design choice. It reduces event count and changes the historical distribution.

Should filtered events still alert?

Only if the alert is explicitly labelled as a filtered event. Otherwise the alert stream becomes inconsistent.

What is the safest default?

Closed-bar break, strict wick comparison and ATR(200)-relative level tolerance.

Educational content. Test thresholds on fixed fixtures.

🚀 Invite friends — Earn $5 You both get $5 credit on Go Ad · opencode.ai AI-Powered Coding Agent — Try Free Build apps, fix bugs & ship faster with opencode. Get $5 free credit when you join. × Ad · quo.com QuoPhone — $20 Visa Gift Card Free Sign up to Quo, subscribe 3 months, get a $20 Visa gift card. Atif's referral gift for you. ×