Il mio approccio. Il nucleo è il motore. - pagina 124

 
Andrey Barinov:

Perché invece di OrderOpenPrice metti OrderOpenTime()

Giusto. Ho fatto confusione. :)

 
Реter Konow:

Devo ammettere che sono rimasto un po' sorpreso dai risultati del test.

Ecco perché volevo che faceste tutto da soli, non dare soluzioni preconfezionate che avrebbero colpito il muro.
Sai, Peter, c'è anche una caratteristica come il puntatore a una funzione, grazie alla quale puoi organizzare le chiamate di funzione semplicemente prendendo questi puntatori da un array di tali puntatori. Penso che questo sarebbe molto utile nel vostro compito. L'unico problema è che devi incasinare di nuovo le classi.
 
Nikolai Semko:
Per questo volevo che faceste tutto da soli, non dare soluzioni preconfezionate, che sono come piselli contro il muro.
E sai, Peter, c'è anche una cosa come un puntatore a una funzione, grazie al quale puoi organizzare le chiamate di funzione semplicemente prendendo questi puntatori da un array di tali puntatori. Penso che questo sarebbe molto utile per il tuo problema. Ma ecco il problema: devi affrontare di nuovo le classi.

Ho sentito parlare di puntatori a funzioni. Ma ho pochissime funzioni. È per questo che non ho spazio e ho bisogno di usare OOP.

Ho un concetto di sviluppo diverso. Credo che il funzionamento di blocchi olistici multifunzione sia più efficiente di quello di grandi complessi di piccole funzioni.

Più promettente, dal punto di vista dello sviluppo dei meccanismi.

Questa è la mia opinione...

Ho diversi grandi blocchi. Per applicare l'OOP, bisogna scomporli in piccole funzioni, organizzarli in classi, e poi, usare puntatori e altre cose.

Ma non sarò in grado di farlo. Semplicemente perché la penso diversamente.

Il concetto di OOP non coincide con le peculiarità del mio modo di pensare, e non posso espandermi in esso. Questo è il motivo.

 
Nikolai Semko:

Nota, Nikolai, che in materia di sviluppo programmatico, non ho alcun problema. Tutto si sta sviluppando molto rapidamente.

Allo stesso tempo, i meccanismi funzionano bene.

Ora ho imparato a padroneggiare le unioni, e vedo la loro applicazione in un compito particolare: scrivere stringhe in una risorsa.

Proverò a controllare la velocità e il carico della CPU nell'EA di prova e posterò il risultato.

Se è buono, ricostruirò la comunicazione tra motore e EA, rendendola su risorse.

 

Per usare le risorse per passare stringhe di lunghezza non definita, queste stringhe devono essere scritte in un array di char.

Tuttavia, sembra che la loro dimensione sia dichiarata solo all'interno dell'unione e non cambi dopo.

Ho provato a ridimensionare l'array di char dall'unione, attraverso ArrayResize, ma non c'è alcun effetto.

Sembra che la dimensione dell'array di char debba essere impostata in anticipo. E dovrebbe essere di dimensioni massime.


Ecco il codice:

//+------------------------------------------------------------------+
//|                                                       TEST_2.mq4 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
union Char_Uint
  {
   uchar   Char[4];
   uint    Uint[1];   
  };
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   EventSetMillisecondTimer(1000);
   //----------------------------------------------
   if(!ObjectCreate(0,"Resource",OBJ_BITMAP_LABEL,0,0,0))Print("Object is not created!  ",GetLastError());
   else Print("Object created!");
   //-------------------------------
   if(!ObjectSetString(0,"Resource",OBJPROP_BMPFILE,"::Resource"))Print("BMPFILE is not created!");
   else Print("BMPFILE created!");
   //----------------------------------------------
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   Char_Uint u;
   string String = NULL;
   int q = MathRand();
   if(q > 10000)q = 10000;
   //-------------------------------------------------------
   //Формируем случайную строку.
   //-------------------------------------------------------
   for(int a1 = 0; a1 < q; a1++)String += (string)a1 + "^";
   //-------------------------------------------------------
   //Получаем размер собранной строки.
   //-------------------------------------------------------
   int StrSize = StringLen(String);
   //-------------------------------------------------------
   //Меняем размер массива из Char[] юниона. 
   //-------------------------------------------------------
   ArrayResize(u.Char,StrSize);
   //-------------------------------------------------------
   //Копируем строку в массив Char[].
   //-------------------------------------------------------
   //StringToCharArray(String,u.Char);
   //-------------------------------------------------------
   //
   //-------------------------------------------------------
   Print("StrSize  ",StrSize," Размер u.Char  ",ArraySize(u.Char));
  }
//+------------------------------------------------------------------+
 

Ora è chiaro che la dimensione dell'array dichar nell' unione deve essere conosciuta in anticipo. PerchéArrayResize(u.Char,StrSize) non lo cambia.

Quindi dobbiamo impostare la dimensione dell'array uguale alla lunghezza della stringa massima...

 

Buone notizie. Tutto funziona bene.

La stringa viene scritta nella risorsa e letta da un altro EA su un altro grafico.

Non c'è carico sul processore. Il carico è causato solo dalla chiamata dell'Alert che stampa la stringa.

Ecco il codice di Expert Advisors:

1. Expert Advisor forma la stringa e la scrive in una risorsa.

//+------------------------------------------------------------------+
//|                                                       TEST_2.mq4 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
union Char_Uint
  {
   uchar   Char[32000];
   uint    Uint[8000];   
  };
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   EventSetMillisecondTimer(16);
   //----------------------------------------------
   if(!ObjectCreate(0,"Resource",OBJ_BITMAP_LABEL,0,0,0))Print("Object is not created!  ",GetLastError());
   else Print("Object created!");
   //-------------------------------
   if(!ObjectSetString(0,"Resource",OBJPROP_BMPFILE,"::Resource"))Print("BMPFILE is not created!");
   else Print("BMPFILE created!");
   //----------------------------------------------
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   Char_Uint u;
   string String = NULL;
   int q = MathRand(),width,height;
   if(q > 1000)q = 1000;
   //-------------------------------------------------------
   //Формируем случайную строку.
   //-------------------------------------------------------
   for(int a1 = 0; a1 < q; a1++)String += (string)a1 + "^";
   //-------------------------------------------------------
   //Получаем размер собранной строки.
   //-------------------------------------------------------
   int StrSize = StringLen(String);
   //-------------------------------------------------------
   //Копируем строку в массив Char[].
   //-------------------------------------------------------
   StringToCharArray(String,u.Char);
   //-------------------------------------------------------
   //Cохраняем строку переведенную в байты в ресурсе.
   //-------------------------------------------------------
   if(!ResourceCreate("::Resource",u.Uint,8000,1,0,0,0,COLOR_FORMAT_XRGB_NOALPHA))Print("Resource is not created!");
   //-------------------------------------------------------
  }
//+------------------------------------------------------------------+
 

Un consulente che legge una linea da una risorsa su un altro grafico:

//+------------------------------------------------------------------+
//|                                              Resource reader.mq4 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

//+------------------------------------------------------------------+
union Char_Uint
  {
   uchar   Char[32000];
   uint    Uint[8000];   
  };
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   EventSetMillisecondTimer(16); 
   
   if(!ObjectSetString(0,"Resource",OBJPROP_BMPFILE,"\\Experts\\TEST_2.ex4::Resource"))Print("Resource is not connected!");
   else Print("Resource connected!");
//---
   return(INIT_SUCCEEDED);
  }


//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   Char_Uint u;   
   uint width,height;
   //string Message; 
   //-----------------------------
   if(!ResourceReadImage("\\Experts\\TEST_2.ex4::Resource",u.Uint,width,height))Print("Failed to read resource!  ",GetLastError());
   //-----------------------------
   string String = CharArrayToString(u.Char);
   //-----------------------------
   Alert("  String  ",String);
   //-----------------------------
  }
//+------------------------------------------------------------------+


Userà le risorse per la comunicazione. L'unico inconveniente è che dovete impostare la dimensione massima dell'array di char nell'unione. Ma non c'è bisogno di pensare alla dimensione della stringa e al numero di oggetti MT.

Questo metodo è più lento del metodo di collegamento MT-object, ma va bene.

 
Реter Konow:

Hai una teoria interessante, anche se non corrisponde del tutto ai risultati dei miei esperimenti, che ora posterò qui sotto.

Come mostra il test, è l'inizializzazione dell'array di pixel che carica maggiormente la CPU.

Guarda il test EA qui sotto.

Rileggete il compito:

Vasiliy Sokolov:

Peter, ecco il compito. Creare un pannello che mostri le attuali aperture degli ordini in MT4. Non è necessario fare una copia completa del pannello del sistema, basta fare una semplice tabella con le proprietà di base degli ordini aperti: prezzo aperto, direzione, profitto. Il resto dipende da voi. La cosa principale è che quando un ordine viene chiuso, anche la sua indicazione nella tua tabella scompare. E viceversa, apparirebbe in questa tabella quando viene aperto un nuovo ordine.

Qui potete vedere le due operazioni necessarie di ridisegno quando la tabella cambia sullo schermo: 1. quando si chiude un trade e 2. quando si apre un trade. Perché ridisegnare i pixel nel resto del tempo?

Sta risolvendo qualche altro problema?

 
Vladimir:

Rileggete il problema:

Vasiliy Sokolov:

Qui vediamo due operazioni di ridisegno necessarie quando la tabella cambia sullo schermo: 1. quando si chiude un trade e 2. quando si apre un trade. Perché ridisegnare i pixel in altri momenti?

Sta risolvendo qualche altro problema?

Beh, sono ridisegnati esattamente come hai detto tu.

Il carico del processore appare durante l'animazione:

C'è una costante reinizializzazione dei valori nell'array di pixel. Ogni 16 millisecondi. Questo carica il processore fino al 40%.

Stavo cercando di capire quale sia esattamente il carico. Ho pensato che si trattasse di salvare una risorsa o di leggerla. Si è scoperto che era la reinizializzazione dell'array nel ciclo di disegno.


Si è anche scoperto che una chiamata costante di ObjectSetInteger(0, "MT object",OBJPROP_SELECTED,1); (ogni 16 ms) carica anche il processore. Di circa il 10%.

Uso questa chiamata per dire a un altro EA di leggere la risorsa con i dati dell'animazione.

In totale, ottiene +~50% di carico della CPU durante l'animazione.