Hi
I have a goal to understand applystop and afl in more detail.
I would like to code a couple of simple applystop modes, as opposed to using the applystop function itself via the backtester, purely as an exercise in understanding it.
I have read the applystop documentation and looked through this forum around applystop and there is great information about it. Additionally I have read thru Dr Bandy’s Book however, I have not been able to find sample code which simulates (using AFL for loops) some of the applystop modes/features.
I have the following code, which is a simple trending system, it includes the following applystops
The applystops I am trying to replicate are the following:
ApplyStop(stopTypeProfit, stopModePoint, ProfitATR, 1, False );
ApplyStop(stopTypeTrailing, stopModePoint, StopATR, 1, False );
ApplyStop( stopTypeNBar, stopModeBars, NBARS);
SetOption("MaxOpenPositions", 10);
SetOption("InitialEquity", 10000);
// backtesting
SetOption("AllowSameBarExit", True);
SetOption("ActivateStopsImmediately",False);
SetOption("AllowPositionShrinking", True);
SetPositionSize( 100000 / 10, spsValue);
SetTradeDelays(0,0,0,0);
// Buy & Sell
Buy = Sell = Short = Cover = 0;
BuyPrice = SellPrice = Open;
ShortPrice = CoverPrice = 0;
//=====================================================
// Volume Filter (VF) - Volume
Volume_Threshold = 5000000; // Weekly threshold
TurnoverOK = Weekly_Avg_TurnOver = Ref(MA(Volume * Close,10),-1);
//=====================================================
// Universe Trend Filter - UTF
TrendOK = EMA( C, 28 ) > EMA(C, 48);
//=====================================================
// Universe Price Filter - UPF
MinPrice = 0.2;
MaxPrice = 2000;
PriceOK = MA(C,10) > MinPrice AND MA(C,10) < MaxPrice;
//====================================================
// *** SMACD for positionScore***
mafast_Param = 20;
maslow_Param = 26;
SMACD_smooth = 9;//Optimize("SMACD_smooth_Param", 9, 5, 12, 1);
mafast = ma(C,mafast_Param);
maslow = ma(C,maslow_Param);
SMACD_osc = ((mafast - maslow)/C)*100; //SMAC fast
SMACD_signal = ma(SMACD_osc,SMACD_smooth); //SMAC slower
Tradeable = TurnOverOK AND PriceOK AND TrendOK;
PositionScore = Max(SMACD_signal + 100,0);
Buy = EMA(C,4)> EMA(C,15) AND TradeAble;
Sell = EMA(C,15)> EMA(C,4);
///https://www.amibroker.com/guide/afl/applystop.html
//ApplyStop( type, mode, amount, exitatstop, volatile = False, ReEntryDelay = 0, ValidFrom = 0, ValidTo = -1 )
//ExitAtStop
/*
ExitAtStop = 0 - means check stops using only trade price and exit at regular trade price(1)
(if you are trading on close it means that only close price will be checked for exits and exit will be done at close price)
ExitAtStop = 1 - check High-Low prices and exit intraday on price equal to stop level on the same bar when stop was triggered
ExitAtStop = 2 - check High-Low prices but exit NEXT BAR on regular trade price.
*/
ProfitATR = 10 *ATR(10); //Percentage
StopATR = 5 * ATR(10);
NBARS = 30;
//## 3 types of Applystop
/*
ApplyStop(stopTypeProfit, stopModePoint, ProfitATR, 1, False );
ApplyStop(stopTypeTrailing, stopModePoint, StopATR, 1, False );
ApplyStop( stopTypeNBar, stopModeBars, NBARS);
*/
//## Following mimics the respective applyStops above by looping through all the bars and testing each condition etc.
// If the following is uncommented then comment out the respective applystop statements above.
PriceAtBuy = 0; // IF not 0 then we it is in a trade
HighSinceBuy = 0; // Highest price since buy required for chandelier
Exit = 0; //True if we are in exit mode, can be used for scalling out
BarsSinceBuy = 0;
for( i = 0; i < BarCount; i++ )
{
if( PriceAtBuy == 0 AND Buy[i] == 1 )
{
PriceAtBuy = BuyPrice[i]; // We have a new buy
}
else if( PriceAtBuy > 0 )
{
// if here, we must be in the trade
HighSinceBuy = Max( High[i], HighSinceBuy ); //keeps track of high price in trade for chandelier stop, not used in this case
BarsSinceBuy++;
//## PROFIT TARGET HIT -EXIT ApplyStop(stopTypeProfit, stopModePoint, ProfitATR, 1, False )
if(Exit==0 AND H[i] >= ((1 + ProfitATR[i]*0.01) * PriceAtBuy))
{
Exit = 1;
SellPrice[i] = Close[i]; //or do we use high price?
}
//## TRAILING STOP -EXIT ApplyStop(stopTypeTrailing, stopModePoint, StopATR, 1, False );
if(L[i] <= ( 1 - StopATR[i] * 0.01 ) )
{
Exit = 2;
SellPrice[i] = Close[i]; //or do we use low price?
}
//##TIMESTOP - EXIT ApplyStop( stopTypeNBar, stopModeBars, NBARS);
if ( BarsSinceBuy >= NBARS )
{
Exit = 3;
SellPrice[i] = Close[i];
}
//# REQUIRED FOR RESETTING COUNTERS IN THIS LOOP
if( Exit >= 1 ) //reset
{
Buy[i] = 0;
Sell[i] = Exit + 1; // mark appropriate exit code
Exit = 0;
PriceAtBuy = 0;
HighSinceBuy = 0;
BarsSinceBuy = 0;
}
}
}
//### End of alternative APPLY STOP
I have attempted to add AFL code to replace each of these applystops individually, however I am not able to get same the results (from backtesting) between the applystops and my AFL version of it. FYI I comment out the relevant sections in the code to isolate each applystop.
My objective it to have same/similar results from backtesting when using applystop and my AFL version to confirm my understanding.
Would be appreciated if someone could assist with my understanding (from the code) with the applystop. I am sure this would benefit others as well.
Thanks
Richard