Skip to content
Level 2 · AmiBroker AnalystLessonPart 03 · page 5 of 830 min
30Minutes
13AFL functions
8Sources
StandardRequires
AFL functions taught here13

Importing and Updating Market Data

An empty database is a folder. This lesson fills it, by the two routes AmiBroker provides — a downloader called AmiQuote, and a text importer that will read almost any CSV anybody has ever produced — and then verifies the result, which is the part most people skip and later regret.

There is a habit worth forming here, and it is the reason the lesson ends with a formula rather than with a menu path. An import that completes without an error message is not an import that worked. AmiBroker’s importer is forgiving by design: it quietly repairs some malformed bars, it takes the ticker from the filename when you did not give it one, and it defaults to a separator that is probably not the one in your file. Every one of those behaviours is documented, sensible, and capable of producing a database full of plausible-looking rubbish. So you check.

AmiQuote is a separate program, bundled with the AmiBroker installer, that downloads quotes from public web sources into text files and then hands them to AmiBroker over automation. It lives in an AmiQuote subfolder of the main AmiBroker directory.

The current version is 4.40, released 9 July 2026, with a universal 32/64-bit installer. The 64-bit build needs the Microsoft Visual C++ 2022 runtime, which the setup usually fetches for you.

The sources documented in the official AmiQuote Read Me are: historical end-of-day data from Yahoo Finance; fundamental data from Yahoo; end-of-day and current-day data from Tiingo (needs an API token); end-of-day data from Quandl (needs an API key); end-of-day data from Stooq; historical end-of-day and intraday forex from FinAm; and any web source with a REST-like CSV API, through the user-definable data source mechanism. Google Finance and BarChart were built-in sources once and were removed in version 4.00.

Two warnings about that list.

AmiQuote works from a .TLS file: plain text, one ticker per line, saved with that exact extension or AmiQuote will not load it. AmiQuote ships lists for the main NYSE and NASDAQ indices and several European markets, and version 4.30 added a Warsaw Stock Exchange symbol list to its ticker-list downloader.

Yahoo uses suffixes for non-US stocks — .L for London, .AX for Australia, .TO for Toronto, .DE for XETRA, .HK for Hong Kong, .PA for Paris, and around forty more — and a caret prefix for indices. A ticker list for a non-US market needs the suffixes, and this is the most frequent cause of “AmiQuote downloaded nothing for my symbols”.

The quickest route, straight from the guide: run AmiBroker, then choose Tools -> Auto-update quotes (US & Canada). Internally AmiQuote does four things — retrieves the ticker list from AmiBroker, gets the last quotation date already in the database, downloads history from that date to today, and instructs AmiBroker to import.

Other AmiQuote commands worth knowing: Edit -> Add tickers takes space-separated symbols; only marked (check-marked) tickers are downloaded, controlled by the Edit -> Mark all / Unmark all / Toggle family; View -> Refresh re-applies the date settings and re-marks everything; Tools -> Get tickers from AmiBroker fills the list from the open database; and Tools -> Settings sets the destination folder and the file-writing mode. That last one has a default worth understanding: historical files are overwritten while daily files are appended, which is how repeated daily downloads accumulate into a history.

AmiQuote imports into whichever database is open in AmiBroker at the time. With several AmiBroker instances running it talks to the one launched first.

Split adjustment, and the file that controls it

Section titled “Split adjustment, and the file that controls it”

This is the most consequential AmiQuote detail in the whole lesson, and it is not in the AmiQuote interface at all. It is in a format file.

AmiQuote writes .AQH files for historical downloads, and AmiBroker parses them with aqh.format in the Formats folder of the main AmiBroker directory. Its default field list is:

$FORMAT Date_DMY,Open,High,Low,Close,Skip,Volume
$SEPARATOR ,
$AUTOADD 1
$CONT 1

The Skip in position six is the adjusted-close column being thrown away.

File -> Import Wizard. A three-step guided importer for text and CSV quote files, aimed at people who do not want to write a format definition. It also has a hidden virtue: it can save what you built as a reusable format file.

Step 1, picking the files. Press Pick files and multi-select with Ctrl or Shift. The chosen files are listed at the bottom of the wizard.

Step 2, defining fields. One Column N combo per column, with a sample of the first few lines of the first file shown so you can see what you are mapping. The field types the wizard offers are Ticker, YMD, DMY, MDY, Open, High, Low, Close and Volume. A More columns checkbox reveals combos beyond the first seven. Also on this step: Group, Watch list, Separator, Skip lines, Log errors, Automatically add new symbols, Calculate composites, Allow negative prices and No quotation data.

Step 3, additional settings. This is where the wizard’s one trap lives.

Date parsing is generously forgiving: two- and four-digit years, months as numbers or three-letter codes, separators of slash, backslash, hyphen or nothing at all. You only have to declare the order — DMY, MDY or YMD. All of 20001231, 2000-12-31, 2000/12/31, 2000-Dec-31 and 00\12\31 are accepted as 31 December 2000 under YMD.

The wizard is explicitly documented as offering “only a subset of features available in the ASCII importer… provided for novice users only”. Anything beyond ticker, date and OHLCV needs a format file.

File -> Import ASCII, driven by format definition commands that begin with $. Commands may be embedded in the data file itself or stored in a separate .format file for reuse. Format files live in the Formats subdirectory of AmiBroker’s working directory. The default one is default.format, and AmiBroker reads it first, then your chosen file — with commands embedded in the data file overriding the defaults.

If no default.format exists, the built-in default is $FORMAT DATE_USA, OPEN, HIGH, LOW, CLOSE, VOLUME with a space separator and every other option at zero.

Command Default What it does
$FORMAT <fields> The order and type of fields on each line
$SEPARATOR <char> space The field separator
$SKIPLINES <n> 0 Header lines to ignore
$AUTOADD <0 or 1> 0 Create symbols that do not already exist
$OVERWRITE <0 or 1> 0 Update group/market/industry/full name on existing symbols too
$NOQUOTES <0 or 1> 0 Import ticker-and-name-only files with no price validation
$DEBUG <0 or 1> 0 Log errors to import.log
$BREAKONERR <0 or 1> 0 Stop on the first error
$ALLOWNEG <0 or 1> 0 Permit negative prices and disable OHLC repair
$CONT <0 or 1> 0 Give new symbols continuous-quotation mode, which enables candlesticks
$GROUP / $MARKET / $INDUSTRY / $WATCHLIST <n> File newly added symbols into a category
$PRICEFACTOR / $VOLFACTOR <n> 1 Multipliers
$TIMESHIFT <hours> 0 Shift intraday timestamps; fractional and negative allowed

Field names for $FORMAT include the three date orders DATE_MDY, DATE_DMY and DATE_YMD (with aliases DATE_USA, DATE_CDN and DATE_INT), TIME, the identity fields NAME (alias TICKER), ALIAS and FULLNAME, the price fields OPEN, HIGH, LOW, CLOSE, ADJCLOSE, OPENINT and VOLUME, the category fields MARKET, GROUP, WATCHLIST, INDUSTRY, INDUSTRYNAME and SECTORNAME, contract specifications such as TICKSIZE and POINTVALUE, and SKIP — which is how you ignore a column, there being no positional “omit”.

A working example. Given a CSV that looks like this:

Ticker,Date,Open,High,Low,Close,Volume
AAPL,2025-01-02,248.93,249.10,241.82,243.85,55740700
AAPL,2025-01-03,243.36,244.18,241.89,243.36,40244100

the format file is:

$FORMAT Ticker,Date_YMD,Open,High,Low,Close,Volume
$SEPARATOR ,
$SKIPLINES 1
$AUTOADD 1
$CONT 1
$DEBUG 1

Six lines, and five of them are there because a default would otherwise catch you out.

Five documented behaviours that will surprise you

Section titled “Five documented behaviours that will surprise you”

The default separator is a space, not a comma. Forgetting $SEPARATOR , is the classic first failure, and it usually produces zero imported bars rather than an error.

Without a ticker field, the filename becomes the ticker. Importing C:\My data\AAPL.CSV creates or updates the symbol AAPL. This is a genuinely useful feature for one-symbol-per-file data — and a disaster if your files are called download1.csv and download2.csv.

$AUTOADD defaults to 0, so an import into an empty database with no $AUTOADD 1 adds nothing at all, silently, because there are no existing symbols to update.

Without $ALLOWNEG, AmiBroker repairs your bars. The documented fix-up is: if open is zero, set it to close; if high is below the greater of open and close, raise it; if low is zero, set it to the lesser of open and close. Setting $ALLOWNEG 1 disables the whole OHLC relationship check and permits negative prices, which is what you want for spread series.

Fractions are accepted. 5 1/3 parses as a price, provided the whole part is followed by at least one space. On space-separated data this can silently mangle your fields.

The distinction matters because the two have different failure modes.

Updating means adding new bars to the end of an existing history. AmiQuote’s auto-update does this: it reads the last date already present and downloads from there. It is fast and it is what you do daily.

Re-importing means replacing history you already have. You do it when the source corrects its data, when a split has been applied retroactively, or when you change aqh.format and want the whole history re-parsed under the new field mapping. AmiQuote’s default write mode overwrites historical files, so a fresh download from an earlier start date genuinely replaces rather than appends.

One symbol-level setting interacts with all of this: Use only local database for this symbol, in Symbol -> Information. It is checked by default for symbols added by ASCII import — including AmiQuote downloads — into a real-time database, deliberately, so the plug-in cannot overwrite the data you imported. $USEONLYLOCALDB 0 overrides it at import time. On a purely local database it makes no difference.

Answer, for every symbol you just touched, six questions that between them catch nearly every import defect: does it have bars, over what dates, are the four prices internally consistent, are any prices zero or negative, is volume present, and is there a single-bar move so large that it demands an explanation.

Complete runnable AFL

import-health-check.afl
// ===========================================================================
// Import health check
// Run this immediately after any import or update. It asks six questions of
// every symbol and prints the answers as one row each, so that a defect in the
// data is found before it becomes a conclusion about a market.
//
// HOW TO RUN
// Analysis window: Apply to = All symbols (or a watch list via Filter),
// Range = All quotations, then Explore.
//
// WHAT EACH COLUMN MEANS
// Bars how many bars the symbol holds inside the range
// First / Last the ends of the stored history
// OHLC errors bars where the four prices contradict each other
// Non-positive bars carrying a zero or negative price
// Zero volume bars reporting no traded volume
// Flat bars bars with no range at all: open, high, low and close equal
// Largest move the biggest single-bar percentage change against the
// previous close, as an absolute value
//
// ASSUMPTIONS, STATED SO THEY CAN BE CHECKED
// - None of these counts is proof of a defect. Zero volume is normal for
// many index and FX series; a flat bar is normal for an illiquid symbol
// that did not trade. Every non-zero count is a reason to open the symbol
// in the Quote Editor and look, not a reason to delete anything.
// - The percentage-move test compares against the previous close, so the
// first bar of each symbol is excluded from it by construction.
// - Split and dividend adjustments produce genuine large moves in an
// unadjusted series. A large "Largest move" on a known split date is the
// data telling the truth, not lying.
// ===========================================================================
Filter = Status( "lastbarinrange" );
SetOption( "NoDefaultColumns", True );
BarsInRange = Cum( 1 );
FirstBarDate = ValueWhen( BarsInRange == 1, DateTime() );
// A bar is internally inconsistent when the high is not the highest price on
// the bar, or the low is not the lowest. AmiBroker's ASCII importer quietly
// repairs some of these on import unless $ALLOWNEG is set, so anything that
// survives to here came in through a path that did not repair it.
InconsistentBar = High < Low
OR Close > High OR Close < Low
OR Open > High OR Open < Low;
NonPositivePrice = Open <= 0 OR High <= 0 OR Low <= 0 OR Close <= 0;
NoVolume = Volume <= 0;
FlatBar = High == Low AND Open == Close;
// Percentage change against the previous close. Nz() stops a missing previous
// close from propagating a Null through the whole column.
PreviousClose = Ref( Close, -1 );
PercentMove = IIf( PreviousClose > 0,
100 * ( Close - PreviousClose ) / PreviousClose,
0 );
LargestMove = Highest( Abs( Nz( PercentMove ) ) );
AddTextColumn( Name(), "Symbol", 1.0, colorDefault, colorDefault, 80 );
AddColumn( BarsInRange, "Bars", 1.0 );
AddColumn( FirstBarDate, "First bar", formatDateTime );
AddColumn( DateTime(), "Last bar", formatDateTime );
// The background colour is a convenience, never the message: the count itself
// is the evidence and is readable without seeing any colour at all.
AddColumn( Cum( InconsistentBar ), "OHLC errors", 1.0, colorDefault,
IIf( Cum( InconsistentBar ) > 0, colorRose, colorDefault ) );
AddColumn( Cum( NonPositivePrice ), "Non-positive", 1.0, colorDefault,
IIf( Cum( NonPositivePrice ) > 0, colorRose, colorDefault ) );
AddColumn( Cum( NoVolume ), "Zero volume", 1.0 );
AddColumn( Cum( FlatBar ), "Flat bars", 1.0 );
AddColumn( LargestMove, "Largest move %", 1.1 );
// Worst first: sort descending on the OHLC error count.
SetSortColumns( -5 );

Download import-health-check.afl75 lines

The formula is one exploration producing one row per symbol, built in four movements.

The framing. Filter = Status("lastbarinrange") collapses the whole history to one row, and SetOption("NoDefaultColumns", True) removes the automatic Ticker and Date/Time columns so that the export is self-describing.

The four defect tests, each a Boolean array. InconsistentBar asks whether the four prices on a bar contradict each other — high below low, or close or open outside the high-low range. NonPositivePrice catches zeros and negatives. NoVolume catches missing volume. FlatBar catches bars with no range at all. Each is one Boolean per bar.

The counts. Cum() of a Boolean array is a running total of the bars where it was true, so on the last bar it is the total count over the whole history. That is the idiom that turns “which bars are broken” into “how many bars are broken”, which is what a per-symbol report needs.

The largest move. Ref(Close, -1) is the previous bar’s close. The percentage change is guarded by IIf, so a zero or missing previous close contributes zero rather than infinity, and Nz() catches any Null that survives. Highest() of the absolute value gives the running maximum, which at the last bar is the largest single-bar move in the history.

Function What it gives you
Cum(condition) A running count of the bars where the condition was true
Ref(array, -1) The array shifted back one bar — the previous bar’s value
Nz(x) Converts Null, NaN and infinity to zero, stopping them propagating
IIf(cond, a, b) Element-by-element choice between two arrays
Highest(array) The running maximum from the start of the data to each bar
Abs(array) Absolute value, element by element
  1. Deliberately break one symbol. Import a two-line CSV for a scratch ticker in which the high is below the low, with $ALLOWNEG 1 set so AmiBroker does not repair it. The OHLC errors column should report exactly the number of bad bars you created. If it reports zero, the importer repaired them — which is itself worth knowing.
  2. Run it on the sample DJIA database. You have a known-good dataset there. Anything the health check flags on it is either a real defect in the sample data or a bug in your understanding of the formula, and either is worth ten minutes.
Symptom Cause
Every symbol shows a huge “Largest move” Splits in an unadjusted series, or a price-factor mismatch between files
Zero-volume count equals the bar count Normal for indices and many FX series; not a defect
All counts are zero and all bar counts are 1 Range is set to a recent-bars value rather than All quotations
Bar counts far lower than expected The import added far fewer bars than you think, or $SKIPLINES is wrong
No rows at all The import added no symbols — $AUTOADD is probably 0

Add a seventh test: bars whose date is not strictly greater than the previous bar’s date. Duplicated or out-of-order timestamps are a real and nasty import defect, and they are invisible on a chart because AmiBroker draws them in stored order. DateTime() and Ref() are all you need. Later parts turn checks like this into a general data-integrity tool.

Set $DEBUG 1 and AmiBroker writes import.log into its main directory. It is plain text; open it in any editor. That log plus the health check answers most import questions faster than any amount of staring at the CSV.

Two more settings that cause imports to misbehave in ways that look like data problems. Tools -> Preferences, Miscellaneous tab, has Case sensitive ticker symbols. With it checked, INTC, Intc and iNTc are three different symbols. The guide’s own advice: “If your exchange does not use case-sensitive tickers, please make sure it is UNCHECKED.” Getting it wrong silently duplicates every symbol on the next import. And both official pages that mention it agree that tickers should be entered in capitals for import to work properly.

You have three routes into a database now, and a sense of which one fits: AmiQuote for free end-of-day updates on a schedule, the Import Wizard for a one-off CSV, and the ASCII importer with a saved .format file for anything you will do repeatedly or anything the wizard cannot express.

You know the specific defaults that catch people — a space separator, $AUTOADD 0, the ticker taken from the filename, the wizard discarding your format unless you tick a box, and split-adjusted rather than dividend-adjusted closes arriving from Yahoo because of one Skip in a format file.

Most of all, you have a verification step. From here on, “I imported the data” and “the data is right” are two different claims, and you have a formula that turns the second one into evidence.

Check your understanding

Question 1. You import a CSV with no ticker column, from a file called quotes-2025.csv. What symbol does AmiBroker create?
Show the answer and why

Answer: A symbol called quotes-2025

When no field in $FORMAT names the ticker, the importer uses the file name without path or extension. That is deliberate and useful for one-symbol-per-file data, and disastrous for generically named downloads. It is also silent — you get a symbol, just not the one you wanted.

Question 2. In `import-health-check.afl`, what does `Cum( InconsistentBar )` evaluate to on the last bar of a symbol?
InconsistentBar = High < Low OR Close > High OR Close < Low OR Open > High OR Open < Low;
AddColumn( Cum( InconsistentBar ), "OHLC errors", 1.0 );
Show the answer and why

Answer: The total number of inconsistent bars in the whole history

Cum() is a running sum. Applied to a Boolean array it counts the bars where the condition held, so its value on the final bar is the total over the history. Turning a per-bar test into a per-symbol count is what makes an exploration a report rather than a list.

Question 3. Which of these are true of the ASCII importer defaults? Select all that apply.
Show the answer and why

Answer: $AUTOADD defaults to 0, so unknown symbols are not created, Error logging to import.log is off unless $DEBUG 1 is set, Without $ALLOWNEG, AmiBroker adjusts malformed OHLC values rather than rejecting the bar

The default separator is a space, not a comma — which is why $SEPARATOR , appears in almost every real format file. The other three are correct, and together they explain most first-attempt import failures: nothing was added, nothing was logged, and whatever did arrive may have been quietly repaired.

Question 4. True or false: the 10-symbol limit people encounter when downloading with AmiQuote is a restriction of the AmiBroker Standard edition.
Show the answer and why

Answer: False

False. AmiQuote is a separately licensed product, and the 10-symbol cap belongs to its unregistered version across all data sources. It has nothing to do with which AmiBroker edition you own, and no AmiBroker edition removes it — an AmiQuote licence does.

Sources for this lesson

8 verified · checked 2026-08-31

  1. 01AmiBroker User's Guide — Importing data from ASCII filesamibroker.com/guide/d_ascii.html2026-08-31
  2. 02AmiBroker User's Guide — ASCII Import Wizardamibroker.com/guide/w_impwizard.html2026-08-31
  3. 03AmiBroker User's Guide — How to download quotes manually using AmiQuoteamibroker.com/guide/h_amiquote.html2026-08-31
  4. 04AmiBroker User's Guide — How to update US quotes automatically using AmiQuoteamibroker.com/guide/h_amiquote2.html2026-08-31
  5. 05AmiBroker User's Guide — Symbol information windowamibroker.com/guide/w_information.html2026-08-31
  6. 06AmiBroker — Orderamibroker.com/order.html2026-08-31
  7. 07AmiBroker Knowledge Base — AmiQuote and free data from Yahooamibroker.com/kb/2007/08/04/amiquote-and-free-data-from-yahoo2026-08-31
  8. 08AmiBroker User's Guide — How to get quotes from various marketsamibroker.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.