Replay Exercise: Intraday Setups and Alerts
The previous exercise put your reading of a chart under test. This one puts your code under
test. You will run a breakout alert and a higher-timeframe filter against a replayed
intraday session and answer four questions that nobody can answer from the documentation
alone: does the alert reach the Alert Output window at all, how many times does it fire,
what happens to the completed-bar guard when it meets the lookback argument, and how
different a daily filter looks when the daily bar is only half built.
Every one of those has bitten somebody at 09:32 on a Monday. Finding out here costs forty-five minutes and nothing else.
Setting up
Section titled “Setting up”This exercise is written for intraday bars. It works on daily bars and the fallback is named at every step, but the session-filter material only means something intraday.
| What you have | Chart interval | Step interval | Higher frame |
|---|---|---|---|
| One-minute bars | 5-minute | 1 minute | Daily |
| Five-minute bars | 30-minute | 5 minutes | Daily |
| End-of-day bars only | Daily | Daily | Weekly |
If you have no intraday data at all, Part 18 covers the free and end-of-day sources AmiQuote supports, and Part 19’s lab builds an intraday database from historical files. Neither requires a subscription. A single day of one-minute bars for one liquid symbol is enough for this exercise, and that is a small enough amount of data to obtain by ordinary means.
Preferences, before anything else
Section titled “Preferences, before anything else”Alerts raised from a chart formula only reach the Alert Output window if AmiBroker has been told to accept them. In Tools, Preferences, Alerts there is an “Enable alerts from” group with separate checkboxes for Automatic Analysis, Commentary and custom indicators. The formula below is a custom indicator, so that box must be ticked.
Open Window, Alert Output and dock it where you can see it without covering the chart. The window carries a column identifying which subsystem raised each line, which is how you will tell an alert from your chart apart from one raised by a scan.
The workspace
Section titled “The workspace”Four panes on one sheet: the price chart with the alert harness applied, the replay clock from the first lesson, the higher-timeframe context panel, and the Alert Output window.
Set the replay range to cover one full session plus at least a hundred bars before it, so that the lookback windows are warm at the open rather than filling up during the exercise.
Rules of engagement
Section titled “Rules of engagement”Different from the previous exercise, because a different thing is under test.
The alert harness
Section titled “The alert harness”A breakout alert you can rehearse. It raises a line in the Alert Output window when a bar closes above the previous N bars’ high on above-average volume inside your session hours, it stamps every line with the replay position so the log tells you when in the session each alert fired, and it exposes as parameters exactly the two settings whose interaction this exercise exists to establish.
It stops at the alert. There is no order, no broker connection, and no automation beyond putting a line of text in front of a human being.
The formula
Section titled “The formula”Complete runnable AFL
// replay-alert-harness.afl// Part 26 - Replay Exercise: Intraday Setups and Alerts//// A breakout alert built so that it can be rehearsed under Bar Replay instead// of being tested for the first time in a live session. It writes to the Alert// Output window and stamps every line with the replay position, so the log you// end up with says WHEN in the replayed session each alert was raised.//// It ends where this course ends: an alert, a human reading it, a decision.// There is no order routing here and none is coming.//// How to run it:// Tools -> Preferences -> Alerts: tick "Enable alerts from" custom indicators,// or nothing you do below will reach the Alert Output window.// Formula Editor -> paste -> name it "Replay alert harness" -> Apply Indicator.// Window -> Alert Output to see the lines arrive.// Then Tools -> Bar Replay, Step interval = your base interval, Speed 1.//// Assumptions declared up front:// - Chart formula on an intraday database. It runs on daily bars too, in// which case leave the session filter off.// - The breakout level uses the previous BreakoutLook bars only. The current// bar's own high is excluded, so the level cannot move to meet the price.// - Session times are read with TimeNum(), which reports the timestamp your// database holds. If your bars are stamped in a different time zone from// the exchange, this filter is wrong in exactly that many hours - Part 20// covers how to check which convention your data uses.// - Alerts here are informational. No position size, no risk, no order.
_SECTION_BEGIN( "Replay alert harness" );
BreakoutLook = Param( "Breakout lookback (bars)", 20, 2, 200, 1 );MinRelVolume = Param( "Minimum relative volume", 1.5, 0, 10, 0.1 );VolumeLook = Param( "Relative-volume lookback", 20, 5, 200, 1 );UseSession = ParamToggle( "Apply session filter", "No|Yes", 1 );SessionStart = Param( "Session start (HHMMSS)", 100000, 0, 235959, 100 );SessionEnd = Param( "Session end (HHMMSS)", 154500, 0, 235959, 100 );CompletedOnly = ParamToggle( "Alert on completed bars only", "No|Yes", 1 );LookbackBars = Param( "AlertIf lookback argument", 2, 1, 10, 1 );AlertFlags = Param( "AlertIf flags", 1 + 2, 0, 15, 1 );
// --- The setup -------------------------------------------------------------PriorHigh = Ref( HHV( High, BreakoutLook ), -1 );Breakout = Cross( Close, PriorHigh );
AverageVolume = MA( Volume, VolumeLook );RelVolume = IIf( AverageVolume > 0, Volume / AverageVolume, 0 );VolumeOk = RelVolume >= MinRelVolume;
InSession = IIf( UseSession, TimeNum() >= SessionStart AND TimeNum() <= SessionEnd, True );
// The last bar on an intraday chart is still forming: a condition can go true// and false again inside it. This is AmiBroker's own documented remedy - alert// only from bars that have closed.//// The interaction between this guard and the lookback argument is NOT written// down anywhere, and it is the first thing this lab asks you to establish.// AlertIf examines only the `lookback` most recent bars, `lookback` defaults to// 1, and BarComplete is false on that bar by construction. Two readings follow.// Either the alert for a signal on bar T appears when you step onto T+1, or a// lookback of 1 leaves nothing for it to fire from at all. LookbackBars is a// parameter so that you can run both and record which one your build does.// The default of 2 is the setting that produces output under either reading.BarComplete = IIf( CompletedOnly, BarIndex() < LastValue( BarIndex() ), True );
Condition = Breakout AND VolumeOk AND InSession AND BarComplete;
// --- Where the clock is ----------------------------------------------------PlaybackPos = GetPlaybackDateTime(); // zero when Bar Replay is not active
if ( PlaybackPos ){ ClockText = "REPLAY " + DateTimeToStr( PlaybackPos );}else{ ClockText = "live/EOD " + Now( 0 );}
AlertText = "Breakout candidate: " + Name() + " closed above the prior " + NumToStr( BreakoutLook, 1.0 ) + "-bar high on " + NumToStr( LastValue( RelVolume ), 1.2 ) + "x volume [" + ClockText + "]" + " -- review before acting; this is not an order";
// Type 1 is AmiBroker's "buy" alert type. The type is the key the built-in// de-duplication state machine remembers per symbol, so give different kinds of// alert different types or they will suppress each other.// Flags default to 1+2+4+8, which also suppresses repeats of the same type and// the same timestamp. The parameter above starts at 1+2 so that you can see// every raised alert while you are rehearsing, and can put the suppression// bits back once you know what the formula does.AlertIf( Condition, "", AlertText, 1, AlertFlags, LookbackBars );
// --- What you see on the chart ---------------------------------------------Plot( Close, "Close", colorDefault, styleCandle );Plot( PriorHigh, "Prior " + NumToStr( BreakoutLook, 1.0 ) + "-bar high", colorBlue, styleLine | styleThick );
PlotShapes( IIf( Condition, shapeUpArrow, shapeNone ), colorBrightGreen, 0, Low );
// Read the state as text, not as a colour: the title says in words whether the// three parts of the condition are true on the last visible bar.Title = Name() + " " + ClockText + "\n" + "Breakout: " + WriteIf( LastValue( Breakout ), "yes", "no" ) + " Volume filter: " + WriteIf( LastValue( VolumeOk ), "yes", "no" ) + " (" + NumToStr( LastValue( RelVolume ), 1.2 ) + "x)" + " In session: " + WriteIf( LastValue( InSession ), "yes", "no" ) + "\n" + "Alert raised on this bar: " + WriteIf( LastValue( Condition ), "YES", "no" );
_SECTION_END();How it works
Section titled “How it works”The setup is three conditions combined. Cross( Close, PriorHigh ) fires on the bar
where the close moves above the level, not on every bar it stays above it — the state
versus event distinction from Part 8, and the single most common cause of an alert that
repeats forty times. Ref( HHV( High, BreakoutLook ), -1 ) shifts the high window back one
bar so that the current bar’s own high is excluded from the level it is supposed to be
breaking; without the shift the level moves to meet the price and the cross can never
happen. The volume filter and the session filter are ordinary gates.
The session filter uses TimeNum(), which returns the timestamp your database holds in
HHMMSS form. It is worth being clear that this is your database’s idea of the time, not the
exchange’s: if your bars are stamped in a different zone, or your bar time-stamping
preference records the start of the interval where you assumed the end, the filter is wrong
by a fixed offset and everything downstream is wrong with it. Part 20 covers how to
establish which convention your data uses. Replay is a good place to notice the symptom —
alerts clustering an hour before or after the session — but it will not diagnose it for you.
The completed-bar guard is AmiBroker’s own documented remedy for intraday alerts:
BarComplete = BarIndex() < LastValue( BarIndex() ) is false on the last, still-forming
bar and true on every bar before it. The tutorial gives it precisely because a condition can
go true and then false again inside a forming bar.
The AlertIf call takes the condition, an empty command string (text only, no sound, no
e-mail, no external program), the text, a type of 1, the flags, and the lookback. Type
matters more than it looks: the documented internal state machine remembers the type of the
last alert per symbol, and two different alerts sharing a type will suppress each other.
Flags default to 1+2+4+8, where 4 suppresses repeats of the same type and 8 suppresses
repeats at the same timestamp; the parameter starts at 1+2 so that you can see everything
during a rehearsal, which is the tutorial’s own suggestion for experimentation.
The chart output draws the level, marks triggering bars with an arrow, and — because meaning must never live in a colour alone — writes the state of all three conditions into the title as words.
Key functions
Section titled “Key functions”AlertIf( expression, command, text, type = 0, flags = 1+2+4+8, lookback = 1 )— raises an alert when the expression is true on one of thelookbackmost recent bars. An empty command string writes to the Alert Output window; the documented alternatives are"SOUND path","EMAIL"and"EXEC path-or-URL".Cross( array1, array2 )— true on the bar where the first rises above the second.TimeNum()— the bar’s time as HHMMSS.BarIndex()andLastValue( array )— together, the completed-bar test.GetPlaybackDateTime()— the replay position, or zero, used here only to stamp the text.
Expected result
Section titled “Expected result”With replay off, applying the formula to an intraday chart should draw the prior-high line as a staircase above the price and put arrows on the bars where a breakout closed. The title should report the three conditions in words on the last bar.
Under replay, stepping through a session should produce lines in the Alert Output window
whose text ends with [REPLAY <timestamp>], where the timestamp advances with the
playback position rather than sitting at today’s date.
Test it
Section titled “Test it”Set BreakoutLook to 3 and replay a volatile stretch. You should get many alerts — enough
to be sure the mechanism works. Then set it to 100 on the same stretch; you should get very
few or none. A formula that produces the same number of alerts at both settings is not
computing the level you think it is.
Then check the arrow and the alert agree. Every arrow on a completed bar should correspond to exactly one line in the Alert Output window. An arrow with no line, or a line with no arrow, is the discrepancy the next section is about.
Common errors
Section titled “Common errors”- Arrows but no alert lines. The custom-indicators checkbox in Preferences is off, or the flags have had bit 1 cleared, which silences the window while leaving other actions active.
- The same alert repeats every bar. The condition is a state rather than an event —
Close > PriorHighinstead ofCross( Close, PriorHigh ). - Alerts stop after the first one and never come back. Flags include 4, which suppresses repeats of the same type. That is usually what you want in production and never what you want while rehearsing.
- Alerts an hour either side of the session. A time-zone or bar-time-stamping mismatch, not a formula bug. Part 20.
- No alerts at all with the completed-bar guard on. That is phase 3 below, and it is the point of the exercise rather than a fault.
Extension
Section titled “Extension”Replace the empty command string with "SOUND" and a path to a short WAV file, and rehearse
with your eyes off the screen. It changes the exercise considerably: an alert you have to
notice is a different thing from an alert you were already watching for. The documented
alternatives to AlertIf for unconditional actions are PlaySound, SendEmail and
ShellExecute, which do the same jobs without the de-duplication state machine.
Running it: four phases
Section titled “Running it: four phases”Phase 1. Does an alert reach the window under replay at all?
Section titled “Phase 1. Does an alert reach the window under replay at all?”Set CompletedOnly to No and LookbackBars to 1, so nothing is masked. Step forward
through a stretch containing at least one obvious breakout and watch the Alert Output
window.
The documentation supports two halves of this and not the third. It says Bar Replay affects all formulas, in charts and in Analysis alike. It says indicators can raise alerts when the Preferences checkbox is ticked. It does not, anywhere, state what happens to alerts while replay is driving the chart. That combination is exactly why this is phase 1 rather than an assumption: you are establishing it on your installation, on your version, and writing the answer down.
Record: alerts appeared / alerts did not appear, and the AmiBroker version from Help, About.
Phase 2. How many times does one breakout fire?
Section titled “Phase 2. How many times does one breakout fire?”Keep CompletedOnly at No. Run the same stretch three ways and count the lines each time.
| Flags | What is suppressed | Count |
|---|---|---|
1+2 |
Nothing beyond the default text and beep | |
1+2+8 |
Repeats at the same date and time | |
1+2+4+8 |
Repeats of the same type, and at the same timestamp |
Fill in the counts before reading on. The interesting comparison is the first row against the third. On a forming intraday bar the condition can flicker, and each re-execution of the formula is another opportunity for the alert to be raised; the suppression bits are what stand between you and a log full of the same event.
Phase 3. The completed-bar guard and the lookback argument
Section titled “Phase 3. The completed-bar guard and the lookback argument”Now set CompletedOnly to Yes, leaving LookbackBars at 1. Replay the same stretch.
Two documented facts collide here, and the documentation never says what happens when they
do. AlertIf examines only the lookback most recent bars, and lookback defaults to 1.
BarComplete is false on the most recent bar by construction. Two readings follow, and both
are defensible from the text.
Reading one, which Part 25 states as a prediction to be checked: a signal on bar T produces an alert when you step onto bar T+1, because stepping makes bar T complete. The one-bar delay is the acknowledged cost of the guard.
Reading two: on the step onto T+1, the only bar being examined is T+1 itself, where
BarComplete is false — so nothing fires, and the guard with a lookback of 1 silences the
alert entirely.
Neither reading is documented. Run it and find out. Then set LookbackBars to 2 and run the
same stretch again, which puts the newly completed bar inside the examined window under
either reading.
Record all three counts: guard off with lookback 1, guard on with lookback 1, guard on with lookback 2. Whatever they turn out to be on your build, you will have settled a question the manual leaves open, by observation rather than by argument — and that habit is worth considerably more than this particular answer.
Phase 4. The higher timeframe, half built
Section titled “Phase 4. The higher timeframe, half built”Most intraday rules carry a filter from a larger frame: only take longs when the daily close is above its average, and so on. Under replay you can see the thing that a daily-bar backtest hides completely — at 11:00 the daily bar does not exist yet.
What a daily filter actually sees at 11:00
- Your daily filterCompares the daily close with its own average
- Today's daily barOpen, high so far, low so far, last price so far - it will not settle until the close
- Intraday bars replayed so farEverything from the open up to the playback position
- Bars not yet replayedInvisible to every formula while replay is active
The higher-timeframe context panel
Section titled “The higher-timeframe context panel”Show the larger frame the way it exists during a session rather than the way it exists in a finished database: computed from the intraday bars that have arrived, updating as they arrive, and labelled clearly as incomplete.
The formula
Section titled “The formula”Complete runnable AFL
// replay-mtf-context.afl// Part 26 - Replay Exercise: Intraday Setups and Alerts//// The higher-timeframe check, done the way it has to be done under replay: the// daily context is COMPUTED from the intraday bars that have arrived so far,// not looked up from a finished daily bar. Under Bar Replay the current daily// bar is a partial bar, exactly as it is at eleven o'clock on a real Tuesday.// That is the honest version of a multi-timeframe filter, and it is the version// that will disagree with your backtest.//// How to run it:// Formula Editor -> paste -> name it "Replay MTF context" -> Apply Indicator// on an intraday chart. Then drive it with Tools -> Bar Replay.//// Assumptions declared up front:// - Chart formula on an INTRADAY database. On a daily chart the compressed// frame equals the base frame and the panel has nothing to say.// - Compression uses AmiBroker's own session definitions from// File -> Database Settings -> Intraday Settings. If those are wrong, the// daily bars built here are wrong in the same way.// - expandLast is used deliberately. The documented caveat is that// expandFirst, applied to anything other than the period's open, can make a// value visible before the period that produced it has finished - which is// the definition of reading the future.// - Nothing here is a signal. It is a description of the larger frame that// you record in the log sheet alongside your intraday decision.
_SECTION_BEGIN( "Replay MTF context" );
HigherFrame = ParamList( "Higher timeframe", "Daily|Hourly|15-minute", 0 );TrendPeriod = Param( "Higher-frame average period", 20, 2, 200, 1 );
if ( HigherFrame == "Hourly" ){ UpperInterval = inHourly;}else{ if ( HigherFrame == "15-minute" ) { UpperInterval = in15Minute; } else { UpperInterval = inDaily; }}
// Guard against the case that makes this panel meaningless: asking for a frame// that is not actually larger than the chart you are looking at.BaseSeconds = Interval();FrameIsUp = UpperInterval > BaseSeconds;
if ( FrameIsUp ){ // Inside this block Open/High/Low/Close/Volume ARE the compressed bars. TimeFrameSet( UpperInterval );
UpperClose = Close; UpperHigh = High; UpperLow = Low; UpperTrend = MA( Close, TrendPeriod ); UpperAbove = Close > UpperTrend;
TimeFrameRestore();
// Expand back to the chart's own interval for display and for comparison // with intraday values. expandLast places each compressed value on the last // bar of its period, and carries it forward from there. UpperCloseX = TimeFrameExpand( UpperClose, UpperInterval, expandLast ); UpperHighX = TimeFrameExpand( UpperHigh, UpperInterval, expandLast ); UpperLowX = TimeFrameExpand( UpperLow, UpperInterval, expandLast ); UpperTrendX = TimeFrameExpand( UpperTrend, UpperInterval, expandLast ); UpperAboveX = TimeFrameExpand( UpperAbove, UpperInterval, expandLast );
Plot( Close, "Close", colorDefault, styleCandle ); Plot( UpperTrendX, HigherFrame + " average", colorBlue, styleLine | styleThick ); Plot( UpperHighX, HigherFrame + " high", colorLightGrey, styleLine ); Plot( UpperLowX, HigherFrame + " low", colorLightGrey, styleLine );
PlaybackPos = GetPlaybackDateTime();
if ( PlaybackPos ) { ClockText = "REPLAY " + DateTimeToStr( PlaybackPos ); } else { ClockText = "Replay OFF"; }
Title = Name() + " " + ClockText + "\n" + HigherFrame + " frame: close " + NumToStr( LastValue( UpperCloseX ), 1.4 ) + " average " + NumToStr( LastValue( UpperTrendX ), 1.4 ) + " above average: " + WriteIf( LastValue( UpperAboveX ), "yes", "no" ) + "\n" + "The " + HigherFrame + " bar covering this moment is INCOMPLETE. " + "It contains only the bars replayed so far.";}else{ Plot( Close, "Close", colorDefault, styleCandle );
Title = Name() + "\nChosen higher timeframe (" + HigherFrame + ") is not larger than this chart's interval (" + Interval( 2 ) + "). Nothing to compress.";}
_SECTION_END();How it works
Section titled “How it works”TimeFrameSet( interval ) replaces the price arrays with time-compressed bars of the
requested interval. Inside that block, Close is the daily close and MA( Close, 20 ) is
a twenty-day average, computed from whatever intraday bars are currently visible.
TimeFrameRestore() puts the base interval back, and TimeFrameExpand maps each compressed
value onto the chart’s own bars so the two can be drawn and compared.
expandLast is chosen deliberately. The documentation’s own caveat is about expandFirst:
used on anything other than the period’s open it makes a value visible before the period
that produced it has ended, which lets a formula know on Monday what the week’s high turned
out to be. expandLast places the value at the end of its period and carries it forward,
which is the behaviour that matches how the information actually became available.
The guard at the top compares the requested interval with Interval() and refuses to
compress to something that is not larger than the chart. It is two lines, and it prevents a
panel that appears to work while telling you nothing.
The title says in words that the higher-frame bar covering this moment is incomplete. That sentence is the entire lesson of the panel, and it belongs on screen rather than in a comment.
Key functions
Section titled “Key functions”TimeFrameSet( interval )/TimeFrameRestore()— switch the price arrays to a compressed interval and back. The documentation is explicit that you must restore before callingTimeFrameSetagain with a different interval.TimeFrameExpand( array, interval, mode = expandLast )— map a compressed array back onto the base interval. The interval must match the one used to compress.Interval( format = 0 )— the chart’s own bar size in seconds, used here as the guard.ParamList( name, values, default )— a dropdown parameter returning the chosen string.
Expected result
Section titled “Expected result”On a five-minute chart with the higher frame set to Daily, you should see a slow line for the daily average and two flat lines for the daily high and low, all of them stepping once per day. Under replay, the daily high and low lines should extend during the session — the day’s high can only rise and its low can only fall as bars arrive — and the average should adjust slightly as today’s partial close changes.
Test it
Section titled “Test it”The ratchet test above is the one that matters, and it is worth doing every time you build a multi-timeframe rule. A second check: press Stop and compare the panel’s daily close with the same day’s close on an actual daily chart of the same symbol. They should agree at the end of the day and disagree during it, and both of those are correct.
Common errors
Section titled “Common errors”- The panel says the frame is not larger than the chart. You are on a daily chart asking for a daily frame. Change one of them.
- The daily bars do not line up with the exchange’s day. Compression follows File, Database Settings, Intraday Settings. A wrong session definition or time shift produces daily bars that begin and end in the wrong place, and every value here inherits the error.
- The expanded lines are flat across the whole chart. The interval passed to
TimeFrameExpanddoes not match the one passed toTimeFrameSet. - Values appear one period early.
expandFirsthas been used whereexpandLastwas needed. This is look-ahead, and a backtest built on it will look considerably better than it should.
Extension
Section titled “Extension”Add a second higher frame — hourly as well as daily — and record at each alert whether they agreed. Disagreement between two filter frames is common, and deciding in advance which one wins is a rule you have to write down before the session, not during it.
Recording outcomes
Section titled “Recording outcomes”For every alert raised during the session, one row:
| Field | What goes in it |
|---|---|
| Alert time | From the [REPLAY ...] stamp, not the system clock |
| Bar | The bar the alert refers to, and whether it was the forming bar or the one before |
| Phase | Which parameter combination was running |
| Level broken | The prior-high value from the chart |
| Relative volume | From the title |
| Daily filter | Above or below, from the context panel, at that moment |
| Would you have acted? | Yes, no, or “needed something the alert did not tell me” — decided before stepping on |
| Outcome | Filled in during the debrief, from the exploration |
The last-but-one column is the one that repays the effort. An alert you would not have acted on is a false positive from your own point of view even if the price then went your way, and a run of them means the alert is firing on a condition you do not actually trade.
Debrief
Section titled “Debrief”Press Stop, then run the debrief exploration from the previous exercise on the same
symbol and date range, with BreakoutLook set to the same value the harness used and
Report every bar switched off, so that the exploration reports precisely the breakout
bars. Set Horizon to something that matches how long you would have held: twelve bars on a
five-minute chart is an hour.
Match the rows to your sheet by timestamp and fill in the Outcome column. Then answer these in writing.
- How many alerts did the session produce in each of the five parameter combinations you ran? Which single setting changed the count most?
- Did the alert stamp ever disagree with the bar you thought it referred to? A stamp on the forming bar and an arrow on the completed one are not the same event.
- On how many alerts did the daily filter agree with the direction of the breakout? On those where it disagreed, what did the exploration say happened?
- How many alerts would you have acted on? Of those you would not, what was missing — and is it something the formula could compute, or something you were doing by eye?
- Did any alert fire outside your intended session hours? If so, is that a filter bug or a time-stamping mismatch, and how would you tell the two apart?
- Compare the number of alerts with the number of distinct situations. If eight lines describe three events, the suppression flags are the fix, not a shorter lookback.
- What would this formula have done on a day when the instrument gapped up at the open and drifted? Set the replay to such a day and find out, rather than reasoning about it.
- Which of today’s findings are about your code, and which are about the market? Sort every finding into one of those two piles before you finish.
Self-scoring
Section titled “Self-scoring”Six criteria, 0 to 4 each, out of 24. As before, none of the points are for the price going your way.
| Criterion | 0 | 2 | 4 |
|---|---|---|---|
| Phases run | One combination tried | Two or three | All five combinations, each recorded, including the ones that produced nothing |
| Isolation | Several parameters changed together | Mostly one at a time | Exactly one change per run, with the count written down before the next change |
| Stamp discipline | Times taken from the system clock | Mixed | Every row timed from the replay stamp, forming and completed bars distinguished |
| Filter honesty | Daily filter read from a finished daily chart | Read from the panel but not questioned | Read from the panel during the session, with the ratchet test performed first |
| Decision recorded in advance | Outcome column filled before the “would you have acted” column | Some rows | Every row committed before the exploration was run |
| Sorting findings | Findings about code and market mixed together | Partially separated | Every finding assigned to one pile, with the market pile explicitly marked as one session of one symbol |
Below 12 usually means phases were skipped. Between 12 and 18 is a normal first pass. Above 18 means you have a rehearsal procedure you can run on any formula you write from here on, which is the actual deliverable.
What this proved, and what it did not
Section titled “What this proved, and what it did not”It proved things about your software and your code, and those proofs are solid because they
are deterministic. If the alert fired twice on one breakout with 1+2 and once with
1+2+4+8, that is a property of AlertIf and your flags, and it will behave the same way
tomorrow. If no alert appeared until the lookback was raised to 2, that is a property of the
interaction between two documented behaviours, and you established it by observation. If the
daily high line ratcheted upward through the session, your multi-timeframe filter is not
reading the future. All three are reproducible facts about a machine.
It proved nothing whatsoever about the setup.
You now have a rehearsal procedure for real-time code that does not need a real-time feed. Enable alerts from custom indicators, apply the harness and the context panel, set the replay range around a session, and change one parameter per pass while counting what comes out.
You have established, on your own installation, whether alerts reach the output window
under replay, how the suppression flags change the count, what the completed-bar guard does
when it meets a lookback of 1, and what a higher-timeframe filter looks like when its bar
is only half built. You have an outcome sheet in which the decision was recorded before the
result was known, and a debrief that sorts every finding into “about my code” or “about the
market”.
That is the end of the real-time track. Everything in Parts 17 to 26 that needed a live feed now has a route that does not, and the remaining question — whether any of these rules have an edge — is a different kind of question, which Part 27 starts to ask properly.
Check your understanding
Sources for this lesson
9 verified · checked 2026-08-31
- 01AmiBroker User's Guide — Bar Replay windowamibroker.com/guide/w_barreplay.html2026-08-31
- 02AmiBroker User's Guide — Using formula-based alertsamibroker.com/guide/h_alerts.html2026-08-31
- 03AmiBroker AFL Function Reference — AlertIfamibroker.com/guide/afl/alertif.html2026-08-31
- 04AmiBroker AFL Function Reference — GetPlaybackDateTimeamibroker.com/guide/afl/getplaybackdatetime.html2026-08-31
- 05AmiBroker AFL Function Reference — TimeFrameSetamibroker.com/guide/afl/timeframeset.html2026-08-31
- 06AmiBroker AFL Function Reference — TimeFrameExpandamibroker.com/guide/afl/timeframeexpand.html2026-08-31
- 07AmiBroker AFL Function Reference — TimeNumamibroker.com/guide/afl/timenum.html2026-08-31
- 08AmiBroker User's Guide — About AmiBroker Editionsamibroker.com/guide/versions.html2026-08-31
- 09AmiBroker User's Guide — Database Settings§ Intraday Settingsamibroker.com/guide/w_dbsettings.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.