Features of the mql5 language, subtleties and tricks - page 147

 
Igor Makanu:

IsInf() and IsNaN() are working,

IsEqual() and IsZerro() are questionable, googled from some sources as "trick for double".

IsNan() works, but IsInf() does not

IsInf( DBL_MIN_DENORM) == true

Since when did denormalised numbers become infinity?

And all these comparisons with epsilon - epsilon should be increased proportionally to operands. Anyway, there's no universal recipe, I use Point as an epsilon (with rounded operands) and I don't want (and don't need) to compare the difference with DBL_EPSILON.

 
Vict:

And all these comparisons with epsilon - epsilon should be increased proportionally to operands. In general, there's no universal recipe, I use Point as epsilon (with rounded operands), I don't want to compare the difference with DBL_EPSILON(and I don't need to).

found an article I read yesterday from TVhttps://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

Yes, you must use another example where you should specify the comparison accuracy

Vict:

IsNan() works, but IsInf() does not

Since when did denormalized numbers become infinity?

MQL seems to normalize to 8-th digit, i.e. if NormalizeDouble() is added to IsInf(), the result will still be no better.

 
Igor Makanu:

normalisation in MQL seems to be up to 8th digit, i.e. if NormalizeDouble() is added to IsInf(), the result is still no better

Normalization in MQL is not the same at all, I don't know why they named the function that way. https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%B0

 
I accidentally discovered in ME that you can create bookmarks with CTRL+1, CTRL+2, ..... And switch between them with ALT+1, ALT+2, ...
 
// Количество успешных OrderSend.
int GetOrderSendSucceeded()
{
  MqlTradeRequest Request = {0};
  MqlTradeResult Result;

  return(OrderSend(Request, Result) ? 0 : (int)Result.request_id + 1);
}

Shows how many successful synchronous trade orders (OrderSend) and asynchronous orders generated in the Terminal in total (since start).

I use it in the Tester (at the end) to see how many times the orders have been modified.

 
There are few people who don't know how to create TC classes with their own On-events, for example.

Forum on trading, automated trading systems and trading strategy testing

OnTick() doesn't work in a class instance?

fxsaber, 2019.10.31 23:45

class BASE
{  
private:
  static BASE* Objects[];
  
public:
  BASE()
  {
    BASE::Objects[::ArrayResize(BASE::Objects, ::ArraySize(BASE::Objects) + 1) - 1] = &this;
  }
  
  ~BASE()
  {
    const int Size = ::ArraySize(BASE::Objects);
    
    for (int i = Size - 1; i >= 0; i--)
      if (BASE::Objects[i] == &this)
      {
        for (int j = i; j < Size - 1; j++)
          BASE::Objects[j] = BASE::Objects[j + 1];
          
        ::ArrayResize(BASE::Objects, Size - 1);
        
        break;
      }
  } 
    
  virtual void OnTick() = 0;
  
  static void AllTick()
  {
    for (int i = ::ArraySize(BASE::Objects) - 1; i >= 0; i--)
      BASE::Objects[i].OnTick();
  }
};

static BASE* BASE::Objects[];


class A : BASE
{
  virtual void OnTick()
  {
    Print(__FUNCSIG__);
  }
};

class B : BASE
{
  virtual void OnTick()
  {
    Print(__FUNCSIG__);
  }
};

A a;
B b;

void OnTick()
{
  BASE::AllTick();
}


Inherit from BASE, then OnTick methods in classes will be called automatically.

 

An example of using X Macro (don't mind the obscure types, I ripped it out of working code. Vector is a dynamic array):

For example:

   vector_fund<upindex_t> seg2; vector_ref<vector_fund<upindex_t>> seg2_sub;
   vector_fund<upindex_t> seg3; vector_ref<vector_fund<upindex_t>> seg3_sub;
   vector_fund<upindex_t> seg4; vector_ref<vector_fund<upindex_t>> seg4_sub;
   for (uint i = 0;  i < 5114;  ++ i) {
      restore_image(seg2, "seg2"); restore_subimages(seg2_sub, "seg2");
      restore_image(seg3, "seg3"); restore_subimages(seg3_sub, "seg3");
      restore_image(seg4, "seg4"); restore_subimages(seg4_sub, "seg4");
      
      if (true) {} // тест №1, использует seg2 и seg2_sub
      if (true) {} // тест №2, использует seg3 и seg3_sub
      if (true) {} // тест №3, использует seg4 и seg4_sub
   }

1. we want to define vectors behind a loop to prevent constant allocations.

2. Each of the tests can be switched off (actually there are many).

3. restore_image() and restore_subimages(), a heavy and very time-consuming function (reading graph objects from the graph).

4. If none of the tests use seg2, for example, I would like to remove both the definition and the corresponding restore...() in one action, to prevent a situation where the vector is defined but empty because of the commented restore...(), which would give erroneous results.

What to do?

#define  DEFSEG_LIST    \
   DEFSEG_HELPER(seg2) \
   DEFSEG_HELPER(seg3) \
   DEFSEG_HELPER(seg4)
   
#define  DEFSEG_HELPER(SEG) vector_fund<upindex_t> SEG; vector_ref<vector_fund<upindex_t>> SEG##_sub;
    DEFSEG_LIST;
#undef  DEFSEG_HELPER
   
   for (uint i = 0;  i < 5114;  ++ i) {
#define  DEFSEG_HELPER(SEG) restore_image(SEG, #SEG);  restore_subimages(SEG##_sub, #SEG);
    DEFSEG_LIST;
#undef  DEFSEG_HELPER
      ...
   }

Simply comment out the unnecessary segx in DEFSEG_LIST. This will generate the same results as in the first code. Actually it's a pity the compiler is unable to show the processor's output (the gcc -E analog).

 

Sometimes in genetic optimisation the first few thousand passes are enough to already understand the outcome more or less.

When you automatically run a lot of optimizations, you want it all to run faster. That is why we will need a mechanism to interrupt optimization.

#include <fxsaber\MultiTester\MTTester.mqh>  // https://www.mql5.com/ru/code/26132

// Выключает Оптимизацию ( и одиночный проход)
bool OptimizationStop( void )
{
  return(!MTTESTER::IsReady() && MTTESTER::ClickStart(false));
}


Usage.

// Демонстрация прерывания Оптимизации.

sinput int inAmountPasses = 20; // Через сколько проходов закончить
input int Range = 0; // 0..10000

double OnTester()
{
  int Data[];
  
  return(FrameAdd(NULL, 0, 0, Data)); // Сгенерировали TesterPass
}

void OnTesterPass()
{
  static int Amount = 0;
  
  ulong Pass;
  string Name;
  long ID;
  double Value;
  int Data[];

  while (FrameNext(Pass, Name, ID, Value, Data))
    if (++Amount > inAmountPasses)
    {
      OptimizationStop(); // Как достигли нужного количества проходов, выключили оптимизатор.
      
      break;
    }
}
 

Instructions for opening a chart with a Null character.


  1. Delete all charts from Market Watch.
  2. Start Optimization of a frame EA (e.g. this one) in mathematical mode.
  3. Stop Optimization and remove the frame EA from the Null-symbol chart.
Such a chart can probably be useful to save resources.
 
I have encountered this peculiarity.
class A
{
  static int i;
} a; // unresolved static variable 'A::i'

static int A::i = 0;

A b; // Надо прописывать после static


If a class with static fields is immediately created while defining a class, there will be a compile-time error.

Reason: