Mouteki EA 01.4





//+------------------------------------------------------------------+
//|                                              Mouteki EA v0.4.mq4 |
//|                                    Copyright 2006, Hua Ai (aha)  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2006, Hua Ai (aha)"
#property link      ""

// Ver 0.4 Added parameters to control the mark hours the EA is allowed
//         to enter a trade.
//

// Ver 0.3 Fixed a minor bug causing problems on finding right point
//         for trend lines.
//
// Ver 0.2
// Modiciations:
// 1. On a trend reversal, when the PP calculated based on the highs 
//    after the first point is smaller (consolidating) than that based 
//    on the highs between the first point and the 2nd point, use 
//    latter PP for calculating ST and TP.
// 2. When both TL are broken, only signal this special situation, not
//    to close any trades. When price break the Top TL again from that 
//    situation, close all the short trades and let the long trades
//    run. When price break the bottom TL again from that situation,
//    close all the long trades and let the short trades run.

// Ver 0.1
// Modifications:
// 1. Allow EA to enter a trade even 3 bars after TL breaks. This is
//    because sometimes we got whipsaw back below TL and then breaks
//    again, or sometimes, the break is not detectation by only 
//    checking the recent two bars.

// Determine trend lines:
// 1. Each time determine two trend lines: top trend line and bottom 
//    trend line.
// 2. Each trend line is determined by two points. Top trend line has
//    to be slopped downward from left to right. Bottom trend line 
//    has to be slopped upward from left to right.
// 3. The 1st point for the top trend line is the most recent high.
//    The 2nd point is the most recent high that is higher than the
//    1st point.
// 4. The 1st point for the bottom trend line is the most recent low.
//    The 2nd point is the most recent low that is lower than the
//    1st point.
// 5. A bar is qualified as a high when it's high is the highest among 
//    the 5 bars centered at this bar. A bar is qualified as a low when
//    it's low is the lowest among the 5 bars centered at this bar.

// Entry Conditions:
//
// 1. Enter long trade
//   1) Enter long when price open higher than the top trend line. The
//      entry price is the first open price above the top trend line.
//   2) Profit projection is determined by calculating the distance 
//      between the lowest low from the current bar to the 2nd point 
//      of the top trend line, and the trend line.
//   3) TP is calculated by adding the profit projection to the first
//      open price above the top trend line.
//   4) SL is calulated based on profit projection:
//     i.  When profit projection is less than 90 pips, set SL to half 
//         of the profit projection to create a 2:1 win/loss ratio.
//     ii. When profit project is greater than 90 pips, set SL to 33% 
//         of the profit projection to create a 3:1 win/loss ratio.
//
// 2. Enter short trade
//   1) Enter short when price open lower than the bottom trend line. 
//      The entry price is the first open price below the bottom trend
//      line.
//   2) Profit projection is determined by calculating the distance 
//      between the highest high from the current bar to the 2nd point 
//      of the bottom trend line, and the trend line.
//   3) TP is calculated by adding the profit projection to the first
//      open price below the bottom trend line.
//   4) SL is calulated based on profit projection:
//     i.  When profit projection is less than 90 pips, set SL to half 
//         of the profit projection to create a 2:1 win/loss ratio.
//     ii. When profit project is greater than 90 pips, set SL to 33% 
//         of the profit projection to create a 3:1 win/loss ratio.
//
// Condition to modify a trade:
// 
// 1. When profit is greater than ProfitToMoveSL pips, move the SL to +PositiveSL.
// 2. When a new trade setup is formed in the same direction of an 
//    existing trade:
//   1) Adjusting TP if the new TP is farther than the existing one.
//   2) Adjusting SL if the new SL is closer than the existing one.
//   3) May add a position based on the new setup if there is only 
//      one trade exists.
//
// Conditions to close a trade:
//
// 1. TP is hit.
// 2. SL is hit.
// 3. A new trade setup is formed in a reversed direction of the 
//    existing trade.
//
// Timing:
//
// 1. The first 10 seconds of every 4 hours:
//   1) Check entry conditions.
//   2) Check new setups -- may open new position and/or close old 
//      positions.
//   3) Condition to modify SL. (This items was checked every tick but
//      was proved not good, it tends to cut profits a lot. So now this
//      is checked every 4 hours as well)
// 

extern bool    AlertsOn=true;
extern bool    MultiPositions=false;
extern double  LotsPerTrade=1;
extern int     ProfitToMoveSL=40;
extern int     PositiveSL=10;
extern int     SL_Offset=0;
extern int     TP_Offset=0;
extern bool    LondonOpen=true;
extern bool    NewYorkOpen=true;
extern bool    TokyoOpen=true;

int         spread;
bool        TD=False;/*Default is false. True setting draws up and down arrows instead of dots on TD Points creating more clutter.*/ 
int         BackSteps=0;/*Used to be extern int now just int. Leave at 0*/
int         ShowingSteps=1;/*Used to be extern int now just int.  Leave at 1*/
bool        FractalAsTD=false;/*Used to be extern bool now just bool.  Leave at false, otherwise Trend Lines based on Fractal Points not TD Points*/
 
double      TrendLineBreakUp=-1;//Line added.
double      TrendLineBreakUpPrev=-1;//Line added.
double      TrendLineBreakUpPrev1=-1;//Line added.
bool        TrendLineBreakUpFlag=False;//Line added.
double      TrendLineBreakDown=-1;//Line added.
double      TrendLineBreakDownPrev=-1;//Line added.
double      TrendLineBreakDownPrev1=-1;//Line added.
bool        TrendLineBreakDownFlag=False;//Line added.
bool        BothTLBroken=false;

//---- buffers
double highs[100000];
double lows[100000];

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   spread = MarketInfo(Symbol(),MODE_SPREAD);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//--------------------------------------------------------------------
// Find the highs and lows in the current chart. 
int SetTDPoint(int B)
{
 int shift;
 if (FractalAsTD==false)
   {
    //Print("B = ",B);
    //Print("Bars = ",Bars);
    //Print("IndicatorCounted() = ",IndicatorCounted());
    //It seems B is the same as IndicatorCounted()function 
    for (shift=B;shift>2;shift--)
       {       
        
        // If the bar highs at the left are equal to current bar high, 
        // the current bar high is still a valid high.
        if (High[shift+2]<=High[shift] && High[shift+1]<=High[shift] && 
            High[shift-1]<High[shift]  && High[shift-2]<High[shift])
           highs[shift]=High[shift];
        //if(shift<100 && highs[shift]!=0) Print("shift=", shift, " highs[shift]=", highs[shift]);
            
        //else highs[shift]=0;
        
        // If the bar lows at the left are equal to current bar low, 
        // the current bar low is still a valid low.
        if (Low[shift+2]>=Low[shift] && Low[shift+1]>=Low[shift] && 
            Low[shift-1]>Low[shift]  && Low[shift-2]>Low[shift])
           lows[shift]=Low[shift];
        
        //else lows[shift]=0;    
       }  
    highs[0]=0;
    lows[0]=0;
    highs[1]=0;
    lows[1]=0;
   }
 else
   {
    for (shift=B;shift>3;shift--)
       {
        if (High[shift+1]<=High[shift] && High[shift-1]<High[shift] &&
            High[shift+2]<=High[shift] && High[shift-2]<High[shift])
             highs[shift]=High[shift];
        else highs[shift]=0;    
        if (Low[shift+1]>=Low[shift] && Low[shift-1]>Low[shift] && 
            Low[shift+2]>=Low[shift] && Low[shift-2]>Low[shift])
            lows[shift]=Low[shift];
        else lows[shift]=0;    
       }  
    highs[0]=0;
    lows[0]=0;
    highs[1]=0;
    lows[1]=0;
    highs[2]=0;
    lows[2]=0;    
   }  
 return(0);
}

//--------------------------------------------------------------------
int GetHighTD(int P)
{
 int i=0,j=0;
 while (j<P)
   {
    i++;
    while(highs[i]==0)
      {i++;if(i>Bars-2)return(-1);}
    j++;
   }   
 return (i);         
}
//--------------------------------------------------------------------
int GetNextHighTD(int P)
{ 
 int i=P+1;
 while(highs[i]<=High[P]){i++;if(i>Bars-2)return(-1);}
 return (i);
}
//--------------------------------------------------------------------
int GetLowTD(int P)
{
 int i=0,j=0;
 while (j<P)
   {
    i++;
    while(lows[i]==0)
      {i++;if(i>Bars-2)return(-1);}
    j++;
   }   
 return (i); 
}
//--------------------------------------------------------------------
int GetNextLowTD(int P)
{
 int i=P+1;
 while(lows[i]>=Low[P] || lows[i]==0){i++;if(i>Bars-2)return(-1);}
 return (i);
}
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
   int      cnt, H1, H2, L1, L2, ii, iii, pos, total, ticket;
   double   kH, kL, k, pp, tp, sl;
   
   //--------------------------------------------------------
   // The first 10 seconds of every 4 hours
   if (MathMod(Hour(),4)==0 && Minute()==0 && Seconds()<10)
   {
      //--------------------------------------------------------
      // Condition to modify ST
      // Whenever order profit reaches ProfitToMoveSL pips, move SL to +PositiveSL
      total=OrdersTotal();
      for(cnt=0;cnt<total;cnt++)
      {
         if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES)==true)
         {
            if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
            {
               if(OrderType()==OP_BUY && 
                  Bid-OrderOpenPrice()>=ProfitToMoveSL*Point &&
                  OrderOpenPrice()-OrderStopLoss()>=0)
               {
                  OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+PositiveSL*Point,OrderTakeProfit(),0);
                  continue;
               }
               if(OrderType()==OP_SELL &&
                  OrderOpenPrice()-Ask>=ProfitToMoveSL*Point &&
                  OrderOpenPrice()-OrderStopLoss()<=0)
               {
                  OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-PositiveSL*Point,OrderTakeProfit(),0);
                  continue;
               }
            }
         }
         else
            Print("OrderSelect returned the error of ",GetLastError());
      }
      
      
      // Where is the trend line?
      SetTDPoint(Bars-1);
      H1=GetHighTD(1);
      H2=GetNextHighTD(H1);
      L1=GetLowTD(1);
      L2=GetNextLowTD(L1);
      kH=(High[H2]-High[H1])/(H2-H1);
      kL=(Low[L1]-Low[L2])/(L2-L1);
      TrendLineBreakUp=High[H2]-kH*H2;
      TrendLineBreakUpPrev=High[H2]-kH*(H2-1);
      TrendLineBreakUpPrev1=High[H2]-kH*(H2-2);
      TrendLineBreakDown=Low[L2]+kL*L2;
      TrendLineBreakDownPrev=Low[L2]+kL*(L2-1);
      TrendLineBreakDownPrev1=Low[L2]+kL*(L2-2);

/*             
               Print("H1=", H1, " High[H1]=", High[H1]);
               Print("H2=", H2, " High[H2]=", High[H2]);
               Print("L1=", L1, " Low[L1]=", Low[L1]);
               Print("L2=", L2, " Low[L2]=", Low[L2]);
               Print("TrendLineBreakUp=", TrendLineBreakUp);
               Print("TrendLineBreakDown=", TrendLineBreakDown);
               Print("Open[0]=", Open[0], " Open[1]=", Open[1]);
*/
      
      //Top trend line and bottom trend line both broken? Wait!
      if(Open[0]>TrendLineBreakUp && Open[0]<TrendLineBreakDown)
        // && H2<50 && L2<50)
      {
/*
         total=OrdersTotal();
         for(cnt=0;cnt<total;cnt++)
         {
            if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES)==true)
            {
               if(OrderType()==OP_SELL && OrderSymbol()==Symbol())
               {
                  OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
                  continue;
               }
               
               if(OrderType()==OP_BUY && OrderSymbol()==Symbol())
               {
                  OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet);
                  continue;
               }
            }
            else
               Print("OrderSelect returned the error of ",GetLastError());
         }
*/
         BothTLBroken=true;
         ArrayInitialize(highs, 0.0);
         ArrayInitialize(lows, 0.0);
         return(0);
      }
      //Top trend line broken?
      /*if(Open[0]>TrendLineBreakUp && Open[0]>TrendLineBreakDown &&
         (Open[1]<TrendLineBreakUpPrev || Open[2]<TrendLineBreakUpPrev) &&
         H2<50 && L2<50)*/
      //if(Open[0]>TrendLineBreakUp &&
      //   (Open[1]<TrendLineBreakUpPrev || Open[2]<TrendLineBreakUpPrev))
      if((Open[0]>TrendLineBreakUp&&Open[0]>TrendLineBreakDown && (
          Open[1]<TrendLineBreakUpPrev||Open[2]<TrendLineBreakUpPrev1||
          Open[3]<TrendLineBreakUpPrev1)
         ) || (
          BothTLBroken==true && 
          Open[0]>TrendLineBreakUp&&Open[0]>TrendLineBreakDown && (
          Open[1]<TrendLineBreakDownPrev||Open[2]<TrendLineBreakDownPrev1||
          Open[3]<TrendLineBreakDownPrev1)
         ))
      {
         BothTLBroken=false;
         //Print("Upper TrendLine Break ",Symbol()," ",Period()," ",Bid);
         if(AlertsOn) 
            Alert("UTL Break>",TrendLineBreakUp," on ",Symbol()," ",Period()," @ ",Ask); 
         //TrendLineBreakUpFlag=True;
         
         // Calculate profit projection, stop loss, take profit
         ii=Lowest(NULL,0,MODE_LOW,H2-1,1);
         iii=Lowest(NULL,0,MODE_LOW,H2-H1,H1);
         pp=MathMax(High[H2]-kH*(H2-ii)-Low[ii], High[H2]-kH*(H2-iii)-Low[iii]);
         // Calculate TP and SL
         tp=pp-spread*Point+Open[0]+TP_Offset*Point;
         if (pp>90*Point) 
            sl=Open[0]-spread*Point-MathRound(10000*pp*0.33)/10000-SL_Offset*Point;
         else
            sl=Open[0]-spread*Point-MathRound(10000*pp*0.5)/10000-SL_Offset*Point;
         
         // Short exists? Close it. Long exists? Change it.
         total=OrdersTotal();
         pos=0;
         for(cnt=0;cnt<total;cnt++)
         {
            if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES)==true)
            {
               // Close the shorts
               if(OrderType()==OP_SELL && OrderSymbol()==Symbol())
               {
                  OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet);
                  continue;
               }
               
               // Modify the longs
               if(OrderType()==OP_BUY && OrderSymbol()==Symbol())
               {
                  pos++;
                  OrderModify(OrderTicket(),OrderOpenPrice(),sl,tp,0);
                  continue;
               }
            }
            else
               Print("OrderSelect returned the error of ",GetLastError());
         }
         
         //Print("pos=", pos, " MultiPositions=", MultiPositions);
         // Long at the break of top trend line
         //if (pos==0||MultiPositions)
         if ( ((LondonOpen==true  && Hour()>=7 && Hour()<=16)  || (NewYorkOpen==true && Hour()>=12 && Hour()<=21) || (TokyoOpen==true   && ((Hour()>=0 && Hour()<=8) || (Hour()>=23 && Hour()<=24)))) && (pos==0||MultiPositions) )
            {
               //Print("Ready to open a trade");
            
            ticket=OrderSend(Symbol(),OP_BUY,LotsPerTrade,Ask,3,sl,tp,"Mouteki",00011,0,Green);
            if(ticket>0)
            {
               if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) 
                  Print("Long order opened : ",OrderOpenPrice());
/*             
               Print("H1=", H1, " High[H1]=", High[H1]);
               Print("H2=", H2, " High[H2]=", High[H2]);
               Print("L1=", L1, " Low[L1]=", Low[L1]);
               Print("L2=", L2, " Low[L2]=", Low[L2]);
               Print("TrendLineBreakUp=", TrendLineBreakUp);
               Print("TrendLineBreakDown=", TrendLineBreakDown);
               Print("Open[0]=", Open[0], " Open[1]=", Open[1]);
*/
            }
            else Print("Error opening Long order : ",GetLastError()); 
         }
      }
      
      //Bottom trend line broken?
      /*if(Open[0]<TrendLineBreakDown && Open[0]<TrendLineBreakUp &&
         (Open[1]>TrendLineBreakDownPrev || Open[2]>TrendLineBreakDownPrev) &&
         H2<50 && L2<50)*/
      //if(Open[0]<TrendLineBreakDown &&
      //   (Open[1]>TrendLineBreakDownPrev || Open[2]>TrendLineBreakDownPrev))
      if((Open[0]<TrendLineBreakDown&&Open[0]<TrendLineBreakUp&&(
          Open[1]>TrendLineBreakDownPrev||Open[2]>TrendLineBreakDownPrev1||
          Open[3]>TrendLineBreakDownPrev1)
         ) || (
          BothTLBroken==true && 
          Open[0]<TrendLineBreakUp&&Open[0]<TrendLineBreakDown&&(
          Open[1]>TrendLineBreakUpPrev||Open[2]>TrendLineBreakUpPrev1||
          Open[3]>TrendLineBreakUpPrev1)
         ))
          
      {
         BothTLBroken=false;
         //Print("Lower Trendline Break ",Symbol()," ",Period()," ",Bid);
         if(AlertsOn)
            Alert("LTL Break<",TrendLineBreakDown," on ",Symbol()," ",Period()," @ ",Bid); 
         //TrendLineBreakDownFlag=True;

         // Calculate profit projection, stop loss, take profit
         ii=Highest(NULL,0,MODE_HIGH,L2-1,1);    
         iii=Highest(NULL,0,MODE_HIGH,L2-L1,L1);    
         pp=MathMax(High[ii]-(Low[L2]+kL*(L2-ii)), High[iii]-(Low[L2]+kL*(L2-iii)));
         // Calculate TP and SL
         tp=Open[0]-pp+spread*Point-TP_Offset*Point;
         if (pp>90*Point) 
            sl=Open[0]+spread*Point+MathRound(10000*pp*0.33)/10000+SL_Offset*Point;
         else
            sl=Open[0]+spread*Point+MathRound(10000*pp*0.5)/10000+SL_Offset*Point;
         
         // Long exists? Close it. Short exists? Change it.
         total=OrdersTotal();
         pos=0;
         for(cnt=0;cnt<total;cnt++)
         {
            if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES)==true)
            {
               // Close the longs
               if(OrderType()==OP_BUY && OrderSymbol()==Symbol())
               {
                  OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet);
                  continue;
               }
               
               // Modify the shorts
               if(OrderType()==OP_SELL && OrderSymbol()==Symbol())
               {
                  pos++;
                  OrderModify(OrderTicket(),OrderOpenPrice(),sl,tp,0);
                  continue;
               }
            }
            else
               Print("OrderSelect returned the error of ",GetLastError());
         }
         
         // Short at the break of the bottom trend line
         //if (pos==0||MultiPositions)
         if ( ((LondonOpen==true  && Hour()>=7 && Hour()<=16)  ||
               (NewYorkOpen==true && Hour()>=12 && Hour()<=21) ||
               (TokyoOpen==true   && ((Hour()>=0 && Hour()<=8) || 
                                      (Hour()>=23 && Hour()<=24)))
               ) && (pos==0||MultiPositions)
            )
         {
            ticket=OrderSend(Symbol(),OP_SELL,LotsPerTrade,Bid,3,sl,tp,"Mouteki",00021,0,Red);
            if(ticket>0)
            {
               if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) 
                  Print("Short order opened : ",OrderOpenPrice());
/*                  
               Print("H1=", H1, " High[H1]=", High[H1]);
               Print("H2=", H2, " High[H2]=", High[H2]);
               Print("L1=", L1, " Low[L1]=", Low[L1]);
               Print("L2=", L2, " Low[L2]=", Low[L2]);
               Print("TrendLineBreakUp=", TrendLineBreakUp);
               Print("TrendLineBreakDown=", TrendLineBreakDown);
               Print("Open[0]=", Open[0], " Open[1]=", Open[1]);
*/
            }
            else Print("Error opening Long order : ",GetLastError()); 
         }
      }
      ArrayInitialize(highs, 0.0);
      ArrayInitialize(lows, 0.0);
   }
   
//----
   return(0);
  }
//+------------------------------------------------------------------+



Sample





Analysis



Market Information Used:

Series array that contains the highest prices of each bar
Series array that contains the lowest prices of each bar
Series array that contains open prices of each bar


Indicator Curves created:


Indicators Used:



Custom Indicators Used:

Order Management characteristics:
Checks for the total of open orders

It can change open orders parameters, due to possible stepping strategy
It Closes Orders by itself
It automatically opens orders when conditions are reached

Other Features:

It issuies visual alerts to the screen