Questions des débutants MQL4 MT4 MetaTrader 4 - page 137

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

Il est étrange que le compilateur ne le signale pas lorsqu'il voit des commandes de trading dans le code de l'indicateur.

Nous allons maintenant devoir transférer la partie trading de l'indicateur vers l'EA, en la liant à celui-ci via ICustom().

Cela ressemble à "la queue sur la tête et l'arc sur le côté".

Le compilateur ne vérifie que la syntaxe. Sa tâche n'est pas de déterminer comment le programme résultant fonctionnera (ou ne fonctionnera pas). La non-fonctionnalité des commandes commerciales ne peut être découverte qu'au stade de l'exécution du programme. C'est-à-dire qu'une erreur d'exécution sera reçue.

 

Bonjour à tous, pourriez-vous me dire s'il est possible de faire ce qui suit ?

Il existe une structure, par exemple :
// une structure de certains événements.
struct MyStruct
{
int Numéro ;
datetime DTm ;
double Valeur ;
Type de chaîne ;
}

Je déclare un tableau dynamique de structures de type MyStruct :
MyStruct DataEvents[] ;

Je forme et remplis un tableau dans une fonction, par exemple
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 ;
}
}

Quelque part, nous remplissons le tableau en appelant GetDataEventsTest() :
GetDataEventsTest(DataEvents) ;

Nous devons, par exemple, insérer un nouvel élément de type MyStruct au milieu de l'intervalle des éléments du tableau, quelque part à l'indice 2.
La logique suggère les étapes suivantes :
ArrayResize(DataEvents, ArraySize(DataEvents)+1) ;
et quelque chose comme ça :
int iNew = 2 ;
int i = ArraySize(DataEvents) - 2 ;
while( i>=iNouveau )
{
// DataEvents[i+1] = DataEvents[i] ; // cela ne fonctionne pas, bien sûr, car nous devons travailler avec les adresses référencées par l'élément du tableau, donc
// écrire DataEvents[i+1] dans l'élément de tableau pointant vers l'élément de tableau DataEvents[i] ;
i = i - 1 ;
}
... Ensuite, je remplis l'élément du tableau DataEvents[iNew] avec des données.


Question : est-il possible de faire cela avec les structures mql4 ?

 
GitSM:

Question : est-il possible de faire cela avec des structures dans mql4 ?

Oui, c'est possible. Si la structure ne comportait pas de type de données complexe (ici, il s'agit d'une chaîne de caractères), tout s'arrangerait d'un coup. Et lorsque la structure contient des types de données dont la taille peut changer au fil du temps, vous devez surcharger l'opérateur d'affectation:

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:

Oui, c'est possible. Si la structure ne comportait pas de type de données complexe (ici, il s'agit d'une chaîne de caractères), cela fonctionnerait immédiatement. Et lorsque la structure contient des types de données dont la taille peut changer au fil du temps, vous devez surcharger l'opérateur d'affectation:

Merci pour le conseil !
 

Une fois encore, une question s'est posée dans le même sens que dans le dernier exemple.
Si la structure est complexe et peut contenir des tableaux avec d'autres structures. Par exemple, je fais des déclarations comme celle-ci :

// élément avec des propriétés
struct ItemProperty
{
double Low ;
double High ;
double milieu ;
double gamme ;
double zone ;
Type de chaîne ;

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

// éléments avec des propriétés statistiques
struct ItemsProperty ;
{
double MinLow ;
double MaxHigh ;
double AvgRange ;
double AvgArea ;
Phase de la chaîne ;

Items Items[] ;

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

// Items = SourceItemProperty.Items ; // Comment faire en sorte que plusieurs variables de tableau pointent vers le même tableau physique en mémoire ?
}
}

// structure de certains événements basée sur l'analyse des éléments
struct EventProperty
{
int Numéro ;
datetime DTm ;
double Valeur ;
Type de chaîne ;

double Levels[] ;
int Weigths[] ;

ItemsProperty ItemsProp[] ;

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

// Levels = SourceEventProperty.Levels ; // il y a un hic.
// Weigths = SourceEventProperty.Weigths ; // ehhh.

// ItemsProp = SourceEventProperty.ItemsProp ; // ici aussi il y a un problème

}
}

Déclarer un tableau dynamique d'événements :
EventProperty MesEvents[] ;

Je remplis les données du tableau d'événements dans une fonction.
void GetEventsProperty(EventProperty& MyEvents)
{
// code de remplissage
}

et quelque part, il est nécessaire de manipuler les éléments du tableau MyEvents en les ajoutant ou en les supprimant.

int iNew = 2 ;
int i = ArraySize(MyEvents) - 2 ;
while( i>=iNew )
{
// MyEvents[i+1] = MyEvents[i] ; // ici, nous avons un hic
i = i - 1 ;
}

Est-il possible de faire cela avec un tableau de structures dans mt4 ? Il s'avère que nous devons pouvoir faire référence à un même élément d'un tableau de structures en mémoire à partir de différentes variables de référence, en les créant et en les supprimant.
Est-il possible de travailler avec un tableau de références à des structures ?

 
GitSM:

Est-il possible de faire cela avec un tableau de structures dans mt4 ? Il s'avère que vous devez être en mesure de référencer un même élément du tableau de structures en mémoire à partir de différentes références de variables, en les créant et en les supprimant.

Est-il possible de travailler avec un tableau de références à des structures ?

En théorie, ça devrait être comme ça :

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];
    }
}

Et avec toutes les autres matrices exactement les mêmes. Question :

Comment puis-je faire en sorte que plusieurs variables de tableau pointent vers le même tableau physique en mémoire ?

Je ne comprends pas.

P. S. Pour insérer du code, utilisez l'icône "</>" ou Alt+S.

 

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

Je ne comprends pas.

Désolé, je n'ai pas formulé la question correctement. Si je comprends bien, un tableau de structures est essentiellement des références-adresses par des index de tableau, dont chacune pointe vers une adresse physique en mémoire, distribuée d'une certaine manière selon la structure de données. Par "Comment faire en sorte que plusieurs variables de tableau pointent vers le même tableau physique en mémoire", je voulais dire la possibilité de faire en sorte que MesEvents[2] et MesEvents[5] pointent vers la même structure en mémoire, c'est-à-dire que MesEvents[2] et MesEvents[5] ne devraient pas pointer vers deux structures identiques, ils devraient pointer vers la même structure.

La surcharge de l'opérateur créera une copie de la structure. Les structures de données peuvent être très lourdes ou il peut y en avoir beaucoup et il n'est pas nécessaire de les copier, vous avez juste besoin d'un tableau pour sauter d'un index à l'autre pour adresser la structure de données. Quelque chose comme ceci *MyEvents[2] = *MyEvents[1]. J'ai peut-être utilisé les pointeurs de manière incorrecte ici, je vais donc l'expliquer de cette manière. Vous devez prendre l'adresse de MyEvents[2] et la remplacer par l'adresse de MyEvents[1].

Et puis, quelles que soient la complexité et la lourdeur des structures de données, vous pouvez les "mélanger" dans le tableau dans l'ordre que vous voulez, sans pratiquement gaspiller de ressources informatiques. Après tout, copier une adresse mémoire d'un endroit à un autre est beaucoup plus facile, plusieurs fois plus rapide et ne nécessite pas de mémoire supplémentaire, que copier des structures dont la complexité peut varier fortement afin de modifier l'index référencé à cette structure dans un tableau.

Распределенные вычисления в сети MQL5 Cloud Network
Распределенные вычисления в сети MQL5 Cloud Network
  • cloud.mql5.com
Большую часть времени современные компьютеры простаивают и не используют всех возможностей процессора. Мы предлагаем задействовать их с пользой. Вы можете сдавать мощности вашего компьютера другим участникам нашей сети для выполнения разнообразных...
 
Si je comprends bien, pour mettre en œuvre un tel mécanisme de "brassage" des références à des structures dans un tableau, ces structures devront être mises en œuvre par le biais de classes.
J'ai essayé un tel exemple, et il semble fonctionner. Je comprends que je devrai également surveiller la suppression des objets de classe créés via new.
J'ai décrit une classe de test et un tableau dynamique de pointeurs (si j'ai bien compris, il s'agit essentiellement des mêmes liens) vers des classes dans la déclaration de la variable:
class MyClassTest
{
        public:
        int a;
        double b;
        string c;
};

MyClassTest* arrayRefsMyClassTest[];
J'ai également effectué ces contrôles :
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Тест операций над массивом ссылок на классы: конец");
J'ai obtenu ces résultats dans le journal :
Тест операций над массивом ссылок на классы: начало
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
Тест операций над массивом ссылок на классы: конец
Il semble fonctionner comme prévu. Dans ce cas, si je comprends bien, les copies superflues de données ne sont pas créées. Si je me trompe, veuillez me corriger. Peut-être y a-t-il des commentaires ou des clarifications ?
 
Comment MQL5 (ou WinAPI) peut-il étendre le graphique en plein écran ???
 
GitSM:
D'après ce que j'ai compris, pour mettre en œuvre un tel mécanisme de "brassage" des références aux structures dans un tableau, ces structures doivent être mises en œuvre par le biais de classes.

Oui, malheureusement, vous ne pouvez pas créer des pointeurs vers des structures dans MQL. La raison d'une telle limitation n'est pas claire, si vous pouvez le faire avec des classes. Après tout, les structures ne diffèrent pas vraiment des classes.

Raison: