初心者の方からの質問 MQL5 MT5 MetaTrader 5 - ページ 1332

 
Mikhail Tkachev:

ドキュメントやフォーラムを掘り起こすと......。
ポインタ型の変数を OnInit()で文字列で作成した場合、グローバル 変数(例ではvar)にするにはどうしたらよいでしょうか。

で、オブジェクトの数やコンストラクタのパラメータは事前に不明で、OnInit()で計算されるのでしょうか?

それは簡単なことです。

CObj* var1 = NULL;
CObj* var2 = NULL;
CObj* var3 = NULL;

int OnInit()
{
   var1 = new CObj( p1, p2, p3 );
   var2 = new CObj( p1, p2, p3 );
   var3 = new CObj( p1, p2, p3 );
}
 

こんにちは

mt5には十字キーボタンがある

チャート上で押すと、何バー、何ピップス、何パーセントと表示されます。

この値を正しく計算し、私のロボットにバインドする方法を教えてください。

ありがとうございました。

 
Artyom Trishkin:

新バークラスはすでに導入されているのですか?

また、入力パラメータは具体的にどのようなものなのでしょうか?

クラスは、https://www.mql5.com/ru/code/768、 マイナーチェンジしています。

//+------------------------------------------------------------------+
//|                                                     IsNewBar.mqh |
//|                               Copyright © 2011, Nikolay Kositsin |
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+ 
#property copyright "2011,   Nikolay Kositsin"
#property link      "farria@mail.redcom.ru"
#property version   "1.00"
//+------------------------------------------------------------------+
//|  Алгоритм определения момента появления нового бара              |
//| Для каждого таймфрейма каждого символа нужно создавать объект    |
//+------------------------------------------------------------------+  
#include <Object.mqh>

class CIsNewBar : public CObject // Сделан наследником класса для возможности работы с классом CArrayObj (из библиотеки)
// class CIsNewBar   // Первоначальная редакция
  {
   //----
public:

      //---- функция определения момента появления нового бара
   bool IsNewBar()
     {
      //---- получим время появления текущего бара
      datetime TNew=datetime(SeriesInfoInteger(m_Symbol,m_TimeFrame,SERIES_LASTBAR_DATE));

      if(TNew!=m_TOld && TNew) // проверка на появление нового бара
        {
         m_TOld=TNew;
         return(true); // появился новый бар!
        }
      //----
      return(false); // новых баров пока нет!
     };

   //---- конструктор класса    
                     CIsNewBar(const string &pSymbol, const ENUM_TIMEFRAMES pTimeFrame){
                        m_Symbol=pSymbol; m_TimeFrame=pTimeFrame;
                        m_TOld=-1;};

protected:
   datetime          m_TOld;        // Время хранится 
   ENUM_TIMEFRAMES   m_TimeFrame;   //    для каждого таймфрейма
   string            m_Symbol;      //    каждого символа

   //---- 
  };
//+------------------------------------------------------------------+

以下のように適用することを意図しています。

int OnInit()
{
    // Переменная NB_M1 - объект для контроля нового бара по символу currSymbol для таймфрейма M1

    CIsNewBar* NB_M1=new CIsNewBar(currSymbol,PERIOD_M1);
}

void OnTick()
{
    if (NB_M1.IsNewBar())  // (1) Если появился новый бар M1
        {....}
    ......
}
 
Koldun Zloy:

簡単です。

返信ありがとうございます)
最初はそうしていました。
そのため、オブジェクトは2回作成されます。最初は空で、次にパラメータを持つコンストラクタによって、あるべき姿のオブジェクトが作成されます。
でも ...この場合、コンパイラは OnInit() 内の行に警告を表示します。

var1' の宣言がグローバル変数を隠す → OnInit()
の行で 'var1' の前の宣言を見る。

つまり、ローカル変数が グローバル変数を隠している・・・。それでどうなるんですか?
例えばOnTick()のような別の関数では、どのような変数が見られるのでしょうか?グローバル変数は=NULLで、ローカル変数は正しく初期化されていますが、他の関数からは見えません ...

 
Mikhail Tkachev:

このクラスはhttps://www.mql5.com/ru/code/768 から借用したものです。

次のように適用することになっている。

入力パラメータからすべての部分文字列を抽出し、それらを使ってシンボルと対応する時間枠の名前を作成します。

そして、これらのリストから新しいバーオブジェクトを作成し、作成される各オブジェクトへのポインタ - "New Bar" - をグローバルに宣言されているCArrayObjに配置します。

次に、OnTimer()ループでリストの次のオブジェクトへのポインタを受け取り、新しいバーがあるかどうかをチェックします。新しいオブジェクトがなければ、次のオブジェクトに行かなければならないし、あれば、新しいバーが開いたときにしなければならないことをしなければならない。

タイマーは、ミリ秒、秒、分など、必要に応じて設定し、一般的には、現在表示されていないシンボルの新しいバーに反応するのに十分と思われる頻度で設定します。

 
Mikhail Tkachev:

返信ありがとうございます)
最初はそうしていました。
そのため、オブジェクトは2回作成されます。最初は空で、次にパラメータを持つコンストラクタによって、あるべき姿のオブジェクトが作成されます。
でも ...この場合、コンパイラは OnInit() 内の行に警告を表示します。

var1' の宣言がグローバル変数を隠す → OnInit()
の行で 'var1' の前の宣言を見る。

つまり、ローカル変数が グローバル変数を隠している・・・。それでどうなるんですか?
例えばOnTick()のような別の関数では、どのような変数が見られるのでしょうか?グローバル変数は=NULLで、ローカル変数は正しく初期化されていますが、他の関数からは見ることができません。

よく見てください。それは、あなたがしたことではありません。

 
Artyom Trishkin:

入力パラメータからすべての部分文字列を抽出し、そこからシンボル名とそれに対応する時間軸をコンパイルしなければならない。

そして、これらのリストから新しいバーオブジェクトを作成し、それぞれの新しいオブジェクトへのポインタをグローバルレベルで宣言されているCArrayObjに入れます。

次に、OnTimer()ループでリストの次のオブジェクトへのポインタを受け取り、新しいバーがあるかどうかをチェックします。新しいオブジェクトがなければ、次のオブジェクトに行かなければならないし、あれば、新しいバーが開いたときにしなければならないことをしなければならない。

ミリ秒、秒、分など、必要に応じてタイマーを作成し、一般的には、現在表示されていないシンボルの新しいバーに反応するのに十分と思われる頻度を設定します。

これは私がやっていたことですが、ArrObj.At(0)はクラスの メンバ関数を呼び出さないのです......。

 
Koldun Zloy:

よく見てください。それは、あなたがやっていたことではありません。

すでに気づいている)
つまり、解決策はグローバルに空のオブジェクトを宣言すること...。
また、その人数が事前にわからない場合は?ただ、"with reserve" と宣言するだけでいいのですか? :)
追伸:このようなオブジェクトの宣言の仕方は、組み込みのヘルプにはありませんでした。

CObj* var1 = NULL;
 
Mikhail Tkachev:

すでに気づいている)
つまり、解決策はグローバルに空のオブジェクトを宣言すること...。
また、その人数が事前にわからない場合は?ただ、"with reserve "と宣言しておけばいいのでは?)

CArrayObjに 入れる。

ArrObj.At(0) 関数は、 派生 クラスのメンバについて何も知らないベースクラスへのポインタを返します

それを参照するためには、型変換をすればよい。

CIsNewBar* newBar = (CIsNewBar*)ArrayObj.At(0);
newBar.method( parameter );
 
Koldun Zloy:

CArrayObjに 入れる。

関数ArrObj.At(0)はベースクラスへのポインタを返す ので派生クラスの メンバについて何も知らない。

タイプ変換をして参照すればよい。

返信ありがとうございます、あなたは全く邪悪ではありません)
これですべてが明らかになりました)
UPD
これもうまくいく構造です。

CIsNewBar* newBar = ArrayObj.At(0);
newBar.method( parameter )
理由: