Skip to content
Level 5 · Real-Time AmiBroker UserLessonPart 18 · page 5 of 526 min
26Minutes
11AFL functions
9Sources
StandardRequires
AFL functions taught here11

Free and End-of-Day Sources with AmiQuote

This is the lesson that makes the rest of the course free. By the end of it you will have a repeatable routine that fills an AmiBroker database with end-of-day price history at no cost, verifies that the routine worked, and knows which of its results to distrust.

It is also the lesson where the course is most careful about what it claims. Free data comes from public web sources that change without notice, and AmiQuote’s own history is a record of adapting to exactly that. Two of its documented sources were removed in a single version; its most important source stopped working, was replaced by a workaround, and then started working again three versions later. Anything written about free data that does not carry a version number is unreliable, so this lesson carries them.

AmiQuote is a separate program, not a feature of AmiBroker. It lives as Quote.EXE in the AmiQuote subfolder of the AmiBroker installation, and it does three things in sequence: build a list of URLs from your ticker list and date range, download the results into text files with .AQ-prefixed extensions, and then instruct AmiBroker over OLE automation to import them.

What happens when you press the green arrow

  1. Ticker listA .TLS text file, one symbol per line, or symbols pulled from AmiBroker
  2. URL generationOne request per marked ticker, built from source, symbol and date range
  3. DownloadResults written as .AQH, .AQD or .AQI text files in the destination folder
  4. Automatic importAmiQuote drives AmiBroker over OLE; failures are logged to import.log
  5. Bars in your databaseParsed according to the matching .format file
Five stages, each of which can fail independently. Knowing which one failed is most of the diagnosis.

Three facts about it are worth fixing early.

It is licensed separately from AmiBroker. It is bundled in the trial installer and in the top-tier product bundle, but a plain AmiBroker licence does not cover it, and the features page footnotes the free download features with exactly that condition. Registration is also separate: Help -> Register AmiQuote inside AmiQuote itself.

It imports into whichever database is open in AmiBroker at import time. With several AmiBroker instances running it talks to the one that was launched first. This is a real source of “I updated the wrong database” incidents.

It is only a downloader. If a quote is wrong, the source sent it wrong. The documented way to check is to open the vendor’s own page for the same symbol and compare. That distinction matters for every defect discussed later in this lesson.

The current version is AmiQuote 4.40, released 9 July 2026. On AmiBroker 7.00 Help -> Check for and Install updates is the documented update path. Full documentation of the newer features exists only in the ReadMe.html file installed in the AmiQuote folder — and that file needs its pics subfolder beside it, so open it where it was installed rather than copying it elsewhere.

The last complete published list is the official AmiQuote 4.00 Read Me, dated 23 May 2019. Everything after that comes from release announcements. The complete list for 4.40 exists only in the installed Read Me, which is the file to trust on your own machine.

Source What it provides Notes
Yahoo! Finance historical End-of-day history See the version history below — this one has a story
Yahoo! Finance fundamental Fundamental data Basic mode 200 symbols per request; Extra and Key Statistics are one symbol per request and registered-version only
Tiingo End-of-day and current-day Requires an API token
Quandl End-of-day See the caution below
Stooq.pl End-of-day Downloader re-implemented in 4.30 after breaking changes, with a deliberate 3-second delay
FinAm Forex end-of-day and intraday Intraday is registered-version only
User-definable sources Anything with a CSV-over-HTTP API The headline 4.x feature; see below

Two sources were removed in AmiQuote 4.00: the built-in Google Finance source and the built-in BarChart.com source. BarChart can be re-added as a user-defined source.

The Yahoo story, and why version numbers matter here

Section titled “The Yahoo story, and why version numbers matter here”

This sequence is the clearest illustration in the whole course of why undated advice about free data is worthless:

  • 4.16 (September 2024) — the built-in Yahoo Historical source began showing a “defunct” message. A “Yahoo Finance Workaround” user data-source definition shipped alongside it.
  • 4.17 (November 2024) — the workaround improved, with better error handling, longer history and a 300-requests-per-minute cap to avoid Yahoo’s “Too many requests” response.
  • 4.18 (May 2025) — automatic rotation of common user-agent strings, to avoid Yahoo blocking the downloader.
  • 4.19 — the built-in Yahoo Historical source was re-implemented and works again, with seven-significant-digit rounding to correct bad values coming back from the Yahoo API. This is the version shipped inside AmiBroker 7.00.1.

Every forum post, blog entry and video produced between those two points tells you that Yahoo is dead and that you must install a workaround. On AmiQuote 4.19 and later that advice is wrong, and following it gets you a duplicated, unnecessary data source. Check your AmiQuote version before believing anything about Yahoo.

The most durable feature in AmiQuote 4.x is that you can define a source yourself, so that a vendor change or a new vendor no longer requires a new AmiQuote build. A definition is created under Data sources -> New and needs a name, a URL template with {token} placeholders — {symbol}, {from_ymd}, {api_key}, and later additions {from_utime}/{to_utime} and {from_yyyymmdd}/{to_yyyymmdd} — and a list of supported intervals. Downloads are CSV only.

Two smaller options in that dialog repay attention. Error message prefix lets you give AmiQuote a string to look for in the server’s response, so that a vendor error is detected and the item is marked failed instead of being imported as garbage. And Convert ISO datetime into date and time columns splits a combined timestamp into the two columns the importer expects.

Definitions are plain XML .ADS files, exported and imported through the same menu, which is the intended way to share one. Example definitions ship in the DataSources subfolder, including AlphaVantage and a Tiingo intraday definition. Deleting a user-defined source cannot be undone, and a newly imported source is auto-selected in the Source combo — which can silently change what you are about to download.

The manual route, which is worth doing once even though you will use the automatic one afterwards:

  1. Prepare a ticker list. A .TLS file is plain text, one ticker per line, saved with that exact extension by a plain text editor. AmiQuote ships lists for the main US indices and several European markets. Non-US Yahoo symbols take a suffix — .L for London, .DE for XETRA, .AX for Australia, .TO for Toronto and around forty others — and Yahoo indices take a ^ prefix.
  2. Open it in AmiQuote with File -> Open.
  3. Choose the Source and the date range.
  4. Check what is marked. Only tickers with a checkmark are downloaded. Edit -> Mark all, Mark selection and their opposites control this, and View -> Refresh re-marks everything after a date-range change.
  5. Press the green arrow (File -> Start Download).

With Automatic import ticked — the default — the import happens by itself. If you have cleared it, File -> Import From ASCII in AmiBroker does the same job manually; the file-type combo offers AmiQuote Historical (.AQH), AmiQuote Daily (.AQD), AmiQuote Intraday (.AQI), AmiQuote MSN (.AQM) and AmiQuote eSignalCentral (.AQE). Failures are written to import.log in AmiBroker’s main directory.

Day to day you will use the automatic path. In AmiBroker, Tools -> Auto-update quotes (US & Canada) runs Quote.EXE /autoupdate, and AmiQuote performs four steps: it retrieves the ticker list from AmiBroker, reads the last quotation date available there, downloads from that date to today, and instructs AmiBroker to import.

Useful commands when you need to intervene: Tools -> Get tickers from AmiBroker, Tools -> Get last update date, Tools -> Import into AmiBroker, and Tools -> Settings, which sets the destination folder and the file write mode. That last one has a consequence worth knowing: historical files are overwritten and daily files are appended by default, and appending daily files is how you accumulate an intraday history over time from a source that only offers you today.

Two further notes. The guide’s claim that automatic update “works only for US & Canada markets, because Yahoo provides historical quotes only for those markets” has been obsolete for a long time: AmiBroker’s own data-sources page lists fifty-plus international exchanges on Yahoo, and AmiQuote 4.30 added a Warsaw Stock Exchange symbol list. And AmiBroker ships preloaded with a sample DJIA-components database, which is what the Tools menu command targets out of the box — create your own database before you start, or you will be updating the sample.

By default AmiBroker imports Yahoo’s split-adjusted open, high, low and close, and discards the adjusted close. The parsing is controlled by aqh.format in AmiBroker’s Formats folder, whose default format line is:

Pseudocode — not valid AFL

$FORMAT Date_DMY, Open, High, Low, Close, Skip, Volume

To import the split-and-dividend-adjusted close instead, replace Skip with AdjClose. A $VOLFACTOR 1 line makes volume single shares rather than hundreds.

Three things follow, and all three have caught people out.

A study of total return needs the dividend-adjusted series, and you will not get it by default. If your backtest of a high-yield universe looks disappointing, check which series you imported before concluding anything about the strategy.

Yahoo has reordered its columns before. In 2017 it swapped close and adjusted close, which required editing the $FORMAT line; AmiBroker published a corrected aqh.format at the time. If every price in a fresh import looks subtly wrong, a column order change is a live hypothesis.

A hand-edited format file may not survive. A 2026 forum topic reports AmiQuote rewriting aqh.format. Verify your edit after every AmiQuote upgrade.

After every download, answer two questions without opening a chart: did every symbol get its bar, and is what arrived internally consistent? Run it as an Exploration over the whole database, immediately after the import.

Complete runnable AFL

eod-update-audit.afl
// eod-update-audit.afl
// Part 18 - Free and End-of-Day Sources with AmiQuote
//
// The verification step of a free end-of-day update routine. Run it as an
// EXPLORATION immediately after every AmiQuote download, over the whole
// database or over your working watch list.
//
// It answers the only question that matters after an update: did every symbol
// get today's bar, and is what arrived internally consistent?
//
// Why this exists rather than a glance at a chart. AmiQuote's automatic update
// reads the last quotation date of the FIRST symbol in the database and uses
// that as the From date for everything. In a database where symbols sit at
// different dates - which happens the moment you add a new symbol, or a source
// skips one - that is the wrong From date for every symbol except the first,
// and nothing warns you. Charts of the symbols you happen to look at will be
// fine. The ones you do not look at are the ones that go stale.
//
// Assumptions:
// - End-of-day database. Set Range to "All quotations".
// - Freshness is judged by comparing the "Last bar" column across rows, not
// against an exchange calendar. AFL has no knowledge of which days the
// exchange was open, so the audit shows you the dates and leaves the
// judgement to you. Sort by that column and the laggards group together.
_SECTION_BEGIN( "EOD update audit" );
// ---------------------------------------------------------------------------
// 1. Freshness
// ---------------------------------------------------------------------------
LastBarDT = LastValue( DateTime() );
LastBarDate = LastValue( DateNum() );
StoredBars = LastValue( Cum( 1 ) );
// Bars whose date equals the newest date this symbol holds. For a healthy
// end-of-day symbol that is exactly one bar. Two or more means the same session
// was imported twice under different timestamps, which the ASCII importer will
// do quite happily if a downloaded file changes format.
DuplicateLastDay = LastValue( Cum( DateNum() == LastBarDate ) );
// ---------------------------------------------------------------------------
// 2. Internal consistency of the bar itself
// ---------------------------------------------------------------------------
// These are impossible bars, not unusual ones. Any count above zero is a defect
// in what was delivered or in how it was parsed.
//
// The Close-outside-the-range case is worth naming: it is the documented
// signature of a source that adjusted the close for dividends while leaving
// open, high and low adjusted for splits only. AmiBroker's own knowledge base
// records exactly that happening to free Yahoo data.
Impossible = High < Low
OR Close > High OR Close < Low
OR Open > High OR Open < Low;
ImpossibleBars = LastValue( Cum( Nz( Impossible, 0 ) ) );
NonPositive = LastValue( Cum( Nz( Close <= 0, 0 ) ) );
ZeroVolume = LastValue( Cum( Nz( Volume <= 0, 0 ) ) );
// ---------------------------------------------------------------------------
// 3. Padding and staleness inside the history
// ---------------------------------------------------------------------------
// A long run of identical closes in daily data is almost always a symbol the
// source stopped updating - a delisting, a ticker change, or a suspension -
// rather than a share that genuinely did not move for weeks.
CloseChanged = Nz( Close != Ref( Close, -1 ), 1 );
LongestFlat = LastValue( Highest( BarsSince( CloseChanged ) ) );
// The largest one-day move in the history, expressed as a percentage. This is
// not a defect test; it is a shortlist. A 400% one-day move in an ordinary
// large-cap is far more likely to be an unadjusted split than a real event.
DailyMove = Nz( 100 * Abs( Close - Ref( Close, -1 ) ) / Ref( Close, -1 ), 0 );
BiggestMove = LastValue( Highest( DailyMove ) );
// ---------------------------------------------------------------------------
// 4. Report
// ---------------------------------------------------------------------------
Filter = Status( "lastbarinrange" );
AddColumn( LastBarDT, "Last bar", formatDateTime );
AddColumn( StoredBars, "Bars", 1.0 );
AddColumn( DuplicateLastDay, "Dup last", 1.0 );
AddColumn( ImpossibleBars, "Impossible", 1.0 );
AddColumn( NonPositive, "Price <= 0", 1.0 );
AddColumn( ZeroVolume, "Zero vol", 1.0 );
AddColumn( LongestFlat, "Flat run", 1.0 );
AddColumn( BiggestMove, "Max move %", 1.1 );
_SECTION_END();

Download eod-update-audit.afl88 lines

The report has three groups of columns.

Freshness. The last stored timestamp per symbol, the total bar count, and a count of bars carrying the newest date this symbol holds. For a healthy end-of-day symbol that last figure is exactly 1. Two or more means the same session was imported twice under different timestamps, which the ASCII importer will do without complaint if a downloaded file changes shape.

Impossibility. High < Low, or a close or open outside the bar’s own range. These are not unusual bars, they are impossible ones, so any count above zero is a defect in what was delivered or in how it was parsed. Nz() wraps each comparison so that a Null at the array edges does not silently disappear from the running total.

Padding and outliers. BarsSince( CloseChanged ) counts bars since the close last moved, and Highest() of that over the array gives the longest flat run — the signature of a symbol the source stopped updating. The largest one-day percentage move is reported alongside, not as a defect test but as a shortlist: a 400 per cent daily move in an ordinary large-cap is much more likely to be an unadjusted split than an event.

Filter = Status( "lastbarinrange" ) collapses each symbol to one row.

  • Status( "lastbarinrange" ) — true on the final bar of the Analysis range, the standard idiom for one summary row per symbol.
  • Cum( array ) — a running total, so LastValue( Cum( condition ) ) counts how many bars satisfied a condition.
  • BarsSince( array ) — bars elapsed since a condition was last true.
  • Highest( array ) — the running maximum, so its LastValue() is the maximum over the whole range.
  • Nz( x, valueifnull ) — replaces Null with a definite value, keeping missing data out of the totals.

Sort by Last bar and confirm the whole database groups on one date. Then add a symbol that is not in your ticker list, re-run the audit without downloading, and confirm it appears as an obvious outlier with almost no bars — that is what a symbol missed by the update looks like, and recognising it on sight is the point of the exercise.

  • Every symbol reports Impossible counts above zero. Suspect the format file rather than the source: a $FORMAT line whose columns no longer match the downloaded file will assign values to the wrong fields.
  • Max move % is enormous across the board. Unadjusted splits, or a currency or unit change in the source.
  • Flat run is large on many symbols at once. The most likely cause is a stalled update: the source stopped delivering and something kept importing the same values.

Add a column counting the bars in the last twenty sessions whose volume is zero. A symbol that still prices but has stopped trading behaves quite differently from one that has stopped being updated, and separating the two saves you from deleting something you wanted.

Free data is worth exactly what it is designed for, and it is worth being precise about the boundaries.

Coverage and depth vary by market. AmiBroker’s own guidance notes that historical data for international exchanges is usually much shorter than for US markets. Measure what you have with the data requirements audit rather than assuming.

Delisted symbols are generally absent. A universe assembled from free sources is a universe of survivors, and every study run over it carries survivorship bias. That is not a reason to avoid free data; it is a reason to state the bias when you report a result, and it is why the paid end-of-day vendors advertise delisted history as a feature.

Rate limits are real and belong to the source. Yahoo’s “Too many requests” is a Yahoo response, not an AmiQuote defect, and AmiQuote 4.17 added a 300-requests-per- minute cap specifically to stay under it, while 4.30 gave the Stooq downloader a deliberate three-second delay. Do not work around these; they exist so that the source keeps answering.

Terms of use belong to the source, and this course cannot state them for you. Each site sets its own conditions on automated access, redistribution and commercial use, and they change. Read the terms of any source you download from, and understand that a personal-research use and a commercial one are commonly treated very differently. If you cannot find the terms, that is itself information.

And the source can vanish. Two built-in sources were removed in one AmiQuote version; another stopped working for three versions. The user-definable source mechanism exists precisely because this keeps happening.

Here is the routine, assembled. It takes about half an hour the first time and about two minutes a day afterwards.

  1. Create your own database — not the sample DJIA one — with the data source left as (local) and the base time interval set to end-of-day. Keep it out of any cloud-synced folder.
  2. Choose a universe you can defend. A liquid index’s constituents is a good start: broad enough for screening work, small enough to update quickly, and with long histories on free sources. Save it as a .TLS file.
  3. Download the full history once. Set a From date well before you need it and let it run. Expect it to take a while, and do not restart it repeatedly — every restart is more requests against the same rate limit.
  4. Run the data requirements audit from the decision-framework lesson. Record the Days figure for the shallowest symbol in the universe. That number is the real limit on every study you will run over it.
  5. Run the EOD update audit. Deal with anything it flags now, while the database is small and you remember what you did.
  6. Establish the daily routine. Tools -> Auto-update quotes, then the update audit. Two commands, and you will know within a minute whether the evening’s data is sound.
  7. Write down what you built. The database path, the base interval, the universe, the source, whether you edited aqh.format, and the date. Later parts will ask.

You now have a data source that costs nothing, a routine for keeping it current, and — more importantly — a routine for checking that the routine worked. That last part is what separates a database you can build research on from a folder of files you hope are correct.

The three appendices before this one describe what money buys: live streaming, deep intraday backfill, delisted history, maintained symbol tables. Each of those is a real capability with a real price. None of them is needed to finish this course, and the database you built here is the one the majority of the remaining parts assume.

Check your understanding

Question 1. A tutorial written in early 2025 tells you Yahoo historical downloads are defunct in AmiQuote and that you must install a workaround data source. You are running the AmiQuote bundled with AmiBroker 7.00.1. What should you do?
Show the answer and why

Answer: Check your AmiQuote version — the built-in Yahoo source was re-implemented in 4.19 and works again

Yahoo Historical was reported defunct in 4.16 and re-implemented in 4.19, which is the version inside AmiBroker 7.00.1. Advice written between those releases is wrong for current versions, and installing the workaround gives you a duplicate source you do not need.

Question 2. Which of these are documented consequences of AmiQuote's "Get last update date"? Select all that apply.
Show the answer and why

Answer: It reads the date of the first symbol in the database only, It applies that date as the From date for every symbol, It can leave symbols silently stale in a database whose symbols sit at different dates

It performs no verification at all — which is exactly why an audit after the import is worth two minutes. A symbol added last week sits at last week's date and is never caught up if the first symbol in the database is current.

Question 3. Your backtest of a high-yield share universe looks worse than expected. Which import setting is worth checking first?
Show the answer and why

Answer: Whether aqh.format imports AdjClose or discards it with Skip

By default AmiBroker imports the split-adjusted OHLC and skips the adjusted close, so dividends are absent from the series. On a high-yield universe that is a large and systematic difference, and it is a one-line change to the format file.

Question 4. True or false: it is safe to run AmiQuote against a database fed by a real-time plugin, because AmiBroker merges the two sources.
Show the answer and why

Answer: False

False. The plugin controls the quotation data. The documentation states that the plugin will eventually overwrite the imports, or the database will be corrupted if end-of-day data is imported over an intraday database. The one narrow exception is importing symbols that are not in the database at all, which the importer then marks as local-only.

Sources for this lesson

9 verified · checked 2026-09-01

  1. 01AmiBroker User's Guide — How to download quotes manually using AmiQuoteamibroker.com/guide/h_amiquote.html2026-08-31
  2. 02AmiBroker User's Guide — How to update US quotes automatically using AmiQuoteamibroker.com/guide/h_amiquote2.html2026-08-31
  3. 03AmiQuote 4.00 Read Meamibroker.com/devlog/wp-content/uploads/2019/05/aqreadme4000.html2026-08-31
  4. 04AmiBroker — Download page§ AmiQuote 4.40 Official Releaseamibroker.com/download.html2026-09-01
  5. 05AmiBroker Knowledge Base — AmiQuote and free data from Yahooamibroker.com/kb/2007/08/04/amiquote-and-free-data-from-yahoo2026-08-31
  6. 06AmiBroker Knowledge Base — Wrong close price in Yahoo dataamibroker.com/kb/2017/06/30/wrong-close-price-in-yahoo-data2026-08-31
  7. 07AmiBroker User's Guide — How to work with Real-Time data plugins§ Things you should NOT doamibroker.com/guide/h_rtsource.html2026-08-31
  8. 08AmiBroker User's Guide — How to get quotes from various marketsamibroker.com/guide/h_quotes.html2026-08-31
  9. 09AmiBroker — Productsamibroker.com/products.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.