Форум » Консультации по программированию » Я в шоке! Подскажите. » Ответить

Я в шоке! Подскажите.

Sergey: Всем привет! Я в шоке! Выпал из рынка на 3,5 месяца, а тут такие перемены. Игорь подскажи, где можно ознакомиться с изменениями в MQL4? Хотел перенести все данные на новый комп, но некоторые индикаторы после компиляции перестают работать. Вот один из них. http://gfile.ru/a8cCP Хотя не перекомпилированные файлы работают. Компиляция ошибок в коде не выявляет. Но при отладке выдается ошибка формирования массива стр.67. Но в чем ошибка не пойму. Буду благодарен, если найдешь время исправить.

Ответов - 204, стр: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 All

Genry: Sergey пишет: Всем привет! Я в шоке! Выпал из рынка на 3,5 месяца, а тут такие перемены. Привет, Сергей! С возвращением ! У Игоря была статья про возможности обновленного MQL, но видимо надо его попросить обновить две базовые статьи: "Как создать советник, не обладая навыками программирования", "Как создать индикатор, не обладая навыками программирования", и шаблоны к ним.

Sergey: Genry пишет: Привет, Сергей! С возвращением Спасибо Genry! Неотложных дел еще на месяц. Затем буду включаться в работу.

Genry: Sergey пишет: Всем привет! Я в шоке! Выпал из рынка на 3,5 месяца, а тут такие перемены. Игорь подскажи, где можно ознакомиться с изменениями в MQL4? Хотел перенести все данные на новый комп, но некоторые индикаторы после компиляции перестают работать. ... Хотя не перекомпилированные файлы работают. Компиляция ошибок в коде не выявляет. Но при отладке выдается ошибка формирования массива стр.67. Но в чем ошибка не пойму. Буду благодарен, если найдешь время исправить. Статья на MQL4 по теме. В статье рассмотрены возможные ошибки, возникающие при компиляции старых программ и методы их устранения. Может что пригодится. 1.Ошибки компиляции ◾1.1. Идентификатор совпадает с зарезервированным словом ◾1.2. Специальные символы в наименованиях переменных и функций ◾1.3. Ошибки использования оператора switch ◾1.4. Возвращаемые значения у функций ◾1.5. Массивы в аргументах функций 2.Ошибки времени выполнения ◾2.1. Выход за пределы массива (Array out of range) ◾2.2. Деление на ноль (Zero divide) ◾2.3. Использование 0 вместо NULL для текущего символа ◾2.4. Строки в формате Unicodе и их использование в DLL ◾2.5. Совместное использование файлов ◾2.6. Особенность преобразования datetime 3.Предупреждения компилятора ◾3.1. Пересечения имен глобальных и локальных переменных ◾3.2. Несоответствие типов ◾3.3. Неиспользуемые переменные


Scriptong: Исправленный индикатор - здесь. Ошибки: 1. Выход за пределы массивов при расчете начального бара (переменная limit). В момент начала работы индикатора выражение limit = Bars - counted_bars; указывает на бар с индексом Bars, которого не существует. Bars - это общее количество баров на графике, которое индексируется с нуля. Поэтому последний бар графика будет иметь индекс Bars - 1. Чтобы подобное не происходило, нужно начинать обработку баров с того бара, для которого будет произведен корректный расчет всех значений индиктаора. В общем случае можно поступить так: limit = (int)MathMin(Bars - counted_bars, Bars - 1); Но в данном случае это тоже неправильно, т. к. необходимо обеспечить расчет средней скользящей с периодом Periods. То есть от конца графика нужно отодвинуться еще на Periods баров: limit = (int)MathMin(Bars - counted_bars, Bars - Periods - 1); 2. Связывание индикаторных буферов с индексами произведено неправильно: if( !SetIndexBuffer(0,e7) && !SetIndexBuffer(1,e2) && !SetIndexBuffer(2,e3) && !SetIndexBuffer(3,e4) && !SetIndexBuffer(4,e5) && !SetIndexBuffer(5,e6) && !SetIndexBuffer(6,e1) ) В новом MQL4 логические выражения обрабатываются по укороченному сценарию. Это означает, что если после вычисления первой части выражения результат всего выражения уже не изменится, то вторая и последующая части не вычисляются. В данном случае при успешном связывании первого буфера становится ясно, что выражение будет иметь результат false. Потому последующие буфера не связываются. Правильно делать так: if( !SetIndexBuffer(0,e7) || !SetIndexBuffer(1,e2) || !SetIndexBuffer(2,e3) || !SetIndexBuffer(3,e4) || !SetIndexBuffer(4,e5) || !SetIndexBuffer(5,e6) || !SetIndexBuffer(6,e1) ) В этом случае результат будет true как только появится первая ошибка связывания. Связывание остальных буферов уже не потребуется, т. к. индикатор и так не должен работать.

Sergey: Scriptong пишет: Исправленный индикатор Игорь, огромное спасибо! Как всегда исчерпывающий ответ.... Выход за пределы массивов при расчете начального бара я исправил, согласно новым функциям и правилам расчета индикаторов. И все равно не мог понять, почему индикатор не отображается. Оказалось проблема не только в этом. Разбор ошибок самый эффективный способ обучения... Очень благодарен за такую ветку. Удачи!

Sergey: В папке Include файл MovingAverages.mqh Функция double ExponentialMA(const int position,const int period,const double prev_value,const double &price[]) Что обозначает параметр prev_value? И каково предназначение символа & ( &price[])?

Scriptong: Sergey пишет: Что обозначает параметр prev_value? Это предыдущее значение экспоненциального среднего. Расчет значения текущего экспоненциального среднего производится на основе предыдущего значения. Подразумевается, что отсутствие предыдущего значения допускается только для самого первого расчета в истории. Для всех последующих значений предыдущие значения уже будут. Sergey пишет: И каково предназначение символа & ( &price[])? В MQL4/5 символ "&", поставленный в объявлении переменной перед ее именем, означает ссылку на переменную. Ссылка в большинстве случаев дает возможность изменять значение переменной внутри локальной функции так, что измененное значение будет доступно после окончания выполнения этой локальной функции. Вот простой пример. В одной функции объявляются переменные a и b, но их значения меняются в другой функции, в которой они не объявлены, а переданы по ссылке: void SwapVars(int &a, int &b) { int c = a; a = b; b = c; } void OnTick() { int a = 5; int b = 10; Print("До изменения: a = ", a, ", b = ", b); SwapVars(a, b); Print("После изменения: a = ", a, ", b = ", b); } В случае с функцией ExponentialMA ссылка имеет другое назначение. Перед типом данных установлен спецификатор const, который указывает на тот факт, что переменная, передаваемая по ссылке, не может быть изменена. Возникает логичный вопрос - а зачем тогда ссылка? Здесь она нужна по той причине, что в функцию требуется передать не одно значение, а целый массив. Если передавать массив по значению, то чем большее количество элементов в массиве, тем дольше он будет передаваться в функцию. Ссылка же дает возможность не передавать все значения массива, а просто указать место в памяти, где все эти значения лежат. При этом передающая функция "может быть спокойна за целостность данных", т. к. функция ExponentialMA не имеет право изменять данные массива price.

Sergey: Всегда имел проблемы с графикой. Вот код: ShowTypeBars(g_typebar, Volume|i|, Time|i|, clrText); //+-------------------------------------------------------------------------------------+ //| Отображение надписи типа сигнала | //+-------------------------------------------------------------------------------------+ void ShowTypeBars(string j_typebar, int j_volume, datetime j_time, color clr) { string name = PREFIX + j_time; ObjectDelete("name"); ObjectCreate(name, OBJ_TEXT, WindowFind(short_name), j_time, j_volume); ObjectSetText(name, j_typebar, 8, "Arial Black", clr); } //================================================= Не могу понять, почему после установки индикатора на нулевом баре не обновляется координата j_volume, хотя текущая гистограмма объема отображается верно.

Scriptong: Sergey пишет: Не могу понять, почему после установки индикатора на нулевом баре не обновляется координата j_volume, хотя текущая гистограмма объема отображается верно. Если руководствоваться только приведенным участком кода, то можно говорить только об одной ошибке. Вместо: ObjectDelete("name"); нужно написать: ObjectDelete(name); Ведь name - это имя переменной, а в коде оно используется как имя объекта. То есть удаляется объект с названием name, а создается потом совершенно другой объект с названием, которое находится в переменной name. При обновлении данных графических объектов лучше использовать не удаление/создание, а создание/модификацию: string name = PREFIX + ...; if (ObjectFind(name) < 0) // объекта нет - можно создавать { ObjectCreate(..); // назначение свойств объекта } else { // модификация объекта - те свойства, которые нужно изменить }

Sergey: Огромное спасибо! Первоначальный вариант бал такой, однако он так же не работал из-за ошибки в названии. void ShowTypeBars(string j_typebar, int j_volume, datetime j_time, color clr) { string name = PREFIX + j_time; ObjectDelete("name"); if (ObjectFind(name) < 0) { ObjectCreate(name, OBJ_TEXT, WindowFind(short_name), j_time, j_volume); ObjectSetText(name, j_typebar, 8, "Arial Black", clr); // текст объекта return; } ObjectMove(name, WindowFind(short_name), j_time, j_volume); ObjectSet(name, OBJ_TEXT, j_typebar); ObjectSet(name, OBJPROP_COLOR, clr); } Вернулся к нему, так как он работает более корректно при смене ТФ.

Scriptong: Да, именно о таком варианте я и говорил... Только не забудьте в нем убрать кавычки вокруг name.

Husanboy: Scriptong пишет: Добрый день уважаемый Игорь! Пожалуйста помогите с кодом?! Надо написать простой советник по этим индикатор(вложил ссылки ниже). Я сам попробовал, но не получилось. Почему то не возможно получить сигнал от буфер индикатора. Есть какой то способ получить сигнал от него? Условии: BUY когда линия индикатора више "0" и SELL когда линия индикатора ниже "0". Очень прощу от вас, пожалуйста помогите?! Жду ваше ответы. http://qclk.ru/kx/iWuC http://qclk.ru/kN/OGO51

Scriptong: Husanboy пишет: Есть какой то способ получить сигнал от него? Да. Причем способ очень простой, т. к. обращение к индикатору вовсе не требуется. Его код, отвечающий за расчет значения, умещается в одну строку. Итак, что нужно сделать: 1. Скопировать в код советника из кода индикатора все настроечные параметры индикатора и тело функции priceSwitch. 2. Получить значения индикатора на двух последних барах: double lastValue = priceSwitch(1) - iMA(NULL, NULL, DPOPeriod, MaShift, MaType, PriceType, 1); double preLastSwitch = priceSwitch(2) - iMA(NULL, NULL, DPOPeriod, MaShift, MaType, PriceType, 2); 3. Написать условие для сигнала Buy: if (lastValue > 0 && preLastValue < 0) { // Открыть Buy } 4. Написать условие для сигнала Sell: if (lastValue < 0 && preLastValue > 0) { // Открыть Sell } Советник готов.

Husanboy: Scriptong пишет: Классно!!! Все получилось. Вы самый лучший MQL программист в мире. Спасибо за помощь! Еще раз скажу Вы самый лучший! Спасибо бесконечно!!!!

Scriptong: Пожалуйста. Обращайтесь.



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