Mt4 サポート終了。 - ページ 20

 
Alexey Viktorov:
そこからスタートしないほうがいい。これが怖いんですよね。OOPを熟知しているサポーターの私でさえ、この文章のせいでつまずいてしまいました...。...何も理解できなかった。だから、その違いを最下層で説明しようとしているのです。

また、よりシンプルにすることも可能です。

OOP - 単一のインターフェースを定義することができます。それ以降は、プラットフォーム特有のものはすべて「隠れる」ので、作業の邪魔になることはありません。

もちろん、純粋に手続き的なアプローチで行うことも可能です。しかし、手続き型バリアントのサポートは、各関数ですべてのプラットフォームを一度に処理しなければならないため、より複雑なものになるでしょう。

 

少し遅れて申し訳ございませんでした。

以下は、その関数の最初のバージョンです。さらに磨きをかけて発展させることができます。もし、間違いに気づかれた方がいらっしゃいましたら、コメントをお願いします。

//+------------------------------------------------------------------+
//|                                                    Новый бар.mq4 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//------------------------
datetime Время_последнего_бара;
//------------------------
//Счетчики
//------------------------
int Частота_таймера = 25;
int Минута;
int 5_Минут;
int 15_Минут;
int 30_Минут;
int 1_Час;
int 4_Часа;
int 1_День;
//------------------------
//Флаги
//------------------------
bool Новый_минутный_бар;
bool Новый_5_минутный_бар;
bool Новый_15_минутный_бар;
bool Новый_30_минутный_бар;
bool Новый_часовой_бар;
bool Новый_4_часовой_бар;
bool Новый_дневной_бар;
//--------------------------------------------
//Значения временных периодов в миллесекундах.
//--------------------------------------------
#define  M1    60000
#define  M5    300000
#define  M15   900000
#define  M30   1800000
#define  H1    3600000
#define  H4    14000000
#define  D1    84000000
//------------------------
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetMillisecondTimer(25);
   //-------------------------------------------------------------
   //Записываем время последнего бара на момент загрузки эксперта.  
   //Для корректного начала работы, робота нужно запустить на М1. 
   //-------------------------------------------------------------
   Время_последнего_бара = Time[0];
   //-------------------------------------------------------------
   
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
      
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
//---------------------------------------------------------------
//Считаем время в счетчиках. Для каждого таймфрейма свой счетчик.
//Как только значение счетчика достигает количество миллесекунд в 
//периоде таймфрейма, счетчик обнуляется и выставляется флаг нового
//бара этого таймфрейма. Этот флаг остается до тех пор, пока 
//один из вызовов функции Новый_бар() не снимет его. 
//Таким образом, флаг нового бара любого таймфрейма остается до тех
//пор, пока пользователь не узнает этот факт, вызвав функцию Новый_бар().
//---------------------------------------------------------------
void OnTimer()
{
 static bool Ведется_отсчет;
   //---------------------------
   if(!Ведется_отсчет && Time[0] != Время_последнего_бара) 
     {
      Ведется_отсчет = true;
     }   
   //---------------------------
   if(Ведется_отсчет)
     {
      Минута ++;
      5_Минут  ++;
      15_Минут ++;
      30_Минут ++;
      1_Час    ++;
      4_Часа   ++;
      1_День   ++;
      //--------------------------
      if(Минута*Частота_таймера >= M1)
        {
         Новый_минутный_бар = true;
         Минута = 0;
        } 
      //--------------------------
      if(5_Минут*Частота_таймера >= M5)
        {
         Новый_5_минутный_бар = true;
         5_Минут = 0;
        } 
      //--------------------------   
      if(15_Минут*Частота_таймера >= M15)
        {
         Новый_15_минутный_бар = true;
         15_Минут = 0;
        } 
      //--------------------------   
      if(30_Минут*Частота_таймера >= M30)
        {
         Новый_30_минутный_бар = true;
         30_Минут = 0;
        } 
      //--------------------------   
      if(1_Час*Частота_таймера >= H1)
        {
         Новый_часовой_бар = true;
         1_Час = 0;
        } 
      //--------------------------  
      if(4_Часа*Частота_таймера >= H4)
        {
         Новый_4_часовой_бар = true;
         4_Часа = 0;
        } 
      //--------------------------  
      if(1_День*Частота_таймера >= D1)
        {
         Новый_дневной_бар = true;
         1_День = 0;
        } 
   //-------------------------- 
   }          
}
//--------------------------





//--------------------------
bool Новый_бар(int Таймфрейм = M1)
{
 bool Новый_бар;
 //-----------------------
 switch(Таймфрейм)
   {
    case M1: 
          //-----------------------
          Новый_бар  = Новый_минутный_бар;
          if(Новый_бар)Новый_минутный_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------      
    case M5: 
          //-----------------------
          Новый_бар  = Новый_5_минутный_бар;
          if(Новый_бар)Новый_5_минутный_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------  
    case M15: 
          //-----------------------
          Новый_бар  = Новый_15_минутный_бар;
          if(Новый_бар)Новый_15_минутный_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------  
    case M30: 
          //-----------------------
          Новый_бар  = Новый_30_минутный_бар;
          if(Новый_бар)Новый_30_минутный_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------  
    case H1: 
          //-----------------------
          Новый_бар  = Новый_часовой_бар;
          if(Новый_бар)Новый_часовой_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------      
    case H4: 
          //-----------------------
          Новый_бар  = Новый_4_часовой_бар;
          if(Новый_бар)Новый_4_часовой_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------              
    case D1: 
          //-----------------------
          Новый_бар  = Новый_дневной_бар;
          if(Новый_бар)Новый_дневной_бар = false;
          return(Новый_бар);
          //-----------------------
          break;
    //-----------------------------     
   }
 //-----------------------
 return(false);
}
//--------------------------
//+------------------------------------------------------------------+
 
Peter Konow OOPを使わなくても、もっと簡単にできるはずです。

謹んで申し上げます。
 
ユーザーがNew_bar()関数を 呼び出すとすぐに、要求された時間枠に新しいバーが発生したという応答を受け取ります。同時に、この関数が呼ばれた後、新しいバーイベントが発生した場合、イベントフラグがクリアされます。つまり、所望の時間枠の新しいバーの通知は、バーごとに一度だけ受け取ることができます。新しいバーの通知を受けた後、このバーは新しいものではなくなります。
 
Реter Konow:

以下は、その関数の最初のバージョンです。さらに磨きをかけて発展させることができます。もし、間違いに気づかれた方がいらっしゃいましたら、コメントをお願いします。

一見すると、すべてがうまくいっているように見えます。あまり深く掘り下げてはいないのですが。

個人的には、前回と今回の 時間をバーの継続時間で割って、値が変わっていれば新しいバーが表示されるようにすればよいのではないかと思っています。でも、こんなやり方もあるんですね。

スタイルについては、個人的には変数の型がわからないのがちょっと気になりますが(私は「ハンガリー記法、あらゆる変数の接頭辞がその型の略称である場合」に慣れているので)、それは不要かもしれませんね。

 
Andrey Kisselyov:
Peter Konow OOPを使わなくても、もっと簡単にできるはずです。

謹んで申し上げます。
確かに、できる可能性はありますね。1時間の猶予があった。考えて何かを削ればいいんです。すべて可能です。
 
Andrey Kisselyov:
Peter Konow OOPを使わなくても、もっとシンプルにできるかもしれませんよ。

敬具

私が正しく理解している限りではという狙いがあります。もし彼がこの機能でプロテクトされたファイルを掲載していたとしても、このような書き方をしているとは思いもよらなかったでしょう。

 
George Merts:

一見すると、すべてがうまくいっているように見えます。深堀りが足りないんです。

個人的には、前回と今回の 時間をバーの長さで割って、値が変わったら新しいバーが来たということでいいんじゃないかと思います。でも、こんなやり方もあるんですね。

スタイルについては、個人的には変数の型がわからないのがちょっと気になりますが(私は「ハンガリー記法、あらゆる変数の接頭辞がその型の略称である場合」に慣れているので)、それは不要かもしれませんね。

まあ、スタイルの認識というのは、習慣の問題ですからね。私も、支店で渡されたコードを読むのは難しいと感じています。ただ、たまにムカつくんですよね))

 
George Merts:

また、よりシンプルにすることも可能です。

OOP - 単一のインターフェースを定義することができます。それ以降は、プラットフォーム特有のものはすべて「隠れる」ので、作業の邪魔になることはありません。

もちろん、純粋に手続き的なアプローチで行うことも可能です。しかし、手続き型バリアントのサポートは、各関数ですべてのプラットフォームを一度に処理しなければならないため、より困難です。

あらゆる計算タスクのプログラミングに単一のインタフェースが適用できないことは、すでに述べたとおりである...インターフェイスの形で素敵なものを置くことは、すでに完成されたコードにのみ適用される純粋な化粧直しであり、コードのサポートと洗練をさらに妨げることになる...。

 
Mickey Moose:

私が正しく理解している限りではという狙いがあります。もし、この機能でプロテクトされたファイルを投稿していたとしても、このような書き方をしていたとは思いもよらなかったでしょう。

ただ動くだけでなく、早く、正確に、間違いなく動くこと、ソースに構造化された形式があること、明確に書かれていることが望ましいです。

よろしくお願いします。