AM2
Андрей

 
Уровень 34

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


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

Рейтинг 280



Пишем мультивалютный советник на MQL4

Меня уже давно интересовала тема создания мультивалютных советников на MQL4, но до последнего времени я только правил чужие коды и не было своей основы. И вот благодаря следующему заказу мой первый мультик на MQL4 увидел свет :)  zakaz.opentraders.ru/30606.html
Все оказалось достаточно просто, для людей знакомых с языком не составит особого труда внести небольшие изменения в код обычного советника.

Советник открывает и закрывает позиции при пересечении верхнего и нижнего ADX.



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


//+------------------------------------------------------------------+
//|                                                          ADX.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  string s="Настройки советника";

extern double Lots       = 0.01;      // лот
extern int TakeProfit    = 3333;      // Тейк
extern int StopLoss      = 3333;      // Лосс
extern int Slip          = 30;        // Проскальзывание 
extern int Magic         = 123;       // Магик

extern  string sss="Настройки индикатора ADX";

//--- input ADX parameters
extern int ADXPeriod=14;        // ADX
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   Comment("");
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   OpenPos();
   ClosePos();
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PutOrder(int type,double price)
  {
   int r=0,d=0;
   color clr=Green;
   double sl=0,tp=0, pp=0;
   pp= MarketInfo(NULL,MODE_POINT);
   d =(int)MarketInfo(NULL,MODE_DIGITS);

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

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

   r=OrderSend(NULL,type,Lots,NormalizeDouble(price,d),Slip,sl,tp,"",Magic,0,clr);
   return;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OpenPos()
  {
   double bid=0,ask=0;

   double padx1=iADX(NULL,0,ADXPeriod,0,MODE_PLUSDI,1);
   double padx2=iADX(NULL,0,ADXPeriod,0,MODE_PLUSDI,2);
   double madx1=iADX(NULL,0,ADXPeriod,0,MODE_MINUSDI,1);
   double madx2=iADX(NULL,0,ADXPeriod,0,MODE_MINUSDI,2);

   if(CountTrades()<1)
     {
      bid = MarketInfo(NULL,MODE_BID);
      ask = MarketInfo(NULL,MODE_ASK);

      //buy
      if(padx2>madx2 && padx1<madx1)
        {
         PutOrder(0,ask);
        }
      //sell
      if(padx2<madx2 && padx1>madx1)
        {
         PutOrder(1,bid);
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ClosePos()
  {
   double bid=0,ask=0;
   double padx1=iADX(NULL,0,ADXPeriod,0,MODE_PLUSDI,1);
   double padx2=iADX(NULL,0,ADXPeriod,0,MODE_PLUSDI,2);
   double madx1=iADX(NULL,0,ADXPeriod,0,MODE_MINUSDI,1);
   double madx2=iADX(NULL,0,ADXPeriod,0,MODE_MINUSDI,2);

   if(CountTrades()>0)
     {
      for(int i=OrdersTotal()-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
              {
               if(OrderType()==OP_BUY)
                 {
                  if(padx2<madx2 && padx1>madx1)
                    {
                     bid=MarketInfo(NULL,MODE_BID);
                     if(!OrderClose(OrderTicket(),OrderLots(),bid,Slip,White))
                        Print("OrderClose error ",GetLastError());
                    }
                 }
               if(OrderType()==OP_SELL)
                 {
                  if(padx2>madx2 && padx1<madx1)
                    {
                     ask=MarketInfo(NULL,MODE_ASK);
                     if(!OrderClose(OrderTicket(),OrderLots(),ask,Slip,White))
                        Print("OrderClose error ",GetLastError());
                    }
                 }
              }
           }
        }
      return;
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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);
  }
//+------------------------------------------------------------------+



Чтобы переделать его в мульта добавим в настройки список пар по которым будем торговать:


extern  string s="Выбор валютной пары";

extern  string Symbol1 = "EURUSD";
extern  string Symbol2 = "GBPUSD";
extern  string Symbol3 = "";
extern  string Symbol4 = "";
extern  string Symbol5 = "";
extern  string Symbol6 = "";
extern  string Symbol7 = "";
extern  string Symbol8 = "";
extern  string Symbol9 = "";


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


void PutOrder(int type,double price)
  {
   int r=0,d=0;
   color clr=Green;
   double sl=0,tp=0, pp=0;
   pp= MarketInfo(symb,MODE_POINT);
   d =(int)MarketInfo(symb,MODE_DIGITS);

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

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

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


Чтобы сделать ее мультивалютной, нужно всего то сделать 2 замены:
1. Меняем строку
void PutOrder(int type,double price)

на
void PutOrder(int type,double price,string symb)
т.е. добавляем во входные параметры функции символ по которому будем торговать string symb
2. И в строке:
r=OrderSend(NULL,type,Lots,NormalizeDouble(price,d),Slip,sl,tp,"",Magic,0,clr);
пропишем этот самый символ symb
r=OrderSend(symb,type,Lots,NormalizeDouble(price,d),Slip,sl,tp,"",Magic,0,clr);


В итоге наша функция примет вид:


void PutOrder(int type,double price,string symb)
  {
   int r=0,d=0;
   color clr=Green;
   double sl=0,tp=0, pp=0;
   pp= MarketInfo(symb,MODE_POINT);
   d =(int)MarketInfo(symb,MODE_DIGITS);

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

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

   r=OrderSend(symb,type,Lot(symb,Magic),NormalizeDouble(price,d),Slip,sl,tp,"",Magic,0,clr);
   return;
  }


Сейчас поправим подсчет позиций:

Было:


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);
  }


Стало:


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


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


void OpenPos()
  {
   double bid=0,ask=0;

   double padx1=iADX(NULL,0,ADXPeriod,0,MODE_PLUSDI,1);
   double padx2=iADX(NULL,0,ADXPeriod,0,MODE_PLUSDI,2);
   double madx1=iADX(NULL,0,ADXPeriod,0,MODE_MINUSDI,1);
   double madx2=iADX(NULL,0,ADXPeriod,0,MODE_MINUSDI,2);

   if(CountTrades()<1)
     {
      bid = MarketInfo(NULL,MODE_BID);
      ask = MarketInfo(М,MODE_ASK);

      //buy
      if(padx2>madx2 && padx1<madx1)
        {
         PutOrder(0,ask);
        }
      //sell
      if(padx2<madx2 && padx1>madx1)
        {
         PutOrder(1,bid);
        }
     }
  }


После всех замен получим:


void OpenPos(string symb)
  {
   double bid=0,ask=0;

   double padx1=iADX(symb,0,ADXPeriod,0,MODE_PLUSDI,1);
   double padx2=iADX(symb,0,ADXPeriod,0,MODE_PLUSDI,2);
   double madx1=iADX(symb,0,ADXPeriod,0,MODE_MINUSDI,1);
   double madx2=iADX(symb,0,ADXPeriod,0,MODE_MINUSDI,2);

   if(CountTrades(symb)<1)
     {
      bid = MarketInfo(symb,MODE_BID);
      ask = MarketInfo(symb,MODE_ASK);

      //buy
      if(padx2>madx2 && padx1<madx1)
        {
         PutOrder(0,ask,symb);
        }
      //sell
      if(padx2<madx2 && padx1>madx1)
        {
         PutOrder(1,bid,symb);
        }
     }
  }


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

Это у нас было сначала:


void OnTick()
  {
   OpenPos();
   ClosePos();
  }


А теперь с учетом всех символов:


   if(Symbol1!=""){OpenPos(Symbol1); ClosePos(Symbol1);}
   if(Symbol2!=""){OpenPos(Symbol2); ClosePos(Symbol2);}
   if(Symbol3!=""){OpenPos(Symbol3); ClosePos(Symbol3);}
   if(Symbol4!=""){OpenPos(Symbol4); ClosePos(Symbol4);}
   if(Symbol5!=""){OpenPos(Symbol5); ClosePos(Symbol5);}
   if(Symbol6!=""){OpenPos(Symbol6); ClosePos(Symbol6);}
   if(Symbol7!=""){OpenPos(Symbol7); ClosePos(Symbol7);}
   if(Symbol8!=""){OpenPos(Symbol8); ClosePos(Symbol8);}
   if(Symbol9!=""){OpenPos(Symbol9); ClosePos(Symbol9);}


Если символ не пустая строка, торгуем.

В итоге поличили достаточно компактный код мультивалютного советника для 9 пар:


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

extern  string s="Выбор валютной пары";

extern  string Symbol1 = "EURUSD";
extern  string Symbol2 = "GBPUSD";
extern  string Symbol3 = "";
extern  string Symbol4 = "";
extern  string Symbol5 = "";
extern  string Symbol6 = "";
extern  string Symbol7 = "";
extern  string Symbol8 = "";
extern  string Symbol9 = "";

extern  string ss="Настройки советника";

extern double Lots       = 0.01;      // лот
extern int TakeProfit    = 3333;      // Тейк
extern int StopLoss      = 3333;      // Лосс
extern int Slip          = 30;        // Проскальзывание 
extern int Magic         = 123;       // Магик

extern  string sss="Настройки индикатора ADX";

//--- input ADX parameters
extern int ADXPeriod=14;        // ADX
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   Comment("");
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(Symbol1!=""){OpenPos(Symbol1); ClosePos(Symbol1);}
   if(Symbol2!=""){OpenPos(Symbol2); ClosePos(Symbol2);}
   if(Symbol3!=""){OpenPos(Symbol3); ClosePos(Symbol3);}
   if(Symbol4!=""){OpenPos(Symbol4); ClosePos(Symbol4);}
   if(Symbol5!=""){OpenPos(Symbol5); ClosePos(Symbol5);}
   if(Symbol6!=""){OpenPos(Symbol6); ClosePos(Symbol6);}
   if(Symbol7!=""){OpenPos(Symbol7); ClosePos(Symbol7);}
   if(Symbol8!=""){OpenPos(Symbol8); ClosePos(Symbol8);}
   if(Symbol9!=""){OpenPos(Symbol9); ClosePos(Symbol9);}
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PutOrder(int type,double price,string symb)
  {
   int r=0,d=0;
   color clr=Green;
   double sl=0,tp=0, pp=0;
   pp= MarketInfo(symb,MODE_POINT);
   d =(int)MarketInfo(symb,MODE_DIGITS);

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

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

   r=OrderSend(symb,type,Lots,NormalizeDouble(price,d),Slip,sl,tp,"",Magic,0,clr);
   return;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OpenPos(string symb)
  {
   double bid=0,ask=0;

   double padx1=iADX(symb,0,ADXPeriod,0,MODE_PLUSDI,1);
   double padx2=iADX(symb,0,ADXPeriod,0,MODE_PLUSDI,2);
   double madx1=iADX(symb,0,ADXPeriod,0,MODE_MINUSDI,1);
   double madx2=iADX(symb,0,ADXPeriod,0,MODE_MINUSDI,2);

   if(CountTrades(symb)<1)
     {
      bid = MarketInfo(symb,MODE_BID);
      ask = MarketInfo(symb,MODE_ASK);

      //buy
      if(padx2>madx2 && padx1<madx1)
        {
         PutOrder(0,ask,symb);
        }
      //sell
      if(padx2<madx2 && padx1>madx1)
        {
         PutOrder(1,bid,symb);
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ClosePos(string symb)
  {
   double bid=0,ask=0;
   double padx1=iADX(symb,0,ADXPeriod,0,MODE_PLUSDI,1);
   double padx2=iADX(symb,0,ADXPeriod,0,MODE_PLUSDI,2);
   double madx1=iADX(symb,0,ADXPeriod,0,MODE_MINUSDI,1);
   double madx2=iADX(symb,0,ADXPeriod,0,MODE_MINUSDI,2);

   if(CountTrades(symb)>0)
     {
      for(int i=OrdersTotal()-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
           {
            if(OrderSymbol()==symb && OrderMagicNumber()==Magic)
              {
               if(OrderType()==OP_BUY)
                 {
                  if(padx2<madx2 && padx1>madx1)
                    {
                     bid=MarketInfo(symb,MODE_BID);
                     if(!OrderClose(OrderTicket(),OrderLots(),bid,Slip,White))
                        Print("OrderClose error ",GetLastError());
                    }
                 }
               if(OrderType()==OP_SELL)
                 {
                  if(padx2>madx2 && padx1<madx1)
                    {
                     ask=MarketInfo(symb,MODE_ASK);
                     if(!OrderClose(OrderTicket(),OrderLots(),ask,Slip,White))
                        Print("OrderClose error ",GetLastError());
                    }
                 }
              }
           }
        }
      return;
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CountTrades(string symb)
  {
   int count=0;
   for(int i=OrdersTotal()-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==symb && OrderMagicNumber()==Magic)
           {
            if(OrderType()<2) count++;
           }
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+


П.С. Также можно сделать мультивалютный советник, который будет торговать по всем символам в окне рынка или путем перебора символов в массиве строк, мультик гридер или усреднитель. С новыми идеями и доработками можете обращаться в Стол заказов MQL
Исходные коды советников также можно скачать по ссылке: www.opentraders.ru/downloads/1063/
  • +7
  • Просмотров: 26771
  • 19 февраля 2016, 17:34
  • AM2
Понравилcя материал? Не забудьте поставить плюс и поделиться в социальной сети!

Вступите в группу "Программирование на MQL", чтобы следить за обновлениями
ПРИСОЕДИНИТЬСЯ К ГРУППЕ
присоединиться
  Предыдущая запись в группе
Пишем мультивалютный усреднитель на MQL5
25 ноября 2015
20 февраля 2016

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

+
0
Наверно надо ввести уроки по программированию советников *good*  на сайте
avatar

  19  lorik Сообщений: 357 - Лариса

  • 19 февраля 2016, 19:40
+
0
Так есть уже mql.opentraders.ru/ — кто хочет, тот научится…
avatar

  13  Fargo Сообщений: 495

  • 19 февраля 2016, 21:46
+
+1
А как прописать подсчёт ордеров для каждого символа по отдельности.
avatar

  3  kiboss Сообщений: 14

  • 20 февраля 2016, 16:25
+
0
Хороший вопрос
avatar

  16  cerber04 Сообщений: 409

  • 20 февраля 2016, 16:54
+
0
А как прописать подсчёт ордеров для каждого символа по отдельности.


В тексте статьи все есть.
avatar

  34  AM2 Автор Сообщений: 15880 - Андрей

  • 20 февраля 2016, 17:03
+
0
Значит получается функция int CountTrades(string symb)
считает ордера отдельно по каждому символу?
avatar

  3  kiboss Сообщений: 14

  • 20 февраля 2016, 20:05
+
0
Значит получается функция int CountTrades(string symb)
считает ордера отдельно по каждому символу?

В мультике да.
avatar

  34  AM2 Автор Сообщений: 15880 - Андрей

  • 20 февраля 2016, 20:07
+
0
Так же можно использовать глобальные переменные GlobalVariableSet и GlobalVariableGet
avatar

  2  Cerberus Сообщений: 11 - Cerberus

  • 11 марта 2016, 12:53
+
0
Спасибо, ваши наработки мне помогли
Редактирован: 6 марта 2020, 15:17
avatar

  2  sir Сообщений: 2

  • 4 февраля 2020, 11:10

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