Прежде чем ценовые данные будут доступны в терминале MetaTrader 5, их необходимо получить и обработать. Для получения данных требуется подключение к торговому серверу MetaTrader 5. Данные поступают с сервера по запросу терминала в виде экономно упакованных блоков минутных баров. Механизм обращения к серверу за данными не зависит от того, каким...
Скайп-чат поддержки продукта: Последние версии библиотек, скриптов и приложений: Сей скрипт продолжение темы закачек котировок обновлением графика. Решил не обновлять старую версию, а выложить заново. Это принципиально новый скрипт. Удалось добиться максимальной надёжности его работы за счёт переноса функций WinAPI в DLL. Скрипт, как и...
#property strict#property indicator_chart_window//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+//--- Время открытия текущего часа, дня и неделиdatetime _weekOpenTime = 0;
datetime _hourOpenTime = 0;
datetime _dayOpenTime=0;
//--- Вести лог журналаconstbool inpFileLog=true;
//--- Количество секунд в одном днеconstint SEC_PER_DAY=86400;
//--- Флаг работоспособности индикатораbool _isWorking=true;
//--- Флаг соединения с торговым сервером (для таймера, получаем в OnCalculate())bool _isConnected=false;
//+------------------------------------------------------------------+//| Custom indicator initialization function |//+------------------------------------------------------------------+intOnInit()
{
//--- Сбрасываем время открытия текущего часа, дня и недели
_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 );
}
//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+voidOnDeinit(constint reason)
{
//--- Выключаем таймерEventKillTimer();
}
//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+voidOnTimer()
{
//---if(!_isWorking)
return;
//---if(!_isConnected)
return;
//---Print(__FUNCTION__,": Данные старших ТФ загружены!");
//--- Отключаем таймерEventKillTimer();
}
//+------------------------------------------------------------------+//| Custom indicator iteration function |//+------------------------------------------------------------------+intOnCalculate(constint rates_total,
constint prev_calculated,
constdatetime &time[],
constdouble &open[],
constdouble &high[],
constdouble &low[],
constdouble &close[],
constlong &tick_volume[],
constlong &volume[],
constint &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();
constdatetime weekBarOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
constint 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();
constdatetime tempDayOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
constint 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();
constdatetime tempHourOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
constint 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.0409:10:56.266 test_isNewDayInOnCalculate EURGBP.e,M1: OnTimer: Данные старших ТФ загружены!
2018.10.0409:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего часа = 2018.10.0309:00. Ошибка #02018.10.0409:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего часа = 2018.10.0309:00. Ошибка #02018.10.0409:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего дня = 2018.10.0300:00. Ошибка #02018.10.0409:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего дня = 2018.10.0300:00. Ошибка #02018.10.0409:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущей недели = 2018.10.0100:00. Ошибка #02018.10.0409:10:56.237 test_isNewDayInOnCalculate EURGBP.e,M1: test_isNewDayInOnCalculate.mq4: Время открытия недельного бара = 2018.09.3000:00. Ошибка #0
#property strict#property indicator_chart_window//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+//--- Время открытия текущего часа, дня и неделиdatetime _weekOpenTime = 0;
datetime _hourOpenTime = 0;
datetime _dayOpenTime=0;
//--- Вести лог журналаconstbool inpFileLog=true;
//--- Количество секунд в одном днеconstint SEC_PER_DAY=86400;
//--- Флаг работоспособности индикатораbool _isWorking=true;
//--- Флаг соединения с торговым сервером (для таймера, получаем в OnCalculate())bool _isConnected=false;
//+------------------------------------------------------------------+//| Custom indicator initialization function |//+------------------------------------------------------------------+intOnInit()
{
//--- Сбрасываем время открытия текущего часа, дня и недели
_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 );
}
//+------------------------------------------------------------------+//| |//+------------------------------------------------------------------+voidOnDeinit(constint reason)
{
}
//+------------------------------------------------------------------+//| Custom indicator iteration function |//+------------------------------------------------------------------+intOnCalculate(constint rates_total,
constint prev_calculated,
constdatetime &time[],
constdouble &open[],
constdouble &high[],
constdouble &low[],
constdouble &close[],
constlong &tick_volume[],
constlong &volume[],
constint &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();
constdatetime weekBarOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
constint 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();
constdatetime tempDayOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
constint 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();
constdatetime tempHourOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
constint 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 );
}
//+------------------------------------------------------------------+
3.分析の興味深い点は、CopyClose()が何を返すかです。私は自分でチェックしましたが、要求されたTFの.hst ファイルがない場合、CopyClose()は2048 以上を返すことはありません - つまり、これがダウンロードできる最大値なのでしょうか。
2048番は、クライアントにファイルがない場合にサーバーからダウンロードされる部分です。
いいえ。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の多くの例では、模倣の対象ではない、一般的には、指標のない歴史のページングがあります。
四つ子では、「ホームキーが押された」。それ以外の方法はない。しばらく勉強している人は、"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
私の無料 ダウンローダーで確認できます。
私のフリーダウンローダーを ご覧いただけます。
コードをどのように見ればいいのでしょうか? 履歴をダウンロードする方法は知っていますが、ダウンロードのインジケータを確認する方法がわかりません。
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を記述してください。
では、どのようにコードを見ればいいのでしょうか?
履歴が自動で読み込まれるだけでいいのでは...?
大変残念ですが、もう一度MT4でシニアTFのデータを取得する話題に戻らねばなりません。今回は、ここで提案したテクニックが通用しなかったことが原因です。
以下は、使用するコードです。
アドバイス通り、ページングデータを実装しています。
トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム
[SERVICESDESK] タイマーで古いTFの時刻を取得するエラー!
スラバ さん 2018.09.27 06:20
何度も議論されてきたことです。エラー4066」についての12ページ。
また、OnInitでリクエストを送信し、OnCalculateで分析するというのは正しいアドバイスでした。
ミリ秒タイマーは何のために必要なのでしょうか?クライアント端末の正常な起動を妨げています。風のメッセージが邪魔をするのではなく、自分のタイマーがみんなの邪魔をするんです。もう一度:クライアントのMT4ターミナルのインジケータは、インターフェイスポテンシャルで動作します。
実装はまさにこんな感じです。最初のデータリクエストはOnInit()で行われます。そして、トレードサーバーとの接続が確立するのを待ち、OnCalculate()!で、高いTFのデータを取得するのです。今日の初打ちで結果を出す。
ログからわかるように、時間帯と時刻の値が間違っています。
そう、開発者(@Slava)は、私が与えられたアドバイスをすべて適用していないことに気がつくかもしれませんね。つまり、本来はスロータイマーを実行するようにアドバイスされた のですが、私は今でもOnInit()でファストタイマーを実行しています。しかし、この場合はわざとそうしているのです。もし、高速タイマーがインターフェーススレッドで開始され、他のインジケータからのデータ取得が遅くなる可能性があるとすれば、これは大きな問題です。ドキュメントにはそれに関する警告が書かれていません。高速タイマーを持つプログラムを置くと、一種の「ウイルス」となり、他のプログラムの「故障」の原因となる可能性があります。
以上のことから、ミリ秒タイマーに制限を設けるか、OnInit()でこの関数を起動できないことをEventSetMillisecondTimer()のドキュメントに明記し、端末起動時に正常に立ち上がれるようにする必要があると考えます。
さて、お楽しみのところです。タイマーを使わないコードです。
そして、それでも望む結果を得ることはできないのです。開発者(@Slava)さん、コメントお願いします。複数の上位TFから端末を読み込んだ場合、正しいデータが取得できない。シャットダウン後1時間以上経過していることが必須条件です(1時間のバーのデータを取得するため)。もちろん、TFでの起動は1時間以内。
タイマーは関係ないことが判明した。