2026-09-14 06:08:33 +00:00 | | | # ACD
|
| | |
|
2026-09-14 11:09:20 +05:00 | | | A live market activity gauge in native MQL5: how busy the quote stream is
|
| | | right now, compared with what is normal for this time of day, updated on
|
| | | every quote.
|
| | |
|
| | | Companion code for the MQL5 article: https://www.mql5.com/en/articles/24742
|
| | |
|
| | | ## What it does
|
| | |
|
| | | Tick volume answers "how many quotes arrived in this bar", which is a
|
| | | different question from "is the market unusually busy right now". Most of its
|
| | | variation is the clock: on EURUSD the quietest half hour of the day waits
|
| | | roughly forty-seven times longer between quotes than the busiest one, every
|
| | | day. It is also complete only when the bar closes, and two bars with the same
|
| | | count look identical whether their quotes arrived evenly or in one burst.
|
| | |
|
| | | The library works on the waits between consecutive quote changes instead.
|
| | | `CAcdEvents` turns the tick stream into events, folding ticks that share a
|
| | | millisecond and marking waits longer than five minutes as a closed market.
|
| | | On a retail feed these are quote changes, not trades, and nothing here
|
| | | pretends otherwise. `CAcdDiurnal` learns the time-of-day profile on the
|
| | | training period only, files each wait under the time it started, interpolates
|
| | | between half-hour bins, and scales the profile so an adjusted wait of 1 means
|
| | | "exactly as long as usual for this hour".
|
| | |
|
| | | What remains still clusters, and `CAcdModel` fits the autoregressive
|
| | | conditional duration model of Engle and Russell (1998) to it by maximum
|
| | | likelihood, with exponential or Weibull surprises and omega pinned by mean
|
| | | targeting. Every fit is scored on a held-out period against a rhythm-only
|
| | | baseline that gets its own best Weibull shape, so the recursion receives no
|
| | | credit for dispersion it did not explain. On six symbols the clustering beat
|
| | | that baseline out of sample on every one, and on EURUSD it removed 99.3% of
|
| | | the Ljung-Box statistic of the adjusted waits.
|
| | |
|
| | | `CAcdState` runs the fitted model live in constant time per quote, through
|
| | | the same one-step update and the same stored profile as the fit, so a state
|
| | | replayed over the fitting history reproduces the model's expectations
|
| | | exactly. Its main reading is the activity ratio: 1 at the normal pace for the
|
| | | hour, 2 when quotes are expected twice as often, 0.5 when half as often. A
|
| | | silence ratio covers the gap between quotes, when the expectation cannot move.
|
| | |
|
| | | `ACD_Evidence.mq5` asks whether any of this helps forecast the volatility of
|
| | | the next few minutes, with a ladder of regressions scored on a later test
|
| | | period, at the bar close and at a varying second inside each bar. Mid-bar,
|
| | | every live measure beats tick volume from finished bars on all six symbols.
|
| | | Most of that gain, however, is freshness rather than activity: live realised
|
| | | volatility alone, measured up to the same second, beats the ACD gauge alone
|
| | | everywhere. Activity still adds something prices do not. With live
|
| | | volatility already in the forecast, adding the gauge improved it on all six
|
| | | symbols at both horizons, by a small margin that is largest on the indices.
|
| | | Whether the gauge or plain rhythm-adjusted rolling counts add more depends on
|
| | | the market and the horizon: the gauge at five minutes and on the indices,
|
| | | the counts at one minute on currencies and gold.
|
| | |
|
| | | ## Layout
|
| | |
|
| | | ```
|
| | | Include/ACD/AcdTypes.mqh parameters, fit report, buffer map, the one-step update and log-density
|
| | | Include/ACD/AcdEvents.mqh tick stream to events: same-millisecond folding, session gaps, daily loading
|
| | | Include/ACD/AcdDiurnal.mqh time-of-day profile with interpolation and unit-mean scaling
|
| | | Include/ACD/AcdModel.mqh maximum-likelihood fit, rhythm-only baseline, residual diagnostics
|
| | | Include/ACD/AcdState.mqh live constant-time state: activity ratio, surprise, expected wait, silence
|
| | | Scripts/ACD/ACD_Calibrate.mq5 fits one symbol: feed check, rhythm, both fits, residuals, live parameters
|
| | | Scripts/ACD/ACD_Evidence.mq5 multi-symbol volatility-forecast ladder, at the bar close and mid-bar
|
| | | Indicators/ACD/ACD_Activity.mq5 live activity gauge with a tick volume contrast and buffers for EAs
|
| | | ```
|
| | |
|
| | | Run `ACD_Calibrate.mq5` first, on the symbol you care about with thirty days
|
| | | of quotes. It stops if the feed looks timer-driven, since a clustering model
|
| | | fitted to a clock describes the broker's server rather than the market. Check
|
| | | that the clustering gain on the test period is positive, then paste the
|
| | | printed alpha and beta into `ACD_Activity.mq5`. The indicator learns its own
|
| | | rhythm from the trading days before the plot. Recalibrate about once a month
|
| | | and whenever you change symbol or broker.
|
| | |
|
| | | An Expert Advisor should read buffer 3, the plain activity ratio, through
|
| | | `iCustom`. Buffer 4 holds the expected wait in milliseconds for the next
|
| | | quote on the forming bar; divide the time since the last tick by it for a
|
| | | silence ratio of your own, since timer events do not reach an indicator
|
| | | created through `iCustom`.
|
| | |
|
| | | ## Disclaimer
|
| | |
|
| | | Educational code. The gauge measures market conditions and says nothing about
|
| | | direction, and nothing here demonstrates a trading edge. The evidence covers
|
| | | thirty days of quotes from one broker, the gains from activity over live
|
| | | volatility are small, and the ranking between the gauge and simpler counts
|
| | | shifted with horizon and asset class within that window. Test on your own
|
| | | account and broker feed before relying on any of it.
|