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

 

Здравствуйте. Как то писал советник на MetaTraider 4. Вернее учился писать. Многое не умею и не знаю еще. И решил перенести его на MetaTraider 5 где немного оказалось все по другому. Вообщем брал другой советник. Разбирал его. Копировал код для открытия ставок. Вообщем ошибок вроде нету но работает не так как должно быть. Помогите перенести правильно. 

 MetaTraider 4:

int err = 0;            
double Lot = 0.01;       // Лот
double CoofLot = 0;
double Ballance = AccountBalance();
double loss = 100;    
bool nap = true;       //true  - 1
                       //false - 0
int start()
  {  
    if(OrdersTotal()==0)                                
    {
       if(Ballance != AccountBalance())                
       {
        if(AccountBalance() < Ballance )                
        {
            CoofLot++;
            Lot = pow(2, CoofLot) * 0.01;
            if(nap == true)                            
               {
                nap = false;
               }
             else
               {
                nap = true;
               }
         }
         if(AccountBalance() > Ballance)                
           {
             Lot = 0.01;
             CoofLot = 0;
           }
       }
    Ballance = AccountBalance();
    
    int order;
    if(nap == true)                                      
      {
       order = OrderSend(Symbol(),OP_BUY,Lot,Ask,1*Point,Ask-loss*Point,Ask+loss*Point);   // Вверх
      }                  
    else
      {
       order = OrderSend(Symbol(),OP_SELL,Lot,Bid,1*Point,Bid+loss*Point,Bid-loss*Point);    // Вниз
      }
  
       if(order<0)                                
         {
           if (GetLastError()==134)
             {
               err=1;
               Print("NOT ENOGUGHT MONEY!!");
             }
           return (-1);
         }
       }
   return(0);
  }


И вот кое как перенес на MetaTraider 5:

double Lot = 0.01;      
double CoofLot = 0;

double Ballance = ACCOUNT_BALANCE;
double loss = 100;    
bool nap = true;       //true  - 1
                       //false - 0



void OnTick()
{
   MqlTick latest_price;       // Будет использоваться для текущих котировок
   MqlTradeRequest mrequest;   // Будет использоваться для отсылки торговых запросов
   MqlTradeResult mresult;  
   if(OrdersTotal()==0)                                
      {
      if(!SymbolInfoTick(_Symbol,latest_price))
         {
            Alert("Ошибка получения последних котировок - ошибка:",GetLastError(),"!!");
            return;
         }
        
      if(Ballance != ACCOUNT_BALANCE)                
       {
        if(ACCOUNT_BALANCE < Ballance )                
        {
            CoofLot++;
            Lot = pow(2, CoofLot) * 0.01;
            if(nap == true)                            
               {
                nap = false;
               }
             else
               {
                nap = true;
               }
         }
         if(ACCOUNT_BALANCE > Ballance)                
           {
             Lot = 0.01;
             CoofLot = 0;
           }
       }
    Ballance = ACCOUNT_BALANCE;
    int order;
    if(nap == true)                                      
      {
         mrequest.action = TRADE_ACTION_DEAL;                                  // немедленное исполнение
         mrequest.price = NormalizeDouble(latest_price.ask,_Digits);           // последняя цена ask
         mrequest.sl = NormalizeDouble(latest_price.ask - 100*_Point,_Digits); // Stop Loss
         mrequest.tp = NormalizeDouble(latest_price.ask + 100*_Point,_Digits); // Take Profit
         mrequest.symbol = _Symbol;                                            // символ
         mrequest.volume = Lot;                                                // количество лотов для торговли
         mrequest.type = ORDER_TYPE_BUY;                                       // ордер на покупку
         mrequest.type_filling = ORDER_FILLING_FOK;                            // тип исполнения ордера - все или ничего
         mrequest.deviation=100;                                               // проскальзывание от текущей цены
         //--- отсылаем ордер

         order = OrderSend(mrequest,mresult);
      }                  
    else
      {
         mrequest.action = TRADE_ACTION_DEAL;                                  // немедленное исполнение
         mrequest.price = NormalizeDouble(latest_price.bid,_Digits);           // последняя цена Bid
         mrequest.sl = NormalizeDouble(latest_price.bid + 100*_Point,_Digits); // Stop Loss
         mrequest.tp = NormalizeDouble(latest_price.bid - 100*_Point,_Digits); // Take Profit
         mrequest.symbol = _Symbol;                                            // символ
         mrequest.volume = Lot;                                                // количество лотов для торговли
         mrequest.type= ORDER_TYPE_SELL;                                       // ордер на продажу
         mrequest.type_filling = ORDER_FILLING_FOK;                            // тип исполнения ордера - все или ничего
         mrequest.deviation=100;                                               // проскальзывание от текущей цены
         //--- отсылаем ордер

         order = OrderSend(mrequest,mresult);  
      }
      }
   return;
  }
 
DenZell:

Здравствуйте. Как то писал советник на MetaTraider 4. Вернее учился писать. Многое не умею и не знаю еще. И решил перенести его на MetaTraider 5 где немного оказалось все по другому. Вообщем брал другой советник. Разбирал его. Копировал код для открытия ставок. Вообщем ошибок вроде нету но работает не так как должно быть. Помогите перенести правильно. 


Код будет такой (но при этом будьте внимательны - здесь идёт проверка на общее количество позиций на торговом счёте (PositionsTotal):

   if(PositionsTotal()==0)

то есть нет проверки сколько именно позиций по данному символу и данному Magic (к слову сказать, Magic вообще не задан))

//+------------------------------------------------------------------+
//|                                                       TestEA.mq5 |
//|                              Copyright © 2016, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2016, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.00"
//---
double         Lot            = 0.01;
double         CoofLot        = 1.0;
double         loss           = 100.0;
bool           nap            = true;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   CoofLot  = 1.0;
   loss     = 100.0;
   nap      = true;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   static double         Balance=0.0;
   if(Balance==0.0)
      Balance=AccountInfoDouble(ACCOUNT_BALANCE);

   if(PositionsTotal()==0)
     {
      MqlTick latest_price;                        // Будет использоваться для текущих котировок
      if(!SymbolInfoTick(_Symbol,latest_price))
        {
         Alert("Ошибка получения последних котировок - ошибка:",GetLastError(),"!!");
         return;
        }

      if(Balance!=AccountInfoDouble(ACCOUNT_BALANCE))
        {
         if(AccountInfoDouble(ACCOUNT_BALANCE)<Balance)
           {
            CoofLot++;
            Lot=pow(2,CoofLot)*0.01;
            if(nap==true)
              {
               nap=false;
              }
            else
              {
               nap=true;
              }
           }
         if(AccountInfoDouble(ACCOUNT_BALANCE)>Balance)
           {
            Lot=0.01;
            CoofLot=1.0;
           }
        }
      Balance=AccountInfoDouble(ACCOUNT_BALANCE);

      MqlTradeRequest mrequest;   // Будет использоваться для отсылки торговых запросов
      MqlTradeResult mresult;
      ZeroMemory(mrequest);
      ZeroMemory(mresult);

      bool order=false;
      if(nap==true)
        {
         mrequest.action = TRADE_ACTION_DEAL;                                  // немедленное исполнение
         mrequest.price = NormalizeDouble(latest_price.ask,_Digits);           // последняя цена ask
         mrequest.sl = NormalizeDouble(latest_price.bid - 100*_Point,_Digits); // Stop Loss
         mrequest.tp = NormalizeDouble(latest_price.bid + 100*_Point,_Digits); // Take Profit
         mrequest.symbol = _Symbol;                                            // символ
         mrequest.volume = Lot;                                                // количество лотов для торговли
         mrequest.type = ORDER_TYPE_BUY;                                       // ордер на покупку
         mrequest.type_filling = ORDER_FILLING_FOK;                            // тип исполнения ордера - все или ничего
         mrequest.deviation=100;                                               // проскальзывание от текущей цены
         //--- отсылаем ордер

         order=OrderSend(mrequest,mresult);
        }
      else
        {
         mrequest.action = TRADE_ACTION_DEAL;                                  // немедленное исполнение
         mrequest.price = NormalizeDouble(latest_price.bid,_Digits);           // последняя цена Bid
         mrequest.sl = NormalizeDouble(latest_price.ask + 100*_Point,_Digits); // Stop Loss
         mrequest.tp = NormalizeDouble(latest_price.ask - 100*_Point,_Digits); // Take Profit
         mrequest.symbol = _Symbol;                                            // символ
         mrequest.volume = Lot;                                                // количество лотов для торговли
         mrequest.type= ORDER_TYPE_SELL;                                       // ордер на продажу
         mrequest.type_filling = ORDER_FILLING_FOK;                            // тип исполнения ордера - все или ничего
         mrequest.deviation=100;                                               // проскальзывание от текущей цены
         //--- отсылаем ордер

         order=OrderSend(mrequest,mresult);
        }
     }
   return;
  }
//+------------------------------------------------------------------+

Также результат операции OrderSend имеет тип bool.
 

Для хранения баланса я применил статическую переменную

   static double         Balance=0.0;
   if(Balance==0.0)
      Balance=AccountInfoDouble(ACCOUNT_BALANCE);

- то есть переменная "Balance" при последующих заходах в OnTick() не будет пересоздаваться заново, а она будет помнить своё значение с предыдущего тика.

Файлы:
TestEA.mq5  10 kb
 

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

//+------------------------------------------------------------------+
//|                                                       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
Приветствую! Пишу трейлинг, который проходится по барам начиная от времени входа в позицию...
Причина обращения: