Características del lenguaje mql5, sutilezas y técnicas - página 235

 
Marat Sultanov #:
Antes era posible (incluso en compiladores antiguos) utilizar una clase antes de declararla:
Pero ahora obtenemos un error al compilar:
no se puede utilizar la clase indefinida 'A

Si deja de funcionar, sería bueno saber si es correcto.

Si haces punteros en lugar de objetos, la versión antigua también funcionará.

 
fxsaber #:

Si ha dejado de funcionar, es bueno saber si es lo correcto.

Si haces punteros en lugar de objetos, la versión antigua también funcionará.

¡Buen punto y gracias por el consejo!

Sí, efectivamente, la situación se resuelve perfectamente con un puntero:

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());
}
 

Los aficionados a los algoritmos rápidos. Los que luchan por nanosegundos :)


Tarea: Encontrar la hora de apertura de la barra según la hora y TF dados, cuando se sabe que la barra existe en ese momento. Por ejemplo, por la hora de apertura y cierre de posiciones.

La mayoría de los programadores utilizarán una combinación de iTime e iBarShift. Esta será la implementación más lenta, especialmente tal implementación requiere un historial actualizado de datos cargados o matrices peinadas. Además, este enfoque puede generar errores si falta el historial requerido.

Los programadores más avanzados resolverán este problema mediante la estructura MqlDateTime y la función TimeToStruct(). Esta no es una mala solución y es suficientemente rápida.

Pero hay una tercera solución, que es varias veces más productiva que la anterior:

//+------------------------------------------------------------------+
// получает время открытия виртуального бара по входному времени и Таймфрейму, вне зависимости от того, существует реальный бар или нет.
// корректно считает только до 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 principal dificultad de este algoritmo es calcular la hora de principio de mes (resaltada en verde) Por favor, no intente entender el funcionamiento del algoritmo. Hay magia, que es el resultado de ir de lo simple a lo complejo. El camino inverso de lo complejo a lo simple será mucho más difícil de recorrer.

La ganancia de rendimiento también es proporcionada por el algoritmo de obtener segundos en una barra desde el TF en lugar de la función estándar PeriodSeconds() - resaltada en color amarillo.


Adjunto un script de prueba que calcula y compara el rendimiento de los tres métodos:

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)    ========================================================================

La suma de comprobación con iBarShift no coincidirá , porque iBarShift trabaja con barras reales. La suma de comprobación coincidirá sólo en los timeframes MN1 y W1, porque no hay agujeros en el historial de dichas barras.
El rendimiento será mayor si utiliza un paso de tiempo pequeño en el bucle (menos de un día) cuando el algoritmo empieza a trabajar para guardar los cálculos anteriores:

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)    ========================================================================


Los valores excesivos para el algoritmo a través de iBarShift (resaltados en azul) son causados por la falta actual de historia necesaria o TFs calculados por la matriz, que inicia su carga.
Después de la carga el resultado será el siguiente:

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)    ========================================================================

Archivos adjuntos:
 
Nikolai Semko #:

Los aficionados a los algoritmos rápidos. Los que luchan por los nanosegundos :)

...

😮😲😳🥴🤪

...

ah...

mmm....

oooh....

gkghm... No pensé que mi simple pregunta saldría así.

Justo así. Oh.

 
Artyom Trishkin #:

😮😲😳🥴🤪

...

ah...

mmm.

ohhhh....

ejem. No pensé que mi simple pregunta saldría así.

Oh.

Sí, Artem, me engañaste por un momento.
Era un interés deportivo.
Espero que le sea útil a alguien, incluyéndome a mí. :))

 
Nikolai Semko #:

Sí, Artem, me has engañado por un tiempo.
He trabajado en el interés deportivo.
Espero que sea útil para alguien, y yo entre otros. :))

Por supuesto que sí. Estupendo. Gracias de nuevo.

S.F. Esto me ha hecho gracia: "cuenta correctamente sólo hasta el 28.02.2100 !!!!".

¿Qué hacemos después?

 
Artyom Trishkin #:

Por supuesto que será útil. Estupendo. ¡Gracias de nuevo!

S.F. Esto me ha hecho gracia: "cuenta correctamente sólo hasta el 28.02.2100 !!!!".

¿Qué hacemos después?

jaja.
Dudo que este algoritmo tenga demanda durante 75 años. Los ordenadores cuánticos probablemente ya dominarán el mundo, con una programación completamente diferente.
Para ser honesto, era perezoso tener en cuenta el calendario gregoriano. El año 2000 era muy importante, el 2100 ya no lo es.

 
Nikolai Semko #:

jaja.
dudo que este algoritmo tenga demanda dentro de 75 años. Los ordenadores cuánticos probablemente ya dominarán el mundo, con una programación completamente diferente.
para ser honesto, fue perezoso tener en cuenta el calendario gregoriano por completo. El año 2000 era muy importante, el 2100 ya no lo es.

Para MN puedes usar un array precalculado, no hay casi nada ahí dentro

Ln2(12 meses * cien años)...11 if`'s y comparaciones en busqueda binaria, pero sin otros calculos.

 
Maxim Kuznetsov #:

Puedes usar un array precalculado para MN, apenas hay datos ahí.

Ln2(12 meses * cien años)...11 if`'s y comparaciones en búsqueda binaria, pero sin otros cálculos.

No hay dificultades. Sé cómo implementarlo.
Simplemente no quiero hacer algo que estoy 100% seguro de que nunca será útil.
 
Maxim Kuznetsov #:

Puedes usar un array precalculado para MN, apenas hay datos ahí.

Ln2(12 meses * cien años)...11 if`'s y comparaciones en búsqueda binaria, pero sin otros cálculos.

ah, lo leí mal al principio.
No, estás equivocado. El aumento de rendimiento no funcionará. Usted todavía estará atascado en los cálculos. Y el acceso a los elementos del array ralentiza mucho el algoritmo.

Razón de la queja: