Индикатор не рисуется, хотя, наверное, должен. Может, кто подскажет почему и как исправить? Голову сломал уже. Зигзаг можно любой вставить. Спасибо!
- Ошибка в коде. Кто исправит, тот молодец!
- Обсуждение статьи "Инструмент «Ценовая гистограмма» (Рыночный профиль) и его реализация на MQL5"
- Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам
в таких случаях требуется
1. изложить требуюмую логику индикатора
2. приложить используемый сабиндикатор
3. желательно при обучении комментировать свой код
посмотрел твой код, внутри комментарии
1. изложить требуюмую логику индикатора
2. приложить используемый сабиндикатор
3. желательно при обучении комментировать свой код
посмотрел твой код, внутри комментарии
//+------------------------------------------------------------------+ //| Idalgo.mq4 | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property indicator_separate_window #property indicator_buffers 1 #property indicator_color1 Red //---- input parameters //---- buffers double Buffer1[]; //при написании кода нужно стараться давать имена которые будут тебе говорить о функциональной нагрузке //---- //+------------------------------------------------------------------+ //| Init | //+------------------------------------------------------------------+ int init() { IndicatorBuffers(1); //---- indicators string short_name; IndicatorShortName(short_name); SetIndexStyle(0,DRAW_LINE,EMPTY,2); SetIndexBuffer(0,Buffer1); //---- return(0); } //+------------------------------------------------------------------+ //| Start Function | //+------------------------------------------------------------------+ int start() { int counted_bars=IndicatorCounted(); //---- check for possible errors if(counted_bars<0) { return(-1); } //---- last counted bar will be recounted if(counted_bars>0) counted_bars--; //---- do it for (int j=0;j>=5000;j++) { //int Bar1=ZZBar("",0,j+1,3000,12); //int Bar2=ZZBar("",0,j+2,3000,12); //изменились входные параметры функции, меняем код int Bar1=ZZBar(j+1,3000,12); int Bar2=ZZBar(j+2,3000,12); Buffer1[j]=Close[Bar2]-Close[Bar1]; } //---- return(0); } //+----------------------------------------------------------------------------+ //| Возвращает номер бара экстремума ЗигЗага по его номеру. | //| Параметры: | //| sym - наименование инструмента ("" - текущий символ) | //| tf - таймфрейм ( 0 - текущий ТФ) | //| ne - номер экстремума ( 0 - текущий) | //| dp - ExtDepth | //| dv - ExtDeviation | //| bc - ExtBackstep | //+----------------------------------------------------------------------------+ //при написании собственных функций в объявлении лучше просто перечислить //входные переменные и их типы, а присвоение делать уже внутри функции //потому заменил твою строчку //int ZZBar(string sym="", int tf=0, int ne=1, int dp=600, int dv=12) //для чего объявлять входную переменную sym, если она никак и нигде не меняется? //то же самое по т.ф. int ZZBar(int ne, int dp, int dv) { //if (sym=="") sym=Symbol(); double zz; //зачем грузить код лишними вызовами "тяжелых" функций? k нигде не меняется, //поэтому заменил твой код //int i, k=iBars(NULL, 0), ke=0; int i,ke=0; //здесь присваиваю значения переменным (хотя они у тебя статичные, и можно было указать //их значение непосредственно при вызове iCustom dp=600; dv=12; ne=1; //обязательно комментируй свой код, потому что //1. будешь видеть четкий пошаговый алгоритм кода //2. легко даже по прошествии времени сможешь разобраться, чего же делает твой код //3. это признак профессионального подхода, т.к. и другим людям позволит понять логику твоего кода //в цикле ты задаешь начало просчета с бара с индексом 1, т.е. на каком бы участке ты бы не хотел //посчитать какие-либо данные всегда будешь просчитывать с бара имеющего индекс 1 (из всего множества //что есть на графике, т.е. непонятно зачем тебе нужно пробегать в функции старт по всем 5000 барам //если тебя интересуют только крайне правые две вершины от индекса 1 до индекса Bars-1 for (i=1; i<Bars; i++) { //будем надеяться что твой ZigZag_new_1, это аналог стандартного и использует именно 0 буфер, //и количество входных данных (внешних) у него равно 2, и заданы они корректно zz=iCustom(NULL,0,"ZigZag_new_1",dp,dv,0,i); //т.к. в буферах содержится информация типа double, то твое сравнение некорректно //на форуме это обсуждалось мягко говоря "туева хуча" раз, я вписал свою функцию, которую пользую, //с точностью до Digits знаков, видимо твой зигзаг может иметь значение и меньше нуля //а сравнение только на неравенство, но можно посмотреть и стандартную библиотеку там тоже есть //функция на равенство вещественных чисел //if (zz!=0 ) if( !CompareDoubles_m(zz,0,Digits) ) { //если есть отрисовка ЗЗ на графике ты увеличиваешь счетчик ke++; //когда счетчик больше 1, т.е. 2 отрисовки происходит выход из цикла if (ke>ne) //здесь ты просто фиксируешь и возвращаешь индекс бара от 1 до того места где у тебя обнаружена второй //экстримум на зигзаге, как я уже и говорил это будет всегда одна и та же точка return(i); } } //видимо ты хотел чтобы ne у тебя была переменной?, тогда не нужно присваивать значение 1 //и тогда не понятно какая логика в увязке количества баров и количества вершин //хотя вроде ты хотел вычислить разницу в ценах закрытия на двух последних вершинах? или я ошибаюсь? return(0); } //+--------------------------------------------------------------------------------------------------------------------------------------------------+ //| right comparison of 2 doubles | //+--------------------------------------------------------------------------------------------------------------------------------------------------+ bool CompareDoubles_m(double number1,double number2,int dig) { if(NormalizeDouble(number1-number2,dig)==0) return(true); else return(false); }
Уважаемый Profi_R! Огромное спасибо за столь подробный разбор моего кода и ценные советы, которые я обязательно приму к сведению.
Вообще, я хотел создать индикатор, который позволял бы сравнивать определенный набор вершин зигзага, причем не просто несколько последних вершин, а позволял бы выявлять определенные паттерны (в рамках волнового анализа, к примеру) на истории. Например, если принять за экстремум зигзага Ext[n], где n - номер экстремума, то пятиволновая модель у нас будет (образно) выглядеть как Ext[5]<Ext[4] && Ext[5]<Ext[3]<Ext[4] && Ext[2]>Ext[3] и т.д. до нулевого или первого экстремума. При наличии такой конфигурации можно говорить о том, что мы находимся, к примеру, на вершине пятиволновой модели и ожидаем коррекцию (и, скажем, ставим соответствующую стрелку вниз).
С помощью функции ZZBar, которую, не стану скрывать, написал не я, можно сравнивать экстремумы зигзага, но это работает "только вперед", при прогонке индикатора на тестере. А хотелось бы, чтобы все эти конфигурации считались назад, на истории, и все было видно сразу.
Соответственно, если рассматривать предложенный мной вначале (неработающий) код, я хотел в функции Start спроецировать расчитанные экстремумы ZZBar на историю - в шаблонном, разумеется варианте и там должно быть не
Close[Bar2]-Close[Bar1], а, скажем,
if (Close[Bar2]-Close[Bar1]) {рисуем стрелку вверх или вниз} - это уже просто.
Если осуществление этой затеи не является чем-то очень сложным, буду признателен за содействие - наверное, это многим было бы интересно!
Ниже код зигзага, который я использовал, его единственное достоинство - он не перерисовывает лучи:
Вообще, я хотел создать индикатор, который позволял бы сравнивать определенный набор вершин зигзага, причем не просто несколько последних вершин, а позволял бы выявлять определенные паттерны (в рамках волнового анализа, к примеру) на истории. Например, если принять за экстремум зигзага Ext[n], где n - номер экстремума, то пятиволновая модель у нас будет (образно) выглядеть как Ext[5]<Ext[4] && Ext[5]<Ext[3]<Ext[4] && Ext[2]>Ext[3] и т.д. до нулевого или первого экстремума. При наличии такой конфигурации можно говорить о том, что мы находимся, к примеру, на вершине пятиволновой модели и ожидаем коррекцию (и, скажем, ставим соответствующую стрелку вниз).
С помощью функции ZZBar, которую, не стану скрывать, написал не я, можно сравнивать экстремумы зигзага, но это работает "только вперед", при прогонке индикатора на тестере. А хотелось бы, чтобы все эти конфигурации считались назад, на истории, и все было видно сразу.
Соответственно, если рассматривать предложенный мной вначале (неработающий) код, я хотел в функции Start спроецировать расчитанные экстремумы ZZBar на историю - в шаблонном, разумеется варианте и там должно быть не
Close[Bar2]-Close[Bar1], а, скажем,
if (Close[Bar2]-Close[Bar1]) {рисуем стрелку вверх или вниз} - это уже просто.
Если осуществление этой затеи не является чем-то очень сложным, буду признателен за содействие - наверное, это многим было бы интересно!
Ниже код зигзага, который я использовал, его единственное достоинство - он не перерисовывает лучи:
//+------------------------------------------------------------------+ //| High_Low v2 (ZigZag).mq4 | //| rewritten by CrazyChart | //| | //+------------------------------------------------------------------+ #property copyright "rewritten by CrazyChart" #property link "" #property indicator_chart_window #property indicator_buffers 1 #property indicator_color1 Blue //---- input parameters extern int barn=300; extern int Length=6; //---- buffers double ExtMapBuffer1[]; //double ExtMapBuffer2[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- indicators SetIndexEmptyValue(0,0.0); //SetIndexDrawBegin(0, barn); SetIndexStyle(0,DRAW_SECTION); SetIndexBuffer(0,ExtMapBuffer1); //---- return(0); } //+------------------------------------------------------------------+ //| Custor indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { int counted_bars=IndicatorCounted(); int shift,Swing,Swing_n,uzl,i,zu,zd,mv; double LL,HH,BH,BL,NH,NL; double Uzel[10000][3]; string text; // loop from first bar to current bar (with shift=0) Swing_n=0;Swing=0;uzl=0; BH =High[barn];BL=Low[barn];zu=barn;zd=barn; for (shift=barn;shift>=0;shift--) { LL=10000000;HH=-100000000; for (i=shift+Length;i>=shift+1;i--) { if (Low[i]< LL) {LL=Low[i];} if (High[i]>HH) {HH=High[i];} } if (Low[shift]<LL && High[shift]>HH){ Swing=2; if (Swing_n==1) {zu=shift+1;} if (Swing_n==-1) {zd=shift+1;} } else { if (Low[shift]<LL) {Swing=-1;} if (High[shift]>HH) {Swing=1;} } if (Swing!=Swing_n && Swing_n!=0) { if (Swing==2) { Swing=-Swing_n;BH = High[shift];BL = Low[shift]; } uzl=uzl+1; if (Swing==1) { Uzel[uzl][1]=zd; Uzel[uzl][2]=BL; } if (Swing==-1) { Uzel[uzl][1]=zu; Uzel[uzl][2]=BH; } BH = High[shift]; BL = Low[shift]; } if (Swing==1) { if (High[shift]>=BH) {BH=High[shift];zu=shift;}} if (Swing==-1) { if (Low[shift]<=BL) {BL=Low[shift]; zd=shift;}} Swing_n=Swing; } for (i=1;i<=uzl;i++) { //text=DoubleToStr(Uzel[i][1],0); //text=; mv=StrToInteger(DoubleToStr(Uzel[i][1],0)); ExtMapBuffer1[mv]=Uzel[i][2]; } return(0); } //+------------------------------------------------------------------+
вот посмотри, я не понял твоего задания, но и тебе лучше начинать с простого
//+------------------------------------------------------------------+ //| Education_Idalgo.mq4 | //| rvm_fam @ fromru . com | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property link "http://www.metaquotes.net" //индикатор будем отрисовывать в основном окне #property indicator_chart_window /* Не пытайся сразу объять не объятное, пользуйся уже проверенными народными мудростями и ранее полученным опытом, а именно, начни с простого, поняв механизмы ты затем сможешь реализовывать более сложные задачи. Этот подход можно реализовать не только упрощением задачи, но и путем разбития задачи на подзадачи. Давай реализуем более простую задачу, т.к. из того что ты изложил я мало что понял, а дальше я думаю ты сам сможешь воплотить то, что ты хотел. итак на входе имее индикатор High_Low v2 с двумя внешними переменными - типа целочисленные, кроме того известно входной индикатор пишет все свои значения в один буфер с индексом - 0 и еще что он имеет тип отрисовки - зигзаг, т.е. вершины в нем чередуются с впадинами. Задача - найти на графике все наборы из двух последовательных а) повышающихся вершин б) понижающихся впадит, и отметить их соответствующими значками */ //потребуется два буфера для отрисовки, в одном будем ставить значки означающие повышение вершин, //в другом - понижающиеся впадины #property indicator_buffers 2 //назначим цвета для наших значков #property indicator_color1 Black #property indicator_color2 Yellow //---- input parameters //т.к. мы будем экспеременитровать с входящими значениями исходного индикатора, то //вынесем его внешние переменные на вход нашего индикатора, при этом желательно чтобы имена //совпадали, это даст лего понять в любом месте кода что за переменные мы используем //и даже больше можно добавить в начало аббревиатуру исходного индикатора extern int HL_v2_barn=3000; extern int HL_v2_Length=12; //---- buffers здесь объявление использования буферов double increasing_tops[]; //в этом буфере (массиве) будем отображать значки повышающихся вершин double lowerring_troughs[]; //в этом буфере (массиве) будем отображать значки понижающихся впадин //----- var здесь будем описывать глобальные для индикатора переменные, которые будут доступны datetime time_0; //последнее известное время 0 бара double High_0,Low_0; //последние известные максимум и минимум 0 бара //----- из любого места нашего кода индикатора //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- indicators //функция init предназначена для начальной инициализации буферов, переменных //т.к. нас интересуют значки то соответственно выбераем этот тип отрисовки //о специфике и различиях можно почитать в справке, и посмотреть на примере //стандартных индикаторов SetIndexStyle(0,DRAW_ARROW); SetIndexStyle(1,DRAW_ARROW); //назначаем код значка которым будет отображаться наш индикатор SetIndexArrow(0,217); SetIndexArrow(1,218); //привязываем наши массивы к буферам индикаторов SetIndexBuffer(0,increasing_tops); SetIndexBuffer(1,lowerring_troughs); //назначаем инициализационное значение для буфера, я например практикую значение "-1" //это дает возможность использование сравнения с 0, в данном случае это делать не //обязательно, но бывает очень удобно в некоторых случаях, а означает то, что до тех пор //пока мы явно не назначим конкретное значение, в буфере содержится значение "-1" и //при отрисовке если такое значение встречается, то на этом месте индикатор ничего не //отрисует SetIndexEmptyValue(0,-1.0); SetIndexEmptyValue(1,-1.0); //можно задать некоторые имена для буферов, которые будут подсвечиваться, при наведении //на них курсора (хинты) SetIndexLabel(0,"есть повышающиеся максимумы"); SetIndexLabel(1,"есть понижающиеся минимумы"); //инициализируем также нижеописанную глобальную для индикатора переменную time_0=0; //---- return(0); } //---- из опыта знаю что мало какие расчеты обходятся без сравнения чисел с плавающей точкой //---- и специфики этого сравнения в MQL4 сразу вставляю функции на сравнении двух чисел //---- их две - на равенство, и на то что первое число, больше второго. Они нам пригодятся. //+--------------------------------------------------------------------------------------------------------------------------------------------------+ //| right comparison of 2 doubles | //+--------------------------------------------------------------------------------------------------------------------------------------------------+ bool GreaterDoubles(double number1,double number2,int dig) { if(NormalizeDouble(number1-number2,dig)>0) return(true); else return(false); } //+--------------------------------------------------------------------------------------------------------------------------------------------------+ //| right comparison of 2 doubles | //+--------------------------------------------------------------------------------------------------------------------------------------------------+ bool CompareDoubles_m(double number1,double number2,int dig) { if(NormalizeDouble(number1-number2,dig)==0) return(true); else return(false); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { //теперь нам нужно определиться, как мы будем просчитывать индикатор //слева направо, или наоборот и как часто мы будем это делать //думаю классический расчет слева направо можно использовать //в дальнейшем нужно подходить к каждому случаю индивидуально //и выбирать оптимальный вариант, чтобы производить как можно //меньше операций //следующим шагом будет определение области баров (подсвечников) //на которых необходимо произвести расчет, при ее определении //также необходимо учитывать специфику исходных данных //например мы знаем что исходный индикатор модифицируется //изменяет свои показания при условии что на последнем баре //установлен новый минимум или максимум, также начальную фиксацию //минимума и максимума нужно начинать с момента появления этого бара //т.е. определение состояния мы будем производить в двух случаях //1. если появился новый бар //2. если установлен новый минимум или максимум //для определения появления нового бара можно воспользоваться //следующими приемами //1. сравнение количества баров текущего и ранее записанного //2. сравнение времени начала отрисовки 0 бара текущего и ранее записанного //мы будем использовать второй вариант //также нас интересует первый просчет всей области индексов, на момент //прикрепления индикатора, т.к. в это время может и не появляться новых баров, //а мы должны просчитать всю область, этот момент мы будем определять по количеству //просчитанных баров определяемых функцией IndicatorCounted(), т.к. при первоначальном //просчете количество этих баров равно 0 //для фиксации времени нулевого бара, а также его минимума и максимума //заведем глобальные для индикатора переменные, там где у нас раздел //"//----- var " //итак если у нас появился новый бар или это первый расчет, т.е. время последнего известного //времени 0 бара меньше чем время 0 бара на графике if( time_0<Time[0] ) { //здесь идет объявление и сразу расчет переменной counted_bars, но я лично //предпочитаю выносить все объявления переменных в начало функции //на мой взгляд так удобнее int counted_bars=IndicatorCounted(); //цикл мы будем делать по барам поэтому индекс бара рассчитываемого в текущий момент //мы так и обзовем current_bar, а количество баров требующих расчет (вернее область индексов) //обзавем limit_calculated_bar, обе эти переменные будут иметь целочисленный тип int current_bar,limit_calculated_bar; //если по какой-то причине произошел сбой, то переменная counted_bars, будет содержать значение //меньше 0, в этом случае не производим никаких расчетов и выходим из функции с возвратом кода "-1" //это на всякий, чтобы можно было обработать эту ситуацию if( counted_bars<0 ) { return(-1); } //фиксируем последнее известное время 0 бара time_0=Time[0]; //фиксируем максимум и минимум нового 0 бара High_0=High[0]; Low_0=Low[0]; //т.к. при появлении нового бара появлется один непросчитанный бар+для гарантированного //просчета в MQL4 значение IndicatorCounted() возвращается на 1 меньше чем реальное значение //то получается что при появлении нового бара нужно посчитать два последних бара, но //мы во избежание лишней головомороки и оптимизации увеличиваем это значение на 1 //и таким образом будем просчитыать только последний "0" бар counted_bars++; //таким образом при первом расчете у нас будет просчитано Bars-1-counted_bars(эта вся область индексов минус 1, //самый левый бар на графике просчитываться не будет, а оно нам и не надо) //при последующих эта область будет состоять из области 0 индекса, т.е. самый последний бар limit_calculated_bar=Bars-1-counted_bars; } else { //иначе если нет нового бара и не первый расчет //область индексов требующих расчет равна 0, т.е. требуется просчитать только последний бар limit_calculated_bar=0; } //как уже раньше упомянал что нам не надо ничего считать если не изменились максимумы и минимумы //за исключением когда максимум=минимум, а такое бывает на первом тике бара //здесь понадобятся наши предсказанные функции на сравнение //формируем условие - если максимум 0 бара не равен минимуму 0 бара (не первый тик) и при этом //значение максимума 0 бара не больше последнего известного максимума 0 бара и последний известный //минимум 0 бара больше минимума 0 бара и это не первый просчет, пропускаем расчеты и выходим // if( !CompareDoubles_m(High[0],Low[0],Digits) && !GreaterDoubles(High[0],High_0,Digits) && !GreaterDoubles(Low_0,Low[0],Digits) && counted_bars>1 ) { return(0); } //иначе сохраняем новые значения максимума и минимума High_0=High[0]; Low_0=Low[0]; //а здесь будем проводить обсчет всех требуемых индексов //для начала напишем шаблон цикла, затем перейдем к доп функциям //которые напишем для облегчения читаемости кода for( current_bar=limit_calculated_bar;current_bar>=0;current_bar-- ) { //после того как мы описали функцию получения значений //вспомогательного индикатора, можем продолжить дальше //понятно, что если на текущем баре индикатор не отрисовывался //то значит ничего пока не изменилось и считать его не надо, //но если это не последний индекс (крайне правый - 0), //то есть еще бары на которых возможно необходимо будет //произвести расчет поэтому мы воспользуемся командой continue //а не return //заведем временную переменную в которой будем хранить значение полученное //функцией Get_mInd_value double tmp_value=Get_mInd_value(current_bar); if( !GreaterDoubles(tmp_value,0,Digits) ) { continue; } else { //первая точка у нас есть, теперь нужно найти вторую точку //с которой будет идти сравнение, для этого напишем еще //одну функцию - search_second_point double first_point=tmp_value; double second_point=search_second_point(current_bar); //теперь если первая точка построена по максимуму и она выше второй //записываем значение в буфер increasing_tops //если же построена по минимуму и ниже ниже //записываем значение в буфер lowerring_troughs if( CompareDoubles_m(first_point,High[current_bar],Digits) && GreaterDoubles(first_point,second_point,Digits) ) { //наверно целесообразно поставить значок чуть выше на 10 пипсов increasing_tops[current_bar]=High[current_bar]+10*Point; } else { if( CompareDoubles_m(first_point,Low[current_bar],Digits) && GreaterDoubles(second_point,first_point,Digits) ) { lowerring_troughs[current_bar]=Low[current_bar]-10*Point; } } } } //---- //---- return(0); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| Функция возвращает значение вспомогательного индикатора на | //| полученном в качестве параметра индексе | //+------------------------------------------------------------------+ double Get_mInd_value( int cur_bar ) { //---- double result; //переменная в которой будет храниться результат работы функции //будь внимателен большинство людей обращавшихся ко мне за помощью в поиске ошибок //просто неверно писали наименование индикатора в результате чего получали //неправильный результат работы кода result=iCustom(NULL,0,"High_Low_v2",HL_v2_barn,HL_v2_Length,0,cur_bar); //в данном случае cur_bar - это полученный индекс, на котором необходимо определить факт //отрисовки вспомогательного индикатора //---- return(result); } //+------------------------------------------------------------------+ //| Функция возвращает значение вспомогательного индикатора на | //| втором искомом индексе | //+------------------------------------------------------------------+ double search_second_point( int cur_bar ) { //---- double result; //переменная в которой будет храниться результат работы функции //здесь потребуется свой миницикл с индекса следующего за 1 найденной точкой //фактически нам нужно найти третье значение индикатора больше значения инициализации //объявим переменную int cb; //current_bar сократили до cur_bar, а здесь еще короче :) //также нам потребуется булева переменная, которая по умолчанию фальсе //а нагрузка будет состоять в том, что прошли мы уже вторую точку или нет bool intermediate_point=0; //почему мы ищем третью наверно понятно, потому что вершины чередуются //если последняя вершина, предпоследняя впадина, а предшествующая ей опять вершина //нам же нужно будем сравнивать две вершины или две впадины //здесь цикл идет справа налево for( cb=cur_bar+1;cb<Bars;cb++ ) { //здесь нам понадобится уже написанная функция Get_mInd_value //опять таки если значений нет пропустим бар double tmp_value=Get_mInd_value(cb); if( !GreaterDoubles(tmp_value,0,Digits) ) { continue; } else { //смотрим если вторая точка еще не пропущена if( !intermediate_point ) { intermediate_point=1; //выставляем флаг что вторая точка, ту что нужно пропустить найдена } else { //нашли искомую точку, прерываем цикл, далее в нем нет необходимости result=tmp_value; break; } } } //---- return(result); }
Спасибо тебе огромное, дружище! На самом деле, заложенная тобой в твой индикатор логика соответствует тому, что я говорил, просто надо кое-что добавить. Но я уже вижу, что справлюсь с этим самостоятельно с учетом твоих подробнейших комментариев.
Я читал что-то по mql (начинал с нуля, безо всякого опыта программирования чего-либо), но, конечно, парочка твоих постов с разбором конкретных задач помогли мне куда больше, чем изучение абстрактных примеров. Думаю, если бы ты написал учебник по mql, он бы пользовался спросом (по крайней мере, я бы купил) :)
Спасибо!
Я читал что-то по mql (начинал с нуля, безо всякого опыта программирования чего-либо), но, конечно, парочка твоих постов с разбором конкретных задач помогли мне куда больше, чем изучение абстрактных примеров. Думаю, если бы ты написал учебник по mql, он бы пользовался спросом (по крайней мере, я бы купил) :)
Спасибо!
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь