Erros, bugs, perguntas - página 540

 

O meu Conselheiro Especialista, que participa actualmente no Campeonato, está a realizar acções incorrectas devido ao funcionamento incorrecto da biblioteca padrão do CTrade.

Utilizo a função PositionClose para fechar posições. Mas, juntamente com as posições de fecho, esta função abre-se ela própria!

A função é utilizada desta forma:

//--- Объект класса СTrade
CTrade mytrade;
//--- Объект класса СPositionInfo
CPositionInfo myposition;

//+------------------------------------------------------------------+
//| Проверяет и если нужно, закрывает открытую позицию               |
//+------------------------------------------------------------------+
bool ClosePosition(string ptype,double clp)
  {
   bool R=false, marker=false; int i;
     
      if(myposition.Select(_Symbol)==true)
        {
         if(myposition.Symbol()==_Symbol)
           {
            //--- Делаем попытки закрыть позицию, если позиция не закрылась с первого раза
              for (i=5; i>=1; i--) 
                {R=mytrade.PositionClose(_Symbol,50,5); if (R == true && myposition.Select(_Symbol)==false) break;}
               if(i >= 1) 
                 {//--- запрос успешно выполнен
                  Alert("Открытая позиция была успешно закрыта!!");
                  marker=true;
                 }
               else
                 {
                  Alert("Запрос на закрытие позиции не выполнен - ошибка: ",mytrade.ResultRetcodeDescription());
                 }
            //  }
           }
        }
      return(marker);
     }

PositionClose acaba por abrir ordens por vezes desnecessárias.

Aqui, o comércio de Compra foi primeiro fechado e depois foi aberto um comércio extra de Venda do mesmo tamanho. Além disso, AccountInfoDouble(ACCOUNT_FREEMARGIN) não notou este comércio extra. Porque foi seguido por um comércio com lotes maiores, embora não houvesse dinheiro suficiente para isso, de acordo com o MM usado.

Percebo que talvez não esteja a utilizar as funções MQL de forma óptima. Mas o facto de que uma função na biblioteca proprietária da MQL destinada a fechar negócios abrirá negócios por si só não se enquadra na minha ideia do comportamento aceitável das funções.

 
masharov:

Compreendo que posso não estar a utilizar as funções MQL de forma óptima. Mas o facto de uma função de biblioteca proprietária da MQL destinada a fechar comércios abrir comércios por si só não se enquadra na minha ideia do comportamento aceitável das funções.

Leia o artigo Trading Events in MetaTrader 5:

Os eventos comerciais e mudanças no histórico comercial são relatados através de canais independentes. Ao enviar um pedido de compra utilizando a função OrderSend(), pode reconhecer imediatamente o bilhete da encomenda, que foi criado se o pedido tiver sido verificado com sucesso. Mas ao mesmo tempo, a ordem em si pode ainda não aparecer no terminal do cliente, e uma tentativa de a seleccionar utilizando a função OrderSelect() falhará.

Ver também o artigo Encomendas, Posições e Oportunidades no MetaTrader 5
 

Ainda não utilizei a função OrderSend. É utilizada a função PositionClose da biblioteca MQL padrão, que foi concebida para funcionar com encomendas.

A ajuda para esta função não descreve que ela possa abrir comércios.

Citação da referência:

PosiçãoFechar

Fecha uma posição no símbolo especificado.

bool PositionClose(
const string símbolo, // símbolo
ulong desvio=ULONG_MAX // desvio
)

Parâmetros

símbolo

[em] Nome do instrumento comercial, sobre o qual a posição deve ser encerrada.

desvio=ULONG_MAX

[em] Desvio máximo em relação ao preço actual (em pontos).

Valor devolvido

verdadeiro - se a verificação básica das estruturas for bem sucedida, caso contrário falsa.

Nota

O êxito do método PositionClose(...) nem sempre significa a execução bem sucedida de uma operação comercial. É necessário verificar o resultado de um pedido comercial (o código de retorno do servidor comercial), chamando o método ResultRetcode().

 
masharov:

Não utilizei a função OrderSend. É utilizada a função PositionClose da biblioteca MQL padrão, que foi concebida para simplificar o trabalho com encomendas.

A ajuda para esta função não descreve que ela possa abrir comércios.

Citação da referência:

PosiçãoFechar

Fecha uma posição no símbolo especificado.

bool PositionClose(
const string símbolo, // símbolo
ulong desvio=ULONG_MAX // desvio
)

Parâmetros

símbolo

[em] Nome do instrumento comercial, sobre o qual a posição deve ser encerrada.

desvio=ULONG_MAX

[em] Desvio máximo em relação ao preço actual (em pontos).

Valor devolvido

verdadeiro - se a verificação básica das estruturas for bem sucedida, caso contrário falsa.

Nota

O êxito do método PositionClose(...) nem sempre significa a execução bem sucedida de uma operação comercial. O resultado da execução do pedido de troca (o código de retorno do servidor de troca) deve ser verificado chamando o método ResultRetcode().

Não há erro na função da biblioteca PositionClose(...). Mas há um no seu código. Aqui está a citação da referência.

Успешное окончание работы метода PositionClose(...) не всегда означает успешное совершение торговой операции. 
Необходимо проверять результат выполнения торгового запроса (код возврата торгового сервера) вызовом метода ResultRetcode(). 

Eu, por exemplo, não vejo esta verificação no seu código.

 
masharov:

Não utilizei a função OrderSend. A função PositionClose da biblioteca MQL padrão, que foi concebida para funcionar com encomendas, é utilizada.

A ajuda para esta função não descreve que ela possa abrir comércios.


E pode ver a implementação da função PositionClose:

bool CTrade::PositionClose(const string symbol,ulong deviation)
  {
   bool   partial_close=false;
   int    retry_count  =10;
   uint   retcode      =TRADE_RETCODE_REJECT;
//--- check stopped
   if(IsStopped(__FUNCTION__)) return(false);
//--- variables
   string action,result;
//--- clean
   ClearStructures();
   do
     {
      //--- checking
      if(PositionSelect(symbol))
        {
         if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            //--- prepare request for close BUY position
            m_request.type =ORDER_TYPE_SELL;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID);
           }
         else
           {
            //--- prepare request for close SELL position
            m_request.type =ORDER_TYPE_BUY;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK);
           }
        }
      else
        {
         //--- position not found
         m_result.retcode=retcode;
         return(false);
        }
      //--- setting request
      m_request.action      =TRADE_ACTION_DEAL;
      m_request.symbol      =symbol;
      m_request.deviation   =(deviation==ULONG_MAX) ? m_deviation : deviation;
      m_request.type_filling=m_type_filling;
      m_request.volume      =PositionGetDouble(POSITION_VOLUME);
      //--- check volume
      double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
      if(m_request.volume>max_volume)
        {
         m_request.volume=max_volume;
         partial_close=true;
        }
      else
         partial_close=false;
      //--- order check
      if(!OrderCheck(m_request,m_check_result))
        {
         //--- copy return code
         m_result.retcode=m_check_result.retcode;
         if(m_log_level>LOG_LEVEL_NO)
            printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
         return(false);
        }
      //--- order send
      if(!OrderSend(m_request,m_result))
        {
         if(--retry_count!=0) continue;
         if(retcode==TRADE_RETCODE_DONE_PARTIAL)
            m_result.retcode=retcode;
         if(m_log_level>LOG_LEVEL_NO)
            printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
         return(false);
        }
      retcode=TRADE_RETCODE_DONE_PARTIAL;
      if(partial_close) Sleep(1000);
     }
   while(partial_close);
   if(m_log_level>LOG_LEVEL_ERRORS)
      printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
//--- ok
   return(true);
  }
 

Achei que não precisava de estudar o código fonte das bibliotecas padrão.

A ajuda não descreve a possibilidade de abrir negócios com a função PositionClose. As verificações e protecções contra a abertura de comércios com a função PositionClose, que a sua equipa desenvolveu, devem conter-se a si próprias. Acredito que as bibliotecas padrão são um código ideal que deve servir de modelo para outros. Por conseguinte, não deve ser necessário analisar o código das bibliotecas antes de as utilizar.

Citação:

A biblioteca MQL5 padrão é escrita em linguagem MQL5 e foi concebida para facilitar a escrita de programas (indicadores, scripts, peritos) aos utilizadores finais. A biblioteca fornece acesso fácil à maioria das funções internas da MQL5.

 
masharov:

Achei que não precisava de estudar o código fonte das bibliotecas padrão.

A ajuda não descreve a possibilidade de abrir negócios com a função PositionClose. As verificações e protecções contra a abertura de comércios com a função PositionClose, que a sua equipa desenvolveu, devem conter-se a si próprias. Acredito que as bibliotecas padrão são um código ideal que deve servir de modelo para outros. Por conseguinte, não deve ser exigida a análise do código das bibliotecas antes da sua utilização.

A ignorância da lei não o isenta de responsabilidade. Em que parte do seu código se encontra a verificação de que a posição foi fechada?

            //--- Делаем попытки закрыть позицию, если позиция не закрылась с первого раза
              for (i=5; i>=1; i--) 
                {
                 R=mytrade.PositionClose(_Symbol,50,5); 
                 if (R == true && myposition.Select(_Symbol)==false) break;
                }

Expressão

R == true

indica apenas que a função PositionClose() foi executada com sucesso, mas não que a posição foi fechada:

Nota

A conclusão bem sucedida do método PositionClose(...) nem sempre significa a execução bem sucedida de uma operação comercial. É necessário verificar o resultado da execução de um pedido comercial (código de retorno do servidor comercial), chamando o método ResultRetcode().

A segunda expressão

myposition.Select(_Symbol)==false)

é equivalente a

PositionSelect(_Symbol)==false)

e também não dá qualquer garantia para operações de comércio assíncrono. Uma posição já foi fechada no servidor comercial e o terminal ainda não recebeu uma mensagem sobre a mesma. Assim, acontece que criou um bug no seu código.

Na vida real, nem tudo é tão suave como no provador; pode haver pequenos atrasos entre o envio de um pedido comercial e o resultado da sua execução. Todos resolvem este problema sozinhos, para começar não faria mal verificar o código de retorno usando a função ResultRetcode(), tal como está escrito na ajuda.

 

Mais uma vez.

Percebo que talvez não esteja a utilizar as funções MQL de forma óptima. Mas o facto de uma função na biblioteca proprietária da MQL destinada afecharcomércios não se adequa à minha ideia do comportamento aceitável das funções.

Tudo o que disser aplica-se ao encerramento de negócios. Sim, a EA não verifica de forma óptima as posições de fecho. Mas isso não permite que uma função concebida para fechar os comércios abertos por si só.

A ajuda diz:

PosiçãoFechar

Fecha a posição de acordo com o símbolo especificado.

Não são descritas condições para que a função possa abrir uma troca. A recomendação de verificar o código de retorno também serve apenas para verificar adicionalmente se o comércio está fechado ou não.

 
masharov:

Mais uma vez.

Compreendo que posso não estar a utilizar as funções MQL de forma óptima. Mas o facto de a função na biblioteca proprietária da MQL destinada afechar comérciosabrir comércios por si só não se enquadra na minha ideia do comportamento aceitável das funções.
Não existe função de fecho de posição, existe apenas a função de enviar um pedido de compra ou venda (e qual será o resultado - abertura ou fecho de uma posição - é desconhecido). No seu caso, devido a um erro algorítmico, os pedidos repetidos são enviados sem verificar se o pedido anterior foi executado.
 
Rosh:
Não há função de fecho de posição, apenas a função de enviar um pedido de compra ou venda (e o resultado - a abertura ou fecho de uma posição - é desconhecido). No seu caso, devido a um erro algorítmico, os pedidos repetidos são enviados sem verificar se o pedido anterior foi executado.

A Ajuda tem esta função

Referência MQL5 / Biblioteca Standard / Classes de Negociação / CTrade / PositionClose

Fecha a posição por símbolo especificado.

O utilizador não deve preocupar-se com a forma como a função é implementada a um nível baixo. Uma vez que esta função existe, a MetaQuotes garantiu que não terá qualquer comportamento atípico não descrito na ajuda.

A biblioteca MQL5 padrão é escrita em MQL5 e destina-se a facilitar a escrita de programas (indicadores, scripts, e Expert Advisors) pelos utilizadores finais. A biblioteca fornece acesso fácil à maioria das funções internas da MQL5.

Razão: