A simple EA used by professionals in all markets. ATR trailing stop properly done.

 
I've scoured the internet for a good ATR trailing stop indicator and EA. I found 1 of each that have been the best thus far, but they are still awful. The indicator its fairly useful. Plots support and resistance ATR using the visual dots the PSAR uses. The EA is junk. I thinking of combining the indicator with the EA I have but I have never coded anything before. I came here for assistance and/or advise, maybe even links to well programmed ATR trailing stop indicator/EAs.
Here is what I got. I would prefer to have the indicator turned into a trailing stop EA.
I was trying to use the EA I already have as a template but they are very different and I ran into trouble.

The only problem with the indicator is it only shows Long/Buy order stops on Gold. Never shows Short position stops. I dont know if that can be worked out. I havent caught the issue in the coding to figure that one out.
The EA I dont like because its very glitchy. It will move stops very very tight, beyond the normal ATR sometimes, and sometimes much too wide. So I have chosen to make a EA from just the indicator.
Anyone able to show me how to turn the indicator into an EA? Also, to fix it so it works both ways on XAUUSD? Much Appreciated. My first attempted at coding anything ever.
I uploaded the indicator. I dont think the EA I have will be much help to any experienced coders who know what they are doing. Any Help will be really appreciated and getting a new MT4 user going on the right foot. Looking forward to contributing to this forum and meeting other traders and programmers. Thanks guys. Much respect to you. Namaste. _/\_
Atr Trailing Stop Indicator

ATRTrailing StopGold

Files:
 
Threshold: show me how to turn the indicator into an EA?
  1. You don't (not easily.) You get the indicator values via iCustom
  2. You have only three choices: Search for it, learn to code it, or pay someone. We're not going to code it FOR you. We are willing to HELP you when you post your attempt (using SRC) and the nature of your problem.
  3. "properly done?" The indicator posted is broken.
             PricePrev = (High[i-1] + Low[i-1])/2;
     :
             PricePrev = Close[i-1];           // Previous is i+1
    :
             revUp=PricePrev - (iATR(NULL,0,ATRPeriod,i-1) * Factor);
 
Well I'm willing to learn. Thanks for the link. I think it should get me started off. I'll be back.
 
Interestingly changing the 'prev'ious values to +1 (I assume the logic is to push the indicator forward one, effectively making the current candle use the previous value) didnt change a thing. Indicator still works, except on Gold in which case it only shows stops for Longs. Clearly this is because of the digit placement of gold "xxxx.xx". No problem on silver which is "xx.xxx"
 

It has nothing to do with the price format. It is the bar index accessed in a loop using the counter i. High[i+1] refers to the highest price of the previous bar. High[i-1] refers to the next future bar.

Using High[i-1] in the calculation gives an artificial result that only works on historical bars where each bar already has a future bar.

Obviously that cannot happen on real live prices because High[i-1] is in the future.

 
Someone on a different board ended up showing me how to fix it. Here is the code:
//+------------------------------------------------------------------+
//|                                               ATR Trail Stop.mq4 |
//+------------------------------------------------------------------+
//fix, 2013.11.26, fxdaytrader: Should work with Gold etc. also now, problem seems to be fixed, fxdaytrader (Marc)

//---- indicator settings
#property  indicator_chart_window
#property  indicator_buffers 2
#property  indicator_color1  RoyalBlue
#property  indicator_width1  0
#property  indicator_style1  0
#property  indicator_color2  RoyalBlue
#property  indicator_width2  0
#property  indicator_style2  0

//---- indicator parameters
extern int BackPeriod = 2000;
extern int ATRPeriod = 20;
extern double Factor = 2;
extern bool MedianPrice = true;
extern bool MedianBase = true;
extern bool CloseBase = false;
extern double distance = 0;

      bool UseFix=true;//set to false if the indicator does not work as desired
double LvlDnDefaultValue = 1000;//fix

//---- indicator buffers
double     ind_buffer1[];
double     ind_buffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init() {
//---- drawing settings  
   //SetIndexStyle(0,DRAW_LINE,EMPTY,2);
   SetIndexStyle(0, DRAW_ARROW);
   SetIndexArrow(0, 159);
   SetIndexDrawBegin(0,ATRPeriod);
   SetIndexBuffer(0,ind_buffer1);
   //SetIndexStyle(1,DRAW_LINE,EMPTY,2);
   SetIndexStyle(1, DRAW_ARROW);
   SetIndexArrow(1, 159);
   SetIndexDrawBegin(1,ATRPeriod);
   SetIndexBuffer(1,ind_buffer2);

   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS)+2);
//---- name for DataWindow and indicator subwindow label
   IndicatorShortName("ATR Stop("+ATRPeriod+" * "+Factor+")");
   SetIndexLabel(0,"Support");
   SetIndexLabel(1,"Resistance");
//---- initialization done
   return(0);
  }
//+------------------------------------------------------------------+
//| Moving Averages Convergence/Divergence                           |
//+------------------------------------------------------------------+
int start()
  {
   int limit;
   int counted_bars=IndicatorCounted();
   double PrevUp, PrevDn;
   double CurrUp, CurrDn;
   double PriceCurr, PricePrev;
   double PriceLvl;
   double PriceHLorC;
   double LvlUp = 0;
   double LvlDn = LvlDnDefaultValue;//1000;//fix
   int Dir = 1;
   int InitDir;
//---- check for possible errors
   if(counted_bars<0) return(-1);
//---- last counted bar will be recounted
   //if(counted_bars>0) counted_bars--;
   if(counted_bars==0) counted_bars++;
   if (BackPeriod==0) limit=Bars-counted_bars; else limit=BackPeriod;
//---- fill in buffervalues
   InitDir = 0;
   for(int i=limit; i>=0; i--)
   {
      if (MedianPrice) PriceLvl = (High[i] + Low[i])/2;
      else PriceLvl = Close[i];  
      
      if (MedianBase) {
          PriceCurr = (High[i] + Low[i])/2;
          PricePrev = (High[i-1] + Low[i-1])/2;
          }
      else {
          PriceCurr = Close[i];
          PricePrev = Close[i-1];
         }
      
      if(InitDir == 0) {
         CurrUp=PriceCurr - (iATR(NULL,0,ATRPeriod,i) * Factor);
         PrevUp=PricePrev - (iATR(NULL,0,ATRPeriod,i-1) * Factor);
         CurrDn=PriceCurr + (iATR(NULL,0,ATRPeriod,i) * Factor);
         PrevDn=PricePrev + (iATR(NULL,0,ATRPeriod,i-1) * Factor);
           
         if (CurrUp > PrevUp) Dir = 1;
         LvlUp = CurrUp;
         if (CurrDn < PrevDn) Dir = -1;
         LvlDn = CurrDn;
         InitDir = 1;
       
      }
      
      CurrUp=PriceLvl - (iATR(NULL,0,ATRPeriod,i) * Factor);
      CurrDn=PriceLvl + (iATR(NULL,0,ATRPeriod,i) * Factor);

      //if (i==0) Comment("Dir:",Dir,",CurrUp:",CurrUp,",PrevUp:",PrevUp,",CurrDn:",CurrDn,",PrevDn:",PrevDn);
      if (Dir == 1) {
         if (CurrUp > LvlUp) {
            ind_buffer1[i] = CurrUp-distance;
            LvlUp = CurrUp;
         }
         else {
            ind_buffer1[i] = LvlUp-distance;
         }
         ind_buffer2[i] = EMPTY_VALUE;
         if (CloseBase) PriceHLorC = Close[i]; else PriceHLorC=Low[i];
         if (PriceHLorC < ind_buffer1[i]) {
            Dir = -1;
            if (UseFix) LvlDn = MathMax(CurrDn,LvlDnDefaultValue);//1000;//fix
             else if (!UseFix) LvlDn = 1000;
         }
      }
      
      if (Dir == -1) {
         if (CurrDn < LvlDn) {
            ind_buffer2[i] = CurrDn+distance;
            LvlDn = CurrDn;
         }
         else {
            ind_buffer2[i] = LvlDn+distance;
         }
         ind_buffer1[i] = EMPTY_VALUE;
         if (CloseBase) PriceHLorC = Close[i]; else PriceHLorC=High[i];
         if (PriceHLorC > ind_buffer2[i]) {
            Dir = 1;
            LvlUp = 0;
         }
      }
      
      if (Dir == 1) {
         if (CurrUp > LvlUp) {
            ind_buffer1[i] = CurrUp-distance;
            LvlUp = CurrUp;
         }
         else {
            ind_buffer1[i] = LvlUp-distance;
         }
         ind_buffer2[i] = EMPTY_VALUE;
         if (CloseBase) PriceHLorC = Close[i]; else PriceHLorC=Low[i];
         if (PriceHLorC < ind_buffer1[i]) {
            Dir = -1;
            if (UseFix) LvlDn = MathMax(CurrDn,LvlDnDefaultValue);//1000;//fix
             else if (!UseFix) LvlDn=1000;
         }
      }
      
      //if (ind_buffer1[0]!=EMPTY_VALUE && ind_buffer1[1]==EMPTY_VALUE) {ind_buffer1[i+1]=ind_buffer1[i];}
      //if (ind_buffer2[0]!=EMPTY_VALUE && ind_buffer2[1]==EMPTY_VALUE) {ind_buffer2[i+1]=ind_buffer2[i];}
      //Comment("support: "+ind_buffer1[1]+" | resistance: "+ind_buffer2[1]); 
   }

//---- done
   return(0);
  }
 
Threshold: Someone on a different board ended up showing me how to fix it. Here is the code:
  1. Really? you are still using i-1 in at least FIVE different places.
  2. Dir is undefined. It has to be retrieved from a buffer from previous bar and stored for the next one. or comment out the initDir=1 line and calculate it every bar.
 

As stated. The indicator works beautifully. I changed the Prev -1 to +1 and it did not change the function of the indicator whatsoever nor did it fix Gold only showing long support, so i reverted it back to -1. Use the indicator and see for yourself. I dont know coding, but I know a working indicator. I use it daily...

Someone also made the EA for me... for free...

 
Gold now fixed.
indicator
 
For the EA there is actually a very simple command to retrieve the indicator rather than converting it:
extern string th="ATR TrailingStop (call via iCustom, file ATRTrailStop_v3.mq4 needs to be in mt4/experts/indicators/-folder:";
 

can anyone change this code buy with sell and sell with buy ?

//+------------------------------------------------------------------+
//|                                                  ATR-Trailer.mq4 |
//|                                                    Andriy Moraru |
//|                                                                  |
//|                                                                                              |
//+------------------------------------------------------------------+


// Plain trailing stop EA with ATR-based stop-loss.

#define LONG 1
#define SHORT 2

extern int ATR_Period = 24;
extern int ATR_Multiplier = 3;
extern int StartWith = 1; // 1 - Short, 2 - Long
extern int Slippage = 100;      // Tolerated slippage in pips
extern double Lots = 0.1;
extern bool ECN_Mode = false; // Set to true if stop-loss should be added only after Position Open
extern int TakeProfit = 0; // In your broker's pips

extern int Magic = 123123123;

// Global variables
bool HaveShortPosition;
bool HaveLongPosition;


int LastPosition = 0;

int init()
{
   LastPosition = 3 - StartWith;
   return(0);
}

//+------------------------------------------------------------------+
//| Expert Every Tick Function                                       |
//+------------------------------------------------------------------+
int start()
{
        double SL = 0, TP = 0;
        
        if (IsTradeAllowed() == false) return(0);
        
   // Getting the ATR values
   double ATR = iATR(NULL, 0, ATR_Period, 0);
   ATR *= ATR_Multiplier;

   if (ATR <= (MarketInfo(Symbol(), MODE_STOPLEVEL) + MarketInfo(Symbol(), MODE_SPREAD)) * Point)
        ATR = (MarketInfo(Symbol(), MODE_STOPLEVEL) + MarketInfo(Symbol(), MODE_SPREAD)) * Point;

        // Check what position is currently open
        GetPositionStates();
  
        // Adjust SL and TP of the current position
        if ((HaveLongPosition) || (HaveShortPosition)) AdjustSLTP(ATR);
   else
        {
        // Buy condition
        if (LastPosition == SHORT)
        {
                        for (int i = 1; i < 10; i++)
                        {
                           RefreshRates();
                                // Bid and Ask are swapped to preserve the probabilities and decrease/increase profit/loss size
                        if (!ECN_Mode)
                        {
               SL = NormalizeDouble(Ask + ATR, Digits);
               if (TakeProfit > 0) TP = NormalizeDouble(Ask - TakeProfit * Point, Digits);

                        }
                                int result = OrderSend(Symbol(), OP_BUY, Lots, Bid, Slippage, SL, TP, "ATR-Trader", Magic, 0, Blue);
                                Sleep(1000);
            if (result == -1)
            {
               int e = GetLastError();
               Print(e);
            }
                                else return(0);
                        }
        }
        // Sell condition
        else if (LastPosition == LONG)
        {
                        for (i = 1; i < 10; i++)
                        {
                           RefreshRates();
                                // Bid and Ask are swapped to preserve the probabilities and decrease/increase profit/loss size
                      if (!ECN_Mode)
                      {
                                       SL = NormalizeDouble(Bid - ATR, Digits);

               if (TakeProfit > 0) TP = NormalizeDouble(Bid + TakeProfit * Point, Digits);
            }
                         result = OrderSend(Symbol(), OP_SELL, Lots, Ask, Slippage, SL, TP, "ATR-Trader", Magic, 0, Red);
                                Sleep(1000);
            if (result == -1)
            {
               e = GetLastError();
               Print(e);
            }
                                else return(0);
                        }
        }
        }
        
        return(0);
}

//+------------------------------------------------------------------+
//| Check What Position is Currently Open                                                                               |
//+------------------------------------------------------------------+
void GetPositionStates()
{
   int total = OrdersTotal();
   for (int cnt = 0; cnt < total; cnt++)
   {
      if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES) == false) continue;
      if (OrderMagicNumber() != Magic) continue;
      if (OrderSymbol() != Symbol()) continue;

      if (OrderType() == OP_BUY)
      {
                        HaveLongPosition = true;
                        HaveShortPosition = false;
                }
      else if (OrderType() == OP_SELL)
      {
                        HaveLongPosition = false;
                        HaveShortPosition = true;
                }
        if (HaveLongPosition) LastPosition = LONG;
        else if (HaveShortPosition) LastPosition = SHORT;
        return;
        }

   HaveLongPosition = false;
        HaveShortPosition = false;
}

//+------------------------------------------------------------------+
//| Adjust Stop-Loss and TakeProfit of the Open Position                                        |
//+------------------------------------------------------------------+
void AdjustSLTP(double SLparam)
{
   double TP = 0;
  
   int total = OrdersTotal();
   for (int cnt = 0; cnt < total; cnt++)
   {
      if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES) == false) continue;
      if (OrderMagicNumber() != Magic) continue;
      if (OrderSymbol() != Symbol()) continue;

      if (OrderType() == OP_BUY)
                {
                   RefreshRates();
                        double SL = NormalizeDouble(Bid - SLparam, Digits);
                        if (TakeProfit > 0) TP = NormalizeDouble(Bid + TakeProfit * Point, Digits);
                        if ((SL > NormalizeDouble(OrderStopLoss(), Digits)) || (NormalizeDouble(OrderStopLoss(), Digits) == 0) || ((TP > 0) && (NormalizeDouble(OrderTakeProfit(), Digits) == 0)))
                        {
                                for (int i = 0; i < 10; i++)
                                {
                   bool result = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0);
                   if (result) return;
                                }
                        }
                }
      else if (OrderType() == OP_SELL)
                {
                   RefreshRates();
                        SL = NormalizeDouble(Ask + SLparam, Digits);
                        if (TakeProfit > 0) TP = NormalizeDouble(Ask - TakeProfit * Point, Digits);
                        if ((SL < NormalizeDouble(OrderStopLoss(), Digits)) || (NormalizeDouble(OrderStopLoss(), Digits) == 0) || ((TP > 0) && (NormalizeDouble(OrderTakeProfit(), Digits) == 0)))
                        {
                                for (i = 0; i < 10; i++)
                                {
                   result = OrderModify(OrderTicket(), OrderOpenPrice(), SL, TP, 0);
                   if (result) return;
                                }
                        }
                }
        }
}
//+------------------------------------------------------------------+

Reason: