mql5言語の特徴、微妙なニュアンスとテクニック - ページ 229

 

English (original): MQLの言語機能について要望を出したいと思います。もしこのスレッドが適切でなければ、教えてください。元のリクエストは英語フォーラムにあります ...

ロシア語(Google翻訳):MQLの言語機能に関する要望を出したいと思います。 このスレッドが適切でない場合は、私に知らせてください。 元のリクエストは英語フォーラムにあります ...

 

配列を 1行で埋めるには?

struct clr_struct{
   color uncheck;
};
clr_struct clr[];

//clr[0].uncheck=0x999999;
//clr[1].uncheck=0x999999;

clr[].uncheck={0x999999,0x999999};//как правильно?
 
Pavel Kolchin 配列を 1行で埋めるには?
clr_struct clr[] = {{0x999999}, {0x999999}};
 

アクセス権に関するライフハックをもうひとつ:あるクラスのプライベート・フィールドや関数へのアクセスを別のクラスに与えたいという欲求が抑えられない場合、標準的なMQLツールを使って以下のようにすることができる:

BからA::f1()にアクセスできるようにする。

//--------- как было
class   A
  {
   int               m;
   int               f1() {return m;}                       // нужно дать к нему доступ классу B
public:
                     A(int a): m(a) {}
  };

class B {};

このように書き換えてみよう:

class A;
class B
  {
private:
   class AB
     {
   public:
      virtual int    CallAf1(A&) const  = 0;
                     AB() {ABptr = &this;}
     } static *ABptr;

   // внутри B используем  этот метод для получения доступа к A::f1()
   static int        CallAf1(A & obj)
     {
      return ABptr.CallAf1(obj);
     }

public:
   class AB2: AB {};

   // вспомогательный метод - только для проверки
   static void       _f1_test(A & obj)
     {
      Print("test ", CallAf1(obj));
     }
  };
B::AB *B::ABptr = NULL;

class   A
  {
   int               m;
   int               f1() {return m;}
public:
                     A(int a): m(a) {}

   //--  добавлено
private:
   class AB3: B::AB2
     {
      int            CallAf1(A &obj) const {return obj.f1();}
     }   static  const     ABlink;
  };
const A::AB3 A::ABlink;

Bの内部で(A)a.f1()を呼び出すには、CallAf1(a)を呼び出す。f1()にパラメータがある場合は、それをCallAf1()に追加する。

テスト:

void OnStart()
  {
    A f(2);
    B::_f1_test(f);
  }

CallAf1()をprotectedにすることもできるが、それはアクセス権に大きな穴を開けることになる。コード内のどこでも、クラスBの子孫を作り、その中にCallAf1()を呼び出すpublicメソッドを作ることができる。


P.S.この構文は非常に面倒ですが(必要であればマクロに詰め込むこともできます)、フレンドC++より優れている点がひとつあります。

 
mktr8591 #:

アクセス権に関するライフハックをもうひとつ:あるクラスのプライベートなフィールドや関数へのアクセス権を別のクラスにも与えたいという欲求が抑えられない場合、標準的なMQLツールを使ってこれを行うことができます。

それを理解するのに時間がかかったよ...。仮想化はいい手だ!
 
fxsaber #:
この世界に入るのに、ずいぶん時間がかかったよ...。仮想化はいい手だ!
最初に書かなかった唯一のことは、これ以上B::AB2クラス(とその子孫)のオブジェクトを作っちゃいけないってこと。)
 
このExpert Advisorをテスターの全シンボルモードで実行すると
input int inTmp = 0; // https://www.mql5.com/ru/forum/321656/page90#comment_44727856

bool Res = true;

// Проверяет, нормализована ли цена по алгоритму NormalizeDouble.
bool IsNDPrice( const double &Price )
{
  return(Price == NormalizeDouble(Price, 5));
}

// Проверяет, нормализована ли цена, как при парсинге или ручном вводе.
bool IsNDPrice2( const double &Price )
{
  return(Price == (double)DoubleToString(Price, 5));
}

void OnTick()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))
//    Res &= IsNDPrice(Tick.bid) && IsNDPrice(Tick.ask); // OnTester == 1.
    Res &= IsNDPrice2(Tick.bid) && IsNDPrice2(Tick.ask); // OnTester == 0.
}

double OnTester()
{
  return(Res);
}
を実行すると、すべての価格が NormalizeDouble アルゴリズムを使用して正規化されていることがわかります。また、ターミナルからではなく、解析や手動入力で取得した価格を扱う場合、正しい動作のために正規化が必要であることがわかります。勘違い する必要はありません。
 

REASON_ACCOUNTが 実行されると(口座が変更されず 再ログイン されただけでも)、Expert Advisorは完全にアンロードされ、新しいコピーがロードさ れます。

このため、OnDeinit の ExpertRemove は新しいコピーには影響しません。

void OnInit() { Print(__FUNCSIG__); }

void OnDeinit( const int ) { Print(__FUNCSIG__); }


再ログイン後の結果。

2023.02.07 11:33:12.717 Test5-3 (EURUSD,M1)     void OnDeinit(const int)
2023.02.07 11:33:13.926 Test5-3 (EURUSD,M1)     void OnInit()


Deinit後、新しいEAコピーの起動が1秒以上(最大2秒)待たされます。このような長い待ち時間の理由は何ですか?また、待ち時間を短縮することは可能ですか?

 

SymbolInfoTickは この3回の呼び出しのそれぞれで最新のティックを返します。つまり、インジケータをスキップすることなくティックを収集することは、控えめに言っても疑わしい。


インジケータによる(スキップなしの)ティック収集が不可能であることの証明。

// Аналог Sleep для индикатора.
void Sleep2( const uint Pause )
{
  const uint StartTime = GetTickCount();
  
  while (!IsStopped() && (GetTickCount() - StartTime) < Pause)
    ;
}

#define  TOSTRING(A) #A + " = " + (string)(A) + " "

int OnCalculate( const int rates_total,
                 const int,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[] )
{  
  static const int period = PeriodSeconds();
  
  Sleep2(1000); // Расчеты.
  
  MqlTick Tick[1];
  
  if (SymbolInfoTick(_Symbol, Tick[0]) &&
      ((Tick[0].bid != close[rates_total - 1]) || // Свежий бар не соответсвует последнему тику.
       Tick[0].time / period > time[rates_total - 1] / period))
  {
    ArrayPrint(Tick);
    Print(TOSTRING(time[rates_total - 1]) + TOSTRING(close[rates_total - 1]));
  }

  return(rates_total);
}


結果。

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:39 1.54951 1.54959 0.0000        0 1675787319322      98       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.5495 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:40 1.54948 1.54959 0.0000        0 1675787320719      98       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.5495 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:41 1.54952 1.54960 0.0000        0 1675787321823     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54954 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:42 1.54954 1.54961 0.0000        0 1675787322223     102       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54951 00000000002 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:43 1.54955 1.54964 0.0000        0 1675787323721     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54948 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:44 1.54954 1.54962 0.0000        0 1675787324323     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54952 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:45 1.54956 1.54962 0.0000        0 1675787325421     102       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54952
 
MQL5言語で可能なコンストラクトの1つ。

取引、自動取引システム、取引戦略のテストに関するフォーラム

エラー、バグ、質問

fxsaber, 2023.02.14 13:11

input string inStr = "B2";

class A {};

class B1 : public A {};
class B2 : public A {};
// .....
class B100 : public A {};

void OnStart()
{
  A* a = New2(inStr); // создает объект, который прописан в inStr.
}

// Решение.
template <typename T>
A* New( const string &ClassName ) { return((typename(T) == ClassName) ? new T : NULL); }

typedef A* (*TNew)( const string& );
static const TNew FuncNew[] = {New<B1>, New<B2>, /*....,*/ New<B100>};

A* New2( string ClassName )
{  
  A* Res = NULL;
  
  ClassName = "class " + ClassName;
  
  for (int i = ArraySize(FuncNew) - 1; !Res && (i >= 0); i--)
    Res = FuncNew[i](ClassName);  
    
  return(Res);
}

残念ながら、MQL4ではこのような作業はまだできません。