#property indicator_separate_window // в отд. окне 
#property indicator_buffers 3
#property indicator_color1 Blue // главная
#property indicator_style1 0
#property indicator_color2 Red // сигнальная
#property indicator_style2 0
#property indicator_maximum 100
#property indicator_minimum 0
#property indicator_level5 50

// входные параметры
extern int KperiodShort=5; // %K
extern int KperiodLong=12; // %K
extern int KperiodMax=100; // предельное значение %K
extern int SlowKsens=0; // порог увеличение старшего %K на оппозитных движениях стохастика
 int Dperiod=1; // %D сигнальная
   double kd; // коэфф. EMA для сигнальной
extern int Slowing=3; // замедление
 int Dmethod=0; // тип MA сигнальной: 0-SMA, 1-EMA
 int PriceField=0; // тип цены: 0-High/Low; 1-Close/Close
extern int Sens=7; // чувствительность в пп.
   double sens; // чувствительность в ценах
extern int OverSold=20; // уровень ПП в %%
 int OverSoldShort=20; // уровень ПП в %%
   int OverBoughtShort;
 int OverSoldLong=20; // уровень ПП в %%
   int OverBoughtLong;
 bool Logic=1;
 int OverStep=0;
 int History=0; // история пересчета: 0 - все бары

// массивы инд.буферов
double   Main[], // главная
         Signal[], // сигнальная
         Trend[]; // тренд: 0 - вниз, 1 - вверх

int init() {
   sens=Sens*Point; // чувствительность в ценах
   if(Dmethod==1) kd=2.0/(1+Dperiod); // коэфф. EMA для сигнальной
   
   OverSoldShort=OverSold;
   OverSoldLong=OverSoldShort;
   
   SetLevelValue(0,OverSoldShort);
   OverBoughtShort=100-OverSoldShort;
   SetLevelValue(1,OverBoughtShort);

   SetLevelValue(2,OverSoldLong);
   OverBoughtLong=100-OverSoldLong;
   SetLevelValue(3,OverBoughtLong);

   // буфер главной   
   SetIndexBuffer(0,Main);
   SetIndexStyle(0,DRAW_LINE);
   string _str="("+KperiodShort+"/"+KperiodLong+","+Slowing+")";
   SetIndexLabel(0,"Main"+_str);
   SetIndexEmptyValue(0,0.0);
   // буфер сигнальной
   SetIndexBuffer(1,Signal);
   SetIndexStyle(1,DRAW_LINE);
   _str="("+Dperiod+")";
   SetIndexLabel(1,"Signal"+_str);
   SetIndexEmptyValue(0,0.0);
   // тренд
   SetIndexBuffer(2,Trend);
   SetIndexStyle(2,DRAW_NONE);
   SetIndexLabel(2,"Trend");
   SetIndexEmptyValue(0,0.0);

   // короткое имя
   if(Sens!=0) string ShName=Sens+" ";
   ShName=ShName+"Stoch ";
   if(PriceField==0) ShName=ShName+"H/L";
   else ShName=ShName+"C/C";
   ShName=ShName+" ("+KperiodShort+"/"+KperiodLong+","+Dperiod+","+Slowing+")";
   IndicatorShortName(ShName);   
   
  }

int reinit() // ф-я дополнительной инициализации
  {
   ArrayInitialize(Main,0.0);
   ArrayInitialize(Signal,0.0);
   ArrayInitialize(Trend,0.0);
   return(0);
  }

void start() {
   int ic=IndicatorCounted();
   if(Bars-ic-1>1) ic=reinit(); 
   int limit=Bars-ic-1; // кол-во пересчетов
   if(History!=0 && limit>History) limit=History-1; // кол-во пересчетов по истории

   for(int i=limit; i>=0; i--) { // цикл пересчета по ВСЕМ барам
      // первоначальные значения
      static bool Kperiod0,Kperiod1,trend;
      static int OverSold,OverBought;
      if(i==limit && limit>1) { 
         Kperiod0=KperiodShort; Kperiod1=KperiodShort;
         OverSold=OverSoldShort; OverBought=OverBoughtShort;
         trend=0;
        }
      // главная
      Main[i]=Stoch(Kperiod0, Kperiod1, Slowing, PriceField, sens, i);
      // сигнальнаяё
      switch(Dmethod) {
         case 1: // EMA
            Signal[i]=kd*Main[i]+(1-kd)*Signal[i+1]; break;
         case 0: // SMA
            int sh=i+Dperiod;
            double ma=Signal[i+1]*Dperiod-Main[sh];
            Signal[i]=(ma+Main[i])/Dperiod;
        }
      // переключение направления
      if(i>0) {
         if(Signal[i]>=OverBought && !trend) { // аптренд
            Kperiod0=KperiodShort;
            Kperiod1=KperiodLong;
            OverSold=OverSoldShort;
//            OverBought=OverBoughtLong;
            trend=1;
           }
         if(Signal[i]<=OverSold && trend) { // даунтренд
            Kperiod0=KperiodLong;
            Kperiod1=KperiodShort;
//            OverSold=OverSoldLong;
            OverBought=OverBoughtShort;
            trend=0;
           }
         
         if(Signal[i+1]>=OverBought || Signal[i+1]<=OverSold) {int step=OverStep; bool over=1;}
         else {step=1; over=0;}
         
         if(Logic) {
            if((( trend && Signal[i]-Signal[i+1]>=SlowKsens) || over) && Kperiod1<KperiodMax) Kperiod1=Kperiod1+step;
            if(((!trend && Signal[i+1]-Signal[i]>=SlowKsens) || over) && Kperiod0<KperiodMax) Kperiod0=Kperiod0+step;
           }
         else {
            if( trend && Signal[i+1]-Signal[i]>=SlowKsens && Kperiod1<KperiodMax) Kperiod1=Kperiod1+1;
            if(!trend && Signal[i]-Signal[i+1]>=SlowKsens && Kperiod0<KperiodMax) Kperiod0=Kperiod0+1;
           }
        }   

      if(trend) Trend[i]=Kperiod1; else Trend[i]=Kperiod0;
//      Trend[i]=trend;
     }
  }
//>>>>>>>>>>>>>>>>>>>>>  

// стохастик с шумодавом
double Stoch(int Kperiod0, int Kperiod1, int Slowing, int PriceField, double sens, int i) {  
   if(i+MathMax(Kperiod0,Kperiod1)+Slowing>Bars) return(-1); // недостаточно баров - выход
   // экстремумы цены в цикле замедления/сглаживания
   double max,min,c;
   for(int j=i; j<i+Slowing; j++) {
      if(PriceField==1) { // по Close
         max+=Close[ArrayMaximum(Close,Kperiod0,j)];
         min+=Close[ArrayMinimum(Close,Kperiod1,j)];
        }
      else { // по High/Low
         max+=High[ArrayMaximum(High,Kperiod0,j)];
         min+=Low[ArrayMinimum(Low,Kperiod1,j)];
        }
      c+=Close[j];
     }
   // шумоподавление
   sens*=Slowing; // приведение чувствительности в соответствие с периодом замедления
   double delta=max-min; // размах
   double diff=sens-delta; // разница между порогом чувств. и размахом
   if(diff>0) { // если разница >0 (размах меньше порога), то
      delta=sens; // размах = порогу,
      min-=diff/2; // новое значение минимума
     }
   // вычисление осциллятора
   if(delta==0) return(-2); // деление на ноль
   else return(100*(c-min)/delta); // стохастик
  }


