[SERVICE DESK】タイマーでシニアTFの時刻を取得する際にエラーが発生!? - ページ 15

 
Taras Slobodyanik:

インジケーターがデータ更新に追従していない。
ブローカーから新しいバーが来て いるのに、それをチェックしない。
確認するとすべて正しく表示されることを示すために、2行ほど追加しました。

新しいバーをチェックする、という作業状況です。

言わないんですか!?なぜ、新しいバーを記録しておかなければならないと思うのですか?ドキュメントに書かれているのでしょうか?つまり、関数の値を必ず取得し、それを必ず前の値と比較しなければならないのですか?関数があり、その関数は高い時間枠で動作するように設計されています。この関数は,データがない場合はエラーを返すか,不正確な値(この場合は0に等しい)を返すことがあります。以上です。プログラマーは何もしなくても、100%正しい値が得られるのです。

しかし、SeriesInfoInteger()のドキュメントを見ると、こんなことが書いてありました。

エラーの詳細情報を得るには、GetLastError() 関数を呼び出す必要があります。

私のコードにGetLastError()が表示されていますか?こちらがそのチェックです。このチェックは必要で、本当に必要なものでなければなりません。それ以外のものは、すべて松葉づえの解決策です。
 
Alexey Kozitsyn:

そして、私の一番最初の投稿を見てください。そこにエラー4066が表示されていませんか?そして、エラー0となり、不正なデータが返されます。なぜ、関数(この場合は SeriesInfoInteger())はデータを送信する前に関連性をチェックしないのでしょうか?なぜエラーフラグが立たないのでしょうか?ほら、後でエラーを探すより、内部チェックが通るのを少し待った方がいいでしょ。

しかし、その後もいろいろとアドバイスをいただきましたが、まだ結果は出ていません。しかも、それはタイマーがどうのこうのという話ではないことがわかったのです。

OK、ヘルプを読む)

SeriesInfoInteger

履歴データの 状態に関する情報を返す。

ヒストリカルという言葉は何を意味するのか?
履歴が読み込まれている場合 - エラーにはなりません。


アレクセイ・コジツィン

まさか!?また、なぜ私が必ずしも新しいバーを追跡する必要があるとお考えなのでしょうか?ドキュメントに書かれているのでしょうか?つまり、私は関数の値を取得しなければならず、そして、必然的に前のものと比較しなければならないのですか?関数があり、その関数は高い時間枠で動作するように設計されています。この関数は,データがない場合はエラーを返すか,不正確な値(この場合は0に等しい)を返すことがあります。以上です。プログラマーは何もしなくても、100%正しい値が得られるのです。

しかし、SeriesInfoInteger()のドキュメントを見ると、こんなことが書いてありました。

私のコードでは、GetLastError()を参照してください?ここでチェックです。このチェックは必要なものでなければならないし、REALでなければならないそれ以外のものは、すべて松葉づえの解決策です。

何もしなくていいのです)。
...ブローカーはあなたに更新されたデータを送信します - あなたがしたい場合は、計算のためにそれを使用し、そうでない場合 - いいえ問題は、既存の履歴を使用してください)。


ps. 週末で市場が閉まって いるので、端末のデータが間違っていますよ。
で、エラーはありません!!!)

 
Taras Slobodyanik:

OK, read the help)

歴史という言葉の意味は?
履歴が読み込まれている場合 - エラーは発生しません。


借りはありません)。
...ブローカーはあなたに更新されたデータを送信します - あなたがない場合は、計算するためにそれを使用したい場合 - いいえ問題は、使用 歴史)

端末に入ってくるダニが、すでにストーリーになっているのです。そして、その実際の値やエラーを取得したいのです。それでいいのなら-OK。

 
Alexey Kozitsyn:

端末に入ってくるダニが、すでにストーリーになっているのです。そして、その実際の値やエラーを受け取りたいのです。それが自分に合っているならば、それでいいのです。

はい、履歴とは、過去にダウンロードされたもの、またはダウンロード中のものです。
そして、今(最後の引用の後)だけ更新されているのは、歴史ではなく、新しい生データである。

 
Taras Slobodyanik:

バーの計算ではなく、ローソク足の時間を確認する。
こうすることで、正しくアップデートされます(チェック済み)。

Taras、あなたのコードの結果は以下の通りです。

2018.10.08 11:11:39.080 test_isNewDayInOnCalculate GBPUSD,M1: initialized
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Время открытия недельного бара = 2018.09.30 00:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущей недели = 2018.10.01 00:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего дня = 2018.10.05 00:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего дня = 2018.10.05 00:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего часа = 2018.10.05 23:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего часа = 2018.10.05 23:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: OnCalculate: Данные старших ТФ загружены!
 
Alexey Kozitsyn:

Tarasさん、あなたのコードの結果は以下の通りです。

そう、最初の刻み、完成した物語を生み出す刻み、使える刻みなのです。
このティックの後(新しいバーが ある場合)、すぐに2番目のティックが来て、私のコードはあなたの変数を更新し、それらは正しいデータを表示します。

ps. 新しいバーをチェックするために、独自の関数を挿入しても同じになります。

私自身、バーの数を常にチェックしています。数が1以上変化した場合は、もう一度すべてを再計算する必要があり、数が1だけ変化した場合は、新しいバーができたということです。そして、最も重要なエラーだけをチェックするのですが、このディレイエラーは見当たりません。

 
Taras Slobodyanik:

そう、これが最初のティック、つまり準備完了の履歴を与えるものです。
このティックの後(新しいバーが ある場合)、すぐに2番目のティックが来て、私のコードはあなたの変数を更新し、それらは正しいデータを表示します。

Pc.新しいバーを確認するために独自の関数を挿入することができます、それは同じになります。

私自身、バーの数を常にチェックしています。数が1以上変化した場合は、もう一度すべてを再計算する必要があり、数が1だけ変化した場合は、新しいバーができたということです。そして、最も重要なエラーだけをチェックするのですが、このディレイエラーは見当たりません。

ところで、ここにもエラー発生を支持する論拠がある。インジケータでの計算でエラーになる!Expert Advisorを書きました。

#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//--- Время открытия текущего часа, дня и недели
datetime _weekOpenTime = 0;
datetime _hourOpenTime = 0;
datetime _dayOpenTime=0;
//--- Вести лог журнала
const bool inpFileLog=true;
//--- Количество секунд в одном дне
const int SEC_PER_DAY=86400;
//--- Флаг работоспособности индикатора
bool _isWorking=true;
//--- Флаг соединения с торговым сервером (для таймера, получаем в OnCalculate())
bool _isConnected=false;
//---
bool _firstLaunch = true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Устанавливаем флаг первого запуска
   _firstLaunch = true;
//--- Сбрасываем время открытия текущего часа, дня и недели
   _weekOpenTime= 0;
   _dayOpenTime = 0;
   _hourOpenTime= 0;
//--- Устанавливаем флаг работоспособности
   _isWorking=true;
//--- Сбрасываем флаг установки соединения
   _isConnected=false;
////--- Запускаем таймер
//   if(!EventSetMillisecondTimer(20))
//     {
//      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": таймер с частотой 20 не установлен!");
//      //--- Устанавливаем флаг неработоспособности индикатора
//      _isWorking=false;
//     }
//--- Запрос данных
   SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
   SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
   SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
//---
   return( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//|                                                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
////--- Выключаем таймер
//   EventKillTimer();
  }
////+------------------------------------------------------------------+
////|                                                                  |
////+------------------------------------------------------------------+
//void OnTimer()
//  {
////---
//   if(!_isWorking)
//      return;
////---
//   if(!_isConnected)
//      return;
////---
//   Print(__FUNCTION__,": Данные старших ТФ загружены!");
////--- Отключаем таймер
//   EventKillTimer();
//  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Проверяем связь с сервером
   if(!IsConnected())                              // Если не удалось установить связь с сервером
     {
      //--- Сбрасываем флаг соединения с сервером
      _isConnected=false;
      //--- Выходим
      return;
     }
        //--- Проверяем первый запуск эксперта
        if( _firstLaunch )
                {
            //--- Проверяем, записано ли время открытия текущей недели
            if(!CheckCurrentWeekOpenTime())                              // Если время не записано
              return;                                                // Выходим
            //--- Проверяем, записано ли время открытия текущего дня
            if(!CheckCurrentDayOpenTime())                              // Если время не записано
              return;                                                // Выходим
            //--- Проверяем, записано ли время открытия текущего часа
            if(!CheckCurrentHourOpenTime())                              // Если время не записано
              return;                                                // Выходим
            ////--- Устанавливаем флаг соединения с сервером для запуска таймера
            //_isConnected=true;
            //---
            Print(__FUNCTION__,": Данные старших ТФ загружены!");
            //--- Сбрасываем флаг первого запуска
            _firstLaunch = false;
                }
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущей недели             |
//+------------------------------------------------------------------+
bool CheckCurrentWeekOpenTime()
  {
//--- Проверяем, записано ли время
   if(_weekOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия недельного бара
      ResetLastError();
      const datetime weekBarOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия недельного бара = "+TimeToString(weekBarOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия недельного бара
      if(weekBarOpenTime==0 || err!=0) // Если время бара не получено или история обновляется
         return(false);                              // Возвращаем ложь
      //--- Запоминаем время открытия текущей недели (время открытия недельного бара - воскресенье)
      _weekOpenTime=weekBarOpenTime+SEC_PER_DAY;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущей недели = "+TimeToString(_weekOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия недели ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего дня                  |
//+------------------------------------------------------------------+
bool CheckCurrentDayOpenTime()
  {
//--- Проверяем, записано ли время
   if(_dayOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия дневного бара
      ResetLastError();
      const datetime tempDayOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия текущего дня = "+TimeToString(tempDayOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия дневного бара
      if(tempDayOpenTime==0 || err!=0) // Если время бара не получено
         return(false);                                 // Возвращаем ложь
      //--- Сохраняем в глобальную переменную значение открытия текущего дня
      _dayOpenTime=tempDayOpenTime;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущего дня = "+TimeToString(_dayOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия дня ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего часа              |
//+------------------------------------------------------------------+
bool CheckCurrentHourOpenTime()
  {
//--- Проверяем, записано ли время
   if(_hourOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия часового бара
      ResetLastError();
      const datetime tempHourOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия текущего часа = "+TimeToString(tempHourOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия часового бара
      if(tempHourOpenTime==0 || err!=0) // Если время бара не получено
         return(false);                                 // Возвращаем ложь
      //---
      _hourOpenTime=tempHourOpenTime;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущего часа = "+TimeToString(_hourOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия часа ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+

インジケータと同じチャートから実行されます。その結果を見てみましょう。

2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: OnTick: Данные старших ТФ загружены!
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Актуальное время открытия текущего часа = 2018.10.09 06:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Время открытия текущего часа = 2018.10.09 06:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Актуальное время открытия текущего дня = 2018.10.09 00:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Время открытия текущего дня = 2018.10.09 00:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Актуальное время открытия текущей недели = 2018.10.08 00:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Время открытия недельного бара = 2018.10.07 00:00. Ошибка #0
2018.10.09 08:45:41.479 test_isNewDayInOnTick GBPUSD,M1: initialized

2018.10.09 08:45:40.822	GBPUSD,M1: CheckCurrentHourOpenTime: Время открытия текущего часа = 2018.10.08 11:00
2018.10.09 08:45:40.822	GBPUSD,M1: CheckCurrentDayOpenTime: Время открытия текущего дня = 2018.10.08 00:00
2018.10.09 08:45:40.822	GBPUSD,M1: CheckCurrentWeekOpenTime: Время открытия текущей недели = 2018.10.08 00:00
2018.10.09 08:45:40.064	GBPUSD,M1: initialized

2018.10.09 08:45:40.022 Expert Other\test_isNewDayInOnTick GBPUSD,M1: loaded successfully

私たちが見るものすべてがうまくいっていることがわかります。すべてロードされ、エラーがないことに注意してください、データはすぐに更新されます一番の疑問は、なぜGMTのデータは普通に取得できるのに、指標は「ダイヤモンドで勝負」しなければならないのか、ということです。プログラムは平等に機能すべきなのでは?同じコードがインジケータとExpert Advisorで異なる動作をするのはなぜですか?これではいけないと思います。

 
Alexey Kozitsyn:

ところで、ここにもエラー発生を肯定する論拠がある。インジケータでの計算のエラーです!Expert Advisorを書きました。

インジケータと同じチャートから実行されます。その結果を見てみましょう。

私たちが見るものすべてがうまくいっていることがわかります。すべてロードされ、エラーがないことに注意してください、データはすぐに更新されます一番の疑問は、なぜGMTのデータは普通に取得できるのに、指標は「ダイヤモンドで勝負」しなければならないのか、ということです。プログラムは平等に機能すべきなのでは?同じコードがインジケータとExpert Advisorで異なる動作をするのはなぜですか?これではいけないと思います。

すべての指標は単一のスレッドにあり、フローが終了するまで(実際には、次にOpsalureを呼び出すまで)何も新しいことは起こりません。Expert Advisor は独立したスレッドにあるので、起動時にデータ更新のために起動を延期したり、データを更新したりすることができます - ターミナル内の他のすべては影響を受けません。生まれたときからこの状態で、metatrader4の環境が埋もれてしまっているので、直しようがないのです。

 
Unicornis:

接続し、ロード、チェックなどで何かをするのは端末次第なので、すべての指標は1つのスレッドにあり、スレッドのすべてが終了するまで(実際にはOpCalculateの次の呼び出しまで)新しいことは何も起こりません、すなわち、このスレッドにいると、とにかくスレッドの終わりよりも速く何も得られません。Expert Advisor は独自の独立したスレッドにあるので、起動時にデータ更新のために起動を遅らせたり、データを更新したりすることができます - ターミナル内の他のすべては影響を受けません。生まれたときからこうで、メタトレーダー4の環境が埋もれてしまっているので、直しようがないのです。

私は、1つのシンボルのすべての指標が1つのスレッドにあるのに対して、それぞれの専門家が独自のスレッドを持っていることを意識しています。しかし、これは事実ではありません。開発者は、自分たちが作った作品のエラーを修正する開発者そのものなのです。プログラムは異なる動作をするべきではありませんインジケータが何かを見落としていたとしても、それはエラーであり、問題はない。Expert Advisorは、なぜかエラーなく正しいデータを受信しました!だから、実装できるのです。@Slava さん、明らかに間違っている動作が修正されるかどうかについて、ご意見をお聞かせください。あるいは、少なくともドキュメントの追加(prev_calculated = 0では、上級TFの正しいデータが得られないということ)?

 
Alexey Kozitsyn:

はい、1つのシンボルのすべてのインジケータが1つのスレッドにあり、各エキスパートに別のスレッドが割り当てられていることは承知しています。しかし、これは事実ではありません。開発者は、自分の作った作品のエラーを修正するのが開発者です。プログラムは異なる動作をするべきではありませんインジケータが何かを見落としていたとしても、それはエラーであり、問題はない。Expert Advisorは、なぜかエラーなく正しいデータを受信しました!だから、実装できるのです。@Slava さん、明らかに誤った動作が修正されるかどうかについて、ご意見をお聞かせください。少なくとも、ドキュメントへの追記(prev_calculated = 0の場合、高いTFの正しいデータを取得できないこと)でしょうか。

ドキュメントによると、Expert Advisorはデータ受信開始までに最大5秒あり、この間、端末はExpert Advisorのデータを受信しようとするそうです。このインジケータにはそのような可能性はなく、同様に履歴の更新を要求することもありません。履歴が重要であれば、Expert Advisorで計算されなければなりません。現在の実装では望ましい状況が得られないというのが主旨です。本来、TFはタイマーであり、これら複数のタイマーがある瞬間に一致する期間がある。これは、現在のTFの分の最初のティックが5分、時間などの最初の分と一致するため、(開閉時間を除く)100%一致する同期処理である。- は、複数の変数に同じ値を書き込むだけなので、必要なTFをセットして、必要なデータを一度に取得するのが論理的です。なぜ開発者がそうして、逆に開発者がそうしないのかは分かりませんが、多分、今までの端末運用モデルでは、クライアントとサーバーの区分があるので、エキスパートがインジケーターを使えるようにすると、端末がハングアップしてしまうので、できない(しない)のでしょう。

インディケータコールの仕組みは、インディケータが別のインディケータを呼び出す、エキスパート(_asktfexp)がインディケータ(_asktf_sample)を呼び出す、インディケータ(_asktf)を呼び出すというものですが、興味があれば、最後に見てみてください。エキスパートからインジケータを呼び出す場合、インジケータ内のタイマーはスタートしません。したがって、インジケータ内にタイマーを持つソリューションは、このインジケータがチャート上でハングアップするだけで、呼び出されない場合のみです(これは一般的に論理的なことです)。

ファイル: