MT5 is for programmers, not traders - page 17

 
Andrey F. Zelinsky:

long gone are the days when a programmer before learning C -- went through machine commands, assembler, Fortran, PL/1, Pascal and many other things -- all without textbooks, without proper explanation, as Volchansky said above, with documentation printed out in crooked letters.

this is the time of complex multifunctional application systems -- with an embedded application programming language -- and the task of this language is to make the application terminal available to application users, who, without digging deep into programming, can quickly learn and use this terminal language.


I agree! That's a good point. The trading terminal should facilitate trading.

 
ILNUR777:
Who are you judging by? As the face of the company, it is not nice for you to slip into trolling. You have already written that even those who have experience in MT4 have difficulties. And they don't need lego.

Do you see trolling?

I have already written many times that there are plenty of opportunities to write a simple and easy test EA for your strategy.

I even gave a link to the help. But if we started asking questions regarding the help, we would see that we were interested in this kind of knowledge. But it went on and on about how bad everything is.

That's why I say - perhaps the generation we have now - 18 years old, parents-daughter-in-law have to buy a car, 21 - get a house. But to study - no, why?

 
Mickey Moose:

how complicated is the assembler? I need its functions

Why. Write it in µl5. It's easy and straightforward.
 
Artyom Trishkin:

Because only 10 years ago beginners were asking much different questions on this forum - much more complicated and interesting.

By the way, today's questions in MQL4 are much more informative than in MQL5. The reason is obvious, and it's not the age of MQL-versions.

 
Alexey Viktorov:

No I don't. What do you mean?

Alexey, really, I can't give you an example right now. But you like to experiment - run it and see what it returns with different input data.

It's just difficult for me to remember and look for it now.

Well, fxsaber gave an example (I have modified it for me), compare the code:

//+------------------------------------------------------------------+
//| Возвращает смещение бара таймфрейма по времени                   |
//+------------------------------------------------------------------+
int CTimes::BarShift(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const datetime time) const
  {
   int res=WRONG_VALUE;
   datetime last_bar;
   if(::SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE,last_bar)){
      if(time>last_bar) res=0;
      else{
         const int shift=::Bars(symbol_name,timeframe,time,last_bar);
         if(shift>0) res=shift-1;
         }
      }
   return(res);
  }
//+------------------------------------------------------------------+

Here you can see under what conditions Bars() returns a foul.

 
fxsaber:

The first thing a beginner writes is a trading script. The second is a simple indicator. The third one - a simple Expert Advisor.

Even the first stage in MQL4 is faster than in MQL5.

A trading script? Why not an Expert Advisor or even a Standard Library replacement ?

In my opinion, writing a trading script is a clear Intermediate task, and in no way suitable for a beginner.

A beginner should be limited to the simplest line output first. Then - a simple indicator. And only then - move on to requesting indicators and trading functions.

 
Mickey Moose:

How complicated is the assembler? I need its functions.

What functions?

Assembler is too specific to say "I need its functions".

 

A fresh example on the subject of what the SB is selling to newbies on the forum and why even far from lazybones are having a really hard time. Today I got a very constructive question on MQL5 without any whining.

This is the forum for trading, automated trading systems and testing of trading strategies

Bugs, bugs, questions

damirqa, 2018.01.09 12:14

Hello! I started studying MQL5 fromhttps://www.mql5.com/ru/articles/100. I started the code and received error 4756. I thought I would start with something simple (Alert/Print...). One of the most important functions is OrderSend. I started searching through the forum/documentation on how to use OrderSend. I found this articlehttps://www.mql5.com/ru/docs/constants/tradingconstants/enum_trade_request_actions and found the code for opening a Buy position. I got error 4756 and retcode 10030. I understood that 10030 - it is the OrderSend property, but I have not understood how this property should be used (I looked at somebody else's code) and what it is mainly used for. Then I openedhttps://www.mql5.com/ru/docs/trading/ordersend, copied the code, launched it, everything is fine, it worked.
But I still don't understand why error 4756 appears and how to get rid of it, as well as 10030.

Looked at the code between

void OnTick(){
      //--- объявление и инициализация запроса и результата
      MqlTradeRequest request={0};
      MqlTradeResult  result={0};
      //--- параметры запроса
      request.action   =TRADE_ACTION_DEAL;                     // тип торговой операции
      request.symbol   =Symbol();                              // символ
      request.volume   =0.1;                                   // объем в 0.1 лот
      request.type     =ORDER_TYPE_BUY;                        // тип ордера
      request.price    =SymbolInfoDouble(Symbol(),SYMBOL_ASK); // цена для открытия
      request.deviation=5;                                     // допустимое отклонение от цены
      request.magic    =EXPERT_MAGIC;                          // MagicNumber ордера
      //--- отправка запроса
      if(!OrderSend(request,result))
         PrintFormat("OrderSend error %d",GetLastError());     // если отправить запрос не удалось, вывести код ошибки
         Alert(GetLastError());
      //--- информация об операции
      PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
   }

and this one.

uint SendRandomPendingOrder(long const magic_number) 
  { 
//--- готовим запрос 
   MqlTradeRequest request={0}; 
   request.action=TRADE_ACTION_PENDING;         // установка отложенного ордера 
   request.magic=magic_number;                  // ORDER_MAGIC 
   request.symbol=_Symbol;                      // инструмент 
   request.volume=0.1;                          // объем в 0.1 лот 
   request.sl=0;                                // Stop Loss не указан 
   request.tp=0;                                // Take Profit не указан    
//--- сформируем тип ордера 
   request.type=GetRandomType();                // тип ордера 
//---сформируем цену для отложенного ордера 
   request.price=GetRandomPrice(request.type);  // цена для открытия 
//--- отправим торговый приказ 
   MqlTradeResult result={0}; 
   OrderSend(request,result); 
//--- выведем в лог ответ сервера   
   Print(__FUNCTION__,":",result.comment); 
   if(result.retcode==10016) Print(result.bid,result.ask,result.price); 
//--- вернем код ответа торгового сервера 
   return result.retcode; 
  } 

They seem almost identical to me, I don't see the places where these errors appear (4756 and 10030). Point the finger and explain please


Moderator answer

Forum about trading, automated trading systems and strategy tester

Errors, Bugs, Questions

Vladimir Karputov, 2018.01.09 12:20


Use CTrade trade class - that way you are guaranteed to make as few mistakes as possible.

Example of sending a trade order to open Buy:


Probably helped to make sense of it. But in fact the rookie has a very serious problem.

I.e. you have to go and read the links on the designated topic. In SB this is solved through a wonderful place. I.e. when writing the simplest trading script (the first progam of any beginner) it's almost trindetz.

 
George Merts:

Trade script ??? Why not an Expert Advisor or even a replacement for the Standard Library?

In my opinion, writing a trade script is a clear Intermediate task, and in no way suitable for a beginner.

A beginner should be limited to the simplest line output first. Then - a simple indicator. And only then - move on to requesting indicators and trading functions.

I started with multicurrency MTF Expert Advisor right away. And I felt good in the newbies branch. And I didn't ask too many questions - I've got help and a brain somewhere...

 

Oh, and speaking of iBarsShift.

Here's my counterpart function (CTSTime is a time-series class), I think it's a bit complicated for newbies, even with the comments. So it's really lacking in SB:

// Функция ищет бар, внутри которого находится указанный момент.
// Если такой бар найден - возвращается true и ссылка rIdx устанавливает нужное значение 
// Если такой бар не найден - возвращается false и ссылка rIdx устанавливает значение на ближайший индекс,
// время которого меньше, требуемого.
// При недостаточности буффера функция возвращает false, ссылка устанавливается на отрицательное значение.   
// NOTE !!! ненаступивший момент может лежать внутри нулевого бара, в этом случае вернется true,
// даже если фактически данный момент еще не наступил. false вернется только если данный момент лежит позже
// нулевого бара. 
// Если искомый момент находится раньше самого раннего бара, возвращается false и  rIdx = INT_MAX

bool CTSTime::FindIdxOf(datetime dtMomentToFind,int& rIdx)
{
   ASSERT(dtMomentToFind > MIN_DATETIME && dtMomentToFind < NEVER_EXPIRES);

   // Пока найденный индекс - невалиден.
   rIdx = WRONG_VALUE;

   // Если данных нет - возвращаем отрицательный результат поиска.
   if(GetTSSize() == 0)
      return(false);

   // Найдем продолжительность текущего бара
   int iSecondsInBar = PeriodSeconds(m_etTimeframe);
   
   ASSERT(iSecondsInBar >= SECS_IN_MINUTE);

   datetime dtMomentOfZeroBar = GetTime(0);
   datetime dtMomentOfLastBar = GetTime(GetTSSize()-1);
   
   // Искомый момент лежит внутри или позже, чем нулевой бар ?  
   if(dtMomentToFind >= dtMomentOfZeroBar)   
      {
      rIdx = 0;
      
      // Искомый момент лежит на открытии минус первого бара или позже ?  
      if(dtMomentToFind >= dtMomentOfZeroBar + iSecondsInBar) 
         return (false);   // Искомый момент лежит после нулевого бара. 
      
      // Искомый момент лежит внутри нулевого бара.
      return(true);               
      };
      
   // Здесь ясно, что искомый момент был ранее нулевого бара. 
   
   // Проверим, может быть искомый момент лежит раньше последнего бара ? 
   if(dtMomentToFind < dtMomentOfLastBar)
      {
      // Увы, такого раннего момента в таймсерии нет. 
      // Возвращаем самый большой индекс бара, какой можем возвратить
      // (Потому, что бара со временем меньше требуемого - в таймсерии нет).
      rIdx = INT_MAX;
      return(false);
      };

   // Здесь ясно, что искомый момент был позже начала самого раннего бара, но раньше начала самого нового бара.

   ASSERT(GetTSSize()  > 1);  // Проверим, размер буффера должен быть минимум два бара. (Иначе условие не выполняется, что искомый момент был позже начала самого раннего бара, но раньше начала самого нового бара, не выполняется)

   // Ищем примерно, где был данный момент.
   ASSERT(dtMomentOfZeroBar > dtMomentToFind);
   ASSERT(dtMomentOfZeroBar > dtMomentOfLastBar);
   
   ulong ulSecFromSearchToLatest = dtMomentOfZeroBar - dtMomentToFind;   
   ulong ulSecFromEarlestToLatest = dtMomentOfZeroBar - dtMomentOfLastBar;
   
   ASSERT(ulSecFromEarlestToLatest > ulSecFromSearchToLatest);
    
   double dResIdx = (double)ulSecFromSearchToLatest*(double)(GetTSSize()-1)/(double)ulSecFromEarlestToLatest;
   
   ASSERT(dResIdx <INT_MAX && dResIdx >= 0);
   
   int iResIdx = (int)MathRound(dResIdx);
   
   ASSERT(iResIdx >= 0 && iResIdx<(int)GetTSSize());   // По идее, мы должны уложиться в этот диапазон.
   
   // Поскольку мы исследуем минимум два бара (текущий и следующий),
   // Текущий бар не должен быть нулевым.
   // Поскольку случай с буффером в один бар у нас был отсеян раньше, мы не должны получить ошибку.
   
   if(iResIdx == 0)  
      iResIdx = 1;

   // Получен приблизительный индекс (uiResIdx).
   
   // Уточняем. Берем два бара, текущий и следующий.
   datetime dtResMoment;
   datetime dtNextMoment;
   
   
   dtResMoment = GetTime(iResIdx);
   dtNextMoment = GetTime(iResIdx-1);
   
   int iShift = 0;
   bool bUp = false;
   bool bDown = false;
   
   do
      {
      if(dtResMoment > dtMomentToFind)       // Если искомый момент раньше начала первого бара
         {
         iShift = 1;                         // Возьмем на один бар раньше.
         bUp = true;                         // Запомним направление
         }
      else                                   // Иначе - Искомый момент равен или позже начала первого бара. 
         {
         if(dtNextMoment <= dtMomentToFind)  // Если искомый момент больше или равен началу второго бара
            {
            iShift = -1;                     // Возьмем на один бар позже
            bDown = true;                    // Запомним направление
            }
         else                          // Иначе - искомый момент равен или позже начала перого бара и раньше начала  второго бара   
            {         
            iShift = 0;                // То есть, можно выходить из цикла коррекции.
            }
         }  

      iResIdx += iShift;               // Смещаемся

      if(iResIdx > (int)GetTSSize() || iResIdx <= 0) // Проверим на допустимый диапазон
         {
         ASSERT(false);    // В серии недостаточно данных (мал буффер)
         rIdx = INT_MAX;
         return(false);
         };
                  
      dtResMoment = GetTime(iResIdx);  // Запрашиваем новые данные 
      dtNextMoment = GetTime(iResIdx-1);
            
      if(bUp == true && bDown == true) // Контроль направления коррекции
         {
         ASSERT(false);                // Сменилось направление коррекции !!!
         iShift = 0;
         }           
      }
   while(iShift != 0);
   
   // В этой точке искомый момент равен или позже начала перого бара и раньше начала  второго бара.
   // Проверим, может быть, искомый момент позже конца первого бара, но раньше начала второго бара 
   // (между барами разрыв, и искомый момент находится именно там)
   
   // Ясно, что ссылка должна показывать на первый бар в любом случае 
   
   rIdx = iResIdx;
   
   if(dtMomentToFind >= dtResMoment+iSecondsInBar)
      // Действительно, искомый момент - внутри разрыва между барами.
      return(false);
   
   return(true);         
};