Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 235

 
Marat Sultanov #:
In passato era possibile (anche nelle vecchie versioni del compilatore) utilizzare una classe prima che fosse dichiarata:
Ma ora si ottiene un errore in fase di compilazione:
classe non definita 'A' non può essere usata

Se smette di funzionare, sarebbe bene sapere se è corretto.

Se si creano dei puntatori al posto degli oggetti, funzionerà anche la vecchia versione.

 
fxsaber #:

Se ha smesso di funzionare, è bene sapere se è la cosa giusta da fare.

Se si creano puntatori invece di oggetti, funzionerà anche la vecchia versione.

Ottima osservazione e grazie per il suggerimento!

Sì, in effetti la situazione è perfettamente risolta con un puntatore:

class A;

class B
{
   public: A * a;
   public: int Val;
};

class A
{
   public: B * b;
   public: int Test() {return b.Val + 1;}
};

//+------------------------------------------------------------------+
//|                                                                                |
//+------------------------------------------------------------------+
void OnStart()
{
   B b;
   A a;
   
   b.a = GetPointer(a);
   b.a.b = GetPointer(b);
   b.Val = 1;
   
   Print(b.a.Test());
}
 

Gli appassionati di algoritmi veloci. Quelli che lottano per i nanosecondi :)


Compito: trovare l'ora di apertura della barra in base all'ora e al TF indicati, quando si sa che la barra esiste in questo momento. Ad esempio, in base all'orario di apertura e chiusura delle posizioni.

La maggior parte dei programmatori utilizzerà una combinazione di iTime e iBarShift. Questa sarà l'implementazione più lenta, soprattutto perché richiede una cronologia aggiornata dei dati caricati o degli array combinati. Inoltre, questo approccio può generare errori se manca la cronologia richiesta.

I programmatori più avanzati risolveranno questo problema con la struttura MqlDateTime e la funzione TimeToStruct(). Questa non è una cattiva soluzione ed è abbastanza veloce.

Ma esiste una terza soluzione, che è più produttiva della precedente di molte volte:

//+------------------------------------------------------------------+
// получает время открытия виртуального бара по входному времени и Таймфрейму, вне зависимости от того, существует реальный бар или нет.
// корректно считает только до 28.02.2100 !!!!
// не является заменой iBarShift!!! Не зависит от истории баров.  
datetime getStartTimeOfBarFast(ENUM_TIMEFRAMES tf, datetime t) {
   if (tf==0) tf=_Period;

   int ts=0;
   if (tf<PERIOD_MN1) {
      ushort i_tf= ushort(tf);
      uchar _i =uchar(i_tf>>14);
      int n = i_tf & 0x0FFF;
      ts = (_i==0)?n*60:(_i==1)?n*60*60:60*60*24*7;
   }
   if (tf<PERIOD_W1) return t-t%ts;
   if (tf==PERIOD_W1) return t-(t+4*24*60*60)%ts;
   else { // Period MN1
      static int dm[12] = {0,31,61,92,122,153,184, 214, 245, 275, 306, 337};
      static int last_days = 0;
      static datetime last_result = 0;
      int days = int(t/(24*60*60));
      if (last_days!=days) {
         last_days = days;
         int d1 = (days+306+365)%1461;
         int y = d1/365;
         datetime t1 = t - t%(24*60*60) - d1*24*60*60;
         int m = 0;
         if (d1==1460) {
            m=11;
            y--;
         };
         int d = d1-y*365+1;
         if (d!=31) if (d==276) m = 9;
            else m = int (d/30.68);
         if (m<0 || m>11) return -1;
         last_result = t1+y*365*24*60*60+dm[m]*24*60*60;
      }
      return last_result;
   }
}
//+------------------------------------------------------------------+

La difficoltà principale di questo algoritmo è il calcolo dell'ora di inizio del mese (evidenziata in verde) Non cercate di capire il funzionamento dell'algoritmo. C'è una magia, che è il risultato del passaggio dal semplice al complesso. Il percorso inverso, da complesso a semplice, sarà molto più difficile da percorrere.

Il guadagno di prestazioni è dato anche dall'algoritmo che ricava i secondi in una barra dal TF invece che dalla funzione standard PeriodSeconds() - evidenziato in giallo.


Allego uno script di test che calcola e confronta le prestazioni di tutti e tre i metodi:

2023.11.14 12:15:29.145 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_MN1========
2023.11.14 12:15:29.146 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 21.20 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:29.146 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 6.10 наносекунд - Быстрый расчет
2023.11.14 12:15:29.147 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 142.00 наносекунд - Расчет через iBarShift
2023.11.14 12:15:29.147 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:34.226 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_MN1========
2023.11.14 12:15:34.227 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 19.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:34.227 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 6.70 наносекунд - Быстрый расчет
2023.11.14 12:15:34.228 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11987239507200, время выполнения 1 иттерации = 127.50 наносекунд - Расчет через iBarShift
2023.11.14 12:15:34.228 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_W1========
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 2.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:39.856 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:39.857 timeToStartMonth (EURUSD,M1)    контрольная сумма - 11997367833600, время выполнения 1 иттерации = 98.30 наносекунд - Расчет через iBarShift
2023.11.14 12:15:39.857 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:52.770 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H2========
2023.11.14 12:15:52.771 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000355999200, время выполнения 1 иттерации = 4.10 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:52.771 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000355999200, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:54.255 timeToStartMonth (EURUSD,M1)    контрольная сумма - 0, время выполнения 1 иттерации = 148466.50 наносекунд - Расчет через iBarShift
2023.11.14 12:15:54.255 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_M4========
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000391999920, время выполнения 1 иттерации = 3.60 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:15:58.759 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000391999920, время выполнения 1 иттерации = 1.50 наносекунд - Быстрый расчет
2023.11.14 12:15:59.864 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000017286960, время выполнения 1 иттерации = 110555.70 наносекунд - Расчет через iBarShift
2023.11.14 12:15:59.864 timeToStartMonth (EURUSD,M1)    ========================================================================

Il checksum con iBarShift non coincide , perché iBarShift lavora con barre reali. Il checksum coinciderà solo sui timeframe MN1 e W1, perché non ci sono buchi nella storia di tali barre.
Le prestazioni saranno più elevate se si utilizza un piccolo passo temporale nel ciclo (meno di un giorno) quando l'algoritmo inizia a lavorare per salvare i calcoli precedenti:

2023.11.14 12:14:10.714 timeToStartMonth (EURUSD,M1)    =====LOOP=1000000========STEPS=1000 seconds======PERIOD_MN1========
2023.11.14 12:14:10.722 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 8.03 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:14:10.723 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 1.18 наносекунд - Быстрый расчет
2023.11.14 12:14:10.860 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 136.80 наносекунд - Расчет через iBarShift
2023.11.14 12:14:10.860 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:14:17.502 timeToStartMonth (EURUSD,M1)    =====LOOP=1000000========STEPS=1000 seconds======PERIOD_MN1========
2023.11.14 12:14:17.510 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 7.70 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:14:17.511 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 1.18 наносекунд - Быстрый расчет
2023.11.14 12:14:17.648 timeToStartMonth (EURUSD,M1)    контрольная сумма - 1198674131961600, время выполнения 1 иттерации = 137.54 наносекунд - Расчет через iBarShift
2023.11.14 12:14:17.648 timeToStartMonth (EURUSD,M1)    ========================================================================


I valori eccessivi per l'algoritmo tramite iBarShift (evidenziati in blu) sono causati dall'attuale mancanza dello storico necessario o dei TF calcolati dall'array, che ne avvia il caricamento.
Dopo il caricamento il risultato sarà il seguente:

2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H2========
2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000379996800, время выполнения 1 иттерации = 4.60 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:47:06.158 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000379996800, время выполнения 1 иттерации = 2.60 наносекунд - Быстрый расчет
2023.11.14 12:47:06.159 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000009103200, время выполнения 1 иттерации = 129.10 наносекунд - Расчет через iBarShift
2023.11.14 12:47:06.159 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_M4========
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000411199920, время выполнения 1 иттерации = 2.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 12:47:13.899 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000411199920, время выполнения 1 иттерации = 1.40 наносекунд - Быстрый расчет
2023.11.14 12:47:13.903 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000038634480, время выполнения 1 иттерации = 381.30 наносекунд - Расчет через iBarShift
2023.11.14 12:47:13.903 timeToStartMonth (EURUSD,M1)    ========================================================================

File:
 
Nikolai Semko #:

Gli appassionati di algoritmi veloci. Quelli che lottano per i nanosecondi :)

...

😮😲😳🥴🤪

...

ah...

mmm....

oooh....

gkghm... Non pensavo che la mia semplice domanda sarebbe uscita in questo modo.

Proprio così.

 
Artyom Trishkin #:

😮😲😳🥴🤪

...

ah...

mmm.

ohhhh....

ahem. Non pensavo che la mia semplice domanda sarebbe uscita in questo modo.

Oh.

Sì, Artem, mi hai ingannato per un po'.
Era un interesse sportivo.
Spero che possa essere utile a qualcuno, me compreso. :))

 
Nikolai Semko #:

Sì, Artem, mi hai imbrogliato per un po'.
Ho lavorato sull'interesse sportivo.
Spero che sia utile a qualcuno, e a me tra gli altri. :))

Certo che lo sarà. Ottimo. Grazie ancora!

S.F. Questo mi ha divertito: "conta correttamente solo fino al 28.02.2100 !!!!".

Cosa facciamo dopo?

 
Artyom Trishkin #:

Certo che tornerà utile. Ottimo. Grazie ancora!

S.F. Questo mi ha divertito: "conta correttamente solo fino al 28.02.2100 !!!!".

Cosa facciamo dopo?

haha.
Dubito che questo algoritmo sarà richiesto per 75 anni. I computer quantistici probabilmente governeranno già il mondo, con una programmazione completamente diversa.
Ad essere onesti, è stato pigro tenere conto del calendario gregoriano. Il 2000 era una data importante, il 2100 non lo è più.

 
Nikolai Semko #:

haha.
Dubito che questo algoritmo sarà richiesto per 75 anni. I computer quantistici probabilmente governeranno già il mondo, con una programmazione completamente diversa.
ad essere onesti, è stato pigro tenere completamente conto del calendario gregoriano. Il 2000 era una posta in gioco alta, il 2100 non lo è più.

Per MN si può usare un array precalcolato, non c'è quasi nulla lì dentro

Ln2(12 mesi * cento anni)... 11 if` e confronti nella ricerca binaria, ma senza altri calcoli.

 
Maxim Kuznetsov #:

È possibile utilizzare un array precalcolato per MN, non ci sono praticamente dati.

Ln2(12 mesi * cento anni)... 11 if` e confronti nella ricerca binaria, ma senza altri calcoli.

Non ci sono difficoltà. So come implementarlo.
Solo che non voglio fare qualcosa che sono sicuro al 100% che non sarà mai utile.
 
Maxim Kuznetsov #:

È possibile utilizzare un array precalcolato per MN, i dati sono praticamente inesistenti.

Ln2(12 mesi * cento anni)... 11 if` e confronti nella ricerca binaria, ma senza altri calcoli.

Ah, ho letto male all'inizio.
No, ti sbagli. L'aumento delle prestazioni non funzionerà. Si rimarrà comunque bloccati nei calcoli. E l'accesso agli elementi dell'array rallenta molto l'algoritmo.

Motivazione: