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

 
Igor Makanu:

IsInf() y IsNaN() funcionan,

IsEqual() e IsZerro() son cuestionables, buscados en Google como "truco para el doble".

IsNan() funciona, pero IsInf() no

IsInf( DBL_MIN_DENORM) == true

¿Desde cuándo los números desnormalizados son infinitos?

Y todas estas comparaciones con épsilon - épsilon debe aumentar proporcionalmente a los operandos. En general, no hay una receta universal, yo uso Punto como épsilon (con operandos redondeados) y no quiero (ni necesito) comparar la diferencia con DBL_EPSILON.

 
Vict:

Y todas estas comparaciones con épsilon - épsilon debe aumentar proporcionalmente a los operandos. En general, no hay una receta universal, yo uso Punto como épsilon (con operandos redondeados), no quiero comparar la diferencia con DBL_EPSILON(y no lo necesito).

encontré un artículo que leí ayer de TVhttps://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

Sí, debe utilizar otro ejemplo en el que debe especificar la precisión de la comparación

Victora:

IsNan() funciona, pero IsInf() no

¿Desde cuándo los números desnormalizados son infinitos?

MQL parece normalizar hasta el octavo dígito, es decir, si se añade NormalizeDouble() a IsInf(), el resultado seguirá sin ser mejor.

 
Igor Makanu:

la normalización en MQL parece ser hasta el 8º dígito, es decir, si se añade NormalizeDouble() a IsInf(), el resultado sigue sin ser mejor

La normalización en MQL no es para nada lo mismo, no sé por qué nombraron la función así. https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%B0

 
Accidentalmente descubrí en ME que se pueden crear marcadores con CTRL+1, CTRL+2, ..... Y cambiar entre ellos con ALT+1, ALT+2, ...
 
// Количество успешных OrderSend.
int GetOrderSendSucceeded()
{
  MqlTradeRequest Request = {0};
  MqlTradeResult Result;

  return(OrderSend(Request, Result) ? 0 : (int)Result.request_id + 1);
}

Muestra el número de órdenes comerciales síncronas (OrderSend) y asíncronas generadas con éxito en la Terminal en total (desde el inicio).

Lo uso en el Probador (al final) para ver cuántas veces se han modificado los pedidos.

 
Hay pocas personas que no sepan crear clases de TC con sus propios On-events, por ejemplo.

Foro sobre comercio, sistemas de comercio automatizados y pruebas de estrategias

¿OnTick() no funciona en una instancia de clase?

fxsaber, 2019.10.31 23:45

class BASE
{  
private:
  static BASE* Objects[];
  
public:
  BASE()
  {
    BASE::Objects[::ArrayResize(BASE::Objects, ::ArraySize(BASE::Objects) + 1) - 1] = &this;
  }
  
  ~BASE()
  {
    const int Size = ::ArraySize(BASE::Objects);
    
    for (int i = Size - 1; i >= 0; i--)
      if (BASE::Objects[i] == &this)
      {
        for (int j = i; j < Size - 1; j++)
          BASE::Objects[j] = BASE::Objects[j + 1];
          
        ::ArrayResize(BASE::Objects, Size - 1);
        
        break;
      }
  } 
    
  virtual void OnTick() = 0;
  
  static void AllTick()
  {
    for (int i = ::ArraySize(BASE::Objects) - 1; i >= 0; i--)
      BASE::Objects[i].OnTick();
  }
};

static BASE* BASE::Objects[];


class A : BASE
{
  virtual void OnTick()
  {
    Print(__FUNCSIG__);
  }
};

class B : BASE
{
  virtual void OnTick()
  {
    Print(__FUNCSIG__);
  }
};

A a;
B b;

void OnTick()
{
  BASE::AllTick();
}


Heredar de BASE, entonces los métodos OnTick en las clases serán llamados automáticamente.

 

Un ejemplo de uso de la macro X (no te preocupes por los tipos oscuros, lo he sacado de un código de trabajo. El vector es un array dinámico):

Por ejemplo:

   vector_fund<upindex_t> seg2; vector_ref<vector_fund<upindex_t>> seg2_sub;
   vector_fund<upindex_t> seg3; vector_ref<vector_fund<upindex_t>> seg3_sub;
   vector_fund<upindex_t> seg4; vector_ref<vector_fund<upindex_t>> seg4_sub;
   for (uint i = 0;  i < 5114;  ++ i) {
      restore_image(seg2, "seg2"); restore_subimages(seg2_sub, "seg2");
      restore_image(seg3, "seg3"); restore_subimages(seg3_sub, "seg3");
      restore_image(seg4, "seg4"); restore_subimages(seg4_sub, "seg4");
      
      if (true) {} // тест №1, использует seg2 и seg2_sub
      if (true) {} // тест №2, использует seg3 и seg3_sub
      if (true) {} // тест №3, использует seg4 и seg4_sub
   }

1. queremos definir vectores detrás del bucle para evitar asignaciones constantes.

2. Cada una de las pruebas puede ser desactivada (en realidad hay muchas).

3. restore_image() y restore_subimages(), una función pesada y que consume mucho tiempo (lectura de objetos del gráfico).

4. Si ninguna de las pruebas utiliza seg2, por ejemplo, me gustaría eliminar tanto la definición como el correspondiente restore...() en una sola acción, para evitar una situación en la que el vector esté definido pero vacío debido al restore...() comentado, lo que daría resultados erróneos.

¿Qué hacer?

#define  DEFSEG_LIST    \
   DEFSEG_HELPER(seg2) \
   DEFSEG_HELPER(seg3) \
   DEFSEG_HELPER(seg4)
   
#define  DEFSEG_HELPER(SEG) vector_fund<upindex_t> SEG; vector_ref<vector_fund<upindex_t>> SEG##_sub;
    DEFSEG_LIST;
#undef  DEFSEG_HELPER
   
   for (uint i = 0;  i < 5114;  ++ i) {
#define  DEFSEG_HELPER(SEG) restore_image(SEG, #SEG);  restore_subimages(SEG##_sub, #SEG);
    DEFSEG_LIST;
#undef  DEFSEG_HELPER
      ...
   }

Simplemente comenta los segx innecesarios en DEFSEG_LIST. Esto generará los mismos resultados que en el primer código. En realidad es una pena que el compilador no pueda mostrar la salida del procesador (el análogo gcc -E).

 

A veces, en la optimización genética, los primeros miles de pases son suficientes para entender más o menos el resultado.

Cuando se ejecuta automáticamente una gran cantidad de optimizaciones, se quiere que todo funcione más rápido. Por eso necesitaremos un mecanismo para interrumpir la optimización.

#include <fxsaber\MultiTester\MTTester.mqh>  // https://www.mql5.com/ru/code/26132

// Выключает Оптимизацию ( и одиночный проход)
bool OptimizationStop( void )
{
  return(!MTTESTER::IsReady() && MTTESTER::ClickStart(false));
}


Uso.

// Демонстрация прерывания Оптимизации.

sinput int inAmountPasses = 20; // Через сколько проходов закончить
input int Range = 0; // 0..10000

double OnTester()
{
  int Data[];
  
  return(FrameAdd(NULL, 0, 0, Data)); // Сгенерировали TesterPass
}

void OnTesterPass()
{
  static int Amount = 0;
  
  ulong Pass;
  string Name;
  long ID;
  double Value;
  int Data[];

  while (FrameNext(Pass, Name, ID, Value, Data))
    if (++Amount > inAmountPasses)
    {
      OptimizationStop(); // Как достигли нужного количества проходов, выключили оптимизатор.
      
      break;
    }
}
 

Instrucciones para abrir un gráfico con un carácter nulo.


  1. Borrar todos los gráficos de Market Watch.
  2. Iniciar la optimización de un marco EA (por ejemplo, éste) en modo matemático.
  3. Detener la optimización y eliminar el marco EA del gráfico de símbolos nulos.
Un gráfico de este tipo puede ser probablemente útil para ahorrar recursos.
 
Me he encontrado con esta peculiaridad.
class A
{
  static int i;
} a; // unresolved static variable 'A::i'

static int A::i = 0;

A b; // Надо прописывать после static


Si se crea inmediatamente una clase con campos estáticos mientras se define una clase, se producirá un error de compilación.