Форум » Полезные советы » Выявление дыр истории » Ответить

Выявление дыр истории

Stoletov: Я собираюсь затронуть проблему дыр в истории и дать рецепт, как выявлять эти дыры программным путем. Эта проблема может коснуться тех, кто каким-либо образом использует в расчете индикатора внутренние бары. В дальнейшем изложении буду называть бары текущего графика внешними барами, а более «мелкие» бары внутри внешнего бара внутренними барами. Например 4-х часовой бар-внешний, а минутный -внутренний . Дыры в истории относятся именно к внутренним барам. На практике бывает, что к примеру минутные бары могут отсутствовать на интервале нескольких дней. Особенно неприятно, если эта дыра возникла в недавнее время . Тогда сами понимаете, что будет с индикатором - он может дать ложный сигнал или наоборот не сработает в нужный момент. Поэтому нужно по крайне мере иметь средство оповещения о таких дырах в истории внутренних баров, чтобы предпринять меры по ликвидации этих дыр – закачать новые данные внутреннего таймфрейма. Для этого предлагается скрипт, приведенный здесь в конце. В скрипте критерий наличия дыры выглядит так: jmax<jmin, где jmax - номер самого позднего внутреннего бара у начала внешнего бара, а jmin - номер самого раннего бара у конца внешнего бара. В нормальной ситуации, когда дыр нет, выполняется неравенство jmax>jmin. Вначале скрипт вычисляет количество внешних баров i, в пределах которого имеется история внутренних баров. Затем выполняется цикл по всем внешним барам от i до 0. Скрипт выводит сообщения в зависимости от результата. Если дыр нет, то будет сообщение типа «EURUSD: в истории дыр на барах 1 мин нет, текущий период=240 мин». Если дыры есть, то будут несколько сообщения типа «EURUSD: дыра в истории на барах 1 мин в момент t=2014.11.27 04:00, текущий период=240 мин» и одно завершающее сообщение «EURUSD: дата начала счета 2014.01.08, имеется 5 дыр в истории». Приведенный текст скрипта можно вставить в индикатор, чтобы автоматически получать сигналы тревоги. В индикаторе сообщение о том, что в истории дыр нет, можно удалить. Примечание: В скрипте встречается идентификатор Time[i-0]. Если убрать 0, то после копирования скрипта сюда почему-то остается только Time без квадратных скобок, поэтому и добавлен 0. В тексте скрипта 0 конечно можно убрать. // скрипт выявления дыр истории test_holes.mq4 // created by Stoletov // i - количество внешних баров на графике для расчета (для внешних баров с номерами свыше i история внутренних баров отсутствует) // Per - внутренний период // jmax - номер самого позднего внутреннего бара у начала внешнего бара i // jmin - номер самого раннего бара у конца внешнего бара i // j - текущий номер внутреннего бара во внешнем баре i // tst - дата начала расчета #property show_inputs extern int Per=1; // должен быть не больше, чем период внешнего бара, // например если внешний бар дневной (период = 1440 мин), то допустимые значения Per=1440,240,60,30,15,5,1 void OnStart() { int jmin, jmax, i, cnt=0; string tst, Cur=Symbol(); i=iBarShift(Cur, Period(), iTime(Cur, Per,iBars(Cur,Per)-1))-1; tst=TimeToStr(Time[i-0], TIME_DATE); while(i>=0) {if (i==0) jmin=0; else {jmin=iBarShift(Cur,Per,Time[i-1]); if (iTime(Cur, Per, jmin)>=Time[i-1]) jmin++;} jmax=iBarShift(Cur,Per,Time[i-0]); if (iTime(Cur, Per, jmax)<Time[i-0]) jmax--; if(jmax<jmin) // признак дыры в истории внутренних баров {Alert(Cur, " : дыра в истории на барах ", Per, " мин в момент t=", TimeToStr(Time[i-0], TIME_DATE|TIME_MINUTES), ", текущий период= ", Period()," мин"); cnt++;} i--;} //конец цикла while if(cnt==0) Alert(Cur, ": в истории дыр на барах ", Per, " мин нет, текущий период = ", Period(), " мин"); else Alert(Cur, ": дата начала счета ", tst,", имеется ", cnt, " дыр в истории"); return; }

Ответов - 9

Scriptong: Stoletov пишет: В скрипте критерий наличия дыры выглядит так: jmax<jmin, где jmax - номер самого позднего внутреннего бара у начала внешнего бара, а jmin - номер самого раннего бара у конца внешнего бара. В нормальной ситуации, когда дыр нет, выполняется неравенство jmax>jmin. Таким образом, проверяется не наличие всех баров младшего ТФ, принадлежащих исследуемому бару старшего ТФ, а только принципиальное наличие баров младшего ТФ? То есть если в баре Н1 будет всего два бара М1 (а не 60, как предполагается), то скрипт не отнесет такое положение вещей к дыре? Правильно я понимаю? Терминология На мой взгляд, термины "внутренний бар" и "внешний бар" в контексте поднятой проблемы выбраны очень неудачно, т. к. эти понятия являются частью паттернов Price Action (очень распространенные паттерны). Чтобы не вводить любителей таких паттернов в заблуждение, лучше использовать термины "бар старшего ТФ", "бар младшего ТФ". По коду В новом MQL4 есть такое перечисление как ENUM_TIMEFRAMES. Им можно заменить тип единственного настроечного параметра скрипта. Это позволит оградить пользователя от ввода некорректного значения. Также при инициализации скрипта желательно сделать проверку, является ли указанный ТФ младшим по отношению к текущему. Stoletov пишет: Примечание: В скрипте встречается идентификатор Time[i-0]. Если убрать 0, то после копирования скрипта сюда почему-то остается только Time без квадратных скобок, поэтому и добавлен 0. В тексте скрипта 0 конечно можно убрать. Форум относит литеру i в квадратных скобках к BB-коду "курсив". Чтобы этого не было, можно просто оставлять пробелы по краям от литеры i. Вот так: Time[ i ].

Stoletov: Scriptong пишет: Таким образом, проверяется не наличие всех баров младшего ТФ, принадлежащих исследуемому бару старшего ТФ, а только принципиальное наличие баров младшего ТФ? То есть если в баре Н1 будет всего два бара М1 (а не 60, как предполагается), то скрипт не отнесет такое положение вещей к дыре? Правильно я понимаю? Да, именно так и надо понимать. С учетом всех замечаний переписываю основной текст следующим образом: Здесь затрагивается проблема дыр в истории и дается рецепт, как выявлять эти дыры программным путем. Под дырами понимается отсутствие в терминале информации по части баров младшего ТФ. Не следует путать дыры с недостаточного количеством баров младшего ТФ в баре старшего ТФ. Например, если в часовом баре минутных баров меньше 60, то это не дыра. Проблема дыр может коснуться тех трейдеров, кто каким-либо образом использует в расчете индикатора бары младшего ТФ. На практике бывает, что к примеру минутные бары могут отсутствовать на интервале нескольких дней. Особенно неприятно, если эта дыра возникла в недавнее время . Тогда сами понимаете, что будет с индикатором - он может дать ложный сигнал или наоборот не сработает в нужный момент. Поэтому нужно по крайней мере иметь средство оповещения о дырах в истории баров младшего ТФ, чтобы предпринять меры по ликвидации этих дыр – закачать новые данные младшего ТФ. Для этого предлагается скрипт, приведенный ниже. Вначале скрипт вычисляет количество i баров старшего ТФ, в пределах которого имеется история баров младшего ТФ, оператором i=iBarShift. В цикле по барам старшего ТФ от i до 0 вычисляется номер jmin самого раннего бара младшего ТФ у конца бара i старшего ТФ и номер jmax самого позднего бара младшего ТФ у начала бара i старшего ТФ. Для этого используются операторы jmin=iBarShift и jmax=iBarShift. Если номер jmin или jmax вышел за пределы бара старшего ТФ, что бывает в случае недостаточного количества баров младшего ТФ например ночью, то производится коррекция операторами if … jmin++ и if … jmax--. После этих манипуляций критерий наличия дыры будет выглядеть так: jmax<jmin. В нормальной ситуации, когда дыр нет, выполняется неравенство jmax>=jmin. Скрипт выводит сообщения в зависимости от результата. Если дыр нет, то будет сообщение типа «EURUSD: в истории дыр на барах 1 мин нет, текущий период=240 мин». Если дыры есть, то будут несколько сообщения типа «EURUSD: дыра в истории на барах 1 мин в момент t=2014.11.27 04:00, текущий период=240 мин» и одно завершающее сообщение «EURUSD: дата начала счета 2014.01.08, имеется 5 дыр в истории». Приведенный текст скрипта можно вставить в индикатор, чтобы автоматически получать сигналы тревоги. В индикаторе сообщение о том, что в истории дыр нет, можно удалить. Как вариант можно в индикаторе при выполнении критерия дыры jmax<jmin просто присвоить элементу индикаторного массива 0. Тогда дыра будет видна и без сообщений по провалу в индикаторной линии. // скрипт выявления дыр истории test_holes.mq4 // created by Stoletov // i - количество баров старшего ТФ на графике для расчета (для баров старшего ТФ с номерами свыше i история баров младшего ТФ отсутствует) // Per - период младшего ТФ // jmax - номер самого позднего бара младшего ТФ у начала бара i старшего ТФ // jmin - номер самого раннего бара младшего ТФ у конца бара i старшего ТФ // tst - дата начала расчета #property show_inputs extern ENUM_TIMEFRAMES Per=PERIOD_M1; // должен быть не больше, чем период бара старшего ТФ, // например если бар старшего ТФ дневной (период = 1440 мин), то допустимые значения Per=1440,240,60,30,15,5,1 void OnStart() { int jmin, jmax, i, cnt=0; string tst, Cur=Symbol(); if(Per>Period()) {Alert("Младший ТФ должен быть не больше старшего ТФ, который равен ", Period(), " мин"); return;} i=iBarShift(Cur, Period(), iTime(Cur, Per,iBars(Cur,Per)-1))-1; tst=TimeToStr(Time[ i ], TIME_DATE); while(i>=0) {if (i==0) jmin=0; else {jmin=iBarShift(Cur,Per,Time[i-1]); if (iTime(Cur, Per, jmin)>=Time[i-1]) jmin++;} jmax=iBarShift(Cur,Per,Time[ i ]); if (iTime(Cur, Per, jmax)<Time[ i ]) jmax--; if(jmax<jmin) // признак дыры в истории баров младшего ТФ {Alert(Cur, " : дыра в истории на барах ", Per, " мин в момент t=", TimeToStr(Time[ i ], TIME_DATE|TIME_MINUTES), ", текущий период= ", Period()," мин"); cnt++;} i--;} //конец цикла while if(cnt==0) Alert(Cur, ": в истории дыр на барах ", Per, " мин нет, текущий период = ", Period(), " мин"); else Alert(Cur, ": дата начала счета ", tst,", имеется ", cnt, " дыр в истории"); return; }

Scriptong: Stoletov пишет: Да, именно так и надо понимать. В принципе, тоже интересный критерий. Тем более, его специфика в том, что он проверяет наличие "подистории" для старшего ТФ. Тогда же, когда дыра на самом старшем ТФ, скрипт определить такую дыру не сможет. Но это, исходя из цели программы, даже не требуется, т. к. индикатор не начнет искать историю на младшем ТФ по причине отсутствия баров на текущем ТФ. Хотя в моем понимании дыра - это отсутствие в истории баров, которые были в истории реально. В свое время писал подобный скрипт и под дырами понимал отсутствие минутных баров в рабочий день более 20 баров подряд. Остальные провалы, где не было 5 - 10 (до 19 включительно) баров, не считал за дыры. Выходные и праздничные дни скрипт "понимал". По сути функционирования программы Запустил на имеющейся в одном из терминалов истории. Скрипт нашел 13 дыр. Посмотрел в соответствующем месте истории. Оказалось, что на М1 отсутствовали данные с 20:00 25.06.2014 до 09:00 26.06.2014 (на Н1 эти бары были). Получаем, что это не 13 дыр, а одна сплошная дыра - отсутствие минутных баров подряд, без перерывов.


Stoletov: Scriptong пишет: Хотя в моем понимании дыра - это отсутствие в истории баров, которые были в истории реально. Все правильно. Можно еще сказать так: дыра - это когда для конкретного бара старшего ТФ ПОЛНОСТЬЮ или ЧАСТИЧНО отсутствует информация о барах младшего ТФ, хотя последние реально были. Scriptong пишет: Получаем, что это не 13 дыр, а одна сплошная дыра - отсутствие минутных баров подряд, без перерывов. Да, обычно так и бывает - одна большая дыра. Но скрипт выдает ее как серию дыр. Такой уж у него алгоритм. Можно конечно в скрипте этот недостаток устранить.

Scriptong: Stoletov пишет: Все правильно. Можно еще сказать так: дыра - это когда для конкретного бара старшего ТФ ПОЛНОСТЬЮ или ЧАСТИЧНО отсутствует информация о барах младшего ТФ, хотя последние реально были. В данном случае я не спорю. Каждый мыслит по-своему. Я вот, к примеру, даже подумать о предложенной трактовке дыры не мог. Увидев код, долго искал в нем ошибку, пока не понял, что представлено другое видение. Причем это видение проблемы дыр достаточно интересное. Кроме всего прочего, такой подход в некоторых случаях лучше того, о котором говорил я, т. к. критерий дыры устанавливается автоматически, а не путем указания пользователем величины "простоя" рынка в минутах. То есть присутствует фактор автонастройки программы. Stoletov пишет: Можно конечно в скрипте этот недостаток устранить. Я на это и намекал Но делать или не делать - решать Вам. У каждого свои критерии степени готовности программы.

Stoletov: Я еще вчера доработал скрипт так, чтобы сообщение о каждой дыре было один раз вместо дробления на целый ряд сообщений, когда дыра охватывает подряд несколько баров старшего ТФ. Однако «природной» дыры не нашел, чтобы проверить скрипт. Типа охотник вышел на охоту, а зверь затаился. Нет, не "типа" , а "конкретно". А сегодня пришла мысль создать искусственную дыру, точнее сразу две. Для этого взял и удалил в меню «сервис-архив котировок» из истории минутных баров периоды 7:45-11:07 вчера и с 11:50 до текущего времени. В результате применения скрипта на часовом графике были выданы сообщения о двух дырах: с 2014.12.02 08:00 по с 2014.12.02 11:00 и с 2014.12.02 12:00 по 2014.12.02 14:53. Отсюда можно сделать такой вывод: скрипт выявляет только случай ПОЛНОГО отсутствия младших баров в старшем, а в случае частичного отсутствия бессилен. Но ведь частичное отсутствие истории младших баров в старшем (дыра) по форме ничем не отличается от фактического отсутствия части этих баров, например ночью. Ниже приводится модернизированный скрипт с комментариями операторов. // скрипт выявления дыр истории test_holes.mq4 // created by Stoletov // объединяет смежные дыры // i - количество баров старшего ТФ на графике для расчета (для баров старшего ТФ с номерами свыше i история баров младшего ТФ отсутствует) // Per - период младшего ТФ // jmax - номер самого позднего бара младшего ТФ у начала бара i старшего ТФ // jmin - номер самого раннего бара младшего ТФ у конца бара i старшего ТФ // tst - дата начала расчета // hole - признак наличия дыры (если hole=true, то дыра есть) // cnt_bar - количество баров старшего ТФ подряд в дыре // t1 и t2 - время начала и конца дыры #property show_inputs extern ENUM_TIMEFRAMES Per=PERIOD_M1; // должен быть не больше, чем период бара старшего ТФ, // например если бар старшего ТФ дневной (период = 1440 мин), то допустимые значения Per=1440,240,60,30,15,5,1 void OnStart() { int jmin, jmax, i, cnt=0, cnt_bar=0; string tst, Cur=Symbol(); bool hole=false; int t1, t2; if(Per>Period()) {Alert("Младший ТФ должен быть не больше старшего ТФ, который равен ", Period(), " мин"); return;} i=iBarShift(Cur, Period(), iTime(Cur, Per,iBars(Cur,Per)-1))-1; tst=TimeToStr(Time[ i ], TIME_DATE); while(i>=0) {if (i==0) jmin=0; else {jmin=iBarShift(Cur,Per,Time[i-1]); if (iTime(Cur, Per, jmin)>=Time[i-1]) jmin++;} jmax=iBarShift(Cur,Per,Time[ i ]); if (iTime(Cur, Per, jmax)<Time[ i ]) jmax--; if(jmax<jmin) // признак дыры в истории баров младшего ТФ {if (cnt_bar==0) // если до этого дыры не было t1=iTime(Cur, Per, jmin); hole=true; cnt_bar++;} else // если признака дыры больше нет {t2=iTime(Cur, Per, jmax); cnt_bar=0;} // сбрасывается счетчик баров в дыре if(hole && cnt_bar==0) // это признак окончания дыры {if(i==0) // если дыра простирается до текущего времени t2=TimeCurrent(); Alert(Cur, " : дыра в истории на барах ", Per, " мин c ", TimeToStr(t1, TIME_DATE|TIME_MINUTES), " по ", TimeToStr(t2, TIME_DATE|TIME_MINUTES), ", текущий период= ", Period()," мин"); hole=false; cnt++;} i--;} //конец цикла while if(cnt==0) Alert(Cur, ": в истории дыр на барах ", Per, " мин нет, текущий период = ", Period(), " мин"); else Alert(Cur, ": дата начала счета ", tst,", имеется ", cnt, " дыр в истории"); return; }

Scriptong: Stoletov пишет: Я еще вчера доработал скрипт так, чтобы сообщение о каждой дыре было один раз вместо дробления на целый ряд сообщений, когда дыра охватывает подряд несколько баров старшего ТФ. Да, теперь реакция правильная. Stoletov пишет: Отсюда можно сделать такой вывод: скрипт выявляет только случай ПОЛНОГО отсутствия младших баров в старшем, а в случае частичного отсутствия бессилен. Я об этом и говорил выше. Просто для выявления реальных дыр потребуется другой критерий. По выводу немного изменю формулировку: скрипт определяет только такие дыры в истории, которые имеют искусственное происхождение, т. е. ведут к образованию рассогласования графиков (бары Н1 есть, а М1 - нет). Это прямое указание пользователю на то, что бары старшего ТФ были построены не на минутных данных, а взяты сами по себе (например, закачаны данные Н1 напрямую с сервера, без оглядки на М1).

Stoletov: Ранее я утверждал, что скрипт выявляет только случай полного отсутствия младших баров в старшем, а в случае частичного отсутствия бессилен. И был не прав. Если в скрипте заменить оператор t1=Time[ i ] на t1=iTime(Cur, Per, jmin), а оператор t2=Time[ i ] на t2=iTime(Cur, Per, jmax), то сообщения о двух дырах будут выданы с точностью до минут: с 2014.12.02 07:45 по с 2014.12.02 11:08 и с 2014.12.02 11:50 по 2014.12.02 14:53. Таким образом все-таки скрипт выявляет и случай частичного отсутствия младших баров в старшем. Эти исправления в скрипт внесены. В разделе "скрипты МТ4" под заголовком "объемы на внешнем и внутреннем барах не совпадают" говорилось о том, что сумма объемов на младших барах не всегда совпадает с объемом соответствующего им старшего бара. Похоже на то, что дыры истории и несовпадение объемов - это две стороны одной медали. При запуске скрипта из упомянутого раздела видно, что где дыра, там сумма объемов младших баров меньше объема старшего.

Scriptong: Stoletov пишет: Похоже на то, что дыры истории и несовпадение объемов - это две стороны одной медали. При запуске скрипта из упомянутого раздела видно, что где дыра, там сумма объемов младших баров меньше объема старшего. Кстати, Вы вспомнили хороший критерий выявления дыр. Ведь именно так проверяет корректность истории тестер стратегий, выдавая ошибки рассогласования. В итоге имеем достаточно простой алгоритм: 1. Взяли бар старшего ТФ. 2. Нашли все бары младшего ТФ, которые ему соответствуют, суммировав объемы баров младшего ТФ. 3. Сравнили объем бара старшего ТФ и суммарный объем баров младшего ТФ. При расхождении (причем в любую сторону) индицируется ошибка.



полная версия страницы