*********************************************************
Latest Update:
AFL modified
Last update on: 01 Jan 2010
*********************************************************
The modified portion is in MAGENTA Color
Hi Friends,
Now let us go into the details of system and the AFL. Here instead of just posting the AFL, I will describe the step-by-step development of the AFL based on the idea in our mind. This may be unnecessary for experts but will be useful for those who are new to AFL writing and want to learn to write their own AFL for their own trading ideas. It also helps in understanding the AFL in complete detail so that the experts can understand my logic and do their own tweaking and modifications. So, Let us start.
As I have already written in the earlier post, the strategy is based on Moving Average. The core of the strategy is, therefore, Buy when Price goes above the Moving Average and Sell when it goes below. Appears too simple but more refinement is required. We will represent the Moving Average by a variable A. The period of averaging is P. So, Buy = Close > A and Sell = Close < A, A = Moving Avg(Close, P).
Before Writing the AFL let us list what we want out of the AFL. My expectations from the AFL are:
1. It should give me Buy and Sell Signals and show these signals on chart
2. It should indicate on chart on which candle the Buy/Sell trigger is generated and print the message also indicating the trigger and the action to be taken next day.
3. It should show the present status whether the stock is in Buy-Hold or in Sell-Hold condition
4. In Buy-Hold condition it show on the chart the current profit/Loss at each candle
5. In Buy-Hold condition it should show the next Target expected and the stop loss
6. In Sell-Hold condition it should show the profit/loss made in the previous trade.
7. On the chart it should show the Target and Stop Loss as straight lines between which the price is moving
8. When target is reached, announce it on the chart and automatically calculate the next Target and Stop Loss and show on the chart.
9. For any selected day Generate reports giving the Buy-Sell triggers generated, the targets/Stop Loss reached and daily update of the stocks which have already given Buy Trigger.
10. Add Bollinger Bands to chart optionally, default no BB added. BB period and Width should be changeable without affecting Averaging period.
Quite a long list of expectations? Then the AFL should be very long and complicated. Is it so?
No, it is not that difficult to code these and the AFL will not be very long and complicated.
Now let us develop the AFL and incorporate our expectations into it.
You may later use this AFL as part of another strategy. For this purpose we will confine this AFL code in a separate Section. This can be done in AMiBroker AFL by enclosing the code between two statements:
*************************************
_SECTION_BEGIN(SingleMA);
(All of the AFL code here)
_SECTION_END();
**************************************
I have tested four types of Moving Averages: Simple, Exponential, Wilders and Linear Regression. Linear regression gives some very good triggers but it changes depending on future prices. Therefore I have eliminated it. We will have remaining three of them available in the same AFL and select whichever we want. I have put Wilders MA as default and the other two as options. I have found 20-day period of averaging good enough but we will have option of changing this also as required. We will also specify the type of report we would like to get: Triggers report, Update Report, Target / SL reached report. As we want charts also display the information, we define some options for charts also. The code for these is as follows:
************************************************
_SECTION_BEGIN(SingleMA);
SetChartOptions(0, chartShowDates | chartWrapTitle);
Type = ParamList(Average Type, Wilders,SMA,EMA);
P = Param(Averaging Period, 20, 3, 100);
Report = ParamList(Trigs or Update or Tgt-SL, Triggers,Update,Tgt-SL);
Q = Param(%Change, 1, 0.1, 10, 0.1);
BP = Param("BB period", 20, 3, 100);
BW = Param("BB Width", 2, 0.5, 10, 0.5);
BBOption = ParamToggle("Plot BB?", "NO | YES");
If(Type == SMA) A = MA(C, P);
If(Type == EMA) A = EMA(C, P);
If(Type == Wilders) A = Wilders(C, P);
************************************************
Note the double = signs in the above if statements. Q is a number we use to define the percent change in price to determine Peaks and troghs in the prices. The default is 1.
Now define top and bottom Bollinger Bands. BB period is BP, BB width is BW and BB is based on Closing Price:
************************************************
BBTop = BBandTop(C, BP, BW);
BBBot = BBandBot(C, BP, BW);
************************************************
We define Stop Loss as the higher of lowest low in last 5 days or the previous trough and Target as two times the High on the day of Buy Trigger minus the Stop Loss. The code follows:
**************************************
SL = Max(Trough(Low, Q, 1), LLV(L, 5));
Tgt = 2 * High SL;
MeanPrice = (Open + Close) / 2;
****************************************
Mean price is average of Open and Close for the day. This is used to calculate buy and sell prices and profit/loss made. As we can not enter the actual buy/sell prices we use these figures. The calculated profit/loss will slightly differ from actual but it is sufficient to get an idea of our portfolio value.
A Buy or Sell condition when price (Closing price of the day) goes above or below the average A will lead to many false signals. Therefore, we take a Buy condition only if the whole candle is above the Moving Average and Sell when it is completely below. I found that the Sell condition is okay but if we wait till the whole candle goes above the average it will have some delay. By experimenting with different values I found that if about 70% of candle is above the Average is good enough and acceptable. Therefore, we should determine the part of the candle which is above the Average.
When the low of the candle is just touching the average (Low = Average) the candle is 100% above. When the High is just touching the Average (High = Average) the candle is 0% above Average. The average line cutting across the candle means a part of the candle is above. So (High Average) divided by (High Low) and then multiplied by 100 gives the part of candle above the average in percentage. We code this as follows:
**********************************
Part = 100 * (H A) / (H L);
Buy = (C > A) AND (Part > 70);
Sell = H < A;
************************************
This will give Buy for every candle which is 70% or more above A and Sell for every candle below A. We want only the first candle which is a Buy and only the first candle which is Sell. So, we remove all subsequent Buy/Sell signals till an opposite signal is found. So, the code is:
**********************************
Buy = ExRem(Buy, Sell);
Sell = ExRem(Sell, Buy);
**********************************
In between the Buy and next Sell signal the stock is in BOUGHT condition or Buy-Hold (BH) as Savant calls it. Similarly between Sell and next Buy signal the stock is in SOLD condition (or Sell-Hold). We code this as:
********************************
Bought = Flip(Buy, Sell);
Sold = Flip(Sell, Buy);
*********************************
The Target Price calculation code is:
****************************************
NextTgt = ValueWhen(Buy, Tgt, 1);
*****************************************
When the Stock reaches its Target we should shift the Target price to the next value. This happens only when the stock is in Bought condition and not when the Buy trigger is generated. Similarly, the Stop Loss also is raised when a higher low is made after buying (Bought condition). This we code as follows:
************************************
For(i = 1; i < BarCount; i++)
{
If(Bought AND NOT Buy)
{
SL = Max(SL, SL[i 1]);
If(C[i 1] >= NextTgt[i 1]) NextTgt = Tgt[i 1];
NextTgt = Max(NextTgt, NextTgt[i 1]);
}
}
**************************************
For reporting the current status of the stock and profit/loss made we should know when the stock was bought, at what price it was bought and at what price it was sold. Similarly we should know whether the stock reached target or hit the stop loss. These are coded as follows:
***********************************************
BuyDate = ValueWhen(Buy, Ref(DateTime(), 1), 1);
BuyPrice = ValueWhen(Buy, Ref(MeanPrice, 1), 1);
SellPrice = ValueWhen(Sell, Ref(MeanPrice, 1), 1);
TgtReached = IIf(Bought AND NOT Buy AND C>= NextTgt, True, False);
SLHit = IIF(Bought AND NOT BUY AND C < SL, True, False);
SLHit = ExRem(SLHit, Buy);
************************************************
Now we have all the information computed by the AFL and now we want this to be displayed on the chart or shown in a report. First we take the case of displaying in the chart. The information can be displayed by including it in the chart title. This we do as follows:
********************************************
Ttl = EncodeColor(colorTurquoise) + Single MA System, AFL by ANANT NAVALE \n
+ WriteIf(Buy, EncodeColor(colorGreen) + Buy Triggered Today. Buy this stock tomorrow., )
+ WriteIf(Sell, EncodeColor(coloRed) + Sell Triggered Today. Sell this Stock Tomorrow., )
+ EncodeColor(colorTan) + WriteIf(Bought AND NOT Buy, Bought @ + BuyPrice + .
+ Target Price = + NextTgt + , Stop Loss = + SL + .\n
+ WriteIf(TgtReached, Target Reached. Next Target = + Ref(NextTgt, 1) + .\n, )
+ EncodeColor(colorGold) + Profit / Loss so far =
+ Prec(100 * (C BuyPrice) / (BuyPrice, 2) + %, )
+ WriteIf(Sold AND NOT Sell, Sold @ + SellPrice + \nProfit / Loss in previous trade =
+ Prec(100 * (SellPrice BuyPrice) / BuyPrice, 2) + %, );
*********************************************
In the above code you can replace my name with yours if you want.
Finally the title to display is:
*********************************************
_N(Title = StrFormat({{NAME}} ({{INTERVAL}}), {{DATE}} ; O=%g, H=%g, L=%g, L=%g, C=%g, {{VALUES}}\n\n, O, H, L, C) + Ttl);
**********************************************
We will show Arrow marks on the chart at the candles where the Buy/Sell signals are generated.
Now plot the chart with Buy/Sell Arrows
***********************************************
If(Status(action) == actionIndicator)
{
PlotOHLC(O, H, L, C, , colorLightGrey, styleBar);
Plot(A, Type + ( + P +), colorYellow, styleLine | styleThick);
Plot(IIf(Bought, NextTgt, Null), Target, colorBlueGrey, styleLine);
Plot(SL, Trail SL, colorTeal, styleLine);
Plotshapes(Marker, MarkerColor, 0, MarkerDist);
if(BBOption) Plot(BBTop, "BB-Top", colorPink, styleLine);
if(BBOption) Plot(BBBot, "BB-Bottom", colorPink, styleLine);
PlotShapes(IIf(Buy, shapeSquare, shapeNone),colorLime, 0,L, Offset=-50);
PlotShapes(IIf(Buy, shapeUpArrow, shapeNone),colorWhite, 0,L, Offset=-45);
PlotShapes(IIf(Sell, shapeSquare, shapeNone),colorRed, 0, H, Offset=40);
PlotShapes(IIf(Sell, shapeSquare, shapeNone),colorOrange, 0,H, Offset=50);
PlotShapes(IIf(Sell, shapeDownArrow, shapeNone),colorWhite, 0,H, Offset=-45);
}
*******************************************
To get different reports:
Triggers report
*******************************************
if((Status(action) == actionExplore) AND Report == Triggers)
{
Filter = Buy OR Sell;
SetOption(NoDefaultColumns, True);
AddTextColumn(Name(), Symbol, 77, colorDefault, colorDefault, 120);
AddColumn(DateTime(), Trigger Date, formatDateTime);
AddColumn(IIf(Buy, 66, 83), Signal, formatChar, colorYellow, IIf(Buy, colorGreen, colorRed);
AddColumn(C, C. M. P., 6.2);
AddColumn(IIf(Buy OR bought, NextTgt, Null), Target, 6.2);
AddColumn(IIf(Buy OR Bought, SL, Null), Stop Loss, 6.2);
}
***********************************
For updating:
****************************************
If((Status(action) == actioExplore) AND Report == Update)
{
Filter = True;
SetOption(NoDefaultColumns, True);
ADDColumn(DateTime(), Updated on, formatDateTime);
AddTextColumn(Name(), Symbol, 77, colorDefault, colorDefault, 120);
AddColumn(BuyDate, Buy Date, formatDateTime);
AddColumn(BuyPrice, Buy Price, 6.2);
AddColumn(NextTgt, Target, 6.2);
AddColumn(SL, StopLoss, 6.2);
AddColumn(C, C. M. P., 6.2);
}
*******************************************
For Target/Stoploss Hit Report:
******************************************
if(Status(action) == actionExplore AND Report == Tgt-SL
{
Filter = TgtReached OR SLHit;
SetOption(NoDefaultColumns, True);
AddColumn(DateTime(), Updated on, formatDateTime);
AddTextColumn(Name(), Symbol, 77, colorDefault, colorDefault, 120);
AddColumn(BuyDate, Buy Date, formatDateTime);
AddColumn(BuyPrice, Buy Price, 6.2);
AddColumn(NextTgt, Target, 6.2);
AddColumn(SL, StopLoss, 6.2);
AddColumn(C, C. M. P., 6.2);
AddColumn(IIf(TgtReached, 89, 32), Tgt Hit?, formatChar, colorYellow, IIf(TgtReached, colorGreen, colorDefault));
AddColumn(IIf(SLHit, 89, 32), SL Hit?, formatChar, colorYellow, IIF(SLHit, colorRed, colorDefault));
}
******************************************
The complete modified AFL file is available here. You can download it and save in your Formulas/Custom folder. To plot the chart double click on it and to get reports run it in Analysis.
You may post all your queries, comments and suggestions and I will try to answer them as much as possible.
I am using a list if about 300 stocks to track trading signals using the AFL. The list can be obtained from the following link.
Stocks List
Regards
-Anant