Skip to content
Level 3 · AFL DeveloperLessonPart 16 · page 2 of 432 min
32Minutes
12AFL functions
10Sources
StandardRequires
AFL functions taught here12

Building Composites with AddToComposite()

Foreign() reads one other symbol, and you have to name it. That is fine for a benchmark and useless for a count across five hundred shares, because you would have to write five hundred calls and the formula would only work on the market you wrote it for. AddToComposite() is the answer: run one ordinary single-symbol formula across a universe, and let each symbol deposit its own contribution into an artificial symbol that AmiBroker creates for you. When the run finishes, that artificial symbol holds the sum.

By the end of this lesson you will be able to write such a formula with the right flags, run it in the mode it requires, read the result back, clear it when it goes stale, and demonstrate — not assume — that the numbers in it are correct.

Fragment — not a complete formula

AddToComposite( array, "ticker", "field", flags = atcFlagDefaults );

It returns nothing. The three ideas in it are:

  • array — the values to be added to the chosen field. Accumulation is additive across every symbol the run visits. Feed it a Boolean condition and you get a count; feed it Close and you get a sum of prices; feed it a position-open flag and you get a count of open positions.
  • "ticker" — the name of the artificial symbol. The documentation advises a leading tilde: ~comp, ~MyIndex, ~ADV.
  • "field" — which field of that symbol to write into. The documented codes are "O", "H", "L", "C", "V", "I" (open interest), "1" (Aux1), "2" (Aux2), and "X", which updates all four OHLC fields at once.

Because a composite is an ordinary-looking symbol with the ordinary set of fields, you can store up to eight independent series in one ticker. In practice that is a false economy: a formula that has to remember that declines live in the Open field is a formula you will misread in six months. One measure, one composite symbol.

New composites are assigned to group 253 by default and have the use only local database flag switched on, so an external data source never tries to fetch them. The tilde prefix is advice rather than enforcement, but it is advice the documentation repeats on both of its AddToComposite pages, and it earns its keep: composites sort together at one end of the symbol tree instead of scattering through your real tickers.

Group 253 is not decoration. AddToComposite skips symbols in group 253, which is how a composite is prevented from being fed into itself when your “Apply to” selection is broad enough to include it. The flag that maintains this arrangement is discussed next.

The flags argument is a sum of constants. Getting it wrong is the single most common way to produce a composite that is confidently, silently incorrect.

Constant Value What it does
atcFlagDeleteValues 1 Deletes all previous data from the composite symbol at the beginning of the scan. The reference page marks this one recommended.
atcFlagCompositeGroup 2 Puts the composite into group 253 and excludes every other ticker from group 253, which is what stops a composite being added to a composite.
atcFlagTimeStamp 4 Writes the scan’s date and time stamp into the composite’s Full name field.
atcFlagEnableInBacktest 8 Allows the call to run in backtest and optimization mode.
atcFlagEnableInExplore 16 Allows the call to run in exploration mode.
atcFlagResetValues 32 Resets values at the beginning of the scan. Not required if you use atcFlagDeleteValues.
atcFlagEnableInPortfolio 64 Allows the call in the custom portfolio backtester phase.
atcFlagEnableInIndicator 128 Allows the call in indicator mode.
atcFlagNormalize 256 After the scan completes, normalises by dividing the OHLCV fields by the field named in the field argument, which must be "I", "1" or "2".
atcFlagDefaults 7 The default: 1 + 2 + 4.

Two of these deserve a warning rather than a description.

atcFlagEnableInIndicator (128) makes AddToComposite write to the database every time the chart repaints. Every scroll, every zoom, every symbol change. If you also omit atcFlagDeleteValues, each repaint adds another copy of the values on top of the last. It exists for a reason, but it is not a reason you are likely to have, and a composite that changes when you scroll a chart is very hard to debug.

atcFlagNormalize (256) automates the divide-by-counter pattern described below. It is convenient once you understand what it replaces, and confusing before that, so this lesson does the division explicitly.

It only works in Scan mode, and that is deliberate

Section titled “It only works in Scan mode, and that is deliberate”

AddToComposite detects the context it is running in. By default it works only in Scan mode. Everywhere else it does nothing at all unless you opt in:

Context What happens by default
Scan Works.
Exploration Nothing, unless you add atcFlagEnableInExplore (16).
Backtest / Optimization Nothing, unless you add atcFlagEnableInBacktest (8).
Custom portfolio backtester Nothing, unless you add atcFlagEnableInPortfolio (64).
Indicator Nothing, unless you add atcFlagEnableInIndicator (128).
Commentary Nothing.

Building and using a composite

  1. Write the formulaAddToComposite() with a ~ticker, plus Buy = 0 so the scan reports nothing
  2. Choose the universeApply to: a watch list, a market, or all symbols
  3. Choose the rangeAll quotations, unless you deliberately want part of history
  4. Press ScanNot Explore, not Backtest
  5. Read it backForeign("~ticker", "V") from any formula
  6. Re-run after new quotesA composite is stored data, not a live calculation

The last step is the one people forget. The tutorial page states it plainly: to update any composite ticker — for example after adding or editing quotes — you must run the scan again. Nothing recalculates a composite automatically. If you download today’s end-of-day data and then look at your breadth panel, you are looking at yesterday’s breadth until you re-run the scan.

Buy = 0; appears in the official examples with the comment required by scan mode. Scan reports Buy/Sell signals, and a composite builder has no signals to report; without the assignment you get a result list full of noise, or a warning that the buy and sell variables were never assigned.

Produce four artificial symbols — advancing, declining and unchanged member counts, plus the number of members that had a usable bar — and plot the advance/decline line built from them. One file, two behaviours: it builds when scanned and plots when charted.

Complete runnable AFL

advance-decline-composite.afl
/* Advance / decline composites
-------------------------------------------------------------------------
Part 16 - Market Breadth. One file, two jobs:
* Run with the SCAN button in the Analysis window, it writes four
artificial symbols, each holding a per-bar count in its Volume field:
~ADV members that closed above their previous close
~DEC members that closed below their previous close
~UNC members that closed exactly at their previous close
~MEMBERS members that had a usable bar at all
* Applied to a chart, it reads those four symbols back and draws the
advance/decline line built from them.
AddToComposite is a no-op in indicator mode unless you explicitly opt in,
so charting this file cannot damage the composites it builds.
ASSUMPTIONS - state them, because every one of them changes the answer
1. Daily bars. On any other interval these are still advances and
declines, but of that interval, not of a trading day.
2. Analysis -> Settings -> General has "Pad and align all data to
reference symbol" turned ON, with a reference symbol that exists in
this database. Without it, members on different trading calendars
contribute to different bars and the counts are not comparable
across time.
3. The universe is whatever "Apply to" is set to in the Analysis
window. This formula does not filter symbols itself.
4. The database contains the symbols that exist today. Companies that
were delisted are absent, so historical counts under-report the
declines that actually happened.
*/
// ---- Configuration -------------------------------------------------------
CompositeAdvancing = "~ADV";
CompositeDeclining = "~DEC";
CompositeUnchanged = "~UNC";
CompositeMembers = "~MEMBERS";
// atcFlagDeleteValues - wipe the previous run's data before accumulating, so
// re-running the Scan replaces the composite instead of
// adding a second copy on top of it.
// atcFlagCompositeGroup - park the composite in group 253 and exclude every
// other symbol from that group. AddToComposite skips
// group 253, so a composite can never feed itself.
// atcFlagTimeStamp - write the run's date and time into the composite's
// Full name field, which is how you later tell a fresh
// composite from a stale one.
// The three together are the value of atcFlagDefaults (7). They are spelled
// out here so that changing one is a deliberate act.
CompositeFlags = atcFlagDeleteValues | atcFlagCompositeGroup | atcFlagTimeStamp;
// ---- Per-symbol measurement ---------------------------------------------
PreviousClose = Ref( Close, -1 );
// A member only votes on bars where it has a close and a previous close to
// compare it with. That makes Advancing + Declining + Unchanged equal to
// Contributing on every bar - the arithmetic identity used to verify the
// composites afterwards.
Contributing = NOT IsNull( Close ) AND NOT IsNull( PreviousClose );
// IsTrue() maps Null to 0, so a warm-up bar contributes a definite zero
// rather than a Null that AddToComposite would silently convert anyway.
Advancing = IsTrue( Contributing AND Close > PreviousClose );
Declining = IsTrue( Contributing AND Close < PreviousClose );
Unchanged = IsTrue( Contributing AND Close == PreviousClose );
// ---- Scan half: build the composites -------------------------------------
if( Status( "action" ) == actionScan )
{
AddToComposite( Advancing, CompositeAdvancing, "V", CompositeFlags );
AddToComposite( Declining, CompositeDeclining, "V", CompositeFlags );
AddToComposite( Unchanged, CompositeUnchanged, "V", CompositeFlags );
AddToComposite( Contributing, CompositeMembers, "V", CompositeFlags );
Buy = 0; // Scan reports Buy/Sell signals; this formula wants none
Sell = 0;
_exit(); // nothing below this line is useful while scanning
}
// ---- Chart half: read the composites back --------------------------------
_SECTION_BEGIN( "Advance/decline line" );
// Cum() no longer forces a full-history evaluation, so without this the
// running total would restart at whatever the leftmost visible bar happens
// to be and the line's level would change every time you zoom.
SetBarsRequired( sbrAll, sbrAll );
Adv = Nz( Foreign( CompositeAdvancing, "V" ) );
Dec = Nz( Foreign( CompositeDeclining, "V" ) );
Unc = Nz( Foreign( CompositeUnchanged, "V" ) );
Members = Nz( Foreign( CompositeMembers, "V" ) );
NetAdvances = Adv - Dec;
ADLine = Cum( NetAdvances );
// If the parts do not add up to the whole, the four composites were not all
// written by the same completed scan.
Mismatch = Adv + Dec + Unc - Members;
Plot( ADLine, "A/D line", colorBlue, styleLine | styleThick );
Plot( NetAdvances, "Net advances", colorLightGrey,
styleHistogram | styleOwnScale | styleNoLabel );
Title = StrFormat(
"%s A/D line %g advancing %g declining %g unchanged %g "
+ "contributors %g arithmetic check %g (must be 0)",
Name(),
SelectedValue( ADLine ), SelectedValue( Adv ), SelectedValue( Dec ),
SelectedValue( Unc ), SelectedValue( Members ), SelectedValue( Mismatch ) );
_SECTION_END();

Download advance-decline-composite.afl113 lines

The file has four logical sections.

Configuration names the four composite symbols in one place and builds the flag expression. Writing atcFlagDeleteValues | atcFlagCompositeGroup | atcFlagTimeStamp instead of atcFlagDefaults costs a line and buys clarity: the three flags are visible, so removing one becomes a deliberate act rather than an accident.

Measurement is ordinary single-symbol AFL. Contributing is true on bars where the symbol has both a close and a previous close, and the three conditions are defined so that advancing plus declining plus unchanged equals contributing on every bar. That identity is not decoration; it is the test used later to prove the composite is sound.

The scan half is guarded by Status("action") == actionScan. Inside it, four AddToComposite calls deposit the four counts, Buy and Sell are silenced, and _exit() ends execution rather than computing chart code that nobody will look at.

The chart half reads all four composites back with Foreign(), forms the net advances and their running total, and prints the arithmetic check in the title so a broken composite announces itself the moment you look at the chart.

  • Status("action") returns a code for the context the formula is running in; actionScan is 3. This is how one file behaves differently in two modes.
  • _exit() ends formula execution gracefully at that point. Nothing after it runs.
  • IsTrue() maps Null to 0 and any non-zero value to 1. AddToComposite converts Nulls to zero anyway, so this is about being explicit rather than about fixing a bug.
  • Nz() converts Null, NaN and Infinity to zero. It is applied to every Foreign() result because the documentation does not define what Foreign() returns for a ticker that does not exist yet, and on a fresh database none of these composites do.
  • SetBarsRequired( sbrAll, sbrAll ) requires all past and future bars, which turns QuickAFL off for this formula. Cum() needs it: since version 5.30, Cum() no longer forces a full-history evaluation on its own.

Run it with Scan, “Apply to” set to a watch list of a few dozen shares, and Range set to All quotations. The scan finishes with no result rows — that is correct, Buy is zero. Four new symbols appear in the symbol tree: ~ADV, ~DEC, ~UNC and ~MEMBERS.

Now select ~MEMBERS and apply the same file as an indicator. You should see a running A/D line, a grey histogram of net advances behind it, and a title ending in arithmetic check 0 (must be 0). If the check is zero on the bar under your cursor and on every bar you move the cursor to, the four composites came from one completed scan.

Pick one date. Run an exploration over the same universe with Filter = DateNum() == 1250612; and a column showing Close > Ref( Close, -1 ). DateNum() codes a date as 10000 * (year - 1900) + 100 * month + day, so 12 June 2025 is 1250612. Count the ones by hand or sort the column. That count must equal the value of ~ADV on that date. If it does not, the universe you scanned and the universe you explored are not the same universe.

  • Nothing was created. You pressed Explore or Backtest rather than Scan.
  • The numbers doubled. Your flag expression omitted atcFlagDeleteValues, so the second scan added to the first instead of replacing it.
  • The composite contains itself. You dropped atcFlagCompositeGroup, and “Apply to: all symbols” swept the composite into its own universe.
  • The A/D line’s level changes when you zoom. SetBarsRequired was removed, so Cum() restarted at the leftmost evaluated bar.
  • Counts look right but are aligned to the wrong calendar. You plotted the chart half on an illiquid share. Foreign() aligns foreign data to the current symbol, so bars the current symbol did not trade are deleted from the composite you are looking at.

Add a fifth composite holding the summed volume of advancing members and a sixth holding the summed volume of declining members. Their ratio, divided by the advancing/declining issue ratio, is the Arms index. Building it yourself, from a universe you defined, is a useful contrast with the built-in Trin() — which, as Lesson 1 noted, works only with composites that AmiBroker calculated internally.

Pad and align, and why a composite needs it

Section titled “Pad and align, and why a composite needs it”

AddToComposite accumulates bar by bar, matching on date. Two members contribute to the same composite bar only if they both have a bar on that date. Members on different trading calendars — different exchanges, different holidays, halted names, recent listings, thin issues that simply do not print on some days — contribute to different subsets of bars. Your “sum across N members” is then a sum across a varying N, and the variation has nothing to do with the market.

The setting that fixes this is a checkbox in Analysis → Settings, on the General tab of the Backtester settings dialog: “Pad and align all data to reference symbol:”, with an edit field beside it for the reference symbol. Turning it on pads and aligns every symbol’s quotes to that reference symbol’s calendar.

Four documented facts about it that you need:

  1. It is off by default. The manual says so explicitly, and adds “Use responsibly.”
  2. The manual names two intended uses, and creating composites out of unaligned data is one of them. The other is general market timing driven by a reference symbol.
  3. It has a cost. It may slow a scan, exploration or backtest down, and it may change indicator values slightly wherever your data has holes, because those holes get filled with previous-bar data.
  4. It fails silently. If the reference symbol does not exist, data is not padded. There is no error message.

AmiBroker will sometimes tell you about this itself. Notice 801 — “Turn ON ‘Pad and align to reference symbol’ when using ranking, composites or rotational trading” — is emitted for formulas containing AddToComposite, among others. It is a notice rather than an error, so it does not stop the run.

You will read advice to “set the number of passes to two” before building composites. There is no such setting. A search of the AmiBroker 7.00 User’s Guide across the Analysis, Filter, Backtester-settings, Preferences, Database-settings, Exploration, Backtest, Portfolio, Optimization, Ranking, New Analysis, Batch, multi-threading and AddToComposite pages finds no control named “number of passes”, and the Backtester settings screenshot shows none.

What is real is the two-stage structure of composite work, and AmiBroker gives you three documented ways to run it:

  • Run the scan again. The blunt instrument, and the one the tutorial page prescribes for refreshing a composite after new quotes arrive.
  • #pragma sequence(scan,explore), added in AmiBroker 6.40. The New Analysis window gains a Run Sequence toolbar button that performs the listed actions in order. The manual’s own example is precisely the composite case: build composites in the scan step, then run an exploration that consumes them, from a single click.
  • The Batch window, which automates and runs sequences of Analysis operations and can drive saved analysis projects.

The reason the two stages cannot be collapsed into one is worth stating: while a scan is running, the composite is incomplete. A formula that both writes to a composite and reads it back in the same pass reads a partial sum whose value depends on how far through the symbol list the run happens to be. Write in one stage, read in the next.

A composite is stored data. It persists until something changes it, which means the default failure is not an empty composite but an old one that looks perfectly plausible.

The correct mechanism is atcFlagDeleteValues. With it set, the composite’s previous data is deleted at the start of the scan, so every run replaces the last one. Without it — and without atcFlagResetValues (32), which does the reset job less thoroughly — successive scans keep adding, and your counts grow every time you press Scan. This is why the default atcFlagDefaults is safe and a hand-written flag expression that drops bit 1 is not.

atcFlagTimeStamp is how you detect staleness. With it set, each scan writes its date and time into the composite’s Full name field, which is visible in the symbol tree, in the Information window, and from AFL via FullName(). If the timestamp is from last Tuesday, so are the numbers.

Deleting quotes by hand is the last resort, for when you want a composite gone rather than rebuilt: Edit → Delete quotation removes the selected bar, Edit → Delete session removes a given day across all symbols, and Edit → Delete range removes a range of quotes and supports multiple symbol selection. Reach for these when you have changed the definition of a composite and want to be certain that nothing from the old definition survives.

A composite has no error state. It is a symbol full of numbers, and wrong numbers look exactly like right ones. Four checks, in increasing order of effort:

  1. The arithmetic identity. If you built the parts so that they must sum to the whole — advances plus declines plus unchanged equals contributing members — then any bar where they do not is proof of a problem. This test costs nothing and catches interrupted scans, mixed flag settings and composites built from different universes.
  2. Contributor stability. Chart the member count. It should change only when the universe genuinely changes. Day-to-day jitter means unaligned calendars.
  3. A hand count on one date. Run an exploration over the same universe on a single date with the same condition as a column, and count the rows. This is the only check that validates the condition rather than the plumbing.
  4. Comparison with something known. If your universe is the members of a published index, your member count should be close to that index’s published membership, and a day the index fell heavily should be a day your declining count dominates.

The formula below automates the first two.

An exploration that reports, for every bar in a range, the four counts, their arithmetic check, the change in contributor count, and the timestamp of the scan that produced them.

Complete runnable AFL

composite-audit.afl
/* Composite audit
-------------------------------------------------------------------------
Part 16 - Market Breadth. An EXPLORATION that answers one question:
"is the composite I just built actually right?"
It checks three things that a wrong composite fails and a right one passes:
1. Arithmetic. Advancing + declining + unchanged must equal the number
of contributing members on every single bar. Any other number means
the four composites did not all come from one completed scan.
2. Contributor stability. The member count should change only when the
universe genuinely changes - a listing, a delisting, a symbol added
to the watch list. A count that wobbles day to day is the signature
of unaligned trading calendars.
3. Freshness. atcFlagTimeStamp writes the scan's date and time into the
composite's Full name field, so the last column tells you when these
numbers were produced.
HOW TO RUN IT
Select ~MEMBERS in the Symbol window, set "Apply to" to Current symbol,
set Range to something you can read (30 recent bars is plenty), and
press EXPLORE. Selecting ~MEMBERS matters: Foreign() aligns foreign data
to the CURRENT symbol, so running this on a thinly traded share would
silently delete composite bars that the share did not trade on.
*/
// ---- Configuration -------------------------------------------------------
CompositeAdvancing = "~ADV";
CompositeDeclining = "~DEC";
CompositeUnchanged = "~UNC";
CompositeMembers = "~MEMBERS";
ShowOnlyProblems = ParamToggle( "Show only problem bars", "No|Yes", 0 );
// ---- Read the composites back -------------------------------------------
Adv = Nz( Foreign( CompositeAdvancing, "V" ) );
Dec = Nz( Foreign( CompositeDeclining, "V" ) );
Unc = Nz( Foreign( CompositeUnchanged, "V" ) );
Members = Nz( Foreign( CompositeMembers, "V" ) );
Mismatch = Adv + Dec + Unc - Members;
MemberChange = Members - Ref( Members, -1 );
// A bar is suspicious if the arithmetic fails, or if the contributor count
// moved. The second test is deliberately strict: it is there to make you look,
// not to make you panic.
Suspicious = Mismatch != 0 OR IsTrue( MemberChange != 0 );
if( ShowOnlyProblems )
Filter = Suspicious;
else
Filter = 1;
// ---- Output --------------------------------------------------------------
AddColumn( Members, "Contributors", 1.0 );
AddColumn( MemberChange, "Change", 1.0,
IIf( IsTrue( MemberChange != 0 ), colorRed, colorDefault ) );
AddColumn( Adv, "Advancing", 1.0 );
AddColumn( Dec, "Declining", 1.0 );
AddColumn( Unc, "Unchanged", 1.0 );
AddColumn( Mismatch, "Adv+Dec+Unc-Contributors", 1.0,
IIf( Mismatch != 0, colorRed, colorDefault ) );
AddTextColumn( FullName(), "Composite full name (scan time stamp)" );
// Colour is never the only carrier of meaning here: the numbers themselves
// say whether a row is wrong, and a zero in the check column means correct.
SetSortColumns( 2 );

Download composite-audit.afl67 lines

It reads the same four composites with Foreign(), forms Mismatch and MemberChange, and emits one row per bar. ParamToggle lets you switch between listing every bar and listing only the bars that failed a check, which matters once you are auditing twenty years of history. The last column shows FullName() — the current symbol’s full name — which for a composite built with atcFlagTimeStamp is the date and time of the scan.

Select ~MEMBERS, set “Apply to” to Current symbol and Range to 30 recent bars, and press Explore. You should get thirty rows, a mismatch column of zeros, and a change column of zeros. Turn the parameter to Yes and set Range to All quotations: an uneventful history returns no rows at all.

  • Every row shows a mismatch equal to the member count. One of the four composites does not exist, so Nz() is supplying zeros for it. Check the spelling of the ticker names.
  • The mismatch is non-zero only before a certain date. Your last scan used a shorter range than the one before it, so the early history is left over from an older run.
  • Running it on a share instead of on ~MEMBERS. Foreign() aligns to the current symbol, so a share that was suspended for a week silently removes that week from the audit.

Add a column showing the member count as a fraction of the number of symbols in the watch list you scanned, so a member count that is right but systematically low — because a third of your universe had not listed yet — becomes visible as well.

Cost, and the alternative you will meet later

Section titled “Cost, and the alternative you will meet later”

Every AddToComposite call is a cross-symbol access, and the multi-threading documentation is explicit that any access to a symbol other than the current one takes a global lock and may impact performance. It recommends reducing the use of AddToComposite and Foreign() in favour of static variables where you can. In practice a scan writing eight composites over a few hundred symbols is still quick; a scan writing eighty is not.

Two related facts belong here. AddToComposite internally requires all bars, so a formula containing it cannot benefit from QuickAFL — which is why the composite is always updated over the entire data range regardless of the visible bars. A side effect is that Tools → Check and Profile may report that such a formula references future bars. The Knowledge Base states this is a false alarm caused by that all-bars request, and that it only appears when atcFlagEnableInBacktest is set, because Check and Profile evaluates in the backtest state.

The alternative is StaticVarAdd(), which performs the same additive accumulation into a static variable rather than into a database symbol, and is documented as faster. It is not a drop-in replacement: static variables live only as long as AmiBroker is running, so nothing persists between sessions unless you arrange it. Part 13 introduces static variables for cross-sectional work and Part 36 covers them in depth. For breadth series that you want to keep, a composite is the right tool precisely because it is stored.

AddToComposite() turns a single-symbol formula into a market-wide statistic by accumulating each symbol’s contribution into an artificial symbol. It runs only in Scan mode unless you opt in with a flag, and the flags decide whether your composite is replaced or doubled, whether it can feed itself, and whether you can tell how old it is. Its correctness depends on something outside the formula — whether every member is aligned to a common calendar — and on something you have to do by hand: re-running the scan whenever the data changes. Because a composite has no error state, verification is not optional, and the cheapest verification is to design the measures so that they must add up.

Check your understanding

Question 1. You run a composite-building formula from a chart pane and nothing appears in the symbol tree. What is the most likely explanation?
Show the answer and why

Answer: AddToComposite does nothing in indicator mode unless atcFlagEnableInIndicator is set

AddToComposite detects its context. Indicator and Commentary are deliberate no-ops, which is what allows the scan code and the chart code to live in one file.

Question 2. Which flag expression rebuilds a composite from scratch on every scan, keeps it out of its own universe, and records when it was built?
AddToComposite( values, "~X", "V", /* flags */ );
Show the answer and why

Answer: atcFlagDeleteValues | atcFlagCompositeGroup | atcFlagTimeStamp

Those three are 1 + 2 + 4, which is the value of atcFlagDefaults. Written out, removing one becomes a visible decision rather than an accident.

Question 3. Your member-count composite jitters between 480 and 512 from one bar to the next. What does that indicate?
Show the answer and why

Answer: Members are on different trading calendars, so different subsets contribute to different bars

That is the documented reason "Pad and align all data to reference symbol" exists. Until the calendars are reconciled, every percentage built on that count divides by a moving denominator.

Question 4. Which of these will leave you looking at stale composite values? Select all that apply.
Show the answer and why

Answer: Downloading new end-of-day quotes and then opening the breadth chart, Re-running the scan with a shorter Range than the previous run, Changing the definition of the condition without rebuilding over the full history

Composites are stored data and are rebuilt only over the range you scan. atcFlagTimeStamp does not prevent staleness - it is how you detect it.

Question 5. Why must a formula not write to a composite and read the same composite back in the same scan?
Show the answer and why

Answer: The composite is incomplete during the run, so the value read depends on how far through the symbol list the scan has got

Accumulation happens symbol by symbol. Write in one stage and read in the next - by re-running, by #pragma sequence, or from the Batch window.

Sources for this lesson

10 verified · checked 2026-08-31

  1. 01AFL Function Reference - AddToCompositeamibroker.com/guide/afl/addtocomposite.html2026-08-31
  2. 02AmiBroker User's Guide - Calculating multiple-security statistics with AddToCompositeamibroker.com/guide/a_addtocomposite.html2026-08-31
  3. 03AmiBroker User's Guide - Analysis settings (Pad and align all data to reference symbol)§ General tabamibroker.com/guide/w_settings.html2026-08-31
  4. 04AmiBroker User's Guide - New Analysis window§ #pragma sequence and Run Sequenceamibroker.com/guide/h_newanalysis.html2026-08-31
  5. 05AmiBroker User's Guide - Multi-threading in AmiBrokeramibroker.com/guide/h_multithreading.html2026-08-31
  6. 06AmiBroker Knowledge Base - QuickAFLamibroker.com/kb/2008/07/03/quickafl2026-08-31
  7. 07AFL Function Reference - Foreignamibroker.com/guide/afl/foreign.html2026-08-31
  8. 08AFL Function Reference - StaticVarAddamibroker.com/guide/afl/staticvaradd.html2026-08-31
  9. 09AFL Function Reference - _exitamibroker.com/guide/afl/_exit.html2026-08-31
  10. 10AFL Function Reference - Cumamibroker.com/guide/afl/cum.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.