Percentage Trail Stop

 

Hello, I programmed part of this EA. I modified it for different levels of profit which would then have a % trail stop. So that 20 pips would have 40% trail stop or 8 pips locked in. The EA compiles with zero errors however I am not sure it is running correctly as it seems that the trail stop moves backwards at time. Also it seems to recalculate weirdly. I was wondering if someone could check this coding as I have been programming for 3-4 months and not really familiar with the order/trailing stop component of an EA. Thanks

/+------------------------------------------------------------------+
//| Blueprint.mq4 |
//| Campbell Congdon |
//| campbell_congdon@hotmail.com |
//+------------------------------------------------------------------+
#property copyright "Campbell Congdon"
#property link "campbell_congdon@hotmail.com"
extern double InitialTrailingStop = 10;
extern double trailing_stop_percentage = 20;
extern double SecTrailingStop = 20;
extern double sec_trailing_stop_percentage = 40;
extern double ThirdTrailingStop = 30;
extern double thr_trailing_stop_percentage = 50;
extern double FourthTrailingStop = 40;
extern double fourth_trailing_stop_percentage = 60;
extern double FifthTrailingStop = 60;
extern double fifth_trailing_stop_percentage = 70;

// Set it to some value above 0 to activate stop-loss
extern double StopLoss = 40;

//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{double PointValue;
for (int i = 0; i < OrdersTotal(); i++)
{
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
//Calculate the point value in case there are extra digits in the quotes
if (MarketInfo(OrderSymbol(), MODE_POINT) == 0.00001) PointValue = 0.0001;
else if (MarketInfo(OrderSymbol(), MODE_POINT) == 0.001) PointValue = 0.01;
else PointValue = MarketInfo(OrderSymbol(), MODE_POINT);
//Normalize trailing stop value to the point value
double TSTP = InitialTrailingStop * PointValue;
double TSTP2 = SecTrailingStop * PointValue;
double TSTP3 = ThirdTrailingStop * PointValue;
double TSTP4 = FourthTrailingStop * PointValue;
double TSTP5 = FifthTrailingStop * PointValue;


if (OrderType() == OP_BUY)
{
if ((trailing_stop_percentage > 0) && (Bid - OrderOpenPrice() >= TSTP))
{ TSTP = NormalizeDouble((Bid - OrderOpenPrice()) * trailing_stop_percentage / 100, Digits);
{ if (OrderStopLoss() < (Bid - TSTP))
{ OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TSTP, OrderTakeProfit(), Red);
}
}
}
}
{ if ((sec_trailing_stop_percentage > 0) && (Bid - OrderOpenPrice() >= TSTP2))
{ TSTP2 = NormalizeDouble((Bid - OrderOpenPrice()) * sec_trailing_stop_percentage / 100, Digits);
{ if (OrderStopLoss() < (Bid - TSTP2))
{ OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TSTP2, OrderTakeProfit(), Red);
}
}
}
}

{ if ((thr_trailing_stop_percentage > 0) && (Bid - OrderOpenPrice() >= TSTP3))
{ TSTP3 = NormalizeDouble((Bid - OrderOpenPrice()) * thr_trailing_stop_percentage / 100, Digits);
{ if (OrderStopLoss() < (Bid - TSTP3))
{ OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TSTP3, OrderTakeProfit(), Red);
}
}
}
}
{if ((fourth_trailing_stop_percentage > 0) && (Bid - OrderOpenPrice() >= TSTP4))
{ TSTP4 = NormalizeDouble((Bid - OrderOpenPrice()) * fourth_trailing_stop_percentage / 100, Digits);
{ if (OrderStopLoss() < (Bid - TSTP4))
{ OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TSTP4, OrderTakeProfit(), Red);
}
}
}
}
{if ((fifth_trailing_stop_percentage > 0) && (Bid - OrderOpenPrice() >= TSTP5))
{ TSTP5 = NormalizeDouble((Bid - OrderOpenPrice()) * fifth_trailing_stop_percentage / 100, Digits);
{ if (OrderStopLoss() < (Bid - TSTP5))
{ OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TSTP5, OrderTakeProfit(), Red);
}
}
}

else if ((OrderStopLoss() != Bid - StopLoss * PointValue) && (StopLoss != 0))
OrderModify(OrderTicket(), OrderOpenPrice(), Bid - StopLoss * PointValue, OrderTakeProfit(), Red);

else if (OrderType() == OP_SELL)

if ((trailing_stop_percentage > 0) && (OrderOpenPrice() - Ask >= TSTP))
{ TSTP = NormalizeDouble((OrderOpenPrice() - Ask) * trailing_stop_percentage / 100, Digits);
{ if ((OrderStopLoss() > (Ask + InitialTrailingStop * PointValue)) || (OrderStopLoss() == 0))
{OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TSTP, OrderTakeProfit(), Red);
}
}
}

if ((sec_trailing_stop_percentage > 0) && (OrderOpenPrice() - Ask >= TSTP2))
{ TSTP2 = NormalizeDouble((OrderOpenPrice() - Ask) * sec_trailing_stop_percentage / 100, Digits);
{ if ((OrderStopLoss() > (Ask + SecTrailingStop * PointValue)) || (OrderStopLoss() == 0))
{ OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TSTP2, OrderTakeProfit(), Red);
}
}
}


if ((thr_trailing_stop_percentage > 0) && (OrderOpenPrice() - Ask >= TSTP3))
{ TSTP3 = NormalizeDouble((OrderOpenPrice() - Ask) * thr_trailing_stop_percentage / 100, Digits);
{ if ((OrderStopLoss() > (Ask + ThirdTrailingStop * PointValue)) || (OrderStopLoss() == 0))
{ OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TSTP3, OrderTakeProfit(), Red);
}
}
}

{ if ((fourth_trailing_stop_percentage > 0) && (OrderOpenPrice() - Ask >= TSTP4))
{ TSTP4 = NormalizeDouble((OrderOpenPrice() - Ask) * fourth_trailing_stop_percentage / 100, Digits);
{ if ((OrderStopLoss() > (Ask + FourthTrailingStop * PointValue)) || (OrderStopLoss() == 0))
{ OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TSTP4, OrderTakeProfit(), Red);
}
}
}
}
if ((fifth_trailing_stop_percentage > 0) && (OrderOpenPrice() - Ask >= TSTP5))
{ TSTP5 = NormalizeDouble((OrderOpenPrice() - Ask) * fifth_trailing_stop_percentage / 100, Digits);
{ if ((OrderStopLoss() > (Ask + FifthTrailingStop * PointValue)) || (OrderStopLoss() == 0))
{ OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TSTP5, OrderTakeProfit(), Red);
}

}
}

else if ((OrderStopLoss() != Ask + StopLoss * PointValue) && (StopLoss != 0))
OrderModify(OrderTicket(), OrderOpenPrice(), Ask + StopLoss * PointValue, OrderTakeProfit(), Red);
}
}

//----

//----
return(0);
}
//+------------------------------------------------------------------

 
 

Check-Out this Article, includes hints about trailing stops.

 

I believe this part of the code is why I am seeing the trailing stop move backwards and forwards:

for(cnt=0;cnt<total;cnt++)
This is from your link. If I change this count would that stop the trailing stop from moving backwards?

thanks

 

This is the one from the article I was referring to.

should the trailing stop be reset?
We set the trailing stop only in case the position already has a profit exceeding the trailing stop level in points, and in case the new level of the stop is better than the previous.

// check for trailing stop
if(TrailingStop>0) { 
     if(Bid-OrderOpenPrice()>Point*TrailingStop) {
          if(OrderStopLoss() {
               OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop, OrderTakeProfit(),0,Green);
               return(0);
}}}
 

I still can't see why my trail stop would be moving backwards and forwards on price- I did a line by line comparison from the article to my EA

Standard from Article: My EA:

if(TrailingStop>0) {if ((fourth_trailing_stop_percentage > 0) && (Bid - OrderOpenPrice() >= TSTP4)) - I combined these into one line but that should not affect anything.

if(Bid-OrderOpenPrice()>Point*TrailingStop)

{ TSTP4 = NormalizeDouble((Bid - OrderOpenPrice()) * fourth_trailing_stop_percentage / 100, Digits); Maybe I should define this elsewhere?!

if(OrderStopLoss()<Bid-Point*TrailingStop) { if (OrderStopLoss() < (Bid - TSTP4)) - This should be performing the same function

OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop, { OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TSTP4,

OrderTakeProfit(),0,Green); OrderTakeProfit(), Red); This is the same line (function) with a different colour.

 

Here the sample codes should solve your Bouncing. Save as EA and test.

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~General Variables:
int     iReverse_Logic=1;
int     iMaximum_Slip=2;
//~~~~~~~~~~~~~~~OrderSend Variables:
int     iType;
double  iPrice;
int     iMagic=777;
color   iColor;
int     iSlippage;
double  iLot=0.1;
//~~~~~~~~~~~~~~~MarketInfo Variables:
int     iSpreads;
double  iPoint2Pip;
double  iPip2Point;
double  iPip2Real;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void start(){
    Get_Market_Info();
    //~~~~~~~~~~~~~~~
    if(OrdersTotal()==0){
        Get_Direction();
        OrderSend(Symbol(),iType,iLot,iPrice,iSlippage,0,0,
        "Comment: Magic="+iMagic+"  Spreads="+iSpreads,
        iMagic,0,iColor);
    }
    //~~~~~~~~~~~~~~~
    if(OrdersTotal()> 0){
        Get_Trail_Stop();
    }
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Get_Direction(){
    iReverse_Logic= -(iReverse_Logic);
    if(iReverse_Logic== 1){ iType=0; iPrice=Ask; iColor=Blue;}
    if(iReverse_Logic==-1){ iType=1; iPrice=Bid; iColor=Red; }
    iSlippage=iMaximum_Slip*iPip2Point;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Get_Market_Info(){
    iSpreads=MarketInfo(Symbol(),MODE_SPREAD);
    //~~~~~~~~~~iPoint2Pip:
    iPoint2Pip=Point;
    if(Digits==3){iPoint2Pip=0.01;}//------------------ Japanese Yen Standard Pip
    if(Digits==5){iPoint2Pip=0.0001;}//---------------- Other Currency Standard Pip
    //~~~~~~~~~~iPip2Real:
    if(Digits==2 || Digits==3){iPip2Real=100;}//------- Japanese Yen Standard Pip in Integer
    if(Digits==4 || Digits==5){iPip2Real=10000;}//----- Other Currency Standard Pip in Integer
    //~~~~~~~~~~iPip2Point
    if(Digits==4){iPip2Point=1;}else{iPip2Point=10;}//- Turn Integer Standard Pip into Points
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Get_Trail_Stop(){
    int Direction;
    //~~~~~~~~~~~~~~~Arrays Index/Columns Corresponds
    int Pip_Gain_Modify_Trigger[5]=  {20, 40, 60, 80, 100};
    int Percentage_To_Lock_In[5]=    {40, 50, 60, 70, 80};
    int Order_Profit_In_Pips;
    int Lock_Value_In_Integer;
    int Stop_Distance_In_Integer;
    double New_StopLoss_Price;
    //~~~~~~~~~~~~~~~
    for(int i=OrdersTotal()-1; i>=0; i--){
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)
        && OrderSymbol()==Symbol()
        && OrderMagicNumber()==iMagic
        && OrderProfit()>0
        ){
            if(OrderType()==0){Direction=1;}else{Direction=-1;}
            for(int j=ArraySize(Pip_Gain_Modify_Trigger)-1; j>=0; j--){
                Order_Profit_In_Pips=MathAbs(OrderOpenPrice()-OrderClosePrice())*iPip2Real;
                if( Order_Profit_In_Pips == Pip_Gain_Modify_Trigger[j]){/* <------------------------This == Logic is Tick Dependent,
                Consider adding logic which can tell if OrderModify() have done the highest Pip_Gain_Trigger and tell it not to modify
                again until the next higher Level*/
                    Lock_Value_In_Integer=Order_Profit_In_Pips*(Percentage_To_Lock_In[j]*0.01);
                    Stop_Distance_In_Integer=MathAbs(Order_Profit_In_Pips-Lock_Value_In_Integer);
                    New_StopLoss_Price= (OrderClosePrice()-(iPoint2Pip*Stop_Distance_In_Integer)* Direction) ;
                    //Alert(New_StopLoss_Price);
                    if( OrderStopLoss()==0 || (New_StopLoss_Price-OrderStopLoss())*Direction >iPoint2Pip ){
                        OrderModify(OrderTicket(),OrderOpenPrice(),New_StopLoss_Price,OrderTakeProfit(),0,White);
                    }
                }
            }
        }
    }
    //~~~~~~~~~~~~~~~
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
For more on working with doubles and order-modify, follow the links within this thread.
 

Thanks for this. I have incorporated this into my EA and will test it. Its very different from the programming that I am use to. I will need to do more research.

Cheers

 
You're welcome.
 
ubzen:

Here the sample codes should solve your Bouncing. Save as EA and test.

Dear ubzen,

I'm testing the code in the latest version of MT4 but unfortunately it is not working.

This code is compatible with the latest version of MT4?


Thank you,

Rogério

Reason: