Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 229

 

Inglese (originale): Vorrei fare una richiesta di funzionalità della lingua MQL. Se questo non è il thread corretto, fatemelo sapere. La richiesta originale è sul forum inglese ...

Russo (Google translate): Vorrei fare una richiesta di funzionalità della lingua MQL. Se questo non è il thread corretto, fatemelo sapere. La richiesta originale è sul forum inglese ...

 

come riempire un array con una riga?

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

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

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

Un altro lifehack per i diritti di accesso: Se si ha un desiderio irresistibile di dare accesso a campi/funzioni private di una classe a un'altra classe, si può fare quanto segue usando gli strumenti standard di MQL:

Abbiamo bisogno di: rendere possibile l'accesso ad A::f1() da parte di B

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

class B {};

Riscriviamo in questo modo:

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;

Per chiamare (A)a.f1() all'interno di B, chiamare CallAf1(a). Se f1() ha dei parametri, li aggiungiamo a CallAf1().

Prova:

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

Si può rendere protetta CallAf1(), ma sarà un grosso buco nei diritti di accesso: in qualsiasi punto del codice si può creare un discendente della classe B e in esso un metodo pubblico per chiamare CallAf1() - cioè tutti avranno accesso a A::f1().


P.S. Il costrutto è molto macchinoso (se si vuole, lo si può racchiudere in macro), ma ha un vantaggio rispetto all'amico C++: non dà accesso a tutti i membri della classe, ma solo a quelli selezionati.

 
mktr8591 #:

Un altro trucco per i diritti di accesso: Se avete un desiderio irresistibile di concedere l'accesso a campi/funzioni private di una classe ad un'altra classe, potete farlo utilizzando gli strumenti standard di MQL

Mi ci è voluto molto tempo per capirlo... buona mossa con la virtualizzazione, grazie!
 
fxsaber #:
Ci è voluto molto tempo per entrare in gioco... buona mossa con la virtualizzazione, grazie!
L'unica cosa che non ho scritto all'inizio è che non si possono creare altri oggetti di classe B::AB2 (e i suoi discendenti), altrimenti tutto va a rotoli :-)
 
L'esecuzione di questo Expert Advisor nel Tester in modalità tutti i simboli
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);
}
mostra che tutti i prezzi sono normalizzati utilizzando l'algoritmo NormalizeDouble. E che se si lavora con prezzi ottenuti non dal Terminale, ma tramite parsing o input manuale, essi richiedono la normalizzazione per un corretto funzionamento. Non c'è bisogno di sbagliarsi.
 

REASON_ACCOUNT (anche se il conto non viene cambiato, ma viene solo rifatto il login) l'Expert Advisor viene completamente scaricato e ne viene caricata una nuova copia.

Per questo motivo ExpertRemove in OnDeinit non ha effetto sulla nuova copia, perché tocca quella scaricata.

void OnInit() { Print(__FUNCSIG__); }

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


Risultato dopo il relogin.

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


Dopo Deinit, la nuova copia di EA attende più di un secondo (fino a due secondi) per avviarsi. Quali sono le ragioni di un'attesa così lunga ed è possibile velocizzarla?

 

SymbolInfoTick restituirà l'ultimo tick in ognuna di queste tre chiamate. In altre parole, la cosiddetta raccolta di tick senza saltare attraverso gli indicatori è discutibile, per usare un eufemismo.


Prova dell'impossibilità di raccogliere i tick da un indicatore (senza salti).

// Аналог 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);
}


Risultato.

                 [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
 
Uno dei possibili costrutti del linguaggio MQL5.

Forum sul trading, sui sistemi di trading automatizzati e sulla verifica delle strategie di trading

Errori, bug, domande

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

Sfortunatamente, MQL4 non è ancora in grado di svolgere questo tipo di lavoro.

Motivazione: