148 lines
6.8 KiB
Markdown
148 lines
6.8 KiB
Markdown
# SMC Pullback
|
|
|
|
**Swing high / low detection by the pullback rule — MetaTrader 5 indicator**
|
|
|
|
Marks swing highs and lows using the pullback definition instead of the usual
|
|
3-candle pattern. A high is confirmed only when price trades back through the low
|
|
of the candle that made it, so every marked point is an actual rejection rather
|
|
than a shape. Closed bars only, no repainting.
|
|
|
|
📦 **MQL5 Code Base:** https://www.mql5.com/en/code/76451
|
|
|
|
---
|
|
|
|
## What is in this folder
|
|
|
|
```text
|
|
Indicators/Code Base/
|
|
│
|
|
└── SMC Pullback v1.0.mq5 the indicator - one self-contained file
|
|
|
|
```
|
|
|
|
No includes, no dependencies. The whole indicator is one `.mq5`.
|
|
|
|
`make_figures.py` re-implements the detector in Python and draws the figures from
|
|
its output, so the diagrams cannot drift away from the MQL5 code. It doubles as an
|
|
independent check on the algorithm.
|
|
|
|
## Installing
|
|
|
|
1. Copy `SMC Pullback v1.0.mq5` into `MQL5/Indicators/Code Base` (or any subfolder of it).
|
|
2. Open it in MetaEditor and compile (F7).
|
|
3. Drag it onto a chart from the Navigator.
|
|
|
|
Works on any symbol and any timeframe. It needs no other indicator and no market
|
|
data beyond the chart's own history.
|
|
|
|
---
|
|
|
|
## The rule
|
|
|
|
The detector never looks for both sides at once. It searches for **one side at a
|
|
time** and holds three values:
|
|
|
|
- **Direction** — which side it is currently looking for.
|
|
- **Tracked extreme** — the highest high (or lowest low) of the current leg.
|
|
- **Reference level** — the *opposite* edge of the candle that made that extreme.
|
|
|
|
The reference is the key. A candle that sets a new highest high also supplies the
|
|
level that will later confirm it: **its own low**. When price trades back through
|
|
that low, the high becomes a swing and the search flips to the low side, seeded
|
|
from the candle that caused the break. Looking for a low is the mirror image.
|
|
|
|
Because confirming one side always flips the search to the other, **highs and lows
|
|
alternate automatically** — there is no rule enforcing it and no comparison against
|
|
earlier swings.
|
|
|
|
On each closed candle two independent questions are asked: *did it make a new
|
|
extreme?* and *did it break the reference?* That gives four cases per direction:
|
|
|
|
| # | Current trend | Current candle | Action 1 | Action 2 |
|
|
|---|---|---|---|---|
|
|
| 1 | Looking for a **HIGH** | **Inside bar** — no new high, reference low intact | nothing | nothing |
|
|
| 2 | Looking for a **HIGH** | **New high**, reference low intact | tracked high = this candle's high | reference low = this candle's low |
|
|
| 3 | Looking for a **HIGH** | **Break** — no new high, trades below the reference low | confirm the tracked high as a **swing high** | flip to LOW, seeded from this candle |
|
|
| 4 | Looking for a **HIGH** | **Outside bar** — new high *and* breaks the reference low | confirm **this candle's own high** as a swing high | flip to LOW, seeded from this candle |
|
|
| 5 | Looking for a **LOW** | **Inside bar** — no new low, reference high intact | nothing | nothing |
|
|
| 6 | Looking for a **LOW** | **New low**, reference high intact | tracked low = this candle's low | reference high = this candle's high |
|
|
| 7 | Looking for a **LOW** | **Break** — no new low, trades above the reference high | confirm the tracked low as a **swing low** | flip to HIGH, seeded from this candle |
|
|
| 8 | Looking for a **LOW** | **Outside bar** — new low *and* breaks the reference high | confirm **this candle's own low** as a swing low | flip to HIGH, seeded from this candle |
|
|
|
|
Rows 1–4 and 5–8 are exact mirrors, which is why the engine is only a few dozen lines.
|
|
|
|
Rows 4 and 8 are the interesting ones. An **outside bar** can extend the leg and
|
|
break the reference in the same candle, and the two rules contradict each other.
|
|
The resolution is to let the candle be the swing itself: its own extreme is
|
|
confirmed, and the same candle then opens the opposite leg. On the chart that
|
|
shows up as a marker above *and* below one bar, with a vertical leg between them.
|
|
|
|
See [here](https://www.mql5.com/en/code/76451) for the full explanation with figures.
|
|
|
|
## No repainting
|
|
|
|
The tracked extreme is provisional and is **never drawn**. A swing reaches the
|
|
chart only on the candle that confirms it, and once drawn it is never moved,
|
|
recoloured or removed. Only closed bars are evaluated — the forming bar is ignored.
|
|
|
|
The trade-off, stated plainly: **confirmation lag**. The newest swing appears only
|
|
after the break that validates it. A marker that appeared the instant a new high
|
|
printed would have to move later, which is exactly what repainting means.
|
|
|
|
---
|
|
|
|
## Inputs
|
|
|
|
| Group | Input | Default | Notes |
|
|
|---|---|---|---|
|
|
| Detection | Start by looking for | swing high | Affects only the oldest bars; after the first confirmation the direction follows the breaks. |
|
|
| Detection | Break confirmed by | Wick | `Wick` is the literal rule. `Close` requires a close through the reference — fewer, larger swings. |
|
|
| Display | Draw the swing markers | true | Buffers stay filled either way, so `iCustom` is unaffected. |
|
|
| Display | Arrow code high / low | 217 / 218 | Wingdings codes. |
|
|
| Display | Arrow distance | 10 | Pixels between the candle and the arrow. |
|
|
| Display | Draw the legs | true | The dotted zig-zag between consecutive swings. |
|
|
| Display | Leg colour / style / width | silver, dotted, 1 | |
|
|
| Alerts | Popup / Push | false | Fire once per swing, on live updates only. |
|
|
|
|
**Choosing a break mode:** start with `Wick`. On M1–M15, or on wick-heavy symbols
|
|
such as gold and index CFDs, switch to `Close` — it removes most swings caused by a
|
|
single spike without changing the logic anywhere else. There is no period or
|
|
sensitivity to tune; a higher timeframe is the other way to get larger structure.
|
|
|
|
## Using it from an EA
|
|
|
|
Two buffers, non-empty only on confirmed swings (empty value `0.0`):
|
|
|
|
| Buffer | Contents |
|
|
|---|---|
|
|
| `0` | price of a confirmed swing **high** |
|
|
| `1` | price of a confirmed swing **low** |
|
|
|
|
```mql5
|
|
int h = iCustom(_Symbol, _Period, "SMC_Pullback");
|
|
double buf[];
|
|
CopyBuffer(h, 0, 0, 100, buf); // swing highs
|
|
```
|
|
|
|
The detection engine is a single self-contained class, `CPullbackDetector`, with no
|
|
buffer or chart dependencies — it takes the price arrays and reports confirmed
|
|
swings. Copy it straight into an EA if you would rather not go through `iCustom`.
|
|
|
|
## Scope
|
|
|
|
This indicator stops at the swing points. It does **not** label HH/HL/LH/LL and it
|
|
does not derive BOS, CHoCH, IDM, order blocks or liquidity levels. Those are
|
|
separate steps that all need a reliable set of swings first — which is what this
|
|
provides.
|
|
|
|
---
|
|
|
|
## Credits and use
|
|
|
|
The pullback definition of a swing comes from the **Trading Hub 3.0** methodology.
|
|
This is an independent MQL5 implementation of that rule; it shares no code with any
|
|
other project.
|
|
|
|
Copyright 2026, **Sandro Begashvili**
|
|
|
|
Published free on the MQL5 Code Base: https://www.mql5.com/en/code/76451
|