Erros, bugs, perguntas - página 2377

 
Slava:
Sim. Qualquer impressão do OnInit

Obrigado. Interessante, se por acaso não me apercebi, como seria possível descobrir...


ZS deixá-lo-ia apenas para Agentes locais. Na Nuvem, pode facilmente fazer spam no registo desta forma.

 
fxsaber:

Obrigado. Interessante, se por acaso não me apercebi, como seria possível descobrir...


ZS deixá-lo-ia apenas para Agentes locais. Na Nuvem, pode facilmente fazer spam no registo desta forma.

Em Cloud, não vai aparecer. Porque não há razão para tal.
 
Slava:

Quando executa a genética, optimiza de acordo com o seu critério personalizado?

Com base nos registos apresentados, o OnTester devolveu 0 em todos os casos

Normalmente optimizo de acordo com o meu critério, mas aqui experimentei também o critério personalizado. O resultado é o mesmo.

OnTester devolve 0, é por isso que devolve zeros nos resultados - isso é compreensível. A questão é porque é que retorna "0" em execução geral (optimização) mas em execução única a partir de "resultados zero" (com os mesmos parâmetros) retorna resultado normal, gráfico, etc.? Ou seja, algo não está a funcionar em "Full overshoot" e, no entanto, a genética funciona bem. Algum outro pensamento/ideas?

 
Kuzmich:

Algum outro pensamento/ideas?

Puxar toda a informação de optimização passe desta forma

Fórum sobre comércio, sistemas automatizados de comércio e testes estratégicos

MT5. TESTADOR DE ESTRATÉGIA. Divergência dos resultados dos testes e da optimização.

fxsaber, 2017.08.22 11:06

Inserir estas linhas na EA

#define  REPORT_TESTER // В тестере будут автоматически записываться отчеты
#include <Report.mqh>

E executar Optimização. Em seguida, executar uma única corrida desencontrada.

Depois comparar os dois relatórios guardados da execução correspondente da Optimização e da execução única.

O resultado da comparação dos dois relatórios revelará rapidamente as causas.

 
No âmbito da familiarização com a funcionalidade Socket*, surgiram várias questões relativas à implementação actual.
O objectivo é melhorar o mais possível o que é feito, peço aos criadores que não se ofendam com possíveis críticas.



1. Não compreendo as razões para diferenças tão fortes em "interfaces" para funções de leitura de socket
: a) Para ligação encriptada existem duas funções para leitura, e para não encriptada - uma.
b) EmSocketRead
é necessário especificar explicitamente o
timeout_ms, e emSocketTlsRead eSocketTlsReadAvailable
não existe nenhum parâmetro deste tipo (definido pela função separada SocketTimeouts).
int  SocketTlsRead(int socket, uchar& buffer[], int buffer_maxlen);
int  SocketTlsReadAvailable(int socket, uchar& buffer[], int buffer_maxlen);

int  SocketRead(int socket, uchar& buffer[], int buffer_maxlen, uint timeout_ms);


2. O nome da função SocketIsReadable não tem nada a ver com o que ela realmente executa:

bool  SocketIsWritable(const int  socket); // Return true if writing is possible, otherwise false.
uint  SocketIsReadable(const int  socket); // Number of bytes that can be calculated. In case of an error, 0 is returned.
bool  SocketIsConnected(const int socket); // New function without description. May be, it returns true if connection is not closed.

De facto, SocketIsReadable é análogo à função ioctlsocket() com a bandeira FIONREAD em Ws2_32.dll


3. Como pode um utilizador que utiliza a funcionalidade Socket* através de uma ligação não encriptada obter uma resposta de um servidor com um atraso mínimo de tempo, se o servidor não interromper a ligação após a transferência de dados?

- A função SocketIsReadable sem usar explicitamente um atraso de tempo (por exemplo, sem dormir) retorna 0.
- a função SocketRead não sabe o quanto ler, especificabuffer_maxlen com uma reserva - terá de esperar portimeout_ms

Sim, é assim que é feito:

- esperar por 1 byte de dados em SocketRead;
- depois descobrir o tamanho de toda a resposta usando SocketIsReadable;
- ler o comprimento restante em SocketRead;
- fundir resultados através da cópia de matrizes:

#define  PRINT(x) Print(#x, ": ", string(x))
                
void OnStart() {
   string domain = "www.mql5.com";
   int port = 80;
 
   string request = "GET / HTTP/1.1\r\nHost: " + domain + "\r\n\r\n";
   char req[];
   
   int socket = SocketCreate();
   PRINT(SocketConnect(socket, domain, port, 5000));
   int len=StringToCharArray(request,req)-1;
   PRINT(SocketSend(socket,req,len));
   
   
   
   uchar resp[];
   uchar result[];
   
   int resp_result;
   uint resp_len;
   int start_write;
   
   
   resp_len = 1;
   resp_result = SocketRead(socket, resp, resp_len, 5000);
   if (resp_result <= 0){
      PRINT(GetLastError());
      return;
   }
   start_write = ArraySize(result);
   ArrayResize(result, start_write + resp_result);
   ArrayCopy(result, resp, start_write);
   
   
   resp_len = SocketIsReadable(socket);
   resp_result = SocketRead(socket, resp, resp_len, 5000);
   if (resp_result <= 0){
      PRINT(GetLastError());
      return;
   }
   start_write = ArraySize(result);
   ArrayResize(result, start_write + resp_result);
   ArrayCopy(result, resp, start_write);
   
   
   PRINT(CharArrayToString(result));
};

Isto não é demasiado código?


4. SocketIsReaditáveis devolve informações falsas.
Desligar a Internet e executar o código acima.
Como resultado, a SocketIsReadable devolve um valor razoável de 1. Maravilhas.


Consegui descrever cerca de um terço de todas as questões e problemas relacionados com a Socket*.
Infelizmente, precisei de muito tempo para verificar, descrever e verificar tudo de novo. (para que não seja um facto que haverá uma sequela)

A impressão geral é que ou tudo foi feito com muita pressa, ou a funcionalidade Socket* chegou ao revelador júnior.
Em qualquer caso, a solução actual é muito grosseira e cobre uma abordagem bastante restrita da utilização de tomadas.

 
MQL5\Inclua a análise de dados MQL5\AlgLib.mqh - CLinReg::LRLine não funciona para 1M ou mais valores?
 
Kuzmich:

Normalmente optimizo de acordo com os meus próprios critérios, mas aqui também experimentei os critérios padrão. O resultado é semelhante.

OnTester retorna 0, é por isso que há zeros nos resultados - isso é compreensível. A questão é porque é que retorna "0" em execução geral (optimização) mas em execução única a partir de "resultados zero" (com os mesmos parâmetros) retorna resultado normal, gráfico, etc.? Ou seja, algo não está a funcionar em "Full overshoot" e, no entanto, a genética funciona bem. Algum outro pensamento/ideas?

Pode partilhar uma EA (ex5 em condições privadas) e de optimização?

Queremos reproduzir o problema que mencionou.

Após a investigação, a EA será irrevogavelmente apagada

 
Slava:

Pode partilhar a EA (ex5 numa mensagem privada) e as condições de optimização?

Queremos reproduzir o problema que mencionou.

Após a investigação, a EA será irrevogavelmente apagada

Poderia olhar para a minha EA? Tenho um problema semelhante - o lucro não é contabilizado, consequentemente a optimização não funciona.
 
Slava:

Pode partilhar a EA (ex5 numa mensagem privada) e as condições de optimização?

Queremos reproduzir o problema que mencionou.

A EA será irremediavelmente apagada após a investigação

Respondido numa mensagem privada.

 
Sergey Dzyublik:
No âmbito da familiarização com a funcionalidade Socket*, surgiram algumas questões relativas à implementação actual.
O objectivo é melhorar o mais possível o que é feito, peço aos criadores que não se ofendam com possíveis críticas.



1. Não compreendo as razões para diferenças tão fortes em "interfaces" para funções de leitura de socket
: a) Para ligação encriptada existem duas funções para leitura, e para não encriptada - uma.
b) EmSocketRead
é necessário especificar explicitamente o
timeout_ms, e emSocketTlsRead eSocketTlsReadAvailable
não existe nenhum parâmetro deste tipo (definido pela função separada SocketTimeouts).


2. O nome da função SocketIsReadable não tem nada a ver com o que ela realmente executa:

De facto, SocketIsReadable é análogo à função ioctlsocket() com a bandeira FIONREAD em Ws2_32.dll


3. Como pode um utilizador que utiliza a funcionalidade Socket* através de uma ligação não encriptada obter uma resposta de um servidor com um atraso mínimo de tempo, se o servidor não interromper a ligação após a transferência de dados?

- SocketIsFunção legível sem uso explícito de tempo de atraso (por exemplo, sem dormir) retorna 0.
- A função SocketRead não sabe quanto ler, se especificarbuffer_maxlen com reserva - terá de esperar pelotimeout_ms

Sim, é assim que é feito:

- esperar por 1 byte de dados em SocketRead;
- depois descobrir o tamanho de toda a resposta usando SocketIsReadable;
- ler o comprimento restante em SocketRead;
- fundir resultados através da cópia de matrizes:

Isto não é demasiado código?


4. SocketIsReaditáveis devolve informações falsas.
Desligar a Internet e executar o código acima.
Como resultado, a SocketIsReadable devolve um valor razoável de 1. Maravilhas.


Consegui descrever cerca de um terço de todas as questões e problemas relacionados com a Socket*.
Infelizmente, precisei de muito tempo para verificar, descrever e verificar tudo de novo. (para que não seja um facto que haverá uma sequela)

A impressão geral é que ou tudo foi feito com muita pressa, ou a funcionalidade Socket* chegou ao revelador júnior.
Em qualquer caso, a solução actual é muito grosseira e cobre uma abordagem bastante restrita da utilização de tomadas.

1. esta é a interface.

As funções TLS são auxiliares para apoiar casos complexos. Não há problema com a definição de SocketTimeouts - estes são os melhores a utilizar.


2. desempenha a sua função correctamente.

Não deve estar consciente dos problemas com a detecção de quebra de ligação TCP. É bastante difícil (com recursos intensivos ao custo de chamadas extra) detectar que uma ligação é garantidamente interrompida correctamente. Todas as implementações de redes sofrem com este problema.

A nossa implementação de SocketIsReadible é suficientemente inteligente e tem um detector de ruptura. Quando detecta um byte 0 limpo, faz o trabalho extra de verificar se a tomada está completa:

   //+------------------------------------------------------------------+
   //| Доступно для чтения?                                             |
   //+------------------------------------------------------------------+
   UINT32 IsReadible(void)
     {
      unsigned long size=1;    // специально, чтобы убиться при попытке чтения, если сокет мертв
      //--- проверка
      if(m_socket!=INVALID_SOCKET)
        {
         //--- считаем количество доступных для чтения байт
         if(ioctlsocket(m_socket,FIONREAD,&size)!=0)
           {
            Close();
            return(1);        // вернем 1, чтобы убиться при попытке чтения
           }
         //--- если нет данных, проверим сокет на завершенность
         if(size==0)
           {
            timeval wait_time;
            fd_set  fd;
            //--- ждём
            FD_ZERO(&fd);
            FD_SET(m_socket,&fd);

            wait_time.tv_sec =0;          // секунды
            wait_time.tv_usec=1000;       // микросекунды
            //--- ждём
            if(select(0,&fd,NULL,NULL,&wait_time)>0)
               return(1);                 // вернем 1, чтобы убиться при попытке чтения
           }
        }
      //--- размер
      return(size);
     }

Uma vez que devolve o número de bytes sem uma bandeira de terminação, produz 1 byte para que uma tentativa de leitura posterior/iminente SocketRead normalmente devolva um erro.

Porque é que isto é correcto? Porque a maior parte do código é escrito por programadores desta forma:

if(SocketIsReadible(...)>0)
  {
   if(SocketRead( )<1)
     return(false);
   ...
  }
... уходим на следующий круг ожидания

o resultado real da operação é verificado numa tentativa de leitura directa.


3. precisa de fazer SocketIsReadible() antes da leitura propriamente dita, se não souber o tamanho exacto dos dados a serem lidos.

A ligação SocketisReadible/SocketRead dá-lhe a capacidade de não perder o controlo (minimizar a quase zero a perda de controlo) sobre o fluxo de execução do seu programa. Isto evita voar para dentro de timeouts de rede.

Sim, mais algumas linhas de código, mas não perderá o controlo durante um milissegundo(aproximadamente). Cabe-lhe a si decidir o que fazer nos intervalos de ausência de dados da rede.


4. Explicado no segundo parágrafo.

Emissão 1 por causa da leitura e do estímulo de saída como um erro de leitura.



As suas conclusões estão erradas.

Esta é a natureza do transporte TCP/IP, onde não existem quaisquer garantias. Também aí se pode entrar em buracos negros na rede em filtros/firewalls quando não há parte de sinalização TCP. O tempo limite bruto e o controlo do fluxo de dados permitem-lhe detectá-los e terminar as ligações você mesmo.

Demos uma interface de acesso bruto/directo a funções de rede, incluindo implementações de TLS. Se os utilizar, é você quem precisa de embrulhar correctamente as funções em bruto numa SocketIsReadible/SocketRead handleer segura/controlada.

Se quiser fazer pedidos de alto nível sem ter de pensar nas minúcias, existem as funções WebRequest. Todas as protecções são aí construídas.