Common Coding mistakes in AFL

This document presents most common mistakes and problems that users encounter when writing their custom formulas. Please read carefully to avoid making similar errors.


“=” (assignment)  vs  “==” (equality check)

There are two similar looking but completely different operators in AFL.

“=” is a variable assignment operator

“==” is an equality check operator

EXAMPLE

Incorrect code:

result = IIf( Variable = 10 , High, Low ); // WRONG

If you want to check if variable is equal to 10, you MUST use “==”

Correct code:

result = IIf( Variable == 10 , High, Low ); // CORRECT


Using parentheses

Parentheses can be used to control the operation precedence (the order in which the operators are calculated). AmiBroker always does operations within the innermost parentheses first. To learn the the precedence of operations when parentheses are not used, visit: http://www.amibroker.com/guide/a_language.html

EXAMPLE:

“I would like to buy whenever either Close is higher that it’s 10-periods Moving Average or Close is at least 10% higher than yesterday’s close, but buy should only apply when Current Volume is higher than it’s 10-period Moving Average. However – I get Buy signals for the days when Volume is lower than MA(Volume,10). Why?”

Buy = Close > MA( Close, 10 ) OR Close == 1.1 * Ref( Close, -1 ) AND Volume > MA( Volume, 10 );

The solution is to add parentheses, otherwise system buys whenever Close > MA(Close,10) condition is met ( or Close == 1.1*Ref(Close,-1) AND  Volume > MA(Volume,10) are both met).

Buy = ( Close > MA( Close, 10 ) OR Close == 1.1 * Ref( Close, -1 ) )
      AND Volume >
MA( Volume, 10 );


IIf function

The IIf( ) function is used to create conditional assignments.

variable = IIf( EXPRESSION, TRUE_PART, FALSE_PART );

The above "IIf" statement means: For each bar EXPRESSION is true assign TRUE_PART to the variable, otherwise (when EXPRESSION is false) assign FALSE_PART.

EXAMPLE

Incorrect code

IIf( Close > 10, result = 7, result = 9 ); // WRONG

Correct code:

result = IIf( Close > 10, 7, 9 ); // CORRECT


IIf is for arrays, WriteIf is for strings

IIf functions should be used to handle arrays, if you need conditional text function use WriteIf instead.

EXAMPLE

Incorrect code:

variable = IIf(Condition, "Text 1","Text 2" ); // WRONG

IIf( ) function returns array, NOT STRING, so it’s impossible to assign text to variable with use of IIF. Use WriteIf( ) function instead:

Correct code:

variable = WriteIf( condition, "Text 1", "Text 2" ); // CORRECT

Please note however that WriteIf function returns just single STRING, not arrays of strings, so only the selected value is used for evaluation.


if-else statement needs boolean (or single numeric expression), not array

The if keyword executes statement1 if expression is true (nonzero); if else is present and expression is false (zero), it executes statement2. After executing statement1 or statement2, control passes to the next statement. Expression must be boolean ( True/False) type (so it CANNOT be ARRAY because there would be no way do decide whether to execute statement1 or not, if for example array was: [True,True,False,.....,False,True] )

if( expression )
   statement1
else
   statement2

EXAMPLE

if( Close > Open// WRONG
   Color =
colorGreen; //statement 1
else
   Color =
colorRed; //statement 2

Plot(Close,"Colored Price",Color,styleCandle);

The above example is wrong, as both Open and Close are arrays and such expression as Close > Open is also an ARRAY. The solution depends on the statement. It’s either possible to implement it on bar-by-bar basis, with use of FOR loop:

for( i = 0; i < BarCount; i++ )
{
  
if( Close[ i ] > Open[ i ] ) // CORRECT
       Color[ i ] =
colorGreen;
  
else
       Color[ i ] =
colorRed;
}

Plot( Close, "Colored Price", Color, styleCandle );

It is also possible in this case to use IIf( ) function:

Color = IIf( Close > Open, colorGreen, colorRed ); // ALSO CORRECT - working directly on arrays
Plot( Close, "Colored Price", Color, styleCandle );


Barcount vs BarIndex()

There is a fundamental difference between BarCount and BarIndex(). BarCount is a numeric variable that holds just one number (the count of elements in array). On the other hand BarIndex() is a function that returns ARRAY representing consecutive index of each bar.

EXAMPLE

Incorrect code:

for (i = 0; i < BarIndex();i++ ) // WRONG
{
  
// your formula
}

It’s not allowed to use ARRAY inside for loop, and Barindex() returns ARRAY. That is why it’s necessary to change the formula.

Correct code:

for (i =0 ; i < BarCount ;i++ )  // CORRECT
{
  //your formula
}


TimeFrameExpand( ) is required to match data with original time frame

The TimeFrameSet( ) replaces current price/volume arrays: open, high, low, close, volume, openint, avg with time-compressed bars of specified interval once you switched to a different time frame all calculations and built-in indicators operate on selected time frame. To get back to original interval call TimeFrameRestore( ) function. The TimeFrameExpand( ) is used to decompress array variables that were created in different time frame. Decompressing is required to properly display and use the array created in different time frame.

EXAMPLE

Incorrect code:

TimeFrameSet( inWeekly );
MA14_Weekly =
MA( Close, 14 );
TimeFrameRestore();
Buy =
Cross( Close, MA14_Weekly ); // WRONG - Close and MA15_Weekly use different time scales

The above formula is wrong, as MA14_Weekly variable should be EXPANDED to match original timeframe. The right contents should be:

Correct code:

TimeFrameSet( inWeekly );
MA14_Weekly =
MA( Close, 14 );
TimeFrameRestore();
Buy =
Cross( Close, TimeFrameExpand( MA14_Weekly, inWeekly ) ); // CORRECT, expanded weekly MA can be matched against daily close

EXAMPLE 2:

Incorrect code:

TimeFrameSet( inWeekly );
MA14_Weekly =
MA( Close, 14 );
TimeFrameRestore();
Buy =
Cross( Close, TimeFrameExpand( MA14_Weekly, inDaily ) ); // WRONG

It’s always necessary to indicate in TimeFrameExpand( ) function, which timeframe was  variable calculated in. So if MA14_Weekly was calculated in out of weekly data, inWeekly should be the correct parameter of TimeFrameExpand( ) function.

Correct code:

TimeFrameSet( inWeekly );
MA14_Weekly =
MA( Close, 14 );
TimeFrameRestore();
Buy =
Cross( Close, TimeFrameExpand( MA14_Weekly, inWeekly ) );
// CORRECT