Наступил год пятилетнего Юбилея выхода серии статей Игоря по программированию на mql, на мой взгляд очень значимых и исключительно полезных: Как создать эксперт, не обладая навыками программирования Как создать эксперт, не обладая навыками программирования. Часть 2. Как создать эксперт, не обладая навыками программирования. Часть 3.
Сообщение: 2238
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация:
3
Отправлено: 21.02.16 10:39. Заголовок: Игорь, день добрый! ..
Игорь, день добрый!
Столкнулся с непонятной ситуацией. Встроил в template_expert вызов индикатора Quantum, разрешил открывать много позиций в одном направлении - обычно пользовался стандартным вариантом с одним входом. У измененной версии заметил одну особенность: сигналы покупок отрабатывают чаще чем сигналы продаж.
Т.е. я не ожидал от эксперта 100% обработки всех сигналов: на то есть брокер, реквоты и проскальзывания, но смещение в сторону большего количества покупок все-же заметно.
Столкнулся с непонятной ситуацией. Встроил в template_expert вызов индикатора Quantum, разрешил открывать много позиций в одном направлении - обычно пользовался стандартным вариантом с одним входом. У измененной версии заметил одну особенность: сигналы покупок отрабатывают чаще чем сигналы продаж.
Добрый день.
Вы дали ссылку на ex4-файл. А для того чтобы понять, о чем идет речь, нужен код (файл mq4).
Отправлено: 23.02.16 14:28. Заголовок: Genry пишет: У изм..
Genry пишет:
цитата:
У измененной версии заметил одну особенность: сигналы покупок отрабатывают чаще чем сигналы продаж.
При проверке текущего сигнала из кода была убрана проверка типа текущего ордера. Так делать нельзя, потому как эксперт не рассчитан на количество ордеров больше 1. В итоге при поиске своих ордеров в функции FindOrders он регистрирует только один из множества существующих ордеров, теряя все остальные. Поэтому и получается такая каша, как показана на рисунке: новый Buy открывается тогда, когда не закрыты все предыдущие Sell.
Ну а по факту проблемы (не обрабатываются сигналы от Quantum), то все просто: текущий период М5, а сигналы берутся с ТФ М1 (параметр tf равен 1).
Сообщение: 2243
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация:
3
Отправлено: 24.02.16 11:03. Заголовок: Scriptong пишет: В ..
Scriptong пишет:
цитата:
В итоге при поиске своих ордеров в функции FindOrders он регистрирует только один из множества существующих ордеров, теряя все остальные.
Я планировал замену
Scriptong пишет:
цитата:
Ну а по факту проблемы (не обрабатываются сигналы от Quantum), то все просто: текущий период М5, а сигналы берутся с ТФ М1 (параметр tf равен 1).
ЗЫ. Это было бы самое быстрое решение, но не единственная причина
Может проблема возникает при расчете StopLoss последующих ордеров в функции GetLevel ? Если StopLoss =0 она просто возвращает 0, а если > 0 то что-то не так - пока не разобрался. Я использую расчет только в ATR, смотрю на эту часть GetLevel - все вроде правильно, .... пока тупик
ЗЫ: проверил StopLoss в пунктах > 0 - такая же проблема как и c ATR - при торговле в селл открывает только один ордер, бай открывается по сигналам. И еще есть особенность, возможно одна причина: при работе этого темплейта иногда теряется SL. Т.е. первичный SL устанавливается, потом подтягивается за ценой, но в какой-то момент оказывается равным 0. Причину так-же установить не смог.
//+-------------------------------------------------------------------------------------+ double GetLevel(bool in_points, double value, int atr_period, double price, int koef) { if (value == 0) // Если исходная величина равна нулю, return(0); // ..то ноль и вернем
if (in_points) // Исходная величина задана в пунктах return(NP(price + koef*value*Point)); // Вернем уровень, который отстоит от // ..цены на value пунктов в.. // ..направлении koef return(NP(price + koef*value* // Исходная величина задана в.. iATR(NULL, 0, atr_period, 1))); // ..волатильностях. Поэтому вернем.. // ..уровень, который отстоит от цены // ..price на value волатильностей в // ..направлении koef
Получился вот такой код: https://dropmefiles.com/tJ6HZ , но опять баи открываются по всем сигналам, а селлы - только по первому.
Одна из причин кроется в коде функции FindOrders. Так, для подсчета количества ордеров заведена отдельная переменная (cnt), которая даже считает ордера. Но вот проблема - ордера записываются в ячейки с номерами, которые не имеют никакого отношения к числу ордеров эксперта. Они привязаны к индексу расположения ордера в списке рабочих ордеров (используется счетчик i). Для тестера в режиме работы без отложенных ордеров это еще будет работать. Во всех остальных случаях - нет.
Хотя основная причина в том, что используется функция ModifyDeal, которой не было в оригинальной версии Template_Expert. Видимо, функция взята из какого-то другого эксперта. Эта функция использует глобальную переменную SL. В эксперте эта переменная не инициализирована, т. е. в ней мусор, который, чаще всего (зависит от конкретного компьютера), равен 0. В итоге функция ModifyDeal для ордеров Sell не может выполниться корректно, не давая открываться второму ордеру Sell.
Также в эксперте, хоть и используется ограничение количества сделок (MaxPosAmount), нигде нет проверки на достижение этого числа. В итоге, если эксперт его достигнет, то произойдет выход за пределы массива. А это фатальная ошибка. Правда, в текущем виде кода терминал ее пропустит, т. к. используется старый MQL4. И вот тогда то мы с Вами будем долго и нудно искать ошибку.
В новом MQL4 (нужно использовать директиву #property strict) этот код даже не скомпилируется, не говоря уже о выполнении. Кстати, попробуйте запустить индикатор Quantum в этом режиме. Он тоже не будет работать.
Также в эксперте, хоть и используется ограничение количества сделок (MaxPosAmount), нигде нет проверки на достижение этого числа. В итоге, если эксперт его достигнет, то произойдет выход за пределы массива. А это фатальная ошибка. Правда, в текущем виде кода терминал ее пропустит, т. к. используется старый MQL4. И вот тогда то мы с Вами будем долго и нудно искать ошибку.
Проверка есть, она в модуле Trade:
if (cnt < MaxPosAmount) { // Если можно добавить новую позицию, if (OpenOrderCorrect(OP_BUY, GetLots(), NP(Ask), sl, tp) != 0) {
Сообщение: 2254
Зарегистрирован: 04.03.13
Откуда: Москва
Репутация:
3
Отправлено: 27.02.16 01:05. Заголовок: Scriptong пишет: В ..
Scriptong пишет:
цитата:
В новом MQL4 (нужно использовать директиву #property strict) этот код даже не скомпилируется, не говоря уже о выполнении. Кстати, попробуйте запустить индикатор Quantum в этом режиме. Он тоже не будет работать.
Спасибо, Игорь! Ну и дела Мне и в голову не приходило что и в нем есть ошибка. Я так понимаю проблема в определении размерности индекса массива бар, надо изменить строку:
Отправлено: 28.02.16 18:24. Заголовок: Genry пишет: int in..
Genry пишет:
цитата:
int intLimit = Bars - counted_bars ;
на int intLimit = Bars - counted_bars - 1;
Ага.
Интересно.
А может - 2.
Это как раз та часть, где "веселуха" начинается (я как-то на это внимание обращал). У Игоря "сквозняк" согласованности по всем функциям достаточно трудно проследить. Особенно, когда со временем работаешь это видно.
Ну а с #property strict к этому привыкли - не так сложно привести в порядок.
Отправлено: 28.02.16 21:08. Заголовок: Balbesik пишет: У И..
Balbesik пишет:
цитата:
У Игоря "сквозняк" согласованности по всем функциям достаточно трудно проследить.
Если под "сквозняком" имеется в виду использование значений глобальных переменных программы, то да - этот подход является плохим. От него я ушел с началом эры нового MQL4. Теперь во всех случаях, когда можно обойтись локальными переменными, я это делаю. Если требуется значение переменной, объявленной в другой функции, то оно явно передается в вызываемую функцию по значению или же по ссылке.
Отправлено: 28.02.16 21:04. Заголовок: Genry пишет: Я так ..
Genry пишет:
цитата:
Я так понимаю проблема в определении размерности индекса массива бар, надо изменить строку:
Этот подход при построении индикаторов является немного запутанным. По крайней мере, в моем понимании. Поэтому я один раз разработал специальную функцию и больше не вспоминаю о том, с какого бара нужно начинать расчет:
цитата:
int GetRecalcIndex(int& total, const int ratesTotal, const int prevCalculated) { total = ratesTotal - 1;
if (i_indBarsCount > 0 && i_indBarsCount < total) total = MathMin(i_indBarsCount, total);
Далее во всех функциях оперирую значениями текущего обрабатываемого бара (он имеет индекс от 0 до GetRecalcIndex) и доступным количеством баров (total). Единственное изменение, которое вношу в тело функции GetRecalcIndex - это отступ от левого края истории. Например, если нужно рассчитывать данные индикатора с каким-либо периодом, то в строку:
Все даты в формате GMT
2 час. Хитов сегодня: 0
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет