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

 

Español (original): Me gustaría hacer una solicitud de característica de idioma MQL. Si este no es el hilo correcto, por favor hágamelo saber. La solicitud original está en el foro Inglés ...

Ruso (Google translate): Me gustaría hacer una solicitud de función de idioma MQL. Si este no es el hilo correcto, por favor hágamelo saber. La solicitud original está en el foro Inglés ...

 

¿cómo rellenar un array con una línea?

struct clr_struct{
   color uncheck;
};
clr_struct clr[];

//clr[0].uncheck=0x999999;
//clr[1].uncheck=0x999999;

clr[].uncheck={0x999999,0x999999};//как правильно?
 
Pavel Kolchin rellenar un array con una línea?
clr_struct clr[] = {{0x999999}, {0x999999}};
 

Un truco más para los derechos de acceso: Si tienes un deseo irresistible de dar acceso a campos/funciones privadas de una clase a otra clase, puedes hacer lo siguiente usando herramientas MQL estándar:

Necesitamos: dar acceso a A::f1() desde B

//--------- как было
class   A
  {
   int               m;
   int               f1() {return m;}                       // нужно дать к нему доступ классу B
public:
                     A(int a): m(a) {}
  };

class B {};

Vamos a reescribirlo así

class A;
class B
  {
private:
   class AB
     {
   public:
      virtual int    CallAf1(A&) const  = 0;
                     AB() {ABptr = &this;}
     } static *ABptr;

   // внутри B используем  этот метод для получения доступа к A::f1()
   static int        CallAf1(A & obj)
     {
      return ABptr.CallAf1(obj);
     }

public:
   class AB2: AB {};

   // вспомогательный метод - только для проверки
   static void       _f1_test(A & obj)
     {
      Print("test ", CallAf1(obj));
     }
  };
B::AB *B::ABptr = NULL;

class   A
  {
   int               m;
   int               f1() {return m;}
public:
                     A(int a): m(a) {}

   //--  добавлено
private:
   class AB3: B::AB2
     {
      int            CallAf1(A &obj) const {return obj.f1();}
     }   static  const     ABlink;
  };
const A::AB3 A::ABlink;

Para llamar a (A)a.f1() dentro de B, llama a CallAf1(a). Si f1() tiene parámetros, los añadimos a CallAf1().

Prueba:

void OnStart()
  {
    A f(2);
    B::_f1_test(f);
  }

Puedes hacer CallAf1() protegida, pero será un gran agujero en los derechos de acceso - en cualquier parte del código puedes crear un descendiente de la clase B y en él un método público para llamar a CallAf1() - es decir, todo el mundo tendrá acceso a A::f1().


P.D. La construcción es muy engorrosa (si quieres, puedes meterla en macros), pero tiene una ventaja sobre el amigo C++: no da acceso a todos los miembros de la clase, sino sólo a los seleccionados.

 
mktr8591 #:

Otro truco para los derechos de acceso: Si tiene un deseo irresistible de conceder acceso a campos/funciones privados de una clase a otra clase, puede hacerlo utilizando las herramientas MQL estándar

Me llevó mucho tiempo ponerme a ello... buen movimiento con la virtualización, ¡gracias!
 
fxsaber #:
Tardé mucho en ponerme a ello... Buen movimiento con la virtualización, ¡gracias!
Lo único que no escribí al principio es que no se pueden crear más objetos de la clase B::AB2 (y sus descendientes), de lo contrario todo se vendrá abajo :-)
 
Ejecutando este Asesor Experto en el Probador en el modo de todos los símbolos
input int inTmp = 0; // https://www.mql5.com/ru/forum/321656/page90#comment_44727856

bool Res = true;

// Проверяет, нормализована ли цена по алгоритму NormalizeDouble.
bool IsNDPrice( const double &Price )
{
  return(Price == NormalizeDouble(Price, 5));
}

// Проверяет, нормализована ли цена, как при парсинге или ручном вводе.
bool IsNDPrice2( const double &Price )
{
  return(Price == (double)DoubleToString(Price, 5));
}

void OnTick()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))
//    Res &= IsNDPrice(Tick.bid) && IsNDPrice(Tick.ask); // OnTester == 1.
    Res &= IsNDPrice2(Tick.bid) && IsNDPrice2(Tick.ask); // OnTester == 0.
}

double OnTester()
{
  return(Res);
}
muestra que todos los precios se normalizan utilizando el algoritmo NormalizeDouble. Y que si se trabaja con precios obtenidos no del Terminal, sino por parseo o entrada manual, requieren normalización para su correcto funcionamiento. No hay que equivocarse.
 

REASON_ACCOUNT (aunque no se cambie la cuenta, sino que simplemente se vuelva a iniciar sesión) se descarga completamente el Asesor Experto y se carga una copia nueva.

Por esta razón ExpertRemove en OnDeinit no afecta a la nueva copia, porque toca a la descargada.

void OnInit() { Print(__FUNCSIG__); }

void OnDeinit( const int ) { Print(__FUNCSIG__); }


Resultado tras el reinicio.

2023.02.07 11:33:12.717 Test5-3 (EURUSD,M1)     void OnDeinit(const int)
2023.02.07 11:33:13.926 Test5-3 (EURUSD,M1)     void OnInit()


Después de Deinit, la nueva copia de EA espera más de un segundo (hasta dos segundos) para iniciarse. ¿Cuáles son las razones de una espera tan larga y es posible acelerarla?

 

SymbolInfoTick devolverá el último tick en cada una de esas tres llamadas. Es decir, la llamada colección de ticks sin saltar a través de indicadores es cuestionable, por decirlo suavemente.


Prueba de la imposibilidad de recoger ticks por un indicador (sin saltos).

// Аналог Sleep для индикатора.
void Sleep2( const uint Pause )
{
  const uint StartTime = GetTickCount();
  
  while (!IsStopped() && (GetTickCount() - StartTime) < Pause)
    ;
}

#define  TOSTRING(A) #A + " = " + (string)(A) + " "

int OnCalculate( const int rates_total,
                 const int,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[] )
{  
  static const int period = PeriodSeconds();
  
  Sleep2(1000); // Расчеты.
  
  MqlTick Tick[1];
  
  if (SymbolInfoTick(_Symbol, Tick[0]) &&
      ((Tick[0].bid != close[rates_total - 1]) || // Свежий бар не соответсвует последнему тику.
       Tick[0].time / period > time[rates_total - 1] / period))
  {
    ArrayPrint(Tick);
    Print(TOSTRING(time[rates_total - 1]) + TOSTRING(close[rates_total - 1]));
  }

  return(rates_total);
}


Resultado.

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:39 1.54951 1.54959 0.0000        0 1675787319322      98       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.5495 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:40 1.54948 1.54959 0.0000        0 1675787320719      98       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.5495 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:41 1.54952 1.54960 0.0000        0 1675787321823     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54954 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:42 1.54954 1.54961 0.0000        0 1675787322223     102       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54951 00000000002 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:43 1.54955 1.54964 0.0000        0 1675787323721     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54948 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:44 1.54954 1.54962 0.0000        0 1675787324323     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54952 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:45 1.54956 1.54962 0.0000        0 1675787325421     102       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54952
 
Una de las posibles construcciones del lenguaje MQL5.

Foro sobre trading, sistemas de trading automatizados y prueba de estrategias de trading

Errores, bugs, preguntas

fxsaber, 2023.02.14 13:11

input string inStr = "B2";

class A {};

class B1 : public A {};
class B2 : public A {};
// .....
class B100 : public A {};

void OnStart()
{
  A* a = New2(inStr); // создает объект, который прописан в inStr.
}

// Решение.
template <typename T>
A* New( const string &ClassName ) { return((typename(T) == ClassName) ? new T : NULL); }

typedef A* (*TNew)( const string& );
static const TNew FuncNew[] = {New<B1>, New<B2>, /*....,*/ New<B100>};

A* New2( string ClassName )
{  
  A* Res = NULL;
  
  ClassName = "class " + ClassName;
  
  for (int i = ArraySize(FuncNew) - 1; !Res && (i >= 0); i--)
    Res = FuncNew[i](ClassName);  
    
  return(Res);
}

Desafortunadamente, MQL4 no tira de este tipo de trabajo todavía.