
Исследование быстродействия скользящих средних в MQL5
Введение
В исследованиях временных рядов, построении индикаторов и в разработке советников, редко кто обходится без применения в анализе рынка скользящих средних (MovingAverage). Это самый популярный метод сглаживания ценовых данных. В новой версии языка, вариантов использования алгоритма MovingAverage (MA) насчитывается около десятка.
Возникает вопрос: а все ли йогурты одинаково полезны? Действительно, на сколько снижается или увеличивается быстродействие расчётов при участии скользящих средних? Какой вариант выбрать в той или иной ситуации?
Насколько расчёт MovingAverage в MetaTrader 5 быстрее чем в MetaTrader 4? И подобных вопросов возникает очень много. Вот и давайте разберёмся с большинством из них.
Конечно, быстродействие новой платформы впечатляет, но проверить экспериментально истинное положение вещей не помешает.
1. Условия проведения экспериментов
Быстродействие расчётов относительно и зависит от многих факторов. Поэтому, данные, которые были получены в рамках проведённых исследований, в других условиях будут отличаться. Иначе говоря, абсолютные значения быстродействия изменятся, а относительные (один вариант относительно другого в пределах одной платформы) нет.
Поскольку индикатор скользящих средних iMA в MQL5 результаты расчёта данных непосредственно не возвращает (возвращается хэндл индикатора), то исследовать быстродействие надо для связки iMA-CopyBuffer, т.к. нас интересует быстродействие не только самого расчёта, но и получения результатов.
Исходные условия:
- Процессор: Core i7 965
- Символ: "EURUSD"
- Размер массива ценовых данных: 10000 элементов
- Режим работы терминала: автономный, максимальное количество баров в окне 10000
- Модели расчёта скользящих средних: MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA
- Точность расчёта быстродействия: ограничена 2 значащими цифрами
- Количество вариантов вызова скользящих средних: 7
2. Программа испытаний
Для того чтобы измерить время расчёта скользящих средних, в нашем распоряжении есть функция GetTickCount(), которая оперирует миллисекундами. Этой точности не достаточно, поэтому необходимо организовать какие-то циклы для повышения качества измерений.
Однако, если организовать цикл, который будет многократно повторять один и тот же расчёт с одними и теми же входными данными, то результаты будут искажены. Дело в том, что функция iMA из MQL5 создаёт в глобальном кеше клиентского терминала копию соответствующего
технического индикатора. А если копия индикатора с этими параметрами уже
существует, то новая копия в глобальном кеше не создаётся(!), а увеличивается счётчик ссылок на
данную копию. Другими словами, весь индикаторный буфер рассчитывается только один раз при первом обращении, а при всех последующих - берёт готовые значения и пересчёт происходит только новых данных.
Поэтому, цикличность расчётов надо организовать так, чтобы на каждом цикле входные параметры скользящих средних изменялись. Таких параметров выбрано три: период усреднения; таймфрейм и используемая цена.
Параметр | Диапазон значений |
---|---|
Период усреднения | от 1 до 100 |
Таймфрейм | М1, М5, М15, М30 |
Используемая цена | PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED |
Таблица 1. Диапазоны изменения входных параметров
Расчёт значений МА будем проводить на массиве из 10 000 элементов и для семи вариантов вызова скользящих средних (подробно см. раздел 4).
3. Результаты исследований
Результаты исследований сведены в следующую таблицу, в которой быстродействие расчёта скользящих средних оцениваем по времени исполнения всей программы испытаний (см. табл.1) в секундах. По этой программе получается 100х4х7=2800 шагов (циклов), т.е. определяем за какое время происходит расчёт всех шагов (циклов) на массиве ценовых данных из 10 000 элементов. Время исполнения одного шага (цикла) приблизительно будет равно отношению полученного быстродействия к 2800. Например, для варианта 1 и модели расчёта SMA оно равняется ~ 0,0028/2800.
Вариант | MODE_SMA | MODE_EMA | MODE_SMMA | MODE_LWMA | Платформа |
---|---|---|---|---|---|
0 (см. раздел 4.1) |
0,0041 | 0,0040 | 0,0043 | 0,0041 | MetaTrader 4 |
1 (см. раздел 4.2) | 0,0028 | 0,00023 | 0,00027 | 0,0045 | MetaTrader 5 |
2 (см. раздел 4.3) | 0,0029 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
3 (см. раздел 4.4) | 0,0998 | 0,0997 | 0,0998 | 0,0998 | MetaTrader 5 |
4 (см. раздел 4.5) | 0,0996 | 0,0996 | 0,0996 | 0,0996 | MetaTrader 5 |
5 (см. раздел 4.6) | 0,0030 | 0,0029 | 0,0029 | 0,0029 | MetaTrader 5 |
6 (см. раздел 4.7) | 0,000140 | 0,000121 | 0,000117 | 0,0035 | MetaTrader 5 |
Таблица 2. Сводная таблица результатов исследований
Что означают номера вариантов, будет подробно рассмотрено в статье чуть ниже (разделы 4.1-4.7). А пока давайте оценим общую картину быстродействия MA.
Для наглядности анализа, результаты представлены в графическом виде на рис.1-5. По оси Х номер варианта вызова MA (см. табл.2), а по оси Y логарифмическая шкала времени с обратным порядком значений, т.е. чем выше столбик на диаграмме, тем больше быстродействие. Каждой модели расчёта (SMA, EMA, SMMA, LWMA) соответствует свой столбик диаграммы.
Рисунок 1. Результаты исследования быстродействия скользящих средних
Трудно не заметить существенную разницу в скорости расчёта скользящих
средних для разных вариантов. О чём это может говорить? Самое простое,
что напрашивается, не все предлагаемые разработчиками языка способы
использования MA одинаково хороши: есть очень скоростные (вариант 6) и
есть очень медленные (варианты 3 и 4). Следовательно, разработчикам прикладных программ на языке MQL5 надо быть очень разборчивыми с "машками" (MovingAverag).
На следующих рисунках, для удобства анализа, каждая модель расчёта MovingAverage рассмотрена в отдельности для всех исследованных вариантов (от 0 до 6) см. в табл. 2.
Рисунок 2. Быстродействие МА для модели MODE_SMA
Рисунок 3. Быстродействие МА для модели MODE_EMA
Рис.4 Быстродействие МА для модели MODE_SMMA.
Рисунок 5. Быстродействие МА для модели MODE_LWMA
Интересно сравнить быстродействие двух платформ: MetaTrader 4 и MetaTrader 5. В таблице 2 это вариант №0 (MQL4) и вариант №2 (MQL5). Для удобства анализа, поместим результаты расчёта стандартного индикатора скользящих средних iMA в отдельную таблицу и диаграмму (см. рис.6). По оси Y шкала времени исполнения теста.
Рисунок 6. Быстродействие платформ MetaTrader 4 и MetaTrader 5
Выводы:
- Новая платформа MetaTrader 5 по быстродействии более чем на 40% опережает предыдущую - MetaTrader 4.
- Самое высокое быстродействие получено: для моделей расчёта SMA, EMA, SMMA - вариант вызова MovingAverage №6, а для модели LWMA - варианты №2 и №5.
- В тех вариантах, где используется стандартный индикатор iMA, быстродействие разных моделей расчёта практически одинакова. Чего нельзя сказать о библиотеке скользящих средних из файла MovingAverages.mqh. Там разбег точек для разных моделей отличается почти на порядок (0,00023~0,0045).
- Результаты соответствуют режиму "холодный запуск", т.е., предварительно рассчитанных значений в глобальном кеше нет.
4. Исследованные варианты использования скользящих средних
Разработчики MQL5 рекомендуют примерно вот такой вариант получения значений стандартных индикаторов:
//---- indicator buffers double MA[]; // массив для индикатора iMA //---- handles for indicators int MA_handle; // указатель на индикатор iMA //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- создание указателя на объект - индикатор iMA MA_handle=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE); //--- если произошла ошибка при создании объекта, то выводим сообщение if(MA_handle<0) { Print("Объект iMA не создан: MA_handle= ",INVALID_HANDLE); Print("Ошибка исполнения = ",GetLastError()); //--- принудительное завершение программы return(-1); } return(0); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- заполнение массива MA[] текущими значениями индикатора iMA //--- в массив будет записано 100 элементов, а если произошла //--- ошибка, то прекращаем выполнение дальнейших операций if(CopyBuffer(MA_handle,0,0,100,MA)<=0) return; //--- задаём порядок индексации массива MA[] как в таймсерии ArraySetAsSeries(MA,true); //--- а дальше делайте с этими данными всё что угодно }
Об этом способе получения значений технических индикаторов подробно написано в одноимённой статье.
Для тестирования скользящих средних лучше всего подойдёт скрипт,
поскольку он сразу выполняет все необходимые расчёты, не дожидаясь поступления каких либо событий (например, прихода нового тика).
Создание универсальной программы, для расчёта всех запланированных способов расчёта скользящих средних, вряд ли оправдано. Поэтому для каждого варианта вызова МА создадим свой скрипт.
Итак, рассмотрим подробно каждый вариант вызова скользящих средних (MovingAverage).
4.1. Вариант №0
В этом варианте определяется быстродействие функции технического индикатора iMA из MQL4. Испытания проводились в терминале MetaTrader 4. Расчёт на всём массиве данных.
Модель | Результат | Лучший результат |
---|---|---|
MODE_SMA | 0,0041 | 0,000140 (вариант 6) |
MODE_EMA | 0,0040 | 0,000121 (вариант 6) |
MODE_SMMA | 0,0043 | 0,000117 (вариант 6) |
MODE_LWMA | 0,0041 | 0,0029 (вариант 2,5) |
Код этого варианта представлен на языке MQL4:
int M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; int P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[]; double time; int count=10000; int startGTC,endGTC; int m,p; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { if(ArrayResize(buf,count)<0) return(-1); Print("СТАРТ "); startGTC=GetTickCount(); //---- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test0(); } } } //---- endGTC=GetTickCount(); time=endGTC-startGTC; Print("Общее время [мсек] ",time); time=time/1000/m/p/periodMA; Print("Быстродействие [сек] ",DoubleToStr(time, 10)); return(0); } //+------------------------------------------------------------------+ void Test0() { //--- Модель расчёта: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA for(int i=0;i<count;i++) { buf[i]=iMA(NULL,M[m],periodMA,0,MODE_SMA,P[p],i); } }Примечание:
В терминале MetaTrader 5 данный код работать не будет, т.к. он написан на языке MQL4. Его следует запускать в терминале MetaTrader 4.
4.2. Вариант №1
В этом варианте участвуют 4 теста: №1(SMA), №2(EMA), №3(SMMA) и №4(LWMA).
В них используется библиотека функций MovingAverages.mqh из стандартной поставки. Расчёт ведется на всём массиве данных.
Модель | Результат | Лучший результат |
---|---|---|
MODE_SMA | 0,0028 | 0,000140 (вариант 6) |
MODE_EMA | 0,00023 | 0,000121 (вариант 6) |
MODE_SMMA | 0,00027 | 0,000117 (вариант 6) |
MODE_LWMA | 0,0045 | 0,0029 (варианты 2,5) |
#include <MovingAverages.mqh> ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[],close[]; double time; int count=10000; int startGTC,endGTC; int m,p; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { if(ArrayResize(buf,count)<0) return(-1); ArraySetAsSeries(buf,false); ArraySetAsSeries(close,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { CopyClose(_Symbol,M[m],0,count,close); for(periodMA=1;periodMA<=100;periodMA++) { Test1(); // заменить на необходимый тест } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test1() { for(int i=0;i<count;i++) { buf[i]=SimpleMA(i,periodMA,close); } } //+------------------------------------------------------------------+ void Test2() { buf[0]=close[0]; for(int i=1;i<count;i++) { buf[i]=ExponentialMA(i,periodMA,buf[i-1],close); } } //+------------------------------------------------------------------+ void Test3() { buf[0]=close[0]; for(int i=1;i<count;i++) { buf[i]=SmoothedMA(i,periodMA,buf[i-1],close); } } //+------------------------------------------------------------------+ void Test4() { for(int i=0;i<count;i++) { buf[i]=LinearWeightedMA(i,periodMA,close); } }
Примечание: В расчётах участвовал только один массив цен закрытия баров, хотя по программе должны участвовать разные. Это упрощение, принятое для данного варианта, на быстродействие никакого влияния не оказывает.
4.3. Вариант №2
В этом варианте используется стандартный технический индикатор iMA и один тест №5. Расчёт ведется на всём массиве данных.
Модель | Результат | Лучший результат |
---|---|---|
MODE_SMA | 0,0029 | 0,000140 (вариант 6) |
MODE_EMA | 0,0029 | 0,000121 (вариант 6) |
MODE_SMMA | 0,0029 | 0,000117 (вариант 6) |
MODE_LWMA | 0,0029 | 0,0029 (вариант 2,5) |
ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double time; int count=10000; int startGTC,endGTC; int m,p; double MA[]; // массив для индикатора iMA int MA_handle; // указатель на индикатор iMA //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test5(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test5() { //--- Модель расчёта: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA MA_handle=iMA(NULL,M[m],periodMA,0,MODE_SMA,P[p]); while(BarsCalculated(MA_handle)<count){} CopyBuffer(MA_handle,0,0,count,MA); }
4.4. Вариант №3
Используется стандартная библиотека: классы для работы с индикаторами.
Копирование поэлементное. Расчёт ведется на всём массиве данных.
Модель | Результат | Лучший результат |
---|---|---|
MODE_SMA | 0,0998 | 0,000140 (вариант 6) |
MODE_EMA | 0,0997 | 0,000121 (вариант 6) |
MODE_SMMA | 0,0998 | 0,000117 (вариант 6) |
MODE_LWMA | 0,0998 | 0,0029 (вариант 2,5) |
#include <Indicators\Trend.mqh> ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[]; double time; int count=10000; int startGTC,endGTC; int m,p; CiMA objMA; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { if(ArrayResize(buf,count)<0) return(-1); ArraySetAsSeries(buf,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test6(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test6() { //--- Модель расчёта: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA objMA.Create(NULL,M[m],periodMA,0,MODE_SMA,P[p]); objMA.BuffSize(count); objMA.Refresh(1); for(int i=0;i<count;i++) { buf[i]=objMA.Main(i); } }
4.5. Вариант №4
Используется стандартная
библиотека: классы для работы с индикаторами.
Копирование индикаторного буфера целиком. Расчёт производится на всём массиве данных.
Модель | Результат | Лучший результат |
---|---|---|
MODE_SMA | 0,0996 | 0,000140 (вариант 6) |
MODE_EMA | 0,0996 | 0,000121 (вариант 6) |
MODE_SMMA | 0,0996 | 0,000117 (вариант 6) |
MODE_LWMA | 0,0996 | 0,0029 (вариант 2,5) |
#include <Indicators\Trend.mqh> ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[]; double time; int count=10000; int startGTC,endGTC; int m,p; CiMA objMA; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { if(ArrayResize(buf,count)<0) return(-1); ArraySetAsSeries(buf,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test7(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test7() { //--- Модель расчёта: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA objMA.Create(NULL,M[m],periodMA,0,MODE_SMA,P[p]); objMA.BuffSize(count); objMA.Refresh(1); objMA.GetData(0,count,0,buf); }
4.6. Вариант №5
Используются тест: №8, в котором применён универсальный способ получения значений технических индикаторов.
Расчёт производится на всём массиве данных.
Модель | Результат | Лучший результат |
---|---|---|
MODE_SMA | 0,0030 | 0,000140 (вариант 6) |
MODE_EMA | 0,0029 | 0,000121 (вариант 6) |
MODE_SMMA | 0,0029 | 0,000117 (вариант 6) |
MODE_LWMA | 0,0029 | 0,0029 (вариант 2,5) |
ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double time; int count=10000; int startGTC,endGTC; int m,p; double MA[]; // массив для индикатора iMA int MA_handle; // указатель на индикатор iMA MqlParam params[]; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { ArrayResize(params,4); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test8(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test8() { //--- Модель расчёта: MODE_SMA; MODE_EMA; MODE_SMMA; MODE_LWMA //--- set ma_period params[0].type =TYPE_INT; params[0].integer_value=periodMA; //--- set ma_shift params[1].type =TYPE_INT; params[1].integer_value=0; //--- set ma_method params[2].type =TYPE_INT; params[2].integer_value=MODE_SMA; //--- set applied_price params[3].type =TYPE_INT; params[3].integer_value=P[p]; //--- create MA MA_handle=IndicatorCreate(NULL,M[m],IND_MA,4,params); while(BarsCalculated(MA_handle)<count){} CopyBuffer(MA_handle,0,0,count,MA); }
4.7. Вариант №6
В этом варианте участвуют 4 теста: №9(SMA), №10(EMA), №11(SMMA) и
№12(LWMA).
В них используется библиотека функций MovingAverages.mqh из стандартной поставки, аналог функции iMAOnArray из MQL4. Расчёт ведется на всём массиве данных.
Модель | Результат | Лучший результат |
---|---|---|
MODE_SMA | 0,000140 | 0,000140 (вариант 6) |
MODE_EMA | 0,000121 | 0,000121 (вариант 6) |
MODE_SMMA | 0,000117 | 0,000117 (вариант 6) |
MODE_LWMA | 0,00350 | 0,0029 (вариант 2,5) |
#include <MovingAverages.mqh> ENUM_TIMEFRAMES M[4]= { PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30 }; ENUM_APPLIED_PRICE P[7]= { PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED }; int periodMA; double buf[],arr[]; double close[]; double time; int count=10000,total; int startGTC,endGTC; int m,p; //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int OnStart() { CopyClose(_Symbol,_Period,0,count,close); total=ArrayCopy(arr,close); if(ArrayResize(buf,total)<0) return(-1); //--- ArraySetAsSeries(close,false); ArraySetAsSeries(arr,false); ArraySetAsSeries(buf,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { CopyClose(_Symbol,M[m],0,count,close); total=ArrayCopy(arr,close); for(periodMA=1;periodMA<=100;periodMA++) { Test9(); // заменить на необходимый тест } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- return(0); } //+------------------------------------------------------------------+ void Test9() { SimpleMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ void Test10() { ExponentialMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ void Test11() { SmoothedMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ void Test12() { LinearWeightedMAOnBuffer(total,0,0,periodMA,arr,buf); }
Примечание: В расчётах участвовал только один массив цен закрытия баров, хотя по программе должны участвовать разные. Это упрощение, принятое для данного варианта, на быстродействие никакого влияния не оказывает.
5. Отображение результатов тестирования
Для получения результатов и проверки правильности расчёта скользящих средних, предлагаю использовать вот такую функцию:
void PrintTest(const int position, const double &price[]) { Print("Общее время исполнения [мсек] ",(endGTC-startGTC)); Print("Быстродействие [сек] ",time); Print(position," - элемент массива = ",price[position]); }
А вызвать её можно, например вот так, при этом указав, на каком баре и какой массив вас интересует:
//--- ArraySetAsSeries(buf,false); ArraySetAsSeries(close,false); startGTC=GetTickCount(); //--- for(m=0;m<=3;m++) { for(p=0;p<=6;p++) { for(periodMA=1;periodMA<=100;periodMA++) { Test(); } } } //--- endGTC=GetTickCount(); time=endGTC-startGTC; time=time/1000/m/p/periodMA; //--- Вывод результатов ArraySetAsSeries(buf,true); ArraySetAsSeries(close,true); PrintTest(0,buf); PrintTest(0,close); //---
Обратите внимание на изменение индексации массивов перед расчётом и перед выводом результатов.
ВАЖНО. Перед расчётом скользящих средних флаг индексации = false, а перед выводом результатов флаг индексации = true.
6. Дополнительные исследования
Дополнительные исследования потребовались для того, чтобы ответить на вопрос: как влияют входные параметры на быстродействие расчёта скользящей средней?
Для этого исследуем вариант №6 (см. раздел 4.7). Этот вариант выбран потому, что его быстродействие оказалось самым высоким в рамках проведённых экспериментов.
Программа испытаний:
Вариант | Таймфрейм | Период усреднения |
---|---|---|
1 | М1 | 144 |
2 | М5 | 144 |
3 | М15 | 144 |
4 | М30 | 144 |
5 | М1 | 21 |
6 | М1 | 34 |
7 | М1 | 55 |
8 | М1 | 89 |
9 | М1 | 233 |
10 | М1 | 377 |
11 | М1 | 610 |
12 | М1 | 987 |
Таблица 3. Программа дополнительных исследований
Код тестов:
//+------------------------------------------------------------------+ //| Test_SMA Модель расчёта: MODE_SMA | //+------------------------------------------------------------------+ void Test_SMA(int periodMA,ENUM_TIMEFRAMES periodTF) { CopyClose(_Symbol,periodTF,0,count,close); int total=ArrayCopy(arr,close); SimpleMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ //| Test_EMA Модель расчёта: MODE_EMA | //+------------------------------------------------------------------+ void Test_EMA(int periodMA,ENUM_TIMEFRAMES periodTF) { CopyClose(_Symbol,periodTF,0,count,close); int total=ArrayCopy(arr,close); ExponentialMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ //| Test_SMMA Модель расчёта: MODE_SMMA | //+------------------------------------------------------------------+ void Test_SMMA(int periodMA,ENUM_TIMEFRAMES periodTF) { CopyClose(_Symbol,periodTF,0,count,close); int total=ArrayCopy(arr,close); SmoothedMAOnBuffer(total,0,0,periodMA,arr,buf); } //+------------------------------------------------------------------+ //| Test_LWMA Модель расчёта: MODE_LWMA | //+------------------------------------------------------------------+ void Test_LWMA(int periodMA,ENUM_TIMEFRAMES periodTF) { CopyClose(_Symbol,periodTF,0,count,close); int total=ArrayCopy(arr,close); LinearWeightedMAOnBuffer(total,0,0,periodMA,arr,buf); }
Для проведения дополнительных исследований, воспользуемся программой autotestMA, внешний вид которой показан на рис. 7.
Рисунок 7. Внешний вид программы автоматического тестирования autotest
Результаты исследований: (по оси Х логарифмическая шкала времени)
Рисунок 8. Влияние таймфрейма на быстродействие расчёта скользящих средних
Рисунок 9. Влияние периода усреднения на быстродействие расчёта скользящих средних
ВЫВОДЫ по результатам дополнительных исследований:
- С какого таймфрейма брать данные для расчёта МА не имеет значения, поскольку на быстродействие этот параметр влияния не оказывает (см. рис.8).
- Период усреднения скользящих средних для моделей расчёта SMA, EMA, SMMA на быстродействие практически не влияет. А вот для модели LWMA увеличение периода усреднения замедляет расчёт, причём существенно с 0,00373 сек. до 0,145 сек(см. рис.9).
Заключение
Неудачный выбор функции расчёта скользящих средних может существенно снизить быстродействие ваших программ.





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования