Скачать MetaTrader 5

Эксперты на основе популярных торговых систем и алхимия оптимизации торгового робота (Продолжение)

1 апреля 2008, 09:42
Nikolay Kositsin
16
888

Введение


Поступило предложение от читателя предыдущей статьи немного механизировать сам процесс бэктестинга, чтобы за один общий заход можно было получить результаты всех оптимизаций одновременно. Да и всё время передвигать период тестирования в бэктестинге тоже не так чтобы и шибко удобно, лучше это как-то сделать в автопилотном режиме. Сама идея просто великолепная - благо возможностей для её реализации в MQL4 более чем достаточно, так что с решения этой задачи я и начну эту статью.

Механизация бэктестинга


Для решения этой задачи следует:

1. Вписать под шапкой любого, интересующего вас эксперта строку следующего содержания:

//+==================================================================+
//| Custom BackTesting function                                      |
//+==================================================================+
#include <IsBackTestingTime.mqh>

Посредством этой директивы мы включаем в код эксперта функцию IsBackTestingTime(). Вполне естественно следует не забыть поместить файл IsBackTestingTime.mqh в папку INCLUDE. Эта функция:

bool IsBackTestingTime()
 {
 } 

предназначена для определения времени, в течении которого происходит бэктестерная оптимизация или бэктестинг. В эти периоды времени эта функция всегда возвращает true, в остальное время эта функция возвращает false. Помимо этой функции в код эксперта этой директивой добавляются внешние экспертные переменные:

//---- Объявления внешних переменных для бэктестинга
extern datetime Start_Time = D'2007.01.01'; // время старта нулевой оптимизации
extern int Opt_Period = 3; // период оптимизации в месяцах, если значение периода меньше нуля, то все параметры измеряются в днях
extern int Test_Period = 2; // период тестирования в месяцах
extern int Period_Shift = 1; // шаг сдвига периода оптимизации в месяцах
extern int Opt_Number = 0; // номер оптимизации

Я надеюсь, что смысл этих переменных будет абсолютно понятен всем, кто читал мою предыдущую статью, и пояснять их смысл второй раз несколько излишне!

2. В блок стартовой функции перед кодом эксперта необходимо поместить простейший универсальный код обращения к функции IsBackTestingTime(), ограничивающий работу эксперта определёнными временными рамками, в зависимости от номера бэктестерной оптимизации.


 //----+ Выполнение условий бэктестинга  
   if (!IsBackTestingTime())
                       return(0);

Схематично это будет выглядеть следующим образом:

//+==================================================================+
//|                                                 Exp_BackTest.mq4 |
//|                             Copyright © 2008,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2008, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//+==================================================================+
//| Custom BackTesting function                                      |
//+==================================================================+
#include <IsBackTestingTime.mqh>
//---- ВХОДНЫЕ ПАРАМЕТРЫ ЭКСПЕРТА 
//---- ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ЭКСПЕРТА
//+==================================================================+
//| ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ ЭКСПЕРТА                                |
//+==================================================================+
 
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//----+ +------------------------------------------------------------+    
//---- КОД ДЛЯ ИНИЦИАЛИЗАЦИИ ЭКСПЕРТА
//----+ +------------------------------------------------------------+                 
//---- завершение инициализации
   return(0);
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Выполнение условий бэктестинга  
   if (!IsBackTestingTime())
                       return(0);             
   //----+ +---------------------------------------------------------+    
   //----+ КОД АЛГОРИТМА ЭКСПЕРТА
   //----+ +---------------------------------------------------------+
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

Кому интерсно решение подобной задачи на примере готового эксперта, могут посмотреть код эксперта Exp_5_1.mq4, являющегося модифицированным для бэктестинга экспертом Exp_5.mq4 из предыдущей статьи. По большому счёту какой-то значительной разницы в оптимизации подобного эксперта по сравнению с обычным экспертом нет. Разве что, на мой взгляд, не стоит оптимизировать бэктестерные переменные, за исключением переменной Opt_Number, хотя как знать, тут у каждого свой подход должен быть.

Самое главное не забывать, что после оптимизации при тестировании мы получаем результаты уже не внутри периода оптимизации, а после него, за правой границей! И всё-таки делать все бэктестерные оптимизации за один заход с помощью генетического алгоритма не совсем сподручно, гораздо более интересно делать более углублённое исследование каждой бэктестерной оптимизации отдельно без оптимизации входной переменной Opt_Number.

Но даже в этом случае подобный подход очень сильно ускоряет понимание поведения эксперта. Ну и при подобном мероприятии следует помнить, что значение внешней переменной Opt_Number может изменяться от нуля и до некоторого максимального значения, которое можно определить следующим образом: от общего периода, на котором проводятся все бэктестерные оптимизации взятого в месяцах, отнимается период бэктестерной оптимизации в месяцах (Opt_Period) и отнимается период бэктестинга (Test_Period). К полученной величине добавить единицу. Полученный результат и будет максимумом для переменной Opt_Number, в случае, ежели Period_Shift равен единице.


Торговые системы, основанные на пересечениях двух мувингов

Этот вариант торговых систем достаточно распространён, и алгоритм, лежащий в их основе давно следовало рассмотреть поподробнее. Для длинных позиций алгоритм входа в рынок будет выглядеть следующим образом:

Для коротких позиций алгоритм входа в рынок аналогично будет таким:

В качестве индикаторов могут использоваться два одинаковых мувинга с разными значениями параметров, определяющих усреднение в индикаторах. Предполагается, что параметр, определяющий усреднение у мувинга MovA имеет всегда меньшее значение, чем этот же параметр у мувинга MovB. Таким образом мувинг MovA оказывается в этой торговой системе быстрым мувингом, а мувинг MovB медленным. Вот вариант реализации данной торговой системы на двух JMA мувингах:

//+==================================================================+
//|                                                        Exp_6.mq4 |
//|                             Copyright © 2007,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2007, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +-------------------------------------------------------------------------------+
//---- ВХОДНЫЕ ПАРАМЕТРЫ ЭКСПЕРТА ДЛЯ BUY СДЕЛОК 
extern bool   Test_Up = true;//фильтр направления расчётов сделок
extern int    Timeframe_Up = 240;
extern double Money_Management_Up = 0.1;
extern int    LengthA_Up = 4;  // глубина сглаживания быстрого мувинга
extern int    PhaseA_Up = 100; // параметр, изменяющийся в пределах 
          //-100 ... +100, влияет на качество переходного процесса быстрого мувинга; 
extern int    IPCA_Up = 0;/* Выбор цен, по которым производится расчёт 
индикатора быстрым мувингом (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 
6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
extern int    LengthB_Up = 4; // приращение глубины сглаживания медленного мувинга к быстрому
extern int    PhaseB_Up = 100; // параметр, изменяющийся в пределах 
          //-100 ... +100, влияет на качество переходного процесса  медленного мувинга; 
extern int    IPCB_Up = 0;/* Выбор цен, по которым производится расчёт 
индикатора медленным мувингом (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 
6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
extern int    STOPLOSS_Up = 50;  // стоплосс
extern int    TAKEPROFIT_Up = 100; // тейкпрофит
extern bool   ClosePos_Up = true; // разрешение принудительного закрывания позиции
//----+ +-------------------------------------------------------------------------------+
//---- ВХОДНЫЕ ПАРАМЕТРЫ ЭКСПЕРТА ДЛЯ SELL СДЕЛОК 
extern bool   Test_Dn = true;//фильтр направления расчётов сделок
extern int    Timeframe_Dn = 240;
extern double Money_Management_Dn = 0.1;
extern int    LengthA_Dn = 4;  // глубина сглаживания быстрого мувинга
extern int    PhaseA_Dn = 100; // параметр, изменяющийся в пределах
         // -100 ... +100, влияет на качество переходного процесса быстрого мувинга; 
extern int    IPCA_Dn = 0;/* Выбор цен, по которым производится расчёт 
индикатора быстрым мувингом (0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 
6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
extern int    LengthB_Dn = 4; // приращение глубины сглаживания медленного мувинга к быстрому
extern int    PhaseB_Dn = 100; // параметр, изменяющийся в пределах
         // -100 ... +100, влияет на качество переходного процесса  медленного мувинга; 
extern int    IPCB_Dn = 0;/* Выбор цен, по которым производится расчёт 
индикатора медленным мувингом(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 
6-WEIGHTED, 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi Low, 12-Heiken Ashi High, 13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
extern int   STOPLOSS_Dn = 50;  // стоплосс
extern int   TAKEPROFIT_Dn = 100; // тейкпрофит
extern bool   ClosePos_Dn = true; // разрешение принудительного закрывания позиции
//----+ +-------------------------------------------------------------------------------+
//---- Целые переменные для минимума расчётных баров
int MinBar_Up, MinBar_Dn;
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Проверка значения переменной Timeframe_Up на корректность
   if (Timeframe_Up != 1)
    if (Timeframe_Up != 5)
     if (Timeframe_Up != 15)
      if (Timeframe_Up != 30)
       if (Timeframe_Up != 60)
        if (Timeframe_Up != 240)
         if (Timeframe_Up != 1440)
           Print(StringConcatenate("Параметр Timeframe_Up не может ",  
                                  "быть равным ", Timeframe_Up, "!!!"));
//---- Проверка значения переменной Timeframe_Dn на корректность 
   if (Timeframe_Dn != 1)
    if (Timeframe_Dn != 5)
     if (Timeframe_Dn != 15)
      if (Timeframe_Dn != 30)
       if (Timeframe_Dn != 60)
        if (Timeframe_Dn != 240)
         if (Timeframe_Dn != 1440)
           Print(StringConcatenate("Параметр Timeframe_Dn не может ",  
                                 "быть равным ", Timeframe_Dn, "!!!")); 
//---- Инициализация переменных             
   MinBar_Up = 4 + 30;
   MinBar_Dn = 4 + 30;                                        
//---- завершение инициализации
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- Завершение деинициализации эксперта
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Объявление локальных переменных
   int    bar;
   double MovA[2], MovB[2];
   //----+ Объявление статических переменных
   static int LastBars_Up, LastBars_Dn;
   static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop;
   
   //----++ КОД ДЛЯ ДЛИННЫХ ПОЗИЦИЙ
   if (Test_Up)
    {
      int IBARS_Up = iBars(NULL, Timeframe_Up);
      
      if (IBARS_Up >= MinBar_Up)
       {
         if (LastBars_Up != IBARS_Up)
          {
           //----+ Иницмализация переменных 
           BUY_Sign = false;
           BUY_Stop = false;
           LastBars_Up = IBARS_Up;
           
           //----+ ВЫЧИСЛЕНИЕ ИНДИКАТОРНЫХ ЗНАЧЕНИЙ И ЗАГРУЗКА ИХ В БУФЕРЫ        
           for(bar = 1; bar < 3; bar++)
                     MovA[bar - 1] =                  
                         iCustom(NULL, Timeframe_Up, 
                                "JJMA", LengthA_Up, PhaseA_Up, 
                                                   0, IPCA_Up, 0, bar);
           for(bar = 1; bar < 3; bar++)
                MovB[bar - 1] =                  
                   iCustom(NULL, Timeframe_Up, 
                     "JJMA", LengthA_Up + LengthB_Up, PhaseB_Up, 
                                                   0, IPCB_Up, 0, bar);
                                                   
           //----+ ОПРЕДЕЛЕНИЕ СИГНАЛОВ ДЛЯ СДЕЛОК                                          
           if ( MovA[1] < MovB[1])
               if ( MovA[0] > MovB[0])
                        BUY_Sign = true;
                          
            if ( MovA[0] > MovB[0])
                        BUY_Stop = true;                                           
          }
          
          //----+ СОВЕРШЕНИЕ СДЕЛОК
          if (!OpenBuyOrder1(BUY_Sign, 1, Money_Management_Up, 
                                          STOPLOSS_Up, TAKEPROFIT_Up))
                                                                 return(-1);
          if (ClosePos_Up)
                if (!CloseOrder1(BUY_Stop, 1))
                                        return(-1);
        }
     }
     
   //----++ КОД ДЛЯ КОРОТКИХ ПОЗИЦИЙ
   if (Test_Dn)
    {
      int IBARS_Dn = iBars(NULL, Timeframe_Dn);
      
      if (IBARS_Dn >= MinBar_Dn)
       {
         if (LastBars_Dn != IBARS_Dn)
          {
           //----+ Иницмализация переменных 
           SELL_Sign = false;
           SELL_Stop = false;
           LastBars_Dn = IBARS_Dn; 
           
           //----+ ВЫЧИСЛЕНИЕ ИНДИКАТОРНЫХ ЗНАЧЕНИЙ И ЗАГРУЗКА ИХ В БУФЕРЫ
           for(bar = 1; bar < 3; bar++)
                     MovA[bar - 1] =                  
                         iCustom(NULL, Timeframe_Dn, 
                                "JJMA", LengthA_Dn, PhaseA_Dn, 
                                                   0, IPCA_Dn, 0, bar);
           for(bar = 1; bar < 3; bar++)
                MovB[bar - 1] =                  
                   iCustom(NULL, Timeframe_Dn, 
                     "JJMA", LengthA_Dn + LengthB_Dn, PhaseB_Dn, 
                                                   0, IPCB_Dn, 0, bar);
           
           //----+ ОПРЕДЕЛЕНИЕ СИГНАЛОВ ДЛЯ СДЕЛОК                                          
           if ( MovA[1] > MovB[1])
               if ( MovA[0] < MovB[0])
                        SELL_Sign = true;
                          
            if ( MovA[0] < MovB[0])
                        SELL_Stop = true;                                                
          }
          //----+ СОВЕРШЕНИЕ СДЕЛОК
          if (!OpenSellOrder1(SELL_Sign, 2, Money_Management_Dn, 
                                            STOPLOSS_Dn, TAKEPROFIT_Dn))
                                                                   return(-1);
          if (ClosePos_Dn)
                if (!CloseOrder1(SELL_Stop, 2))
                                        return(-1);
        }
     }
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

Торговые системы, основанные на пересечениях двух осцилляторов


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

Для выставления отложенных ордеров BuyLimit алгоритм будет выглядеть следующим образом:

Аналогичный алгоритм для ордеров типа SellLimit получим в следующем виде:



Код этого эксперта во многом аналогичен коду предыдущего эксперта:

//+==================================================================+
//|                                                        Exp_7.mq4 |
//|                             Copyright © 2007,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2007, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +---------------------------------------------------------------------------+
//---- ВХОДНЫЕ ПАРАМЕТРЫ ЭКСПЕРТА ДЛЯ BUY СДЕЛОК 
extern bool   Test_Up = true; //фильтр направления расчётов сделок
extern int    Timeframe_Up = 240;
extern double Money_Management_Up = 0.1;
extern int    FST_period_Up = 12;  // период быстрого мувинга
extern int    SLO_period_Up = 22; // приращение периода медленного мувинга к быстрому
extern int    SIGN_period_Up = 8; // период сигнальной линии
extern int    Price_Up = 0;  // выбор цен, по которым производится расчёт MACD
extern int    STOPLOSS_Up = 50;  // стоплосс
extern int    TAKEPROFIT_Up = 100; // тейкпрофит
extern int    PriceLevel_Up =40; // разница между текущей ценой и 
                                         // ценой срабатывания отложенного ордера
extern bool   ClosePos_Up = true; // разрешение принудительного закрывания позиции
//----+ +---------------------------------------------------------------------------+
//---- ВХОДНЫЕ ПАРАМЕТРЫ ЭКСПЕРТА ДЛЯ SELL СДЕЛОК 
extern bool   Test_Dn = true; //фильтр направления расчётов сделок
extern int    Timeframe_Dn = 240;
extern double Money_Management_Dn = 0.1;
extern int    FST_period_Dn = 12;  // период быстрого мувинга
extern int    SLO_period_Dn = 22; // приращение периода медленного мувинга к быстрому
extern int    SIGN_period_Dn = 8; // период сигнальной линии
extern int    Price_Dn = 0;  // выбор цен, по которым производится расчёт MACD
extern int    STOPLOSS_Dn = 50;  // стоплосс
extern int    TAKEPROFIT_Dn = 100; // тейкпрофит
extern int    PriceLevel_Dn =40;  // разница между текущей ценой и 
                                         // ценой срабатывания отложенного ордера
extern bool   ClosePos_Dn = true; // разрешение принудительного закрывания позиции
//----+ +---------------------------------------------------------------------------+
//---- Целые переменные для минимума расчётных баров
int MinBar_Up, MinBar_Dn;
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Проверка значения переменной Timeframe_Up на корректность
   if (Timeframe_Up != 1)
    if (Timeframe_Up != 5)
     if (Timeframe_Up != 15)
      if (Timeframe_Up != 30)
       if (Timeframe_Up != 60)
        if (Timeframe_Up != 240)
         if (Timeframe_Up != 1440)
           Print(StringConcatenate("Параметр Timeframe_Up не может ",  
                                  "быть равным ", Timeframe_Up, "!!!"));
//---- Проверка значения переменной Timeframe_Dn на корректность 
   if (Timeframe_Dn != 1)
    if (Timeframe_Dn != 5)
     if (Timeframe_Dn != 15)
      if (Timeframe_Dn != 30)
       if (Timeframe_Dn != 60)
        if (Timeframe_Dn != 240)
         if (Timeframe_Dn != 1440)
           Print(StringConcatenate("Параметр Timeframe_Dn не может ",  
                                 "быть равным ", Timeframe_Dn, "!!!")); 
//---- Инициализация переменных             
   MinBar_Up = 4 + FST_period_Up + SLO_period_Up + SIGN_period_Up;
   MinBar_Dn = 4 + FST_period_Dn + SLO_period_Dn + SIGN_period_Dn;                                        
//---- завершение инициализации
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- Завершение деинициализации эксперта
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Объявление локальных переменных
   int    bar;
   double MovA[2], MovB[2];
   //----+ Объявление статических переменных
   static int LastBars_Up, LastBars_Dn;
   static datetime StopTime_Up, StopTime_Dn; 
   static bool BUY_Sign, BUY_Stop, SELL_Sign, SELL_Stop;
   
   //----++ КОД ДЛЯ ДЛИННЫХ ПОЗИЦИЙ
   if (Test_Up)
    {
      int IBARS_Up = iBars(NULL, Timeframe_Up);
      
      if (IBARS_Up >= MinBar_Up)
       {
         if (LastBars_Up != IBARS_Up)
          {
           //----+ Иницмализация переменных 
           BUY_Sign = false;
           BUY_Stop = false;
           LastBars_Up = IBARS_Up;
           StopTime_Up = iTime(NULL, Timeframe_Up, 0)
                                            + 60 * Timeframe_Up;
           
           //----+ ВЫЧИСЛЕНИЕ ИНДИКАТОРНЫХ ЗНАЧЕНИЙ И ЗАГРУЗКА ИХ В БУФЕРЫ           
           for(bar = 1; bar < 3; bar++)
             MovA[bar - 1] = iMACD(NULL, Timeframe_Up, 
                      FST_period_Up, FST_period_Up + SLO_period_Up,
                                         SIGN_period_Up, Price_Up, 0, bar);
                          
           for(bar = 1; bar < 3; bar++)
             MovB[bar - 1] = iMACD(NULL, Timeframe_Up, 
                      FST_period_Up, FST_period_Up + SLO_period_Up,
                                         SIGN_period_Up, Price_Up, 1, bar);
                 
           //----+ ОПРЕДЕЛЕНИЕ СИГНАЛОВ ДЛЯ СДЕЛОК                                          
           if ( MovA[1] < MovB[1])
               if ( MovA[0] > MovB[0])
                        BUY_Sign = true;
                          
            if ( MovA[0] > MovB[0])
                        BUY_Stop = true;                                           
          }
          
          //----+ СОВЕРШЕНИЕ СДЕЛОК
          if (!OpenBuyLimitOrder1(BUY_Sign, 1, 
              Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up,
                                            PriceLevel_Up, StopTime_Up))
                                                                 return(-1);
          if (ClosePos_Up)
                if (!CloseOrder1(BUY_Stop, 1))
                                        return(-1);
        }
     }
     
   //----++ КОД ДЛЯ КОРОТКИХ ПОЗИЦИЙ
   if (Test_Dn)
    {
      int IBARS_Dn = iBars(NULL, Timeframe_Dn);
      
      if (IBARS_Dn >= MinBar_Dn)
       {
         if (LastBars_Dn != IBARS_Dn)
          {
           //----+ Иницмализация переменных 
           SELL_Sign = false;
           SELL_Stop = false;
           LastBars_Dn = IBARS_Dn;
           StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) 
                                            + 60 * Timeframe_Dn; 
           
           //----+ ВЫЧИСЛЕНИЕ ИНДИКАТОРНЫХ ЗНАЧЕНИЙ И ЗАГРУЗКА ИХ В БУФЕРЫ          
           for(bar = 1; bar < 3; bar++)
             MovA[bar - 1] = iMACD(NULL, Timeframe_Dn, 
                      FST_period_Dn, FST_period_Dn + SLO_period_Dn,
                                         SIGN_period_Dn, Price_Dn, 0, bar);
                          
           for(bar = 1; bar < 3; bar++)
             MovB[bar - 1] = iMACD(NULL, Timeframe_Dn, 
                      FST_period_Dn, FST_period_Dn + SLO_period_Dn,
                                         SIGN_period_Dn, Price_Dn, 1, bar);
           
           //----+ ОПРЕДЕЛЕНИЕ СИГНАЛОВ ДЛЯ СДЕЛОК                                          
           if ( MovA[1] > MovB[1])
               if ( MovA[0] < MovB[0])
                        SELL_Sign = true;
                          
            if ( MovA[0] < MovB[0])
                        SELL_Stop = true;                                                
          }
          //----+ СОВЕРШЕНИЕ СДЕЛОК
          if (!OpenSellLimitOrder1(SELL_Sign, 2, 
              Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn,
                                            PriceLevel_Dn, StopTime_Dn))
                                                                 return(-1);
          if (ClosePos_Dn)
                if (!CloseOrder1(SELL_Stop, 2))
                                        return(-1);
        }
     }
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

Заключение

Очередная статья подходит к своему концу. Очередная торговая система была абсолютно без проблем реализована в экспертах на абсолютно разных вариантах индикаторов. Я надеюсь, что данная статья окажется полезной начинающим экспертописателям для дальнейшего развития навыков превращения первоначально правильно формализованных алгоритмов, лежащих в основе торговых систем, в готовый и абсолютно рабочий код ваших экспертов.

Прикрепленные файлы |
EXPERTS.zip (8.58 KB)
INCLUDE.zip (17.98 KB)
indicators.zip (5.19 KB)
TESTER.zip (5.27 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (16)
MQL4 Comments
MQL4 Comments | 3 апр 2008 в 16:31
GODZILLA:
Но всё равно, постах много лишней воды, поневоле озвереешь!

Извините... В дальнейшем постараюсь быть более лаконичным.

MQL4 Comments
MQL4 Comments | 3 апр 2008 в 19:37
Николай, возможно мы друг друга не поняли.

Я внимательно проанализировал код Вашей программы, но не нашёл в ней того чего искал. Насколько я понял предлагаемая Вами программа просто варирует синтервалами оптимизации и тестирования. Возможно Вы не поняли суть моего вопроса.

Эх, придётся опять водички налить. :)

Вы предлагаете результаты оптимизации сохратить в файл, а потом их загрузить в другой терминал и снова оптимизировать. Возникает вопрос какие результаты и в какой файл? Я знаю пока лишь одну возможность сохранения результатов оптимизации в файл - это из окна "результаты оптимизации" установить какой-то один проход оптимизации во входные параметры, а затем из окна "свойства эксперта" - всохранить этот один проход в файл "".set. Но это сохранение сохранит результаты только одного прохода не более. К чему тогда повторная оптимизация на данных одного прохода?

Я же предлагал другой вариант. После выполнения первой оптимизации в окне "результаты оптимизации" тестового терминала выдаётся таблица в которой выдаются результаты всех положительных проходов. Вот если бы ВСЕ эти результаты загрузить как шаги повторной оптимизации.

Извините, но ещё больше детализирую на цифрах. Допустим советник оптимизируется по трём переменным - х1, х2, х3.

После первой оптимизации выдаются наборы параметров, типа:

1-й проход - х1=5, х2=15, х3=30... и прочая информация: прибыль, просадка и т.д.;

2-й проход - х1=20, х2=4, х3=18... ;

3-й проход - х1=43, х2=26, х3=8... ;

... и т.д.

Та вот, вторую оптимизацию по следующему периоду хотелось бы проводить не на случайных параметрах х1, х2, х3, а брать только те комбинации этих параметров, которые уже были предложены после первой оптимизации, а все прочие - просто опустить.

Вот я что имел ввиду...

Nikolay Kositsin
Nikolay Kositsin | 4 апр 2008 в 06:02
Kadet:
Николай, возможно мы друг друга не поняли.

Я внимательно проанализировал код Вашей программы, но не нашёл в ней того чего искал. Насколько я понял предлагаемая Вами программа просто варирует синтервалами оптимизации и тестирования. Возможно Вы не поняли суть моего вопроса.

Эх, придётся опять водички налить. :)

Вы предлагаете результаты оптимизации сохратить в файл, а потом их загрузить в другой терминал и снова оптимизировать. Возникает вопрос какие результаты и в какой файл? Я знаю пока лишь одну возможность сохранения результатов оптимизации в файл - это из окна "результаты оптимизации" установить какой-то один проход оптимизации во входные параметры, а затем из окна "свойства эксперта" - всохранить этот один проход в файл "".set. Но это сохранение сохранит результаты только одного прохода не более. К чему тогда повторная оптимизация на данных одного прохода?

Я же предлагал другой вариант. После выполнения первой оптимизации в окне "результаты оптимизации" тестового терминала выдаётся таблица в которой выдаются результаты всех положительных проходов. Вот если бы ВСЕ эти результаты загрузить как шаги повторной оптимизации.

Извините, но ещё больше детализирую на цифрах. Допустим советник оптимизируется по трём переменным - х1, х2, х3.

После первой оптимизации выдаются наборы параметров, типа:

1-й проход - х1=5, х2=15, х3=30... и прочая информация: прибыль, просадка и т.д.;

2-й проход - х1=20, х2=4, х3=18... ;

3-й проход - х1=43, х2=26, х3=8... ;

... и т.д.

Та вот, вторую оптимизацию по следующему периоду хотелось бы проводить не на случайных параметрах х1, х2, х3, а брать только те комбинации этих параметров, которые уже были предложены после первой оптимизации, а все прочие - просто опустить.

Вот я что имел ввиду...


Увы! Сударь! Но эту идею, как не изголайся, а в более менее приличном виде реализовать средствами Метатрейдера едва ли удастся! Я сожалею и весьма!
MQL4 Comments
MQL4 Comments | 23 апр 2008 в 14:37

Николай! Вот использую любезно предоставленные Вашими библиотекой функций (INCLUDE). Вроде бы всё нормально.

Только иногда возникает какия-то ошибка при оптимизации. Оптимизационный процесс просто останавливается и всё. Не могу понять почему.

Если меняю функции открытия и закрытия ордеров на более простые (без полной проверки) - всё работает.

А подключу Ваши Опены - опять зависает почему-то.

При работе - вроду бы нормально.

Nikolay Kositsin
Nikolay Kositsin | 24 апр 2008 в 00:15
Kadet:

Николай! Вот использую любезно предоставленные Вашими библиотекой функций (INCLUDE). Вроде бы всё нормально.

Только иногда возникает какия-то ошибка при оптимизации. Оптимизационный процесс просто останавливается и всё. Не могу понять почему.

Если меняю функции открытия и закрытия ордеров на более простые (без полной проверки) - всё работает.

А подключу Ваши Опены - опять зависает почему-то.

При работе - вроду бы нормально.

Kadet, вам следовало бы немного детализировать ситуацию. Что значит "функции без полной проверки"? Дело в том, что я с подобным явлением не сталкивался абсолютно. Так что уточните ситуацию: Из каких функций и что вы из функций убираете, на счёте какого дилера оптимизируете, какой инструмент используете? Я, кстати, сразу после опубликовании статьи поменял файлы библиотек, немного исправив код, может вы используете самую старую библиотеку? Я вчера ещё раз заменил инклюдник Lite_EXPERT1.mqh дописав в него пару функций, совсем мамость код подправил и сделал новые пояснения к функциям в первой статье.

Хотя я немного освежил свою память, да я что-то такое видел. Например, когда перепрыгиваешь при подключении с демо-счёта одного брокера на счёт другого, а его просто уже за давностию лет закрыли. Возникает ситуация недополучения данных от брокера для расчётов.

Как легко и просто опубликовать видео на MQL4.community Как легко и просто опубликовать видео на MQL4.community

Показать обычно легче, чем рассказать. Предлагается простой и бесплатный способ создания видеороликов с помощью CamStudio для публикации на форумах MQL4.community.

MetaEditor: Опираясь на силу шаблонов MetaEditor: Опираясь на силу шаблонов

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

Диагностика рынка по пульсу Диагностика рынка по пульсу

В статье сделана попытка визуализировать интенсивность работы отдельных рынков и их временн`ых сегментов, выявить их закономерности и характер поведения.

Метаязык графических линий-приказов. Торговля и квалифицированное  обучение  трейдингу Метаязык графических линий-приказов. Торговля и квалифицированное обучение трейдингу

В статье описывается простой, доступный язык графических торговых приказов, совместимый с классическим техническим анализом. Представлен советник-полуавтомат GTerminal с применением в торговле результатов графического анализа. Рекомендуется для самоподготовки и обучения начинающих трейдеров.