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.
What AmiQuote is
Section titled “What AmiQuote is”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
- Ticker listA .TLS text file, one symbol per line, or symbols pulled from AmiBroker
- URL generationOne request per marked ticker, built from source, symbol and date range
- DownloadResults written as .AQH, .AQD or .AQI text files in the destination folder
- Automatic importAmiQuote drives AmiBroker over OLE; failures are logged to import.log
- Bars in your databaseParsed according to the matching .format file
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.
Supported sources, as documented
Section titled “Supported sources, as documented”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.
User-definable data sources
Section titled “User-definable data sources”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 end-of-day workflow
Section titled “The end-of-day workflow”The manual route, which is worth doing once even though you will use the automatic one afterwards:
- Prepare a ticker list. A
.TLSfile 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 —.Lfor London,.DEfor XETRA,.AXfor Australia,.TOfor Toronto and around forty others — and Yahoo indices take a^prefix. - Open it in AmiQuote with
File -> Open. - Choose the Source and the date range.
- Check what is marked. Only tickers with a checkmark are downloaded.
Edit -> Mark all,Mark selectionand their opposites control this, andView -> Refreshre-marks everything after a date-range change. - 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.
The update routine
Section titled “The update routine”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.
The adjustment trap
Section titled “The adjustment trap”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, VolumeTo 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.
Verifying the update
Section titled “Verifying the update”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.
The formula
Section titled “The formula”Complete runnable 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();How it works
Section titled “How it works”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.
Key functions
Section titled “Key functions”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, soLastValue( 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 itsLastValue()is the maximum over the whole range.Nz( x, valueifnull )— replacesNullwith a definite value, keeping missing data out of the totals.
Expected result
Section titled “Expected result”Test it
Section titled “Test it”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.
Common errors
Section titled “Common errors”- Every symbol reports
Impossiblecounts above zero. Suspect the format file rather than the source: a$FORMATline 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 runis 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.
Extension
Section titled “Extension”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.
Limitations and terms of use
Section titled “Limitations and terms of use”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.
Building a Level A learning database
Section titled “Building a Level A learning database”Here is the routine, assembled. It takes about half an hour the first time and about two minutes a day afterwards.
- 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. - 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
.TLSfile. - 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.
- Run the data requirements audit from the decision-framework lesson. Record the
Daysfigure for the shallowest symbol in the universe. That number is the real limit on every study you will run over it. - Run the EOD update audit. Deal with anything it flags now, while the database is small and you remember what you did.
- 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. - 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.
What changed
Section titled “What changed”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
Sources for this lesson
9 verified · checked 2026-09-01
- 01AmiBroker User's Guide — How to download quotes manually using AmiQuoteamibroker.com/guide/h_amiquote.html2026-08-31
- 02AmiBroker User's Guide — How to update US quotes automatically using AmiQuoteamibroker.com/guide/h_amiquote2.html2026-08-31
- 03AmiQuote 4.00 Read Meamibroker.com/devlog/wp-content/uploads/2019/05/aqreadme4000.html2026-08-31
- 04AmiBroker — Download page§ AmiQuote 4.40 Official Releaseamibroker.com/download.html2026-09-01
- 05AmiBroker Knowledge Base — AmiQuote and free data from Yahooamibroker.com/kb/2007/08/04/amiquote-and-free-data-from-yahoo2026-08-31
- 06AmiBroker Knowledge Base — Wrong close price in Yahoo dataamibroker.com/kb/2017/06/30/wrong-close-price-in-yahoo-data2026-08-31
- 07AmiBroker User's Guide — How to work with Real-Time data plugins§ Things you should NOT doamibroker.com/guide/h_rtsource.html2026-08-31
- 08AmiBroker User's Guide — How to get quotes from various marketsamibroker.com/guide/h_quotes.html2026-08-31
- 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.