October 5, 2014
The AFL language contains many pre-defined words like: shapeUpArrow, stopTypeTrailing, colorRed, styleThick, inDaily and many more. These are examples of constants. As written in AFL language specification (http://www.amibroker.com/guide/a_language.html): Constants are tokens representing fixed numeric or character values.
To better explain what this means, let us consider example of PI constant, which equals 3.14159265358979….. PI is the name of constant we use this name in mathematical equations, because it is easier and more practical to use than using the numerical value each time. Constants in AFL serve the same purpose, each of these words represents certain value properly interpreted by the program in the context they are used.
That is why using the following statement in backtesting code:
ApplyStop( stopTypeTrailing, stopModePercent, 10 );
is much better to use than cryptic statement like:
ApplyStop( 2, 1, 10 );
Both commands are equivalent, because value of stopTypeTrailing constant equals 2 and value of stopModePercent constant equals 1, yet the first version is much more understandable.
There is also another reason to use pre-defined constants rather than hard-coded numbers in the code. If for any reason the internal value of given constant changes due to development needs – all formulas using constants will continue to work properly (because new version would interpret them properly), while hard-coded numbers may change the code execution. For example – inWeekly and inMonthly constants have changed with introduction of N*inDaily timeframes, however if we always used:
TimeFrameSet( in Weekly ); in the code, then such internal change does not really affect our formulas at all.
There is one more example worth discussing – in the documentation of PlotShapes function we can find:
Plot( Close, "Price", colorBlack, styleCandle );
Buy = Cross( MACD(), Signal() );
Sell = Cross( Signal(), MACD() );
shape = Buy * shapeUpArrow + Sell * shapeDownArrow;
PlotShapes( shape, IIf( Buy, colorGreen, colorRed ), 0, IIf( Buy, Low, High ) );
So – what does the multiplication mean in the above context? If we remember that constants are in fact just numbers, and boolean True in AFL has numeric value of 1, while boolean False has numeric value of 0, then:
– if Buy is True (equals 1) and Sell is False (equals 0), then the result of such calculation will be
shape = 1 * shapeUpArrow + 0 * shapeDownArrow = shapeUpArrow
– if Buy is False (equals 0) and Sell is True (equals 1), then the result of such calculation will be:
shape = 0 * shapeUpArrow + 1 * shapeDownArrow = shapeDownArrow
The above approach is kind of shortcut that saves using conditional statements. It would work correctly only if Buy and Sell signals never occur on the same bar and only if we assign just 0 or 1 (False / True) to Buy and Sell arrays. Otherwise the result of calculations would be different. The internal value of shapeUpArrow is 1 and ShapeDownArrow is 2, so in situation, where both Buy and Sell signals were true, we would get
shape = 1 * shapeUpArrow + 1 * shapeDownArrow = shapeUpArrow + shapeDownArrow = 1 + 2 = 3
So – we would then pass number 3 to PlotShapes function and this is neither shapeUpArrow nor ShapeDownArrow, but a different shape. That is why in general case it is better to use conditional function IIf, like shown below:
shape = IIf( Buy, shapeUpArrow, IIf( Sell, shapeDownArrow, shapeNone ) );
This way we are always sure that returned value will be shapeUpArrow or shapeDownArrow or shapeNone.