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

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

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

Sergey: Scriptong пишет: Чтобы не мучаться каждый раз со встраиванием индикатора во советник, я разработал единый класс CDivergence, который подключается к любой программе. Дааа! Пример явно выше моих познаний в программировании. Не думал, что все так сложно. Придется действовать по-старинке, решать проблемы по мере их поступления. Спасибо!

Scriptong: Sergey пишет: Дааа! Пример явно выше моих познаний в программировании. Не думал, что все так сложно. Придется действовать по-старинке, решать проблемы по мере их поступления. Спасибо! Индикатор дивергенций - сам по себе достаточно сложный инструмент. По этой причине это действительно сложный для понимания пример. Если есть какой-то простенький индикатор, его показания основаны на данных предыдущих баров и индикатор необходимо встроить в советник, то прикрепите его здесь. Я постараюсь показать, как это делается, чтобы желающие делать подобное самостоятельно хотя бы смогли понять сам принцип (в каком направлении думать).

Sergey: Scriptong пишет: По этой причине это действительно сложный для понимания пример. Проблема не в сложности. Раньше ты практически к каждой строчки кода писал комментарий. Я просто учил программирование на примерах. В новом МТ введено много дополнительных параметров - класс, структура и т.д. Справочник не дает развернутого понимания их возможностей применения на примерах, он скорее рассчитан на профессионалов с кратким описанием, да еще с таким, что само описание требует к нему описание. Получается, что не представляя в целом возможностей того или иного параметра и не имея описания при его применении сложно понять, что к чему.


Scriptong: Sergey пишет: Раньше ты практически к каждой строчки кода писал комментарий. Да, потому что раньше (на Адмирале) статьи писал именно для обучения других, т. е. в качестве примеров, т. к. была соответствующая договоренность с администрацией компании. Сейчас же подобных договоренностей ни с кем нет. Программы пишутся именно для использования, а не для примеров. Sergey пишет: В новом МТ введено много дополнительных параметров - класс, структура и т.д. Справочник не дает развернутого понимания их возможностей применения на примерах, он скорее рассчитан на профессионалов с кратким описанием, да еще с таким, что само описание требует к нему описание. Получается, что не представляя в целом возможностей того или иного параметра и не имея описания при его применении сложно понять, что к чему. Да, с обучением языкам MQL4 и MQL5 сейчас достаточно сложно, нет учебника, как было ранее для MQL4. Но возможности ООП в MQL точно такие же, как и в С++. Поэтому для освоения ООП достаточно прочитать соответствующие разделы в учебниках по С++. Также могу порекомендовать неплохую статью Дмитрия Федосеева. В ней он кратко описывает суть ООП. На мой взгляд, достаточно понятно.

Sergey: Scriptong пишет: Поэтому для освоения ООП достаточно прочитать соответствующие разделы в учебниках по С++. Также могу порекомендовать неплохую статью Дмитрия Федосеева. В ней он кратко описывает суть ООП. На мой взгляд, достаточно понятно. Спасибо, посмотрю.

Genry: Привет, Sergey! Я тоже задавал Игорю аналогичные вопросы здесь: http://scriptong.myqip.ru/?1-0-15-00000003-000-15-0 Жаль со временем пропадают файлы и скрины. Sergey, данный пример подойдет к описанной ситуации для решения задачи ? [pre]//+------------------------------------------------------------------+ //| VolumeRSI_v1.mq4 | //| Copyright © 2007, TrendLaboratory Ltd. | //| http://finance.groups.yahoo.com/group/TrendLaboratory | //| E-mail: igorad2003@yahoo.co.uk | //+------------------------------------------------------------------+ #property copyright "Copyright © 2007, TrendLaboratory Ltd." #property link "http://finance.groups.yahoo.com/group/TrendLaboratory" #property indicator_separate_window #property indicator_buffers 1 #property indicator_color1 LightBlue #property indicator_width1 2 #property indicator_level1 50 //---- input parameters extern int Price = 0; //Applied Price(0-Close;1-Open;2-High;3-Low;4-Median;5-Typical;6-Weighted) extern int Length = 14; // Period of evaluation extern int Smooth = 3; // Period of smoothing extern int MA_Mode = 2; // Mode of MA //---- buffers double SmRSI[]; double vRSI[]; double vBulls[]; double vBears[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- indicators IndicatorBuffers(4); SetIndexStyle(0,DRAW_LINE); SetIndexBuffer(0,SmRSI); SetIndexBuffer(1,vRSI); SetIndexBuffer(2,vBulls); SetIndexBuffer(3,vBears); //---- name for DataWindow and indicator subwindow label string short_name="VolumeRSI("+Price+","+Length+","+Smooth+","+MA_Mode+")"; IndicatorShortName(short_name); SetIndexLabel(0,"VolumeRSI"); //---- SetIndexDrawBegin(0,Length+Smooth); return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { int shift, limit, counted_bars=IndicatorCounted(); double Price1, Price2, Bulls, Bears, AvgBulls, AvgBears; //---- if ( counted_bars < 0 ) return(-1); if ( counted_bars ==0 ) limit=Bars-1; if ( counted_bars < 1 ) for(int i=1;i<Length+Smooth-1;i++) {vRSI[Bars-i]=0; SmRSI[Bars-i]=0; vBulls[Bars-i]=0; vBears[Bars-i]=0;} if(counted_bars>0) limit=Bars-counted_bars; limit--; for( shift=limit; shift>=0; shift--) { Price1 = iMA(NULL,0,1,0,0,Price,shift); Price2 = iMA(NULL,0,1,0,0,Price,shift+1); Bulls = 0.5*(MathAbs(Price1-Price2)+(Price1-Price2)); Bears = 0.5*(MathAbs(Price1-Price2)-(Price1-Price2)); if(Bulls > 0) {vBulls[shift] = Volume[shift]; vBears[shift] = 0;} else if(Bears > 0) {vBears[shift] = Volume[shift]; vBulls[shift] = 0;} else if(Bears == Bulls) {vBears[shift]=0; vBulls[shift] = 0;} } for( shift=limit; shift>=0; shift--) { AvgBulls=iMAOnArray(vBulls,0,Length,0,MA_Mode,shift); AvgBears=iMAOnArray(vBears,0,Length,0,MA_Mode,shift); if (AvgBulls+AvgBears != 0) vRSI[shift] = 1.0/(1.0+AvgBears/AvgBulls); else if (AvgBulls+AvgBears==0) vRSI[shift] = 0; } for( shift=limit; shift>=0; shift--) SmRSI[shift] = 100*iMAOnArray(vRSI,0,Smooth,0,MA_Mode,shift); //---- return(0); } //+------------------------------------------------------------------+[/pre]

Sergey: Genry пишет: Sergey, данный пример подойдет к описанной ситуации для решения задачи ? Да вполне. Цикл рассчитанный на предыдущем цикле.

Sergey: Мой мозг сейчас "взорвется"! 1. for (int j = 0; j < OrdersTotal(); j++) // Используется весь список ордеров if (OrderSelect(j, SELECT_BY_POS)) // Убедимся, что ордер выбран 2. for (int j = OrdersTotal(); j > 0; j--) // Используется весь список ордеров if (OrderSelect(j, SELECT_BY_POS)) // Убедимся, что ордер выбран В терминале два отложенных ордера. Почему в первом случае выбирается только один ордер, а во втором как положено два.

Scriptong: Sergey пишет: В терминале два отложенных ордера. Почему в первом случае выбирается только один ордер, а во втором как положено два. Немного путаете: как положено, два ордера, будет выбираться только в первом случае. Потому что, если OrdersTotal() = 2, то будет обращение к ордерам с индексами 0 и 1 (нумерация ведется с нуля). Тут все верно. А вот второй случай описан неправильно. Цикл тоже проходит две итерации (i = 2 и i = 1), но ордера с индексом 2 нет в списке рабочих. Поэтому OrderSelect возвращает false и правильно предостерегает от обращения к ордеру, который не выбран.

Sergey: Scriptong пишет: Немного путаете: как положено, два ордера, будет выбираться только в первом случае. Потому что, если OrdersTotal() = 2, то будет обращение к ордерам с индексами 0 и 1 (нумерация ведется с нуля). Тут все верно. А вот второй случай описан неправильно. Цикл тоже проходит две итерации (i = 2 и i = 1), но ордера с индексом 2 нет в списке рабочих. Поэтому OrderSelect возвращает false и правильно предостерегает от обращения к ордеру, который не выбран. В том то и проблема, что я ничего не путаю. Цикл удаления отложенных ордеров. В первом случае один ордер всегда остается в рынке, а вот во втором удаляются все. Я рассуждаю, как Вы. Вот и не могу понять , почему? Логически правильный первый вариант, а работает второй. Вот я и подумал, что возможно обращение идет не с 0, а 1 ордера. Но цикл с закрытием рыночных ордеров работает правильно именно по первому варианту.

Scriptong: Sergey пишет: Цикл удаления отложенных ордеров. Теперь понятна проблема. Если требуется удалять/закрывать ордера, то следует использовать именно обратный цикл, как во втором случае. Только он должен выглядеть следующим образом: for (int i = OrdersTotal() - 1; i >= 0; i--) Потому как при прямом переборе ордеров удаление любого ордера из середины списка приводит к изменению индексов всех остальных ордеров. Простой пример. Есть три ордера с тикетами А, В и С. Соответственно у ордера А индекс в списке ордеров 0, у В - 1, у С - 2. Если идти прямым перебором, то сначала удаляем ордер А. Сразу после его удаления ордер В получает индекс 0, ордер С - 1. Но в цикле то мы переходим ко второй итерации (i = 1), т. е. к ордеру с индексом 1. В итоге удаляем ордер С и получаем окончание цикла. Выходит, что ордер В так и не будет удален.

Sergey: Scriptong пишет: Потому как при прямом переборе ордеров удаление любого ордера из середины списка приводит к изменению индексов всех остальных ордеров. Игорь, огромное спасибо, наконец разобрался.

Sergey: Кажется я разобрался.... Проблема аналогична той, которую я описывал 03.10.2015. - взаимодействие сервера брокера и терминала. Но возможно я не прав, поэтому приведу код полностью. for (int j = 0; j < OrdersTotal(); j++) // Используется весь список ордеров if (OrderSelect(j, SELECT_BY_POS)) // Убедимся, что ордер выбран { Alert(OrderTicket()); if (OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol() // ордер должен принадлежать текущей валютной паре && OrderType()>1) if(!DeleteDeal(OrderTicket()))return; } //---- bool DeleteDeal(int ticket) { if ( OrderSelect(ticket, SELECT_BY_TICKET) && // Существует ордер с заданным.. OrderCloseTime() == 0 && // ..тикетом и ордер не закрыт ... OrderType()>1) // ордер отложенный { if (!WaitForTradeContext()) return(false); // Свободен ли торговый поток? if (!OrderDelete(OrderTicket())) // Если ордер не удалось удалить, то результат { Alert(GetLastError()); return(False); // функции - False } } return(True); // Ордер удален } //---- Ошибки удаления или занятости торгового потока не выскакивают. Я выставил 8 отложенников - удалилось только 4. Alert при отборе ордеров даже не высветил их (не удаленных) тикеты. Этот глюк появился с 600 билдом - сервер еще не обработал ордер, а терминал продолжает отработку кода, при этом не выдает ошибки . С рыночными ордерами я эту проблему решил путем зацикливания функций закрытия и проверки ордеров.

Scriptong: Sergey пишет: Проблема аналогична той, которую я описывал 03.10.2015. - взаимодействие сервера брокера и терминала. Нет. Взаимодействие здесь не при чем. Проблема лишь с нумерацией ордеров в списке. При проведении торговых операций список, конечно же, претерпевает изменения. Не стоит производить торговые операции в цикле, а по большому счету вообще не рекомендую в одном обработчике событий (OnTick, OnChartEvent, OnTimer) совершать более одной торговой операции. То есть вне зависимости от результата выполнения операции следует перемещать выполнение программы на начало обработчика события. Ведь за время выполнение торгового запроса программа "спала" (в компьютерном исчислении пара секунд - это неимоверно много), а ситуация могла кардинально измениться.

Sergey: К стати, проблему взаимодействия сервера и терминала при модернизации ордеров, описанную мной 03.10.2015 (ордер не успевал обрабатываться сервером до следующего тика) пришлось решать так... if (!OrderModify(OrderTicket(), OpPrice, SL, TP,0)) { int Error = GetLastError(); if (Error!=139 && Error!=0) { Alert("Order modification error ",OrderTicket()," = ",Error); return(false); } } Фигня какая то!



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