Skip to content
Level 5 · Real-Time AmiBroker UserProjectPart 25 · page 3 of 350 min Professional edition Live feed
50Minutes
15AFL functions
9Sources
Professional + live feedRequires

This page needs the Professional edition and a real-time data feed. Every gated part of this course ships a Level A path that uses Bar Replay and historical data instead — look for it below.

AFL functions taught here15

Project: Real-Time Breakout Alert

Everything in this part has been building towards one deliverable: an alert you would actually be willing to leave running. That means a formula whose behaviour you have counted, not estimated, and a testing procedure you can repeat on a Sunday afternoon with the markets shut and no subscription running.

The subject is a breakout — price exceeding the highest high of a recent window — because it is the rule most people write first and the rule that misbehaves most instructively. It breaks in every way this part has described: it is a state if you write it carelessly, it flickers inside a forming bar, it repeats all afternoon once the level is cleared, and it fires at 04:12 on a quote nobody would have traded.

A specification you cannot fail is not a specification. Here is the one this formula is built to meet, written so that each clause is checkable:

  1. On a chosen symbol and interval, raise an alert on the first completed bar whose high exceeds the highest high of the previous N bars by at least a volatility-scaled margin.
  2. The current bar must never contribute to the level it is being measured against.
  3. Alert at most once per session, regardless of how many times the level is cleared, lost and cleared again.
  4. Do not alert outside a configurable session window.
  5. Produce no alert at all while the level cannot be computed — during the warm-up bars, or wherever data is missing.
  6. Label alerts raised during Bar Replay so a practice run cannot be mistaken for a real one.
  7. Place no orders, and provide no mechanism that could.

Clauses 1, 3 and 5 are where the previous two pages get paid for. Clause 6 exists because the first thing anyone does with a replay-driven alert is confuse it with a live one.

The level uses High, not Close. A breakout is defined by price trading through a level, and the high is the record of that. Using the close would change the rule into “finished the bar above the level”, which is a different and slower rule. Both are defensible; the point is to know which one you wrote.

The level is shifted back one bar. Ref( HHV( High, N ), -1 ) means the breakout bar’s own high cannot raise the level it is trying to exceed. Without the shift, High > HHV(High, N) is almost never true, and beginners conclude their formula is broken when it is merely self-referential.

The margin is volatility-scaled. A fixed buffer of two cents means one thing on a four-dollar share and nothing at all on a four-hundred-dollar one. Using a fraction of ATR() makes the same parameter mean roughly the same thing across instruments. It does not make the rule better — it makes the parameter portable, which is a smaller and more honest claim.

The session filter uses TimeNum(). This is the one clause that fails silently on somebody else’s machine, because TimeNum() returns the start or the end time of the interval depending on a Preferences setting. The formula documents that dependency in its header rather than pretending it does not exist.

The reset is a change of calendar day. Of the three reset choices from the previous lesson, a session boundary is the one that matches clause 3 exactly.

From price to one alert

  1. Prior high, shifted back one barRef( HHV( High, N ), -1 ) — the current bar cannot raise its own level
  2. Plus a volatility bufferBufferAtr * ATR( AtrPeriod ), so the parameter means the same thing on any instrument
  3. Warm-up guardNOT IsNull( Level ) — no level, no signal, rather than a Null quietly poisoning the comparison
  4. Cross, not exceedCross( High, Level ) is one bar; High > Level is a whole afternoon
  5. Session gateTimeNum() between the configured start and end
  6. Once-per-session latchExRem( break, day change ) — the first one passes, the rest wait for tomorrow
  7. Completed bars onlyBarIndex() < LastValue( BarIndex() ) — the newest bar is still being written
  8. AlertIf, type 1Text carrying symbol, interval, bar stamp, high and level
Each stage removes a specific class of false alert. Remove any one of them and a known failure returns.

Complete runnable AFL

realtime-breakout-alert.afl
// realtime-breakout-alert.afl
// Part 25 - Project: Real-Time Breakout Alert
//
// Watches one symbol on one chart pane and raises at most one alert per
// session, on the first completed bar whose high exceeds the highest high of
// the previous N bars plus a volatility buffer, inside a session window you
// define.
//
// It raises an alert. It does not place an order, and nothing in this course
// does. The chain ends at: alert -> you read it -> you decide.
//
// Assumptions declared up front:
// - Any interval. On an intraday interval the session filter and the
// once-per-session latch do real work; on daily bars they are harmless.
// - Bar time-stamping: TimeNum() returns the START or the END time of the
// interval depending on Tools -> Preferences -> Intraday. The session
// window below is compared against whatever that setting produces, so
// confirm which convention your database uses before trusting it.
// - Alerts appear only if "custom indicators" is ticked under
// Tools -> Preferences -> Alerts, "Enable alerts from".
// - Neither a real-time feed nor the Professional edition is required to RUN
// this. A live feed only changes how often the pane re-executes. Bar
// Replay (Tools -> Bar Replay) drives it just as well, and that is the
// tested, no-subscription path.
_SECTION_BEGIN( "Real-Time Breakout Alert" );
LookbackBars = Param( "Breakout lookback (bars)", 20, 2, 400, 1 );
BufferAtr = Param( "Buffer (x ATR)", 0.10, 0, 2, 0.05 );
AtrPeriod = Param( "ATR period", 14, 1, 100, 1 );
SessionStart = Param( "Session start (HHMMSS)", 93000, 0, 235959, 100 );
SessionEnd = Param( "Session end (HHMMSS)", 155900, 0, 235959, 100 );
UseSession = ParamToggle( "Session filter", "Off|On", 1 );
AlertsOn = ParamToggle( "Alerts", "Off|On", 1 );
RefreshSecs = Param( "Self-refresh (seconds)", 5, 0, 300, 1 );
AlertLookback = Param( "Alert lookback (bars)", 2, 1, 20, 1 );
// Ask this pane to re-execute on a timer. RequestTimedRefresh() works with or
// without a data plugin, which is exactly what makes the formula testable with
// no subscription. Set the parameter to 0 to switch the timer off.
if( RefreshSecs > 0 )
{
RequestTimedRefresh( RefreshSecs );
}
// --- The level -----------------------------------------------------------
// Ref( ..., -1 ) shifts the running high back one bar, so the current bar is
// never part of the level it is being measured against. Without the shift the
// high of the breakout bar raises the level it is trying to break.
PriorHigh = Ref( HHV( High, LookbackBars ), -1 );
Buffer = BufferAtr * ATR( AtrPeriod );
Level = PriorHigh + Buffer;
// Warm-up: HHV and ATR are Null until they have enough bars, and a Null
// quietly poisons every comparison it touches. Say so explicitly.
HaveLevel = NOT IsNull( Level );
// --- The event -----------------------------------------------------------
// Cross() is true on the one bar where High first exceeded the level. The
// state "High > Level" stays true for as long as the market stays up there,
// which is the difference between one alert and forty.
RawBreak = HaveLevel AND Cross( High, Level );
// --- The session gate ----------------------------------------------------
InSession = NOT UseSession
OR ( TimeNum() >= SessionStart AND TimeNum() <= SessionEnd );
// --- Once per session ----------------------------------------------------
// A change of calendar day resets the latch, so the first qualifying break of
// each session passes and every later one is blocked until the next session.
NewSession = Day() != Ref( Day(), -1 );
FirstBreak = ExRem( RawBreak AND InSession, NewSession );
// --- Completed bars only -------------------------------------------------
// The newest bar is still being built by the feed or by Bar Replay: its high
// can still grow. Alerting on it is how one breakout becomes six alerts.
BarComplete = BarIndex() < LastValue( BarIndex() );
Trigger = FirstBreak AND BarComplete;
// --- The alert -----------------------------------------------------------
// GetPlaybackDateTime() returns zero when Bar Replay is not running, so this
// labels replayed alerts and keeps a practice run out of your real log.
Playback = GetPlaybackDateTime();
if( Playback > 0 )
{
ModeText = "[REPLAY] ";
}
else
{
ModeText = "";
}
AlertText = ModeText + "BREAKOUT " + Name()
+ " " + Interval( 2 )
+ " bar " + DateTimeToStr( LastValue( DateTime() ) )
+ " high " + NumToStr( LastValue( High ), 1.4 )
+ " level " + NumToStr( LastValue( Level ), 1.4 );
// Type 1 (buy), default flags, and an explicit lookback of 2.
//
// The lookback is the argument people leave alone and should not. AlertIf reads
// only the lookback most recent bars, and its default of 1 is exactly the bar
// BarComplete excludes - so with the default nothing would ever fire. Two bars
// puts the most recent completed bar inside the window.
//
// Bit 8 of the flags, "do not display repeated alerts having the same
// date/time", is then what keeps that one completed-bar signal from being
// re-reported on every timed refresh for the whole life of the next bar. The
// AFL above decides WHICH bar may alert; bit 8 decides that it is said once.
if( AlertsOn )
{
AlertIf( Trigger, "", AlertText, 1, 1+2+4+8, AlertLookback );
}
// --- Drawing --------------------------------------------------------------
Plot( Close, "Close", colorDefault, styleCandle );
Plot( Level, "Breakout level", colorOrange, styleLine | styleStaircase );
PlotShapes( Trigger * shapeUpArrow, colorGreen, 0, Low, -20 );
Title = Name() + " " + Interval( 2 ) + " " + ModeText
+ "\nLevel " + NumToStr( LastValue( Level ), 1.4 )
+ " Last high " + NumToStr( LastValue( High ), 1.4 )
+ "\nRaw breaks: " + NumToStr( LastValue( Cum( RawBreak ) ), 1.0 )
+ " After latch: " + NumToStr( LastValue( Cum( FirstBreak ) ), 1.0 )
+ " Alertable: " + NumToStr( LastValue( Cum( Trigger ) ), 1.0 );
_SECTION_END();

Download realtime-breakout-alert.afl129 lines

HHV( High, LookbackBars ) gives the running highest high; Ref( ..., -1 ) shifts it back a bar. ATR( AtrPeriod ) supplies the volatility scale, and BufferAtr is the fraction of it you are demanding as clearance. The sum is Level.

HaveLevel = NOT IsNull( Level ) is not decoration. Both HHV() and ATR() return Null until they have enough bars, and Null propagates through comparisons rather than raising an error. Requiring HaveLevel explicitly means the warm-up produces no signal on purpose, rather than producing no signal by luck.

Cross( High, Level ) is true on the single bar where the high first exceeded the level. The session gate is a plain range test on TimeNum(), which encodes the bar time as 10000 * hour + 100 * minute + second — so 09:30:00 is 93000. Note that this is a packed decimal, not a count of seconds: comparisons like >= are safe, but arithmetic on it is not, which is why the parameters are entered in the same packed form rather than being computed.

NOT UseSession OR ( ... ) lets the toggle switch the whole clause off for daily bars, where every bar is the session.

Fragment — not a complete formula

NewSession = Day() != Ref( Day(), -1 );
FirstBreak = ExRem( RawBreak AND InSession, NewSession );

Day() returns the day-of-month for each bar, so a change of value marks a new trading day. ExRem() passes the first qualifying break and blocks the rest until NewSession is true again. That is clause 3, in two lines, with no state to manage and nothing that behaves differently in a Scan than on a chart.

BarComplete = BarIndex() < LastValue( BarIndex() ) is true for every bar except the newest. Trigger = FirstBreak AND BarComplete is what reaches AlertIf(). The consequence, which you will verify below, is that the alert for a signal on bar T arrives one bar later — when bar T can no longer change.

The alert is raised with type 1, the default flags, and an explicit lookback of 2. That last argument is the one carried over from the previous lesson: AlertIf() examines only the lookback most recent bars, its default is 1, and that one bar is precisely the one BarComplete excludes. Two bars is the smallest window that contains a completed bar. It is exposed as a Param() so you can set it back to 1 during testing and watch the alert go silent, which is a faster way to believe it than reading about it.

Widening the window means the same signal stays eligible for the whole life of the next bar. Flag bit 8 — no repeated alerts with the same date/time — is what turns that back into one line. The AFL decides which bar may alert; bit 8 decides it is announced once.

GetPlaybackDateTime() returns the Bar Replay position, or zero when replay is not active. Zero is a perfectly legal-looking number, so the formula tests it before using it rather than formatting it blindly. When replay is running, every alert line and the chart title are prefixed [REPLAY].

RequestTimedRefresh( RefreshSecs ) asks the pane to re-execute on a timer. It works with or without a data plugin, which is what lets the same formula be exercised offline. Refreshes are aligned to the second boundary, and the manual is explicit that Windows timers are accurate to roughly 55 milliseconds when the machine is idle — near enough for an alert, and nowhere near a real-time scheduling promise.

Function What it contributes here
HHV( ARRAY, periods ) The running highest value over the lookback window
Ref( ARRAY, period ) A negative period shifts back; -1 excludes the current bar from its own level
ATR( period ) Volatility scale for the buffer. It has no documented default period, so it is always passed
Cross( ARRAY1, ARRAY2 ) Converts “is above” into “just went above”
TimeNum() The bar’s time as packed decimal HHMMSS, for the session gate
Day() Day of month per bar; a change of value is a new session
ExRem( ARRAY1, ARRAY2 ) The once-per-session latch
BarIndex(), LastValue() Together, the completed-bar guard
AlertIf( ..., flags, lookback ) The last two arguments: lookback of 2 so the guarded bar is inside the window, flags left at the default so bit 8 collapses re-reads
RequestTimedRefresh( interval ) Re-executes this pane on a timer, plugin or no plugin
GetPlaybackDateTime() Bar Replay position, or zero when replay is off

Apply the formula to a chart pane. You should see:

  • An orange staircase line sitting above recent price — the breakout level. It steps up as new highs are made and stays flat otherwise. If it hugs the price bars exactly, the Ref() shift is missing.
  • A green up arrow beneath the low of each alertable bar. On an intraday chart with the session filter on, at most one arrow per day.
  • A title reporting three counts: raw breaks, breaks after the latch, and alertable breaks. The first should be comfortably larger than the second. The second should exceed the third by at most one, and by exactly one when the final bar of the loaded range is itself a signal.
  • Nothing at all during the first LookbackBars bars of history.

This is the part of the project that matters, and it is deliberately the longest. Four stages, all on stored data.

Before an alert can be verified, you need the number it is supposed to produce. The harness is the identical rule with AlertIf() removed and every intermediate step exposed as a column.

Complete runnable AFL

breakout-alert-test-harness.afl
// breakout-alert-test-harness.afl
// Part 25 - Project: Real-Time Breakout Alert (offline test harness)
//
// The same breakout rule as realtime-breakout-alert.afl, with AlertIf() taken
// out and every intermediate step exposed as a column. Run it as an
// Exploration over the history you are about to alert on.
//
// The "Latch count" on the final row is the number of alert lines the live
// formula is permitted to write over that same range. Not approximately -
// exactly. That is the whole point: the alert is checked against a number you
// can count by hand, on data you already own, with no subscription and no
// market open.
//
// Assumptions declared up front:
// - The parameters here must match the chart pane exactly. One bar of
// difference in the lookback changes the expected count.
// - Analysis -> Range must match the span you intend to watch, because the
// running counts start at the first bar of the range.
// - "Alertable" excludes the final bar of the range for the same reason the
// chart formula excludes it: on a live or replayed chart it is still
// forming. Over pure history that costs you at most one signal, and the
// lesson explains why paying it is the right trade.
_SECTION_BEGIN( "Breakout alert test harness" );
LookbackBars = Param( "Breakout lookback (bars)", 20, 2, 400, 1 );
BufferAtr = Param( "Buffer (x ATR)", 0.10, 0, 2, 0.05 );
AtrPeriod = Param( "ATR period", 14, 1, 100, 1 );
SessionStart = Param( "Session start (HHMMSS)", 93000, 0, 235959, 100 );
SessionEnd = Param( "Session end (HHMMSS)", 155900, 0, 235959, 100 );
UseSession = ParamToggle( "Session filter", "Off|On", 1 );
ShowAll = ParamToggle( "Rows", "Breaks only|Every bar", 0 );
PriorHigh = Ref( HHV( High, LookbackBars ), -1 );
Buffer = BufferAtr * ATR( AtrPeriod );
Level = PriorHigh + Buffer;
HaveLevel = NOT IsNull( Level );
RawBreak = HaveLevel AND Cross( High, Level );
InSession = NOT UseSession
OR ( TimeNum() >= SessionStart AND TimeNum() <= SessionEnd );
NewSession = Day() != Ref( Day(), -1 );
FirstBreak = ExRem( RawBreak AND InSession, NewSession );
BarComplete = BarIndex() < LastValue( BarIndex() );
Trigger = FirstBreak AND BarComplete;
Filter = ShowAll OR RawBreak;
AddColumn( High, "High", 1.4 );
AddColumn( Level, "Level", 1.4 );
AddColumn( TimeNum(), "Bar time", 1.0 );
AddColumn( RawBreak, "Raw break", 1.0 );
AddColumn( InSession, "In session", 1.0 );
AddColumn( FirstBreak, "After latch", 1.0 );
AddColumn( Trigger, "Alertable", 1.0 );
AddColumn( Cum( RawBreak ), "Raw count", 1.0 );
AddColumn( Cum( FirstBreak ), "Latch count", 1.0 );
AddColumn( Cum( Trigger ), "Alert count", 1.0 );
AddColumn( BarComplete, "Complete", 1.0 );
_SECTION_END();

Download breakout-alert-test-harness.afl62 lines

Run it as an Exploration, on one symbol, over a fixed range, with the parameters written down. Read the final row. The “Latch count” is the number of alert lines the chart formula is permitted to write over that range. Also copy out the timestamps of the qualifying bars — you are going to reconcile against them, not just against a total.

Set the row toggle to “Every bar” for a short range and read down the columns once. You should be able to see, for a single day, the level stepping up, one raw break, the “In session” flag excluding anything outside your window, and the latch turning the second and third breaks of that day into zeros. If you cannot see that in the table, the alert has nothing to be right about.

An alert that produces nothing because a checkbox is clear looks exactly like an alert that produces nothing because it is correctly suppressing. Separate the two before going further.

  1. Open Window -> Alert Output and clear it.
  2. Confirm the relevant boxes under Tools -> Preferences -> Alerts are ticked — “custom indicators” for a chart pane, “Automatic Analysis” for a Scan.
  3. Temporarily change the AlertIf() call’s flags to 1+2, and set the Analysis range so that the bar before the last one is a known signal bar. Run it twice.
  4. Two identical lines is a pass: the plumbing works and suppression is off.
  5. Restore the default flags and run twice more. One line is a pass: suppression works.
  6. Set the “Alert lookback (bars)” parameter to 1 and run again. Nothing should appear, because the only bar examined is the one the completed-bar guard excludes. Set it back to 2 and confirm the line returns.

If step 4 produces nothing, stop. Nothing after this point can be interpreted until the alert path is known to be live. Step 6 is not a formality: it is the cheapest demonstration in this part of why an argument you never touched can silence an otherwise correct formula.

Stage 3 — walk the history under Bar Replay

Section titled “Stage 3 — walk the history under Bar Replay”

Bar Replay truncates the database at a moving playback position and affects charts and the Analysis window alike, so advancing it one step is genuinely equivalent to one new bar arriving.

  1. Tools -> Bar Replay. Set Start to a date before your first known signal and End after the last one. Set Step interval to the database’s base interval, which is the documented recommendation.
  2. Press Pause to enter playback mode without running, then use the single-step-forward button.
  3. Watch the chart title. [REPLAY] should appear as soon as playback is active.
  4. Step forward through each known signal. The alert line for a signal on bar T must appear on the step onto T+1, carrying T’s timestamp.
  5. Step backwards over a signal bar and forwards again. No new line should appear.
  6. Press Stop when finished. The full data set is restored.

The one behaviour left is intrabar flicker, and you can reproduce it without a feed. Bar Replay’s step interval is independent of the chart’s viewing interval, and the documentation states the last bar builds up realistically as data arrives.

Put the chart on five-minute bars, set the replay step interval to one minute, and step manually. You will watch a five-minute bar assemble itself in five steps. Temporarily comment out BarComplete from the Trigger line and step through a bar where the high pokes above the level early and the bar closes back below. The alert fires on the forming bar, and the finished data contains no signal at all. Restore the guard and repeat: no alert. That contrast, seen once, is worth more than any amount of reading about it.

Everything above still applies, and one thing is added: run the formula through a full session on a symbol you are not trading, and reconcile the Alert Output lines against the harness Exploration run over that same session afterwards. They should match exactly. If the live run produced more lines than the after-the-fact Exploration, you have found an intrabar defect that history cannot show you — which is the only thing a live feed genuinely buys you in testing.

Check Pass criterion What a failure means
Level excludes the current bar Level line steps up only after a new high, never on the breakout bar itself The Ref( ..., -1 ) shift is missing
Warm-up produces nothing No arrows in the first LookbackBars bars The HaveLevel guard is missing or inverted
Event, not state Raw break count is far below the number of bars above the level Cross() was replaced by a comparison
Session gate No alertable bar has a “Bar time” outside the window Time-stamping convention differs from what the parameters assume
Once per session Latch count equals the number of days with at least one qualifying break The reset argument to ExRem() is wrong
Completed bars only Alert appears on the step onto T+1, never onto T Guard missing, or the comparison is the wrong way round
Lookback covers the guard Setting the lookback parameter to 1 silences the alert; 2 restores it If 1 also produces lines, the guard is not being applied at all
No re-fire on re-visit Stepping back and forward adds no line Suppression is being relied on where the latch should act
Counts reconcile Alert Output line count equals the harness Latch count over the same range Parameters or Analysis range differ between the two
Replay is labelled Every replayed line begins [REPLAY] GetPlaybackDateTime() result used without the zero test
Replay stopped Later scans return the full range Bar Replay left in Pause
Symptom Cause
No alerts at all, no error The context’s box is clear under Tools -> Preferences -> Alerts
No alerts, and the arrows are also missing HaveLevel is false throughout: fewer loaded bars than LookbackBars
Arrows appear but no alert lines AlertsOn toggle is off, or the lookback window excludes the guarded bar — the default of 1 does exactly that
An alert every few seconds The completed-bar guard was removed, on a refreshing chart
One alert, then silence for days Two alerts share type, so the state machine is suppressing the second
Alerts at implausible times Session parameters written for start-of-bar stamping on an end-stamped database, or the reverse
Alert count exceeds the harness count Different parameters, different range, or an intrabar fire
Scans suddenly return truncated results Bar Replay is still in Pause
A SOUND command does nothing Single backslashes in the path; AFL string literals need \\

Across a watchlist. Move the same rule into an Analysis window as a Scan, apply it to a watchlist, and enable “Auto repeat Scan/Explore” with an interval — a plain number means minutes, and 5sec or 5s means seconds. The formula needs no change; the alert type stays 1, and because the state machine keys per symbol, each symbol carries its own memory. Note what this costs: the Standard edition runs two threads per Analysis window against the Professional edition’s thirty-two, so a large watchlist on a short repeat interval is a very different proposition on the two editions.

A second alert type. Add a failure alert of type 5 that fires when price closes back below the level within a few bars of the breakout. Two types now coexist, and the per-type suppression keeps them independent — a good place to observe the state machine behaving rather than reading about it.

An audit trail. Use StaticVarSetText() on each alert to record what was sent, and a second small pane to display the last few entries. You then have something to reconcile against the Alert Output window, and something that survives the window being cleared.

Routing. Once the alert is verified, EMAIL or an EXEC to a notification tool of your choosing turns it into something that reaches you away from the machine. Verify the alert first and route it second; a mis-firing alert that reaches your phone is worse than one that does not.

You have a breakout alert whose behaviour is specified in seven clauses, each of which fails visibly if broken, and a two-formula workflow — the alerting chart pane and the auditing Exploration — where the second establishes the number the first is allowed to produce. You have walked it through history with Bar Replay and watched the one-bar offset that proves the completed-bar guard is real. You have reproduced intrabar flicker on stored data, seen what it does to an unguarded alert, and seen the guard remove it.

None of that required a subscription, and the parts of it that a live feed would have added are small and specific: genuinely live intrabar behaviour, and the reconciliation of a real session against its own history afterwards. Everything else was better done offline, because offline you can run the same twenty minutes as many times as you need.

The alert tells you something happened. What happens next is a decision you make, with the evidence in front of you. That boundary is where this course leaves it, deliberately.

Check your understanding

Question 1. Why is the breakout level written as `Ref( HHV( High, N ), -1 )` rather than `HHV( High, N )`?
Level = Ref( HHV( High, LookbackBars ), -1 ) + Buffer;
Show the answer and why

Answer: So the current bar high cannot raise the level it is being compared against

Without the shift, the current bar is inside its own lookback window, so its high is already part of the maximum it would have to exceed. The comparison becomes nearly impossible to satisfy, and the usual conclusion — that the formula is broken — is the wrong one. The shift is the fix, and it is the kind of self-reference worth checking for in any rule built on a running extreme.

Question 2. The harness Exploration reports a latch count of 7 over a fixed range. Replaying that range produces 9 lines in the Alert Output window. Which explanations are worth checking? Select all that apply.
Show the answer and why

Answer: The chart pane and the Exploration are using different parameter values, The Analysis range and the replay span do not cover the same bars, The completed-bar guard was removed, so some bars fired while still forming

The first three all produce a genuine mismatch. The alert type does not: it affects suppression, and suppression can only reduce the number of lines, never increase it. When counts disagree, always settle the inputs before suspecting the logic.

Question 3. Bar Replay is set to a one-minute step interval while the chart displays five-minute bars. What does that arrangement let you observe?
Show the answer and why

Answer: A five-minute bar assembling itself in five steps, reproducing intrabar behaviour without a feed

The step interval and the viewing interval are independent, and the documentation states that the last bar builds up realistically as data arrives. That makes it the offline substitute for a live feed when you need to see how a condition behaves inside a forming bar — which is precisely the behaviour the completed-bar guard exists to suppress.

Question 4. After a testing session the formula behaves correctly, but every scan you run for the rest of the afternoon returns results that stop several days early. What is the first thing to check?
Show the answer and why

Answer: Bar Replay is still active, because Pause does not exit playback

Bar Replay is global and truncates the data for charts and the Analysis window alike, and Pause is a playback mode rather than a suspension. Only Stop, or closing the window, restores the full data set. Nothing is written to disk, so the database is untouched — which is exactly why the symptom is so confusing.

Sources for this lesson

9 verified · checked 2026-08-31

  1. 01AmiBroker User's Guide — Using formula-based alertsamibroker.com/guide/h_alerts.html2026-08-31
  2. 02AFL Function Reference — AlertIfamibroker.com/guide/afl/alertif.html2026-08-31
  3. 03AFL Function Reference — RequestTimedRefreshamibroker.com/guide/afl/requesttimedrefresh.html2026-08-31
  4. 04AFL Function Reference — GetPlaybackDateTimeamibroker.com/guide/afl/getplaybackdatetime.html2026-08-31
  5. 05AFL Function Reference — TimeNumamibroker.com/guide/afl/timenum.html2026-08-31
  6. 06AmiBroker User's Guide — Bar Replayamibroker.com/guide/w_barreplay.html2026-08-31
  7. 07AmiBroker User's Guide — Preferences§ Intraday and Alerts tabsamibroker.com/guide/w_preferences.html2026-08-31
  8. 08AmiBroker — Standard versus Professional edition comparisonamibroker.com/guide/versions.html2026-08-31
  9. 09AmiBroker User's Guide — Data sourcesamibroker.com/guide/h_quotes.html2026-08-31

Every technical claim on this page was checked against the official AmiBroker documentation on the date shown. Where the course disagrees with folklore, the source is how you can tell which one to trust.