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

設定」→「チャート」→「ウィンドウの最大バー」で「無制限」フラグが有効になっているかどうかを知りたい場合は、このような作りになっています

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

パブリック・メソッドを光らせたくないとき(例えば、オブジェクト名の後にドットを入力したとき)は、このメソッドをパブリック演算子にしています。しかし、そのような松葉杖が必ずしも使えるとは限りません。

 
fxsaber

パブリック・メソッドを光らせたくないとき(例えば、オブジェクト名の後にドットを入力したとき)は、このメソッドをパブリック・オペレータにします。しかし、そのような松葉杖が使えるとは限りません。

コードに例はありますか?お願いします。

 
アルチョム・トリシキン

コードに例はありますか?お願いします。

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);
  }
 
};
これと同じことではありませんか?


 
アレクセイ・ヴィクトロフ

そして、これ。

同じことではありませんか?

いいえ、もちろんそんなことはありません。フィールド Value1、Value2、...が多く、GetValue1()とGetValue2()は同じです。GetValueごとに追加計算を行うのは合理的ではありません。1つの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++では普通の解決法なのでしょうか?テンプレート<typesize S>のように。

 

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

ライブラリ:MT4Orders

fxsaber さん 2017.09.14 08:52

SL/TPトリガーは、MQL5 Reason flags以前からフォーラムに投稿されていました。そのロジックは、オープンポジションの 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.");    
  }
}


...1/4秒以上、TPオーダーがオープンなオーダーにぶら下がっていたことがわかります。それを修正・削除しようとすると、エラーが発生するのである。

MT5のこの機能を意識してください。

 
fxsaber:

パブリックメソッドを光らせたくないとき(例えば、オブジェクト名の後にドットを入力したとき)は、このメソッドをパブリック演算子にしています。しかし、そのような松葉杖が使えるとは限りません。

実はある種のメガクラッチなんです。何をやっているのか理解できないような不親切な演算子を含むコードを後でどのように解析するのでしょうか?

設計上の ミスに違いない。当初は外部から変更されることを想定していなかったクラスが、Get-methodsだけを含んでいる場合、同じであるべきです。すべての変更は、そこから継承されたクラスを通じて行われます。

もう一つの便利な方法は、ベースクラスがすべてのメソッドを含み、継承されたクラスがGetメソッドのみを表示する保護継承である。そして、必要なときには、それを基底クラスにキャストすることができます。しかし、Metaeditorはまだバグを修正していないため、これらのメソッドはすべて、たとえ利用できない場合でもリストにダンプされます。

各GetValueで追加の計算をするのは合理的ではありません。1つのGetValueが複数回呼ばれても、計算を実行する必要はない。

では、Recalculate()メソッドを使用できない理由は何でしょうか?再計算が必要なタイミングをクラス自身が定義できないので、それでクラスが論理的に動くとしたら、そのクラスはユーザーによってコントロールされているということです。

理由: