//+------------------------------------------------------------------+
//|                                                          TMA.mq4 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

extern double TrailingStop = 300;
extern bool trail = true;
extern double Lots = 0.01;

extern double ATRMultiplier   = 2.0;
extern int    atrPeriod       = 100;

extern double    MaxTMASlopeM15       = 0;
extern double    MinTMASlopeM15       = 0;

extern double    MaxTMASlopeH1       = 0.1;
extern double    MinTMASlopeH1       = -0.1;

extern double    MaxTMASlopeH4       = 0.1;
extern double    MinTMASlopeH4       = -0.1;

int periodgr = 15;
int eintPeriod = 56;
double edblHigh1 = 0.5;
double edblLow1 = -0.5;


int ExTMA;
double Tick = 0;
bool AdditionalDigit;

int Signal;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
Signal = 0;
//----
   return(0);
  }

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
   ClosePosution();
   GetSignal();
//----
   return(0);
  }
//+------------------------------------------------------------------+

void ClosePosution()
{ int cnt, ticket, total;
total=OrdersTotal();
        
     for(cnt=0;cnt<total;cnt++)
     {
     
    
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber() == 12062012)  // check for symbol
        {
        double upperBand = calcTmaMTF( 0 , periodgr) + iATR(NULL,periodgr,atrPeriod,0+10)*ATRMultiplier; 
        double lowerBand = calcTmaMTF( 0 , periodgr) - iATR(NULL,periodgr,atrPeriod,0+10)*ATRMultiplier;
        if(OrderType()==OP_BUY)   // long position is opened
           {
            // should it be closed?
            if(upperBand < Ask)
                {
                 OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
                 return(0); // exit
                }
            // check for trailing stop
            if(TrailingStop>0 && trail)  
              {                 
               if(Bid-OrderOpenPrice()>Point*TrailingStop)
                 {
                  if(OrderStopLoss()<Bid-Point*TrailingStop)
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);
                     return(0);
                    }
                 }
              }
           }
         else // go to short position
           {
            // should it be closed?
            if(lowerBand > Bid)
              {
               OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
               return(0); // exit
              }
            // check for trailing stop
            if(TrailingStop>0 && trail)  
              {                 
               if((OrderOpenPrice()-Ask)>(Point*TrailingStop))
                 {
                  if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0))
                    {
                     OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red);
                     return(0);
                    }
                 }
               }  
           }
        }
     }
}


void GetSignal()
    {
    int cnt, ticket, total, all;    
    double НА, НА_p, TmaSlope, TmaSlopeH1, TmaSlopeH4, TmaSlopeH4_p;
    double val, stop;
 total=OrdersTotal();
   //if(total<1)
   
     for(cnt=0;cnt<total;cnt++)
     {OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber() == 12062012) return(0);
     }
   {
       
    double upperBand = calcTmaMTF( 0 , periodgr) + iATR(NULL,periodgr,atrPeriod,0+10)*ATRMultiplier; 
    double lowerBand = calcTmaMTF( 0 , periodgr) - iATR(NULL,periodgr,atrPeriod,0+10)*ATRMultiplier; 
    
    if (lowerBand > Ask && (Signal == 0 || Signal == 2)) Signal = 1;
    if (upperBand < Bid && (Signal == 0 || Signal == 1)) Signal = 2;
    
    if (Signal == 1)
    
        { НА = GetHeikenAshi(0);
          НА_p = GetHeikenAshi(1);

          if (НА > 0 && НА_p >0) 
            {TmaSlope =   TmaSlope(periodgr,0);
             TmaSlopeH1 = TmaSlope(60,0);
             TmaSlopeH4 = TmaSlope(240,0);
             all = Alligator();
             if (TmaSlope > MinTMASlopeM15 && TmaSlopeH4 > MinTMASlopeH4 && TmaSlopeH1 > MinTMASlopeH1 && all ==1)

                {stop=fractal(1);

                 ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,stop,0,"TMA",12062012,0,Blue);
                 if(ticket>0)
                    {
                     if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("BUY order opened : ",OrderOpenPrice());
                     Signal = 0;
                    }
                  else Print("Error opening BUY order : ",GetLastError()); 
                  return(0);
                }  
                else Signal = 0;
            }
         }
   
   if (Signal == 2)
      {НА = GetHeikenAshi(0);
       НА_p = GetHeikenAshi(1);
  
          if (НА < 0 && НА_p <0)
            {TmaSlope = TmaSlope(periodgr,0);
             TmaSlopeH1 = TmaSlope(60,0);
             TmaSlopeH4 = TmaSlope(240,0);
             all = Alligator();
             
             if (TmaSlope < MaxTMASlopeM15 && TmaSlopeH4 < MaxTMASlopeH4 && TmaSlopeH1 < MaxTMASlopeH1 && all ==0)

               {stop=fractal(0);

                  ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,stop,0,"TMA",12062012,0,Red);
                  if(ticket>0)
                     {
                     if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("SELL order opened : ",OrderOpenPrice());
                     Signal = 0;
                     }
                  else Print("Error opening SELL order : ",GetLastError()); 
                  return(0);}
                  else Signal = 0;
            }
       }  
      }
    }
    
    
//+------------------------------------------------------------------+
//| Расчет fractal                                                        |
//+------------------------------------------------------------------+
double fractal(int Pos)
{
   int i, z; // counters
   int extr_n; // номер ближайшего экстремума frktl_bars-барного фрактала 
   double temp; // служебная переменная
   int after_x, be4_x; // свечей после и до пика соответственно
   int ok_be4, ok_after; // флаги соответствия условию (1 - неправильно, 0 - правильно)
   int sell_peak_n, buy_peak_n; // номера экстремумов ближайших фракталов на продажу (для поджатия дл.поз.) и покупку соответсвенно   
   int frktl_bars = 10;
   int tmfrm = periodgr;
   int indent = 30;
   double stop;
   
   temp = frktl_bars;
      
   if (MathMod(frktl_bars,2)==0)
   extr_n = temp/2;
   else                
   extr_n = MathRound(temp/2);
      
   // баров до и после экстремума фрактала
   after_x = frktl_bars - extr_n;
   if (MathMod(frktl_bars,2)!=0)
   be4_x = frktl_bars - extr_n;
   else
   be4_x = frktl_bars - extr_n - 1;    
   
   // если длинная позиция (OP_BUY), находим ближайший фрактал на продажу (т.е. экстремум "вниз")
   if (Pos==1)
      {
      // находим последний фрактал на продажу
      for (i=extr_n;i<iBars(Symbol(),tmfrm);i++)
         {
         ok_be4 = 0; ok_after = 0;
         
         for (z=1;z<=be4_x;z++)
            {
            if (iLow(Symbol(),tmfrm,i)>=iLow(Symbol(),tmfrm,i-z)) 
               {
               ok_be4 = 1;
               break;
               }
            }
            
         for (z=1;z<=after_x;z++)
            {
            if (iLow(Symbol(),tmfrm,i)>iLow(Symbol(),tmfrm,i+z)) 
               {
               ok_after = 1;
               break;
               }
            }            
         
         if ((ok_be4==0) && (ok_after==0))                
            {
            sell_peak_n = i; 
            break;
            }
         }
       stop = iLow(Symbol(),tmfrm,sell_peak_n)-indent*Point;
       if (stop > Bid-200*Point) stop = Bid-200*Point;
       if (stop < Bid-400*Point) stop = Bid-400*Point;

      return(stop);
      }
      
   // если короткая позиция (OP_SELL), находим ближайший фрактал на покупку (т.е. экстремум "вверх")
   if (Pos==0)
      {
      // находим последний фрактал на продажу
      for (i=extr_n;i<iBars(Symbol(),tmfrm);i++)
         {
         ok_be4 = 0; ok_after = 0;
         
         for (z=1;z<=be4_x;z++)
            {
            if (iHigh(Symbol(),tmfrm,i)<=iHigh(Symbol(),tmfrm,i-z)) 
               {
               ok_be4 = 1;
               break;
               }
            }
            
         for (z=1;z<=after_x;z++)
            {
            if (iHigh(Symbol(),tmfrm,i)<iHigh(Symbol(),tmfrm,i+z)) 
               {
               ok_after = 1;
               break;
               }
            }            
         
         if ((ok_be4==0) && (ok_after==0))                
            {
            buy_peak_n = i;
            break;
            }
         }        
      
      stop = iHigh(Symbol(),tmfrm,buy_peak_n)+(indent+MarketInfo(Symbol(),MODE_SPREAD))*Point;
      
      if (stop < Ask+200*Point) stop = Ask+200*Point;
      if (stop > Ask+400*Point) stop = Ask+400*Point;

      return(stop);
      }      
   }
   
   
//+------------------------------------------------------------------+
//| Расчет ТМА                                                        |
//+------------------------------------------------------------------+
double TmaSlope(int Per, int Shift)
{
 double dblTmaMTF, dblPrevMTF, atrMTF;

     
 atrMTF= iATR(NULL,Per,atrPeriod,Shift+10)*0.1;     
 dblTmaMTF = calcTmaMTF( 0 , Per);
      dblPrevMTF = calcTmaMTF( 1 , Per);
      double hh = ( dblTmaMTF - dblPrevMTF ) / atrMTF;

return(hh);
}


//+------------------------------------------------------------------+
//| calcTma()                                                        |
//+------------------------------------------------------------------+
double calcTmaMTF( int inx , int tf)
{
   double dblSum  = (eintPeriod+1)*iClose(Symbol(),tf,inx);
   double dblSumw = (eintPeriod+1);
   int jnx, knx;
         
   for ( jnx = 1, knx = eintPeriod; jnx <= eintPeriod; jnx++, knx-- )
   {
      dblSum  += ( knx * iClose(Symbol(),tf,inx+jnx) );
      dblSumw += knx;

      if ( jnx <= inx )
      {
         dblSum  += ( knx * iClose(Symbol(),tf,inx-jnx) );
         dblSumw += knx;
      }
   }
   
   return( dblSum / dblSumw );
}

//+------------------------------------------------------------------+
//| Расчет Heiken Ashi                                               |
//+------------------------------------------------------------------+

double GetHeikenAshi(int Shift)
{
   Tick = MarketInfo(Symbol(), MODE_TICKSIZE);	
   AdditionalDigit = MarketInfo(Symbol(), MODE_MARGINCALCMODE) == 0 && MarketInfo(Symbol(), MODE_PROFITCALCMODE) == 0 && Digits % 2 == 1;
   if (AdditionalDigit) {
        Tick *= 10;
    } 
double ha = (GetHAClose(Shift) - GetHAOpen(Shift))/Tick;

return(ha);
}

double GetHAClose(int index)
{
   return((Open[index]+High[index]+Low[index]+Close[index])/4);
}

double GetHAOpen(int index)
{
   //The higher you make this lookback the lower the error with the true Heiken Ashi Open)
   int lookback = 8;
   double open = GetHAClose(index+lookback);
   lookback--;
   for(int j = index + lookback;j > index;j--)
   {
      open = (open + GetHAClose(j)) / 2;
   }
   return (open);
}

//+------------------------------------------------------------------+
//| Расчет Heiken Ashi конец                                              |
//+------------------------------------------------------------------+


int Alligator()
{
double jaw_val =  iAlligator(NULL, PERIOD_H4, 13, 8, 8, 5, 5, 3, MODE_SMMA, PRICE_MEDIAN, MODE_GATORJAW, 1);
double TEETH_val =iAlligator(NULL, PERIOD_H4, 13, 8, 8, 5, 5, 3, MODE_SMMA, PRICE_MEDIAN, MODE_GATORTEETH, 1);
double LIPS_val = iAlligator(NULL, PERIOD_H4, 13, 8, 8, 5, 5, 3, MODE_SMMA, PRICE_MEDIAN, MODE_GATORLIPS, 1);

 if ((jaw_val > TEETH_val) && (TEETH_val > LIPS_val)) return (0);
 if ((jaw_val < TEETH_val) && (TEETH_val < LIPS_val)) return (1);
   else
     return(-1);
}