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

 

Особенности наследуемых структур

struct A
{
private: 
  int i;
};

struct B : public A
{
  int i; // A::i в private, поэтому никакого пересечения по именам
};

void OnStart()
{
  A a;
  B b;
  
  Print(sizeof(a)); // 4
  Print(sizeof(b)); // 8 - при любом наследовании размер только увеличивается
  
  // Кастинг в обе стороны без union
  a = b;
  b = a;
}
 

Если нужно узнать, включен ли флаг "Unlimited" в Настройки --> Графики --> Макс.баров в окне, использую такую конструкцию:

   int max_bars=TerminalInfoInteger(TERMINAL_MAXBARS);
   if(max_bars<1e7)
     {
      Print("Макс.баров в окне должно быть Unlimited!");
      return false;
     }
 

Когда не хочется, чтобы какой-то публичный метод светился (при наборе точки после названия объекта, например), оформляю этот метод в виде публичного оператора. Правда, не всегда возможно применение такого костыля.

 
fxsaber:

Когда не хочется, чтобы какой-то публичный метод светился (при наборе точки после названия объекта, например), оформляю этот метод в виде публичного оператора. Правда, не всегда возможно применение такого костыля.

А в коде пример? Пожалуйста.

 
Artyom Trishkin:

А в коде пример? Пожалуйста.

struct A
{
private:  
  int Value;
  
public:
  int GetValue( void ) const
  {
    return(this.Value);
  }
};

struct B : public A
{
private:
  // Делает доп. расчеты
  void AddCalculate( void )
  {
    Print(__FUNCSIG__);
  }
  
public:
  // Так "спрятали" метод доп. расчетов
  void operator ~( void )
  {
    this.AddCalculate();
  }
};

void OnStart()
{
  A a;
  B b;
  
  b = a; // После присвоения требуется вызвать доп. расчеты.
  
  ~b;    // Провели доп. расчеты
  
  b.GetValue(); // После точки попрежнему виден только GetValue()
}
 

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

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

fxsaber, 2017.09.08 13:20

struct A
{
private:  
  int Value;
  
public:
  int GetValue( void ) const
  {
    return(this.Value);
  }
};

struct B : public A
{
private:
  // Делает доп. расчеты
  void AddCalculate( void )
  {
    Print(__FUNCSIG__);
  }
  
public:
  // Так "спрятали" метод доп. расчетов
  void operator ~( void )
  {
    this.AddCalculate();
  }
};

void OnStart()
{
  A a;
  B b;
  
  b = a; // После присвоения требуется вызвать доп. расчеты.
  
  ~b;    // Провели доп. расчеты
  
  b.GetValue(); // После точки попрежнему виден только GetValue()
}

А это

class A
{
 private:
 void AddCalculate(void) const
  {
   Print(__FUNCSIG__);
  }
 public:
 int GetValue(void) const
  {
   this.AddCalculate();
   return(0);
  }
 
};
разве не то-же самое?


 
Alexey Viktorov:

А это

разве не то-же самое?

Нет, конечно. Полей Value1, Value2, ... много, GetValue1(), GetValue2() - аналогично. На каждом GetValue делать доп. расчеты нерационально. Даже на одном GetValue, вызванном более одного раза, расчеты ни к чему.

 

Не смог придумать, как суметь задавать размер поля-массива простой структуры. Поэтому раздул такой костыль

// Простая структура - не имеет сложных объектов
template <typename T>
struct STRING // : public T
{
  int i;
  uchar Array[sizeof(T) - sizeof(int)];

  void operator =( const string Str )
  {
    StringToCharArray(Str, this.Array);    
  }
  
  template <typename T1>
  void operator =( const T1 &Str )
  {
    ArrayCopy(this.Array, Str.Array);
  }
  
  string ToString( void ) const
  {
    return(CharArrayToString(this.Array));
  }

// много методов, работающих с this.Array и this.i
// ....

};

#define SET_STRING(SIZE) \
  struct STRUCT##SIZE    \
  {                      \
    uchar Array[SIZE];   \
  };                     \
                         \
  STRING<STRUCT##SIZE>

void OnStart()
{  
  SET_STRING(20) Str[1];  // Массив "строк", каждая длиной 20 байтов
  SET_STRING(50) Str2[2]; // Массив "строк", каждая длиной 50 байтов
  
  Str[0] = "Hello World!";
  Str2[0] = Str[0];
  
  Print(sizeof(Str));
  Print(sizeof(Str2));
  
  Print(Str[0].ToString());
  Print(Str2[0].ToString());
}


Через макросы, короче. На MQL5, наверное, больше никак. В C++ это решается нормально? Типа шаблона template <typesize S>.

 

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

Библиотеки: MT4Orders

fxsaber, 2017.09.14 08:52

На форуме еще до появления в MQL5 Reason-флагов был выложен триггер SL/TP. Его логика четко показывала, что при акцептировании SL/TP/SO уровней открытой позиции торговым сервером порождается соответствующий маркет-ордер, который находится в MT5-таблице открытых ордеров до тех пор, пока не исполнится.


Поэтому в MT5 даже на чистом MQL5 модификация/удаление таких ордеров невозможна и торговая логика в MT5 требует проверки, является ли открытый ордер фактически замороженным или нет.


// Триггер SL/TP/SO
void OnTradeTransaction ( const MqlTradeTransaction &Trans, const MqlTradeRequest &Request, const MqlTradeResult &Result )
{ 
  if ((Trans.type == TRADE_TRANSACTION_ORDER_ADD) && OrderSelect(Trans.order))
  {
    const ENUM_ORDER_REASON Reason = (ENUM_ORDER_REASON)OrderGetInteger(ORDER_REASON);
    
    if (Reason == ORDER_REASON_TP)
      Print("Position #" + (string)Trans.position + " - triggered TP.");    
    else if (Reason == ORDER_REASON_SL)
      Print("Position #" + (string)Trans.position + " - triggered SL.");    
    else if (Reason == ORDER_REASON_SO)
      Print("Position #" + (string)Trans.position + " - triggered StopOut.");    
  }
}


...Видно, что больше четверти секунды TP-ордер висел среди открытых. Любые попытки его модификации/удаления вызывали бы ошибки.

Учитывайте данную особенность MT5.

 
fxsaber:

Когда не хочется, чтобы какой-то публичный метод светился (при наборе точки после названия объекта, например), оформляю этот метод в виде публичного оператора. Правда, не всегда возможно применение такого костыля.

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

Тут видимо ошибка в проектировании. Если класс изначально не предназначен для изменения извне, а содержит только Get-методы, то он таким и должен быть.  А все модификации проводятся через наследуемые от него классы.

Был бы ещё удобен вариант с protected-наследованием, когда в базовом классе прописаны все методы, а в наследуемом ты показываешь лишь Get.  И когда понадобится, приводишь к базовому.  Но в Metaeditor так до сих по и не исправили баг, что все эти методы вываливаются в списке, даже если они недоступны.

На каждом GetValue делать доп. расчеты нерационально. Даже на одном GetValue, вызванном более одного раза, расчеты ни к чему

Так а что собственно мешает сделать метод Recalculate() ?  Если на этом построена логика работы, т.к. сам класс не может определить, когда надо пересчитывать, значит работой класса управляет пользователь.

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