Народный умелец, с форума mql4 щедро предоставил мне вот такую реализацию подсчета SMA в массив! За что ему примного благодарен.
//+------------------------------------------------------------------+ //| SSMA.mq4 | //| Copyright 2014, Vinin | //| http://vinin.ucoz.ru | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, Vinin" #property link "http://vinin.ucoz.ru" #property version "1.00" #property strict #property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 //--- plot average #property indicator_label1 "average" #property indicator_type1 DRAW_ARROW #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- input parameters input int CountMA=2000; input int Period_start=5; input int Period_shift=3; //--- indicator buffers double averageBuffer[]; double maxBuffer[]; double minBuffer[]; double Label1Buffer[]; double tmparray[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,averageBuffer); //--- setting a code from the Wingdings charset as the property of PLOT_ARROW PlotIndexSetInteger(0,PLOT_ARROW,159); ArrayResize(tmparray, CountMA+1); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ 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 (rates_total<Period_start+Period_shift*CountMA+1) return(0); ArrayInitialize(tmparray,0); int limit=rates_total-prev_calculated; if (limit>1) limit=rates_total-(Period_start+Period_shift*CountMA+1); double min=999999,max=-99999, sum=0; int count, countMA; for (int i=limit;i>=0;i--) { sum=0; count=0; countMA=0; // формируем массив со значенияи машек for (int j=0;j<Period_start+Period_shift*CountMA;j++) { sum+=(High[i+j]+Low[i+j])*0.5; count++; if (count==Period_start+Period_shift*countMA) { tmparray[countMA]=sum/count; countMA++; } } // Массив создан. МОжно обрабатывать } //--- return value of prev_calculated for next call return(rates_total); }
//+------------------------------------------------------------------+
Так же в OnCalculate
//***** Расчитать количество повторенний SMA, в десятичном интервале. for (int b=0;b<CountMA;b++) { schet=0; for (int a =CountMA;a>=0;a--) { if(NormalizeDouble(tmparray[a],4)==NormalizeDouble(tmparray[b],4)&&tmparray[a]!=0) // 1.30000 = 1.30004 ищем места с уплотнением жгутов { scBuf[b][0]=schet; // количество повторений МА scBuf[b][1]=tmparray[b]; // Цена tmparray[a]=0; // Обнуляем посчитанную ячейку schet++; } } } ArraySort(scBuf,WHOLE_ARRAY,0,MODE_DESCEND); // Сортируем массив for (int x=0;x<CountMA+1;x++) { averageBuffer[x]=scBuf[x][1]; //переносим значения в одномерный массив, для отображения через индикатор }
Цель: разместить на экране крестики там где скользящие средние повторяются(в заданном диапазоне цены, в данном случае 1.30000 = 1.30004) ,
Но результат: крестики разбросаны не там где нужно.
Создал 8 буферов, теперь в принципе разобрался, что происходит с объектами.
писец какой-то!)
Как же сделать без 8 буферов, чтоб без ограничений выставлять объекты индикатором в столбец
Начать можно проще, без повторов и отдельного счетчика:
for ( int b = 0; b < CountMA; b ++ ) { scBuf[b][0]=0; for ( int a = b+1; a < CountMA; a++ ) { if ( MathAbs( tmparray[a] - tmparray[b] ) < _Point ) // разница между МА меньше 0.0001 (четырехзнак) { scBuf[b][0]=scBuf[b][0] + 1; // количество повторений МА scBuf[b][1]=tmparray[b]; // Цена } } }
А сортировку надо заменить простым перебором и поиском максимального scBuf[х][0] и выводом результата на экран.
Только не понятно, надо ли на каждом баре выводить весь "жгут" (несколько МА, которые близки друг к другу), или достаточно только одно значение?
PS: ArraySort работает только с одномерными массивами.
Если одно значение, то как-то так:
// Массив создан. МОжно обрабатывать // Находим самую популярную МА (возле которой максимум других) int bestMA = -1, bestCount = 0; for ( int b = 0; b < CountMA; b ++ ) { int curCount = 0; for ( int a = 0; a < CountMA; a++ ) { if ( a == b ) cnontinue; if ( MathAbs( tmparray[a] - tmparray[b] ) < _Point ) // разница между МА меньше 0.0001 (четырехзнак) { curCount ++; // количество МА [a] возле МА [b] } } // Если это лучший на данный момент результат, запомним его if ( curCount > bestCount ) { bestCount = curCount; bestMA = b; } } // Если нашли, рисуем if ( bestMA >= 0 ) averageBuffer[i] = tmparray[bestMA]; } //--- return value of prev_calculated for next call return(rates_total); }
Начать можно проще, без повторов и отдельного счетчика:
А сортировку надо заменить простым перебором и поиском максимального scBuf[х][0] и выводом результата на экран.
Только не понятно, надо ли на каждом баре выводить весь "жгут" (несколько МА, которые близки друг к другу), или достаточно только одно значение?
PS: ArraySort работает только с одномерными массивами.
Спасибо!)
Что касается: "надо ли на каждом баре выводить весь "жгут", или достаточно только одно значение?" - Там не только один жгут надо выделить, а множество.
Тоже проблема что делать когда буферов не хватит.
Получается что ArraySort сортирует по первому измерению, не синхронизируя второе с первым?
Спасибо!)
Что касается: "надо ли на каждом баре выводить весь "жгут", или достаточно только одно значение?" - Там не только один жгут надо выделить, а множество.
Тоже проблема что делать когда буферов не хватит.
Получается что ArraySort сортирует по первому измерению, не синхронизируя второе с первым?
Используйте вместо стандартной ArraySort, QuickSort, в нём можно прописать сортировку многомерного массива по заданному измерению.
А вообще дети у вас хорошие, а всё что вы делаете руками плохо :)
Вы изначально в написании алгоритма пошли ущербным (наиболее затратным путём), сизифов труд.
Спасибо!)
Что касается: "надо ли на каждом баре выводить весь "жгут", или достаточно только одно значение?" - Там не только один жгут надо выделить, а множество.
Тоже проблема что делать когда буферов не хватит.
Вы себе представляете 256 точек на одном баре (кажется, именно столько буферов доступно)?
Какой в этом смысл?
Постарайтесь для начала представить результат. Нарисуйте.
Скорее всего, придет понимание, что нужно что-то другое. Тогда и возвращайтесь )
Может пригодится
https://www.mql5.com/ru/articles/26
- 2010.03.23
- Sergey Pavlov
- www.mql5.com
Здравствуйте, начал с начала, только теперь не могу опять же создать массив значений.
Идея такая:
Создаем массив из 2000 значений простой скользящей средней, применить к Median Price (HL/2)(не знаю как реализовать)
Через реализацию по подобию стандартного индикатора, путем вычисления предыдущих скользящих имея значение конечной 2000-ой MA.
Различные способы решения, но нечего не выходит, я не понимаю в какой момент вставлять, перепробовал всячески
// sma99[i]=(sma100[i]*100-d[i-100])/99;
// Y(n+1)=(Y(n)*n+x[n+1])/(n+1)
// (firstValue*InpMAPeriod+price[i+1])/InpMAPeriod;
// (firstValue*InpMAPeriod+price[InpMAPeriod+1])/(InpMAPeriod+1);
// Y[i]=Y[i+1]+(X[0]-X[N])/N;
// Y(N)=1/N*(Y(N+1)*(N+1)-X[N]), где Y(i) - значение МА(i) на нулевом баре, X[j] - значение цены на j-ом баре;
//+------------------------------------------------------------------+ //| Moving Average | //+------------------------------------------------------------------+ 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[]) { //--- check for bars count if(rates_total<InpMAPeriod-1 || InpMAPeriod<2) return(0); //--- counting from 0 to rates_total ArraySetAsSeries(ExtLineBuffer,false); ArraySetAsSeries(ExtLineBufferFid,false); ArraySetAsSeries(close,false); //--- first calculation or number of bars was changed if(prev_calculated==0) ArrayInitialize(ExtLineBuffer,0); ArrayInitialize(ExtLineBufferFid,0); //--- calculation CalculateSimpleMA(rates_total,prev_calculated,close); ExtLineBufferFid[1]=(ExtLineBuffer[rates_total-2]*InpMAPeriod-close[rates_total-2-InpMAPeriod])/(InpMAPeriod-1);
//Подставлял всякое и в разные места- кавардак здесь пытаюсь получить просто значение предпоследней МА return(rates_total); } //+------------------------------------------------------------------+ //| simple moving average | //+------------------------------------------------------------------+ void CalculateSimpleMA(int rates_total,int prev_calculated,const double &price[]) { int i,limit; //--- first calculation or number of bars was changed if(prev_calculated==0) { limit=InpMAPeriod; //--- calculate first visible value double firstValue=0; for(i=0; i<limit; i++) firstValue+=price[i]; firstValue/=InpMAPeriod; ExtLineBuffer[limit-1]=firstValue; } else limit=prev_calculated-1; //--- main loop for(i=limit; i<rates_total && !IsStopped(); i++) { ExtLineBuffer[i]=ExtLineBuffer[i-1]+(price[i]-price[i-InpMAPeriod])/InpMAPeriod; } //--- }
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Скользящая средняя(SMA) в количестве 2000 шт. Задача, отметить объектом(не имеет значения каким) скопление жгутов, по каждому бару.