Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 229

 

Englisch (Original): Ich möchte einen Antrag auf eine MQL-Sprachfunktion stellen. Wenn dies nicht der richtige Thread ist, lassen Sie es mich bitte wissen. Die ursprüngliche Anfrage befindet sich im englischen Forum ...

Russisch (Google-Übersetzung): Ich möchte einen Antrag für eine MQL-Sprachfunktion stellen. Wenn dies nicht der richtige Thread ist, lassen Sie es mich bitte wissen. Die ursprüngliche Anfrage befindet sich im englischen Forum ...

 

Wie füllt man ein Array mit einer Zeile?

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

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

clr[].uncheck={0x999999,0x999999};//как правильно?
 
Pavel Kolchin füllt man ein Array mit einer Zeile?
clr_struct clr[] = {{0x999999}, {0x999999}};
 

Ein weiterer Lifehack für Zugriffsrechte: Wenn Sie den unwiderstehlichen Wunsch haben, einer anderen Klasse Zugriff auf private Felder/Funktionen einer Klasse zu gewähren, können Sie mit den Standard-MQL-Werkzeugen Folgendes tun:

Wir müssen: den Zugriff auf A::f1() von B aus ermöglichen.

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

class B {};

Lassen Sie uns das so umschreiben:

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;

Um (A)a.f1() innerhalb von B aufzurufen, rufen Sie CallAf1(a) auf. Wenn f1() Parameter hat, fügen wir sie zu CallAf1() hinzu.

Test:

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

Sie können CallAf1() geschützt machen, aber das wird ein großes Loch in die Zugriffsrechte reißen - irgendwo im Code können Sie einen Nachkommen der Klasse B erstellen und darin eine öffentliche Methode, um CallAf1() aufzurufen - d.h. jeder wird Zugriff auf A::f1() haben.


P.S. Das Konstrukt ist sehr umständlich (wenn Sie wollen, können Sie es in Makros packen), aber es hat einen Vorteil gegenüber Friend C++: Es gibt Zugriff nicht auf alle Klassenmitglieder, sondern nur auf ausgewählte.

 
mktr8591 #:

Ein weiterer Lifehack für Zugriffsrechte: Wenn Sie den unwiderstehlichen Wunsch haben, einer anderen Klasse Zugriff auf private Felder/Funktionen einer Klasse zu gewähren, können Sie dies mit den Standard-MQL-Werkzeugen tun

Es hat lange gedauert, bis ich das verstanden habe... guter Schritt mit der Virtualisierung, danke!
 
fxsaber #:
Es hat lange gedauert, bis ich mich darauf eingelassen habe... guter Schritt mit der Virtualisierung, danke!
Das einzige, was ich am Anfang nicht geschrieben habe, ist, dass man keine Objekte der Klasse B::AB2 (und deren Nachkommen) mehr erstellen kann, sonst fällt alles auseinander :-)
 
Wenn Sie diesen Expert Advisor im Tester im Modus "Alle Symbole" ausführen
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);
}
zeigt, dass alle Preise mit dem Algorithmus NormalizeDouble normalisiert werden. Wenn Sie mit Preisen arbeiten, die nicht vom Terminal, sondern durch Parsing oder manuelle Eingabe erhalten wurden, müssen diese normalisiert werden, um korrekt zu funktionieren. Es gibt keinen Grund, sich zu irren.
 

REASON_ACCOUNT (auch wenn das Konto nicht geändert wird, sondern nur ein Re-Login erfolgt) wird der Expert Advisor komplett entladen und eine neue Kopie geladen.

Aus diesem Grund wirkt sich ExpertRemove in OnDeinit nicht auf die neue Kopie aus, da es die entladene Kopie berührt.

void OnInit() { Print(__FUNCSIG__); }

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


Ergebnis nach Neuanmeldung.

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


Nach Deinit wartet die neue EA-Kopie mehr als eine Sekunde (bis zu zwei Sekunden), um zu starten. Was sind die Gründe für eine so lange Wartezeit und ist es möglich, diese zu verkürzen?

 

SymbolInfoTick gibt bei jedem dieser drei Aufrufe den neuesten Tick zurück. Das heißt, die so genannte Sammlung von Ticks ohne Überspringen von Indikatoren ist gelinde gesagt fragwürdig.


Beweis für die Unmöglichkeit des Sammelns von Ticks durch einen Indikator (ohne Überspringen).

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


Ergebnis.

                 [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
 
Eines der möglichen Konstrukte der MQL5-Sprache.

Forum über Trading, automatisierte Handelssysteme und das Testen von Handelsstrategien

Fehler, Bugs, Fragen

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

Leider zieht MQL4 diese Art von Arbeit noch nicht.