Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Советник и индикатор на чарте исполняются в разных параллельных потоках.
От момента физического старта индикатора и до реализации IndicatorSetString(INDICATOR_SHORTAME) проходит время, за которое советник вполне может запросить и получить прежнее имя. А прежнее имя это имя заданное в property и/или сохранённое в шаблонах. Кстати не уверен что изменённое shortname сохраняется в шаблоне, смотреть/проверять традиционно лень :-)
Оставляя индикатор "висеть" (а-ля смена ТФ и всё равно его по новой грузить) вы нарушаете RAII https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization и отсюда весь цирк с конями. Всё созданное в OnInit должно удаляться в OnDeinit, это поведение ожидаемое терминалом от прикладных индикаторов/советников. Не надо бежать впереди паровоза и самому пытаться вместо верхнего уровня (терминала) кешировать объекты.
Но я сейчас говорю про OnInit() советника со строкой:
// делаем вручную, потому что ChartIndicatorName(0, ind_subwindow, 0); может не успеть сработать в OnTick (см.ниже) ind_shortname = IDKey + "_Custom_" + EnumToString(_Period);и OnTick() советника с кодом:
которые живут в одном потоке.
Не может же OnTick() выполниться перед OnInit()? Тогда каким образом может быть выполнено условие
если переменная уже была проинициализирована вот так:
Но я сейчас говорю про OnInit() советника со строкой:
и OnTick() советника с кодом:
которые живут в одном потоке.
Не может же OnTick() выполниться перед OnInit()? Тогда каким образом может быть выполнено условие
если переменная уже была проинициализирована вот так:
после смены ТФ, индикатор получается живёт в отдельном потоке. вопрос - какое shortname он имеет прямо в момент OnInit? то которое прописано в property, которое прописалось в шаблоне или какое установлено в прежней жизни IndicatorSetString(INDICATOR_SHORTNAME) ??
и которое из этих имён, может выловить советник (который напомню - в отдельном независимом потоке)
это классические гонки, кто вперёд того и тапки. Поэтому на медленном VPS или быстрой смене ТФ на супер-компе результаты разительно отличаются
PS/ кстати, а зачем вы в shortname пихаете _Period ? вы-же намереваетесь менять тайм-фрейм чарта. На каждый период по индикатору по задумке ?Благодарю за развернутый ответ и за исправления в индикаторе))! У меня проблема продолжает присутствовать, но проверял на графике, который работает от специальной сервисной утилиты, завтра рынок откроется и еще сравню на форексной демке metaquost. Я не могу понять каким образом в вашем первом логе появилась "Got shortname madebyea_Custom_PERIOD_H1", если в oninit советника ind_shortname формируется вручную, т.е. он заведомо не NULL и условие в OnTick() не должно выполняться.
Вопрос не совсем понятен, потому что "Got shortname madebyea_Custom_PERIOD_H1" там в любом случае правильный, вне зависимости от OnInit.
Но есть другой нюанс, связанный с тем, что исходники менялись в ходе тестов (я выложил только последнюю версию). Там в комментах внутри исходника помечены две строки, в которых во время первой сессии была немного другая логика - имя индикатора получалось из функции ChartIndicatorName во время первого тика, но приход тика мог не произойти до переключения ТФ и тогда имя оставалось равным NULL. Поэтому пришлось перенести в OnInit создание имени по аналогии с тем, что делается внутри индикатора. Это затычка. Оставил обе ветки кода, чтобы было видно как надо бы делать правильно (но не получается из-за терминала) и как делать некрасиво (но приходится, чтобы вообще появился шанс разобраться в баге).
PS/ кстати, а зачем вы в shortname пихаете _Period ? вы-же намереваетесь менять тайм-фрейм чарта. На каждый период по индикатору по задумке ?
Без этого как раз было бы не понять, что происходит. Очень качественный исходник для отладки.
Очевидно, терминал под каждый период создает отдельный экземпляр индикатора.
Без этого как раз было бы не понять, что происходит. Очень качественный исходник для отладки.
Очевидно, терминал под каждый период создает отдельный экземпляр индикатора.
тогда получается что на каждый период создаёте индикатор. Сами. Очень качественный исходник :-)
решение проблемы на виду, не надо заниматься овер-инжинирингом. При раскрутке советника придумал индикатору имя, создал+приаттачил, в OnDeinit отцепил от чарта по уникальному имени и удалил хендл. ВСЁ. По классике: "я тебя породил, я тебя и убью"
а вы начали мудрить с "не удалять при смене ТФ" и городить код. При "неудалении" индикатор сохраняется во внутренний шаблон и перезагражается по нему уже в чарте (отличительная особенность - начинает получать OnChartEvent). Причём перезагрузка происходит параллельно с перезагрузкой советника и чей OnInit на какой стадии впереди кому как повезёт.
PS/ там есть другие вопросы без ответов - что происходит при изменении пользователем параметров приаттаченого к чарту индикатора. Старый сгинет и будет новый с новыми параметрами или поменяются опции работающего с советником, или это неопределённое поведение от билда-к-билду
во время первой сессии была немного другая логика - имя индикатора получалось из функции ChartIndicatorName во время первого тика, но приход тика мог не произойти до переключения ТФ и тогда имя оставалось равным NULL
тогда получается что на каждый период создаёте индикатор. Сами. Очень качественный исходник :-)
решение проблемы на виду, не надо заниматься овер-инжинирингом. При раскрутке советника придумал индикатору имя, создал+приаттачил, в OnDeinit отцепил от чарта по уникальному имени и удалил хендл. ВСЁ. По классике: "я тебя породил, я тебя и убью"
Мне нужно, чтобы индикаторы работали на том ТФ, на котором работает советник в данный момент. Мне НЕ нужно, чтобы было несколько индикаторов под разные ТФ.
Но проблема именно в том, что остаются работать индикаторы для прошлых ТФ, и чтобы это отловить, индикатор и принтует _Period, в результате советник
переключен на H2, а в логе принтуются M30, H1 и H2 (например) или две копии на H2, вместо одного. Это то с чем я борюсь, а не то чего я добиваюсь!
Если не сложно, можете показать свою идею, доработав файлы из этого сообщения?
Это будет понятнее для всех.
В этом тестовом примере заложен всего 1 тестовый индикатор, а когда в советнике их много разных и тяжелых, то проблема усугубляется.
Советник и индикатор на чарте исполняются в разных параллельных потоках.
От момента физического старта индикатора и до реализации IndicatorSetString(INDICATOR_SHORTAME) проходит время, за которое советник вполне может запросить и получить прежнее имя. А прежнее имя это имя заданное в property и/или сохранённое в шаблонах. Кстати не уверен что изменённое shortname сохраняется в шаблоне, смотреть/проверять традиционно лень :-)
Оставляя индикатор "висеть" (а-ля смена ТФ и всё равно его по новой грузить) вы нарушаете RAII https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization и отсюда весь цирк с конями. Всё созданное в OnInit должно удаляться в OnDeinit, это поведение ожидаемое терминалом от прикладных индикаторов/советников. Не надо бежать впереди паровоза и самому пытаться вместо верхнего уровня (терминала) кешировать объекты.
править не буду, но бегло посмотрел
в вашем коде ошибка:
если не главное окно (0) то ind_subwindow может быть (и наверняка будет) другим. Перед удалением текущее окно индикатора ещё надо найти ;-) и в справке это есть
про синхронность/асинхронность ChartIndicatorDelete ничего не сказано, подозреваю что она асинхронна, то есть просто выставляет ему признак isStopped или посылает в очередь сообщение "удалить индикатор".
Если асинхронна, то сразу после ChartIndicatorDelete в переборах вполне может быть обнаружен "призрак" индикатора - он как-бы есть по опросу, но как кот шредингера ни жив ни мёртв. Сейчас опыты ставить нет настроения
В этом тестовом примере заложен всего
ещё отличия вашего кода от моего: у меня в OnInit,OnDeinit советника в конце присутствует ChartRedraw(),
и хендлы созданных и приаттаченных индикаторов я освобождаю через IndicatorRelease. Последнее возможно и лишнее, но у меня работает, у вас подглючивает
править не буду, но бегло посмотрел
в вашем коде ошибка:
если не главное окно (0) то ind_subwindow может быть (и наверняка будет) другим. Перед удалением текущее окно индикатора ещё надо найти ;-) и в справке это есть
про синхронность/асинхронность ChartIndicatorDelete ничего не сказано, подозреваю что она асинхронна, то есть просто выставляет ему признак isStopped или посылает в очередь сообщение "удалить индикатор".
Если асинхронна, то сразу после ChartIndicatorDelete в переборах вполне может быть обнаружен "призрак" индикатора - он как-бы есть по опросу, но как кот шредингера ни жив ни мёртв. Сейчас опыты ставить нет настроения
А вот если бы поправили, то смогли бы скомпилировать, запустить и проверить как работает ; )
ind_subwindow определяется заранее при добавлении индикатора на график в OnInit(). Это вариант Станислава.
Там ниже есть вызов моей первоначальной функции
, которая перебирает все индикаторы на всех окнах, а удалить не удаляет потому, что после смены ТФ shortname индикатора обнуляется раньше, и ChartIndicatorName() получает shortname уже без ID, переданного в индикатор при его создании. Понимаете, во время работы советника индикатор имел shortname вида madebyea_Custom_PERIOD_H2:
, где madebyea - "Made By Ea" - тот самый, переданный в индикатор признак советника, а после смены ТФ, мы имеем shortname в виде имени файла индикатора (Indicator_01__1):
Вот в ЭТОМ и проблема удаления индикатора, если в OnDeinit() советника нужно удалять не все подряд индикаторы, а найти и удалить только те, что созданы советником.