Просто нажмите паузу, добавьте нужный индикатор на график и нажмите продолжение тестирования.
Ура! Проблема с отрисовкой сигнала решена, все сигналы отрисовались. Видимо, проблема была в том, что я расчитывал индикатор для каждого тика, помимо последнего бара, но из-за недостатка опыта делаю это некорректно. Оставил расчёт только по сформированному бару и всё получилось. (Но вопрос по поводу отрисовки индикатора тестер-движком в конце тестирования остаётся и адресован он к разработчикам. Мне интересно, задумывалось это так или всё же есть bag-очик)
Candid и Rosh, большое спасибо за подсказку с визуализатором, теперь буду этим пользоваться. (а в доке про это ни слова).
Такое впечатление что IndicatorCounted() является одним из самых серьёзных камней преткновения для начинающих. Да и не только для начинающих. Не планируется ли для МТ5 поискать какую-нибудь альтернативу этой функции? Тогда у меня есть предложение для рассмотрения.
Сначала предисловие. В очередной раз споткнувшись (интуитивно исходил из того, что бары считаются на момент предыдущего вызова функции) я решил для определённого типа индикаторов отказаться от неё совсем. Сейчас я проверяю такого типа конструкцию
int start() {
// Работаем только при изменении числа баров
if (Bars == preBars) return(0);
// Число баров должно превышать MinBars-1
if (Bars < MinBars) return(0);
// Если число баров увеличилось на 1 и время предпоследнего "правильное"
// обсчитываем закончившийся бар
if (Bars-preBars == 1 && BarTime==Time[1]) FBar = 1;
// Во всех остальных случаях пересчитываем всю историю
// В функции Initialize() уничтожим созданные объекты,
// присвоим начальные значения нужным переменным
// и вернём для FBar значение MinBars
else FBar=Initialize();
// Модифицируем контрольные переменные
preBars = Bars;
BarTime=Time[0];
for (pos=FBar;pos>0;pos--) {
...
Условие пересчёта истории на каждый "чих" (как выразился Slawa) специфично для этого типа индикаторов - используются и меняются значения индикатора из прошлого, пользоваться для привязки временем (то есть постоянно обращаться к iBarShift) мне кажется накладным, думаю дешевле пользоватся для привязки номером бара от начала графика (Bars-pos) и полностью пересчитывать индикатор при "нештатном" изменении Bars (например при докачке истории).
И вот я подумал - а ведь такого типа код (с вариантами для работы на каждом тике и, может быть, для пересчёта при докачке только новых баров) может быть просто зашит в функцию start. Это и есть предложение для рассмотрения. Тогда она должна иметь параметры, например start(bool EveryTick, int& FBar, int MinBars, ...) и необходима дополнительная стандартная функция Initialize, дополнительно к init. Почему дополнительно? Нет смысла заново делать много из того, что делается в init (устанавливать буферы, параметры отображения, устанавливать размеры пользовательских массивов если это делается один раз и пр.). С другой стороны в момент работы Initialize хотелось бы иметь установленными значения предопределённых переменных, типа Bars или Point. Вот собственно на данный момент и всё. Может быть в такой идеологии пользователям будет легче писать правильные индикаторы?
На самом деле, Ваш preBars очень сильно напоминает наш IndiicatorCounted. Не хватает проверки на символ и период (а вдруг они сменились?). И условие ""Работаем только при изменение числа баров" - слишком жёсткое.
На самом деле, Ваш preBars очень сильно напоминает наш IndiicatorCounted.
Я понимаю, что изобретаю велосипед :). Код приведен для илюстрации "естественности" объединения IndicatorCounted() с функцией start() (ну и немножко в расчёте на то что мне укажут на грубые просчёты, если они там есть :). Вопрос в том, с каким интерфейсом легче писать правильные индикаторы: с существующим (IndicatorCounted) или гипотетическим (start(bool EveryTick, int& FBar, int MinBars, ...))
Понятие "легче" разнится от контекста. Для чайника в программировании "легче" - это что-то вроде конструктора с крупнопанельной сборкой. Что-то вроед написания программ с помощью визардов. Профессиональный программист от такой "игрушки" только поморщится и начнет стебаться.
Профессионалам требуется как можно больший контроль с как можно меньшими опциями, чтобы он сам делал то, что ему требуется. Поэтому вряд ли функция с start() с навешанным тюнингом будет востребована.
Поэтому вряд ли функция с start() с навешанным тюнингом будет востребована.
С тюнингом проблемы нет, пусть start(NULL) выводит на прежнюю версию. О предпочтениях пользовательских масс судить не берусь.
P.S. Тем не менее не удивлюсь, если от IndicatorCounted морщатся все, и профессионалы и чайники :)
Поэтому вряд ли функция с start() с навешанным тюнингом будет востребована.
С тюнингом проблемы нет, пусть start(NULL) выводит на прежнюю версию. О предпочтениях пользовательских масс судить не берусь.
P.S. Тем не менее не удивлюсь, если от IndicatorCounted морщатся все, и профессионалы и чайники :)
Так и есть. Для оптимизации вычислений. Чтобы не пересчитывать всю историю, а только несколько баров в конце.
Информация о количестве уже посчитанных баров используется во всех наших встроенных индикаторах. И считается стандартным для всех индикаторов способом. Функция IndicatorCounted просто отдаёт эту уже посчитанную информацию, чтобы индикаторописатели тоже могли вкусить от благ.
Не нравится - не пользуйтесь. Учитывайте самостоятельно.
Для авторизации и пользования сайтом MQL5.com необходимо разрешить использование файлов Сookie.
Пожалуйста, включите в вашем браузере данную настройку, иначе вы не сможете авторизоваться.
Вы вошли в аккаунт. Двухфакторная аутентификация отключена. Настройте её заново и отсканируйте новый QR-код или продолжите с отключённой двухфакторной аутентификацией.
Ура! Проблема с отрисовкой сигнала решена, все сигналы отрисовались. Видимо, проблема была в том, что я расчитывал индикатор для каждого тика, помимо последнего бара, но из-за недостатка опыта делаю это некорректно. Оставил расчёт только по сформированному бару и всё получилось.
(Но вопрос по поводу отрисовки индикатора тестер-движком в конце тестирования остаётся и адресован он к разработчикам. Мне интересно, задумывалось это так или всё же есть bag-очик)
Candid и Rosh, большое спасибо за подсказку с визуализатором, теперь буду этим пользоваться. (а в доке про это ни слова).
Сначала предисловие. В очередной раз споткнувшись (интуитивно исходил из того, что бары считаются на момент предыдущего вызова функции) я решил для определённого типа индикаторов отказаться от неё совсем. Сейчас я проверяю такого типа конструкцию
int start() { // Работаем только при изменении числа баров if (Bars == preBars) return(0); // Число баров должно превышать MinBars-1 if (Bars < MinBars) return(0); // Если число баров увеличилось на 1 и время предпоследнего "правильное" // обсчитываем закончившийся бар if (Bars-preBars == 1 && BarTime==Time[1]) FBar = 1; // Во всех остальных случаях пересчитываем всю историю // В функции Initialize() уничтожим созданные объекты, // присвоим начальные значения нужным переменным // и вернём для FBar значение MinBars else FBar=Initialize(); // Модифицируем контрольные переменные preBars = Bars; BarTime=Time[0]; for (pos=FBar;pos>0;pos--) { ...Условие пересчёта истории на каждый "чих" (как выразился Slawa) специфично для этого типа индикаторов - используются и меняются значения индикатора из прошлого, пользоваться для привязки временем (то есть постоянно обращаться к iBarShift) мне кажется накладным, думаю дешевле пользоватся для привязки номером бара от начала графика (Bars-pos) и полностью пересчитывать индикатор при "нештатном" изменении Bars (например при докачке истории).
И вот я подумал - а ведь такого типа код (с вариантами для работы на каждом тике и, может быть, для пересчёта при докачке только новых баров) может быть просто зашит в функцию start. Это и есть предложение для рассмотрения. Тогда она должна иметь параметры, например start(bool EveryTick, int& FBar, int MinBars, ...) и необходима дополнительная стандартная функция Initialize, дополнительно к init. Почему дополнительно? Нет смысла заново делать много из того, что делается в init (устанавливать буферы, параметры отображения, устанавливать размеры пользовательских массивов если это делается один раз и пр.). С другой стороны в момент работы Initialize хотелось бы иметь установленными значения предопределённых переменных, типа Bars или Point. Вот собственно на данный момент и всё. Может быть в такой идеологии пользователям будет легче писать правильные индикаторы?
Аналогичный код у нас был в наших троечных пользовательских индикаторах.
Я понимаю, что изобретаю велосипед :). Код приведен для илюстрации "естественности" объединения IndicatorCounted() с функцией start() (ну и немножко в расчёте на то что мне укажут на грубые просчёты, если они там есть :). Вопрос в том, с каким интерфейсом легче писать правильные индикаторы: с существующим (IndicatorCounted) или гипотетическим (start(bool EveryTick, int& FBar, int MinBars, ...))
Профессионалам требуется как можно больший контроль с как можно меньшими опциями, чтобы он сам делал то, что ему требуется. Поэтому вряд ли функция с start() с навешанным тюнингом будет востребована.
С тюнингом проблемы нет, пусть start(NULL) выводит на прежнюю версию. О предпочтениях пользовательских масс судить не берусь.
P.S. Тем не менее не удивлюсь, если от IndicatorCounted морщатся все, и профессионалы и чайники :)
С тюнингом проблемы нет, пусть start(NULL) выводит на прежнюю версию. О предпочтениях пользовательских масс судить не берусь.
P.S. Тем не менее не удивлюсь, если от IndicatorCounted морщатся все, и профессионалы и чайники :)
Таки да
Как-то переусложнено.
по-моему слабый аргумент.
Как-то переусложнено.
по-моему слабый аргумент.
Предложите свой изящный и 100%-ный способ добиться экономного и стабильного расчета индикаторов.
Информация о количестве уже посчитанных баров используется во всех наших встроенных индикаторах. И считается стандартным для всех индикаторов способом. Функция IndicatorCounted просто отдаёт эту уже посчитанную информацию, чтобы индикаторописатели тоже могли вкусить от благ.
Не нравится - не пользуйтесь. Учитывайте самостоятельно.