Советник не открывает ордера на демо, а в тестере открывает. Где ошибка?

 

Всем привет! Есть советник. В тестее работает, в рельном времени нет. Пробовал на демо 5 лотом форекс фо ю при демо-депо 10000. Т.е. денег хватает для открытия. Но пишет ошибку неправильного лота. Ломаю голову второй день. Вроде нигде ошибки нету. помогите пжс. Вот код и индикатор необходимый советнику

Сова:

#include <stderror.mqh>



extern string    name             = "EA"; // это будет в комментариях к открытому ордеру
extern string    txxt             = "Параметры торговли";
extern double    Lots             = 0.01; // торговый лот
extern int       TakeProfit       = 350;
extern int       slippage         = 3; // проскальзывание
extern int       magic1           = 316497; // магик
extern int       Retry            = 10; // Количество попыток открытия ордера
extern bool      IncreaseLot      = true;
extern double    LotFactor        = 1.5;
extern double    MaxLot           = 0.1;
extern string    SettingStop      = "Настройки Cтоп-лосса";
extern int       CandleForLow     = 100;  // количество свечей назад, из которых находится самая маленькая цена
extern int       CandleForHigh    = 100;  // количество свечей назад, из которых находится самая большая цена
extern int       DeltaStopLoss    = 10; // это значение отнимаем/прибавляем к свече для успешной установки стоп-лосса.
extern bool      ExitCross        = true; // выход по противоположному сигналу
extern string    SettingBez       = "Настройки безубытка";
extern bool      Bezubytok        = false;
extern int       LevelForNewStopLoss  = 60; // уровень, когда включается безубыток
extern int       NewStopLoss          = 10;      // уровень, на который устанавливается безубыток
extern string    SettingWATRS     = "Настройки WATRs";
extern string    SettingWATR_1TF  = "WATR";
extern int       TF_1_WATR        = 0;
extern int       WATR_K           = 50;
extern double    WATR_M           = 8.0;
extern int       ATR              = 21;



//**************объявление этих, как их....
double sl,tp,pos,watrblue0tfbuy, watrblue0tfsell,watrblue2tfbuy,slforbuy,slforsell,watrred3,watrblue3,Lot;
int ticket,ticket2, candlelow,candlehigh,total;
//**************************************
int init()

//жжжжжжжжжжжжжж     УЧИТЫВАЕМ, СКОЛЬКО ЗНАКОВ ПОСЛЕ ЗАПЯТОЙ   жжжжжжжжжжжжжжжжжжжжжжжжжжжжж
  {
   if(Digits==5 || Digits==3)
     {
      DeltaStopLoss        *=10;
      slippage             *=10;
      LevelForNewStopLoss  *=10;
      NewStopLoss          *=10;
      TakeProfit           *=10;
     }
   return(0);
  }

int deinit()
  {
   return(0);
  }

int start()
  {
// Загружаем данные из ВАТР для текущего ТФ
         watrblue0tfbuy  = iCustom (Symbol(),TF_1_WATR,"WATR",WATR_K,WATR_M,ATR,0,1);
         watrblue0tfsell = iCustom (Symbol(),TF_1_WATR,"WATR",WATR_K,WATR_M,ATR,1,1);
         
// Загружаем данные из ВАТР для 3 бара - для условий чтоб не октрывалось много ордеров а только в начале сигналов 
         watrred3  = iCustom (Symbol(),TF_1_WATR,"WATR",WATR_K,WATR_M,ATR,0,3);
         watrblue3   = iCustom (Symbol(),TF_1_WATR,"WATR",WATR_K,WATR_M,ATR,1,3);
// Загружаем данные из ВАТР для старшего ТФ
         

// На какой свече макс/мин значения

   candlelow     = iLowest  (Symbol(),0,MODE_CLOSE,CandleForLow,0);
   candlehigh    = iHighest (Symbol(),0,MODE_CLOSE,CandleForHigh,0);

   slforbuy   = Low  [candlelow];
   slforsell  = High [candlehigh];

      if (Bezubytok == true)
      
  {  NewStopLosskBuy(); // зайдействуем безубыток для БАЙ ордеров
     NewStopLosskSell(); } // зайдействуем безубыток для СЕЛЛ ордеров
 //==========================================================================
 if (ExitCross == true)
 {
 CloseSellCross();
 CloseBuyCross();
 }
//===============Вычисление рабочего лота============================ 
 total = OrdersHistoryTotal();
 if (IncreaseLot == true && total > 0)
 {
// int total = OrdersHistoryTotal();
 // if(total > 0) 
     
       OrderSelect(ticket, SELECT_BY_TICKET, MODE_HISTORY); //Выбираем предыдущий ордер из истории.
       if(OrderProfit() <= 0) 
       {
          Lot = NormalizeDouble(OrderLots()*LotFactor,2);
          if ( Lot > MaxLot) Lot = MaxLot;
       }
       if(OrderProfit() > 0)
       {
       Lot = Lots; 
       }
     }
 if (total == 0)   
 {
 Lot = Lots;  
 }
 
 if (IncreaseLot == false) 
 
 {
 Lot = Lots;
 }  
   
 Print ("Lots: " + Lots);

//жжжжжжжжжжжжж УСЛОВИЯ ПЕРВОЙ ПРОДАЖИ жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

   if(CountSell()==0 && CountBuy()==0 && Bid < watrblue0tfsell && Bid < watrred3 && watrred3 < 10000)

     {
      sl=NormalizeDouble(slforsell+(DeltaStopLoss*Point),Digits); // делаем стоп лосс в выражении цены
      tp=NormalizeDouble(Bid - (TakeProfit*Point),Digits); // то же с тейком
      ticket=OrderSendX(Symbol(),OP_SELL,Lot,Bid,slippage,0,0,name,magic1,0,Red); // открываем первый ордер

      if(ticket>0) // если ордер открыт удачно
        {
         if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)==true) // выбираем этот ордер для модицикации
           {
            OrderModifyX(ticket,OrderOpenPrice(),sl,tp,0); // модифицируем СЛ и ТП для ЕСН счетов
           }
        }
     }

//жжжжжжжжжжжжжжжжжжж    УСЛОВИЯ ДЛЯ ПЕРВОЙ ПОКУПКИ   жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж

   if(CountBuy()==0 && CountSell()==0 && Ask > watrblue0tfbuy && Ask > watrblue3)

     {
      sl=NormalizeDouble(slforbuy -(DeltaStopLoss*Point),Digits); // делаем стоп лосс в выражении цены
      tp=NormalizeDouble(Ask + (TakeProfit*Point),Digits); // то же с тейком
      ticket=OrderSendX(Symbol(),OP_BUY,Lot,Ask,slippage,0,0,name,magic1,0,Red);
      // модифицикация открытого ордера
      if(ticket>0) // если ордер установился
        {
         if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)==true) // выбираем ордер для модицикации
           {

            OrderModifyX(ticket,OrderOpenPrice(),sl,tp,0); // модифицируем СЛ и ТП для ЕСН счетов

           }
        }
     }    
   return(0);
  }
//жжжжжжжжжжжжжжжжж   ПЕРЕСЧИТЫВАЕМ ОРДЕРА БАЙ жжжжжжжжжжжжжжжжжжжжжжж

int CountBuy()
  {
   int count=0;
   for(int trade=OrdersTotal()-1;trade>=0; trade--)
     {
      OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic1)
        {
         if(OrderType()==OP_BUY)
            count++;
        }
     }
   return(count);
  }
//жжжжжжжжжжжжжж   СЧИТАЕМ ОРДЕРА СЕЛЛ   жжжжжжжжжжжжжжжжжжжжж 

int CountSell()
  {
   int count=0;
   for(int trade=OrdersTotal()-1;trade>=0; trade--)
     {
      OrderSelect(trade,SELECT_BY_POS,MODE_TRADES);
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic1)
        {
         if(OrderType()==OP_SELL)
            count++;
        }
     }
   return(count);
  }
// ========Функция безубытка для БАЙ ордера 
void NewStopLosskBuy()
  {
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic1)
           {
            if(OrderType()==OP_BUY)
              {
               if(OrderStopLoss()<OrderOpenPrice())
                 {
                  double PriceForNewStopLoss=NormalizeDouble(OrderOpenPrice()+LevelForNewStopLoss*Point,Digits);
                 
                  if(OrderOpenPrice()<PriceForNewStopLoss)
                    {

                     if(Ask>=PriceForNewStopLoss)
                       {
                        double SLBuy=NormalizeDouble(OrderOpenPrice()+NewStopLoss*Point,Digits);
                      

                        if(OrderMagicNumber()==magic1)
                          {

                           OrderModify(OrderTicket(),OrderOpenPrice(),SLBuy,tp,0,Magenta);
                          }
                       }
                    }
                 }
              }
           }
        }
     }
  }
// ========Функция безубытка для СЕЛЛ ордера                   

void NewStopLosskSell()
  {
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic1)
           {
            if(OrderType()==OP_SELL)
              {
               if(OrderStopLoss()>OrderOpenPrice())
                 {
                  double PriceForNewStopLoss=NormalizeDouble(OrderOpenPrice()-LevelForNewStopLoss*Point,Digits);
               
                  if(OrderOpenPrice()>PriceForNewStopLoss)
                    {

                     if(Bid<=PriceForNewStopLoss)
                       {
                        double SLBuy=NormalizeDouble(OrderOpenPrice()-NewStopLoss*Point,Digits);
                       

                        if(OrderMagicNumber()==magic1)
                          {

                           OrderModifyX(OrderTicket(),OrderOpenPrice(),SLBuy,tp,0,Magenta);
                          }
                       }
                    }
                 }
              }
           }
        }
     }
  }
//=======ФУНКЦИЯ МОДИФИКАЦИИ ОРДЕРА С ЗАЩИТОЙ ==========

bool OrderModifyX(int ticket,double price,double stoploss,double takeprofit,
                  datetime expiration,color arrow_color=CLR_NONE)

  {
   if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
     {
      price=NormalizeDouble(price,Digits);
      stoploss=NormalizeDouble(stoploss,Digits);
      takeprofit=NormalizeDouble(takeprofit,Digits);
      CheckValidStop(Symbol(),price,stoploss);

      bool  result;
      int err=GetLastError();
      err=0;

      // int Retry = 10;
      int cnt=0;
      bool exit_loop=false;

      while(!exit_loop)
        {
         // result = OrderModify(ticket, price, stoploss,takeprofit,expiration, arrow_color);
         result=OrderModify(ticket,price,stoploss,takeprofit,expiration,arrow_color);
         err=GetLastError();

         if(result==true)
           {
            Print("Ордер #"+ticket+" успешно модифицирован");

            //exit_loop = true;
            return(true);
           }
         switch(err)
           {

            case ERR_NO_ERROR: exit_loop=true;break;
            case ERR_SERVER_BUSY:
            case ERR_NO_CONNECTION:
            case ERR_INVALID_PRICE:
            case ERR_OFF_QUOTES:
            case ERR_BROKER_BUSY:
            case ERR_TRADE_CONTEXT_BUSY:
               cnt++;
               break;
            case ERR_INVALID_PRICE:
            case ERR_PRICE_CHANGED:
            case ERR_OFF_QUOTES:
            case ERR_REQUOTE:
               RefreshRates();
               continue;
            default: exit_loop=true; break;
           }
        }

      if(err!=ERR_NO_ERROR)
        {
         Print("Ошибка модификации ордера #"+ticket);
         Print("Код ошибки: "+err);

        }

     }
   else
     {
      Print("Не удалось выбрать ордер, ticket = "+ticket);
      return(false);

     }

  }
//==========вторая часть функции модификации=
void  CheckValidStop(string symbol,double price,double &sl)

  {
   if(sl==0)
      return;
   double servers_min_stop=MarketInfo(symbol,MODE_STOPLEVEL)*MarketInfo(symbol,MODE_POINT);

   if(MathAbs(price-sl)<=servers_min_stop)
     {

      if(price>sl)
         sl=price-servers_min_stop;
      else sl=sl+servers_min_stop;

     }

   sl=NormalizeDouble(sl,MarketInfo(symbol,MODE_DIGITS));

  }
  //--------Функция ордер сенд с обработкой ошибок============

int OrderSendX(string symbol,int cmd,double volume,
               double price,int slippage,double stoploss,
               double takeprofit,string comment,int magic=0,
               datetime expiration=0,color arrow_color=CLR_NONE)

  {
   int err=GetLastError();
   err=0;
   bool exit_loop=false;
   int ticket=-1;

// int Retry = 10;
   int cnt=0;

   if(cmd==OP_SELL || cmd==OP_BUY)
     {
      while(!exit_loop)
        {
         ticket=OrderSend(symbol,cmd,volume,price,slippage,stoploss,
                          takeprofit,comment,magic,expiration,arrow_color);
         err=GetLastError();

         switch(err)
           {

            case ERR_NO_ERROR: exit_loop=true;break;
            case ERR_SERVER_BUSY:
            case ERR_NO_CONNECTION:
            case ERR_INVALID_PRICE:
            case ERR_OFF_QUOTES:
            case ERR_BROKER_BUSY:
            case ERR_TRADE_CONTEXT_BUSY:
               cnt++;
               break;
            case ERR_INVALID_PRICE:
            case ERR_PRICE_CHANGED:
            case ERR_OFF_QUOTES:
            case ERR_REQUOTE:
               RefreshRates();
               continue;
            default: exit_loop=true; break;
           }
         if(cnt>Retry)
            exit_loop=true;

         if(!exit_loop)
           {
            Sleep(1000);
            RefreshRates();

           }
         else
           {
            if(err!=ERR_NO_ERROR)
              {
               Print("Ошибка: "+err);
              }

           }
         if(err==ERR_NO_ERROR)
           {
            OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);
            return(ticket);
           }
         Print("Ошибка открытия ордера после "+cnt+" попыток");
         return(-1);
        }
     }
  }
  //=================================================
  //**********Функция закрытия БАЙ ордера по противоположному сигналу
void CloseBuyCross()
  {
   if(CountBuy() > 0 && Bid < watrblue0tfsell && Bid < watrred3 && watrred3 < 10000) //&& Bid < watrblue1tfblue && watrblue1tfblue < 10000) 
     {
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic1 && OrderType()==OP_BUY)
        {
         if(OrderSelect(OrderTicket(),SELECT_BY_TICKET,MODE_TRADES)==true)
            OrderClose(OrderTicket(),OrderLots(),Ask,10000,Yellow);

        }
     }
  }
//**********Функция закрытия CЕЛЛ ордера по противоположному сигналу

      void CloseSellCross()
  {
    if(CountSell() > 0 && Ask > watrblue0tfbuy && Ask > watrblue3) // && Ask > watrblue1tfcoral)

     {
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic1 && OrderType()==OP_SELL)
        {
         if(OrderSelect(OrderTicket(),SELECT_BY_TICKET,MODE_TRADES)==true)
            OrderClose(OrderTicket(),OrderLots(),Bid,10000,Yellow);
        }
     }
  }

Во вложении индикатор

Файлы:
watr.mq4  6 kb
 
Lots = 0.1 и все запашет.
 
TheXpert:
Lots = 0.1 и все запашет.

так он сейчас на демо стоит 5, чем он отличается от 0,1
 

Если хотите знать техническую причину: на "нулевом" счёте (на котором ещё не торговали) этот код будет работать. Тестер тому прямое подтверждение. А если на счёте торговали, то советник вычисляет лот равный 0 - а такого не может быть, потому, что "не может быть никогда". Глобальная переменная ticket = 0, а значит, нет возможности узнать лот предыдущего ордера.

Половинчатое решение может быть таким (замените блок "Вычисление рабочего лота"):

    total = OrdersHistoryTotal();
    if (IncreaseLot && total > 0)
    {
        if (OrderSelect (ticket, SELECT_BY_TICKET, MODE_HISTORY)) //Выбираем предыдущий ордер из истории.
        {
            if (OrderProfit() <= 0) 
            {
                Lot = NormalizeDouble(OrderLots()*LotFactor,2);
                if ( Lot > MaxLot) Lot = MaxLot;
            }
            if (OrderProfit() > 0) {Lot = Lots;}
        }
        else {Lot = Lots;}
    }
    if (total == 0) {Lot = Lots;}
    if (!IncreaseLot) {Lot = Lots;}

P.S. Удачи. (камикадзе она не помешает). :)))

 
TarasBY:

Если хотите знать техническую причину: на "нулевом" счёте (на котором ещё не торговали) этот код будет работать. Тестер тому прямое подтверждение. А если на счёте торговали, то советник вычисляет лот равный 0 - а такого не может быть, потому, что "не может быть никогда". Глобальная переменная ticket = 0, а значит, нет возможности узнать лот предыдущего ордера.

Половинчатое решение может быть таким (замените блок "Вычисление рабочего лота"):

P.S. Удачи. (камикадзе она не помешает). :)))


А Вам ничего не говорит, что расчет лота будет выполняться если только уже есть закрытый какой то ордер: total > 0 - т.е. если !total > 0 - то счет нулевой то сразу идем на if (total == 0) {Lot = Lots;}
 
remon:

А Вам ничего не говорит, что total > 0 - т.е. если счет нулевой то сразу идем на if (total == 0) {Lot = Lots;}

И где Вы видите противоречие тому, что я сказал???

На счёте, на котором ранее проводились торговые операции (как вариант: перезагрузка этого советника после торговли), total > 0. А при первой загрузке (или перезагрузке) советника глобальная переменная ticket = 0.

 

А ещё: никогда не помешает делать нормализацию лота (хотя бы простейшую):

//+------------------------------------------------------------------+
double Normalize_Lot(double lot)// Проверка на допустимое значение лота
//+------------------------------------------------------------------+
{
    double lot_min = MarketInfo(Symbol(), MODE_MINLOT);
    double lot_max = MarketInfo(Symbol(), MODE_MAXLOT);
    double lot_step = MarketInfo(Symbol(), MODE_LOTSTEP);
    if ( lot <= lot_min ) lot = lot_min; // минимальный
    else if ( lot >= lot_max ) lot = lot_max; // максимальный
    else lot = MathFloor( lot / lot_step ) * lot_step ; // округление до ближайшего меньшего
    return(lot);
}
 
TarasBY:

А ещё: никогда не помешает делать нормализацию лота (хотя бы простейшую):



Спасибо. Нормализация будет внутри автолота. Проблема была пока в этих открытиях. Пока не знаю стал открывать или нет. Не было еще условий
Причина обращения: