Libraries: TypeToBytes

 

TypeToBytes:

Byte-wise operation with structures and standard data types.

Author: fxsaber

 
A short example of how to use the library

Forum on trading, automated trading systems and testing trading strategies

Two neighbouring BookEvent can duplicate a stack

fxsaber, 2016.09.14 16:29

EA shows when two neighbouring stacks are copies of each other

#include <TypeToBytes.mqh> // https://www.mql5.com/en/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/en/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);
  }
}

Result

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
There can be many reasons for such situations: from MT5 skipping some stakes, to generation of double stakes by the exchange itself.

 
Another example

Forum on trading, automated trading systems and testing trading strategies

Testing 'CopyTicks'

fxsaber, 2016.09.15 10:07 AM

How others use CopyTicks is beyond me. There is no trust, unfortunately. Very raw.

Advisor

#include <TypeToBytes.mqh> // https://www.mql5.com/en/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/en/code/16280
        break;
        
    if (i == Amount)
      Print("In the story (length = " + (string)Amount + ") there is no tick that was on the previous Event.");
  }
  else
    Amount = CopyTicks(_Symbol, Ticks, COPY_TICKS_ALL, TimeCurrent() * 1000);
    
  if (Amount > 0)
    PrevTick = Ticks[Amount - 1];  
}

Result

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.

A Tick that was in the history is no longer in the history at the next Tick event!

Dear developers, bring CopyTicks to a working state. Even simple tests fail.


 
I found a loophole that allows me to replace such cumbersome entries
_W(Tick, Offset, (double)1.23456);     // Write the value (double)1.23456 at the found offset
_W(CloneTick, 0, Tick);                // Write to CloneTick at zero offset the value of structural object Tick
_W(Color, 2, (uchar)230);              // Write the value (uchar)230 at offset 2.
instead of such bulky records.
_W(Tick)[Offset] = 1.23456;             // Write the value (double)1.23456 at the found offset
_W(CloneTick)[0] = Tick;                // Write to CloneTick at zero offset the value of structural object Tick
_W(Color)[2] = (uchar)230;              // Write the value (uchar)230 at offset 2.

I.e. there is a real possibility to work with standard types and simple structures as with an array, not only in read mode, but also in write mode!
 
fxsaber:
I found a loophole that allows me to replace such cumbersome entries
to make the usual

I.e. there is a real possibility to work with standard types and simple structures as with an array, not only in read mode, but also in write mode!

Published. Now for any variable (structure or standard type) works not only reading, as with an array, but also WRITE:

_W(AnyVariable)[Pos] = AnyValue; // Writes the AnyValue value at byte offset Pos to the AnyVariable variable

It was not easy to guess before implementation - I guess it turned out to be a good test for average OOP mastery: I only know the classics for classes.

If anyone knows something similar, please share a link for education.

 
Example of showing byte contents of a variable
#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));
}
Result
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:
 
Concise not-a-number double comparison

Forum on trading, automated trading systems and testing trading strategies

How to quickly compare double and QNaN ?

fxsaber, 2016.10.11.11:14 pm.

That's cool, didn't know that! Well then this way
#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");
   }   
}

 
Example of creating not-a-number double
#include <TypeToBytes.mqh>

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

 
Example of a new feature does not directly touch the library, but indirectly touches - on the topic of structures

Forum on trading, automated trading systems and testing trading strategies.

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 can now print simple structures as well.
 
fxsaber:
Example of creating a not-a-number double
#include <TypeToBytes.mqh>

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

Now we can do it differently

#include <TypeToBytes.mqh>

void OnStart()
{
  double Number = (double)"01.23_example";
  double Nan = (double)"nan";
  
  Print(Number);
  Print(Nan);
  
  ArrayPrint(_R(Nan).Bytes); // Print bytes
  
  ulong Num = 0;
  
  _W(Num) = Nan; // Byte-by-byte copying of Nan to Num
    
  PrintFormat("%I64X", Num);
}

result

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

Now we can do it differently

#include <TypeToBytes.mqh>

void OnStart()
{
  double Number = (double)"01.23_example";
  double Nan = (double)"nan";
  
  Print(Number);
  Print(Nan);
  
  ArrayPrint(_R(Nan).Bytes); // Print bytes
  
  ulong Num = 0;
  
  _W(Num) = Nan; // Byte-by-byte copying of Nan to Num
    
  PrintFormat("%I64X", Num);
}

Result

1.23
nan
255 255 255 255 255 255 255 127
7 F FFFFFFFFFFFFFF
Did you update the source code in the publication?