Include Files and Building a Library
AmiBroker gives you two ways to reuse a piece of AFL, and they are not alternatives.
Code snippets are a Formula Editor feature: you select some text, save it
under a name and a key trigger, and afterwards type @trigger or drag it from
the Code Snippets window to paste it into a formula. What lands in the formula
is a copy. Snippets are excellent for boilerplate you are about to modify - the
skeleton of a for loop, the shape of an exploration.
Include files are the opposite. The #include directive does not paste
anything into your saved formula; it tells the AFL preprocessor to merge the
contents of a file into the program at the moment it runs. Change the file and
every formula that includes it changes. That is what makes a library a library.
This lesson is about the second mechanism: how to write the directive, where AmiBroker looks, what the preprocessor does with the result, and how to organise files so that a library you keep adding to does not become a liability.
The two forms of the directive
Section titled “The two forms of the directive”The official page documents two spellings.
A literal path, in double quotes:
Fragment — not a complete formula
#include "C:\AmiBroker\Formulas\Custom\course-library.afl"Or a bare file name in angle brackets, which is looked up in the standard include path:
Fragment — not a complete formula
#include <course-library.afl>The angle-bracket form is the one to prefer for your own library, for the reason the documentation gives: it “makes much shorter to write includes and you can move include folder now without changing all AFL codes using #includes”.
Where the standard include path lives
Section titled “Where the standard include path lives”The standard include path is a preference, set under Tools → Preferences →
AFL. The documentation gives a worked example: with the path set to
C:\AFL\MyIncludes, the directive #include <common.afl> loads
C:\AFL\MyIncludes\common.afl.
What the online documentation does not state is what that setting contains on a fresh install. This course therefore does not tell you a default path - open Tools → Preferences → AFL on your own machine and read it, then either use that folder or point it at one you prefer.
Wherever you point it, do not point it at the Formulas folder that ships with
AmiBroker. The official FAQ is unambiguous about what happens to files there:
formulas supplied with AmiBroker “will be overwritten” by the next upgrade, and
the recommendation is to save your own work “under a new name or (better) in
your own custom subfolder”. A library folder of your own, backed up with the
rest of your work, is the right home.
What the preprocessor actually does
Section titled “What the preprocessor actually does”The preprocessor runs before your formula executes and is, in the words of the
#pragma page, “responsible for inclusion of external files via #include
command”. The result is one merged text, which the AFL engine then compiles and
runs.
From two files to one program
- You press Apply, or a chart refreshesAmiBroker takes the formula text as saved
- The preprocessor reads any #pragma optionsThese must appear before the includes they affect
- Each #include is replaced by the contents of its fileAt the position of the directive, in order
- One merged program existsIncluded text now sits above your own code
- The AFL engine executes itOnce per pane, per symbol, per Analysis step
Three practical consequences follow from that picture.
Includes go at the very top. A function definition must precede its call, and the merged text is what determines “precede”. An include placed halfway down a formula makes its functions unavailable to everything above it.
Scope is decided on the merged text. The rule from the previous lesson - that a name is local or global depending on where it first appears - operates on the merged program, not on the file you are looking at. If your library assigns a global at the top, every later mention of that name in your own formula refers to the library’s variable. This is the whole argument for prefixes.
Caching is on by default. The documentation says AmiBroker “tries to include
only once and cache pre-processed text”, and warns separately that using
#include “may slow down formula execution”. While you are actively editing a
library, the cache can serve you a stale copy. The documented switch is:
Fragment — not a complete formula
#pragma nocache
#include <course-library.afl>Two rules on that directive, both from the official page: it must appear
before any #include commands, and “between #pragma and nocache there
must be exactly SINGLE space”. A second space or a tab silently does nothing.
Turn it on while you are editing the library, and take it out again afterwards,
because disabling caching “may slow down execution of the formula (especially in
indicators)”.
#include_once
Section titled “#include_once”The function reference index lists #include_once as “preprocessor include
(once) command (AFL 2.70)”. Its detail page is behind the licensed-customer
login on amibroker.com, so this course states only what can be confirmed from
sources it could read: the directive exists, it dates from AFL 2.70, and its
purpose is to include a file only if it has not already been included. The 5.10
release notes separately confirm “unlimited nesting of #include and
#include_once statements”.
The situation it is for is easy to describe. Suppose you write a second library that itself includes the first, and a formula includes both. Without protection, the first library’s text is merged twice, and every function in it is defined twice.
Pseudocode — not valid AFL
formula.afl includes analysis-helpers.afl which includes course-library.afl <- first copy includes course-library.afl <- second copyUsing #include_once for library files that other library files might also
pull in removes that possibility. Given that its parameters are not publicly
documented, the safe pattern is the conservative one: use it exactly as you
would use #include, with the same two path forms, and keep your libraries
shallow enough that you would notice if it behaved differently.
When the file is not there
Section titled “When the file is not there”Historically #include failed silently. The current behaviour is documented on
the same page - “#include now reports file(s) not found in regular error
message box” - and the published error is Error 42: the include failed
because the file does not exist, with the file name and the current working
directory in the message.
Read that message rather than guessing. It tells you both what AmiBroker looked
for and where it was standing when it looked, which between them identify almost
every path mistake: a typo, a doubled backslash, a file saved with a .txt
extension by an editor, or an angle-bracket include with no standard include
path set.
One thing that must not go in an include
Section titled “One thing that must not go in an include”The multithreading chapter documents an initialisation idiom: wrapping
first-symbol setup in if( Status( "stocknum" ) == 0 ). AmiBroker “detects such
a statement and runs the very first symbol in one thread only, waits for
completion, and only after completion does it launch all other threads”.
The page then gives an explicit caveat: that statement must not be placed
inside #include. The detection happens on the main formula. Setup code that
must run once, before the other threads start, belongs in the formula itself,
not in your library.
This matters more than it sounds, because “run this once at the start” is exactly the kind of helper people are tempted to move into a library.
Organising the folder
Section titled “Organising the folder”A library that grows without a shape becomes a place where things are hard to find, which is how duplicate definitions get written. The structure this course uses is deliberately flat:
| File | Contents |
|---|---|
course-library.afl |
The functions. Definitions only, one prefix, no side effects beyond a version guard. |
course-library-test.afl |
A formula that calls every function and checks the ones with a knowable answer. |
chart-defaults.afl |
A separate small include for chart housekeeping, with its own prefix. |
Two rules keep it navigable. One prefix per file, so you can tell from a call site which file a function came from. One purpose per file, so that a formula which needs only the chart helpers does not drag in everything else.
Resist the urge to create a file called utilities.afl. Files named after what
they contain stay useful; files named after the fact that they contain
something become the drawer everything ends up in.
Versioning
Section titled “Versioning”Your library will change, and formulas written against an older version will outlive the change. Three cheap habits handle almost all of the consequences.
A version number the code can read. A one-line function returning a number lets a formula state its requirement:
Fragment — not a complete formula
#include <course-library.afl>
if( LibVersion() < 1.00 ){ _TRACE( "This formula needs course-library 1.00 or later" );}A changelog in the file header. Date each release and say what changed, particularly when a function’s meaning changes rather than its name. A function that quietly starts returning a percentage instead of a fraction is the kind of change that breaks charts silently.
An AmiBroker version guard. Version( minrequired ) returns the running
version number, and the documentation notes that passing a minimum “will issue an
error message when running the formula on AB earlier than” that version. If your
library uses something recent - StDev’s Population argument, added in 6.20,
is the case in this part’s library - say so in code rather than in a comment
nobody reads.
Portability, briefly
Section titled “Portability, briefly”If you send someone a .chart file, AmiBroker stores the contents of any
include files inside it and attempts to recreate them on the target machine. The
documentation describes the collision handling: if a different file already
exists at the target, AmiBroker asks whether to replace it, and makes a .bak
backup if you agree. Files included with angle brackets are restored into the
target machine’s standard include folder “even if the standard include folder
path is different on the source machine”.
This is a good reason to use the angle-bracket form and to keep your library
file names distinctive. course-library.afl will not collide with anything;
utils.afl might.
A two-file example
Section titled “A two-file example”Before building the real library, it is worth running the smallest possible include - one file that defines two functions and does nothing else, and one chart formula that uses them. If this pair works on your machine, your paths and your preferences are correct, and the project at the end of this part becomes an exercise in content rather than in configuration.
The include file
Section titled “The include file”Fragment — not a complete formula
// chart-defaults.afl// ---------------------------------------------------------------------------// A deliberately tiny include file, used by Part 11 to demonstrate #include// before the full course library is built.//// Version : 1.00// Requires: AmiBroker 5.30 or later//// Every public name here starts with Demo, so this file cannot collide with// your own variables, with the course library, or with anything AmiBroker// ships. Nothing in this file executes: it only defines.// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------// DemoHeaderText( ExtraText )// Purpose : One consistent first line for every chart title you write.// Inputs : ExtraText - STRING appended after the symbol and interval// Returns : STRING// Notes : Interval( 2 ) returns the interval's NAME. The official page// warns never to compare that name in code, because it is// translated in localised builds - displaying it is fine.// ---------------------------------------------------------------------------function DemoHeaderText( ExtraText ){ local Result;
Result = Name() + " - " + Interval( 2 ) + " - " + ExtraText;
return Result;}
// ---------------------------------------------------------------------------// DemoPercentOf( PartArray, WholeArray )// Purpose : Express one array as a percentage of another without producing// an infinity when the divisor is zero.// Inputs : PartArray, WholeArray - ARRAYs// Returns : ARRAY, percent, Null where the result would not be finite// ---------------------------------------------------------------------------function DemoPercentOf( PartArray, WholeArray ){ local Quotient; local Result;
Quotient = PartArray / WholeArray; Result = IIf( IsFinite( Quotient ), 100 * Quotient, Null );
return Result;}
// End of chart-defaults.aflNote what is not in it: no Plot, no Title, no assignments at global level. It
defines two functions and stops. An include file with side effects runs those
side effects in every formula that includes it, which is rarely what anyone
intended.
The formula that uses it
Section titled “The formula that uses it”Complete runnable AFL
// chart-with-include.afl// Part 11 - Include Files and Building a Library//// GOAL// Show a formula that is mostly other people's code - specifically, your own// code, kept in one place. Everything the chart needs beyond price comes from// chart-defaults.afl.//// WHAT IT DRAWS// The candle body as a percentage of the whole bar's range. A high reading is// a bar that closed a long way from where it opened relative to how far it// travelled; a low reading is a bar with long wicks and little net movement.// It is a description of one bar, not a signal.//// PREREQUISITE// chart-defaults.afl must be reachable. Either put it in the folder named in// Tools -> Preferences -> AFL as the standard include path and keep the line// below, or replace the line with a full path in quotes and SINGLE// backslashes. If you get Error 42, the file is not where you said it is.
#include <chart-defaults.afl>
_SECTION_BEGIN( "Body size" );
Plot( Close, "Close", colorDefault, styleCandle );
BodySize = abs( Close - Open );BarRange = High - Low;BodyShare = DemoPercentOf( BodySize, BarRange );
Plot( BodyShare, "Body as % of range", colorBlue, styleLine | styleOwnScale );
_N( Title = DemoHeaderText( "candle body as a percentage of the bar's range" ) + "\n" + WriteIf( IsNull( BodyShare ), "No reading at the selected bar: the bar has no range.", "Selected bar body is " + NumToStr( BodyShare, 1.1 ) + "% of its range." ) );
_SECTION_END();How it works
Section titled “How it works”The #include line is the first executable thing in the file, so both functions
exist by the time anything calls them. DemoPercentOf does the arithmetic and
converts a non-finite result to Null, which is what a bar with no range - a
limit-locked future, a halted share, a padded non-trading day - would otherwise
produce. DemoHeaderText builds the first line of the title, so that every
chart you write with this include starts the same way.
Key functions
Section titled “Key functions”Interval( 2 )returns the interval’s name as a string, such as “Daily” or “15-minute”. The official page carries a caveat worth repeating: never compare that string in code, because localised builds translate it. Display it; testInterval() == inWeeklyinstead.abs( x )returns the absolute value, used here so that an up bar and a down bar of the same size report the same body share.Version( minrequired )is the version guard described above.
Expected result
Section titled “Expected result”A candle chart with a second line on its own scale showing the body as a percentage of the range. Values sit between 0 and 100 by construction. Bars with long wicks read low; bars that opened at one extreme and closed at the other read close to 100. The title names the symbol and the interval, then reports the selected bar’s reading in words.
Test it
Section titled “Test it”Edit chart-defaults.afl - change the separator in DemoHeaderText from -
to | - save it, and refresh the chart. If the title does not change, the
preprocessor is serving you a cached copy: add #pragma nocache above the
include, with exactly one space, and try again. Put the change back afterwards.
Then deliberately break the path. Rename the include file, refresh, and confirm that you get Error 42 naming the file it could not find. Knowing what that error looks like before you need to diagnose it is worth the thirty seconds.
Common errors
Section titled “Common errors”| Symptom | Cause |
|---|---|
| Error 42 | The path is wrong, the standard include path is unset, or the file has a different extension |
| Syntax error at the first call | The #include is below the code that uses it |
| Edits to the include have no effect | Preprocessor caching. Add #pragma nocache while editing |
#pragma nocache appears to do nothing |
Two spaces between the words. The documentation requires exactly one |
| Error 34 after adding a second library | Two files define the same name, or a function name collides with one of your globals |
Extension
Section titled “Extension”Add a third function to chart-defaults.afl that returns the bar’s close
position within its range as a percentage, and use it as a second line. Then
create a second formula that includes the same file and uses only the header
function. Change the header format once and confirm that both formulas change -
that is the property you are buying.
#include merges a file into your formula before it runs, which means order
matters, scope is decided on the merged text, and a cached copy can lie to you
while you edit. The angle-bracket form keeps paths out of your formulas at the
cost of one preference setting. Error 42 tells you exactly what could not be
found. Keep libraries in a folder AmiBroker’s installer will not overwrite, one
prefix per file, with a version number the code can read and a test formula
beside it.
Which leaves one question outstanding: what happens when the code inside the library meets data it was not designed for. That is the next lesson.
Check your understanding
Sources for this lesson
9 verified · checked 2026-08-31
- 01AFL Function Reference -amibroker.com/guide/afl/_include.html2026-08-31
- 02AFL Function Reference -amibroker.com/guide/afl/_pragma.html2026-08-31
- 03AmiBroker AFL Function Reference index§ #include_once entryamibroker.com/guide/a_funref.html2026-08-31
- 04AmiBroker User's Guide - Charts, sheets and layouts§ Portable chart files and include filesamibroker.com/guide/h_sheets.html2026-08-31
- 05AmiBroker User's Guide - Drag and drop, formulas and parameters§ Adding your own formulas to the Charts treeamibroker.com/guide/h_dragdrop.html2026-08-31
- 06AmiBroker User's Guide - Multithreading§ Initialisation using Status("stocknum")amibroker.com/guide/h_multithreading.html2026-08-31
- 07AmiBroker User's Guide - Using code snippetsamibroker.com/guide/h_snippets.html2026-08-31
- 08AmiBroker User's Guide - Error and warning messagesamibroker.com/guide/errors2026-08-31
- 09AFL Function Reference - Versionamibroker.com/guide/afl/version.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.