Bibliotheken: TypeToBytes

 

TypeToBytes:

Byteweise Operationen mit Strukturen und Standarddatentypen.

Autor: fxsaber

 
Ein kurzes Beispiel für die Verwendung der Bibliothek

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Zwei benachbarte BookEvents können einen Stapel duplizieren

fxsaber, 2016.09.14 16:29

EA zeigt, wann zwei benachbarte Stapel Kopien voneinander sind

#include <TypeToBytes.mqh> // https://www.mql5.com/de/code/16280

template <typename T>
bool ArrayEqual( const T &Array1[], const T &Array2[] )
{
  const int Amount = ArraySize(Array1);
  bool Res = (Amount == ArraySize(Array2));

  if (Res)
    for (int i = 0; i < Amount; i++)
      if (_R(Array1[i]) != Array2[i]) // https://www.mql5.com/de/code/16280
      {
        Res = false;

        break;
      }

  return(Res);
}

template <typename T>
bool ArrayClone( const T &Source[], T &Target[] )
{
  ArrayFree(Target);

  return(ArrayCopy(Target, Source) >= 0);
}

void OnInit( void )
{
  MarketBookAdd(_Symbol);
}

void OnDeinit( const int Reason )
{
  MarketBookRelease(_Symbol);
}

void OnBookEvent( const string &symbol )
{
  static MqlBookInfo PrevBook[];
  MqlBookInfo Book[];

  if ((symbol == _Symbol) && MarketBookGet(symbol, Book))
  {
    if (ArrayEqual(Book, PrevBook))
    {
      if (ArraySize(PrevBook) > 0)
        Alert("Book == PrevBook");
    }
    else
      ArrayClone(Book, PrevBook);
  }
}

Ergebnis

2016.09.14 17:24:30.896 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:30.896 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:30.896 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:30.896 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:30.896 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:30.896 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:30.896 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:30.896 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:29.406 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:23.151 Test2 (Si-9.16,M1)      Book == PrevBook
2016.09.14 17:24:23.151 Test2 (Si-9.16,M1)      Book == PrevBook
Es kann viele Gründe für solche Situationen geben: vom MT5, der einige Einsätze überspringt, bis zur Erzeugung von doppelten Einsätzen durch die Börse selbst.

 
Ein weiteres Beispiel

Forum zum Thema Handel, automatische Handelssysteme und Testen von Handelsstrategien

Testen von 'CopyTicks'

fxsaber, 2016.09.15 10:07 AM

Wie andere CopyTicks nutzen, ist mir schleierhaft. Das Vertrauen ist leider nicht vorhanden. Sehr roh.

Advisor .

#include <TypeToBytes.mqh> // https://www.mql5.com/de/code/16280

void OnTick( void )
{
  static MqlTick PrevTick;  
  static int Amount = 0;
  
  MqlTick Ticks[];
  
  if (Amount > 0)
  {
    Amount = CopyTicks(_Symbol, Ticks, COPY_TICKS_ALL, PrevTick.time_msc);
    
    int i;
    
    for (i = 0; i < Amount; i++)
      if (_R(Ticks[i]) == PrevTick) // https://www.mql5.com/de/code/16280
        break;
        
    if (i == Amount)
      Print("In der Geschichte (Länge = " + (string)Amount + ") gibt es kein Häkchen, das auf dem vorherigen Ereignis war.");
  }
  else
    Amount = CopyTicks(_Symbol, Ticks, COPY_TICKS_ALL, TimeCurrent() * 1000);
    
  if (Amount > 0)
    PrevTick = Ticks[Amount - 1];  
}

Ergebnis .

2016.09.15 11:04:02.810 Test2 (RTS-9.16,M1)     В истории (length = 2) нет тика, что был на предыдущем Event.
2016.09.15 11:03:59.312 Test2 (RTS-9.16,M1)     В истории (length = 13) нет тика, что был на предыдущем Event.
2016.09.15 11:03:59.290 Test2 (RTS-9.16,M1)     В истории (length = 1) нет тика, что был на предыдущем Event.

Ein Tick, der in der Historie war, ist beim nächsten Tick-Ereignis nicht mehr in der Historie!

Liebe Entwickler, bringt CopyTicks in einen funktionierenden Zustand. Selbst einfache Tests schlagen fehl.


 
Ich habe ein Schlupfloch gefunden, das es mir erlaubt, solche umständlichen Einträge zu ersetzen
_W(Tick, Offset, (double)1.23456);     // Schreiben Sie den Wert (double)1.23456 an den gefundenen Offset
_W(CloneTick, 0, Tick);                // Schreiben des Wertes des Strukturobjekts Tick mit Null-Offset in CloneTick
_W(Color, 2, (uchar)230);              // Schreiben Sie den Wert (uchar)230 an Offset 2.
anstelle solcher sperrigen Einträge zu ersetzen.
_W(Tick)[Offset] = 1.23456;             // Schreiben Sie den Wert (double)1.23456 an den gefundenen Offset
_W(CloneTick)[0] = Tick;                // Schreiben des Wertes des Strukturobjekts Tick mit Null-Offset in CloneTick
_W(Color)[2] = (uchar)230;              // Schreiben Sie den Wert (uchar)230 an Offset 2.

D.h. es gibt eine echte Möglichkeit, mit Standardtypen und einfachen Strukturen wie mit einem Array zu arbeiten, und zwar nicht nur im Lesemodus, sondern auch im Schreibmodus!
 
fxsaber:
Ich habe ein Schlupfloch gefunden, das es mir erlaubt, solche umständlichen Einträge zu ersetzen
um die üblichen

D.h. es gibt eine echte Möglichkeit, mit Standardtypen und einfachen Strukturen wie mit einem Array zu arbeiten, nicht nur im Lesemodus, sondern auch im Schreibmodus!

Veröffentlicht. Jetzt für jede Variable (Struktur oder Standard-Typ) funktioniert nicht nur lesen, wie mit einem Array, sondern auch WRITE:

_W(AnyVariable)[Pos] = AnyValue; // Schreibt den AnyValue-Wert an Byte-Offset Pos in die Variable AnyVariable

Das war vor der Implementierung nicht leicht zu erraten - ich schätze, es hat sich als guter Test für durchschnittliche OOP-Kenntnisse erwiesen: Ich kenne nur die Klassiker für Klassen.

Wenn jemand etwas ähnliches kennt, bitte einen Link für die Ausbildung teilen.

 
Beispiel für die Anzeige des Byte-Inhalts einer Variablen
#include <TypeToBytes.mqh>

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

string BytesToString( const uchar &Bytes[] )
{  
  string Str = "";

  const int Amount = ArraySize(Bytes);
  
  for (int i = 0; i < Amount; i++)
    Str += TOSTRING(i) + "," + TOSTRING(Bytes[i]) + "\n";
    
  return(Str);
}

#define  VALUETOSTRING(A) typename(A) + TOSTRING(A) + ":\n" + BytesToString(_R(A).Bytes)

void OnStart()
{
  int Tmp = 1;  
  Print(VALUETOSTRING(Tmp));
  
  Tmp = -1;
  Print(VALUETOSTRING(Tmp));
}
Ergebnis
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)      i = 3, Bytes[i] = 255
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)      i = 2, Bytes[i] = 255
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)      i = 1, Bytes[i] = 255
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)      i = 0, Bytes[i] = 255
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)     int Tmp = -1:
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)     
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)      i = 3, Bytes[i] = 0
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)      i = 2, Bytes[i] = 0
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)      i = 1, Bytes[i] = 0
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)      i = 0, Bytes[i] = 1
2016.10.02 20:26:52.383 Test (RTS-12.16,M1)     int Tmp = 1:
 
Kurzer Nicht-eine-Zahl-Doppelvergleich

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Wie vergleicht man schnell Double und QNaN ?

fxsaber, 2016.10.11.11:14 pm.

Das ist cool, das wusste ich nicht! Na dann mal her damit
#include <TypeToBytes.mqh>

double Nan(long bit_value)
  {
   struct L { long   x; } l; l.x=bit_value;
   struct D { double x; } d=(D)l;
   return(d.x);
  }

double QNaN   =Nan(0x7FF7000000000000);  

void OnStart()
{
   if (_R(QNaN)==QNaN) {
      Alert("QNaN is QNaN");
   } else {
      Alert("Ooops");
   }   
}

 
Beispiel für die Erstellung von Nicht-eine-Zahl-Double
#include <TypeToBytes.mqh>

void OnStart()
{
  double QNaN = 0;
  
  _W(QNaN) = 0x7FF7000000000000;
  
  Print(QNaN);
}

 
Beispiel für eine neue Funktion berührt nicht direkt die Bibliothek, sondern indirekt berührt - zum Thema Strukturen

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien.

MetaEditor Build 1463

fxsaber, 2016.11.10:42 AM

class PRINTCLASS
{
public:  
  template <typename T>
  static void MyPrint( const T &Value )
  {
    T Array[1];
    
    Array[0] = Value;
    
    ::ArrayPrint(Array);
  }
  
  template <typename T>
  static void MyPrint( const T Value )
  {
    ::Print(Value);
  }
};

#define Print(A) PRINTCLASS::MyPrint(A)

void OnStart()
{
  MqlTick Tick;
  
  SymbolInfoTick(_Symbol, Tick);

  Print(Tick);
  
  int i = 5;
  
  Print(i);
}
Print kann nun auch einfache Strukturen ausdrucken.
 
fxsaber:
Beispiel für die Erstellung eines Nicht-eine-Zahl-Doppels
#include <TypeToBytes.mqh>

void OnStart()
{
  double QNaN = 0;
  
  _W(QNaN) = 0x7FF7000000000000;
  
  Print(QNaN);
}

Jetzt können wir es anders machen

#include <TypeToBytes.mqh>

void OnStart()
{
  double Number = (double)"01.23_example";
  double Nan = (double)"nan";
  
  Print(Number);
  Print(Nan);
  
  ArrayPrint(_R(Nan).Bytes); // Bytes drucken
  
  ulong Num = 0;
  
  _W(Num) = Nan; // Byte-für-Byte-Kopieren von Nan nach Num
    
  PrintFormat("%I64X", Num);
}

Ergebnis

1.23
nan
255 255 255 255 255 255 255 127
7 F FFFFFFFFFFFFFF
 
fxsaber:

Jetzt können wir es anders machen

#include <TypeToBytes.mqh>

void OnStart()
{
  double Number = (double)"01.23_example";
  double Nan = (double)"nan";
  
  Print(Number);
  Print(Nan);
  
  ArrayPrint(_R(Nan).Bytes); // Bytes drucken
  
  ulong Num = 0;
  
  _W(Num) = Nan; // Byte-für-Byte-Kopieren von Nan nach Num
    
  PrintFormat("%I64X", Num);
}

Ergebnis

1.23
nan
255 255 255 255 255 255 255 127
7 F FFFFFFFFFFFFFF
Haben Sie den Quellcode in der Veröffentlichung aktualisiert?