afl for amibrokerThe best resources for Amibroker AFL can be found via the Amibroker AFL library or one of the Amibroker user forums. Here there are usually plenty of generous traders who are happy to share some of their code and give assistance if needed.

I also provide plenty of free AFL code here so make sure to come back regularly.

New to Amibroker?

Luckily writing AFL for Amibroker is fairly straightforward even for someone with no background in programming. If you are new to Amibroker I will recommend a piece of advice that I first received when on the Amibroker forum:

Start off with end of the day data for US stocks and look for simple, robust systems.

Everything you need from a good trading system can be found with EOD data and from here it should be possible to reach returns of 30% CAR a year with a little bit of work. From there you can start to work on even greater returns but remember higher returns will inherently mean higher risk.

By end of day data I mean data that shows the high, low, open, and close from the trading day. It’s far better to concentrate on daily or weekly systems and ignore day trading if you are new to the markets.

And remember, no trading system can be created without good quality data. I recommend Norgate Premium Data and you can get a free trial of the service here.

Writing AFL for Amibroker

When you start writing Amibroker AFL it’s a good idea to begin with a kind of template that you can then use as the basis of several trading systems. I usually start off with something like this, (the set options can also be set in the Amibroker panel but it’s better to write them into the code):

SetOption( “InitialEquity”, 10000);

This one sets how much capital you have to trade e.g. $10,000

SetOption( “UsePrevBarEquityForPosSizing”, True );

Allows position size to be calculated using % of previous bar’s funds. Can be turned on or off

SetTradeDelays( 1, 1, 1, 1 );

It’s usually not possible to trade on the exact moment that a signal occurs. So you can delay the buy, sell, short and cover entries by 1 (or more) bars.

SetOption( “MaxOpenpositions”, 10);

Sets the Maximum open positions you want at any one time. I’ve set mine at 10 as I trade a portfolio of 10 stocks.

SetOption(“SeparateLongShortRank”, True );

Amibroker enters trades based on the signal rank also known as positionscore. If you hold short and long positions this variable allows them to be ranked separately so you dont end up favoring one direction over the other.

SetOption (“Maxopenlong”,MOL);
SetOption (“Maxopenshort”,MOS);
MOL = 10;
MOS = 5:

This code allows a maximum of 10 long positions and 5 short positions at any one time.

SetOption( “AllowSameBarExit”, True );

Allows trades to be closed on the same bar that the exit signal or stop signal occurs

Numberpositions = 10;
SetPositionSize( 1, spsShares );
PositionSize= -20/10;

This is the segment of code I use to set my positionsize or risk. -20 / 10 means my position size per trade is 20% of my account divided by 10.
In other words, if I start with $10,000, my first trade will have a stock value of $200. To get the number of shares, you simply divide this number by the stock price. Eg, for a stock that is $12, I will buy 16 shares.

Ranking trades

Once that’s in place it’s a good idea to define positionscore metrics and enter the formulas for any indicators you plan to use. Remember, positionscore determines the rank. If you have more than one trade signal, Amibroker will take the trade that is scored the highest. This is quite important, particularly if your system generates lots of signals on the same day/ bar. You can use any calculation you like. Here are some ideas:

PositionScore = RSI(14) – 100;       Prefers long positions with lower RSI values and short positions with high RSI
PositionScore = ATR(10) – 100;     Prefers long positions with smaller ATR (average true range) values
PositionScore = ROC(C,1) * -1;       Prefers long positions with lower ROC (rate of change) values 

Then you can enter your buy and sell conditions. When you write AFL for Amibroker it’s a good idea to keep everything organised so that you dont make any mistakes and you can easily understand it in the future. Here’s a very simple moving average crossover example:

fastema = EMA(C,50);
slowema = MA(C,200);

Buy = Cross(fastEMA,slowEMA);  Buys when the 50 period EMA crosses over the 200 period EMA.
Sell = Cross(slowEMA,fastEMA);   Sells when the 200 period EMA crosses under the 50 period EMA.

Once you have tried this, you can set about optimising some of your parameters like below:

fastema = Optimise(“fastEMA”,50,25,200,25);
slowema = Optimise(“slowEMA”,200,180,300,20);

When run, the optimiser will cycle through these values and present them in a table showing which ones performed the best. The numbers in brackets stand for (default setting, first iteration, final iteration, step). In other words the optimizer will first test the fastema with using the ’25’ setting, it will then keep testing at intervals of 25 until it gets to 200 where it stops. If you run the backtest without the optimiser, Amibroker uses the default (50) setting.

After your buy and sell conditions you can enter code that plots your various indicators on the chart and any calculations that you may have with the equity curve.

For more code be sure to check back here regularly as I plan to post several trading systems – analysed and presented with the AFL for Amibroker.

It’s also a good idea to check out the resources from Amibroker for back-testing and portfolio testing here.


Tags: , , , ,

15 opinions

  1. Hello from Spain.. Congratulations for your website and thank you for your help.
    I am a newbie in Amibroker. I would like to code a stop from last high. The rule must be: exit long if actual price is 16% lower than last candle high. I believe applystop function can’t do that. Can you help me?
    Thank you

    • Hi Ricardo
      Well you don’t need to use a stop, you can just program a normal sell function.
      Not exactly sure what you need, what about: Sell = C < Ref( H,-1) * 0.84; Sorry for the delay, I didn't see your comment till now. Cheers

    • Arijit Kundu

    • May 14, 2015

    • 2:51 pm

    • Reply


    Can you develop backtesting coding for the following trading system:

    The system starts with an account balance of Rs 30,000 and starts by buying 1 unit( contract or share) at the OPENING PRICE OF A SPECIFIED DATE(there should be an option to modify this date)..This is step 1

    step 2. buy 1 unit when current account balance increases by Rs.20,000/-


    sell 1 unit when current account balance decreases by Rs.10,000/-

    step 3. Keep on repeating step 2 unless either (1)the account balance gets exhausted or (2) A FINAL EXIT DATE is specified when all units will be squared off at the closing price of that day.

    This is the main theme of the system. Please write back for more clarifications.

    • Shikher

    • October 13, 2015

    • 11:39 pm

    • Reply

    HI CAN AN ANYBODY HELP IN correcting this code

    It should be able to give Buy when blue signal comes and once it goes away sell…
    Then if again blue signal comes it show buy again

    Same way once black signal come it show Short and once it goes away it should show cover.

    There will be time when no signal will be there …( No trading) wait for signal it can be Buy or sell as per the Arrow

    here is the formula that i want to be corrected

    _N(Title = StrFormat(“{{NAME}} – {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}”, O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
    Plot( C, “Close”, ParamColor(“Color”, colorBlack ), styleNoTitle | ParamStyle(“Style”) | GetPriceStyle() );


    a = Param(“Average Pds”, 5, 1, 10, 1 );
    n = Param(“Short Pds”, 8, 5, 21, 1 );
    m = Param(“Long Pds”, 60, 0, 90, 1 );

    Var4 =(Low+High+2*Close)/4;
    OP = EMA(Var4,a);
    res1 = HHV(OP,n);

    res2 =HHV(OP,m);
    sup2 =LLV(OP,m);
    sup1 =LLV(OP,n);

    Linecolor = IIf(Op==sup1,colorBlack,IIf(Op==res1,10,7));


    Buy = Op==res1 ;
    Short= Op==sup1 ;

    Sell = IIf(Linecolor == 7,0,0);
    Cover= IIf(Linecolor == 7,0,0);

    Sell = Flip(Sell, Buy);
    Cover = Flip(Cover, Short);

    //Buy = ExRem(Buy, Short);

    //Short= ExRem(Short, Buy);

    SetPositionSize( 50, spsShares ); // 50 shares by default

    PlotShapes(IIf(Buy, shapeUpArrow , shapeNone), colorBlue);
    PlotShapes(IIf(Short, shapeDownArrow , shapeNone), colorBlack);

    • Hi Shikher, sorry but this isn’t the best place to post long excerpts of code or ask for code debugging. I suggest you take a look at the Amibroker forums on yahoo or on the aussie stock forum… I believe they will be much more helpful to you. If I get enough feedback I might consider creating a forum for this kind of thing, but I’m not sure if there is a need at the moment considering there are already existing forums.

  2. i want an AFL, divergences on RSI, Macd and Stochastics on hour, day, week timeframes. any help is appreciated

    • sudha

    • January 3, 2017

    • 9:44 pm

    • Reply

    backtesting /optimisation accepts only the generated signals for a moving average/trend following based afl.
    i want to consider the first open data( from a specific date) till the first signal as a trade. how to go about it.

    • mukesh

    • February 19, 2017

    • 1:43 am

    • Reply


    I need a afl code to backtest my strategy in amibroker, its a very simple strategy, please please help me

    chart type: line break (3 line break)
    all candles type: close
    all prices at close
    When the 1st bar/brick/candle becomes green (new/1st green bar/candle/brick) in line break charts then open long position
    Stoploss as 1st/new red bar/candle/brick formed
    And target for long position same as above 1st/new red bar/brick/candle formed

    Vice a versa for short positions
    when 1st/new red bar/candle/brick is formed open short position
    Stop loss as 1st/new green bar/candle/brick formation
    Target also the same 1st/new green bar/candle/brick formation

    basically what I am trying to do here is when we have the green bricks start forming in line and break charts I go long and as green bricks become red I close long positions and take short positions

    Thank you so much,

    • ms

    • February 24, 2017

    • 1:06 pm

    • Reply

    Hi, wondering if you can share you thinking on multiplying by -1 in your Positionscore example (PositionScore = ROC(C,1) * -1; ).

    I thought PositionScore was expressed in absolute value terms. If it is, does multiplying by -1 alter the value?

    • E Viswanath

    • April 15, 2017

    • 5:25 pm

    • Reply

    Hi JB Marwood,

    Appreciate for the code snippets.

    Could you post complete AFL of above code.

    • Dakshesh Patel

    • December 21, 2017

    • 8:12 am

    • Reply

    Hi JB Marwood,

    I really appreciate your work, i am learning by your work.

    I have prepared one stratagy, i have used ” PosiionScore= RSI(14)-100″ but when i backtested and see trades, some long trades has low rsi but not every trade.
    i got multiple signal on same day but still amibroker backtested using other trade which has high rsi then other signals?

    i didn’t understood why?

    I hope you can help me.

    thanks in advance

    • Hi, you must simply do the math and adjust to your needs.

      For long strategy, Amibroker chooses high positionscore values first. For short strategy, Amibroker prefers low positionscore values.


      Stock A = RSI(14) = 70
      Stock B = RSI(14) = 40

      If “PositionScore = RSI(14) – 100”, then positionscore for Stock A is 70 – 100 = -30. For Stock B, positionscore is 40 – 100 = -60.

      Therefore Amibroker will choose Stock A because the positionscore has a higher value (-30 is higher than -60). Thus, Amibroker is choosing the stock with the higher RSI(14).

      If you write it the other way “Positionscore = 100 – RSI(14)”. Now Stock A has a value of 100 – 70 = 30. And stock B has a value of 100 – 40 = 60. In this case Amibroker will prefer Stock B first.

Leave a Reply

%d bloggers like this: