Особенности языка mql5, тонкости и приёмы работы - страница 147

 
Igor Makanu:

 IsInf() и IsNaN() рабочие, 

IsEqual() и IsZerro() под вопросом, нагугленные из неких источников как "trick for double"

IsNan() работает, а IsInf() нет

IsInf(DBL_MIN_DENORM) == true

С каких пор денормализованные числа стали бесконечностью?

Ну и все эти сравнения с epsilon - epsilon нужно увеличивать пропорционально операндам. Да и вообще, нет здесь универсального рецепта, вот я в качестве epsilon испоьзую Point (с округлением оперндов), сравнивать разницу с DBL_EPSILON желания не возникает (да и не нужно).

 
Vict:

Ну и все эти сравнения с epsilon - epsilon нужно увеличивать пропорционально операндам. Да и вообще, нет здесь универсального рецепта, вот я в качестве epsilon испоьзую Point (с округлением оперндов), сравнивать разницу с DBL_EPSILON желания не возникает (да и не нужно).

нашел статью, которую вчера с ТВ читал https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

да, нужно другой пример использовать где задавать точность сравнения

Vict:

IsNan() работает, а IsInf() нет

С каких пор денормализованные числа стали бесконечностью?

нормализация в MQL вроде до 8-го знака, т.е. если  NormalizeDouble() добавить в IsInf(), результат все равно будет не лучше

 
Igor Makanu:

нормализация в MQL вроде до 8-го знака, т.е. если  NormalizeDouble() добавить в IsInf(), результат все равно будет не лучше

Нормализация в мкл это совсем не то, я не знаю зачем функцию так назвали. 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

 
Случайно обнаружил в ME, что можно создавать закладки через CTRL+1, CTRL+2, .... А переключаться между ними через ALT+1, ALT+2, ...
 
// Количество успешных OrderSend.
int GetOrderSendSucceeded()
{
  MqlTradeRequest Request = {0};
  MqlTradeResult Result;

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

Показывает, сколько в Терминале всего (с момента запуска) было  отправлено успешных синхронных торговых приказов (OrderSend) и сгенерировано асинхронных.

Использую в Тестере (в конце), чтобы понять, сколько раз модифицировал ордера.

 
Мало ли кто не знает, как, например, создавать классы ТС со своими On-событиями.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

OnTick() не работает в экземпляре класса?

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


Наследуйтесь от BASE, тогда методы OnTick в классах будут вызываться автоматически.

 

Пример использования X Macro (не обессудьте за непонятные типы, выдрал из рабочего кода. Вектор - динамический массив):

Например:

   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. Определять вектора хочется за циклом для предотвращения постоянных аллокаций.

2. Каждый из тестов может быть выключен (на самом деле их много).

3. restore_image() и restore_subimages(), тяжелая и очень времязатратная функция (чтение граф. объектов с графика).

4. Если ни один из тестов не использует seg2, например, то хочется в одно действие убрать и определение, и соответствующий restore...(), для предотвращения ситуации, когда vector определён, но пустой из-за закомментированного restore...(), что даст ошибочные результаты.

Что делать?

#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
      ...
   }

Просто комментируем ненужные segx в DEFSEG_LIST. Это сгенерит то же, что и в первом коде. Вообще жаль, что компилятор не умеет показать выхлоп процессора (аналог gcc -E).

 

Иногда при генетической оптимизации достаточно первых нескольких тысячей проходов, чтобы уже понять исход более-менее.

Когда автоматически запускаешь много оптимизаций, то хочется, чтобы это все отработало побыстрее. Поэтому требуется механизм прерывания оптимизации.

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

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


Применение.

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

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

Инструкция открытия чарта с Null-символом.


  1. Удаляете все чарты из Обзора рынка.
  2. Запускаете Оптимизацию фреймового советника (например, этого) в математическом режиме.
  3. Останавливаете Оптимизацию и снимаете с чарта Null-символа фреймовый советник.
Такой чарт, возможно, может быть полезен для экономии ресурсов.
 
Столкнулся с такой особенностью.
class A
{
  static int i;
} a; // unresolved static variable 'A::i'

static int A::i = 0;

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


Если во время определения класса со статическими полями тут же создается его объект, будет ошибка компиляции.

Причина обращения: