Troca de dados entre dois EAs funcionando em terminais diferentes - página 3

 

Еще можно попробовать забить гвоздь лампочкой. У некоторых получается.

O que há de errado com esta abordagem?

Você também pode definir o tempo do sistema.

É assim que o tempo do sistema é sincronizado :-). Não através do ajuste, mas através da leitura. Este é um tipo de intercâmbio de dados.

 




Bom dia a todos!

Uma das melhores formas de conectar de forma confiável terminais parece ser o uso da rede 1C.
Duas características principais:
1. A aplicação principal é executada em 1C, os terminais e seus programas MQL4 são os executores,
2. A aplicação principal é executada em um dos terminais, a aplicação 1C é usada como um protocolo de conexão.

Vantagens:
1. A capacidade de armazenar e processar o histórico completo de cotações simultaneamente em diferentes servidores;
2

 
Andres >> :

Já escrevi uma pequena biblioteca e meus Conselheiros Especializados já estão mudando informações através do registro. Na verdade, eles são alterados através do registro, não vejo nenhuma operação de leitura-escrita em disco.


Obrigado por fornecer a biblioteca! Lidarei também com esta implementação de intercâmbio.

Há uma pergunta óbvia a ser feita imediatamente. Como você implementou a verificação dos parâmetros de leitura/gravação? Ou seja, como um outro EA sabe que um determinado parâmetro de uma chave já pode ser lido?

Você cria alguma chave adicional de permissão de leitura/escrita por outro EA ou há alguma outra característica que você testou? Isto é, em outras palavras, como você fornece acesso unitário a um parâmetro para que os EAs não trabalhem com o mesmo parâmetro-chave ao mesmo tempo para evitar falhas?

 

Eu meio que descobri como você fornece acesso unitário ao parâmetro-chave. Você simplesmente verifica a existência de erros usando a função GetErrorString( int ErrorCode).

E em caso de erro você deve repetir a operação. Mas ainda não entendi onde na biblioteca é realizada esta operação repetida. Talvez eu mesmo tivesse que acrescentar algo que seria necessário. De qualquer forma, obrigado pela boa solução!

 

Esta é uma embalagem simples em cima da API Win, com saída de erro que só permite trabalhar com parâmetros de chave de string.

GetErrorString( int ErrorCode ) é bastante indicativo, de modo que quando ocorrem erros, você sabe o que, onde, por que e como corrigi-los. Naturalmente, podemos e devemos colocar a manipulação de erros além dos limites das funções de embalagem e biblioteca, e reagir a eles de diferentes maneiras (há muitos tipos de erros), com base na lógica de utilização de chaves por vários especialistas. Enquanto isso, SetStringValue() em qualquer tentativa fracassada só pode lhe dizer que a tentativa fracassou. E GetStringValue(), em caso de falha, não só lhe dirá, mas também devolverá um fio vazio. Eu acho que não há necessidade de chave adicional de permissão de leitura/gravação, porque tais verificações são feitas pelo sistema operacional. O tratamento de erros e a resposta adequada ao erro são suficientes. Meus EAs para teste "quente" são simplesmente dessincronizados no tempo, provavelmente por isso não tiveram conflitos ao ler/escrever um campo ao mesmo tempo. Mas isto não é uma solução, é claro. Temos que seguir em frente. Mesmo assim, escrevi-o durante uma noite, não o julgue muito severamente. Uma espécie de versão "betta", a fim de sentir o método :-).

 
Andres >> :

Já escrevi uma pequena biblioteca, e meus EAs já estão mudando as informações através do registro. Na verdade, eles são trocados através da RAM, não há leitura-escrita em disco que eu não observe. No MSDN está escrito que é melhor não enfiar mais do que algumas centenas de Kb de dados no registro.

A biblioteca é configurada de tal forma, que todas as chaves e parâmetros são criados na área de registro temporário e não são escritos no registro permanente. Depois de reinicializar estas chaves, elas se foram.

MAS, a biblioteca funciona apenas com parâmetros de corda, com não mais de 255 caracteres (limitação em MQL). Mas isto é o suficiente. Em geral, os parâmetros no registro podem ser de diferentes tipos, não apenas strings, mas por enquanto outros tipos não são necessários na minha opinião. Neste momento tenho dois EAs trocados através do registro, mas mais podem ser necessários :-). Outra coisa boa é que em Win API é possível conectar-se ao registro da rede. Se alguém precisar trocar informações entre EAs rodando em computadores diferentes na mesma rede, pode olhar nesta direção. Na minha opinião, é rápido, simples e confiável, e sem nenhuma dll e arquivos. Insira uma corda, produza uma corda.

Andrey, obrigado!

Ligeiramente editado e aparado para mim.

Talvez você devesse colocar isto em seu mealheiro? Bastante, uma solução digna!

Arquivos anexados:
reglib.rar  11 kb
 

Um destes dias integrarei sua biblioteca, Andrey, com minha biblioteca para lidar com variáveis gráficas. Isso me dará mais um nível de declaração variável.

1. Haverá uma GlobalSuperVariable. Tal variável será visível em nível de SO.

2. Agora existe a GlobalVariable.

3. Há também o GlobalChartVariable. Eles são visíveis apenas para uma janela.

Em geral, deve produzir uma biblioteca para trabalhar com suas estruturas no nível do sistema operacional na MQL4.

 
Zhunko >> :

1. Haverá uma GlobalSuperVariable. Tal variável será visível em nível de SO.

Serei extremamente grato (e provavelmente não sou o único) se você carregar tal variável na kodobase.

Cansado de inventar com métodos homebreus.

 

Pergunta para Andrew. Este registro será transferido?

string GetStringValue1 (int    hKey,      // Код ключа реестра.
                        int    lpSize,    // Длина считываемой строки.
                        string ValueName) // Имя параметра ключа.
 {
  int lpType[1];      // Возвращаемый тип параметра.
  int lpcbData[1];    // Размер буфера.
  int i;              // Переменная для подрезки последних пустых строк.
  int lres;           // Результат.
  string lpData = ""; // Буфер для возвращаемой строки.
  //----
  lpcbData[0] = lpSize; // Размер буфера.
  for ( i = 0; i < lpSize; i++) lpData = lpData + "#";
  lres = RegQueryValueExA ( hKey, ValueName, 0, lpType, lpData, lpcbData); // вызов API
  // Теперь в lpcbData[0] размер скопированных байт. Проверяем результат.
  if ( lres != ERROR_SUCCESS)
   {
    Print ("Error in RegQueryValueExA(): ", GetErrorString ( lres));
    return ("");
   }
  if ( lpType[0] == REG_SZ || lpType[0] == REG_EXPAND_SZ) return (StringSubstr ( lpData, 0, lpcbData[0] - 1));
  return ("");
 }
 
Vou explicar. A questão é que, se você usar um cordão dinamicamente incrementado como um buffer, haverá alguns erros. Eu mesmo já tropecei em um antes:
InitRegDefines();
hKey = CreateKey( HKEY_CURRENT_USER, "!MT4TestKey" );

// заносим
SetStringValue( hKey, "Param", "Test" );

// вытаскиваем при помощи Вашей функции:
Print( GetStringValue1( hKey, 20, "Param" ) );

Depois disso, acontece:

2009.05.19 01:22:16 2008.12.31 01:49 temp EURUSD,M1: ####
2009.05.19 01:22:16 2008.12.31 01:49 temp EURUSD,M1: RegCreateKeyExA(): Foi criada uma divisória inexistente.
2009.05.19 01:22:16 temp começou os testes

Ou seja, o conteúdo do buffer não muda, embora não haja erros quando chamado. E é a linha "Teste" no registro.

Aprendi nas postagens do fórum que isso acontece por causa de alguma string estranha que passa do ambiente MQL para as funções DLL. No ambiente MQL os desenvolvedores operam com strings usando seu próprio gerente (string pool), e aparentemente nesta borda o buffer errado é preenchido e, portanto, não podemos ver o resultado retornado pela função API. Mas se usarmos cordas inicializadas em todo o comprimento máximo, então, até onde posso ver, não há problema. É por isso que a cadeia de 255 caracteres "#" está lá. O caracter "#" foi escolhido simplesmente para tornar a corda visível aos olhos. Não tem nada a ver com o próprio Win API, porque não importa com o que o buffer é preenchido antes da chamada. Esta é a limitação do comprimento das cordas que mencionei anteriormente. Você pode passar cordas com mais de 255 caracteres para SetStringValue(), mas não é possível lê-las.

É claro que é bom não ter limitações, mas não vejo como isso seja um grande inconveniente. Isso levanta a questão: por que você precisa ler um fio de um determinado tamanho? Se se tratar de restrições, você pode contorná-las escrevendo uma função que divide a cadeia de entrada em N parâmetros que são 255 de comprimento + parâmetro "restante". E quando o lê recolhe de volta. Não há outra maneira. Se você tiver dificuldade, por favor, entre em contato comigo, eu o farei. Apenas as necessidades de todos são diferentes, você não pode fornecer tudo, é suficiente para mim apenas isto, e alguém usa variáveis globais, e até mesmo em vários níveis.