//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "parody for mladenец"
#property link      "www.forex-tsd.com"
#property version "2.16"  //from "2.04"
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_plots   3
//---
#property indicator_label1  "Asymmetric TMA"
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrLimeGreen, clrRed   //Yellow, clrYellow
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
//---
#property indicator_label2  "Asymmetric TMA lower band"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrDodgerBlue  //Red  //MediumVioletRed
#property indicator_style2  STYLE_DOT
#property indicator_width2  2
//---
#property indicator_label3  "Asymmetric TMA upper band"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrDodgerBlue //LimeGreen  //SeaGreen
#property indicator_style3  STYLE_DOT
#property indicator_width3  2
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

input int       History       = 3456;       // How many candles to calculate?
input bool      RePaint       = true;       // on/off TMA repaint
input int       HalfLength    = 21;         // TMA period      
input enPrices  Price         = pr_close;   // Price to use              
input double    Deviation     = 2.0;        // Deviation for Asymmetric bands

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double MAIN[], UPPER[], LOWER[], TREND[], PRICE[], asLWR[], asUPP[];   
int halfLen=1, MAX=1;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
{
   halfLen = fmax(HalfLength,2);
   MAX     = halfLen;
   //---
   SetIndexBuffer(0,MAIN,INDICATOR_DATA); 
   SetIndexBuffer(1,TREND,INDICATOR_COLOR_INDEX); 
   SetIndexBuffer(2,LOWER,INDICATOR_DATA); 
   SetIndexBuffer(3,UPPER,INDICATOR_DATA); 
   SetIndexBuffer(4,PRICE,INDICATOR_CALCULATIONS); 
   SetIndexBuffer(5,asLWR,INDICATOR_CALCULATIONS); 
   SetIndexBuffer(6,asUPP,INDICATOR_CALCULATIONS); 
   //---
   IndicatorSetString(INDICATOR_SHORTNAME," TMA Asymmetric ["+string(HalfLength)+""+DoubleToString(Deviation,1)+"]");
//------
return(0);
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)  { Comment(""); }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int iBarss, const int CountedBars, 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 (iBarss<=MAX) return(0);     //ChartRedraw(0);
   //---
   int limit=fmax(CountedBars-MAX,0);  //iBarss-3-MAX);  
   if (History>MAX) limit=fmax(CountedBars-History-MAX,0);   //Comment( iBarss +"   "+ CountedBars +"   "+ limit );   //
   //---
   for (int i=0; i<4; i++) {
        PlotIndexSetDouble(i,PLOT_EMPTY_VALUE,0.0);                          //--- значение 0 отображаться не будет 
        //PlotIndexSetInteger(i,PLOT_SHIFT,BBShift);                           //--- установка сдвига линий при отрисовке  
        if (History>MAX)  PlotIndexSetInteger(i,PLOT_DRAW_BEGIN,iBarss-History); //--- пропуск отрисовки первых баров
        if (History<=MAX) PlotIndexSetInteger(i,PLOT_DRAW_BEGIN,MAX*3); }          //--- пропуск отрисовки первых баров     
   //---
   //---
   double FullLength = 2.0 * HalfLength + 1.0;
   //---
   for (int i=limit; i<iBarss; i++)  { PRICE[i]=0;  PRICE[i] = getPrice(Price,open,close,high,low,i); }
   //---
   //---
   for (int i=limit; i<iBarss; i++)
    {
     double sum  = (halfLen+1)*PRICE[i];
     double sumw = (halfLen+1);
     //---
     for (int j=1, k=halfLen; j<=halfLen; j++, k--)
      {
       if ((i-j)>=0)
        {
         sum  += k*PRICE[i-j];
         sumw += k;
        }            
       //---
       if (RePaint && (i+j)<iBarss)
        {
         sum  += k*PRICE[i+j];
         sumw += k;
        }
      }
     //---
     MAIN[i]=0;   MAIN[i] = sumw!=0 ? sum/sumw : MAIN[i-1];
     //---
     TREND[i] = (i>0) ? (MAIN[i]>MAIN[i-1]) ? 0 : (MAIN[i]<MAIN[i-1]) ? 1 : MAIN[i-1] : 0;
     //---
     //---
     double diff = PRICE[i] - MAIN[i];         asLWR[i]=0;   asUPP[i]=0;
     //---
     if (diff>0)
      {
       asLWR[i] = (i>0) ?  asLWR[i-1]*(FullLength-1)/FullLength : 0;
       asUPP[i] = (i>0) ? (asUPP[i-1]*(FullLength-1)+pow(diff,2))/FullLength : 0;
      }
     //---
     else
      {
       asLWR[i] = (i>0) ? (asLWR[i-1]*(FullLength-1)+pow(diff,2))/FullLength : 0;
       asUPP[i] = (i>0) ?  asUPP[i-1]*(FullLength-1)/FullLength : 0;
      }     
     //---
     UPPER[i]=LOWER[i]=0; 
     //---
     if (Deviation!=0) {
       LOWER[i] = MAIN[i] - Deviation*sqrt(asLWR[i]);      //Atr; 
       UPPER[i] = MAIN[i] + Deviation*sqrt(asUPP[i]); }    //Atr;
    }      
//------
return(iBarss);
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double workHa[][4];
//---
double getPrice(enPrices price, const double& open[], const double& close[], const double& high[], const double& low[], int i)
{
  if (price>=pr_haclose && price<=pr_haaverage)
   {
      if (ArrayRange(workHa,0)!=Bars(NULL,0)) ArrayResize(workHa,Bars(NULL,0));

         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  = fmax(high[i], fmax(haOpen,haClose));
         double haLow   = fmin(low[i] , fmin(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);
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+