Scambio di dati tra due EA in esecuzione su terminali diversi - pagina 3

 

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

Cosa c'è di sbagliato in questo approccio?

Potete anche impostare l'ora del sistema.

È così che il tempo del sistema è sincronizzato :-). Non attraverso l'ambientazione, ma attraverso la lettura. Questo è un tipo di scambio di dati.

 




Buongiorno a tutti!

Uno dei modi migliori per collegare in modo affidabile i terminali sembra essere l'uso della rete 1C.
Due caratteristiche principali:
1. L'applicazione principale viene eseguita su 1C, i terminali e i loro programmi MQL4 sono esecutori,
2. L'applicazione principale viene eseguita su uno dei terminali, l'applicazione 1C viene utilizzata come protocollo di collegamento.

Vantaggi:
1. La capacità di memorizzare ed elaborare la storia completa delle quotazioni contemporaneamente su diversi server;
2

 
Andres >> :

Ho già scritto una piccola libreria e i miei Expert Advisors stanno già cambiando le informazioni attraverso il registro. Infatti, vengono cambiati attraverso il registro, non vedo nessuna operazione di lettura-scrittura su disco.


Grazie per aver messo a disposizione la biblioteca! Mi occuperò anche di questa implementazione dello scambio.

C'è subito una domanda ovvia. Come avete implementato il controllo dei parametri di lettura/scrittura? Cioè, come fa un altro EA a sapere che un certo parametro di una chiave può già essere letto?

Crei qualche ulteriore chiave di permesso di lettura/scrittura da un altro EA o c'è qualche altra funzione che hai testato? Cioè, in altre parole, come si fornisce un accesso unitario a un parametro in modo che gli EA non lavorino con lo stesso parametro chiave allo stesso tempo per evitare fallimenti?

 

Ho più o meno capito come si fornisce un accesso unitario al parametro chiave. È sufficiente controllare gli errori usando la funzione stringa GetErrorString( int ErrorCode).

E in caso di errore è necessario ripetere l'operazione. Ma non ho capito dove nella libreria viene eseguita questa operazione ripetuta. Forse dovrei aggiungere io stesso qualcosa che sarebbe necessario. Comunque, grazie per la bella soluzione!

 

Questo è un semplice wrapper sopra l'API di Win, con output di errore che permette di lavorare solo con parametri chiave stringa.

GetErrorString( int ErrorCode ) è piuttosto indicativo, in modo che quando si verificano errori, si sa cosa, dove, perché e come risolverli. Naturalmente, possiamo e dobbiamo mettere la gestione degli errori oltre i confini delle funzioni wrapper e di libreria, e reagire ad essi in modi diversi (ci sono molti tipi di errori), in base alla logica di utilizzo delle chiavi da parte di vari esperti. Nel frattempo, SetStringValue() ad ogni tentativo fallito può solo dirvi che il tentativo è fallito. E GetStringValue(), in caso di fallimento, non solo ve lo dirà, ma restituirà anche una stringa vuota. Penso che non ci sia bisogno di un'ulteriore chiave di permesso di lettura/scrittura, perché tali controlli sono fatti dal sistema operativo. La gestione degli errori e la corretta risposta agli stessi sono sufficienti. I miei EA per il test "a caldo" sono semplicemente desincronizzati nel tempo, probabilmente è per questo che non hanno avuto conflitti quando hanno letto/scritto un campo allo stesso tempo. Ma questa non è una soluzione, ovviamente. Dobbiamo andare avanti. Eppure l'ho scritto in una notte, non giudicatelo troppo severamente. Una specie di versione "betta", per sentire il metodo :-).

 
Andres >> :

Ho già scritto una piccola libreria, e i miei EA stanno già cambiando le informazioni attraverso il registro. Infatti, sono cambiati attraverso la RAM, nessuna lettura/scrittura su disco che io osservi. In MSDN è scritto che è meglio non spingere i dati più di un paio di centinaia di Kb nel registro.

La libreria è configurata in modo tale che tutte le chiavi e i parametri sono creati nell'area temporanea del registro e non sono scritti nel registro permanente. Dopo il riavvio questi tasti sono spariti.

Un MA, la libreria funziona solo con parametri stringa, non più lunghi di 255 caratteri (limitazione in MQL). Ma questo è abbastanza. In generale i parametri nel registro possono essere di diversi tipi, non solo stringhe, ma per ora altri tipi non sono necessari secondo me. In questo momento ho due EA scambiati attraverso il registro, ma potrebbero essercene altri :-). Un'altra buona cosa è che in Win API è possibile connettersi al registro di rete. Se qualcuno ha bisogno di scambiare informazioni tra EA in esecuzione su diversi computer nella stessa rete, può guardare in questa direzione. A mio parere, è veloce, semplice e affidabile, e senza dll e file. Ingresso di una stringa, uscita di una stringa.

Andrey, grazie!

Leggermente modificato e tagliato per me.

Forse dovresti metterlo nel tuo salvadanaio? Abbastanza, una soluzione degna!

File:
reglib.rar  11 kb
 

Uno di questi giorni integrerò la tua libreria, Andrey, con la mia libreria per gestire le variabili grafiche. Mi darà un livello in più di dichiarazione delle variabili.

1. ci sarà una GlobalSuperVariable. Tale variabile sarà visibile a livello di OS.

2. Ora c'è GlobalVariable.

3. c'è anche GlobalChartVariable. Sono visibili solo per una finestra.

In generale, dovrebbe produrre una libreria per lavorare con le sue strutture a livello di sistema operativo in MQL4.

 
Zhunko >> :

1. ci sarà una GlobalSuperVariable. Tale variabile sarà visibile a livello di OS.

Vi sarò estremamente grato (e probabilmente non sono l'unico) se caricate una tale variabile nel kodobase.

Stanco di inventare con metodi casalinghi.

 

Domanda per Andrew. Questo registro verrà mantenuto?

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 ("");
 }
 
Vi spiegherò. Il fatto è che se usate una stringa a incremento dinamico come buffer, ci saranno degli errori. Io stesso mi sono imbattuto in uno di questi prima d'ora:
InitRegDefines();
hKey = CreateKey( HKEY_CURRENT_USER, "!MT4TestKey" );

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

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

Dopo di che si scopre:

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(): È stata creata una partizione inesistente.
2009.05.19 01:22:16 temp avviato per i test

Cioè, il contenuto del buffer non cambia, anche se non ci sono errori quando viene chiamato. Ed è la linea "Test" nel registro.

Ho imparato dai post del forum che succede a causa di qualche strano passaggio di stringhe dall'ambiente MQL alle funzioni DLL. Nell'ambiente MQL gli sviluppatori operano con le stringhe usando il proprio gestore (string pool), e apparentemente su questo confine il buffer sbagliato viene riempito e quindi non possiamo vedere il risultato restituito dalla funzione API. Ma se usiamo stringhe inizializzate all'intera lunghezza massima, allora, per quanto posso vedere, non ci sono problemi. Ecco perché la stringa "#" di 255 caratteri è lì. Il carattere "#" è stato scelto semplicemente per rendere la stringa visibile all'occhio. Non ha niente a che fare con l'API Win stessa, perché non importa con cosa sia riempito il buffer prima della chiamata. Questa è la limitazione della lunghezza delle stringhe che ho menzionato prima. Potete passare stringhe più lunghe di 255 caratteri a SetStringValue(), ma non è possibile leggerle.

Naturalmente è bene non avere limitazioni, ma non vedo come sia un grande inconveniente. Viene da chiedersi: perché avete bisogno di leggere una stringa di una data dimensione? Se si tratta di vincoli, puoi aggirarli scrivendo una funzione che divide la stringa di input in N parametri con lunghezza 255 + parametro "resto". E quando si legge lo raccoglie di nuovo. Non c'è altro modo. Se avete difficoltà, contattatemi, lo farò. Semplicemente le esigenze di ognuno sono diverse, non si può fornire tutto, è sufficiente per me solo questo, e qualcuno usa variabili globali, e anche a più livelli.