Изучаем язык программирования MQL4

AlexeyVik

Программист mql4 mql5
Я спорил с тем, что подобные функции, которые редко используются, не нужно задавать в начале обучения - нужны самые часто используемые в практике - научатся основам - с остальным сами разберутся.
Это на любителя из новичков. Кому-то нравится сразу понять более удобные способы решения задач, кому-то надо подольше тренироваться на выводе фразы "Привет страна" или как там по аглицки... На мой взгляд обучение должно быть в виде подсказок где в справочнике найти информацию и как попроще решить проблему... Но только если эта проблема как-то решена, но не нравится как или не получается решить. Но обязательно начинать с предоставления своего решения, пусть даже не работающего. Примерно так как ты сейчас подсказываешь gravity. На мой взгляд у него получится научиться.

Для дерзких: В обновлённом языке mql4 появился такой оператор ? :
Это аналог оператора if() else только с присваиванием переменной одного из значений или передачи одного из значений в зависимости от какого-то условия. Вот такая строка
Код:
Expand Collapse Copy
int n = Open[1] > Ckose[1] ? 100 : 200;
читается так: Переменной n присвоить значение 100 если открытие бара выше закрытия иначе присвоить значение 200
Можно комбинировать примерно так:
Код:
Expand Collapse Copy
int n = Open[1] > Ckose[1] ? 100 : Open[1] < Ckose[1] ? 200 : 300;
Это заменяется такой конструкцией
Код:
Expand Collapse Copy
int n;
if(Open[1] > Ckose[1])
 n = 100;
else if(Open[1] < Ckose[1])
 n = 200;
 else
 n = 300;
 

vladradon

Программист
Для дерзких: В обновлённом языке mql4 появился такой оператор ? :
Это аналог оператора if() else только с присваиванием переменной одного из значений или передачи одного из значений в зависимости от какого-то условия.
Вот именно, что изначальный вариант понятен и запоминаем, т.к. в нем обычные аглицкие слова if и else, причем даже не сокращенные. А для "дерзкого" варианта нужно четко держать алгоритм в голове - всю последовательность и уметь читать его не только с начала, но и с конца.;)
 

AlexeyVik

Программист mql4 mql5
Вот именно, что изначальный вариант понятен и запоминаем, т.к. в нем обычные аглицкие слова if и else, причем даже не сокращенные. А для "дерзкого" варианта нужно четко держать алгоритм в голове - всю последовательность и уметь читать его не только с начала, но и с конца.;)
А для не знающих аглицкий, таких как я, нет никакой разницы что запоминать ? : или if() else
Правда если придётся строить лесенку из 3х и более вариантов выбора, то я не стану применять ? : а воспользуюсь if() else или вероятнее всего switch
 

gravity

Местный знаток
Пропустил эту строку. Так бывает, когда пишешь код, смотришь сериал по телеку и пытаешься ответить на вопрос одновременно. :ROFLMAO:Правильно:
double op = CalculateProfit(Magic);
в скобках передаем входной параметр = Magic.
Подправил. Добавил вывод в журнал количества ордеров с нашим магиком и количество и профит ордеров с другими магиками.
C++:
Expand Collapse Copy
//+------------------------------------------------------------------+
//|                                                    Магик_111.mq4 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

// https://forexsystemsru.com/threads/izuchaem-jazyk-programmirovanija-mql4.87869/post-1489322
// Напишите функцию, которая на вход принимает значение MagicNumber (уникальный идентификатор ордера).
// Функция должна вернуть суммарную прибыль по всем позициям с соответствующим идентификатором на текущем счете.

//+------------------------------------------------------------------+

input int                Magic         = 12345;       // Летающий слоник

//+------------------------------------------------------------------+ 

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
  
//+------------------------------------------------------------------+
// Условия открытия ордеров                                          |
//+------------------------------------------------------------------+
 
   if(OrdersTotal()<=1) // если оредров меньше 1го
   {
      int ticket = OrderSend(Symbol(), OP_BUY, 0.01, Ask, 0, 0, 0, "Покупка", Magic, 0, Blue);//открываем BAY
   }
   if(OrdersTotal()<5) // если ордеров меньше 5и
   {
      int ticket = OrderSend(Symbol(), OP_SELL, 0.05, Bid, 0, 0, 0, "Продажа", 777, 0, Red);  //открываем SELL
   }
 
//+------------------------------------------------------------------+

   double op = CalculateProfit(Magic);                                   // присваиваем переменной op значение функции CalculateProfit, 
                                                                         // передаем входной параметр Magic в формальный параметр magic
  }  
 
 //+------------------------------------------------------------------+
 //  Считаем профит открытых ордеров
 //+------------------------------------------------------------------+
 
double CalculateProfit(int magic)                                        // Название функции
{
   double Profit = 0.0,                                                  // Задаем значение переменной Profit равное 0
          Profit_other = 0.0;
          int count =0, count777=0;
   for (int i=OrdersTotal()-1; i>=0; i--)                                // цикл - перебираем ордерацикл: кол-во ордеров - 1; пока знач больше или равно 0; уменьшаем на 1
   {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))                       // выбираем ордер для дальнейшей работы
      {
         if(OrderSymbol()==_Symbol &&                                    // проверяем совпадает ли символ ордера с символом графика на котором установлен советник
            OrderMagicNumber()== magic)                                  // проверяем совпадение магик номера ордера с магиком советника   
         {
            if (OrderType() == OP_BUY || OrderType() == OP_SELL)         // проверяем являются ли ордера, рыночными ордерами на покупку или продажу
            {
               count++;                                                  // считаем колечество ордеров, которые подходят условиям
               Profit += (OrderProfit() + OrderSwap() + OrderCommission());// суммируем профиты всех выбранных ордеров c учетом свопа и комиссии
            }
         }
      else  { 
               Profit_other += (OrderProfit() + OrderSwap() + OrderCommission()); // считаем профит ордеров не подходящих условиям
               count777++;                                                        // считаем ордера, которые не подходят условиям
            }                                           
      }
   } 
                  Print(IntegerToString(count)    + " ордера | Профит    = ", DoubleToString(Profit,2));
                                                                                  // выводим в журал колечество и профит ордеров с нашим магиком
                  Print(IntegerToString(count777) + " ордера | Профит777 = ", DoubleToString(Profit_other,2)); 
                                                                                  // выводим в журнал количество и профит других ордеров

   return(Profit);                                                                // возвращем функции значение суммарного профита
   
}
//+------------------------------------------------------------------+
Благодарю за терпение и уделенное время!
 

BorisSedov

Активный участник
Для дерзких: В обновлённом языке mql4 появился такой оператор ? :
Это так называемый "синтаксический сахар" – тернарный оператор, позволяющий точечно использовать различные условные операции, а также более компактно оформлять код.

Пример.
C++:
Expand Collapse Copy
string txt="\n\n\n";
txt+="MagicNumber:  "+(string)MagicNumber+"\n\n";
txt+="Ограничение времени:  "+(!UseTime?"off  (торговля разрешена":TimeStart+" - "+TimeStop+"  (торговля "+(tm_ok?"разрешена":"запрещена"))+")\n\n";
if(ppG>0) txt+="Следующий объем:  "+(Risk!=0?DoubleToStr(flt(),2):DoubleToStr(Lots,2))+"\n\n";
txt+="StopLoss:  "+(string)StopLoss+"\n";
txt+="TakeProfit:  "+(string)TakeProfit+"\n";
txt+="NoLoss:  "+(string)NoLoss+"\n";
txt+="MinProfit:  "+(string)MinProfit+"\n\n";
txt+="Стохастик открытия:  "+(type_s1==-1?"нет сигнала":"пересечение "+(type_s1==OP_BUY?"вверх":"вниз"))+"\n";
txt+="Стохастик закрытия:  "+(!UseCloseSignal?"off":(type_s2==-1?"нет сигнала":"пересечение "+(type_s2==OP_BUY?"вверх":"вниз")))+"\n";
txt+="Фильтр #1 (Стохастик):  "+(!UseFilter1?"off":(type_s3==-1?"нет сигнала":"пересечение "+(type_s3==OP_BUY?"вверх":"вниз")))+"\n";
txt+="Фильтр #2 (Стохастик):  "+(!UseFilter2?"off":(type_s4==-1?"нет сигнала":"пересечение "+(type_s4==OP_BUY?"вверх":"вниз")))+"\n";
txt+="Фильтр #3 (RSI):  "+(!UseFilter3?"off":(type_s5==-1?"нет сигнала":"пересечение "+(type_s5==OP_BUY?"вверх":"вниз")))+"\n";
txt+="Фильтр #4 (спред):  "+(!UseFilter4?"off":"max "+(string)MaxSpread+"   (текущий "+DoubleToStr(MarketInfo(Symbol(),MODE_SPREAD),0)+")");
Comment(txt);


Подправил. Добавил вывод в журнал количества ордеров с нашим магиком и количество и профит ордеров с другими магиками.
Отлично.
Так, шаг за шагом, вы научитесь программировать.
 

1_Lexa

Активный участник
А есть правило, какие команды можно совмещать, а какие нет. Например double find tp,min;
 

1_Lexa

Активный участник
Тут есть, что-то на подобии библиотеки, примеры: как правильно писать, какие ошибки не допустимо делать, какие хитрости есть, ну и разное?
 

1_Lexa

Активный участник
Как только прописал double c=
 

Вложения

  • AF76F5F8-69EB-4BE9-9DBD-42FFD714F14B.jpeg
    AF76F5F8-69EB-4BE9-9DBD-42FFD714F14B.jpeg
    650,4 КБ · Просмотры: 40

BorisSedov

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

MrGreen86

Гуру форума
от себя добавлю, что ошибку "semicolon expected" стоит искать перед той строкой на которую ругается компилятор. Конкретно в примере выше скорее всего забыли поставить точку с запятой где-то выше выражения double c=
 

Leonup

Новичок форума
Здравствуйте! Каким еще способом можно найти максимальный размер бара за n баров, начиная, например, с 3-го номера бара? Кроме способа: double large_bar = MathMax(MathMax(MathMax(MathMax(MathMax(MathMax(MathMax(MathMax(MathMax(hl1,hl2),hl3),hl4),hl5),hl6),hl7),hl8),hl9),hl10);
Спасибо.
 
Последнее редактирование:

Ugar

Гуру форума
Здравствуйте! Каким еще способом можно найти максимальный размер бара за n баров, начиная, например, с 3-го номера бара? Кроме способа: double large_bar = MathMax(MathMax(MathMax(MathMax(MathMax(MathMax(MathMax(MathMax(MathMax(hl1,hl2),hl3),hl4),hl5),hl6),hl7),hl8),hl9),hl10);
Спасибо.
Вместо hl1 - hl10 лучше использовать массив. Индекс ячейки массива с максимальным значением можно легко узнать одной функцией.

Или все вычисления можно сделать в цикле, как размер бара так и сравнивая с предыдущим значением искать максимальное значение. Например так
double hl, large_bar=0;
for(int i=0; i<n; i++)
{
hl=High[i+3]-Low[i+3];
if(large_bar<hl)large_bar=hl;
}
 

AlexeyVik

Программист mql4 mql5
Вместо hl1 - hl10 лучше использовать массив. Индекс ячейки массива с максимальным значением можно легко узнать одной функцией.

Или все вычисления можно сделать в цикле, как размер бара так и сравнивая с предыдущим значением искать максимальное значение. Например так
double hl, large_bar=0;
for(int i=0; i<n; i++)
{
hl=High[i+3]-Low[i+3];
if(large_bar<hl)large_bar=hl;
}
Ой, Андрей извини, но от тебя не ожидал такое увидеть…
Так будет лучше выглядеть
Код:
Expand Collapse Copy
int m = 3,  // С какого бара начинаем поиск
    n = 10; // Количество баров для поиска
double hl, large_bar=0;
for(int i=m; i<n+m; i++)
  hl=fabs(large_bar<hl ? hl : High[i]-Low[i]);
 

Ugar

Гуру форума
Ой, Андрей извини, но от тебя не ожидал такое увидеть…
Так будет лучше выглядеть
Код:
Expand Collapse Copy
int m = 3,  // С какого бара начинаем поиск
    n = 10; // Количество баров для поиска
double hl, large_bar=0;
for(int i=m; i<n+m; i++)
  hl=fabs(large_bar<hl ? hl : High[i]-Low[i]);
Привет, Алексей!
Эта ветка для тех кто первый раз укусил справочник. Мой вариант всё же проще им читать.
 

Leonup

Новичок форума
Спасибо, что откликнулись. Может, я чего-то не понимаю, но почему-то в обоих кодах берется в расчет только одна свеча.
Вместо hl1 - hl10 лучше использовать массив. Индекс ячейки массива с максимальным значением можно легко узнать одной функцией.

Или все вычисления можно сделать в цикле, как размер бара так и сравнивая с предыдущим значением искать максимальное значение. Например так
double hl, large_bar=0;
for(int i=0; i<n; i++)
{
hl=High[i+3]-Low[i+3];
if(large_bar<hl)large_bar=hl;
}
По Вашему коду: только та свеча, которая завершает поиск.
Ой, Андрей извини, но от тебя не ожидал такое увидеть…
Так будет лучше выглядеть
Код:
Expand Collapse Copy
int m = 3,  // С какого бара начинаем поиск
    n = 10; // Количество баров для поиска
double hl, large_bar=0;
for(int i=m; i<n+m; i++)
  hl=fabs(large_bar<hl ? hl : High[i]-Low[i]);

А по Вашему коду: только та свеча, с которой начинаем поиск.
А может это у меня зашел ум за разум. Помогите, пожалуйста, с кодами разобраться.
 

Ugar

Гуру форума
Может, я чего-то не понимаю, но почему-то в обоих кодах берется в расчет только одна свеча.
Нет, в цикле перебираются свечи.
/*Это цикл в котором с каждым проходом i принимает значение от 0 до n-1.*/
for(int i=0; i<n; i++)
{
//здесь вычисляется размер свечи с номером i+3.
hl=High[i+3]-Low[i+3];
//Здесь ищется максимальное значение размера свечи
if(large_bar<hl)large_bar=hl;
}
 

vladradon

Программист
Так будет лучше выглядеть
Привет!
А зачем в абсолютку переводить? Разве high бывает меньше low?;) Вот разделить на пойнт и перевести в int было бы правильнее - размер ведь не вычислили - только разницу между хай и лоу в единицах графика!
 

Вложения

Ugar

Гуру форума
Привет!
А зачем в абсолютку переводить? Разве high бывает меньше low?;) Вот разделить на пойнт и перевести в int было бы правильнее - размер ведь не вычислили - только разницу между хай и лоу в единицах графика!
Привет!
Размер может нужен в натуре, а не в пунктах. Да, лично мне целые нравятся больше дробных с их погрешностями, но лишних преобразований делать не стану.
Я то же удивился наличию fabs. Может какие то мысли были у Алексея. А может просто кинул строчку из какого то своего кода и не всё в ней поправил.
 

AlexeyVik

Программист mql4 mql5
Привет!
А зачем в абсолютку переводить? Разве high бывает меньше low?;) Вот разделить на пойнт и перевести в int было бы правильнее - размер ведь не вычислили - только разницу между хай и лоу в единицах графика!
А я просто попутал с открытием и закрытием.
 
Верх