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

 
Igor Makanu:

3.分析の興味深い点は、CopyClose()が何を返すかです。私は自分でチェックしましたが、要求されたTFの.hst ファイルがない場合、CopyClose()は2048 以上を返すことはありません - つまり、これがダウンロードできる最大値なのでしょうか。

2048番は、クライアントにファイルがない場合にサーバーからダウンロードされる部分です。

 
вSlava:

いいえ。2048は、クライアントにデータがないときに、サーバーからダウンロードされるデータの塊です。

MQLをずっとやっている私にとっては、まだ予想外の出来事です。

OK、以下はヘルプにある例です: https://www.mql5.com/ru/docs/series/timeseries_access

と書いてあります。

次に重要なチェックは、その関数が呼び出されるプログラムの種類を確認することである。更新を呼び出した指標と同じ周期で時系列更新要求を送信することは、非常に望ましくないことを思い出してください。ヒストリカルデータの更新は、インジケータが動作するのと同じスレッドで行われるため、インジケータが持っているのと同じシンボル期間のデータを要求するのは望ましくないこと。そのため、衝突する可能性が高い。それを確認 するために、MQL5_PROGRAM_TYPE修飾子を付けたMQL5InfoInteger() 関数を使用します

すなわち、例https://www.mql5.com/ru/code/449

また、.hstファイルが用意されていない場合、つまり、インジケータが自身のシンボルで履歴読み込みを初期化する場合、インジケータで履歴全体をダウンロードするにはどうすればよいのでしょうか。

ここで、iBars(Symbol(),PERIOD_CURRENT)に等しい履歴全体を「ダウンロード」したことをどのようにして知ることができるでしょうか?

iBars()も不正な値を返すのでしょうか?- まだヒストリーがないので、iBars()はありません。

は、MT5では問題なく履歴がダウンロードされるようなので、あとは待って履歴データの状態を確認するだけですが、MT4ではどうなんでしょうか?

PS:kodobaseで昨日、私はMT4用の正しく動作する多通貨の指標を探していたが、コードはkodobaseの多くの例では、模倣の対象ではない、一般的には、指標のない歴史のページングがあります。

Документация по MQL5: Доступ к таймсериям и индикаторам / Организация доступа к данным
Документация по MQL5: Доступ к таймсериям и индикаторам / Организация доступа к данным
  • www.mql5.com
Прежде чем ценовые данные будут доступны в терминале MetaTrader 5, их необходимо получить и обработать. Для получения данных требуется подключение к торговому серверу MetaTrader 5. Данные поступают с сервера по запросу терминала в виде экономно упакованных блоков минутных баров. Механизм обращения к серверу за данными не зависит от того, каким...
 

四つ子では、「ホームキーが押された」。それ以外の方法はない。しばらく勉強している人は、"brick on the keyboard "という言葉を覚えているはずです。

https://www.mql5.com/ru/code/9968

https://www.mql5.com/ru/code/9153

https://www.mql5.com/ru/code/9888

ZG_All_Quotings 3.2
ZG_All_Quotings 3.2
  • www.mql5.com
Скайп-чат поддержки продукта: Последние версии библиотек, скриптов и приложений: Сей скрипт продолжение темы закачек котировок обновлением графика. Решил не обновлять старую версию, а выложить заново. Это принципиально новый скрипт. Удалось добиться максимальной надёжности его работы за счёт переноса функций WinAPI в DLL. Скрипт, как и...
 
Igor Makanu:

私の無料 ダウンローダーで確認できます。

 
Alexey Kozitsyn:

私のフリーダウンローダーを ご覧いただけます。

コードをどのように見ればいいのでしょうか? 履歴をダウンロードする方法は知っていますが、ダウンロードのインジケータを確認する方法がわかりません。

スラバ

4倍で「ホームキーを押す」。それ以外の方法はない。長く勉強している人なら、"brick on the keyboard "という言葉を覚えているはずです。

https://www.mql5.com/ru/code/9968

https://www.mql5.com/ru/code/9153

https://www.mql5.com/ru/code/9888

ここ数年、MQLを使い始めたときは全く勉強していませんでしたが、今年になってから、開発者がMT5とMT4の互換性を可能な限り作り、MQL4のパフォーマンスを向上させたことに本当に驚いています - 以前、MT4はプロジェクトとしてもう開発しないと言われていましたが、修正すべきバグだけが残っています

と、ここで希望が出たのですが、MT4のインジケーターで履歴の自動読み込みの情報が見つからず

基本的に、MT4で履歴を全てダウンロードし、追加チェックなしで保証したい場合は、dfixコードを使用する方が簡単です - .hstファイルにバーdatetime t=0を記述してください。

 
Igor Makanu:

では、どのようにコードを見ればいいのでしょうか?

履歴が自動で読み込まれるだけでいいのでは...?

 

大変残念ですが、もう一度MT4でシニアTFのデータを取得する話題に戻らねばなりません。今回は、ここで提案したテクニックが通用しなかったことが原因です。

以下は、使用するコードです。

#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//--- Время открытия текущего часа, дня и недели
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;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Сбрасываем время открытия текущего часа, дня и недели
   _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();
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                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[])
  {
//--- Проверяем связь с сервером
   if(!IsConnected())                              // Если не удалось установить связь с сервером
     {
      //--- Сбрасываем флаг соединения с сервером
      _isConnected=false;
      //--- Выходим
      return( 0 );
     }
//--- Проверяем первый запуск индикатора
   if(prev_calculated<=0)
     {
      //--- Проверяем, записано ли время открытия текущей недели
      if(!CheckCurrentWeekOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Проверяем, записано ли время открытия текущего дня
      if(!CheckCurrentDayOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Проверяем, записано ли время открытия текущего часа
      if(!CheckCurrentHourOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Устанавливаем флаг соединения с сервером для запуска таймера
      _isConnected=true;
     }
//---
   return( rates_total );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущей недели             |
//+------------------------------------------------------------------+
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 );
  }
//+------------------------------------------------------------------+

アドバイス通り、ページングデータを実装しています。

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

[SERVICESDESK] タイマーで古いTFの時刻を取得するエラー!

スラバ さん 2018.09.27 06:20

何度も議論されてきたことです。エラー4066」についての12ページ。

また、OnInitでリクエストを送信し、OnCalculateで分析するというのは正しいアドバイスでした。

ミリ秒タイマーは何のために必要なのでしょうか?クライアント端末の正常な起動を妨げています。風のメッセージが邪魔をするのではなく、自分のタイマーがみんなの邪魔をするんです。もう一度:クライアントのMT4ターミナルのインジケータは、インターフェイスポテンシャルで動作します。

実装はまさにこんな感じです。最初のデータリクエストはOnInit()で行われます。そして、トレードサーバーとの接続が確立するのを待ち、OnCalculate()!で、高いTFのデータを取得するのです。今日の初打ちで結果を出す。

2018.10.04 09:10:56.266 test_isNewDayInOnCalculate EURGBP.e,M1: OnTimer: Данные старших ТФ загружены!
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего часа = 2018.10.03 09:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего часа = 2018.10.03 09:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего дня = 2018.10.03 00:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего дня = 2018.10.03 00:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущей недели = 2018.10.01 00:00. Ошибка #0
2018.10.04 09:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Время открытия недельного бара = 2018.09.30 00:00. Ошибка #0

ログからわかるように、時間帯と時刻の値が間違っています。

そう、開発者(@Slava)は、私が与えられたアドバイスをすべて適用していないことに気がつくかもしれませんね。つまり、本来はスロータイマーを実行するようにアドバイスされた のですが、私は今でもOnInit()でファストタイマーを実行しています。しかし、この場合はわざとそうしているのです。もし、高速タイマーがインターフェーススレッドで開始され、他のインジケータからのデータ取得が遅くなる可能性があるとすれば、これは大きな問題です。ドキュメントにはそれに関する警告が書かれていません。高速タイマーを持つプログラムを置くと、一種の「ウイルス」となり、他のプログラムの「故障」の原因となる可能性があります。

以上のことから、ミリ秒タイマーに制限を設けるか、OnInit()でこの関数を起動できないことをEventSetMillisecondTimer()のドキュメントに明記し、端末起動時に正常に立ち上がれるようにする必要があると考えます。

 
今日のオープニングでも同じような状況で、エラーが繰り返されている。テストベッド:1つのチャート、3つの指標を表示。2人はタイマーを使わず、3人目が使っている。すべて読み込み時に不正なデータを受信しています。現在、タイマーを使用するインジケータをチャートから削除し、様子を見ることにしています。
 

さて、お楽しみのところです。タイマーを使わないコードです。

#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//--- Время открытия текущего часа, дня и недели
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;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Сбрасываем время открытия текущего часа, дня и недели
   _weekOpenTime= 0;
   _dayOpenTime = 0;
   _hourOpenTime= 0;
//--- Устанавливаем флаг работоспособности
   _isWorking=true;
//--- Сбрасываем флаг установки соединения
   _isConnected=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)
  {
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                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[])
  {
//--- Проверяем связь с сервером
   if(!IsConnected())                              // Если не удалось установить связь с сервером
     {
      //--- Сбрасываем флаг соединения с сервером
      _isConnected=false;
      //--- Выходим
      return( 0 );
     }
//--- Проверяем первый запуск индикатора
   if(prev_calculated<=0)
     {
      //--- Проверяем, записано ли время открытия текущей недели
      if(!CheckCurrentWeekOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Проверяем, записано ли время открытия текущего дня
      if(!CheckCurrentDayOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Проверяем, записано ли время открытия текущего часа
      if(!CheckCurrentHourOpenTime())                              // Если время не записано
         return(0);                                                // Выходим
      //--- Устанавливаем флаг соединения с сервером для запуска таймера
      _isConnected=true;
      //---
      Print(__FUNCTION__,": Данные старших ТФ загружены!");
     }
//---
   return( rates_total );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущей недели             |
//+------------------------------------------------------------------+
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 );
  }
//+------------------------------------------------------------------+

そして、それでも望む結果を得ることはできないのです。開発者(@Slava)さん、コメントお願いします。複数の上位TFから端末を読み込んだ場合、正しいデータが取得できない。シャットダウン後1時間以上経過していることが必須条件です(1時間のバーのデータを取得するため)。もちろん、TFでの起動は1時間以内。

タイマーは関係ないことが判明した。
 
Alexeyさん、Initeの上級TFのデータを照会しているのですね。まだ接続されていない、エラーが返された可能性が高い。最初に来たティックでリクエストをしてみてください。
コテージにいて、タブレットを持ってこなかったので確認できません。