My approach. The core is the engine. - page 124

 
Andrey Barinov:

Because instead of OrderOpenPrice put OrderOpenTime()

Right. I mixed up. :)

 
Реter Konow:

I have to admit that I was a bit surprised by the test results.

That's why I wanted you to do everything yourself, not to give ready-made solutions that would hit the wall.
You know, Peter, there's also such a feature as a pointer to a function, thanks to which you can organize function calls by simply taking these pointers from an array of such pointers. I think this would be very useful in your task. Only trouble is, you have to mess with classes again.
 
Nikolai Semko:
That's why I wanted you to do everything yourself, not to give ready-made solutions, which are like peas against the wall.
And you know, Peter, there's also such a thing as a pointer to a function, thanks to which you can organize function calls by simply taking these pointers from an array of such pointers. I think this would be very useful in your problem. But here's the trouble - you have to deal with classes again.

I have heard of pointers to functions. But I have very few functions. It's because of this that I don't have space and need to use OOP.

I have a different development concept. I believe that the operation of holistic multi-function blocks is more efficient than that of large complexes of small functions.

More promising, from the point of view of mechanism development.

That's my opinion...

I have several big blocks. To apply OOP, they must be broken down into small functions, organize into classes, and then, use pointers and other things.

But I won't be able to do that. Simply because I think differently.

The concept of OOP does not coincide with the peculiarities of my way of thinking, and I can't expand in it. That's the reason.

 
Nikolai Semko:

Note, Nikolai, that in the matter of programmatic development, I have no problem. Everything is developing very quickly.

At the same time, the mechanisms work fine.

I have now mastered unions, and I see their application in one particular task, - writing strings into a resource.

I will try to check the speed and CPU load in the test EA and post the result.

If it is good, I will rebuild communication between engine and EA, making it on resources.

 

In order to use resources to pass strings of undefined length, these strings must be written to a char array.

However, it seems that their size is only declared inside the union and does not change afterwards.

I tried resizing the char array from the union, through ArrayResize, but there is no effect.

It seems that the size of the char array must be set beforehand. And it should be maximum size.


Here is the code:

//+------------------------------------------------------------------+
//|                                                       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));
  }
//+------------------------------------------------------------------+
 

It is now clear that the size of thechar arrayin the union must be known beforehand. BecauseArrayResize(u.Char,StrSize) does not change it.

So, we have to set the array size equal to the length of the maximum string...

 

Good news. Everything is working well.

The string is written to the resource and read by another EA on a different chart.

There is no load on the processor. The load is only caused by calling the Alert that prints the string.

Here is the code of Expert Advisors:

1. Expert Advisor forming the string and writing it into a resource.

//+------------------------------------------------------------------+
//|                                                       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!");
   //-------------------------------------------------------
  }
//+------------------------------------------------------------------+
 

An advisor reading a line from a resource on another chart:

//+------------------------------------------------------------------+
//|                                              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);
   //-----------------------------
  }
//+------------------------------------------------------------------+


Will use resources for communication. The only drawback is that you have to set the maximum char array size in the union. But, you don't need to think about the size of the string and the number of MT objects.

This method is slower than the MT-object linking method, but it's fine.

 
Реter Konow:

You have an interesting theory, although it doesn't quite match the results of my experiments, which I will now post below.

As the test shows, it is the initialization of the pixel array that loads the CPU the most.

Check out the test EA below.

Reread the task:

Vasiliy Sokolov:

Peter, here's the assignment. Make a panel showing current order openings in MT4. You don't have to make a full copy of the system panel, just make a simple table with basic properties of open orders: open price, direction, profit. The rest is up to you. The main thing is that when an order is closed, its indication in your table would also disappear. And vice versa, it would appear in this table when a new order is opened.

Here you can see the two necessary operations of redrawing when the table changes on the screen: 1. when closing a trade and 2. when opening a trade. Why redraw the pixels at other times?

Are you solving some other problem?

 
Vladimir:

Reread the problem:

Vasiliy Sokolov:

Here we see two necessary redrawing operations when the table changes on the screen: 1. when closing a trade and 2. when opening a trade. Why redraw pixels at other times?

Are you solving some other problem?

Well, they are redrawn exactly as you said.

The load on the processor appears during animation:

There is a constant reinitialization of the values in the pixel array. Every 16 milliseconds. This loads the processor up to 40%.

I was trying to figure out what exactly the load is. I thought it was saving a resource or reading it. It turned out that it was the reinitialization of the array in the drawing loop.


It also turned out that a constant call of ObjectSetInteger(0, "MT object",OBJPROP_SELECTED,1); (every 16 ms) also loads the processor. By about 10%.

I use this call to tell another EA to read the resource with animation data.

In total, it gets +~50% CPU load during animation.

Reason: