AM2
Андрей

 
Уровень 34

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


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

Рейтинг 280



Хитрый усреднитель на MQL5

Язык программирования MQL5 и сама платформа МТ5, как показывает опыт программирования в «Столе заказов MQL» не очень популярны среди основной массы трейдеров. Заказов на MQL5 единицы. Для того чтобы хоть немного популяризировать MQL5 у местной общественности, я попытался создать простейший усреднитель с минимальным количеством кода и уложился в 100 строк. Алгоритм усреднения, используемый в советнике, также заслуживает внимания.

Торговая стратегия:

Эксперт торгует в направлении заданном в настройках BuySell. Закрывает позицию при достижении профита Profit или убытка Loss в валюте депозита. Если после открытия позиции цена пошла не в нашу сторону, советник открывает усредняющий ордер постоянным объемом Lot, через указанное расстояние в пунктах Step. Когда эксперт набрал позиций объемом BigLot, начальный лот увеличивается на коэффициент Mnogitel. Таким образом открывая очередной усредняющий ордер с повышенным объемом, мы увеличиваем шансы позиции закрыться в прибыль. Все операции эксперт совершает на открытии свечи.


Рис.1. Сделки эксперта на графике. EURUSD, H1.


Рис.2. Результат торговли и оптимизации эксперта с 11.01.2013 по 12.09.2016. EURUSD, H1.

Настройки эксперта:


input int BuySell     =    1; // 1-Only Buy 2-Only Sell
input int Step        = 1000; // Step
input double Lot      = 0.1;  // Volume
input double BigLot   = 1;    // Big Lot
input double MaxLots  = 5;    // Maximum lot
input double Profit   = 60;   // Dollars Profit 
input double Loss     = 5100; // Dollars Loss
input double Mnogitel = 12;   // Lots Mnogitel 



Теперь разберем код эксперта:

Чтобы облегчить создание торговых функций будем пользоваться классом CTrade из стандартной библиотеки MT5:


#include <Trade\Trade.mqh>             
CTrade trade;


Далее нам понадобятся всего 2 дополнительные функции SymbProfit и Lots.

Функция SymbProfit вычисляет прибыль по открытой позиции:

//+------------------------------------------------------------------+
//|  Position Profit                                                 |
//+------------------------------------------------------------------+
double SymbProfit(string Symb)
  {
   double p=0;
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         p=+PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP);
        }
     }
   return(p);
  }


Функция Lots считает объем открытой позиции:


//+------------------------------------------------------------------+
//|  Position Volume                                                 |
//+------------------------------------------------------------------+
double Lots(string Symb)
  {
   double lots=0;

   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         if(PositionGetInteger(POSITION_TYPE)<2)
           {
            lots=PositionGetDouble(POSITION_VOLUME);
           }
        }
     }
   return(lots);
  }


Цены аск и бид в MQL5 получаем отдельно:


   string symb=Symbol();
   double Ask=SymbolInfoDouble(symb,SYMBOL_ASK);
   double Bid=SymbolInfoDouble(symb,SYMBOL_BID);


Торговать будем на новом баре:


   if(bars!=Bars(symb,0))
     {
       ...
      bars=Bars(symb,0);
     }


И запишем условия для покупок и продаж:


      if(BuySell==1 && (PositionsTotal()<1 || (PositionsTotal()>0 && (pr-Ask)/_Point>=Step))) {trade.PositionOpen(symb,0,lot,Ask,0,0); pr=Bid;}//buy
      if(BuySell==2 && (PositionsTotal()<1 || (PositionsTotal()>0 && (Bid-pr)/_Point>=Step))) {trade.PositionOpen(symb,1,lot,Bid,0,0); pr=Bid;}//sell



За увеличение лота будет отвечать следующий код:


      if(Lots(symb)>=BigLot) lot=lot*Mnogitel;
      if(lot>MaxLots) lot=Lot;



Позицию мы будем закрывать следующим образом:


      if(SymbProfit(symb)>Profit || SymbProfit(symb)<-Loss) {trade.PositionClose(symb); lot=Lot;}


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


      if(BuySell==1 && (PositionsTotal()<1 || (PositionsTotal()>0 && (pr-Ask)/_Point>=Step))) {... pr=Bid;}//buy
      if(BuySell==2 && (PositionsTotal()<1 || (PositionsTotal()>0 && (Bid-pr)/_Point>=Step))) {... pr=Bid;}//sell


Вывод информации на экран:


   Comment("\n Lots: ",Lots(symb),
           "\n Profit: ",SymbProfit(symb),
           "\n Price: ",pr);


После закрытия позиции лот становится первоначальным:


if(SymbProfit(symb)>Profit || SymbProfit(symb)<-Loss) {... lot=Lot;}


Вот и весь советник:


//+------------------------------------------------------------------+
//|                                                   HelloSmart.mq5 |
//|                                              Copyright 2016, AM2 | 
//|                                     https://www.forexsystems.biz | 
//+------------------------------------------------------------------+ 
#property copyright "Copyright 2016, AM2" 
#property link "https://www.forexsystems.biz" 
#property version "1.00" 

#include <Trade\Trade.mqh>             
CTrade trade;

input int BuySell     =    1; // 1-Only Buy 2-Only Sell
input int Step        = 1000; // Step
input double Lot      = 0.1;  // Volume
input double BigLot   = 1;    // Big Lot
input double MaxLots  = 5;    // Maximum lot
input double Profit   = 60;   // Dollars Profit 
input double Loss     = 5100; // Dollars Loss
input double Mnogitel = 12;   // Lots Mnogitel 

int bars=0;
double lot=Lot,pr=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//|  Position Profit                                                 |
//+------------------------------------------------------------------+
double SymbProfit(string Symb)
  {
   double p=0;
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         p=+PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP);
        }
     }
   return(p);
  }
//+------------------------------------------------------------------+
//|  Position Volume                                                 |
//+------------------------------------------------------------------+
double Lots(string Symb)
  {
   double lots=0;

   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(PositionGetSymbol(i)==Symb)
        {
         if(PositionGetInteger(POSITION_TYPE)<2)
           {
            lots=PositionGetDouble(POSITION_VOLUME);
           }
        }
     }
   return(lots);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   string symb=Symbol();
   double Ask=SymbolInfoDouble(symb,SYMBOL_ASK);
   double Bid=SymbolInfoDouble(symb,SYMBOL_BID);

   if(bars!=Bars(symb,0))
     {
      if(BuySell==1 && (PositionsTotal()<1 || (PositionsTotal()>0 && (pr-Ask)/_Point>=Step))) {trade.PositionOpen(symb,0,lot,Ask,0,0); pr=Bid;}//buy
      if(BuySell==2 && (PositionsTotal()<1 || (PositionsTotal()>0 && (Bid-pr)/_Point>=Step))) {trade.PositionOpen(symb,1,lot,Bid,0,0); pr=Bid;}//sell

      if(Lots(symb)>=BigLot) lot=lot*Mnogitel;
      if(lot>MaxLots) lot=Lot;

      if(SymbProfit(symb)>Profit || SymbProfit(symb)<-Loss) {trade.PositionClose(symb); lot=Lot;}
      bars=Bars(symb,0);
     }

   Comment("\n Lots: ",Lots(symb),
           "\n Profit: ",SymbProfit(symb),
           "\n Price: ",pr);
  }
//+------------------------------------------------------------------+



Как вы только что могли убедиться в программировании на MQL5 нет ничего сложного и даже такие вещи как усреднители пишутся довольно таки быстро. Свойства позиции мы могли получить с помощью класса CPositionInfo таким образом можно еще сократить размер кода.

Скачать советник вы можете по ссылке: www.opentraders.ru/downloads/1315/
  • +5
  • Просмотров: 12493
  • 13 сентября 2016, 10:55
  • AM2
Понравилcя материал? Не забудьте поставить плюс и поделиться в социальной сети!

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

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

+
0
С CPositionInfo:


//+------------------------------------------------------------------+
//|                                                   HelloSmart.mq5 |
//|                                              Copyright 2016, AM2 | 
//|                                     https://www.forexsystems.biz | 
//+------------------------------------------------------------------+ 
#property copyright "Copyright 2016, AM2" 
#property link "https://www.forexsystems.biz" 
#property version "1.00" 

#include <Trade\Trade.mqh> 
#include <Trade\PositionInfo.mqh>   

CTrade trade;
CPositionInfo pos;

input int BuySell     = 2;    // 1-Only Buy 2-Only Sell
input int Step        = 1000; // Step
input double Lot      = 0.1;  // Volume
input double BigLot   = 1;    // Big Lot
input double MaxLots  = 5;    // Maximum lot
input double Profit   = 60;   // Dollars Profit 
input double Loss     = 5100; // Dollars Loss
input double Mnogitel = 3;    // Lots Mnogitel 

int bars=0;
double lot=Lot,pr=0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//|  Position Profit                                                 |
//+------------------------------------------------------------------+
double SymbProfit(string Symb)
  {
   double p=0;
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(pos.Select(Symb))
        {
         p+=pos.Profit();
        }
     }
   return(p);
  }
//+------------------------------------------------------------------+
//|  Position Volume                                                 |
//+------------------------------------------------------------------+
double Lots(string Symb)
  {
   double lots=0;

   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(pos.Select(Symb))
        {
         lots+=pos.Volume();
        }
     }
   return(lots);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseAll(string symb)
  {
   for(int i=PositionsTotal()-1;i>=0;i--)
     {
      if(pos.Select(symb))
        {
         trade.PositionClose(symb);
        }
     }
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   string symb=Symbol();
   double Ask=SymbolInfoDouble(symb,SYMBOL_ASK);
   double Bid=SymbolInfoDouble(symb,SYMBOL_BID);

   if(bars!=Bars(symb,0))
     {
      if(BuySell==1 && (PositionsTotal()<1 || (PositionsTotal()>0 && (pr-Ask)/_Point>=Step))) {trade.PositionOpen(symb,0,lot,Ask,0,0); pr=Bid;}//buy
      if(BuySell==2 && (PositionsTotal()<1 || (PositionsTotal()>0 && (Bid-pr)/_Point>=Step))) {trade.PositionOpen(symb,1,lot,Bid,0,0); pr=Bid;}//sell

      if(Lots(symb)>=BigLot) lot=lot*Mnogitel;
      if(lot>MaxLots) lot=Lot;

      if(SymbProfit(symb)>Profit || SymbProfit(symb)<-Loss) {CloseAll(symb); lot=Lot;}
      bars=Bars(symb,0);
     }

   Comment("\n Lots: ",Lots(symb),
           "\n Profit: ",SymbProfit(symb),
           "\n Price: ",pr);
  }
//+------------------------------------------------------------------+

avatar

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

  • 13 сентября 2016, 15:33
+
0
Доброго дня! А сделки открытые вручную подхватывать и усреднять будет?
avatar

  12  sorusm Сообщений: 181 - sorusm

  • 29 мая 2018, 09:14
+
0
А уровни стоп лосс и тейк профит виртуальные или выставляются?
avatar

  12  sorusm Сообщений: 181 - sorusm

  • 24 ноября 2017, 09:52
+
0
«За увеличение лота будет отвечать следующий код:if(Lots(symb)>=BigLot) lot=lot*Mnogitel; ...»
Никак не могу понять, почему «больше или равно», если по логике должно быть «меньше или равно». Lots(symb)-это количество открытых позиций по конкретному символу?
Если меняю знак >= на <=, компилирую, на графике советник торгует, вроде бы нормально, а вот в тестере не появляется ни одной сделки. В чём может быть причина?
avatar

  7  s22aa Сообщений: 25 - Александр

  • 5 марта 2018, 21:26
+
0
Опечатка:

if(lot>MaxLots) lot=Lot;
меняем на
if(lot>MaxLots) lot=MaxLots;


Редактирован: 18 апреля 2022, 13:25
avatar

  7  kvashnin007 Сообщений: 525 - Андрей

  • 18 апреля 2022, 13:24
+
0
Извините не заметил большую букву в Lot.
Хотя можно попробовать и предлагаемый мной вариант.

Правда, хитрости в усреднении большой не обнаружено.
Можно гораздо хитрее.
Редактирован: 18 апреля 2022, 13:33
avatar

  7  kvashnin007 Сообщений: 525 - Андрей

  • 18 апреля 2022, 13:29
+
0
Если параметр BuySell = 2, то торгует только в селл;

если параметр BuySell = 1, то вообще сделок не открывает ни на бай ни на селл.

Но не у всех в Альпари и на Робофорексе работает.
Редактирован: 19 мая 2022, 13:43
avatar

  19  alex30774 Сообщений: 715

  • 19 мая 2022, 13:14
+
+1
Здравствуйте. А можно доработать данный усреднитель и сделать, чтобы он подхватывал и усреднял сделки по магику другого советника или открытые вручную по выбору?
avatar

  4  Ali-k Сообщений: 15

  • 2 июня 2022, 17:28

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