//+------------------------------------------------------------------+ //| Div.mqh | //| Copyright 2026, Allan NiƱal | //| https://www.allanninal.dev/mql5 | //+------------------------------------------------------------------+ //| Divergence engine, one CLOSED bar per step (no repaint), used by | //| Divergence Signal Alerts. | //| | //| Pivots on price: a pivot low at bar p has a low below each of | //| the `left` bars before it and not above any of the `right` bars | //| after it, so it is known `right` bars later (the confirmation | //| bar). Pivot highs mirror it. | //| At a new pivot low p, the previous pivot lows q (nearest first, | //| up to 3, `min_dist`..`max_dist` bars back) are tried: | //| regular bullish: low[p] < low[q] and oscillator[p] > osc[q]; | //| hidden bullish: low[p] > low[q] and oscillator[p] < osc[q]. | //| Bearish mirrors it on pivot highs. With "clean lines" on, no bar | //| between q and p may cross the straight line q-p, on price or on | //| that oscillator. The first q where at least `min_count` | //| oscillators diverge is the result; `mask` says which ones. | //| | //| Oscillators (textbook formulas, tested against tests/reference.py):| //| RSI Wilder, close | //| MACD histogram = EMA(fast) - EMA(slow) - EMA(signal) of that | //| EMAs and RMAs are seeded with the SMA of their first n values. | //+------------------------------------------------------------------+ // SPDX-License-Identifier: LicenseRef-PolyForm-Noncommercial-1.0.0 (see LICENSE) #ifndef DIV_MQH #define DIV_MQH #define DV_N 160 // ring of recent bars (max_dist + left + right must stay below it) #define DV_RSI 0 #define DV_MACD 1 #define DV_OSC 2 #define DV_PIV 4 // previous pivots remembered per side //--- EMA seeded with the SMA of the first n values (as SignalDashboard Calc.mqh) struct DVEma { int cnt; double sum; double v; }; void DVEmaInit(DVEma &s) { s.cnt=0; s.sum=0.0; s.v=EMPTY_VALUE; } double DVEmaStep(DVEma &s,const int n,const double x) { s.cnt++; if(s.cnt