Математическая задача - как програмно получить правильный ответ Сигма отклонения

 

Задача.

Выявление среднеквадратичного отклонения


Есть пять деревьев, каждое дерево своей высоты

1 - 10

2 - 20

3 - 15

4 - 20

5 - 10

Находим среднее значение

X = 10+20+15+20+10/5;

Получаем среднее значение где Х=15.

Теперь нужно получить дисперсию, что бы ее получить от каждого числа нужно ортнять среднее значение и возвести это в квадрат

(10-15)2  = 25

+

(20-15)2  = 25

+

(15-15)2  = 0

+

(20-15)2  = 25

+

(10-15)2  = 25


Наша дисперсия равна  100

Что бы получить среднеквадратичное отклонение нам нужно из полученного результата извлечь квадратный корень и разделить на кол-во уровней, собственно 5

√100/5 = 2

Получилось что наше среднеквадратичное отклонение - сигма усредненного значения высоты деревьев колеблется с отклонением 2.


Теперь главный вопрос, как это правильно отобразить на языке MQL5

Представим что наши деревья находятся уже в массиве

Derevo[5]

на гуру не претендую

Derevo[5];
for(int i=0;i<5;i++)
   { 
    int volume +=Derevo[i]; // получим объем
    int sred = volume/5     // получим среднее значение
    
    int rezultat = MathSqrt(MathPow(Derevo[i]-sred,2)  +    // Получим результат возведя во вторуб степень взяв корень квадратный разделив на 5
                            MathPow(Derevo[i+1]-sred,2)+
                            MathPow(Derevo[i+2]-sred,2)+
                            MathPow(Derevo[i+3]-sred,2)+
                            MathPow(Derevo[i+4]-sred,2))/5;
    
   }


Интересует вот что, можно ли как то сократить данные вычисления

Пробовал делать так

Derevo[5];
for(int i=0;i<3;i++)
   { 
    int volume +=Derevo[i]; // получим объем
    int sred = volume/5
    
    int rezultat += MathSqrt(MathPow(Derevo[i]-sred,2))/5;    // Получим результат                             
   }


На выходе результат совершенно другой выдается


Как быть, очень хочется правильно вычислить и главное компактным кодом высоту своей травы на лужайке языком mql5


Спасибо.

 
//--------------------------------------------------------------------
//Возвращает средне арефметическое значение элементов массива
double ArrayMean(double & arrIn[])
{
   uint size = ArraySize(arrIn);
   if(size == 0 || size < 2) 
      return(0.0);         

   double sum = 0.0;       
   for(uint i=0; i<size; i++) 
      sum += arrIn[i];     
   
   return(sum/size);
}

//--------------------------------------------------------------------
//Возвращает среднеквадратичное (стандартное) отклонение значений элементов массива
double ArrayStd(double & arrIn[])
{
   uint size = ArraySize(arrIn);
   if(size == 0 || size < 2) 
      return(0.0);   
   
   double sum  = 0.0; 
   double mean = ArrayMean(arrIn); 
          
   for(uint i=0; i<size; i++)
      sum += MathPow(MathAbs(arrIn[i]-mean), 2.0);
      
   return(MathSqrt(sum/size));
}
 
Roman:

Спасибо.

Но всеравно не могу понять, почему разные результаты.

Есть торговый стакан, хочу знать среднеквадратичное отклонение объема по стороне АСК

Сам класс

double CMarketDepth::GetDeviationAsk() {
   MqlBookInfo   m_book_array[];
   long m_sum_vol      =0;
   long m_average      =0;
   double m_square_deviation =0;
   int  level = (int)InfoGetInteger(MBOOK_DEPTH_ASK);        // - Кол-во уровней стакана =20 
   int _begin = (int)InfoGetInteger(MBOOK_LAST_ASK_INDEX);   // - 0 нулевой индекс
   int _end   = (int)InfoGetInteger(MBOOK_BEST_ASK_INDEX);   // - индекс цены ASK

   for(int i = _end; i >= _begin && _begin !=-1; i--)        // - Пройдемся по уровням стакана и начнем отчет от 0 индекса
   {                 
   m_sum_vol += m_book_array[i].volume;                      // - получаем  суммарный объем стакана на цене Аск  
   if(m_sum_vol!=0){m_average = m_sum_vol/level;}            // - получаем среднеарефметический объем стакана по стороне АСК
      
   m_square_deviation = MathSqrt(MathPow(m_book_array[i].volume-m_average,2)+                                 
                                 MathPow(m_book_array[i+1].volume-m_average,2)+
                                 MathPow(m_book_array[i+2].volume-m_average,2)+
                                 MathPow(m_book_array[i+3].volume-m_average,2)+
                                 MathPow(m_book_array[i+4].volume-m_average,2)+
                                 MathPow(m_book_array[i+5].volume-m_average,2)+
                                 MathPow(m_book_array[i+6].volume-m_average,2)+
                                 MathPow(m_book_array[i+7].volume-m_average,2)+
                                 MathPow(m_book_array[i+8].volume-m_average,2)+
                                 MathPow(m_book_array[i+9].volume-m_average,2)+
                                 MathPow(m_book_array[i+10].volume-m_average,2)+
                                 MathPow(m_book_array[i+11].volume-m_average,2)+
                                 MathPow(m_book_array[i+12].volume-m_average,2)+
                                 MathPow(m_book_array[i+13].volume-m_average,2)+
                                 MathPow(m_book_array[i+14].volume-m_average,2)+
                                 MathPow(m_book_array[i+15].volume-m_average,2)+
                                 MathPow(m_book_array[i+16].volume-m_average,2)+
                                 MathPow(m_book_array[i+17].volume-m_average,2)+
                                 MathPow(m_book_array[i+18].volume-m_average,2)+
                                 MathPow(m_book_array[i+19].volume-m_average,2) 
                                 )/level; 
                                 
                                   
      
      }       
    return (m_square_deviation);   
  }


Но если сделать по вашей аналогии.

double CMarketDepth::GetDeviationAsk() {
   MqlBookInfo   m_book_array[];
   long m_sum_vol      =0;
   long m_average      =0;
   double m_square_deviation =0;
   int  level = (int)InfoGetInteger(MBOOK_DEPTH_ASK);        // - Кол-во уровней стакана =20 
   int _begin = (int)InfoGetInteger(MBOOK_LAST_ASK_INDEX);   // - 0 нулевой индекс
   int _end   = (int)InfoGetInteger(MBOOK_BEST_ASK_INDEX);   // - индекс цены ASK

   for(int i = _end; i >= _begin && _begin !=-1; i--)        // - Пройдемся по уровням стакана и начнем отчет от 0 индекса
   {                 
   m_sum_vol += m_book_array[i].volume;                      // - получаем  суммарный объем стакана на цене Аск  
   if(m_sum_vol!=0){m_average = m_sum_vol/level;}            // - получаем среднеарифметический объем стакана по стороне АСК
      
   m_square_deviation += MathPow(MathAbs(m_book_array[i].volume-m_average),2)
                               
      
      }       
    return (MathSqrt(m_square_deviation/level));  
  }


То на выходе получаю другую цифру, где более правильный расчет не пойму

 
Konstantin Seredkin:

Спасибо.

Но всеравно не могу понять, почему разные результаты.

Есть торговый стакан, хочу знать среднеквадратичное отклонение объема по стороне АСК

Сам класс


Но если сделать по вашей аналогии.


То на выходе получаю другую цифру, где более правильный расчет не пойму

Скорее всего, ваша ошибка в функции MathPow, вы передаёте целое число 2, а нужно вещественное 2.0
Иначе функция урежет результат до целого числа.
Всегда вещественные числа, указывайте с точкой.

 
Roman:

Скорее всего, ваша ошибка в функции MathPow, вы передаёте целое число 2, а нужно вещественное 2.0
Иначе функция урежет результат до целого числа.
Всегда вещественные числа, указывайте с точкой.

Не помогает

//+----------------------------------------------------------------------------+
double CMarketDepth::GetDeviationAsk() {

   long m_sum_vol      =0;
   long m_average      =0;
   double m_square_deviation =0;
   int  level = (int)InfoGetInteger(MBOOK_DEPTH_ASK);        // - Кол-во уровней стакана =20 
   int _begin = (int)InfoGetInteger(MBOOK_LAST_ASK_INDEX);   // - 0 нулевой индекс
   int _end   = (int)InfoGetInteger(MBOOK_BEST_ASK_INDEX);   // - индекс цены ASK

   for(int i = _end; i >= _begin && _begin !=-1; i--)        // - Пройдемся по уровням стакана и начнем отчет от 0 индекса
   {                 
   m_sum_vol += m_book_array[i].volume;                      // - получаем  суммарный объем стакана на цене Аск  
   if(m_sum_vol!=0){m_average = m_sum_vol/level;}            // - получаем среднеарефметический объем стакана по стороне АСК
      

   m_square_deviation = MathSqrt(MathPow(m_book_array[i].volume-m_average,2.0)+                                 
                                 MathPow(m_book_array[i+1].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+2].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+3].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+4].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+5].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+6].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+7].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+8].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+9].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+10].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+11].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+12].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+13].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+14].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+15].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+16].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+17].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+18].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+19].volume-m_average,2.0) 
                                 )/level; 
      }       
    return (m_square_deviation);  
  }

//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

double CMarketDepth::GetDeviationAsk2() {

   long m_sum_vol      =0;
   long m_average      =0;
   double m_square_deviation =0;
   int  level = (int)InfoGetInteger(MBOOK_DEPTH_ASK);        // - Кол-во уровней стакана =20 
   int _begin = (int)InfoGetInteger(MBOOK_LAST_ASK_INDEX);   // - 0 нулевой индекс
   int _end   = (int)InfoGetInteger(MBOOK_BEST_ASK_INDEX);   // - индекс цены ASK

   for(int i = _end; i >= _begin && _begin !=-1; i--)        // - Пройдемся по уровням стакана и начнем отчет от 0 индекса
   {                 
   m_sum_vol += m_book_array[i].volume;                      // - получаем  суммарный объем стакана на цене Аск  
   if(m_sum_vol!=0){m_average = m_sum_vol/level;}            // - получаем среднеарефметический объем стакана по стороне АСК
      
   m_square_deviation += MathPow(MathAbs(m_book_array[i].volume-m_average),2.0);
                               
      
      }       
    return (MathSqrt(m_square_deviation/level));  
  }


На выходе получаю во втором варианте число больше


 
Konstantin Seredkin:

Не помогает


На выходе получаю во втором варианте число больше


Сравните результат с моей функцией, если совпадает значит всё правильно, если нет, ищите дальше.
Моя функция возвращает правильный расчёт.

p.s. И функция Comment принимает тип string. Числа нужно приводить к этому типу Comment((string)value);

 
Попробуйте использовать MathStandardDeviation()
Документация по MQL5: Стандартная библиотека / Математика / Статистика / Статистические характеристики / MathStandardDeviation
Документация по MQL5: Стандартная библиотека / Математика / Статистика / Статистические характеристики / MathStandardDeviation
  • www.mql5.com
Стандартная библиотека / Математика / Статистика / Статистические характеристики / MathStandardDeviation - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Konstantin Seredkin:

Спасибо.

Но всеравно не могу понять, почему разные результаты.

Есть торговый стакан, хочу знать среднеквадратичное отклонение объема по стороне АСК

Сам класс


Но если сделать по вашей аналогии.


То на выходе получаю другую цифру, где более правильный расчет не пойму

Этот код даже компилироваться не будет. 

 
Roman:

Сравните результат с моей функцией, если совпадает значит всё правильно, если нет, ищите дальше.
Моя функция возвращает правильный расчёт.

Да возможно оно и так.

Просто если все проверить на калькуляторе, то первый вариант что рассчитывает терминал и калькулятор идентичны.

И если вернутся к расчетам, где мы берем к примеру за расчет 1 сигму

//--- Вычислим дисперсию по сторам стакана
     b_v.SigmaAsk_up     = b_v.Average_Ask+SigmaTotal*m_book_market.GetDeviationAsk();            // Верхний интервал случайной величины
     b_v.SigmaAsk_dn     = b_v.Average_Ask-SigmaTotal*m_book_market.GetDeviationAsk();            // Нижний интервал случвйной величины
     b_v.SigmaPercentAsk = 100*(b_v.SigmaAsk_up-b_v.SigmaAsk_dn)/b_v.SigmaAsk_up;                 // Процент

То при расчете выдается правильное отклонение которое не привышает в нормальном состоянии отклонение более чем 68,26%

Если расчитать % отклонения по второму методу, то там процент колеблется в районе 100, что в корне не верно.

Вот и не понятно, что делает эта строка

 m_square_deviation += MathPow(MathAbs(m_book_array[i].volume-m_average),2.0);

Правильно ли там все считается и возводится в степень, потому что если проверить это раздельно, просто взять и вот таким образом рассчитать

double CMarketDepth::GetDeviationAsk() {

   long m_sum_vol      =0;
   long m_average      =0;
   double m_square_deviation =0.0;
   int  level = (int)InfoGetInteger(MBOOK_DEPTH_ASK);        // - Кол-во уровней стакана =20 
   int _begin = (int)InfoGetInteger(MBOOK_LAST_ASK_INDEX);   // - 0 нулевой индекс
   int _end   = (int)InfoGetInteger(MBOOK_BEST_ASK_INDEX);   // - индекс цены ASK

   for(int i = _end; i >= _begin && _begin !=-1; i--)        // - Пройдемся по уровням стакана и начнем отчет от 0 индекса
   {                 
   m_sum_vol += m_book_array[i].volume;                      // - получаем  суммарный объем стакана на цене Аск  
   if(m_sum_vol!=0){m_average = m_sum_vol/level;}            // - получаем среднеарефметический объем стакана по стороне АСК
      

   m_square_deviation = MathPow(m_book_array[i].volume-m_average,2.0)+                                 
                                 MathPow(m_book_array[i+1].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+2].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+3].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+4].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+5].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+6].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+7].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+8].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+9].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+10].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+11].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+12].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+13].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+14].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+15].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+16].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+17].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+18].volume-m_average,2.0)+
                                 MathPow(m_book_array[i+19].volume-m_average,2.0) 
                                ; 
      }       
    return (m_square_deviation);  
  }




double CMarketDepth::GetDeviationAsk2() {

   long m_sum_vol      =0;
   long m_average      =0;
   double m_square_deviation =0.0;
   int  level = (int)InfoGetInteger(MBOOK_DEPTH_ASK);        // - Кол-во уровней стакана =20 
   int _begin = (int)InfoGetInteger(MBOOK_LAST_ASK_INDEX);   // - 0 нулевой индекс
   int _end   = (int)InfoGetInteger(MBOOK_BEST_ASK_INDEX);   // - индекс цены ASK

   for(int i = _end; i >= _begin && _begin !=-1; i--)        // - Пройдемся по уровням стакана и начнем отчет от 0 индекса
   {                 
   m_sum_vol += m_book_array[i].volume;                      // - получаем  суммарный объем стакана на цене Аск  
   if(m_sum_vol!=0){m_average = m_sum_vol/level;}            // - получаем среднеарефметический объем стакана по стороне АСК
      
   m_square_deviation += MathPow(MathAbs(m_book_array[i].volume-m_average),2.0);
                               
      
      }       
    return (m_square_deviation);  
  }



Вроде логнически все одинаково, в первом варианте мы с плюсовываем каждый индекс и возводим его в степень.

Во втором случае мы считаем все тоже самое

Но возникает сомнение, в степень мы должны взводить каждый индекс, не может ли быть такого, что во втором методе у нас считается сумма по уровням, а потом эта общая сумма возводиться в степень 2  ????

 
Rashid Umarov:

Этот код даже компилироваться не будет. 

По вашему я тут в фотошопе рисую что ли.

int  level = (int)InfoGetInteger(MBOOK_DEPTH_ASK);        // - Кол-во уровней стакана =20 
   int _begin = (int)InfoGetInteger(MBOOK_LAST_ASK_INDEX);   // - 0 нулевой индекс
   int _end   = (int)InfoGetInteger(MBOOK_BEST_ASK_INDEX);   // - индекс цены ASK


Сделать так 

int  level = 20  // - Кол-во уровней стакана =20 
int _begin = 0   // - 0 нулевой индекс
int _end   = 19  // - индекс цены ASK


и все скомпилируется. 

 
Konstantin Seredkin:

По вашему я тут в фотошопе рисую что ли.


и все скомпилируется. 

Да, из-за плохого форматирования я не заметил одну скобку. Но в этом коде есть ошибка - пропущен цикл.

В общем, каша в алгоритме отражается и в качестве форматирования.

Причина обращения: