фильтр цены, как умножение цен последних трёх баров на матрицу коэфф. В какой-то момент достало постоянно использовать ENUM_APPLIED_PRICE и во многих приложениях используется более тонкий тюнинг. Поэтому вот такая нетленка
//+------------------------------------------------------------------+ //| iPrice.mq5 | //| Maxim Kuznetsov | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Maxim Kuznetsov" #property link "https://luxtrade.unaux.com" #property version "1.00" #property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 //--- plot iPrice #property indicator_label1 "iPrice" #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- коэффициенты // цены трёх баров input double open_0=0.0; input double high_0=0.0; input double low_0=0.0; input double close_0=1.0; input double open_1=0.0; input double high_1=0.0; input double low_1=0.0; input double close_1=0.0; input double open_2=0.0; input double high_2=0.0; input double low_2=0.0; input double close_2=0.0; // статистические: медиана, максимум,минимум input double open_median=0.0; input double high_median=0.0; input double low_median=0.0; input double close_median=0.0; input double open_max=0.0; input double high_max=0.0; input double low_max=0.0; input double close_max=0.0; input double open_min=0.0; input double high_min=0.0; input double low_min=0.0; input double close_min=0.0; double PRICE[]; enum ENUM_PRICE { OPEN=0,HIGH,LOW,CLOSE, TOTAL_PRICES }; enum ENUM_BAR { BAR_0=0,BAR_1,BAR_2,MEDIAN,MAX,MIN, TOTAL_BARS }; enum ENUM_NEED { NEED_OPEN=0,NEED_HIGH,NEED_LOW,NEED_CLOSE,NEED_MEDIAN,NEED_MAX,NEED_MIN, TOTAL_NEEDS }; double WEIGHT[TOTAL_PRICES][TOTAL_BARS]; // коэфф. double NORM=0.0; // нормировка=(сумма коэфф) double DATA[TOTAL_PRICES][TOTAL_BARS]; // данные к которым применяем bool NEEDS[TOTAL_NEEDS]; // используемые столбцы MqlRates RATES[]; int OnInit() { // буфер и граф SetIndexBuffer(0,PRICE,INDICATOR_DATA); PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); ArraySetAsSeries(PRICE,true); // нормировка := сумма коэфф. NORM+=open_0+high_0+low_0+close_0; NORM+=open_1+high_1+low_1+close_1; NORM+=open_2+high_2+low_2+close_2; NORM+=open_median+high_median+low_median+close_median; NORM+=open_max+high_max+low_max+close_max; NORM+=open_min+high_min+low_min+close_min; // заполняем веса WEIGHT[OPEN][0]=open_0; WEIGHT[HIGH][0]=high_0;WEIGHT[LOW][0]=low_0;WEIGHT[CLOSE][0]=close_0; WEIGHT[OPEN][1]=open_1; WEIGHT[HIGH][1]=high_1;WEIGHT[LOW][1]=low_1;WEIGHT[CLOSE][1]=close_1; WEIGHT[OPEN][2]=open_2; WEIGHT[HIGH][2]=high_2;WEIGHT[LOW][2]=low_2;WEIGHT[CLOSE][2]=close_2; WEIGHT[OPEN][MEDIAN]=open_median;WEIGHT[HIGH][MEDIAN]=high_median;WEIGHT[LOW][MEDIAN]=low_median;WEIGHT[CLOSE][MEDIAN]=close_median; WEIGHT[OPEN][MAX]=open_max;WEIGHT[HIGH][MAX]=high_max;WEIGHT[LOW][MAX]=low_max;WEIGHT[CLOSE][MAX]=close_max; WEIGHT[OPEN][MIN]=open_min;WEIGHT[HIGH][MIN]=high_min;WEIGHT[LOW][MIN]=low_min;WEIGHT[CLOSE][MIN]=close_min; // проверяем веса (не должно быть отрицательных) for(int i=0;i<TOTAL_PRICES && NORM!=0;i++) { for(int j=0;j<TOTAL_BARS;j++) { if (WEIGHT[i][j]<0.0) { PrintFormat("negative mult. %f",WEIGHT[i][j]); NORM=0; // можно вернуть INIT_FAILED, но это крайне нехорошо break; } } } // какие данные будут использоваться в рассчётах ArrayInitialize(NEEDS,false); if (open_0!=0.0 || open_1!=0.0 || open_2!=0.0 || open_median!=0.0 || open_max!=0.0 || open_min!=0.0) NEEDS[NEED_OPEN]=true; if (high_0!=0.0 || high_1!=0.0 || high_2!=0.0 || high_median!=0.0 || high_max!=0.0 || high_min!=0.0) NEEDS[NEED_HIGH]=true; if (low_0!=0.0 || low_1!=0.0 || low_2!=0.0 || low_median!=0.0 || low_max!=0.0 || low_min!=0.0 ) NEEDS[NEED_LOW]=true; if (close_0!=0.0 || close_1!=0.0 || close_2!=0.0 || close_median!=0.0 || close_max!=0.0 || close_min!=0.0) NEEDS[NEED_CLOSE]=true; if (open_median!=0.0 || high_median!=0.0 || low_median!=0.0 || close_median!=0.0) NEEDS[NEED_MEDIAN]=true; if (open_max!=0.0 || high_max!=0.0 || low_max!=0.0 || close_max!=0.0) NEEDS[NEED_MAX]=true; if (open_min!=0.0 || high_min!=0.0 || low_min!=0.0 || close_min!=0.0) NEEDS[NEED_MIN]=true; // рабочий массив, для получения котировок ArrayResize(RATES,3); ArraySetAsSeries(RATES,true); return(INIT_SUCCEEDED); } 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[]) { for(int bar=prev_calculated>0?prev_calculated-1:0 ; bar<rates_total ; bar++) { int idx=rates_total - bar - 1; if (bar==0) PRICE[idx]=0.0; else PRICE[idx]=PRICE[idx+1]; if (NORM==0 || CopyRates(_Symbol,_Period,idx,3,RATES)!=3) { continue; } ArrayInitialize(DATA,0); if (NEEDS[NEED_OPEN]) { DATA[OPEN][0]=RATES[0].open; DATA[OPEN][1]=RATES[1].open; DATA[OPEN][2]=RATES[2].open; } if (NEEDS[NEED_HIGH]) { DATA[HIGH][0]=RATES[0].high; DATA[HIGH][1]=RATES[1].high; DATA[HIGH][2]=RATES[2].high; } if (NEEDS[NEED_LOW]) { DATA[LOW][0]=RATES[0].low; DATA[LOW][1]= RATES[1].low; DATA[LOW][2]=RATES[2].low; } if (NEEDS[NEED_CLOSE]){ DATA[CLOSE][0]=RATES[0].close;DATA[CLOSE][1]=RATES[1].close; DATA[CLOSE][2]=RATES[2].close; } if (NEEDS[NEED_MEDIAN]) { for(int p=0;p<TOTAL_PRICES;p++) { if (WEIGHT[p][MEDIAN]!=0) DATA[p][MEDIAN]=Median(DATA[p][0],DATA[p][1],DATA[p][2]); } } if (NEEDS[NEED_MAX] || NEEDS[NEED_MIN]) { for(int p=0;p<TOTAL_PRICES;p++) { if (WEIGHT[p][MAX]!=0) DATA[p][MAX]=Max(DATA[p][0],DATA[p][1],DATA[p][2]); if (WEIGHT[p][MIN]!=0) DATA[p][MIN]=Min(DATA[p][0],DATA[p][1],DATA[p][2]); } } double sum=0.0; for(int i=0;i<TOTAL_PRICES;i++) { for(int j=0;j<TOTAL_BARS;j++) { sum+=DATA[i][j]*WEIGHT[i][j]; } } sum/=NORM; PRICE[idx]=sum; } return(rates_total); } double Median(const double &v1,const double &v2,const double &v3) { if (v1<=v2 && v1>=v3) return v1; if (v2<=v1 && v2>=v3) return v2; return v3; } double Max(const double &v1,const double &v2,const double &v3) { if (v1>=v2 && v1>=v3) return v1; if (v2>=v1 && v2>=v3) return v2; return v3; } double Min(const double &v1,const double &v2,const double &v3) { if (v1<=v2 && v1<=v3) return v1; if (v2<=v1 && v2<=v3) return v2; return v3; }
Как использовать, на мой взгляд очевидно : задать нужные коэффициенты в input :-)
Файлы:
iPrice.mq5
15 kb
iPrice.ex5
16 kb