Questions from Beginners MQL4 MT4 MetaTrader 4 - page 137

 
Игорь Васильев:

Strange why the compiler doesn't report it when it sees trading commands in the indicator code.

Now we will have to pull the trading part from the indicator to the Expert Advisor by linking it with it via ICustom().

It looks like "the tail on the head and the bow on the side".

The compiler checks only the syntax. Its task is not to determine how the resulting program will work (or not work). Non-functionality of trade commands may be found out only at the stage of program execution. That is, a run-time error will be received.

 

Hi all, could you please tell me if it's possible to do the following?

There is a structure, for example:
// a structure of some events.
struct MyStruct
{
int Number;
datetime DTm;
double Value;
string Type;
}

I declare a dynamic array of structures of type MyStruct:
MyStruct DataEvents[];

I form and fill in an array in some function, for example
void GetDataEventsTest(MyStruct& DataEvents[], int countEvent=5)
{
MathSrand(GetTickCount());
ArrayResize(DataEvents, countEvent);
int i = 0;
while( i<countEvent )
{
DataEvents.Number = i;
DataEvents.DTm = TimeCurrent();
DataEvents.Value = (double)MathRand();
if( MathMod(i, 2)>0 ) DataEvents.Type = "Up"; else DataEvents.Type = "Dn";
i = i + 1;
}
}

Somewhere we fill the array by calling GetDataEventsTest():
GetDataEventsTest(DataEvents);

We need, for example, to insert a new element of MyStruct type into the middle of the array elements interval, somewhere at index 2.
Logic suggests the following steps:
ArrayResize(DataEvents, ArraySize(DataEvents)+1);
and something like this:
int iNew = 2;
int i = ArraySize(DataEvents) - 2;
while( i>=iNew )
{
// DataEvents[i+1] = DataEvents[i]; // it does not work, of course, because we have to work with the addresses referenced to by the array element, so
// write DataEvents[i+1] to the array element pointing to the array element DataEvents[i];
i = i - 1;
}
... Then I fill the DataEvents[iNew] array element with data.


Question, is it possible to do this with mql4 structures?

 
GitSM:

Question is it possible to do this with structures in mql4?

Yes, it is possible. If the structure was without a complex data type (here it includes string), everything would work out at once. And when the structure contains data types, the size of which may change over time, you need to overload the assignment operator:

struct MyStruct
{
    int Number;
    datetime DTm;
    double Value;
    string Type;

    void operator = (const MyStruct &stMyStruct)
    {
      Number = stMystruct.Number;
      DTm = stMyStruct.DTm;
      Value = stMyStruct.Value;
      Type = stMyStruct.Type;
    }
}
 
Ihor Herasko:

Yes, it is possible. If the structure was without a complex data type (here it includes string), it would work right away. And when the structure contains data types whose data size can change over time, you need to overload the assignment operator:

Thanks for the tip!
 

Again a question arose in the same direction as in the last example.
If the structure is complex and may contain arrays with other structures. For example, I make declarations like this:

// element with properties
struct ItemProperty
{
double Low;
double High;
double Middle;
double Range;
double Area;
string Type;

void operator = (const ItemProperty &SourceItemProperty)
{
Low = SourceItemProperty.Low;
High = SourceItemProperty.High;
Middle = SourceItemProperty.Middle;
Range = SourceItemProperty.Range;
Area = SourceItemProperty.Area;
Type = SourceItemProperty.Type;
}
}

// items with statistical properties
struct ItemsProperty;
{
double MinLow;
double MaxHigh;
double AvgRange;
double AvgArea;
string Phase;

Item Items[];

void operator = (const ItemProperty &SourceItemsProperty)
{
MinLow = SourceItemsProperty.MinLow;
MaxHigh = SourceItemsProperty.MaxHigh;
AvgRange = SourceItemsProperty.AvgRange;
AvgArea = SourceItemsProperty.AvgArea;
Phase = SourceItemsProperty.Phase;

// Items = SourceItemProperty.Items; // How can I make multiple array variables point to the same physical array in memory?
}
}

// structure of some events based on the analysis of items
struct EventProperty
{
int Number;
datetime DTm;
double Value;
string Type;

double Levels[];
int Weigths[];

ItemsProperty ItemsProp[];

void operator = (const ItemProperty &SourceEventProperty)
{
Number = SourceEventProperty.Number;
DTm = SourceEventProperty.DTm;
Value = SourceEventProperty.Value;
Type = SourceEventProperty.Type;

// Levels = SourceEventProperty.Levels; // there's a hitch
// Weigths = SourceEventProperty.Weigths; // ehhh.

// ItemsProp = SourceEventProperty.ItemsProp; // here too is a problem

}
}

Declaring a dynamic array of events:
EventProperty MyEvents[];

I fill in the event array data in some function.
void GetEventsProperty(EventProperty& MyEvents)
{
// filling code
}

and somewhere there is a need to manipulate the elements of the MyEvents array by adding or removing them.

int iNew = 2;
int i = ArraySize(MyEvents) - 2;
while( i>=iNew )
{
// MyEvents[i+1] = MyEvents[i]; // here we have a hitch
i = i - 1;
}

Is it possible to do this with an array of structures in mt4? It turns out that we need to be able to refer to one and the same element of array of structures in memory from different variable-reference variables, creating and deleting them.
Is it possible to work with an array of references to structures?

 
GitSM:

Is it possible to do this with an array of structures in mt4? It turns out that it is necessary to be able to refer to the same element of the array of structures in memory from different variable references, creating and deleting them.

Is it possible to work with an array of references to structures?

In theory, it should be like this:

struct ItemsProperty;
{
    double MinLow;
    double MaxHigh;
    double AvgRange;
    double AvgArea;
    string Phase;
    
    Item Items[];
    
    void operator = (const ItemProperty &SourceItemsProperty)
    {
        MinLow = SourceItemsProperty.MinLow;
        MaxHigh = SourceItemsProperty.MaxHigh;
        AvgRange = SourceItemsProperty.AvgRange;
        AvgArea = SourceItemsProperty.AvgArea;
        Phase = SourceItemsProperty.Phase;
 
        int nTotal = ArraySize(SourceItemProperty.Items);
        ArrayResize(Items, nTotal);
        for (int i = 0; i < nTotal; ++i)
           Items[i] = SourceItemProperty.Items[i];
    }
}

And with all other arrays exactly the same. Question:

How can I make several array variables point to the same physical array in memory?

I don't get it.

P. S. To insert code, use the "</>" icon or Alt+S.

 

Как сделать так чтобы на один и тот же физический массив в памяти могло указывать несколько переменных массива?

I don't get it.

Sorry, I didn't formulate the question quite correctly. If I understand correctly, an array of structures is essentially references-addresses by array indexes, each of which points to some physical address in memory, distributed in a certain way according to the data structure. By "How to make several array variables point to one and the same physical array in memory?" I meant the possibility to make MyEvents[2] and MyEvents[5] point to one and the same structure in memory, i.e. MyEvents[2] and MyEvents[5] should not point to two identical structures, they should point to the same structure.

Overloading the operator will create a copy of the structure. The data structures can be very heavy or there can be many of them and there is no need to copy them, you just need an array to jump from one index to another to address the data structure. Something like this *MyEvents[2] = *MyEvents[1]. I may have used pointers incorrectly here, so I will explain it this way. You need to take the address by MyEvents[2] and change it to the address by MyEvents[1].

And then no matter how complex and heavy data structures are, you could "shuffle" them in the array in any order you need with almost no waste of computational resources. After all, copying a memory address from one place to another is much easier, orders of magnitude faster and does not require additional memory, than copying structures whose complexity may vary greatly in order to change the index referenced to this structure in an array.

Распределенные вычисления в сети MQL5 Cloud Network
Распределенные вычисления в сети MQL5 Cloud Network
  • cloud.mql5.com
Большую часть времени современные компьютеры простаивают и не используют всех возможностей процессора. Мы предлагаем задействовать их с пользой. Вы можете сдавать мощности вашего компьютера другим участникам нашей сети для выполнения разнообразных...
 
As I understand it, in order to implement such a mechanism of "shuffling" references to structures in an array, these structures will have to be implemented through classes.
I tried such an example, and it seems to work. I understand that I will also need to monitor the removal of class objects created via new.
I've described a test class and a dynamic array of pointers (as I understand it, they're essentially the same links) to classes in the variable declaration:
class MyClassTest
{
        public:
        int a;
        double b;
        string c;
};

MyClassTest* arrayRefsMyClassTest[];
I also made these checks:
Print("Тест операций над массивом ссылок на классы: начало");

// создаём объекты классов и сохраняем ссылки на них в массиве ссылок.
i = 0;
while( i<5 )
{
        ArrayResize(arrayRefsMyClassTest, i+1);
        arrayRefsMyClassTest[i] = new MyClassTest();
        arrayRefsMyClassTest[i].a = i;
        arrayRefsMyClassTest[i].b = 3.14+i;
        arrayRefsMyClassTest[i].c = "testclass" + i;
        i = i + 1;
}

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Изменяем размер массива ссылок на классы");
ArrayResize(arrayRefsMyClassTest, ArraySize(arrayRefsMyClassTest)+2);

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Присваиваю последнему элементу ссылку во втором элементе");
i =  ArraySize(arrayRefsMyClassTest) - 1;
arrayRefsMyClassTest[i] = arrayRefsMyClassTest[2];

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Присваиваю 2 элементу ссылку в 5 элементе");
arrayRefsMyClassTest[1] = arrayRefsMyClassTest[5];

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("\nТест операций над массивом ссылок на классы: конец");
I got these results in the log:
Тест операций над массивом ссылок на классы: начало
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Изменяем размер массива ссылок на классы
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Присваиваю последнему элементу ссылку во втором элементе
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[6]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Присваиваю 2 элементу ссылку в 5 элементе
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[6]: a = 2, b = 5.14, c = testclass2
Тест операций над массивом ссылок на классы: конец
It seems to work as intended. Superfluous copies of data in this case, as I understand it, are not created. If I am wrong, please correct me. Maybe there are any comments or clarifications?
 
How can MQL5 (or WinAPI) expand the chart to full screen???
 
GitSM:
As far as I understood, to implement such a mechanism of "shuffling" references to structures in an array, these structures must be implemented through classes.

Yes, unfortunately, you cannot make pointers to structures in MQL. It's not clear why such limitation is made, if you can do it with classes. After all, the structures do not really differ from the classes.