Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 2555

 
Volodymyr Zubov #:

Всё проверяет для MT4 и MT5

О! спсб! Заюзаю!!!
 
Vitaly Murlenko #:

Вообще, может возникнуть ошибка. Если шаг наращивания лота не равен минимальному лоту (честно говоря, я такого не встречал, но чем чёрт не шутит), то моя функция может выдать некорректный лот. В этом случае может начать упрямо вылезать ошибка типа 130, или ошибка неправильных параметров функции. В этом случае лучше запросить информацию с сервера. Я себе сделал вот такой скриптик (надо бы его в кодобазу выложить, что я сейчас и сделаю):

СПС большое. Заюзаю.
 
Roman Shiredchenko #:

у меня на МТ4 надо, а тут ну получили что не является кратным минимальному - дальше то что делать?

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

символы для торгов просто разные.

Что делать можно было заметить тут:

description=StringFormat("Объем не является кратным минимальной градации SYMBOL_VOLUME_STEP=%.2f, ближайший корректный объем %.2f",
                               volume_step,ratio*volume_step);

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

//+------------------------------------------------------------------+
//|  Проверяет объем ордера на корректность для символа              |
//+------------------------------------------------------------------+
bool CorrectVolumeValue(string symbol, double &volume) {
//--- минимально допустимый объем для торговых операций
   double min_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   if(volume < min_volume) {
      volume = 0;
      return(false);
   }

//--- максимально допустимый объем для торговых операций
   double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
   if(volume > max_volume) {
      volume = 0;
      return(false);
   }

//--- получим минимальную градацию объема
   double volume_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);

   int ratio = (int)MathRound(volume / volume_step);
   if(MathAbs(ratio * volume_step - volume) > 0.0000001) {
      volume = ratio * volume_step;
      return(false);
   }
   return(true);
}

Округление корректно происходит в строке

volume = ratio * volume_step;

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

//+------------------------------------------------------------------+
//|  Проверяет объем ордера на корректность                          |
//+------------------------------------------------------------------+
double GetCorrectVolumeValue(string symbol, double volume) {
//--- минимально допустимый объем для торговых операций
   double min_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
//--- максимально допустимый объем для торговых операций
   double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
   if(volume < min_volume || volume > max_volume) {
      return 0;
   }

//--- получим минимальную градацию объема
   double volume_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);

   int ratio = (int)MathRound(volume / volume_step);
   if(MathAbs(ratio * volume_step - volume) > 0.0000001) {
      return ratio * volume_step;
   }
   return volume;
}

// Пример использования
{
   volume = 0.1233;
   volume = GetCorrectVolumeValue(Symbol(), volume);

   if(volume > 0) {
      OrderSend(...);
   }
}

Должно работать одинаково в MQL4 и MQL5

 
Yuriy Bykov #:
В случае выхода за пределы будет возвращаться ноль

В идеале дополнить максимально возможным, к примеру актуально для усреднителей, если запрашиваемый лот 1.1 и не хватает маржи, то рассчитать на максимально возможный, на сколько позволяет маржа.

 
Yuriy Bykov #:

Что делать можно было заметить тут:

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

Округление корректно происходит в строке

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

Должно работать одинаково в MQL4 и MQL5

Понял - ок. Спс.
 
Yuriy Bykov #:

Что делать можно было заметить тут:

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

Округление корректно происходит в строке

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

Должно работать одинаково в MQL4 и MQL5

посмотрю вечером -покурю - спс.

 

Привет. Простите за "детский " вопрос. Робот открыл сделку, получил тикет 2. Когда он закрылся (перестал выбираться по тикету), как получить тикет закрывшей его сделки (чтоб посчитать профит) ?

 
Andrei Sokolov #:

Привет. Простите за "детский " вопрос. Робот открыл сделку, получил тикет 2. Когда он закрылся (перестал выбираться по тикету), как получить тикет закрывшей его сделки (чтоб посчитать профит) ?

статей много н а эту тему через историю делается ордеров, типа этого F1 на операторе - ф-ии нажимайте

HistoryDealsTotal()

 в МЕ и в справке смотрите. 

Проходя в цикле по всем сделкам, записываем в файл сделки buy и sell:

   for(int i=0;i<HistoryDealsTotal();i++){
      ulong ticket=HistoryDealGetTicket(i);
      if(ticket!=0){         
         long type=HistoryDealGetInteger(ticket,DEAL_TYPE);         
         if(type==DEAL_TYPE_BUY || type==DEAL_TYPE_SELL){      
            long entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);      
            FileWrite(h,(datetime)HistoryDealGetInteger(ticket,DEAL_TIME),
                        ticket,
                        HistoryDealGetInteger(ticket,DEAL_ORDER),
                        HistoryDealGetString(ticket,DEAL_SYMBOL),
                        (type==DEAL_TYPE_BUY?"buy":"sell"),
                        (entry==DEAL_ENTRY_IN?"in":(entry==DEAL_ENTRY_OUT?"out":"in/out")),
                        DoubleToString(HistoryDealGetDouble(ticket,DEAL_VOLUME),2),
                        HistoryDealGetDouble(ticket,DEAL_PRICE),
                        DoubleToString(HistoryDealGetDouble(ticket,DEAL_COMMISSION),2),
                        DoubleToString(HistoryDealGetDouble(ticket,DEAL_SWAP),2),
                        DoubleToString(HistoryDealGetDouble(ticket,DEAL_PROFIT),2),
                        HistoryDealGetString(ticket,DEAL_COMMENT)                     
            );
         }
      }
      else{
         Alert("Ошибка выделения сделки, повторите попытку");
         FileClose(h);
         return;
      }
   }
 
Roman Shiredchenko #:

статей много н а эту тему через историю делается ордеров, типа этого F1 на операторе - ф-ии нажимайте

 в МЕ и в справке смотрите. 

я тут так и не понял: как связать сделки 2 и 3 ?

 
Andrei Sokolov #:

я тут так и не понял: как связать сделки 2 и 3 ?

через DEAL. F1 и справку почитайте.... и примеры в справке 

long entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
entry==DEAL_ENTRY_IN?"in":(entry==DEAL_ENTRY_OUT?"out":"in/out")),