//------------------------------------------------------------------

   #property copyright "mladen"
   #property link      "www.forex-tsd.com"

//------------------------------------------------------------------

#property indicator_chart_window
#property indicator_buffers 30
#property indicator_plots   30

#property indicator_label1  "TMA1"
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrWhite,clrKhaki
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2


#property indicator_label2  "TMA2"
#property indicator_type2   DRAW_COLOR_LINE
#property indicator_color2  clrPurple,clrMagenta
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2


#property indicator_label3  "TMA3"
#property indicator_type3   DRAW_COLOR_LINE
#property indicator_color3  clrPurple,clrMagenta
#property indicator_style3  STYLE_SOLID
#property indicator_width3  2


#property indicator_label4  "TMA4"
#property indicator_type4   DRAW_COLOR_LINE
#property indicator_color4  clrBlue,clrDodgerBlue
#property indicator_style4  STYLE_SOLID
#property indicator_width4  2

#property indicator_label5  "TMA5"
#property indicator_type5   DRAW_COLOR_LINE
#property indicator_color5  clrPurple,clrMagenta
#property indicator_style5  STYLE_SOLID
#property indicator_width5  2

#property indicator_label6  "TMA6"
#property indicator_type6   DRAW_COLOR_LINE
#property indicator_color6  clrPurple,clrMagenta
#property indicator_style6  STYLE_SOLID
#property indicator_width6  2

#property indicator_label7  "TMA7"
#property indicator_type7  DRAW_COLOR_LINE
#property indicator_color7  clrGreen,clrKhaki
#property indicator_style7  STYLE_SOLID
#property indicator_width7  2

#property indicator_label8  "CustomH"
#property indicator_type8   DRAW_COLOR_LINE
#property indicator_color8  clrRed,clrRed
#property indicator_style8  STYLE_SOLID
#property indicator_width8  2

#property indicator_label9  "CustomL"
#property indicator_type9  DRAW_COLOR_LINE
#property indicator_color9  clrRed,clrRed
#property indicator_style9  STYLE_SOLID
#property indicator_width9  2

#property indicator_label10  "CustomLx"
#property indicator_type10   DRAW_COLOR_LINE
#property indicator_color10  clrGreen,clrKhaki
#property indicator_style10  STYLE_SOLID
#property indicator_width10  2

datetime prev_time;
datetime prev_time2;
//
//
//

int InpAtrPeriod=14;  // ATR period
//--- indicator buffers
double    ExtATRBuffer[9999999];
double    ExtTRBuffer[];
//--- global variable
int       ATRLength=120;
double Range_Multiplier=3;
  double Range_Multiplier4Hr=3;
  double Range_Multiplier1Hr=3;
  double Range_Multiplier15M=3;
  double Range_Multiplier5M=3;
  double Range_Multiplier1M=3; 

//
//

enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted,   // Weighted
   pr_average,    // Average (high+low+oprn+close)/4
   pr_haclose,    // Heiken ashi close
   pr_haopen ,    // Heiken ashi open
   pr_hahigh,     // Heiken ashi high
   pr_halow,      // Heiken ashi low
   pr_hamedian,   // Heiken ashi median
   pr_hatypical,  // Heiken ashi typical
   pr_haweighted, // Heiken ashi weighted
   pr_haaverage   // Heiken ashi average
};

//
//
//
//
//

 int       Length  = 120;       // TMA period
input enPrices  Price   = pr_close; // Price to use
bool Debug_Global=false;
double channel_width;
double custom_channelGBPUSD=1000;
double custom_channelGBPJPY=450;
double custom_channelUSDCAD=450;
double custom_channel=0;

//
//
//
//
//

double tma1[];
double colorBuffer1[];
double tma2[];
double colorBuffer2[];
double tma3[];
double colorBuffer3[];
double tma4[];
double colorBuffer4[];
double tma5[];
double colorBuffer5[];
double tma6[];
double colorBuffer6[];
double tma7[];
double colorBuffer7[];
double tma8[];
double colorBuffer8[];
double tma9[];
double colorBuffer9[];
double tma10[];
double colorBuffer10[];
//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------
//
//
//
//
//

int OnInit()
{
   SetIndexBuffer(0,tma1,INDICATOR_DATA); 
   SetIndexBuffer(1,colorBuffer1,INDICATOR_COLOR_INDEX); 
  SetIndexBuffer(2,tma2,INDICATOR_DATA); 
   SetIndexBuffer(3,colorBuffer2,INDICATOR_COLOR_INDEX); 
     SetIndexBuffer(4,tma3,INDICATOR_DATA); 
   SetIndexBuffer(5,colorBuffer3,INDICATOR_COLOR_INDEX); 
     SetIndexBuffer(6,tma4,INDICATOR_DATA); 
   SetIndexBuffer(7,colorBuffer4,INDICATOR_COLOR_INDEX); 
      SetIndexBuffer(8,tma5,INDICATOR_DATA); 
   SetIndexBuffer(9,colorBuffer5,INDICATOR_COLOR_INDEX); 
      SetIndexBuffer(10,tma6,INDICATOR_DATA); 
   SetIndexBuffer(11,colorBuffer6,INDICATOR_COLOR_INDEX); 
      SetIndexBuffer(12,tma7,INDICATOR_DATA); 
   SetIndexBuffer(13,colorBuffer7,INDICATOR_COLOR_INDEX); 
      SetIndexBuffer(14,tma8,INDICATOR_DATA); 
   SetIndexBuffer(15,colorBuffer8,INDICATOR_COLOR_INDEX); 
         SetIndexBuffer(16,tma9,INDICATOR_DATA); 
   SetIndexBuffer(17,colorBuffer9,INDICATOR_COLOR_INDEX); 
      SetIndexBuffer(18,tma10,INDICATOR_DATA); 
   SetIndexBuffer(19,colorBuffer10,INDICATOR_COLOR_INDEX); 
   
     SetIndexBuffer(20,ExtATRBuffer,INDICATOR_DATA);
   SetIndexBuffer(21,ExtTRBuffer,INDICATOR_CALCULATIONS);
   //
   //
   //
   //
   //
 
   IndicatorSetString(INDICATOR_SHORTNAME," TMA ("+string(Length)+")");
   return(0);
}

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------
//
//
//
//
//


int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double& open[],
                const double& high[],
                const double& low[],
                const double& close[],
                const long& tick_volume[],
                const long& volume[],
                const int& spread[])
{
   //
   //
      if(Period()==PERIOD_H4)
   {
     Range_Multiplier=Range_Multiplier4Hr;
   }
   if(Period()==PERIOD_H1)
   {
     Range_Multiplier=Range_Multiplier1Hr;
   }
   if(Period()==PERIOD_M15)
   {
     Range_Multiplier=Range_Multiplier15M;
   }
      if(Period()==PERIOD_M5)
   {
     Range_Multiplier=Range_Multiplier5M;
   }
   if(Period()==PERIOD_M1)
   {
     Range_Multiplier=Range_Multiplier1M;
   }
   //
     ArrayResize(tma1,100000,100000);
    ArrayResize(tma2,100000,100000);
    ArrayResize(tma3,100000,100000);
    ArrayResize(tma4,100000,100000);
    ArrayResize(tma5,100000,100000);
    ArrayResize(tma6,100000,100000);
    ArrayResize(tma7,100000,100000);
    ArrayResize(tma8,100000,100000);
    ArrayResize(tma9,100000,100000);
    ArrayResize(tma10,100000,100000);
    ArrayResize(colorBuffer1,100000,100000);
    ArrayResize(colorBuffer2,100000,100000);
    ArrayResize(colorBuffer3,100000,100000);
    ArrayResize(colorBuffer4,100000,100000);
    ArrayResize(colorBuffer5,100000,100000);
    ArrayResize(colorBuffer6,100000,100000);
    ArrayResize(colorBuffer7,100000,100000);
    ArrayResize(colorBuffer8,100000,100000);
    ArrayResize(colorBuffer9,100000,100000);
    ArrayResize(colorBuffer10,100000,100000);
        ArrayResize(ExtTRBuffer,1000000,1000000);
    ArrayResize(ExtATRBuffer,1000000,1000000);
   //
   //
   //----------------------------------------------ATR-------------------------------------
   //Debug(true,"Start ATR2");
     if(prev_time!=iTime(Symbol(),Period(),0))
   {
   prev_time=iTime(Symbol(),Period(),0);
      int i,limit;
//--- check for bars count
int ExtPeriodATR=ATRLength;
   if(rates_total<=ExtPeriodATR)
      return(0); // not enough bars for calculation
//--- preliminary calculations
   if(prev_calculated==0)
     {
      ExtTRBuffer[0]=0.0;
      ExtATRBuffer[0]=0.0;
      //--- filling out the array of True Range values for each period
      for(i=1;i<rates_total && !IsStopped();i++)
         ExtTRBuffer[i]=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
      //--- first AtrPeriod values of the indicator are not calculated
      double firstValue=0.0;
      for(i=1;i<=ExtPeriodATR;i++)
        {
         ExtATRBuffer[i]=0.0;
         firstValue+=ExtTRBuffer[i];
        }
      //--- calculating the first value of the indicator
      firstValue/=ExtPeriodATR;
      ExtATRBuffer[ExtPeriodATR]=firstValue;
      limit=ExtPeriodATR+1;
     }
   else limit=prev_calculated-1;
//--- the main loop of calculations
   for(i=limit;i<rates_total && !IsStopped();i++)
     {
      ExtTRBuffer[i]=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
      ExtATRBuffer[i]=ExtATRBuffer[i-1]+(ExtTRBuffer[i]-ExtTRBuffer[i-ExtPeriodATR])/ExtPeriodATR;
     // Debug(true,"Loading "+i);
     }
     Debug(true,"Loaded "+i);
     //-----------------------------------END ATR -------------------------------
   
   
  
     if(Symbol()=="GBPJPY")
   {
    custom_channel=custom_channelGBPJPY*Point();
    Debug(false,custom_channel);
   }
      if(Symbol()=="GBPUSD")
   {
    custom_channel=custom_channelGBPUSD*Point();
    Debug(false,custom_channel);
   }
   
    if(Symbol()=="USDCAD")
   {
    custom_channel=custom_channelUSDCAD*Point();
    Debug(false,custom_channel);
   }
   
   

   channel_width=iATR(Symbol(),PERIOD_M1,240)*Point()*4;
   Length=30;
 //  Comment(Point()*10,channel_width);
 



 //  for (int i=(int)MathMax(prev_calculated-1,0); i<rates_total; i++)
 int count=0;
 Debug(false,"running");
 for ( i=rates_total-1; i>rates_total-2000; i--)
   {   
      
        
        double dblRange=ExtATRBuffer[i];
        double dblTma = calcTma( 60, count);
         
      tma1[i] = dblTma;
      Debug(false,"range "+dblRange);
      Debug(false,"i "+tma1[i]);  
    
      tma2[i]=dblTma+(dblRange*Range_Multiplier);
      Debug(false,"range 2  "+DoubleToString(tma2[i],5));
      tma3[i]=dblTma-(dblRange*Range_Multiplier);
      tma4[i]=0;
      tma5[i]=0;
      tma6[i]=0;
      tma7[i]=0;
      tma8[i]=0;
      tma9[i]=0;
      tma10[i]=0;
      
      colorBuffer1[i]=0;
      colorBuffer2[i]=0;
      colorBuffer3[i]=0;
      colorBuffer4[i]=0;
      colorBuffer5[i]=0;
      colorBuffer6[i]=0;
      colorBuffer7[i]=0;
      colorBuffer8[i]=0;
      colorBuffer9[i]=0;
      colorBuffer10[i]=0;
      count++;
   }
   }
   return(rates_total);
}



//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------
//
//
//
//
//


double workHa[][4];
double getPrice(enPrices price, const double& open[], const double& close[], const double& high[], const double& low[], int i, int bars)
{
  if (price>=pr_haclose && price<=pr_haaverage)
   {
      if (ArrayRange(workHa,0)!= bars) ArrayResize(workHa,bars);

         //
         //
         //
         //
         //
         
         double haOpen;
         if (i>0)
                haOpen  = (workHa[i-1][2] + workHa[i-1][3])/2.0;
         else   haOpen  = open[i]+close[i];
         double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;
         double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));
         double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));

         if(haOpen  <haClose) { workHa[i][0] = haLow;  workHa[i][1] = haHigh; } 
         else                 { workHa[i][0] = haHigh; workHa[i][1] = haLow;  } 
                                workHa[i][2] = haOpen;
                                workHa[i][3] = haClose;
         //
         //
         //
         //
         //
         
         switch (price)
         {
            case pr_haclose:     return(haClose);
            case pr_haopen:      return(haOpen);
            case pr_hahigh:      return(haHigh);
            case pr_halow:       return(haLow);
            case pr_hamedian:    return((haHigh+haLow)/2.0);
            case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);
            case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);
            case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);
         }
   }
   
   //
   //
   //
   //
   //
   
   switch (price)
   {
      case pr_close:     return(close[i]);
      case pr_open:      return(open[i]);
      case pr_high:      return(high[i]);
      case pr_low:       return(low[i]);
      case pr_median:    return((high[i]+low[i])/2.0);
      case pr_typical:   return((high[i]+low[i]+close[i])/3.0);
      case pr_weighted:  return((high[i]+low[i]+close[i]+close[i])/4.0);
      case pr_average:   return((high[i]+low[i]+close[i]+open[i])/4.0);
   }
   return(0);
}

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------
//
//
//
//
//

double workTma[][1];
double iTma(double price, double period, int i, int total, int instanceNo=0)
{
   if (ArrayRange(workTma,0)!= total) ArrayResize(workTma,total);
   
   //
   //
   //
   //
   //
   
   workTma[i][instanceNo] = price;

      double half = (period+1.0)/2.0;
      double sum  = price;
      double sumw = 1;

      for(int k=1; k<period && (i-k)>=0; k++)
      {
         double weight = k+1; if (weight > half) weight = period-k;
                sumw  += weight;
                sum   += weight*workTma[i-k][instanceNo];
      }             
      return(sum/sumw);
}

double calcTma( int intHalfLength, int intShift )
{
   double dblResult, dblSum, dblSumW;
   int inx, jnx;
   
   dblSumW = intHalfLength + 1;
   dblSum = dblSumW * Close(intShift);
   jnx = intHalfLength;
   
   for ( inx = 1, jnx = intHalfLength; inx <= intHalfLength; inx++, jnx-- )
   {
      dblSumW += jnx;
      dblSum += ( jnx * Close(intShift+inx) );
   } 
   
   dblResult = dblSum / dblSumW;
   
   return( dblResult );
}

//+------------------------------------------------------------------+
//| calcTmaMtf()                                                     |
//+------------------------------------------------------------------+
double calcTmaMtf( int intTF, int intHalfLength, int intUpperTfShift, double dblClose )
{
   double dblResult, dblSum, dblSumW;
   int inx, jnx;
   
   // This is the current bar
   dblSumW = intHalfLength + 1;
   dblSum = dblSumW * dblClose;
   jnx = intHalfLength;
   
   for ( inx = 1, jnx = intHalfLength; inx <= intHalfLength; inx++, jnx-- )
   {
      dblSumW += jnx;
      
      
     // dblSum += ( jnx * iClose( Symbol(), intTF, intUpperTfShift+inx ) );  
      dblSum += ( jnx * iClose( Symbol(), Period(), intUpperTfShift+inx ) );   
   } 
   
   dblResult = dblSum / dblSumW;
   
   return( dblResult );
}
double Convert_2_Pts(double pd_Pips)
  {
//----
   int pd_Points=pd_Pips;  // Default - no conversion
   
 	if (Digits() == 5 || (Digits() == 3 && StringFind(Symbol(), "JPY") != -1)) 
 	   pd_Points=pd_Pips*10;
 	   
 	if (Digits() == 6 || (Digits() == 4 && StringFind(Symbol(), "JPY") != -1)) 
 	   pd_Points=pd_Pips*100;
//----
   return(pd_Points);
  }
//+------------------------------------------------------------------+
//| convert to pips                                                  |
//+------------------------------------------------------------------+
double Convert_2_Pips(double pd_Points)
  {
//----
   double pd_Pips=pd_Points/Point();  // Default - no conversion
   
 	if (Digits() == 5 || (Digits() == 3 && StringFind(Symbol(), "JPY") != -1)) 
 	   {
 	   pd_Pips=pd_Points/Point()/10;
 	   }
 	   
 	if (Digits() == 6 || (Digits() == 4 && StringFind(Symbol(), "JPY") != -1)) 
 	   {
 	   pd_Pips=pd_Points/Point()/100;
 	   }
//----
   return(pd_Pips);
  }
//+------------------------------------------------------------------+
//| get the pips decimal places                                      |
//+------------------------------------------------------------------+
int Get_Pips_Decimal()
  {
//----
   int pi_PipsDecimal = 0;  // Default - no decimals
   
 	if (Digits() == 5 || (Digits() == 3 && StringFind(Symbol(), "JPY") != -1)) 
 	   {
 	   pi_PipsDecimal = 1;
 	   }
 	   
 	if (Digits() == 6 || (Digits() == 4 && StringFind(Symbol(), "JPY") != -1)) 
 	   {
 	   pi_PipsDecimal = 2;
 	   }
//----
   return(pi_PipsDecimal);
  }
 
 
void Debug(bool local,string Debug_Message)
{
if(Debug_Global || local)
{

 Print(Symbol(),"  ",Debug_Message);
}

}
 
 double Close(int bar)
{
int count=1;   // number of elements to copy
double c[];
CopyClose(_Symbol,_Period,bar,count,c);
return c[0];
}
 
 