Перейти к содержанию

Обучение языку MQL4 под MetaTrader 4


Рекомендуемые сообщения

Обучение языку MQL4 под MetaTrader 4 Опубликовано
4 часа назад, Stranger80 сказал:

double NormaliseDouble(double Lots, int 2);
Компилятор ругается

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

   double Lots = 0.1;
   double ND = NormalizeDouble(Lots,2);

Вначале объявлен лот, который вам нужен. Можно и не объявлять, если он уже есть из какого то ордера.

Потом объявляется переменная ND, которая уже округляет дробное число. 
Можно сделать и так:
 

   double Lots = 0.1;
   Lots = NormalizeDouble(Lots,2);

 

  • Лайк 2
Ссылка на сообщение
Поделиться на другие сайты

  • Ответов 6,8k
  • Создано
  • Последний ответ

Популярные авторы

Популярные авторы

Популярные посты

Смотрим видео-уроки, изучаем MQL:       Скачать видеокурс «MQL программирование. Как самому написать форекс советник/ индикатор/ скрипт»   P.S. Тема про Обучение MQ

Перейти

Циклы цикл for Иногда необходимо повторять одно и то же действие несколько раз подряд. Для этого используют циклы. К примеру, мы хотим проанализировать последние 10 баров и выяснить наименьшую цен

Перейти

Речь идет о том, что не будет значимых нововведений. А только баги периодически будут править. А вот все новое мол - в МТ5. Когда они вживую сказали то же самое на конференции в Москве, я уточнил: "То

Перейти
Обучение языку MQL4 под MetaTrader 4 Опубликовано
22 часа назад, Rever27 сказал:

     double Lots =( Free / D);   
     Lots =  NormaliseDouble( Lots, 2);  

объявил функцию: 

39 double NormaliseDouble();

получил:

74     double Lots =( Free / D);   
75    Lots =  NormaliseDouble( Lots, 2); 

80 MA_1 = NormaliseDouble( MA_1, Digits);0
81 MA_2 = NormaliseDouble(MA_2, Digits);

 

'NormaliseDouble' - wrong parameters count    Test!.mq4    74    14
'NormaliseDouble' - wrong parameters count    Test!.mq4    79    8
'NormaliseDouble' - wrong parameters count    Test!.mq4    80    8


Когда объявлял 

38 double NormaliseDouble(double MA_1,int Digits);
39 double NormaliseDouble(double MA_2,int Digits);
40 double NormaliseDouble(double Lots,int 2);

получал только 

1 errors, 0 warnings        2    1

'2' - comma expected    Test!.mq4    40    40
при этом строки 75, 80 и81 возражений не вызывали.

Решил, что от номалзции объёма можно отказаться и вычеркнул строку 40

после чег компилятор сказал:

1 errors, 0 warnings        2    1
'NormaliseDouble' - function must have a body    Test!.mq4    38    8

Но там тело функции есть. После вычёркивании 38-й требовал тело 39-й,а посл удаления и её

сообщил,  3 ошибки что в 74, 79 и 80 функция NormaliseDouble 

'NormaliseDouble' - function not defined    Test!.mq4    75    14

Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
36 минут назад, Stranger80 сказал:
Спойлер

объявил функцию: 

39 double NormaliseDouble();

получил:

74     double Lots =( Free / D);   
75    Lots =  NormaliseDouble( Lots, 2); 

80 MA_1 = NormaliseDouble( MA_1, Digits);0
81 MA_2 = NormaliseDouble(MA_2, Digits);

 

'NormaliseDouble' - wrong parameters count    Test!.mq4    74    14
'NormaliseDouble' - wrong parameters count    Test!.mq4    79    8
'NormaliseDouble' - wrong parameters count    Test!.mq4    80    8


Когда объявлял 

38 double NormaliseDouble(double MA_1,int Digits);
39 double NormaliseDouble(double MA_2,int Digits);
40 double NormaliseDouble(double Lots,int 2);

получал только 

1 errors, 0 warnings        2    1

'2' - comma expected    Test!.mq4    40    40
при этом строки 75, 80 и81 возражений не вызывали.

Решил, что от номалзции объёма можно отказаться и вычеркнул строку 40

после чег компилятор сказал:

1 errors, 0 warnings        2    1
'NormaliseDouble' - function must have a body    Test!.mq4    38    8

Но там тело функции есть. После вычёркивании 38-й требовал тело 39-й,а посл удаления и её

сообщил,  3 ошибки что в 74, 79 и 80 функция NormaliseDouble 

'NormaliseDouble' - function not defined    Test!.mq4    75    14
 

 


 

 

Посмотрите внимательно на синтаксис, не NormaliseDouble, а NormalizeDouble

Пример:

double Lots, MA_1, MA_2;

Lots = NormalizeDouble((Free / D), 2);
MA_1 = NormalizeDouble(MA_1, _Digits);
MA_2 = NormalizeDouble(MA_2, _Digits);

Соответственно переменные Free и D должны также быть объявлены и определены.

 

  • Лайк 2
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано

Здравствуйте, изучаю mql4, возник вопрос: почему в enum нульзя явно указать строку, допустим вот так:

 

enum MODE_ENUM
  {
    All_symbols="", //All symbols
    Current_symbol="0", //Current symbol
  };


 

Компилятор ругается:
'=' - constant expression is not integral
 

 

Приходится вот так изворачиваться:

 

enum MODE_ENUM
  {
    All_symbols, //All symbols
    Current_symbol, //Current symbol
  };

и далее:

  string   Symb;

  switch(Mode)
  {
    case All_symbols:
    Symb="";
    break;
    case Current_symbol:
    break;
    Symb="0";
  }

Как правильнее реализовать мою идею без этого костыля?

Изменено пользователем Aestral
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
2 часа назад, Aestral сказал:

почему в enum нульзя явно указать строку, допустим вот так:

Потому что енум это перечисление, и может быть больше целым чистом типа int. Строковые и другие типа данных сюда не подходят.

2 часа назад, Aestral сказал:

Как правильнее реализовать мою идею без этого костыля?

Это не костыль, а корректный вариант назначения стринговой переменной в зависимости от значения енум. Можно этот записать короче:

enum MODE_ENUM
  {
   All_symbols = 0, //All symbols
   Current_symbol = 1, //Current symbol
  };
  
string Symb=(Mode == All_symbols ? "" : "0");

 

Изменено пользователем Rever27
  • Лайк 2
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано

Еще один вопрос на засыпку: 

 

Делаю панельку с помощью класса CPanel, которая выводит на график историю сделок.

 

2020-07-28_19-37-04.png.426b83d03207cf14d58e3d1e5ad5fac3.png

 

Как заставить панель быть поверх созданных объектов на графике (истории ордеров)?

 

 

Вариант с 

ObjectSet(...,OBJPROP_BACK,true);

не подходит, так как нужно чтоб объекты были поверх графика, но не поверх панели. 

Изменено пользователем Aestral
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
1 час назад, Aestral сказал:

Как заставить панель быть поверх созданных объектов на графике (истории ордеров)?

Автор панели на форуме MQL ответил лаконично - никак. Чтобы панель была поверх объектов, созданных после нее - нужно свернуть и развернуть ее.

 

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

 

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

int _ObjectsTotal = 0;

void OnTick() {
   if(ObjectsTotal() != _ObjectsTotal) {
      _ObjectsTotal = ObjectsTotal();
      TradePanel.Destroy(5);
      TradePanel.Create(ChartID(),ea_name,0,7,20,205,354);
      TradePanel.Run(); 
   }
} 

 

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

  • Лайк 1
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
17 часов назад, Rever27 сказал:

Чтобы панель была поверх объектов, созданных после нее - нужно свернуть и развернуть ее.

У панели в заголовке есть соответствующие кнопочки. @Aestral проверьте после восстановления панели она сверху будет или нет? если Ок, то к кнопочкам привязаны соответствующие функции, которые можно вставить в код @Rever27 и всё.

Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано

 extern int StopLoss = 20;
 extern int TakeProfit = 20;
      
void OnTick()
  {
   double OpenPrice1 = Ask+5*Point;
   double BuyStopLoss = OpenPrice1 - (StopLoss * Point);
   double TakeProfitBuy = OpenPrice1 + (TakeProfit * Point);
   double OpenPrice2 = Bid-5*Point;
   double SellStopLoss = OpenPrice2 + (StopLoss * Point);
   double TakeProfitSell = OpenPrice2 - (TakeProfit * Point);
   //int buyOchil;
   
   if (OrdersTotal() == 0)
   {
   int buyOchil = OrderSend(Symbol(), OP_BUYSTOP, 1, OpenPrice1, 3, BuyStopLoss, TakeProfitBuy);
     bool resb = OrderSelect(buyOchil, SELECT_BY_TICKET);
      double r=OrderOpenPrice();
   
   int sellOchil = OrderSend(Symbol(), OP_SELLSTOP, 1, OpenPrice2, 3, SellStopLoss, TakeProfitSell);
     bool ress = OrderSelect(sellOchil, SELECT_BY_TICKET);
      double r2=OrderOpenPrice();
      
      double k = r-10*Point;
      double l = r2+10*Point;
        
    if (Ask == k)
       {
         int sellOchil2 = OrderSend(Symbol(), OP_BUYSTOP, 2, Ask+10*Point, 3, NULL, NULL);
         Alert("1 ishladi");
       }
        if (Bid == l)
       {
         int buyOchil2 = OrderSend(Symbol(), OP_SELLSTOP, 2, Bid-10*Point, 3, NULL, NULL);
         Alert("2 ishladi");
       }
            
   }
       
                
  }

if не работает 

Что мой ошибка!!! Помогите!!! 

Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
8 часов назад, Элёр сказал:

if не работает 

Вещественные числа сравнивать точно == не рекомендуется- где гарантия, что до 16(?) знака у Вас будет совпадение.
Проверяйте через if(Ask >= k)  (или <=   - как по логике).
п.с. Не уверен, но может NormalizeDouble(k,_Digits) поможет

Изменено пользователем usver73
  • Лайк 1
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано

@Элёр достижение ценой некого расчётного уровня нужно делать в 2 шага: 1. сохраняем Ask, 2. на следующем тике сравниваем if ( Ask1 < k && Ask2 >= k ) .....

Это гарантированно работает

  • Лайк 2
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
В 17.07.2020 в 16:43, diodio сказал:

Ну у меня почти тоже самое написано, только немного по-другому, вопрос в том почему в журнале такие числа? На каждом тике считает?

Потому, что:

1. Вы не обнуляете профит перед началом цикла. Между тиками накопленное значение сохраняется, а потом на следующем тике вы в него еще насыпаете тех же ордеров в цикле.

2. Вывод в консоль внутри цикла. Это уже не очень существенно, но все же неправильно. Скажем, если забыть о первой проблеме и считать в цикле три ордера с профитом по доллару, в консоли вы увидите профит 1, профит 2, профит 3

  • Лайк 1
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
В 21.07.2020 в 02:36, Stranger80 сказал:

Не могу найти ответ. Что делать? И уже не могу вспомнить как задать вопрос.

Отсыпь и мне немного

  • Лол 1
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
В 27.07.2020 в 21:28, Rever27 сказал:

Потому что енум это перечисление, и может быть больше целым чистом типа int. Строковые и другие типа данных сюда не подходят.

Это не костыль, а корректный вариант назначения стринговой переменной в зависимости от значения енум. Можно этот записать короче:


enum MODE_ENUM
  {
   All_symbols = 0, //All symbols
   Current_symbol = 1, //Current symbol
  };
  
string Symb=(Mode == All_symbols ? "" : "0");

 

Еще лучше потом объявить массив строк и обращаться к его значениям по элементам енумерации:

enum MY_ENUM {
	ZERO = 0, //that's zero
	ONE,	//and one
	TWO		//and two
};

string myEnumStr[] = {"String for zero", "String for one", "String for two"};

.....
void PrintInfo(MY_ENUM _e) {
Print("Element ", EnumToString(_e), " number ", int(_e), " is associated with a string '", myEnumStr[_e], "'");
}

А можно и не строк. Очень удобный механизм разделения логики

  • Лайк 2
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
В 02.08.2020 в 04:32, 0ll сказал:

@Элёр достижение ценой некого расчётного уровня нужно делать в 2 шага: 1. сохраняем Ask, 2. на следующем тике сравниваем if ( Ask1 < k && Ask2 >= k ) .....

Это гарантированно работает

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

if(MathAbs(a - b) < DBL_EPSILON)
  these two are equal
if(MathAbs(price1 - price2) < Point())
  the price is the same

Как-то так

  • Лайк 1
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
23 часа назад, Rigal сказал:

ну и в целом сравнение двух чисел с плавающей точкой принято делать через величину их разницы

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

Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано

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

Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано

Любые глобальные переменные. В OnInit не инициализировать, а сразу при объявлении. Тогда не будет сбрасываться при переключении таймфрейма/переинициализации.

Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
1 час назад, machine сказал:

Любые глобальные переменные. В OnInit не инициализировать, а сразу при объявлении. Тогда не будет сбрасываться при переключении таймфрейма/переинициализации.

int init()
  {
  int      HistTotalBuy = 0;
   return(0);
  }

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

Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано

Всем привет! Объявил статический массив для подсчёта ордеров:

int      arrCountOrders[50];

Теперь чтоб в цикле подсчитать ордера я пишу так:

void CountOrder()
  {
   ArrayInitialize(arrCountOrders,0); 

   for(int x=OrdersTotal()-1; x>=0; x--)
     {
      if(OrderSelect(x, SELECT_BY_POS, MODE_TRADES)==false)
         continue;
      if(OrderSymbol()!=Symbol() || OrderMagicNumber() != Magic)
         continue;
      arrCountOrders[OrderType()]++;
     }
   return;
  }

или же чтоб его правильно заполнить, необходимо указать на массив путем ссылки?

void CountOrder(int &arrCountOrders[50])
  {
   ArrayInitialize(arrCountOrders,0); 

   for(int x=OrdersTotal()-1; x>=0; x--)
     {
      if(OrderSelect(x, SELECT_BY_POS, MODE_TRADES)==false)
         continue;
      if(OrderSymbol()!=Symbol() || OrderMagicNumber() != Magic)
         continue;
      arrCountOrders[OrderType()]++;
     }
   return;
  }

Какой вариант будет правильным?

Изменено пользователем diodio
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
2 часа назад, diodio сказал:

Какой вариант будет правильным?

Зачем для того, чтобы просто узнать сколько ордеров по этой паре у этого советника объявлять массив?
Просто можно сделать так:
 

void OnStart()
  {

   count_buy = CountOrder(OP_BUY); 
   count_sell = CountOrder(OP_SELL);
   
  }
//+------------------------------------------------------------------+
int CountOrder(int Order_Type) {
   int orders=0;
   for(int i=OrdersTotal()-1;i>=0;i--){
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)==false) continue;
      if(OrderSymbol()!=_Symbol || OrderMagicNumber() != MagicNumber) continue;
      
      if(Order_Type == OrderType() || Order_Type == -1) orders++;
   }
   return orders;
}

В итоге можно знать отдельно сколько ордеров на покупку, а сколько на продажу. Либо же если вызвать функцию так 

 count = CountOrder(-1); 

То будет суммарный подсчет всех ордеров сразу.

 

Если же нужно в массив записывать типы ордеров, то правильнее сделать так:
 

void CountOrder()
  {
   ArrayInitialize(arrCountOrders,0); 
   int i = 0;
   for(int x=OrdersTotal()-1; x>=0; x--)
     {
      if(OrderSelect(x, SELECT_BY_POS, MODE_TRADES)==false)
         continue;
      if(OrderSymbol()!=Symbol() || OrderMagicNumber() != Magic)
         continue;
      arrCountOrders[i] = OrderType();
      i++;
     }
   return;
  }

Но в сумме это тоже не совсем корректно, потому что ордеров может быть больше 50, а массив является статическим. Лучше уж тогда его сделать динамическим, если для этой задачи он вообще нужен.

Лиииибо, если все же нужен массив и нужно знать значение всех типов ордеров, то можно сделать так:
 

void OnStart()
  {

   int arrCountOrders[6];
   CountOrder(arrCountOrders);
   Print("BUY: ",arrCountOrders[OP_BUY]);
   Print("SELL: ", arrCountOrders[OP_SELL]);
   Print("BUYLIMIT: ", arrCountOrders[OP_BUYLIMIT]);
   Print("BUYSTOP: ", arrCountOrders[OP_BUYSTOP]);
   Print("SELLLIMIT: ", arrCountOrders[OP_SELLLIMIT]);
   Print("SELLSTOP: ", arrCountOrders[OP_SELLSTOP]);
   
  }
//+------------------------------------------------------------------+
void CountOrder(int &arrCountOrders[6])
{
   ArrayInitialize(arrCountOrders,0); 

   for(int x=OrdersTotal()-1; x>=0; x--)
     {
      if(OrderSelect(x, SELECT_BY_POS, MODE_TRADES)==false)
         continue;
      if(OrderSymbol()!=Symbol() || OrderMagicNumber() != Magic)
         continue;
      if(OrderType() > 5) continue;      
      arrCountOrders[OrderType()]++;
     }
   return;
}

 

Изменено пользователем Rever27
  • Лайк 2
Ссылка на сообщение
Поделиться на другие сайты

Обучение языку MQL4 под MetaTrader 4 Опубликовано
4 часа назад, diodio сказал:

Всем привет! Объявил статический массив для подсчёта ордеров:


int      arrCountOrders[50];

Теперь чтоб в цикле подсчитать ордера я пишу так:

Исказил всю идею :)
Размерность массива определяется количеством типов ордеров, т.е. 6
 

 

4 часа назад, diodio сказал:

или же чтоб его правильно заполнить, необходимо указать на массив путем ссылки?

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

  • Лайк 1
Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Специальное предложение


  • Рекомендуемые брокеры

  • ×
    ×
    • Создать...