Есть скрипт, бросаю его на график с периодом H1. Параметр timeframe равен PERIOD_M15.
прикрепите код скрипта или его кусок с вызовом iTime()
input int PERIOD_Vivoda=PERIOD_M15; //Выводимый период. input datetime Nachalo=D'2022.08.15 00:00:00'; input datetime Final=0; //От Nachalo и до конца. void OnStart(void) { if(VremyaFailaPoiska==Nachalo)ZapisStroki(Visota-VisotaLiteri-3,OtstupLinii,"СТАРТ"); //СТАРТ tx=TimeCurrent(); if(Final==0)ty=NTB(tx,PERIOD_Vivoda,nazad,"#673:");//Округлить до PERIOD_Vivoda, вызов NTB() else ty=Final; ... } //-----------------------------------------------------------------------------// // Нормализует время до действительно существующего бара. // // (При отсутствии нескольких баров подряд.) // // Т.е. половина неполного периода определится как существующий бар. Если бара // // не существует (дыра, выходной) то см. 'kudaNT' // // Пример: PERIOD_NTB равен PERIOD_D1 // // t1NTB=середина субботы или середина_воскресения, тогда: // // 'nazad'=начало_пятницы, // // 'vpered'=начало_понедельника, // // 'bliz'=начало_пятницы или начало_понедельника по абсолютной // // разнице в секундах после вычета времени выходных. // //-----------------------------------------------------------------------------// datetime NTB(datetime t1NTB,int PERIOD_NTB=0,int kudaNT=vpered,string strNTB="") { int j,k; datetime told,tper,tnew; j=iBarShift(NULL,PERIOD_NTB,t1NTB,false); told=iTime(NULL,PERIOD_NTB,j); if(j==0)//Если нулевой(крайний) бар. { //Расчет времени окончания нулевого бара(бар есть, значит не выходной) tper=told+PERIOD_NTB*60; if(told<=t1NTB && t1NTB<tper)return(told); //Расчет следующего возможного бара tnew=tper+PERIOD_NTB*60; k=TimeDayOfWeek(tnew); if(k==0 || k==6)tnew+=172800;//Не считая первого часа в субботу if(tper<=t1NTB && t1NTB<tnew)return(tper);//Конец нулевого бара(как начало следующего бара) else{//Если t1NTB далеко в будующем Print(">>>>>Предупреждение:<<<<<"); Print(VivodTime("told",told),VivodTime("t1NTB",t1NTB),VivodTime("tper",tper),VivodTime("tnew",tnew) ," ",PeriodToStr(PERIOD_NTB)," j=",j ); } } ... }
После обращения к таймсериям проверяйте результат. Так если получено значение 0, то вызовите GetLastError() и узнайте причину, по которой не получилось принять данные.
А еще лучше - проверять готовность данных на ТФ загодя, вызвав до начала расчетов функцию:
bool IsTFDataReady(const ENUM_TIMEFRAMES eTF) { ResetLastError(); iTime(NULL, eTF, 1); return GetLastError() == ERR_NO_ERROR; }
После обращения к таймсериям проверяйте результат. Так если получено значение 0, то вызовите GetLastError() и узнайте причину, по которой не получилось принять данные.
А еще лучше - проверять готовность данных на ТФ загодя, вызвав до начала расчетов функцию:
Игорь, хочу выразить вам благодарность. Опираясь на ваши подсказки с форума сделал себе такую штуку для работы с котировками других таймфреймов/инструментов. Пользуюсь до сих пор.
#property strict #define RATES_WAITING_SEC 30 #define RATES_WAITING_TICKS 10 MqlRates ratesD1[]; MqlRates ratesH1[]; datetime ratesWaitingTimeTo; int ratesWaitingTicksLeft; int OnInit() { ratesWaitingTimeTo = 0; ratesWaitingTicksLeft = 0; return(INIT_SUCCEEDED); } void OnTick() { bool isRatesActual = updateRates(); calculateSomethingUsingRates(isRatesActual); } bool calculateSomethingUsingRates(bool isRatesActual) { if(!isRatesActual) return(false); // Можно использовать ratesD1[] и ratesH1[] return(true); } bool updateRates() { datetime timeCurrent = TimeCurrent(); // Waiting for rates to be loaded if(timeCurrent <= ratesWaitingTimeTo || ratesWaitingTicksLeft > 0) { ArrayCopyRates(ratesD1, _Symbol, PERIOD_D1); ArrayCopyRates(ratesH1, _Symbol, PERIOD_H1); PrintFormat("Waiting for rates to be loaded. Remaining: %i seconds, %i ticks", ratesWaitingTimeTo - timeCurrent, ratesWaitingTicksLeft); if(ratesWaitingTicksLeft > 0) ratesWaitingTicksLeft--; return(false); } // Timeframes copying bool allRatesCopied = true; updateRates_CopyTo(ratesD1, PERIOD_D1, allRatesCopied); updateRates_CopyTo(ratesH1, PERIOD_H1, allRatesCopied); // ------- if(!allRatesCopied) { ratesWaitingTimeTo = timeCurrent + RATES_WAITING_SEC; ratesWaitingTicksLeft = RATES_WAITING_TICKS; return(false); } return(true); } void updateRates_CopyTo(MqlRates &ratesArray[], ENUM_TIMEFRAMES timeframe, bool &allRatesCopied) { ResetLastError(); int copied = ArrayCopyRates(ratesArray, _Symbol, timeframe); int error = GetLastError(); if(copied < 1 || error != ERR_NO_ERROR) { PrintFormat("CopyRates error %i, rates copied: %i, timeframe %s", error, copied, EnumToString(timeframe)); allRatesCopied = false; } }
Просто вызываю updateRates() с каждым тиком.
Этот конкретный кусок кода взят из одного из последних экспертов, где требовались котировки с H1 и D1, не зависимо от текущего таймфрейма.
Игорь, хочу выразить вам благодарность. Опираясь на ваши подсказки с форума сделал себе такую штуку для работы с котировками других таймфреймов/инструментов. Пользуюсь до сих пор.
Просто вызываю updateRates() с каждым тиком.
Этот конкретный кусок кода взят из одного из последних экспертов, где требовались котировки с H1 и D1, не зависимо от текущего таймфрейма.
Правда, я не уверен, что обязательно вызывать ArrayCopyRates() с каждым тиком. Ведь справка (по ArrayCopyRates) гласит следующее:
...происходит виртуальное копирование таймсерии в массив структур MqlRates. Это означает, что если данные таймсерии обновились, то повторное копирование не требуется - массив rates_array[] по-прежнему будет ссылаться на актуальную версию таймсерии и данные будут корректными всегда.
Возможно и правда достаточно будет один раз вызвать после инициализации. Давненько хочу проверить это, все руки не доходят.
То есть, понятно, что данные будут автоматически обновляться в этих массивах. Вопрос только в том, продолжат ли они обновляться если этот таймфрейм длительное время не будет использоваться (не открыто окно с этим таймфреймом, ни одна mql программа не запрашивает котировки с него). Вот это проверить все руки не доходят. А до тех пор на всякий пожарный дергаю ArrayCopyRates с каждым тиком, запрашивая таким образом постоянно котировки, что бы они оставались актуальными.
С другой стороны, если вызывать ArrayCopyRates() только раз и случится какая-нибудь херня из-за которой данные вдруг станут не корректными, то мы об этом не узнаем. Может лучше так и оставить, тем более времени на такое дергание тратится не много.
После обращения к таймсериям проверяйте результат. Так если получено значение 0, то вызовите GetLastError() и узнайте причину, по которой не получилось принять данные.
А еще лучше - проверять готовность данных на ТФ загодя, вызвав до начала расчетов функцию:
Наверное, я не верно выразился. Результат не равен нулю. Возвращаемое значение ноль часов, т.к. на дворе была полночь. Дата при этом соответствовала.
Выдержка из Log файла во вложении.
Видно, что параметр t1NTB изменяется с течением времени. Видно, что j=0 т.е. iBarShift отрабатывает правильно. Вот только told выдает ноль часов и ноль минут.
Скрипт запущен:
0 11:28:10.233 Script DiagrammaBMP EURUSD,H1: loaded successfully
Скрипт прошел с ошибками и окончен:
0 11:28:25.661 Script DiagrammaBMP EURUSD,H1: removed
Посмотрел я на это, почесал репу. И запустил повторно (через 10 сек)
Отсюда:
0 11:28:35.520 Script DiagrammaBMP EURUSD,H1: loaded successfully
До окончания:
0 11:28:49.092 Script DiagrammaBMP EURUSD,H1: removed
ни одной ошибки.
Ничего не менял, не перезагружал, не компилировал, вообще ничего не делал. По сути даже мышкой не двигал. Взял файл из навигатора и бросил его на график, переместив на пять сантиметров вправо. И так два раза подряд. Почему один раз прошло с ошибками, а другой раз без них??
Добавил RefreshRates() в начало OnInit(). Возвращает false.
Перенес из OnInit() в OnStart(). Так работает.
Поставил снова в OnInit(), но не в начало, а в конец функции. Работает.
-----
RefreshRates() в первых строках OnInit() стабильно возвращает false. GetLastError()=0.
рефрешратес нужен только если у вас код очень медленный, иначе какой смысл обновлять каждые 10милесекунд?
если с острова торгуете, разумней будет отложенными ордерами.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Доброго времени суток!
[Вопрос по MetaTrader 4.]
Давно (больше года) заметил сбой в функции:
datetime iTime(
string symbol, // символ
int timeframe, // период
int shift // сдвиг
);
когда shift==0, т.е. с текущим/настоящим временем.
Возвращаемое значение оказывается равным предыдущему вызову.
-----
Есть скрипт, бросаю его на график с периодом H1. Параметр timeframe равен PERIOD_M15. Добавил Print() с выводом значений переменных.
Из окна "Навигатор" мышкой перетаскиваю скрипт на график. Сделал так в 0 часов 10 минут, возвращаемое значение 00:00, правильное.
Следующий раз использовал скрипт в 11 часов 28 минут, возвращаемое значение 00:00, как при прошлом вызове!
Тут же, через 3-5 секунд, повторно бросаю скрипт, и он отрабатывает без сбоев возвращаемое значение 11:15.
(Бывает через раз. Около часа ночи запускаю >> работает. В 14 часов запускаю >> работает. В 18 часов запускаю >> возвращает время соответствующее первому часу ночи.)