/* iCustom(NULL,0,"~norm",Source,SourcePeriod,Window,Sens,Power,Smooth,Signal,Fade, N,i); где N: 0 - рез-т нормирования 1 - сглаживание затухания 2 - сглаживание фронта 3 - буфер источника волатильности // не выводится 4 - сырое нормирование // не выводится */ #property indicator_separate_window // в окне индикатора #property indicator_buffers 5 #property indicator_color1 Green // результат нормирования #property indicator_color2 Red // сглаженное затухание #property indicator_color3 Red // сглаженный фронт #property indicator_maximum 1 #property indicator_minimum 0 // входные параметры extern int Source=2; // 0- объем, 1- ATR, 2- ст.дев., 3- Close extern int SourcePeriod=5; // период источника; <0 EMA, >0 SMA double kSp; // коэфф.EMA для SourcePeriod bool bSp; extern int Window=5; // окно нормирования в барах extern double Sens=0; // порог чувствтительности в пп.или тиках (объем) double sens; // порог чувствтительности в ценах или тиках (объем) extern double Power=1; // степень для передаточной функции extern int Smooth=1; // сглаживание нормирования; <0 EMA, >0 SMA double kSm; // коэфф.EMA для Smooth bool bSl; extern int Signal=1; // сигнальная; <0 EMA, >0 SMA double kSg; // коэфф.EMA для Signal bool bSg; extern int Fade=1; // затухание сигнальной double kFd; // коэфф.EMA для Fade int History=0; // 0- все бары // массивы инд.буферов double NRM[], // рез-т нормирования NEG[], // сглаживание затухания POS[], // сглаживание фронта SRC[], // буфер источника волатильности // не выводится NR0[]; // сырое нормирование // не выводится // общие (глобальные) переменные bool first=1; // флаг первого запуска // инициализация int init() { first=1; // флаг первого запуска if(Source>0) sens=Sens*Point; // приведение порога к ценам для ценовых источников else sens=Sens; if(Sens>0) string _sn=DoubleToStr(Sens,1)+" "; // вычисление коэффициентов EMA if(SourcePeriod<0) {SourcePeriod=-SourcePeriod; kSp=2.0/(1+SourcePeriod); bSp=1;} else bSp=0; if(Smooth<0) {Smooth=-Smooth; kSm=2.0/(1+Smooth); bSl=1;} else bSl=0; if(Signal<0) {Signal=-Signal; kSg=2.0/(1+Signal); bSg=1;} else bSg=0; // if(Fade>1) kFd=2.0/(1+Fade); string _sgfd=" ("+(string)Signal+","+(string)Fade+")"; string _src=""; switch(Source) { case 0: _src=_src+"Volume"; break; // объем case 1: _src=_src+"ATR"; break; // ATR case 2: _src=_src+"StDev"; break; // ст.девиация case 3: _src=_src+"Close"; break; // ст.девиация case 4: _src=_src+"H/L"; // ст.девиация } _src=_src+"("+(string)SourcePeriod+")"; string _nrm=" ["+(string)Window+","+(string)Smooth+"]"; IndicatorShortName(_sn+_src+_nrm+_sgfd); // инд.буферы SetIndexBuffer(0,NRM); SetIndexStyle(0,DRAW_LINE); SetIndexLabel(0,_nrm); SetIndexBuffer(1,NEG); SetIndexStyle(1,DRAW_LINE,2); SetIndexLabel(1,"Neg"+_sgfd); SetIndexBuffer(2,POS); SetIndexStyle(2,DRAW_LINE,2); SetIndexLabel(2,"Pos"+_sgfd); SetIndexBuffer(3,SRC); SetIndexStyle(3,DRAW_NONE); SetIndexLabel(3,NULL); SetIndexBuffer(4,NR0); SetIndexStyle(4,DRAW_NONE); SetIndexLabel(4,NULL); return(0); } // ф-я дополнительной инициализации int reinit() { ArrayInitialize(NRM,0.0); // обнуление массива ArrayInitialize(NEG,0.0); // обнуление массива ArrayInitialize(POS,0.0); // обнуление массива ArrayInitialize(SRC,0.0); // обнуление массива ArrayInitialize(NR0,0.0); // обнуление массива return(0); } int start() { int ic=IndicatorCounted(); if(!first && Bars-ic-1>1) ic=reinit(); // если есть пропущенные бары не на подключении - пересчет bool ic0=ic==0; // флаг пересчета int limit=Bars-ic; // кол-во пересчетов if(ic==0) limit-=2; for(int i=limit; i>=0; i--) { // цикл пересчета по ВСЕМ барам bool reset=i==limit && ic0; // сброс на первой итерации цикла пересчета if(reset) { static int BarsPrev=0; // пред. значение Bars } bool NewBar=(ic0 && i>0) || BarsPrev!=Bars; // первый тик нового бара //========================================= // источник int sh=i+SourcePeriod; switch(Source) { case 0: // объем if(bSp) SRC[i]=kSp*Volume[i]+(1-kSp)*SRC[i+1]; // ЕМА else { // SMA double ma=SRC[i+1]*SourcePeriod-Volume[sh]; SRC[i]=(ma+Volume[i])/SourcePeriod; } break; case 1: double atr0 =iATR(NULL,0,1, i); // ATR double atrsh=iATR(NULL,0,1,sh); // ATR if(bSp) SRC[i]=kSp*atr0+(1-kSp)*SRC[i+1]; // ЕМА else { // SMA ma=SRC[i+1]*SourcePeriod-atrsh; SRC[i]=(ma+atr0)/SourcePeriod; } break; case 2: SRC[i]=iStdDev(NULL,0,SourcePeriod,0,bSp,0, i) ; break; // ст.девиация case 3: // Close if(bSp) SRC[i]=kSp*Close[i]+(1-kSp)*SRC[i+1]; // ЕМА else { // SMA ma=SRC[i+1]*SourcePeriod-Close[sh]; SRC[i]=(ma+Close[i])/SourcePeriod; } } //== // нормирование // экстремумы double max=SRC[ArrayMaximum(SRC,Window,i)]; double min=SRC[ArrayMinimum(SRC,Window,i)]; double c=SRC[i]; // шумоподавление double delta=max-min; // размах double diff=sens-delta; // разница между порогом чувств. и размахом if(diff>0) { // если разница >0 (размах меньше порога), то delta=sens; // размах = порогу, min-=diff/2; // новое значение минимума } // нормирование if(delta!=0) NR0[i]=MathPow((c-min)/delta,Power); //== // замедление if(bSl) NRM[i]=kSm*NR0[i]+(1-kSm)*NRM[i+1]; // EMA else { // SMA sh=i+Smooth; ma=NRM[i+1]*Smooth-NR0[sh]; NRM[i]=(ma+NR0[i])/Smooth; } //== // сигнальная if(reset) {static double sgnPrev=0;} if(bSg) double sgn=kSg*NRM[i]+(1-kSg)*sgnPrev; // EMA else { // SMA sh=i+Signal; ma=sgnPrev*Signal-NRM[sh]; sgn=(ma+NRM[i])/Signal; } //== // сглаживание сигнальной // по затуханию NEG[i]=kFd*sgn+(1-kFd)*NEG[i+1]; if(sgn>NEG[i+1]) NEG[i]=sgn; // по фронту POS[i]=kFd*sgn+(1-kFd)*POS[i+1]; if(sgn