Domande dai principianti MQL4 MT4 MetaTrader 4 - pagina 137

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

Strano che il compilatore non lo segnali quando vede i comandi di trading nel codice dell'indicatore.

Ora dovremo tirare la parte di trading dall'indicatore all'EA, collegandolo ad esso tramite ICustom().

Sembra "la coda sulla testa e l'arco sul lato".

Il compilatore controlla solo la sintassi. Il suo compito non è quello di determinare come il programma risultante funzionerà (o non funzionerà). La non funzionalità dei comandi commerciali può essere scoperta solo nella fase di esecuzione del programma. Cioè, verrà ricevuto un errore di esecuzione.

 

Ciao a tutti, potreste dirmi se è possibile fare quanto segue?

C'è una struttura, per esempio:
// una struttura di alcuni eventi.
struct MyStruct
{
Numero int;
datetime DTm;
doppio Valore;
tipo di stringa;
}

Dichiaro un array dinamico di strutture di tipo MyStruct:
MyStruct DataEvents[];

Formulo e riempio un array in qualche funzione, per esempio
void GetDataEventsTest(MyStruct& DataEvents[], int countEvent=5)
{
MathSrand(GetTickCount());
ArrayResize(DataEvents, countEvent);
int i = 0;
mentre( i<countEvent )
{
DataEvents.Number = i;
DataEvents.DTm = TimeCurrent();
DataEvents.Value = (double)MathRand();
if( MathMod(i, 2)>0 ) DataEvents.Type = "Up"; altrimenti DataEvents.Type = "Dn";
i = i + 1;
}
}

Da qualche parte riempiamo l'array chiamando GetDataEventsTest():
GetDataEventsTest(DataEvents);

Abbiamo bisogno, per esempio, di inserire un nuovo elemento di tipo MyStruct nel mezzo dell'intervallo di elementi dell'array, da qualche parte all'indice 2.
La logica suggerisce i seguenti passi:
ArrayResize(DataEvents, ArraySize(DataEvents)+1);
e qualcosa del genere:
int iNew = 2;
int i = ArraySize(DataEvents) - 2;
mentre( i>=iNuovo )
{
// DataEvents[i+1] = DataEvents[i]; // non funziona, ovviamente, perché dobbiamo lavorare con gli indirizzi a cui fa riferimento l'elemento dell'array, quindi
// scrivere DataEvents[i+1] in un elemento dell'array in modo che punti all'elemento dell'array DataEvents[i];
i = i - 1;
}
... Poi riempio l'elemento dell'array DataEvents[iNew] con i dati.


Domanda: è possibile fare questo con le strutture mql4?

 
GitSM:

Domanda: è possibile fare questo con le strutture in mql4?

Sì, è possibile. Se la struttura fosse senza un tipo di dati complesso (qui include la stringa), tutto funzionerebbe subito. E quando la struttura contiene tipi di dati, la cui dimensione può cambiare nel tempo, è necessario sovraccaricare l'operatore di assegnazione:

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:

Sì, è possibile. Se la struttura fosse senza un tipo di dati complesso (qui include la stringa), funzionerebbe subito. E quando la struttura contiene tipi di dati le cui dimensioni possono cambiare nel tempo, è necessario sovraccaricare l'operatore di assegnazione:

Grazie per il suggerimento!
 

Di nuovo è sorta una domanda nella stessa direzione dell'ultimo esempio.
Se la struttura è complessa e può contenere array con altre strutture. Per esempio, faccio dichiarazioni come questa:

// elemento con proprietà
struct ItemProperty
{
doppio Basso;
doppio High;
doppio medio;
doppia gamma;
doppia area;
tipo di stringa;

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

// articoli con proprietà statistiche
struct ItemsProperty;
{
doppio MinLow;
doppio MaxHigh;
doppio AvgRange;
doppio AvgArea;
stringa Fase;

Elemento Items[];

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

// Items = SourceItemProperty.Items; // Come posso fare in modo che più variabili di array puntino allo stesso array fisico in memoria?
}
}

// struttura di alcuni eventi basata sull'analisi degli elementi
struct EventProperty
{
Numero int;
datetime DTm;
doppio Valore;
tipo di stringa;

doppio Livelli[];
int Weigths[];

ItemsProperty ItemsProp[];

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

// Levels = SourceEventProperty.Levels; // c'è un intoppo
// Weigths = SourceEventProperty.Weigths; // ehhh.

// ItemsProp = SourceEventProperty.ItemsProp; // anche qui c'è un problema

}
}

Dichiarare un array dinamico di eventi:
EventProperty MyEvents[];

Riempio i dati dell'array di eventi in qualche funzione.
void GetEventsProperty(EventProperty& MyEvents)
{
// codice di riempimento
}

e da qualche parte c'è la necessità di manipolare gli elementi dell'array MyEvents aggiungendoli o rimuovendoli.

int iNew = 2;
int i = ArraySize(MyEvents) - 2;
mentre( i>=iNuovo )
{
// MyEvents[i+1] = MyEvents[i]; // qui abbiamo un intoppo
i = i - 1;
}

È possibile farlo con un array di strutture in mt4? Si scopre che abbiamo bisogno di essere in grado di fare riferimento a uno stesso elemento di array di strutture in memoria da diverse variabili di riferimento, creandole e cancellandole.
È possibile lavorare con un array di riferimenti a strutture?

 
GitSM:

È possibile farlo con un array di strutture in mt4? Si scopre che è necessario essere in grado di fare riferimento a uno stesso elemento dell'array di strutture in memoria da diversi riferimenti di variabili, creandole e cancellandole.

È possibile lavorare con un array di riferimenti a strutture?

In teoria, dovrebbe essere così:

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

E con tutti gli altri array esattamente lo stesso. Domanda:

Come posso fare in modo che diverse variabili di array puntino allo stesso array fisico in memoria?

Non capisco.

P. S. Per inserire del codice, usate l'icona "</>" o Alt+S.

 

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

Non capisco.

Scusa, non ho formulato bene la domanda. Se ho capito bene, un array di strutture è essenzialmente riferimenti-indirizzi per indici di array, ognuno dei quali punta a qualche indirizzo fisico in memoria, distribuito in un certo modo secondo la struttura dei dati. Con "Come fare in modo che diverse variabili di array puntino allo stesso array fisico in memoria?" intendevo la possibilità di fare in modo che MyEvents[2] e MyEvents[5] puntino alla stessa struttura in memoria, cioè MyEvents[2] e MyEvents[5] non dovrebbero puntare a due strutture identiche, ma alla stessa struttura.

Sovraccaricando l'operatore si crea una copia della struttura. Le strutture di dati possono essere molto pesanti o ce ne possono essere molte e non c'è bisogno di copiarle, basta un array per saltare da un indice all'altro per indirizzare la struttura di dati. Qualcosa come questo *MyEvents[2] = *MyEvents[1]. Forse ho usato i puntatori in modo scorretto qui, quindi lo spiegherò in questo modo. Dovete prendere l'indirizzo di MyEvents[2] e cambiarlo con quello di MyEvents[1].

E poi non importa quanto siano complesse e pesanti le strutture di dati, si potrebbe "mischiarle" nell'array in qualsiasi ordine necessario senza quasi nessuno spreco di risorse computazionali. Dopo tutto, copiare un indirizzo di memoria da un posto all'altro è molto più facile, ordini di grandezza più veloce e non richiede memoria supplementare, che copiare strutture la cui complessità può variare molto per cambiare l'indice riferito a questa struttura in un array.

Распределенные вычисления в сети MQL5 Cloud Network
Распределенные вычисления в сети MQL5 Cloud Network
  • cloud.mql5.com
Большую часть времени современные компьютеры простаивают и не используют всех возможностей процессора. Мы предлагаем задействовать их с пользой. Вы можете сдавать мощности вашего компьютера другим участникам нашей сети для выполнения разнообразных...
 
Da quanto ho capito, per implementare un tale meccanismo di "rimescolamento" dei riferimenti alle strutture in un array, queste strutture dovranno essere implementate tramite classi.
Ho provato un esempio simile e sembra funzionare. Capisco che dovrò anche monitorare la rimozione degli oggetti di classe creati tramite new.
Ho descritto una classe di test e un array dinamico di puntatori (da quanto ho capito, sono essenzialmente gli stessi collegamenti) alle classi nella dichiarazione delle variabili:
class MyClassTest
{
        public:
        int a;
        double b;
        string c;
};

MyClassTest* arrayRefsMyClassTest[];
Ho anche fatto questi controlli:
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Тест операций над массивом ссылок на классы: конец");
Ho questi risultati nel registro:
Тест операций над массивом ссылок на классы: начало
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
Тест операций над массивом ссылок на классы: конец
Sembra funzionare come previsto. Le copie superflue di dati in questo caso, come ho capito, non vengono create. Se mi sbaglio, per favore correggetemi. Forse ci sono commenti o chiarimenti?
 
Come può MQL5 (o WinAPI) espandere il grafico a schermo intero?
 
GitSM:
Per quanto ho capito, per implementare un tale meccanismo di "rimescolamento" dei riferimenti alle strutture in un array, queste strutture devono essere implementate tramite classi.

Sì, purtroppo non si possono fare puntatori a strutture in MQL. Non è chiaro il motivo di tale limitazione, se è possibile farlo con le classi. Dopo tutto, le strutture non differiscono realmente dalle classi.

Motivazione: