Функции статистики для разработчика

Программирование прибыли: от азов к секретам мастерства. Читайте, спрашивайте, делитесь опытом.
Бонус за сообщение 0.5$
Ответственный Модератор - Haos

Функции статистики для разработчика

Сообщение Haos » 10 авг 2017, 10:25

Иногда при создании кода требуются статистические величины, которых нет в MQL. Например, очень популярными являются торговые роботы на основе поиска корреляции между валютными инструментами. Поэтому удобно иметь соответствующий код уже в наличие, а не писать каждый раз заново или по мере необходимости.

Создадим для тестирования правильности работы разрабатываемых функций скрипт (см. код далее):
Код: выделить все
//+------------------------------------------------------------------+
//|                                                      SC-Test.mq4 |
//|                                                             Haos |
//|                                        http://www.investforum.ru |
//+------------------------------------------------------------------+
#property copyright "Haos"
#property link      "http://www.investforum.ru"
#property version   "1.00"
#property strict
#property show_inputs

//*********************************************************************************************

void OnStart()
{
   double dblM[10];
   dblM[0] =  0.3270;  dblM[1] = - 0.5400;  dblM[2] = 8.3860;  dblM[3] = 2.8145;
   dblM[4] =  5.3810;  dblM[5] = - 15.6671; dblM[6] = 18.1873; dblM[7] = 0.0123;
   dblM[8] = -1.2843;  dblM[9] =   12.1298;
}

//*********************************************************************************************

В функции OnStart() определим массив dblM[10] из 10 элементов, которым присвоим значения (0,3270; -0,5400...).
Далее будем добавлять в этот скрипт создаваемые функции для расчета статистических параметров.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Функции статистики для разработчика

Сообщение Haos » 10 авг 2017, 10:29

1. Функция для расчета суммы элементов массива
Код: выделить все
double f_GetSum(double &Y[])
{
// Функция возвращает сумму элементов массива
   int size = ArraySize(Y);
   double Sum = 0.0;
   for(int i = 0; i < size; i++) { Sum += Y[i]; }
   
return(Sum);
}

Вставим её в код скрипта и добавим в функцию OnStart() две строчки:
Код: выделить все
...
   double dblSum = f_GetSum(dblM);
   Comment( "\n", "SUM: ", DoubleToStr(dblSum, 4));

В первой строке задаем переменную dblSum, в которой будем хранить значение функции f_GetSum(). Эта функция и будет рассчитывать сумму элементов массива. Во второй строке будем выводить в качестве комментария полученные значения.
Для проверки работы функций можно создать файл Excel, внести в него числовые данные массива и вызвать функцию для нахождения их суммы "=СУММ(C2:C11)". Результат расчета суммы:

01.png

Запустим скрипт на выполнение и убедимся в правильности расчета 1-ой функции:
Вложения
02.png
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Функции статистики для разработчика

Сообщение Haos » 10 авг 2017, 10:42

2. Функция для расчета среднего арифметического элементов массива
Код: выделить все
double f_GetAve(double &Y[])
{
// Функция возвращает среднее арифметическое элементов массива
// Используется функция f_GetSum()
   int size = ArraySize(Y);
   double Sum = f_GetSum(Y);
   return(Sum / size);
}

Аналогично для проверки работы функции воспользуемся Excel и получим следующее значение:

02-1.png

Мы использовали функцию Excel "=СРЗНАЧ(C2:C11)".
Запустим скрипт на выполнение и убедимся в правильности работы функции 2:
Вложения
02-2.png
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Функции статистики для разработчика

Сообщение Haos » 10 авг 2017, 10:51

3. Расчет дисперсии элементов массива
Код: выделить все
double f_GetDis(double &Y[])
{
// Функция возвращает дисперсию по выборке
// Используется функция f_GetAve()
   int i, size = ArraySize(Y);
   // среднее арифметическое массива:
   double Ave = f_GetAve(Y);
   // найдем квадрат разностей элементов массива и среднего арифметического:
   double Dif = 0.0; 
   for(i = 0; i < size; i++) { Dif += MathPow(Y[i] - Ave, 2); }

return(Dif / (size - 1));
}

Аналогично для проверки работы функции воспользуемся Excel и получим следующее значение:

03-1.png

Для расчета дисперсии была использована функция Excel "=ДИСП(C2:C11)".
Запустим скрипт на выполнение и убедимся в правильности работы функции 3:
Вложения
03-2.png
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Функции статистики для разработчика

Сообщение Haos » 10 авг 2017, 12:30

4. Расчет стандартного отклонения элементов массива
Код: выделить все
double f_GetStD(double &Y[])
{
// Функция возвращает стандартное отклонение по выборке
// Используется функция f_GetDis()
   double StD = MathSqrt(f_GetDis(Y));

return(StD);
}

Стандартное отклонение - это корень квадратный из дисперсии. Для проверки работы функции воспользуемся Excel и получим следующее значение:

04-1.png

Для расчета стандартного отклонения была использована функция Excel "СТАНДОТКЛОН(C2:C11)".
Запустим скрипт на выполнение и убедимся в правильности работы функции 4:
Вложения
04-2.png
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Функции статистики для разработчика

Сообщение Haos » 10 авг 2017, 13:39

5. Расчет ковариации двух выборок данных
Код: выделить все
double f_GetCov(double &Y1[], double &Y2[])
  {
// Функция возвращает ковариацию двух выборок (массивы Y1 и Y2)
   int    int_Size1 = ArraySize(Y1),
          int_Size2 = ArraySize(Y2);
   if(int_Size1 != int_Size2) return(-999999999.9); // ошибка длин массивов
   double dbl_Sum  = 0.0;
   double dbl_Ave1 = f_GetAve(Y1),
          dbl_Ave2 = f_GetAve(Y2);
   for(int i = 0; i < int_Size1; i++)
   dbl_Sum += (Y1[i] - dbl_Ave1) * (Y2[i] - dbl_Ave2);

return(dbl_Sum / int_Size1);
}

Для расчета ковариации необходимы две выборки одинаковой длины. Поэтому сформируем второй массив данных и внесем его в код скрипта:
Код: выделить все
//+------------------------------------------------------------------+
//|                                                      SC-Test.mq4 |
//|                                                             Haos |
//|                                        http://www.investforum.ru |
//+------------------------------------------------------------------+
#property copyright "Haos"
#property link      "http://www.investforum.ru"
#property version   "1.00"
#property strict
#property show_inputs

//*********************************************************************************************

void OnStart()
{
   double dblM[10], dblN[10];
   dblM[0] =  0.3270;  dblM[1] = - 0.5400;  dblM[2] = 8.3860;  dblM[3] = 2.8145;
   dblM[4] =  5.3810;  dblM[5] = - 15.6671; dblM[6] = 18.1873; dblM[7] = 0.0123;
   dblM[8] = -1.2843;  dblM[9] =   12.1298;
   
   dblN[0] =  4.8926;  dblN[1] = - 2.1934;  dblN[2] = 1.9423;  dblN[3] = 12.6687;
   dblN[4] = -6.7249;  dblN[5] = - 5.9973;  dblN[6] = 8.1178;  dblN[7] = 0.0036;
   dblN[8] = -3.5733;  dblN[9] =   2.5597;   
   
   double dblSum = f_GetSum(dblM);
   double dblAve = f_GetAve(dblM);
   double dblDis = f_GetDis(dblM);
   double dblStD = f_GetStD(dblM);
   double dblCov = f_GetCov(dblM, dblN);
   
   Comment( "\n", "SUM: ", DoubleToStr(dblSum, 4),
            "\n", "AVE: ", DoubleToStr(dblAve, 4),
            "\n", "DIS: ", DoubleToStr(dblDis, 4),
            "\n", "StD: ", DoubleToStr(dblStD, 4),
            "\n", "COV: ", DoubleToStr(dblCov, 4));
   
}

//*********************************************************************************************

double f_GetSum(double &Y[])
{
// Функция возвращает сумму элементов массива
   int size = ArraySize(Y);
   double Sum = 0.0;
   for(int i = 0; i < size; i++) { Sum += Y[i]; }
   
return(Sum);
}

//*********************************************************************************************

double f_GetAve(double &Y[])
{
// Функция возвращает среднее арифметическое элементов массива
   int size = ArraySize(Y);
   double Sum = f_GetSum(Y);
   return(Sum / size);
}
//********************************************************************************************* 

double f_GetDis(double &Y[])
{
// Функция возвращает дисперсию по выборке
// Используется функция f_GetAve()
   int i, size = ArraySize(Y);
   // среднее арифметическое массива:
   double Ave = f_GetAve(Y);
   // найдем квадрат разностей элементов массива и среднего арифметического:
   double Dif = 0.0; 
   for(i = 0; i < size; i++) { Dif += MathPow(Y[i] - Ave, 2); }

return(Dif / (size - 1));
}
 
//*********************************************************************************************
 
double f_GetStD(double &Y[])
{
// Функция возвращает стандартное отклонение по выборке
// Используется функция f_GetDis()
   double StD = MathSqrt(f_GetDis(Y));

return(StD);
}

//*********************************************************************************************

double f_GetCov(double &Y1[], double &Y2[])
  {
// Функция возвращает ковариацию двух выборок (массивы Y1 и Y2)
   int    int_Size1 = ArraySize(Y1),
          int_Size2 = ArraySize(Y2);
   if(int_Size1 != int_Size2) return(-999999999.9); // ошибка длин массивов
   double dbl_Sum  = 0.0;
   double dbl_Ave1 = f_GetAve(Y1),
          dbl_Ave2 = f_GetAve(Y2);
   for(int i = 0; i < int_Size1; i++)
   dbl_Sum += (Y1[i] - dbl_Ave1) * (Y2[i] - dbl_Ave2);

return(dbl_Sum / int_Size1);
}

Для проверки работы функции воспользуемся Excel и получим следующее значение:

05-1.png

Для расчета ковариации была использована функция Excel "=КОВАР(C2:C11;D2:D11)".
Запустим скрипт на выполнение и убедимся в правильности работы функции 5:
Вложения
05-2.png
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Функции статистики для разработчика

Сообщение Haos » 10 авг 2017, 13:50

Почему нам важно проверять правильность вычислений той или иной статистической величины через Excel, к примеру? Да потому, что по интернету ходят разработки, которые содержат ошибки в формулах из-за того, что авторы плохо понимают что из себя представляет рассматриваемая статистическая величина. Также есть два варианта некоторых стат. величин, к примеру, дисперсия по выборке и по генеральной совокупности или аналогично стандартное отклонение по выборке и по генеральной совокупности.
Итак, все необходимые статистические величины для определения коэффициента корреляции у нас имеются и теперь мы можем написать код функции для его расчета.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Функции статистики для разработчика

Сообщение Haos » 10 авг 2017, 17:02

6. Расчет линейного коэффициента корреляции (коэффициент корреляции Пирсона)
Код: выделить все
double f_GetCorr(double &Y1[], double &Y2[])
{
// Функция возвращает коэф-т корреляции двух выборок (массивы Y1 и Y2)
// Используются ф-ия f_GetAve()
   int    int_Size1 = ArraySize(Y1),
          int_Size2 = ArraySize(Y2);
   if(int_Size1 != int_Size2) return(-999999999.9); // ошибка длин массивов
   double dbl_Ave1 = f_GetAve(Y1),
          dbl_Ave2 = f_GetAve(Y2),
          dbl_Nume = 0.0, dbl_Zna1 = 0.0, dbl_Zna2 = 0.0;
   for(int i = 0; i < int_Size1; i++)
   {
      dbl_Nume += (Y1[i] - dbl_Ave1) * (Y2[i] - dbl_Ave2);
      dbl_Zna1 += MathPow(Y1[i] - dbl_Ave1, 2);
      dbl_Zna2 += MathPow(Y2[i] - dbl_Ave2, 2);
   }
   if(dbl_Zna1 == 0 || dbl_Zna2 == 0) return(-999999999.9); // знаменатель равен нулю
   double dbl_Corr = dbl_Nume / MathSqrt(dbl_Zna1 * dbl_Zna2);
   
return(dbl_Corr);
}

Для проверки работы функции воспользуемся Excel и получим следующее значение:

06-1.png

Для расчета линейного коэффициента корреляции была использована функция Excel "=КОРРЕЛ(C2:C11;D2:D11)".
Запустим скрипт на выполнение и убедимся в правильности работы функции 6:
Вложения
06-2.png
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Re: Функции статистики для разработчика

Сообщение Haos » 11 авг 2017, 09:30

Используя разработанные функции для расчета статистических величин, напишем скрипт для расчета коэффициента корреляции:
Код: выделить все
//+------------------------------------------------------------------+
//|                                            SC-Correlation-v1.mq4 |
//|                                                             Haos |
//|                                        http://www.investforum.ru |
//+------------------------------------------------------------------+
#property copyright "Haos"
#property link      "http://www.investforum.ru"
#property version   "1.00"
#property strict
#property show_inputs

input int      intBars = 40;        // Количество баров для расчета корреляции (> 3)
input string   strSym2 = "GBPUSD";  // Название второго символа

//*********************************************************************************************

void OnStart()
{
   if(intBars >= 3 && intBars <= Bars)
   {
      string strSym1 = _Symbol;
      double dblM1[], dblM2[];
      ArrayResize(dblM1, intBars);
      ArrayResize(dblM2, intBars);
      int j1 = CopyClose(strSym1, 0, 1, intBars, dblM1);
      int j2 = CopyClose(strSym2, 0, 1, intBars, dblM2);
      if(j1 != -1 && j2 != -1)
      {
         double dblCor = f_GetCorr(dblM1, dblM2);
         Comment( "\n", "Correlation(", strSym1, "&", strSym2, "): ", DoubleToStr(dblCor, 4));
      }
      else {Comment( "\n", "Ошибка запрашиваемых данных!");}     
   }
   else
   {
      Comment( "\n", "Количество баров для расчета корреляции выходит за допустимые границы!");
   }
}

//*********************************************************************************************

double f_GetSum(double &Y[])
{
// Функция возвращает сумму элементов массива
   int size = ArraySize(Y);
   double Sum = 0.0;
   for(int i = 0; i < size; i++) { Sum += Y[i]; }
   
return(Sum);
}

//*********************************************************************************************

double f_GetAve(double &Y[])
{
// Функция возвращает среднее арифметическое элементов массива
   int size = ArraySize(Y);
   double Sum = f_GetSum(Y);
   return(Sum / size);
}
 
//*********************************************************************************************

double f_GetCorr(double &Y1[], double &Y2[])
{
// Функция возвращает коэф-т корреляции двух выборок (массивы Y1 и Y2)
// Используются ф-ия f_GetAve()
   int    int_Size1 = ArraySize(Y1),
          int_Size2 = ArraySize(Y2);
   if(int_Size1 != int_Size2) return(-999999999.9); // ошибка длин массивов
   double dbl_Ave1 = f_GetAve(Y1),
          dbl_Ave2 = f_GetAve(Y2),
          dbl_Nume = 0.0, dbl_Zna1 = 0.0, dbl_Zna2 = 0.0;
   for(int i = 0; i < int_Size1; i++)
   {
      dbl_Nume += (Y1[i] - dbl_Ave1) * (Y2[i] - dbl_Ave2);
      dbl_Zna1 += MathPow(Y1[i] - dbl_Ave1, 2);
      dbl_Zna2 += MathPow(Y2[i] - dbl_Ave2, 2);
   }
   if(dbl_Zna1 == 0 || dbl_Zna2 == 0) return(-999999999.9); // знаменатель равен нулю
   double dbl_Corr = dbl_Nume / MathSqrt(dbl_Zna1 * dbl_Zna2);
   
return(dbl_Corr);
}

//*********************************************************************************************

Скрипт запускается на активе на ТФ из которого будут браться данные для расчета коэффициента корреляции по одному активу, а график второго актива должен быть открыт на таком же ТФ с уже подгруженными данными.
В качестве параметров скрипта задаются: кол-во баров для расчета коэф. корреляции и наименование второго актива. Значение рассчитанного коэф. корреляции выводится на экран в виде комментария:

07-1.png

Если необходимо, то данный расчет можно производить в советнике, при этом сделав пересчет коэф. корреляции на каждом новом баре.
Файл скрипта ниже.
Вложения
SC-Correlation-v1.mq4
(6.04 KB) Скачиваний: 58
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.

Функции статистики для разработчика

Сообщение Haos » 04 сен 2018, 13:13

Функция расчета простого скользящего среднего от массива данных. Данная процедура формирует массив искомых средних для дальнейшего использования в программе.
Код: выделить все
void f_GetSMA(double &X[], double &Y[], int pe)
{
/* Функция возвращает среднее арифметическое элементов массива
   X  - массив от которого вычисляется массив средних Y
   Y  - массив расчитываемых средних значений
   pe - период расчета среднего

*/
   int SizeX = ArraySize(X);
   double Sum = 0.0;
   for(int i = 0; i < SizeX - pe - 1; i++)
   {
      for(int j = i; j < i + pe; j++) { Sum += X[j]; }
      Y[i] = Sum / pe;
      Sum = 0.0;
   } 
}

По коду видно, что исходным массивом, от которого будут считаться средние значения выступает в качестве параметра X[]. Массивом в которым заполняются найденные средние значения выступает Y[]. В основном коде программы они должны быть объявлены.
Параметр "pe" - это период средней.
Аватар пользователя
Haos
Специалист MQL
 
Сообщений: 24699
Зарегистрирован: 29 мар 2014, 16:07
Средств на руках: 193.70 Доллар
Группа: Главные модераторы
Благодарил (а): 3379 раз.
Поблагодарили: 8200 раз.


Вернуться в MQL – теория и практика

Кто сейчас на форуме?

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 47

Права доступа к форуму

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения