AM2
Андрей

 
Уровень 34

  Торгую в компаниях:


Группа "Программирование на MQL"

Рейтинг 280



Напишем советник на MQL4 с использованием ООП

В этом топике создадим свой первый класс на MQL4 и используем его в простейшем советнике.

Заготовка:

Элементарная заготовка класса будет выглядеть так:


class CMyClass 
  {
   // Здесь располагается весь код класса
  };


Наш класс начинается со слова class, затем идет его имя и в фигурных скобках находится весь код класса.

Инкапсуляция :

В классе есть 3 уровня инкапсуляции: private (закрытый), protected (защищенный) и public (открытый).

Нам будет достаточно двух уровней:


class CMyClass 
  {
private:
   // Здесь располагаются переменные и функции, доступные только внутри класса
public:
   // Здесь располагаются переменные и функции, доступные также вне класса
  };


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



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CountTrades()
  {
   int count=0;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()<2) count++;
           }
        }
     }
   return(count);
  }


Добавим ее в раздел private, а функции открытия и закрытия ордеров в раздел public:


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PutOrder(int type,double price)
  {
   int r=0;
   color clr=Green;
   double sl=0,tp=0;

   if(type==1 || type==3 || type==5)
     {
      clr=Red;
      if(StopLoss>0) sl=NormalizeDouble(price+StopLoss*Point,Digits);
      if(TakeProfit>0) tp=NormalizeDouble(price-TakeProfit*Point,Digits);
     }

   if(type==0 || type==2 || type==4)
     {
      clr=Blue;
      if(StopLoss>0) sl=NormalizeDouble(price-StopLoss*Point,Digits);
      if(TakeProfit>0) tp=NormalizeDouble(price+TakeProfit*Point,Digits);
     }

   r=OrderSend(NULL,type,Lots,NormalizeDouble(price,Digits),Slip,sl,tp,"",Magic,0,clr);
   return;
  }



//+------------------------------------------------------------------+
//| Закрытие позиции по типу ордера                                  |
//+------------------------------------------------------------------+
void CloseAll(int ot=-1)
  {
   bool cl;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()==0 && (ot==0 || ot==-1))
              {
               RefreshRates();
               cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),Slip,White);
              }
            if(OrderType()==1 && (ot==1 || ot==-1))
              {
               RefreshRates();
               cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),Slip,White);
              }
           }
        }
     }
  }


И мы получили такой класс:


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CMyClass
  {
private:
   // Здесь располагаются переменные и функции, доступные только внутри класса

   //+------------------------------------------------------------------+
   //|                                                                  |
   //+------------------------------------------------------------------+
   int CountTrades()
     {
      int count=0;
      for(int i=OrdersTotal()-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
              {
               if(OrderType()<2) count++;
              }
           }
        }
      return(count);
     }
   //+------------------------------------------------------------------+

public:
   // Здесь располагаются переменные и функции, доступные также вне класса

   //+------------------------------------------------------------------+
   //|                                                                  |
   //+------------------------------------------------------------------+
   void PutOrder(int type,double price)
     {
      int r=0;
      color clr=Green;
      double sl=0,tp=0;

      if(type==1 || type==3 || type==5)
        {
         clr=Red;
         if(StopLoss>0) sl=NormalizeDouble(price+StopLoss*Point,Digits);
         if(TakeProfit>0) tp=NormalizeDouble(price-TakeProfit*Point,Digits);
        }

      if(type==0 || type==2 || type==4)
        {
         clr=Blue;
         if(StopLoss>0) sl=NormalizeDouble(price-StopLoss*Point,Digits);
         if(TakeProfit>0) tp=NormalizeDouble(price+TakeProfit*Point,Digits);
        }

      r=OrderSend(NULL,type,Lots,NormalizeDouble(price,Digits),Slip,sl,tp,"",Magic,0,clr);
      return;
     }
   //+------------------------------------------------------------------+

   //+------------------------------------------------------------------+
   //| Закрытие позиции по типу ордера                                  |
   //+------------------------------------------------------------------+
   void CloseAll(int ot=-1)
     {
      bool cl;
      for(int i=OrdersTotal()-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
              {
               if(OrderType()==0 && (ot==0 || ot==-1))
                 {
                  RefreshRates();
                  cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),Slip,White);
                 }
               if(OrderType()==1 && (ot==1 || ot==-1))
                 {
                  RefreshRates();
                  cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),Slip,White);
                 }
              }
           }
        }
     }
   //+------------------------------------------------------------------+
  };


Чтобы начать использовать наш класс, его необходимо загрузить. Объявим его аналогично любой другой переменной:


CMyClass mycl;


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



Другой способ записи класса:

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


class CMyClass
  {
private:
   int               CountTrades();
public:
   void              PutOrder(int type,double price);
   void              CloseAll(int ot=-1);
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CMyClass::CountTrades(void)
  {
   int count=0;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()<2) count++;
           }
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CMyClass::CloseAll(int ot=-1)
  {
   bool cl;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()==0 && (ot==0 || ot==-1))
              {
               RefreshRates();
               cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),Slip,White);
              }
            if(OrderType()==1 && (ot==1 || ot==-1))
              {
               RefreshRates();
               cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),Slip,White);
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CMyClass:<img src='http://opentraders.ru/templates/skin/g6h/images/smilies/008.gif' alt=' :P '> utOrder(int type,double price)
  {
   int r=0;
   color clr=Green;
   double sl=0,tp=0;

   if(type==1 || type==3 || type==5)
     {
      clr=Red;
      if(StopLoss>0) sl=NormalizeDouble(price+StopLoss*Point,Digits);
      if(TakeProfit>0) tp=NormalizeDouble(price-TakeProfit*Point,Digits);
     }

   if(type==0 || type==2 || type==4)
     {
      clr=Blue;
      if(StopLoss>0) sl=NormalizeDouble(price-StopLoss*Point,Digits);
      if(TakeProfit>0) tp=NormalizeDouble(price+TakeProfit*Point,Digits);
     }

   r=OrderSend(NULL,type,Lots,NormalizeDouble(price,Digits),Slip,sl,tp,"",Magic,0,clr);
   return;
  }


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

После создания класса и его вызова код простейшего советника будет выглядеть так:
(Эксперт написан в качестве учебного примера и открывает только покупки)


//+------------------------------------------------------------------+
//|                                                          OOP.mq4 |
//|                                              Copyright 2016, AM2 |
//|                                      http://www.forexsystems.biz |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, AM2"
#property link      "http://www.forexsystems.biz"
#property version   "1.00"
#property strict

extern double Lots       = 0.1;      // лот
extern int StopLoss      = 0;        // лось
extern int TakeProfit    = 0;        // язь
extern int Slip          = 30;       // реквот
extern int Shift         = 1;        // на каком баре сигнал индикатора
extern int Magic         = 123;      // магик
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CMyClass
  {
private:
   int               CountTrades();
public:
   void              PutOrder(int type,double price);
   void              CloseAll(int ot=-1);
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CMyClass::CountTrades(void)
  {
   int count=0;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()<2) count++;
           }
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CMyClass::CloseAll(int ot=-1)
  {
   bool cl;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
           {
            if(OrderType()==0 && (ot==0 || ot==-1))
              {
               RefreshRates();
               cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),Slip,White);
              }
            if(OrderType()==1 && (ot==1 || ot==-1))
              {
               RefreshRates();
               cl=OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),Slip,White);
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CMyClass :: PutOrder(int type,double price)
  {
   int r=0;
   color clr=Green;
   double sl=0,tp=0;

   if(type==1 || type==3 || type==5)
     {
      clr=Red;
      if(StopLoss>0) sl=NormalizeDouble(price+StopLoss*Point,Digits);
      if(TakeProfit>0) tp=NormalizeDouble(price-TakeProfit*Point,Digits);
     }

   if(type==0 || type==2 || type==4)
     {
      clr=Blue;
      if(StopLoss>0) sl=NormalizeDouble(price-StopLoss*Point,Digits);
      if(TakeProfit>0) tp=NormalizeDouble(price+TakeProfit*Point,Digits);
     }

   r=OrderSend(NULL,type,Lots,NormalizeDouble(price,Digits),Slip,sl,tp,"",Magic,0,clr);
   return;
  }

CMyClass mycl;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(OrdersTotal()<1) mycl.PutOrder(0,Ask);
  }
//+------------------------------------------------------------------+



И наконец проверим работоспособность эксперта в тестере стратегий:



Желающие подробнее изучить создание экспертов с помощью ООП, могут пройти по ссылке: www.mql5.com/ru/articles/351

Скачать файл: www.opentraders.ru/downloads/1309/
  • +5
  • Просмотров: 11854
  • 3 сентября 2016, 17:14
  • AM2
Понравилcя материал? Не забудьте поставить плюс и поделиться в социальной сети!

Вступите в группу "Программирование на MQL", чтобы следить за обновлениями
ПРИСОЕДИНИТЬСЯ К ГРУППЕ
присоединиться
  Предыдущая запись в группе
Нейросети. Однослойный перцептрон.
Следующая запись в группе  
Советник с применением ООП. Реальный пример
23 августа 2016
04 сентября 2016

Комментарии (1)

+
0
А индикаторную функцию в класс можно занести?
avatar

  8  Kudryashov Сообщений: 129

  • 26 июля 2018, 21:58

Зарегистрируйтесь или авторизуйтесь, чтобы оставить комментарий
Начать торговлю с Альпари