amibroker

HomeKnowledge Base

Purchases from Hong Kong

Customers from Hong Kong sometimes have problems ordering because there are no ZIP codes in Hong Kong and SWREG system that we are using requires ZIP code. If you are buying using credit card, entering 0000 or NA in place of ZIP code field is accepted. But if you are buying using PayPal, it may reject it if your PayPal account does not have matching ZIP code. Therefore, if you are using PayPal you need to follow these instructions:

  1. Update your PayPal account billing address with ‘0000’ in the Postal Code/ZIP field
  2. Now you can use 0000 as ZIP code in SWREG ordering page

Support response times

AmiBroker’s technical support staff everyday faces with very wide scope of subjects ranging from simple installation, lost registration details, password reminders questions to complex things like C++ programming or esoteric issues that occur say once a month or only when program is loaded with dozens of gigabytes of data.

Support response times to those different inquiries obviously vary a lot.

Technically we answer basic questions in 24 hours on week days (Monday-Friday).

Very simple questions get answered even in minutes if you happen to ask them when our support staff is in the office (we are in GMT+1 timezone). If you are in different time zone, we may be currently sleeping so you may need to wait for next day.

This response time applies to questions that are covered already in our Official Knowledge Base, Users’ Knowledge Base, Users’ Manual or internal documentation/resources. It is quite good idea to check those resources yourself as you are very likely to find the answer much quicker.

For more complex questions that need some formulas to be written or checked/verified the response time may be higher (48 hours), as long as this check can be done by our regular support staff.

Some complex issues/questions can not be solved/answered by support staff alone and then they are escalated to development. You need to keep in mind that development is 100% busy all the time, we are not sitting here doing nothing. It is all-day development job that is on-going and those complex support issues must wait in the queue. Also since some of issues/questions require lots of work (setting up environment to mimic customer’s setup, testing, single-step debugging sessions, going through millions of lines of code), it may easily take days or even weeks to complete. If development finds out that the issue is due to software problem, then the problem is either fixed at once or scheduled for fixing. This is a process. So please do not expect “next day response” for those kind of issues. You are also not going to get constant e-mails/updates like “we are working on it”, because we are always working on something in the queue. Please be patient, things are being worked on constantly.

How to register AmiQuote and AFL Code Wizard

AmiQuote and AFL Wizard are separate applications, therefore the registration process is also separate from registering AmiBroker and requires to enter the unlock code into Help->Register menu in AmiQuote or AFL Wizard respectively. The unlock codes are delivered in the transaction receipt generated after the purchase (sent from SWREG, ShareIt or other payment processor)

In order to register these programs, it is necessary to launch AmiQuote or AFL Wizard first.

AmiQuote can be launched e.g. from the Windows Start menu or by double-clicking on Quote (Quote.exe) program in AmiBroker/AmiQuote folder.

register

Once the program is running, we need to enter the unlock codes into Help->Register AmiQuote menu:

register

Then we can enter our name and the unlock code, then press Update button.

register

AFL Code Wizard can be launched from Analysis menu inside AmiBroker:

register

After the program is launched it’s necessary to select Help->Registration details item from the menu.

register

Then we can enter our name and the unlock code, then press Update button.

register

Calling custom user functions in our code

AFL language allows us to define reusable functions that can be used in our formulas. The following chapter of the manual explains the procedure in details: http://amibroker.com/guide/a_userfunctions.html

When we want to call such function in our formula, we should add function definition into our code, so AmiBroker could identify and interpret custom keyword properly. Consequently, if we use the function in multiple chart panes, each of the formulas should contain the function definition first.

// custom function definition
function myMACD( array, fastslow )
{
   return EMA( array, fast ) - EMA( array, slow );
}

// use of function
PlotmyMACDHigh1226 ), "Open MACD"colorRed );

Since we may potentially define a large group of our own functions, pasting the definitions manually may not be very convenient. To avoid that, we can use #include statement and group our definitions in a separate AFL file which will be called with a single statement from our main code.

To create such file we should do the following:

  1. Create a new formula. The preferred location is in Include folder in chart windows, we can in fact choose any custom location of the file.
    include

  2. We can also rename the file to a descriptive name, for example myfunctions.afl:
    include

  3. Now we can edit the file and paste our function definitions, then save the file:
    function myMACD( array, fastslow )
    {
       return EMA( array, fast ) - EMA( array, slow );
    }
  4. Now in our main file we can use only a reference to myfunctions.afl file:
    // include our definitions
    #include <myfunctions.afl>
    
    // use of function
    PlotmyMACDHigh1226 ), "Open MACD"colorRed )

We don’t have to specify the path, because we saved our formula in the folder, which is specified as a ‘default include path’ in Tools–>Preferences–>AFL:

include

In other cases we should provide full path to the file – #include is a pre-processor command, therefore this time we use single backslashes in the path:

#include “C:\Program Files\AmiBroker\AFL\common.afl”

More information about include command can be found at:

http://www.amibroker.com/guide/afl/_include.html

Where does AmiQuote save downloaded data?

AmiQuote is a companion program shipped with AmiBroker, which allows data from free resources, such as Yahoo Finance, Google Finance and others. Since it is a separate application, then it can work independently from AmiBroker and it saves data in text files stored in Destination Folder defined in Tools->Settings window:

aq download folder

AmiQuote can also communicate with AmiBroker using OLE automation and automatically import downloaded data into AmiBroker if Automatic Import option is selected:

aq download folder

AmiQuote will import data to the database, which is opened in AmiBroker at the time of import.

Additionally, if more than one instance of AmiBroker is opened at the same time with different databases loaded, then AQ will communicate with the instance that was launched first and will import data into the database opened in this instance of AmiBroker.

Do not exceed real-time symbol limit

When we subscribe to a real-time datasource, such as eSignal or IQFeed – our subscription package determines how many symbols we can access in realtime at the same time. The plugin configuration in File->Database Settings->Configure should match the subscription limit.

IQFeed:

rt config

eSignal:

rt config

As it is explained in the users guide here: http://www.amibroker.com/guide/h_rtsource.html – although AmiBroker is able to handle more symbols in the database than the streaming limit, we should not really exceed the RT subscription limits in continuous screening during session hours.

This is because if we do otherwise and try to access more symbols than our subscription covers, then it would requires lengthy process that includes:

  1. removing the oldest symbol from the streaming list
  2. adding the new one
  3. triggering backfill for the newly added stock to fill the historical data from last valid update that we already have
  4. streaming and displaying RT data.

Then such process will be repeated for each new symbol that is included in screening. As a result, that might cause various problems with the data source not able to handle that many backfill requests in a short time, additionally data-vendors may be pro-actively protecting their servers from abusing the streaming limits this way.

Therefore – it is highly recommended to stay within the subscription limits for real-time operation and scanning to avoid problems.

Long-only rotational back-test

Rotational trading is a kind of backtest where you trade by switching positions between various symbols based on their relative score instead of traditional buy/sell/short/cover signals.

Since there are no signals used, only PositionScore assigned to given symbol matters.

It is worth noting that in case of rotational test, the Positions field in General tab of the Analysis settings is ignored. It is only used for regular backtests that use actual buy/sell/short/cover signals.

In the rotational mode the trades are driven by values of PositionScore variable alone.

In particular:

  • higher positive score means better candidate for entering long trade
  • lower negative score means better candidate for entering short trade

As you can see the SIGN of PositionScore variable decides whenever it is long or short.

Therefore – if we want to test long-only system in rotational backtesting mode, then we should use only positive values in PositionScore variable. For example – if we are trading a system, which uses 252-bar rate of change for scoring purposes:

SetBacktestModebacktestRotational );
SetOption("MaxOpenPositions",5);
SetOption("WorstRankHeld",5);
SetPositionSize20spsPercentOfEquity );
PositionScore ROCClose252 );

Then, to trade only long positions, we should change PositionScore defintion for example to:

PositionScore 1000 ROCClose252 ); // make sure it is positive by adding big constant

This way our scores will remain positive and that will effectively disable short trades.

More information about the rotational mode of the backtester can be found in the manual: http://www.amibroker.com/guide/afl/enablerotationaltrading.html

Differences between 32-bit and 64-bit version

One common issue that surfaces pretty often is the lack of full understanding of differences between 32-bit and 64-bit versions of AmiBroker among users. This article tries to explain some of the most important bits.

WHICH VERSION DO I HAVE?

To find out which version you have installed just go to Help->About window. It clearly says “32-bit” or “64-bit” in the About window.

OPERATING SYSTEM COMPATIBILITY

32-bit version of AmiBroker is compatible with BOTH 32-bit and 64-bit Windows.
64-bit version of AmiBroker is compatible with 64-bit Windows ONLY.

32-bit version running on 64-bit OS can fully utilize as much as 4GB of RAM for the program data.
The rest of RAM is used for OS, file system cache, system libraries, etc.
64-bit can theoretically use all RAM available but Windows itself has some limits (see Microsoft web pages for details)

More on OS system compatibility can be found here: http://www.amibroker.com/guide/compat.html

REGISTRATION / ACTIVATION KEY

There are separate activation keys for 32-bit and 64-bit version. The key for 32-bit version is ABReg.exe, while the key for 64-bit version is named ABReg64.exe. If you apply wrong key (32-bit key for 64-bit application or vice versa), you will not get any error message but the application will still show “Unregistered”. So make sure you apply 32-bit key (ABReg.exe) to 32-bit application and 64-bit key (ABReg64.exe) to 64-bit application.

Also note that 64-bit key is available only to those who registered “Professional Edition”.

DATA SUPPORT

32-bit version offers the widest selection of supported data sources (all listed here: http://www.amibroker.com/guide/h_quotes.html )

Many 3rd party data sources that are not listed above come in 32-bit only.

64-bit offers limited support for data sources due to the fact that 64-bit support requires 64-bit API from data vendor, and this is not always available.

For more information:
http://www.amibroker.com/guide/compat.html

Typically if you put 3rd party data vendor DLL into “Plugins” directory and it does not show up in the data source list it means that its bitness is wrong (see below for more info).

PLUGIN COMPATIBILITY

Because of Windows OS limitations, 32-bit application is not able to load 64-bit DLLs and 64-bit application is not able to load 32-bit DLLs. In other words the “bitness” of application and DLLs must match. This has wide consequences with respect to plugins. Since plugins are just DLLs (dynamic load libraries), if you want to use a plugin you need to make sure it matches the bitness of your application. As majority of 3rd party plugins come only in 32-bit, so 32-bit version of AmiBroker offers widest selection of data plugin support.

FILE FORMAT COMPATIBILITY

We have put a lot of effort into making files compatible between 32-bit and 64-bit versions, so at the moment all formulas (AFL), project files (APX), all binary databases, layouts, watch lists are all 100% binary compatible between 32-bit and 64-bit versions, as long as they are smaller than 4GB. The only exception are DLLs (plugins) which are different for 32-bit and 64-bit as mentioned above.

PERFORMANCE

Generally speaking 64-bit offers pretty much same performance as 32-bit version. The difference in speed is marginal. The only true advantage of 64-bit versions is ability to address more than 4GB of RAM and support larger data sets.

PRECISION

Contrary to ‘common sense’, 64-bit applications are not more precise. Due to Intel/AMD/Microsoft decision the support for extended double 80-bit floating point (x87 FPU) has been dropped in 64-bit compilers and replaced by less accurate 64-bit floating point SSE2 for sake of speed. That is why you may see some speed up in 64-bit application. 32-bit code computes all results with internal 80 bit accuracy due to the use of 80 bit FPU unit. 64-bit does so with at most 64-bits. Also the ‘old’ x87 FPU handles way more instructions in hardware (like transcendentals), while new SSE2 only has basic math and all more complex functions are implemented in runtime library. While we are building both versions from the very same C/C++ source code and are striving to provide same results from all functions, these architectural differences can cause that output of 32-bit version is more precise.

More on floating point arithmetic can be found here: http://www.amibroker.com/kb/2010/07/20/about-floating-point-arithmetic/

Separate ranks for categories that can be used in backtesting

When we want to develop a trading system, which enters only N top-scored symbols from each of the sectors, industries or other sub-groups of symbols ranked separately, we should build appropriate ranks for each of such categories. This can be done with ranking functionalities provided by StaticVarGenerateRanks function.

The formula presented below iterates though the list of symbols included in the test, then calculates the scores used for ranking and writes them into static variables. The static variables names are based on category number (sectors in this example) and that allows to create separate ranks for each sector.

// watchlist should contain all symbols included in the test
wlnum GetOption"FilterIncludeWatchlist" );
List = CategoryGetSymbolscategoryWatchlistwlnum ) ;

if( Status"stocknum" ) == )
{
    // cleanup variables created in previous runs (if any)
    StaticVarRemove"rank*" );
    StaticVarRemove"values*" );
    categoryList ",";

    for( 0; ( Symbol StrExtract( List, ) )  != "";  n++ )
    {
        SetForeignsymbol );

        // use sectors for ranking
        category sectorID();

        // add sector to the list
        if( ! StrFindcategoryList"," category "," ) ) categoryList += NumToStrcategory1) + ",";

        // write our ranking criteria to a variable
        // in this example we will use 10-bar rate-of-change
        values RocClose10 );
        
        RestorePriceArrays();

        // write ranked values to a static variable
        StaticVarSet"values" category "_" symbolvalues );

    }

    // generate separate ranks for each category from the list
    for( 1; ( category StrExtractcategoryList) ) != ""i++ )
    {
        StaticVarGenerateRanks"rank""values" category "_"01224 );
    }
}

category sectorID();
symbol Name();
Month();

values StaticVarGet"values" category "_" symbol );
rank StaticVarGet"rank" "values" category "_" symbol );

// exploration code for verification
AddColumnvalues"values" );
AddColumnrank"rank" );
AddTextColumnSectorID), "Sector" );
AddColumnSectorID(), "Sector No");
Filter rank <= 2;

if( Status"Action" ) == actionExplore SetSortColumns25);

// sample backtesting rules
SetBacktestModebacktestRotational );
score IIfrank <= 2values);
// switch symbols at the beginning of the month only
PositionScore IIf!= Refm, -), scorescoreNoRotate );
SetPositionSize1spsPercentOfEquity );

Our test should be applied to a watchlist, which contains all symbols we want to include in our ranking code:

Watch list selection

Running the exploration will show two top-ranked symbols for each of the sectors:

Ranking

We can also change Filter variable definition to

Filter 1;

and show all ranked symbols instead.

Such ranking information can be used in backtest and sample rules included at the end of the code use rank information to allow only two top-scored symbols to be traded.

Ruin stop or mysterious Short(6) in the trade list

When you back-test a trading system, you may sometimes encounter trades marked with (6) exit reason, showing e.g.: Short (6) or Short (ruin) in the trade list as in the picture below:

Ruin stop in trade list

As explained in the this Knowledge Base article: http://www.amibroker.com/kb/2014/09/24/how-to-identify-which-signal-triggers/ such identifier tells us that the trade was closed because of the ruin stop activation.

A ruin-stop is a built-in, fixed percentage stop set at -99.96%, so it gets activated if your position is losing almost all (99.96%) of its entry value. It almost never occurs in long trades, but it may be quite common if your trading system places short trades without any kind of maximum loss stop. Imagine that you short a stock when its price is $10, then it’s price rises to $20 (twice the entry price). When you buy to cover the position you must pay $20 per share, which means that your loss on this trade is $10 per share ($20-$10). This means 100% loss (as per entry value). If you placed such a trade with all your capital you would be bankrupt. That is why this stop is called “ruin stop”. Unfortunately, by the nature of short selling, the gains are limited to 100% (when stock price goes down to zero) but losses are virtually unlimited.

So what to do to prevent exits by ruin stop?

The best idea is to just place proper max. loss stop at much smaller percentage (such as 10% or 20%) depending on what your risk tolerance is, to limit drawdowns and decrease the chance of wiping your account down to zero.

If, for some weird reason, you want to turn OFF this built-in stop, you can do so using this code:

SetOption"DisableRuinStop"True );

but it is highly discouraged, because when you wipe your account down to zero (or even below zero) it makes no point to run back-test any further. Instead of disabling this feature you should place proper, tighter maximum loss stop.

Next Page »