Why Your MT4 Indicator Repeats the Same Alert
A trading signal can be correct while its alert system is still broken. That is why an MT4 indicator may draw one valid arrow and send the same notification ten times.
The cause is usually not the entry rule itself. It is missing event identity.
MT4 recalculates indicators whenever new price data arrives. Several ticks can reach the terminal during the same candle. If the alert call sits inside the signal condition, every one of those calculations can repeat the same side effect.
The fix is to separate three jobs: detect the setup, decide whether this is a new event, then commit the alert as handled.
THE REPEATED-ALERT BUG IS A STATE BUG
Imagine a rule that checks whether price closed above a 20-period moving average. The rule becomes true on bar 1, the most recently closed candle.
That truth does not disappear when the next tick arrives. Bar 1 still has the same close and the same moving-average value. So the indicator sees true again. If the code says “condition is true, therefore alert,” it sends another message.
A local Boolean such as alerted = true often looks like a fix. It is not enough. The variable may reset when the indicator reloads, the timeframe changes, an input changes, or the terminal restarts. It also cannot distinguish a new buy setup from an old sell setup.
The indicator needs an identity for the event it has already handled.
STEP 1: DEFINE THE CANDLE STATE
First decide whether the signal is allowed to trigger intrabar or only after candle close.
For a closed-bar indicator, read bar 1 consistently. Do not mix the current bar’s price with the previous bar’s moving-average value. That creates a rule whose meaning changes during the candle.
For an intrabar indicator, accept that the condition may appear and disappear before the candle closes. The alert policy must then say whether the first appearance counts, whether the signal can reset, and whether a second appearance in the same candle is a new event.
This is not a small implementation detail. It is part of the trading rule.
The MQL4 event model explains when indicator calculation runs and why the same bar can be processed repeatedly: https://docs.mql4.com/basis/function/events
STEP 2: BUILD A SETUP IDENTITY
A useful setup identity normally includes:
Symbol
Timeframe
Signal bar opening time
Direction
Rule version or setup type
For example, EURUSD, M15, 2026–08–19 12:30, BUY, rule-v3 is one event.
Every tick that produces the same identity refers to the same setup. It must not create another alert.
The bar index alone is a weak identity. Index 1 always means “the previous bar,” but the candle represented by index 1 moves when a new bar opens. Use the bar’s time, not its current array position.
Time alone may also be too weak when one indicator can issue both buy and sell events or several setup types on the same candle. Include the parts that make two events meaningfully different.
STEP 3: COMPARE BEFORE YOU SEND
Detection should return a candidate event. Delivery should compare that candidate with the last handled identity.
The flow is simple:
Detect the signal on the agreed candle.
Build its setup identity.
If the identity equals the last handled identity, stop.
Send the alert.
Store the identity as handled.
This turns notification delivery into a one-shot state transition. The indicator moves from “candidate exists” to “candidate delivered.” Repeated calculations stay in the delivered state.
One detail matters here. Store the identity only after the alert call succeeds according to the delivery rule you chose. If the code marks the event first and then fails before delivery, the alert can be lost. If delivery has several outputs, such as popup, push and email, define whether success means all outputs or at least one.
MAKE RELOAD BEHAVIOR EXPLICIT
There is no universal answer for what should happen after a reload.
One valid policy is session-only suppression. A reload clears memory, so the most recent historical setup can alert again.
Another policy is persistent suppression. The indicator stores the last handled identity and restores it after reload.
A third policy is live-only delivery. On initialization, the indicator records the newest eligible identity without sending it. Alerts begin only when a later candle creates a new event.
Choose one. Then test it.
Persistent state also needs a namespace. Two chart instances should not overwrite each other unless they intentionally share alert state. A key based on indicator name, symbol, timeframe and instance identifier avoids that collision.
DO NOT MIX DRAWING WITH DELIVERY
An arrow buffer and an alert ledger solve different problems.
The arrow answers: did this candle meet the rule?
The ledger answers: was the corresponding event already delivered?
Rebuilding historical arrows is normal when an indicator recalculates. Re-sending historical notifications is usually not. If the same loop controls both, a refresh can produce a flood of old alerts even though the chart looks correct.
Keep signal calculation deterministic. Keep notification state separate.
THREE ACCEPTANCE CASES CATCH MOST FAILURES
A repair is much easier to verify when the expected behavior is written as three exact cases.
Case 1: one valid closed-bar setup produces one arrow and one alert.
Case 2: every later tick on the same candle produces no additional alert.
Case 3: reload behavior matches the chosen policy, with no unexpected historical flood and no missing next live setup.
Add a negative screenshot or fixture where one condition is false. That confirms the indicator is not merely suppressing everything.
If multiple alert channels exist, record each channel separately. A popup passing does not prove that push delivery passed.
THE SMALL DESIGN RULE
Signal truth is not a notification side effect.
A condition can remain true for hundreds of calculations. An alert should happen only when the event moves from unseen to handled.
Get Arnold Holm | StratCoreAlpha’s stories in your inbox
Join Medium for free to get updates from this writer.
Once that boundary is explicit, the code becomes easier to reason about. The buyer can describe expected behavior with screenshots. The developer can reproduce it with fixed candles. And the repair has a clear finish line: one valid event, one alert, no duplicates, and a stated reload policy.A trading signal can be correct while its alert system is still broken. That is why an MT4 indicator may draw one valid arrow and send the same notification ten times.
The cause is usually not the entry rule itself. It is missing event identity.
MT4 recalculates indicators whenever new price data arrives. Several ticks can reach the terminal during the same candle. If the alert call sits inside the signal condition, every one of those calculations can repeat the same side effect.
The fix is to separate three jobs: detect the setup, decide whether this is a new event, then commit the alert as handled.
THE REPEATED-ALERT BUG IS A STATE BUG
Imagine a rule that checks whether price closed above a 20-period moving average. The rule becomes true on bar 1, the most recently closed candle.
That truth does not disappear when the next tick arrives. Bar 1 still has the same close and the same moving-average value. So the indicator sees true again. If the code says “condition is true, therefore alert,” it sends another message.
A local Boolean such as alerted = true often looks like a fix. It is not enough. The variable may reset when the indicator reloads, the timeframe changes, an input changes, or the terminal restarts. It also cannot distinguish a new buy setup from an old sell setup.
The indicator needs an identity for the event it has already handled.
STEP 1: DEFINE THE CANDLE STATE
First decide whether the signal is allowed to trigger intrabar or only after candle close.
For a closed-bar indicator, read bar 1 consistently. Do not mix the current bar’s price with the previous bar’s moving-average value. That creates a rule whose meaning changes during the candle.
For an intrabar indicator, accept that the condition may appear and disappear before the candle closes. The alert policy must then say whether the first appearance counts, whether the signal can reset, and whether a second appearance in the same candle is a new event.
This is not a small implementation detail. It is part of the trading rule.
The MQL4 event model explains when indicator calculation runs and why the same bar can be processed repeatedly: https://docs.mql4.com/basis/function/events
STEP 2: BUILD A SETUP IDENTITY
A useful setup identity normally includes:
Symbol
Timeframe
Signal bar opening time
Direction
Rule version or setup type
For example, EURUSD, M15, 2026–08–19 12:30, BUY, rule-v3 is one event.
Every tick that produces the same identity refers to the same setup. It must not create another alert.
The bar index alone is a weak identity. Index 1 always means “the previous bar,” but the candle represented by index 1 moves when a new bar opens. Use the bar’s time, not its current array position.
Time alone may also be too weak when one indicator can issue both buy and sell events or several setup types on the same candle. Include the parts that make two events meaningfully different.
STEP 3: COMPARE BEFORE YOU SEND
Detection should return a candidate event. Delivery should compare that candidate with the last handled identity.
The flow is simple:
Detect the signal on the agreed candle.
Build its setup identity.
If the identity equals the last handled identity, stop.
Send the alert.
Store the identity as handled.
This turns notification delivery into a one-shot state transition. The indicator moves from “candidate exists” to “candidate delivered.” Repeated calculations stay in the delivered state.
One detail matters here. Store the identity only after the alert call succeeds according to the delivery rule you chose. If the code marks the event first and then fails before delivery, the alert can be lost. If delivery has several outputs, such as popup, push and email, define whether success means all outputs or at least one.
MAKE RELOAD BEHAVIOR EXPLICIT
There is no universal answer for what should happen after a reload.
One valid policy is session-only suppression. A reload clears memory, so the most recent historical setup can alert again.
Another policy is persistent suppression. The indicator stores the last handled identity and restores it after reload.
A third policy is live-only delivery. On initialization, the indicator records the newest eligible identity without sending it. Alerts begin only when a later candle creates a new event.
Choose one. Then test it.
Persistent state also needs a namespace. Two chart instances should not overwrite each other unless they intentionally share alert state. A key based on indicator name, symbol, timeframe and instance identifier avoids that collision.
DO NOT MIX DRAWING WITH DELIVERY
An arrow buffer and an alert ledger solve different problems.
The arrow answers: did this candle meet the rule?
The ledger answers: was the corresponding event already delivered?
Rebuilding historical arrows is normal when an indicator recalculates. Re-sending historical notifications is usually not. If the same loop controls both, a refresh can produce a flood of old alerts even though the chart looks correct.
Keep signal calculation deterministic. Keep notification state separate.
THREE ACCEPTANCE CASES CATCH MOST FAILURES
A repair is much easier to verify when the expected behavior is written as three exact cases.
Case 1: one valid closed-bar setup produces one arrow and one alert.
Case 2: every later tick on the same candle produces no additional alert.
Case 3: reload behavior matches the chosen policy, with no unexpected historical flood and no missing next live setup.
Add a negative screenshot or fixture where one condition is false. That confirms the indicator is not merely suppressing everything.
If multiple alert channels exist, record each channel separately. A popup passing does not prove that push delivery passed.
THE SMALL DESIGN RULE
Signal truth is not a notification side effect.
A condition can remain true for hundreds of calculations. An alert should happen only when the event moves from unseen to handled.
Once that boundary is explicit, the code becomes easier to reason about. The buyer can describe expected behavior with screenshots. The developer can reproduce it with fixed candles. And the repair has a clear finish line: one valid event, one alert, no duplicates, and a stated reload policy.Why Your MT4 Indicator Repeats the Same Alert








