AM2
Андрей

 
Уровень 35

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


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

Рейтинг 280



Пишем мультивалютный усреднитель на MQL5

Более 3-х лет я мечтал, написать на MQL5 мультивалютный усреднитель и вот сегодня моя мечта осуществилась! Торговать советник будет по всем символам, которые имеются в окне рынка. Предварительно я посмотрел на работы других авторов, но мне захотелось иметь собственную основу. Прототипом послужил мой советник «Hello» на MQL4. Сразу же после создания эксперта он нарисовал мне вот такую красивую картинку за 2 года. Как такое могло получиться сам удивляюсь! :D 



Начал я как всегда со входных переменных:


//--- входные параметры эксперта
input int      TakeProfit = 500;       // Тейкпрофит
input int      StopLoss   = 500;       // Стоплосс
input int      Step       = 10;        // Шаг между ордерами
input int      BuySell    = 1;         // 0-не торгуем 1-Buy 2-Sell
input int      AllSymbols = 1;         // 0-символ графика 1-все символы
input int      Slip       = 50;        // Проскальзывание
input double   Lot        = 0.1;       // Количество лотов для торговли 
input double   MaxLot     = 5;         // Максимальный торговый объем
input double   KLot       = 2;         // Увеличение лота
input double   Profit     = 50;        // Профит в валюте
input long     Magic      = 123;       // Магик


Функции открытия и закрытия позиций я снял со своего советника «Боллинджер на стероидах» и немного только исправил некоторые моменты.


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OpenBuy(string Symb)
  {
   double sl=0,tp=0;
// Лучшее предложение на покупку
   double Ask=SymbolInfoDouble(Symb,SYMBOL_ASK);
   if(StopLoss>0) sl=NormalizeDouble(Ask-StopLoss*_Point,_Digits);
   if(TakeProfit>0) tp=NormalizeDouble(Ask+TakeProfit*_Point,_Digits);
//--- готовим запрос 
   MqlTradeRequest request={0};
   request.action = TRADE_ACTION_DEAL;                                 // немедленное исполнение
   request.price = NormalizeDouble(Ask,_Digits);                       // последняя цена ask
   request.sl = sl;                                                    // Stop Loss
   request.tp = tp;                                                    // Take Profit
   request.symbol=Symb;                                                // символ
   request.volume = Lot;                                               // количество лотов для торговли
   request.magic = Magic;                                              // Magic Number
   request.type = ORDER_TYPE_BUY;                                      // ордер на покупку
   request.type_filling = ORDER_FILLING_FOK;                           // тип исполнения ордера - все или ничего
   request.deviation=Slip;                                             // проскальзывание от текущей цены
//--- отправим торговый приказ 
   MqlTradeResult result={0};
   if(OrderSend(request,result))
      //--- выведем в лог ответ сервера   
      Print(__FUNCTION__,":",result.comment);
   if(result.retcode==10016) Print(result.bid,result.ask,result.price);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OpenSell(string Symb)
  {
   double sl=0,tp=0;
// Лучшее предложение на продажу                           
   double Bid=SymbolInfoDouble(Symb,SYMBOL_BID);
   if(StopLoss>0) sl=NormalizeDouble(Bid+StopLoss*_Point,_Digits);
   if(TakeProfit>0) tp=NormalizeDouble(Bid-TakeProfit*_Point,_Digits);
//--- готовим запрос 
   MqlTradeRequest request={0};
   request.action = TRADE_ACTION_DEAL;                                 // немедленное исполнение
   request.price = NormalizeDouble(Bid,_Digits);                       // последняя цена bid
   request.sl = sl;                                                    // Stop Loss
   request.tp = tp;                                                    // Take Profit
   request.symbol=Symb;                                                // символ
   request.volume = Lot;                                               // количество лотов для торговли
   request.magic = Magic;                                              // Magic Number
   request.type = ORDER_TYPE_SELL;                                     // ордер на продажу
   request.deviation=Slip;                                             // проскальзывание от текущей цены
//--- отправим торговый приказ 
   MqlTradeResult result={0};
   if(OrderSend(request,result))
      //--- выведем в лог ответ сервера   
      Print(__FUNCTION__,":",result.comment);
   if(result.retcode==10016) Print(result.bid,result.ask,result.price);
  }
//+------------------------------------------------------------------+
//| Закрытие длинной позиции                                         |
//+------------------------------------------------------------------+
void CloseBuy(string Symb)
  {
   double Bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);    // лучшее предложение на продажу

   if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
     {
      //--- готовим запрос 
      MqlTradeRequest request={0};
      request.action = TRADE_ACTION_DEAL;               // немедленное исполнение
      request.price = NormalizeDouble(Bid,_Digits);     // последняя цена Bid
      request.sl = 0;                                   // Stop Loss
      request.tp = 0;                                   // Take Profit
      request.symbol = Symb;                            // символ
      request.volume = PositionGetDouble(POSITION_VOLUME);// количество лотов для торговли
      request.magic = Magic;                            // Magic Number
      request.type= ORDER_TYPE_SELL;                    // ордер на продажу
      request.type_filling = ORDER_FILLING_FOK;         // тип исполнения ордера - все или ничего
      request.deviation=Slip;                           // проскальзывание от текущей цены         
      //--- отправим торговый приказ 
      MqlTradeResult result={0};
      if(OrderSend(request,result))
         //--- выведем в лог ответ сервера   
         Print(__FUNCTION__,":",result.comment);
      if(result.retcode==10016) Print(result.bid,result.ask,result.price);
     }
  }
//+------------------------------------------------------------------+
//| Закрытие короткой позиции                                        |
//+------------------------------------------------------------------+
void CloseSell(string Symb)
  {
   double Ask = SymbolInfoDouble(Symb,SYMBOL_ASK);     // лучшее предложение на покупку

   if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
     {
      //--- готовим запрос 
      MqlTradeRequest request={0};     
      request.action = TRADE_ACTION_DEAL;                // немедленное исполнение
      request.price = NormalizeDouble(Ask,_Digits);      // последняя цена ask
      request.sl = 0;                                    // Stop Loss
      request.tp = 0;                                    // Take Profit
      request.symbol = Symb;                             // символ
      request.volume = PositionGetDouble(POSITION_VOLUME); // количество лотов для торговли
      request.magic = Magic;                             // Magic Number
      request.type = ORDER_TYPE_BUY;                     // ордер на покупку
      request.type_filling = ORDER_FILLING_FOK;          // тип исполнения ордера - все или ничего
      request.deviation=5;                               // проскальзывание от текущей цены         
      //--- отправим торговый приказ 
      MqlTradeResult result={0};
      if(OrderSend(request,result))
         //--- выведем в лог ответ сервера   
         Print(__FUNCTION__,":",result.comment);
      if(result.retcode==10016) Print(result.bid,result.ask,result.price);
     }
  } 
//+------------------------------------------------------------------+


В функции открытия позиций,

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OpenPos()
  {
   for(int i=SymbolsTotal(true)-1;i>=0;i--)
     {
      string Symb=SymbolName(i,true);
      if(CountTrades(Symb)<1 && BuySell==1)
        {
         //--- Открываем ордер на покупку
         OpenBuy(Symb);
        }
      //--- Sell
      if(CountTrades(Symb)<1 && BuySell==2)
        {
         //--- Открываем ордер на продажу
         OpenSell(Symb);
        }
     }
  }
//+------------------------------------------------------------------+


сначала получаем количество символов в окне рынка

SymbolsTotal(true)

затем пробегаемся по всем символам и если нет открытой позы по инструменту,

CountTrades(Symb)<1

открываем ордер.


    //--- Открываем ордер на покупку
    OpenBuy(Symb);


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

Функция на MQL4:


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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()==OP_BUY || OrderType()==OP_SELL)
               count++;
           }
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+


Функция на MQL5:


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CountTrades(string Symb)
  {
   int count=0;
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         if(PositionGetInteger(POSITION_MAGIC)==Magic)
           {
            if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY || PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) count++;
           }
        }
     }
   return(count);
  }
//+------------------------------------------------------------------+


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


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double SymbProfit(string Symb)
  {
   double pr=0;
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         if(PositionGetInteger(POSITION_MAGIC)==Magic)
           {
            pr=+PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP);
           }
        }
     }
   return(pr);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseAll(string Symb)
  {
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         if(PositionGetInteger(POSITION_MAGIC)==Magic)
           {
            if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)  CloseBuy(Symb);
            if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) CloseSell(Symb);;
           }
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
long FindOrderType(string Symb)
  {
   long oticket,ticketNumber=0,type=0;
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         if(PositionGetInteger(POSITION_MAGIC)==Magic)
           {
            oticket=PositionGetInteger(POSITION_IDENTIFIER);
            if(oticket>ticketNumber)
              {
               ticketNumber=oticket;
               type=PositionGetInteger(POSITION_TYPE);
              }
           }
        }
     }
   return(type);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double FindLastBuyPrice(string Symb)
  {
   long oticket,ticketNumber=0;
   double oprice=0;
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         if(PositionGetInteger(POSITION_MAGIC)==Magic)
           {
            if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
              {
               oticket=PositionGetInteger(POSITION_IDENTIFIER);
               if(oticket>ticketNumber)
                 {
                  ticketNumber=oticket;
                  oprice=PositionGetDouble(POSITION_PRICE_OPEN);
                 }
              }
           }
        }
     }
   return(oprice);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double FindLastSellPrice(string Symb)
  {
   long oticket,ticketNumber=0;
   double oprice=0;
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         if(PositionGetInteger(POSITION_MAGIC)==Magic)
           {
            if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
              {
               oticket=PositionGetInteger(POSITION_IDENTIFIER);
               if(oticket>ticketNumber)
                 {
                  ticketNumber=oticket;
                  oprice=PositionGetDouble(POSITION_PRICE_OPEN);
                 }
              }
           }
        }
     }
   return(oprice);
  }
//+------------------------------------------------------------------+


В процессе написания эксперта я выводил необходимые функции в коммент, чтобы удостовериться в работоспособности функции.


   Comment("\n Pos: ",CountTrades("GBPUSD"),
           "\n Type: ",FindOrderType("GBPUSD"),
           "\n Price: ",FindLastSellPrice("GBPUSD"),
           "\n Profit: ",SymbProfit("GBPUSD"),
           "\n Symb1: ",SymbolName(0,true),
           "\n Symb2: ",SymbolName(1,true),
           "\n Symbols: ",SymbolsTotal(true));


Функция открытия усредняющих позиций была также написана по образцу с MQL4.

Функция на MQL4:


   if(CountTrades()>0 && CountTrades()<=MaxTrades)
     {
      int otype=FindOrderType();

      if(otype==OP_BUY)
        {
         price=FindLastBuyPrice();
         if((price-Ask)/Point>=Step)
           {
            ticket=OrderSend(Symbol(),OP_BUY,Lot(),Ask,Slip,0,0,"Buy Order",Magic,0,Blue);
            ModifyOrders();
           }
        }

      else if(otype==OP_SELL)
        {
         price=FindLastSellPrice();
         if((Bid-price)/Point>=Step)
           {
            ticket=OrderSend(Symbol(),OP_SELL,Lot(),Ask,Slip,0,0,"Sell Order",Magic,0,Red);
            ModifyOrders();
           }
        }
     }



Функция на MQL5:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OpenLastPos()
  {
   for(int i=SymbolsTotal(true)-1;i>=0;i--)
     {
      string Symb=SymbolName(i,true);
      // Лучшее предложение на покупку
      double Ask=SymbolInfoDouble(Symb,SYMBOL_ASK);
      // Лучшее предложение на продажу                           
      double Bid=SymbolInfoDouble(Symb,SYMBOL_BID);
      
      if(CountTrades(Symb)>0)
        {
         long otype=FindOrderType(Symb);

         if(otype==0)
           {
            price=FindLastBuyPrice(Symb);
            if((price-Ask)/_Point>=Step)
              {
               OpenBuy(Symb);
              }
           }

         else if(otype==1)
           {
            price=FindLastSellPrice(Symb);
            if((Bid-price)/_Point>=Step)
              {
               OpenSell(Symb);
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+


Закрытие позиций по символам когда превышен определенный уровень профита, у меня стоит только для одного символа. Как сделать по всем будет для вас домашним заданием :D 


   if(SymbProfit(_Symbol)>Profit) CloseAll(_Symbol);


Советник уже стоит у меня на демо и тестируется со следующими настройками.



П.С. Советник написан как пример разработки стратегии усреднения позиций, скачать можно по ссылке: www.opentraders.ru/downloads/945/
  • +1
  • Просмотров: 18210
  • 25 ноября 2015, 09:27
  • AM2
Понравилcя материал? Не забудьте поставить плюс и поделиться в социальной сети!

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

Брокер для ваших роботов, 15 лет на рынке

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


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