Exchanging data between two EAs running in different terminals - page 3

 

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

What's wrong with this approach?

You can also set the system time.

That's how the system time is synchronised :-). Not through setting, but through reading. This is a kind of data exchange.

 




Good day all!

One of the best ways to reliably connect terminals seems to be the use of network 1C.
Two main features:
1. The main application is executed on 1C, terminals and their MQL4 programs are the executors,
2. The main application is executed on one of the terminals, 1C application is used as a linking protocol.

Advantages:
1. The ability to store and process full quotes history simultaneously on different servers;
2

 
Andres >> :

I have already written a small library and my Expert Advisors are already changing information through the registry. In fact, they are changed through the register, I don't see any read-write operations on disk.


Thank you for providing the library! I will deal with this exchange implementation as well.

There is one obvious question right away. How have you implemented read/write parameter checking? That is, how does another EA know that a certain parameter of a key can already be read?

Do you create some additional read/write permission key by another EA or is there some other feature you have tested? That is, in other words, how do you provide unitary access to a parameter so that EAs don't work with the same key parameter at the same time to avoid failures?

 

I kind of figured out how you provide unitary access to the key parameter. You simply check for errors using the string GetErrorString( int ErrorCode) function.

And in case of error you must repeat the operation. But I haven't understood where in the library this repeated operation is performed. Perhaps I would have to add something that would be needed myself. Anyway, thanks for the nice solution!

 

This is a simple wrapper on top of the Win API, with error output that only allows you to work with string key parameters.

GetErrorString( int ErrorCode ) is rather indicative, so that when errors occur, you know what, where, why and how to fix it. Of course, we can and should put handling of errors beyond the boundaries of wrapper and library functions, and react to them in different ways (there are many types of errors), based on the logic of using keys by various experts. Meanwhile, SetStringValue() at any failed attempt can only tell you that the attempt failed. And GetStringValue(), in case of failure, will not only tell you, but also return an empty string. I think there is no need for additional read/write permission key, because such checks are done by OS. Error handling and proper error response is sufficient. My EAs for "hot" test are simply desynchronized in time, that's probably why they didn't have conflicts when reading/writing one field at the same time. But this is not a solution, of course. We need to move on. Still I wrote it during one night, don't judge it too severely. Kind of "betta" version, to feel the method :-).

 
Andres >> :

I have already written a small library, and my EAs are already changing information through the registry. In fact, they are changed through the RAM, no read-write to disk I do not observe. In MSDN it is written that it is better not to shove data more than a couple hundred Kb into the registry.

Library is configured in such a way, that all keys and parameters are created in temporary registry area and are not written in permanent registry. After rebooting these keys are gone.

One BUT, the library works only with string parameters, not more than 255 characters long (limitation in MQL). But this is quite enough. In general the parameters in the registry may be of different types, not just strings, but for now other types are not needed in my opinion. Right now I have two EAs exchanged through the registry, but more may be needed :-). Another good thing is that in Win API it is possible to connect to network registry. If someone needs to exchange information between EAs running on different computers in the same network, they can look in this direction. In my opinion, it is quick, simple and reliable, and without any dlls and files. Input a string, output a string.

Andrey, thank you!

Slightly edited and trimmed it for me.

Maybe you should put this in your piggy bank? Quite, a worthy solution!

Files:
reglib.rar  11 kb
 

One of these days I will integrate your library, Andrey, with my library to handle graphical variables. It will give me one more level of variable declaration.

1. there will be a GlobalSuperVariable. Such a variable will be visible at OS level.

2. There is GlobalVariable now.

3. there is also GlobalChartVariable. They are visible only for one window.

In general, it should produce a library for working with its structures at the operating system level in MQL4.

 
Zhunko >> :

1. there will be a GlobalSuperVariable. Such variable will be visible at OS level.

I will be extremely grateful (and probably I'm not the only one) if you upload such a variable to the kodobase.

I'm tired of making it up with homebrew methods.

 

Question for Andrew. Will this registry carry over?

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 ("");
 }
 
I'll explain. The thing is, if you use a dynamically incrementing string as a buffer, there will be some errors. I've stumbled across one myself before:
InitRegDefines();
hKey = CreateKey( HKEY_CURRENT_USER, "!MT4TestKey" );

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

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

After that it turns out:

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(): A non-existing partition was created.
2009.05.19 01:22:16 temp started for testing

That is, the contents of the buffer don't change, although there are no errors when called. And it is the "Test" line in the registry.

I've learned from forum posts that it happens because of some strange string passing from MQL environment to DLL functions. In MQL environment the developers operate with strings using their own manager (string pool), and apparently on this border the wrong buffer is filled and therefore we can't see the result returned by API-function. But if we use strings initialized to the whole maximum length, then, as far as I can see, there's no problem. That's why the 255 character "#" string is there. The "#" character was chosen simply to make the string visible to the eye. It has nothing to do with the Win API itself, because it doesn't matter what the buffer is filled with before the call. This is the string length limitation I mentioned earlier. You can pass strings longer than 255 characters to SetStringValue(), but it's not possible to read them.

Of course it is good to have no limitations, but I don't see how it is a great inconvenience. It begs the question: why do you need to read a string of a given size? If it's about constraints, you can get around them by writing a function which splits input string into N parameters which are 255 long + "remainder" parameter. And when reading it gathers it back. There is no other way. If you have difficulty, please contact me, I will do it. Just everyone's needs are different, you can not provide everything, it is enough for me only this, and someone uses global variables, and even at several levels.

Reason: