Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 728

 

Хотя я бы написал так:

//+------------------------------------------------------------------+
//|                                                       TestEA.mq5 |
//|                              Copyright © 2017, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2017, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.001"
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\AccountInfo.mqh>
CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object
CAccountInfo   m_account;                    // account info wrapper
//---
double         Lot            = 0.01;
double         CoofLot        = 1.0;
double         Loss           = 100.0;
bool           nap            = true;
//---
ulong          m_magic        = 15489;       // magic number
ulong          m_slippage     = 10;          // slippage
double         m_adjusted_point;             // point value adjusted for 3 or 5 points
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   m_symbol.Name(Symbol());                  // sets symbol name
   if(!RefreshRates())
     {
      Print("Error RefreshRates. Bid=",DoubleToString(m_symbol.Bid(),Digits()),
            ", Ask=",DoubleToString(m_symbol.Ask(),Digits()));
      return(INIT_FAILED);
     }
   m_symbol.Refresh();
//---
   m_trade.SetExpertMagicNumber(m_magic);
//---
   m_trade.SetDeviationInPoints(m_slippage);
//--- tuning for 3 or 5 digits
   int digits_adjust=1;
   if(m_symbol.Digits()==3 || m_symbol.Digits()==5)
      digits_adjust=10;
   m_adjusted_point=m_symbol.Point()*digits_adjust;
//---
   CoofLot  = 1.0;
   Loss     = 100.0;
   nap      = true;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   static double         static_Balance=0.0;
   if(static_Balance==0.0)
      static_Balance=m_account.Balance();

   double balance=m_account.Balance();             // локальная переменная для хранения баланса на время OnTick

//--- считаем позиции по символу и по Magic
   int total=0;
   for(int i=PositionsTotal()-1;i>=0;i--) // returns the number of open positions
      if(m_position.SelectByIndex(i))     // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
            total++;

   if(total==0)
     {
      //--- попытка обновить цены
      if(!RefreshRates())
         return;                          // есил не удалось обновить цены - просто выходим

      if(static_Balance!=balance)
        {
         if(balance<static_Balance)
           {
            CoofLot++;
            double lots=pow(2,CoofLot)*0.01;       // локальная переменная для временных расчётов лота
            //--- проверка корректности лота
            Lot=LotCheck(lots);
            if(Lot==0.0)
               return;
            if(nap)
               nap=false;
            else
               nap=true;
           }
         if(balance>static_Balance)
           {
            Lot=0.01;
            CoofLot=1.0;
           }
        }
      static_Balance=balance;

      if(nap==true)
        {
         double sl=m_symbol.NormalizePrice(m_symbol.Bid() - Loss*m_adjusted_point); // Stop Loss
         double tp=m_symbol.NormalizePrice(m_symbol.Bid() + Loss*m_adjusted_point); // Take Profit

         if(m_trade.Buy(Lot,NULL,m_symbol.Ask(),sl,tp))
           {
            if(m_trade.ResultDeal()==0)
               Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
                     ", description of result: ",m_trade.ResultRetcodeDescription());
            else
               Print("Buy -> true. Result Retcode: ",m_trade.ResultRetcode(),
                     ", description of result: ",m_trade.ResultRetcodeDescription());
           }
         else
            Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
                  ", description of result: ",m_trade.ResultRetcodeDescription());
        }
      else
        {
         double sl=m_symbol.NormalizePrice(m_symbol.Ask()+Loss*m_adjusted_point); // Stop Loss
         double tp=m_symbol.NormalizePrice(m_symbol.Ask()-Loss*m_adjusted_point); // Take Profit

         if(m_trade.Sell(Lot,NULL,m_symbol.Ask(),sl,tp))
           {
            if(m_trade.ResultDeal()==0)
               Print("Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
                     ", description of result: ",m_trade.ResultRetcodeDescription());
            else
               Print("Sell -> true. Result Retcode: ",m_trade.ResultRetcode(),
                     ", description of result: ",m_trade.ResultRetcodeDescription());
           }
         else
            Print("Sell -> false. Result Retcode: ",m_trade.ResultRetcode(),
                  ", description of result: ",m_trade.ResultRetcodeDescription());
        }
     }
   return;
  }
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
      return(false);
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| Lot Check                                                        |
//+------------------------------------------------------------------+
double LotCheck(double lots)
  {
//--- calculate maximum volume
   double volume=NormalizeDouble(lots,2);
   double stepvol=m_symbol.LotsStep();
   if(stepvol>0.0)
      volume=stepvol*MathFloor(volume/stepvol);
//---
   double minvol=m_symbol.LotsMin();
   if(volume<minvol)
      volume=0.0;
//---
   double maxvol=m_symbol.LotsMax();
   if(volume>maxvol)
      volume=maxvol;
   return(volume);
  }
//+------------------------------------------------------------------+

Здесь:

  1. Стоп Лосс задаётся в "четвёрочных" пунктах - то есть он будет корректно работать и на EURUSD и на USDJPY
  2. для получения цен используется объект "m_symbol" торгового класса CSymbolInfo
  3. проверяется общее количество позиций по данного символу и данному Magic
  4. если лот меняется, то предварительно проходит его проверка и коррекция в "LotCheck"
  5. торговые операции проводятся при помощи методов объекта "m_trade" торгового класса CTrade
  6. проводится проверка результата торговых операций (две ступени - базовая проверка и результат размещения)

 

Добавлено:

получился очень интересный результат одиночного прогона в тестере стратегий:

Tester 


 
Файлы:
TestEA.mq5  14 kb
[Удален]  
Vladimir Karputov:

Хотя я бы написал так:

На данный момент, я бы не рекомендовал использовать функцию m_symbol.RefreshRates(), т.к. SymbolInfoTick() может возвращать не свежие данные. И, если эту тему читают разработчики, прошу еще раз обратить их внимание на то, что SymbolInfoTick() косячит, но при этом используется в классах СБ! 
 
Здравствуйте! Решил для самообразования сделать мультивалютный эксперт по стратегии Green-Red Candle на MQL5.
Базовый функционал реализован, но постоянно появляются ошибки типа "Invalid price". Добавил дополнительные проверки на то, чтобы устранить их возможные причины, и соответственно, установку их в заведомо корректные значения, но ошибки никуда не делись. Сам уже не знаю, в каком направлении двигаться. Подскажите, где я сделал ошибку? Исходные коды прилагаю.
Файлы:
 
NickWelder:
Здравствуйте! Решил для самообразования сделать мультивалютный эксперт по стратегии Green-Red Candle на MQL5.
Базовый функционал реализован, но постоянно появляются ошибки типа "Invalid price". Добавил дополнительные проверки на то, чтобы устранить их возможные причины, и соответственно, установку их в заведомо корректные значения, но ошибки никуда не делись. Сам уже не знаю, в каком направлении двигаться. Подскажите, где я сделал ошибку? Исходные коды прилагаю.

Перед совершением торговой операции нужно обновлять цены в объекте торгового класса CSymbolInfo. В моих моно-проектах (в которых только один символ) я использую такую функцию:

//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
      return(false);
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
      return(false);
//---
   return(true);
  }

и использование - если ну удалось обновить цены, то просто выходим, если удачно обновили цены, то будет торговая операция:

//--- refresh rates
   if(!m_symbol.RefreshRates())
      return;

   if(m_trade.Buy(lots,NULL,m_symbol.Ask(),sl,tp))
     {
      if(m_trade.ResultDeal()==0)
         Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
               ", description of result: ",m_trade.ResultRetcodeDescription());
      else
         Print("Buy -> true. Result Retcode: ",m_trade.ResultRetcode(),
               ", description of result: ",m_trade.ResultRetcodeDescription());
     }
   else
      Print("Buy -> false. Result Retcode: ",m_trade.ResultRetcode(),
            ", description of result: ",m_trade.ResultRetcodeDescription(



 

 
@Vladimir Karputov, Спасибо Вам! С рыночными ордерами всё получилось.
 

Подскажите красивое и "лёгкое" решение, чем заменить вот эту конструкцию:

if(iBarShift(_Symbol, _Period, TimeLast)==3) {...}

 

Сейчас стоит такое, но как по мне - слишком "тяжёлое" решение:

int iBarShift(string symbol,ENUM_TIMEFRAMES tf,datetime time,bool exact=false) {
  if(time<0) return(-1);
   datetime Arr[],time1;
   CopyTime(symbol,tf,0,1,Arr);
   time1=Arr[0];
   if(CopyTime(symbol,tf,time,time1,Arr)>0) {
      if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
      if(time<time1) return(1);
      else return(0);
     }
   else return(-1);
}
 
Vitaly Muzichenko:

Подскажите красивое и "лёгкое" решение, чем заменить вот эту конструкцию:

if(iBarShift(_Symbol, _Period, TimeLast)==3) {...}

 

Сейчас стоит такое, но как по мне - слишком "тяжёлое" решение:

int iBarShift(string symbol,ENUM_TIMEFRAMES tf,datetime time,bool exact=false) {
  if(time<0) return(-1);
   datetime Arr[],time1;
   CopyTime(symbol,tf,0,1,Arr);
   time1=Arr[0];
   if(CopyTime(symbol,tf,time,time1,Arr)>0) {
      if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
      if(time<time1) return(1);
      else return(0);
     }
   else return(-1);
}
Так как-то (решение от @fxsaber):

//+------------------------------------------------------------------+
//| Возвращает смещение бара по времени                              |
//+------------------------------------------------------------------+
int GetBarShift(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
   int res=-1;
   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);
}
//+------------------------------------------------------------------+
Тут где-то кто-то писал, что в выделенной строке нужно так сделать: if(time>=last_bar) res=0;

Вот не проверял, если честно - всё время не доходит. Проверите, напишите результат пожалуйста.
[Удален]  
Vitaly Muzichenko:

Подскажите красивое и "лёгкое" решение, чем заменить вот эту конструкцию:

if(iBarShift(_Symbol, _Period, TimeLast)==3) {...}

 

Сейчас стоит такое, но как по мне - слишком "тяжёлое" решение:

int iBarShift(string symbol,ENUM_TIMEFRAMES tf,datetime time,bool exact=false) {
  if(time<0) return(-1);
   datetime Arr[],time1;
   CopyTime(symbol,tf,0,1,Arr);
   time1=Arr[0];
   if(CopyTime(symbol,tf,time,time1,Arr)>0) {
      if(ArraySize(Arr)>2) return(ArraySize(Arr)-1);
      if(time<time1) return(1);
      else return(0);
     }
   else return(-1);
}
Не знаю, насколько мое решение "легче", но попробуйте это: https://www.mql5.com/ru/forum/160945#comment_4053382
Как получить номер бара по времени входа в позицию?
Как получить номер бара по времени входа в позицию?
  • www.mql5.com
Приветствую! Пишу трейлинг, который проходится по барам начиная от времени входа в позицию...
[Удален]  
Artyom Trishkin:
Так как-то (решение от @fxsaber):

//+------------------------------------------------------------------+
//| Возвращает смещение бара по времени                              |
//+------------------------------------------------------------------+
int GetBarShift(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
   int res=-1;
   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);
}
//+------------------------------------------------------------------+
Тут где-то кто-то писал, что в выделенной строке нужно так сделать: if(time>=last_bar) res=0;

Вот не проверял, если честно - всё время не доходит. Проверите, напишите результат пожалуйста.
Я это написал. И это логично, т.к. если время time совпадает c временем открытия текущего бара, то индекс у него тоже 0. Да, чистое решение fxsaber'a будет работать с ошибками.
 
Alexey Kozitsyn:
Не знаю, насколько мое решение "легче", но попробуйте это: https://www.mql5.com/ru/forum/160945#comment_4053382

А что, нет стандартной функции в языке и нужно каждому строить свой велосипед, а после этого мерятся писпроизводительностью?

Вроде как нашёл все, кроме этой, но после просмотра разных решений видно, что лепят "кто на что гаразд"