Erros, bugs, perguntas - página 958

 
antt:

Transmitir parâmetros de entrada diferentes. Símbolo, período, parâmetros de entrada são os mesmos, indicador é o mesmo. O terminal tenta minimizar o consumo de recursos e, neste caso, não é criada uma nova cópia do indicador, ou seja, funciona efectivamente um programa mql5.

Por favor aconselhe também sobre esta simples questão: https://www.mql5.com/ru/forum/1111/page975#comment_469324 , porque ninguém sabe. )))

 

Por favor, ajude-me a corrigi-lo. No Testador de Estratégia tudo funciona perfeitamente, mas na demonstração RTS em m1 por vezes em vez de uma posição de 3 lotes envia 2 encomendas de 3 lotes cada, e a posição total de 6 lotes.

#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; //сбросим семафор, операция с ордером завершаена, можно открывать следующий ордер
      }    
  }
 
Talvez isto seja um bug) Ao iniciar o MT5, ao contrário do MT4, ao iniciar sem ligação a um servidor, a última autorização (login/password) não é carregada por alguma razão e precisa de ser autorizada novamente, a password e o login não são guardados neste caso. Qual poderá ser o problema?
 

É isto que a técnica chegou a- diferentes lucros ao mesmo tempo na mesma conta (era um dia de folga, cotações, preços de entrada, swaps - coincidem, só que o lucro não coincide)

A única diferença é que na primeira imagem o terminal está ligado através de senha de investimento e a optimização está em execução; a segunda imagem mostra o login através de senha comercial. E mesmo depois de reiniciar e actualizar o terminal, tudo permaneceu na mesma. Quando as cotações chegaram, tudo parecia normalizado

 
notused:

Foi a isto que a técnica chegou - lucros diferentes ao mesmo tempo na mesma conta (foi um dia de folga, cotações, preços de entrada, swaps - coincidem, só que o lucro não coincide)

A única diferença é que na primeira imagem o terminal está ligado através de senha de investimento e a optimização está em execução; a segunda imagem mostra o login através de senha comercial. E mesmo depois de reiniciar e actualizar o terminal, tudo permaneceu na mesma. Quando as cotações chegaram, tudo parecia normalizado

Aparentemente, as taxas cruzadas disponíveis para o terminal para o cálculo do lucro flutuante eram diferentes.
 
Rosh:
Aparentemente, as taxas cruzadas à disposição do terminal para o cálculo dos lucros flutuantes eram diferentes.
Aconteceu-me uma vez e pode não voltar a acontecer. Ou seja, não é de todo crítico. É por isso que não escrevi para o Service Desk. Só quero que saiba que o procedimento de cálculo do lucro/perda não é perfeito (por que são as taxas cruzadas diferentes, por exemplo?).
Документация по MQL5: Торговые функции / OrderCalcProfit
Документация по MQL5: Торговые функции / OrderCalcProfit
  • www.mql5.com
Торговые функции / OrderCalcProfit - Документация по MQL5
 

A cada dois minutos envia este "conjunto" de erros sobre o Sinal de Negociação. Como repará-lo?

 
Ou onde posso ir para erros de sinais de comércio?
 
kharti: Ou onde posso contactar sobre erros de sinais de comércio?
ServiceDesk (no seu perfil).
 
antt:

Transmitir parâmetros de entrada diferentes. Símbolo, ponto, parâmetros de entrada são os mesmos, o indicador é o mesmo. O terminal tenta minimizar o consumo de recursos e, neste caso, não é criada uma nova cópia do indicador, ou seja, um programa de mql5 funciona de facto.

Compreendo e lembro-me sobre a optimização do consumo de recursos, mas talvez juntamente com o símbolo, ponto, parâmetros de entrada devêssemos também verificar o nome curto do indicador? Se o programador definir claramente um nome curto único, ele compreende o que está a fazer, e precisa de uma cópia separada, mesmo que este indicador já exista no gráfico. Por exemplo, o indicador não tem quaisquer dados introduzidos, calcula automaticamente todos os dados iniciais na fase inicial, mas temos de forçar o utilizador a introduzir um parâmetro falso e lembrá-lo para não o introduzir noutro parâmetro.
Razão: