Ошибки, баги, вопросы - страница 958

 
antt:

Передавать разные input параметры. Символ, период, входные параметры совпадают, индикатор тот же самый. Терминал старается минимизировать потребление ресурсов и в данном случае новая копия индикатора не создается, т.е. фактически работает одна mql5 программа.

Подскажите, пожалуйста, и по этому простому вопросу: https://www.mql5.com/ru/forum/1111/page975#comment_469324 , а то никто не знает. )))

 

Помогите поправить. В тестере все идеально работает, а вот на демке на РТС на м1 иногда вместо позиции лотом 3, отправляет 2 ордера по 3 лота, и суммарно имеем позицию в 6 лотов.

  

#property copyright "Copyright 2013, DKeN"
#property link      ""
#property version   "1.00"
/*
1 Название: Параболик
2 Терминал: МТ5
3​ Рабочий инструмент: любой инструмент и период
4​ Индикатор: параболик
5​ Правила:
 при пересечение входим в направлении пересечения по рынку , 
 профит делим на 3 части , при закрытие первого выставляем стоп в ноль или чуть в плюс, 
 если профит не достигнут, а цена ушла в минус переворачиваем позицию при пересечении параболика…
6​ второй вариант: при пересечение входим в направлении пересечения по рынку , профит делим на 2 части , при закрытие первой части вторую оставляем до пересечения параболика
7​ настройки: а) к-во лотов
б) индикатор
в) время работы
8. возможность работы по нескольким инструментам на одном счете

если торгуем на РТС необходимо строго со спецификацией инструмента данные задавать!

*/
input string comment="";
//комментарий к ордеру
input int    slippage=10; 
//проскальзывание
input double lot=3;
//рабочий лот позиции
input int    takeprofit=200;
//тейк профит основной позиции
input int    stoploss=1000;
//стоп лосс основной позиции
input int    mode=1;
/*режим выхода 1 или 2*/
input int    takeprofit1=100;
//точка закрытия первой части профита в пунктах
input double lot1=1;
//объем закрываемой части ордера
input double bu1=10; 
//для режима 1, пренос в безубыток +1
input int    takeprofit2=150;
//точка закрытия второй части профита в пунктах
input double lot2=1;
//объем закрываемой позиции

input ENUM_TIMEFRAMES tf=0; 
//период, 0 - по умолчанию с графика текущий
input double step=0.02;
input double maximum=0.2;
//настрйоки для сар step,maximum
input string times="00:00-24:00";
//поддерживаются интервалы через , например 00:00-12:00, 16:00-20:00 и т.д. поддержка ночного перехода например 22:00-05:00
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int psar=-1;
ulong semafor=0;

int OnInit()
  {
//---
   psar=iSAR(NULL,tf,step,maximum);
   if(psar==INVALID_HANDLE){
       PrintFormat("Не удалось создать хэндл индикатора iSAR для пары %s/%s, код ошибки %d", _Symbol, EnumToString(_Period),GetLastError());
       return (-1);
   }    
   semafor=0;
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   if(psar!=INVALID_HANDLE) IndicatorRelease(psar);
   Comment("");
   
  }
  
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
     
   bool bWork=time_check(times);
   Comment("Торговый интервал времени");
   if(!bWork)Comment("Неторговый интервал времени. Разрешено закрытие по обратному сигналу и частичное закрытие. Открытие новых сделок запрещено.");
   double sar[],dLot,open,stop,take;
   
   ENUM_POSITION_TYPE type;
   ArraySetAsSeries(sar,true);  
   string n=_Symbol;
   
   if(CopyBuffer(psar,0,0,2,sar)>=0){     
      //1 - предыдущее значение
      //0 - текущий бар
      MqlRates rates[];
      MqlTick tick;
      
      ArraySetAsSeries(rates,true);
      int op=0;
      
      if(CopyRates(NULL,tf,0,2,rates)>0){
         
         if(SymbolInfoTick(n,tick)){
            if(tick.bid<sar[1] && sar[1]<rates[0].open) op=-1;
            else if(tick.ask>sar[1] && sar[1]>rates[0].open) op=1;
         }
                 
         //првоерим если позиции в рынке нет, попробуем открыть по сигналу
         if(!PositionSelect(n)) {
            order_OrderDeleteAll(n); //удалим отложки
            
            if(op==0) return; //сигнала нет!   
            
            if(bWork){
               if(op==1) order_OrderSend(n,ORDER_TYPE_BUY,lot,0,stoploss,takeprofit,comment);
               if(op==-1) order_OrderSend(n,ORDER_TYPE_SELL,lot,0,stoploss,takeprofit,comment);
            }
            
         }else{
            type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            dLot=PositionGetDouble(POSITION_VOLUME);
            
            if(dLot==lot){
                  int orders[];
                  int all=order_OrdersTotal(n,orders);
                  
                  open=PositionGetDouble(POSITION_PRICE_OPEN);
                  
                  if(type==POSITION_TYPE_BUY && orders[ORDER_TYPE_SELL_LIMIT]==0){
                     if(mode==2 || mode==1)order_OrderSend(n,ORDER_TYPE_SELL_LIMIT,lot1,open+takeprofit1*_Point,0,0,"");
                     if(mode==1)order_OrderSend(n,ORDER_TYPE_SELL_LIMIT,lot2,open+takeprofit2*_Point,0,0,"");
                  }
                  
                  if(type==POSITION_TYPE_SELL && orders[ORDER_TYPE_BUY_LIMIT]==0){
                     if(mode==2 || mode==1)order_OrderSend(n,ORDER_TYPE_BUY_LIMIT,lot1,open-takeprofit1*_Point,0,0,"");
                     if(mode==1)order_OrderSend(n,ORDER_TYPE_BUY_LIMIT,lot2,open-takeprofit2*_Point,0,0,"");
                  }
                  
            }else if(dLot<lot && mode==1){
               open=PositionGetDouble(POSITION_PRICE_OPEN);
               stop=PositionGetDouble(POSITION_SL);
               take=PositionGetDouble(POSITION_TP);
               
               if(type==POSITION_TYPE_BUY && (stop<open || stop==0.0)) order_OrderModify(n,open+bu1*_Point,take);
               if(type==POSITION_TYPE_SELL && (stop>open || stop==0.0)) order_OrderModify(n,open-bu1*_Point,take);
            }
            
            //Print(GetLastError()," op=",op," type=",type);           
            if(op==0) return;
            //позиция к этому моменту могла быть уже закрыта, перепроверим и проверим ее лот и тип
            if(PositionSelect(n)){
               type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
               dLot=PositionGetDouble(POSITION_VOLUME);
               //осуществим переворот, да так чтобы закрыть остаток и открыть начальным лотом
               if(type==POSITION_TYPE_BUY && op==-1) {
                  order_OrderDeleteAll(n); //удалим отложки
                  order_OrderSend(n,ORDER_TYPE_SELL,dLot,0,0,0,comment);
               }else if(type==POSITION_TYPE_SELL && op==1) {
                  order_OrderDeleteAll(n); //удалим отложки
                  order_OrderSend(n,ORDER_TYPE_BUY,dLot,0,0,0,comment);
               }
            }
            
         }
      }
     
   }
   
  }
//+------------------------------------------------------------------+
bool order_OrderModify(string name,double sl,double tp){
/* 
SL & TP Modification
Торговый приказ на модификацию уровней StopLoss и/или TakeProfit. Требуется указание 4 полей:
action 
symbol 
sl 
tp 
*/
   MqlTradeRequest  rq={0};      // структура запроса
   MqlTradeResult   rs={0};    
   
   rq.action=TRADE_ACTION_SLTP; 
   rq.symbol=name;
   rq.sl=sl;
   rq.tp=tp;
   
   return (OrderSend(rq,rs)); 
}
bool order_OrderSend(string name,ENUM_ORDER_TYPE type,double dlot,double open,double sl,double tp,string cmt){
   MqlTradeRequest  rq={0};      // структура запроса
   MqlTradeResult   rs={0};    
   MqlTick tick={0};
   MqlTradeCheckResult cr={0};    
   if(PositionSelect(name)) semafor=0;
   
   if(semafor>0) return (false);
   
   if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_SELL){
      
      
         
      rq.action=TRADE_ACTION_DEAL;
      rq.symbol=name;
      rq.volume=NLot(name,dlot);
      rq.type=type;
      
      bool ntick=SymbolInfoTick(name,tick);
      
      if(open<=0){
         if(type==ORDER_TYPE_BUY) rq.price=tick.ask;
         else if(type==ORDER_TYPE_SELL) rq.price=tick.bid;
      }else{
         rq.price=open; //если цена указана явно, то откроем по цене+проскальзывание
      }
      
      rq.sl=0;
      rq.tp=0;
      //выставим стоп
      if(sl>0 && type==ORDER_TYPE_BUY) rq.sl=NormalizeDouble(rq.price-sl*_Point,_Digits);
      else if(sl>0 && type==ORDER_TYPE_SELL) rq.sl=NormalizeDouble(rq.price+sl*_Point,_Digits);
      //выставим тейк
      if(tp>0 && type==ORDER_TYPE_BUY) rq.tp=NormalizeDouble(rq.price+tp*_Point,_Digits);
      else if(tp>0 && type==ORDER_TYPE_SELL) rq.tp=NormalizeDouble(rq.price-tp*_Point,_Digits);
      
      rq.deviation=slippage;//допустимое проскальзывание
      rq.type_filling=ORDER_FILLING_FOK;
   
      rq.comment=cmt;
   }else{
      
      
      rq.action=TRADE_ACTION_PENDING;
      rq.symbol=name;
      rq.volume=NLot(name,dlot);
      rq.type=type;
      rq.deviation=slippage;//допустимое проскальзывание
      rq.type_time=ORDER_TIME_DAY;
//ORDER_TIME_GTC; //ордер будет до снятия его программно или вручную

      //bool ntick=SymbolInfoTick(name,tick);
      
      rq.price=open; 
      
      rq.sl=sl; //должна быть ценой!
      rq.tp=tp;
      rq.type_filling=ORDER_FILLING_RETURN;

      rq.comment=cmt;
   }
   
      
   if(OrderCheck(rq,cr)){
         
            if(OrderSend(rq,rs)){
               if(rs.retcode!=TRADE_RETCODE_DONE && rs.retcode!=TRADE_RETCODE_PLACED){
                  Comment("Debug: order_OrderSend(retcode=",ResultRetcodeDescription(cr.retcode),")");
               }
                  
               semafor=rs.deal;
                   
               if(rs.retcode==TRADE_RETCODE_DONE || rs.retcode==TRADE_RETCODE_PLACED){
                  
                       
                  if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_SELL){
                     rq.action= TRADE_ACTION_SLTP; 
                     rq.order= rs.order;
           
                     return (OrderSend(rq,rs)); 
                  }
               }
               
               return (true);
            }
            
         
   }else{   
         semafor=0;
         Comment("Debug: order_OrderSend(retcode=",ResultRetcodeDescription(cr.retcode),")");
   }
   
   
   return (false);
   
}
/*удаляет отложки*/
bool order_OrderDeleteAll(string name){
   ulong ticket;
   MqlTradeRequest rq={0};
   MqlTradeResult rs={0};
   
   for(int i=OrdersTotal()-1;i>=0;i--){
      
      if((ticket=OrderGetTicket(i))>0){
         ZeroMemory(rq);
         ZeroMemory(rs);
         rq.action=TRADE_ACTION_REMOVE;
         rq.order=ticket;
         
         OrderSend(rq,rs);
      }
   }
   
   return (false);
}

int order_OrdersTotal(string name,int &orders[]){
   ulong ticket;
   int total=0;
   ArrayResize(orders,10,0);
   ArrayInitialize(orders,0);
//--- пройдем по всем отложенным ордерам
   for(int i=OrdersTotal()-1;i>=0;i--)
      if((ticket=OrderGetTicket(i))>0)
         if(OrderGetString(ORDER_SYMBOL)==name){
             orders[(int)OrderGetInteger(ORDER_TYPE)]++;
             total++;
         }    
//---
   return(total);
  }


//+------------------------------------------------------------------+ 
//| возврат стрингового результата торговой операции по его коду     | 
//+------------------------------------------------------------------+ 
string ResultRetcodeDescription(int retcode) 
  { 
   string str; 
//---- 
   switch(retcode) 
     { 
      case TRADE_RETCODE_REQUOTE: str="Реквота"; break; 
      case TRADE_RETCODE_REJECT: str="Запрос отвергнут"; break; 
      case TRADE_RETCODE_CANCEL: str="Запрос отменен трейдером"; break; 
      case TRADE_RETCODE_PLACED: str="Ордер размещен"; break; 
      case TRADE_RETCODE_DONE: str="Заявка выполнена"; break; 
      case TRADE_RETCODE_DONE_PARTIAL: str="Заявка выполнена частично"; break; 
      case TRADE_RETCODE_ERROR: str="Ошибка обработки запроса"; break; 
      case TRADE_RETCODE_TIMEOUT: str="Запрос отменен по истечению времени";break; 
      case TRADE_RETCODE_INVALID: str="Неправильный запрос"; break; 
      case TRADE_RETCODE_INVALID_VOLUME: str="Неправильный объем в запросе"; break; 
      case TRADE_RETCODE_INVALID_PRICE: str="Неправильная цена в запросе"; break; 
      case TRADE_RETCODE_INVALID_STOPS: str="Неправильные стопы в запросе"; break; 
      case TRADE_RETCODE_TRADE_DISABLED: str="Торговля запрещена"; break; 
      case TRADE_RETCODE_MARKET_CLOSED: str="Рынок закрыт"; break; 
      case TRADE_RETCODE_NO_MONEY: str="Нет достаточных денежных средств для выполнения запроса"; break; 
      case TRADE_RETCODE_PRICE_CHANGED: str="Цены изменились"; break; 
      case TRADE_RETCODE_PRICE_OFF: str="Отсутствуют котировки для обработки запроса"; break; 
      case TRADE_RETCODE_INVALID_EXPIRATION: str="Неверная дата истечения ордера в запросе"; break; 
      case TRADE_RETCODE_ORDER_CHANGED: str="Состояние ордера изменилось"; break; 
      case TRADE_RETCODE_TOO_MANY_REQUESTS: str="Слишком частые запросы"; break; 
      case TRADE_RETCODE_NO_CHANGES: str="В запросе нет изменений"; break; 
      case TRADE_RETCODE_SERVER_DISABLES_AT: str="Автотрейдинг запрещен сервером"; break; 
      case TRADE_RETCODE_CLIENT_DISABLES_AT: str="Автотрейдинг запрещен клиентским терминалом"; break; 
      case TRADE_RETCODE_LOCKED: str="Запрос заблокирован для обработки"; break; 
      case TRADE_RETCODE_FROZEN: str="Ордер или позиция заморожены"; break; 
      case TRADE_RETCODE_INVALID_FILL: str="Указан неподдерживаемый тип исполнения ордера по остатку "; break; 
      case TRADE_RETCODE_CONNECTION: str="Нет соединения с торговым сервером"; break; 
      case TRADE_RETCODE_ONLY_REAL: str="Операция разрешена только для реальных счетов"; break; 
      case TRADE_RETCODE_LIMIT_ORDERS: str="Достигнут лимит на количество отложенных ордеров"; break; 
      case TRADE_RETCODE_LIMIT_VOLUME: str="Достигнут лимит на объем ордеров и позиций для данного символа"; break; 
      default: str="Неизвестный результат"; 
     } 
//---- 
   return(str); 
  } 
  
  double NLot(string name,double dlot){
      double stepLot=SymbolInfoDouble(name,SYMBOL_VOLUME_STEP);
      
      return (MathFloor(dlot/stepLot)*stepLot);
  }
  
  bool time_check(string timeList){
      //разделим строку на подстроки (разделитель , )
      ushort usep1=StringGetCharacter(",",0);
      ushort usep2=StringGetCharacter("-",0);
      ushort usep3=StringGetCharacter(":",0);
      string param[],param2[],param3[],param4[];
      long start_hour=0,start_minute=0,start_seconds=0;
      long end_hour=0,end_minute=0,end_seconds=0;
      datetime start_tm=0,end_tm=0,tm[];
      ArrayInitialize(tm,0);
      ArraySetAsSeries(tm,true);
      CopyTime(_Symbol,PERIOD_D1,0,2,tm);
      MqlDateTime dt={0};
      TimeToStruct(TimeCurrent(),dt);
      
      int c=StringSplit(timeList,usep1,param);
      if(c<0) return (true);//диапозон не задан, можно торговать весь день
      for(int i=0;i<c;i++){
         StringTrimRight(param[i]);
         StringTrimLeft(param[i]);
         
         if(StringSplit(param[i],usep2,param2)==2){
            StringTrimRight(param2[0]);
            StringTrimLeft(param2[0]);
            StringTrimRight(param2[1]);
            StringTrimLeft(param2[1]);
            //удалили возможные лишние пробелы, теперь у нас есть время начала и окончания
            //разделим на чч.мм.сс
            if(StringSplit(param2[0],usep3,param3)>=1){
            //время начала
               start_hour=StringToInteger(param3[0]);
               if(ArraySize(param3)>=2) start_minute=StringToInteger(param3[1]);
               if(ArraySize(param3)==3) start_seconds=StringToInteger(param3[2]);
            }
            if(StringSplit(param2[1],usep3,param4)>=1){
            //время окончания
               end_hour=StringToInteger(param4[0]);
               if(ArraySize(param4)>=2) end_minute=StringToInteger(param4[1]);
               if(ArraySize(param4)==3) end_seconds=StringToInteger(param4[2]);
            }
            
            if(start_hour<=end_hour){
               start_tm=(datetime)(tm[0]+start_hour*3600+start_minute*60+start_seconds);
               end_tm=(datetime)(tm[0]+end_hour*3600+end_minute*60+end_seconds);
            }else{
               if(dt.hour>=0 && dt.hour<start_hour){
                  start_tm=(datetime)(tm[1]+start_hour*3600+start_minute*60+start_seconds);
                  end_tm=(datetime)(tm[0]+end_hour*3600+end_minute*60+end_seconds);
               }
               if(dt.hour>0 && dt.hour>=start_hour){
                  start_tm=(datetime)(tm[0]+start_hour*3600+start_minute*60+start_seconds);
                  end_tm=(datetime)(tm[0]+24*3600+end_hour*3600+end_minute*60+end_seconds);
               }
            }
            
            if(TimeCurrent()>=start_tm && TimeCurrent()<=end_tm)  return (true);
              
         }
         
      }
      
      return (false);    
  }
  
  void OnTrade(){
      
      if(semafor>0){
          PrintFormat("Открыт ордер %d",semafor);
          semafor=0; //сбросим семафор, операция с ордером завершаена, можно открывать следующий ордер
      }    
  }
 
Возможно это баг) При запуске MT5, в отличие от MT4, при запуске без подключения к серверу, последняя авторизация (логин/пароль) почему-то не загружается и требуется опять авторизоваться, пароль и логин не сохраняются при этом. В чем может быть проблема?
 

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

 

Отличие только в том, что на первом рисунке терминал залогинен через инвест-пароль и запущен процес оптимизации; на втором рисунке - логин через торговый пароль. Причём даже после перезапуска и обновлений терминалов - всё осталось по прежнему. Когда пошли котировки, вроде всё нормализовалось

 
notused:

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

 Отличие только в том, что на первом рисунке терминал залогинен через инвест-пароль и запущен процес оптимизации; на втором рисунке - логин через торговый пароль. Причём даже после перезапуска и обновлений терминалов - всё осталось по прежнему. Когда пошли котировки, вроде всё нормализовалось

Видимо, отличались доступные для терминала значения кросс-курсов для вычисления плавающей прибыли.
 
Rosh:
Видимо, отличались доступные для терминала значения кросс-курсов для вычисления плавающей прибыли.
У меня это было один раз и может больше и не повторится. Т. е., вообще не критично. Потому и в сервис-деск не писал. Просто довожу к сведению, что процедура вычисления прибыли\убытков - не идеальна (почему кросс-курсы разные, например?)
Документация по MQL5: Торговые функции / OrderCalcProfit
Документация по MQL5: Торговые функции / OrderCalcProfit
  • www.mql5.com
Торговые функции / OrderCalcProfit - Документация по MQL5
 

Через каждые две минуты вот такой "набор" ошибок посылает по Торговому сигналу. Как исправить?

 

 
Или куда можно обратиться по поводу ошибок торговых сигналов?
 
kharti: Или куда можно обратиться по поводу ошибок торговых сигналов?
 В СервисДеск (в Вашем профиле).
 
antt:

Передавать разные input параметры. Символ, период, входные параметры совпадают, индикатор тот же самый. Терминал старается минимизировать потребление ресурсов и в данном случае новая копия индикатора не создается, т.е. фактически работает одна mql5 программа.

Я понимаю и помню про оптимизацию потребления ресурсов, но может быть вместе с символом, периодом, входными параметрами проверять еще и короткое имя индикатора? Если программист явно задает уникальное короткое имя то он понимает, что делает и ему нужна отдельная копия даже если такой индикатор уже есть на чарте. Например индикатор вообще без входных данных, все начальные данные он вычисляет автоматически на начальном этапе, но нужно заставлять пользователя вводить фейковый параметр и помнить его чтоб не ввести в другом.
Причина обращения: