MT5 è per i programmatori, non per i trader - pagina 17

 
Andrey F. Zelinsky:

Sono lontani i tempi in cui un programmatore prima di imparare il C - passava attraverso i comandi macchina, l'assemblatore, il Fortran, il PL/1, il Pascal e molte altre cose - tutto senza libri di testo, senza spiegazioni adeguate, come ha detto Volchansky sopra, con la documentazione stampata a lettere storte.

questa è l'epoca dei complessi sistemi applicativi multifunzionali - con un linguaggio di programmazione applicativa incorporato - e il compito di questo linguaggio è quello di rendere il terminale applicativo disponibile agli utenti dell'applicazione, i quali, senza scavare in profondità nella programmazione, possono imparare rapidamente e utilizzare questo linguaggio terminale in un breve periodo di tempo.


Sono d'accordo! Detto in modo corretto. Il terminale di trading dovrebbe facilitare il trading.

 
ILNUR777:
Da chi stai giudicando? Come volto della società, non è bello che tu scivoli nel trolling. Hai già scritto che anche coloro che hanno esperienza in MT4 hanno difficoltà. E non ne hanno bisogno.

Vede il trolling?

Ho già scritto molte volte che ci sono molte opportunità per scrivere un EA di prova semplice e facile per la tua strategia.

Ho anche dato un link alla guida. Ma se cominciassimo a fare domande sull'aiuto, vedremmo che siamo interessati a questo tipo di conoscenza. Ma continuava a parlare di quanto tutto sia brutto.

Ecco perché dico - forse la generazione che abbiamo ora - 18 anni, genitori e nuore devono comprare una macchina, 21 - prendere una casa. Ma per studiare - no, perché?

 
Mickey Moose:

Quanto è complicato l'assemblatore? Ho bisogno delle sue funzioni

Perché. Scrivilo in µl5. È facile e diretto.
 
Artyom Trishkin:

Perché solo 10 anni fa i principianti facevano domande molto diverse su questo forum - molto più complicate e interessanti.

A proposito, le domande di oggi in MQL4 sono molto più informative che in MQL5. La ragione è ovvia, e non è l'età delle versioni MQL.

 
Alexey Viktorov:

No, non lo so. Cosa vuoi dire?

Alexey, davvero, non posso farti un esempio adesso. Ma ti piace sperimentare - eseguilo e vedi cosa restituisce con diversi dati di input.

È solo difficile per me ricordarlo e cercarlo ora.

Bene, fxsaber ha dato un esempio (l'ho modificato per me), confronta il codice:

//+------------------------------------------------------------------+
//| Возвращает смещение бара таймфрейма по времени                   |
//+------------------------------------------------------------------+
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);
  }
//+------------------------------------------------------------------+

Qui potete vedere in quali condizioni Bars() restituisce un fallo.

 
fxsaber:

La prima cosa che un principiante scrive è uno script di trading. Il secondo è un semplice indicatore. Il terzo - un semplice Expert Advisor.

Anche la prima fase in MQL4 è più veloce che in MQL5.

Uno script di trading? Perché non un Expert Advisor o addirittura un sostituto della Libreria Standard?

A mio parere, scrivere uno script di trading è un chiaro compito intermedio, e in nessun modo adatto a un principiante.

Un principiante dovrebbe limitarsi prima all'uscita della linea più semplice. Poi - un semplice indicatore. E solo allora - passare alla richiesta di indicatori e funzioni di trading.

 
Mickey Moose:

Quanto è complicato l'assemblatore? Ho bisogno delle sue funzioni.

Quali funzioni?

L'assemblatore è troppo specifico per dire "ho bisogno delle sue funzioni".

 

Un esempio fresco sul tema di ciò che l'SB sta vendendo ai neofiti del forum e perché anche i lontani da pigrizia stanno avendo un momento davvero difficile. Oggi ho ricevuto una domanda molto costruttiva su MQL5 senza alcun lamento.

Questo è il forum per il trading, i sistemi di trading automatico e il test delle strategie di trading

Bug, bug, domande

damirqa, 2018.01.09 12:14

Ciao, ho iniziato a studiare MQL5 dahttps://www.mql5.com/ru/articles/100. Ho iniziato il codice e ho ricevuto l'errore 4756. Ho pensato di iniziare con qualcosa di semplice (Allarme/Stampa...). Una delle funzioni più importanti è OrderSend. Ho iniziato a cercare nel forum/documentazione su come usare OrderSend. Ho trovato questo articolohttps://www.mql5.com/ru/docs/constants/tradingconstants/enum_trade_request_actions e ho trovato il codice per aprire una posizione Buy. Ho ottenuto l'errore 4756 e il retcode 10030. Ho capito che 10030 - è la proprietà OrderSend, ma non ho capito come dovrebbe essere usata questa proprietà (ho guardato il codice di qualcun altro) e a cosa serve principalmente. Poi ho apertohttps://www.mql5.com/ru/docs/trading/ordersend, ho copiato il codice, l'ho eseguito e ha funzionato bene.
Ma non ho ancora capito perché appare l'errore 4756 e come liberarmene, così come il 10030.

Guardato il codice tra

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);
   }

e questo.

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; 
  } 

Mi sembrano quasi identici, non vedo i posti dove appaiono questi errori (4756 e 10030). Punta il dito e spiega per favore


Risposta del moderatore

Forum sul trading, sistemi di trading automatico e tester di strategie

Errori, bug, domande

Vladimir Karputov, 2018.01.09 12:20


Usate la classe di trading di CTrade - in questo modo avrete la garanzia di fare meno errori possibili.

Esempio di invio di un ordine di compravendita per aprire Buy:


Probabilmente ha aiutato a risolvere il problema. Ma in realtà il novellino ha un problema molto serio.

Cioè devi andare a leggere i link sull'argomento designato. In SB questo è risolto attraverso un posto meraviglioso. Cioè quando si scrive lo script di trading più semplice (il primo programma di qualsiasi principiante) è quasi trindetz.

 
George Merts:

Scambio di copioni con il mondo esterno. Perché non un Expert Advisor o addirittura un sostituto della Libreria Standard?

A mio parere, scrivere uno script commerciale è un chiaro compito intermedio, e in nessun modo adatto a un principiante.

Un principiante dovrebbe limitarsi prima all'uscita della linea più semplice. Poi - un semplice indicatore. E solo allora - passare alla richiesta di indicatori e funzioni di trading.

Ho iniziato subito con l'Expert Advisor MTF multivaluta. E mi sentivo bene nel ramo dei neofiti. E non ho fatto troppe domande - ho un aiuto e un cervello da qualche parte...

 

Oh, e a proposito, a proposito di iBarsShift.

Ecco la mia funzione controparte (CTSTime è una classe di serie temporali), penso che sia un po' complicato per i neofiti, anche con i commenti. Quindi è davvero carente 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);         
};      


Motivazione: