| / | Статьи |
Cтатьи
Возможности
Визуальное тестирование прибыльности индикаторов и сигналов
Авторизуйтесь или зарегистрируйтесь , чтобы добавить новую статью
|
Визуальное тестирование прибыльности индикаторов и сигналов [ en ]Выбор индикатора торговых сигналов или просто методики их расчета обычно проверяют в тестере при прогонах экспертов, использующих эти сигналы. Однако не всегда бывает возможно/нужно/целесообразно писать эксперт под каждый индикатор. Оперативно просчитать прибыльность торговли по сигналам других индикаторов можно с помощью специального индикатора, который сам собирает их сигналы и рисует картину идеальной торговли по ним. С его помощью вы можете не только визуально оценить результаты, но и быстро подобрать наиболее оптимальные параметры. Вспомните, сколько раз глядя на случайно подвернувшийся под руки или давно разыскиваемый и наконец-то раздобытый индикатор, вы хотели немедленно узнать каков будет результат торговли по его сигналам. Тоже самое хотелось быстренько оценить когда вам предлагают новую систему торговли, по которой еще нет ни экспертов, ни индикаторов. Прежде чем браться за серьезную работу и начинать писать работающего эксперта, все-таки хочется хотя бы прикинуть - а есть ли здравое зерно в предлагаемом материале. Или другая ситуация: есть индикатор с хорошими сигналами, но вы нутром чуете, что его параметры не оптимальны, что его можно докрутить, и вы даже представляете себе где и как это можно сделать. Как можно быстренько проверить свою идею, не увязнув в долгом и сложном программировании? Постановка задачиДавайте задумаемся, что у нас есть и что мы хотим получить. Возьмем в качестве примера известный всем ZigZag из стандартной поставки MetaTrader 4. Набросьте его на любую пару на любом таймфрейме: правда хочется торговать? Все очевидно: на верхнем изломе нужно продать, а на нижнем - закрыть продажу и купить. Теперь вопрос: сколько денег принесет такая торговля? Ответ на него можно получить совершенно элементарно: суммируем все высоты отрезков и пересчитываем с учетом размера торгуемого лота и цены одного пункта в валюте депозита. Доступ к буферу значений зигзага доступен через вызов функции iCustom:
P=iCustom(NULL,0,"ZigZag",0,i); где i - номер бара, для которого нужно получить значение. Все что остается сделать - пробежаться по всем значениям буфера да понаходить все точки с ненулевыми значениями - именно по ним строится зигзаг, ну и просуммировать высоты отрезков. Для наглядности можно даже нарисовать эти линии и раскрасить их в соответствии с цветами операций и их прибыльностью. Задача совершенно не сложная и ее с успехом можно поручить индикатору. Универсальное решениеДля того, чтобы такой индикатор мог тестировать любой
индикатор - нужно позаботится о его универсализме. Поскольку любой индикатор
или торговая система в общем случае предполагает только 4 операции: покупка,
продажа, закрытие покупки и закрытие продажи, в нашем индикаторе под каждый из
них нужно завести отдельный массив, который можно будет заполнять из любого
источника. Это то единственное место, которое вам придется самому править, вписывая код заполнения сигнальных массивов (ну и возможно, еще некоторые из параметров придется вынести в external переменные). Функционально индикатор состоит из следующих блоков:
РеализацияВот код самого индикатора с примером заполнения данных из индикатора ZigZag. /*///——————————————————————————————————————————————————————————————————————————————————————————————————————— IndicatorTester.mq4 Визуальное тестирование прибыльности индикаторов и сигналов Copyright © 2006, Кравчук Сергей, http://forextools.com.ua /*///——————————————————————————————————————————————————————————————————————————————————————————————————————— #property copyright "Copyright © 2006-2008, Sergey Kravchuk. http://forextools.com.ua" #property link "http://forextools.com.ua" #property indicator_chart_window #property indicator_buffers 0 // параметры отображения элементов графика extern bool ShowZZ = true; // рисовать ли ЗЗ extern bool ShowMARKERS = true; // рисовать ли вертикальные линии-метки //даты построения графика extern datetime DateStart = D'1.01.1970'; extern datetime DateEnd = D'31.12.2037'; //параметры расчетов прибыли extern double LotForCalc = 0.05; // размер лота для рассчета прибыли extern int Optimizm = 0; // -1-пессимистический рассчет 0-по ценам открытия баров //+1-оптимистический // цвета линий покупок extern color ColorProfitBuy = Blue; // цвет линии для профитных покупок extern color ColorLossBuy = Red; // цвет линии для убыточных покупок extern color ColorZeroBuy = Gray; // цвет линии для покупок с нулевой прибылью // цвета линий продаж extern color ColorProfitSell = Blue; // цвет линии для профитных продаж extern color ColorLossSell = Red; // цвет линии для убыточных продаж extern color ColorZeroSell = Gray; // цвет линии для продаж с нулевой прибылью // цвета линий сигналов extern color ColorBuy = CornflowerBlue; // цвет линии сигнала на покупку extern color ColorSell = HotPink; // цвет линии сигнала на продажу extern color ColorClose = Gainsboro; // цвет линии сигнала на закрытие //—————————————————————————————————————————————————————————————————————————————————————————————————————————— double sBuy[],sCloseBuy[],sSell[],sCloseSell[]; // массивы для сигналов int sBuyCnt,sSellCnt,sBuyCloseCnt,sSellCloseCnt;// счетчики сигналов int i,DisplayBars; //—————————————————————————————————————————————————————————————————————————————————————————————————————————— // служебные коды #define MrakerPrefix "IT_" #define OP_CLOSE_BUY 444 #define OP_CLOSE_SELL 555 //—————————————————————————————————————————————————————————————————————————————————————————————————————————— int init() { ClearMarkers(); return(0); } int deinit() { ClearMarkers(); return(0); } //—————————————————————————————————————————————————————————————————————————————————————————————————————————— int start() { double Profit=0,P1,P2; int CntProfit=0,CntLoose=0,i1,i2; //———————————————————————————————————————————————————————————————————————————————————————————————————————— // удалим все метки на случай если индикатор перерисовывается ClearMarkers(); //———————————————————————————————————————————————————————————————————————————————————————————————————————— // подготовим счетчики сигналов sBuyCnt=0; sSellCnt=0; sBuyCloseCnt=0; sSellCloseCnt=0; //———————————————————————————————————————————————————————————————————————————————————————————————————————— // отведем память под сигнальные массивы и обнулим их значения DisplayBars=Bars; // к-во отображаемых баров ArrayResize(sBuy,DisplayBars); ArrayInitialize(sBuy,0); ArrayResize(sSell,DisplayBars); ArrayInitialize(sSell,0); ArrayResize(sCloseBuy,DisplayBars); ArrayInitialize(sCloseBuy,0); ArrayResize(sCloseSell,DisplayBars); ArrayInitialize(sCloseSell,0); //———————————————————————————————————————————————————————————————————————————————————————————————————————— // найдем первую точку и запомним ее место и цену for(i1=Bars-1;i1>=0;i1--) { P1=iCustom(NULL,0,"ZigZag",0,i1); if(P1!=0) break; } // обработаем точки зигзага for(i2=i1-1;i2>=0;i2--) { // найдем очередную точку и запомним ее место и цену for(i2=i2;i2>=0;i2--) { P2=iCustom(NULL,0,"ZigZag",0,i2); if(P2!=0) break; } if(i2<0) break; // последнюю точку ставим на текущей цене // условия открытия одновременно и условия закрытия противоположного ордера if(P1>P2) { sSell[i1]=1; sBuy[i2]=1; sCloseSell[i2]=1; } if(P1<P2) { sBuy[i1]=1; sSell[i2]=1; sCloseBuy[i2]=1; } P1=P2; i1=i2; // запомним бар найденной точки } //—————————————————————————————————————————————————————————————————————————————————————————————————————— // удалим повторяющиеся сигналы оставив только самые первые - левые по графику for(i=0;i<DisplayBars;i++) { if(sBuy[i]==sBuy[i+1]) sBuy[i]=0; if(sSell[i]==sSell[i+1]) sSell[i]=0; if(sCloseBuy[i]==sCloseBuy[i+1]) sCloseBuy[i]=0; if(sCloseSell[i]==sCloseSell[i+1]) sCloseSell[i]=0; } // удалим сигналы вне заданного диапазона дат for(i=0;i<DisplayBars;i++) { if(Time[i]<DateStart || DateEnd<Time[i]) { sBuy[i]=0; sSell[i]=0; sCloseBuy[i]=0; sCloseSell[i]=0; } } // добавим принудительное закрытие на границе диапазона if(DateEnd<=Time[0]) { i=iBarShift(Symbol(),Period(),DateEnd); sBuy[i]=0; sSell[i]=0; sCloseBuy[i]=1; sCloseSell[i]=1; } if(DateEnd >Time[0]) { sCloseBuy[0]=1; sCloseSell[0]=1; } //———————————————————————————————————————————————————————————————————————————————————————————————————————— // посчитаем количество сигналов for(i=0;i<DisplayBars;i++) { if(sBuy [i]!=0) sBuyCnt++; if(sCloseBuy [i]!=0) sBuyCloseCnt++; if(sSell[i]!=0) sSellCnt++; if(sCloseSell[i]!=0) sSellCloseCnt++; } //———————————————————————————————————————————————————————————————————————————————————————————————————————— // расставим метки, нарисуем ЗЗ и посчитаем прибыль //———————————————————————————————————————————————————————————————————————————————————————————————————————— // обработаем покупки for(i=DisplayBars-1;i>=0;i--) // пойдем собирать точки { // найдем очередную точку открытия и запомним ее место и цену for(i1=i;i1>=0;i1--) if(sBuy[i1]!=0) break; // найдем очередную точку закрытия покупки и запомним ее место и цену for(i2=i1-1;i2>=0;i2--) if(sCloseBuy[i2]!=0) break; if(i2<0) i2=0; // для последней незакрытой позы считаем закрытие на текущей цене i=i2; // новый бар для продолжения поиска точек открытия // определим цены для рисования в зависимости от параметра оптимистичности Optimizm if(Optimizm<0) { P1=High[i1]; P2=Low[i2]; } if(Optimizm==0) { P1=Open[i1]; P2=Open[i2]; } if(Optimizm>0) { P1=Low[i1]; P2=High[i2]; } P1/=Point; P2/=Point; // приведем цены к пунктам // определяем профит и заполняем соответствующий буфер if(i1>=0) { Profit=Profit+P2-P1; // соберем суммарный профит if(P2-P1>=0) CntProfit++; else CntLoose++; // посчитаем число ордеров DrawLine(i1,i2,OP_BUY,Optimizm); // нарисуем линию ордера PlaceMarker(i1,OP_BUY); PlaceMarker(i2,OP_CLOSE_BUY); } } //———————————————————————————————————————————————————————————————————————————————————————————————————————— // обработаем продажи for(i=DisplayBars-1;i>=0;i--) // пойдем собирать точки { // найдем очередную точку открытия и запомним ее место и цену for(i1=i;i1>=0;i1--) if(sSell[i1]!=0) break; // найдем очередную точку закрытия покупки и запомним ее место и цену for(i2=i1-1;i2>=0;i2--) if(sCloseSell[i2]!=0) break; if(i2<0) i2=0; // для последней незакрытой позы считаем закрытие на текущей цене i=i2; // новый бар для продолжения поиска точек открытия // определим цены для рисования в зависимости от параметра оптимистичности Optimizm if(Optimizm<0) { P1=Low[i1]; P2=High[i2]; } if(Optimizm==0) { P1=Open[i1]; P2=Open[i2]; } if(Optimizm>0) { P1=High[i1]; P2=Low[i2]; } P1/=Point; P2/=Point; // приведем цены к пунктам // если обе точки есть - определяем профит и заполняем соответствующий буфер if(i1>=0) { Profit=Profit+P1-P2; // соберем суммарный профит if(P1-P2>=0) CntProfit++; else CntLoose++; // посчитаем число ордеров DrawLine(i1,i2,OP_SELL,Optimizm); // нарисуем линию ордера PlaceMarker(i1,OP_SELL); PlaceMarker(i2,OP_CLOSE_SELL); } } //———————————————————————————————————————————————————————————————————————————————————————————————————————— // рассчет итоговых цифр для комментария int Cnt=CntProfit+CntLoose; // общее число операций // к-т для перевода пунктов в валюту депозита double ToCurrency = MarketInfo(Symbol(),MODE_TICKVALUE)*LotForCalc; string msg="Период: "+TimeToStr(MathMax(DateStart,Time[Bars-1]))+" - " + TimeToStr(MathMin(DateEnd,Time[0]))+"\n\n"; msg=msg+ sBuyCnt+" покупок и "+sBuyCloseCnt+" их закрытий\n"+ sSellCnt+" продаж и "+sSellCloseCnt+" их закрытий\n\n"; // общее время в днях int TotalDays = (MathMin(DateEnd,Time[0])-MathMax(DateStart,Time[Bars-1]))/60/60/24; //переведем секунды в дни if(TotalDays<=0) TotalDays=1; // чтоб не было деления на ноль для неполного дня if(Cnt==0) msg=msg+("Нет ни одной операции"); else msg=msg+ ( DoubleToStr(Profit,0)+" пункт на "+Cnt+" операциях за "+TotalDays+" дней\n"+ DoubleToStr(Profit/Cnt,1)+" пункт на операцию ("+ DoubleToStr(Profit/TotalDays,1)+" за день)\n\n"+ "При торговле лотом "+DoubleToStr(LotForCalc,2)+" получаем в "+AccountCurrency()+":\n"+ DoubleToStr(Profit*ToCurrency,0)+" всего, по "+ DoubleToStr(Profit/Cnt*ToCurrency,1)+" на операцию ("+ DoubleToStr(Profit/TotalDays*ToCurrency,1)+" за день)\n\n"+ CntProfit+" прибыльных ("+DoubleToStr(((CntProfit)*1.0/Cnt*1.0)*100.0,1)+"%)\n"+ CntLoose+" убыточных ("+DoubleToStr(((CntLoose)*1.0/Cnt*1.0)*100.0,1)+"%)" ); Comment(msg); } //—————————————————————————————————————————————————————————————————————————————————————————————————————————— //—————————————————————————————————————————————————————————————————————————————————————————————————————————— // удаление всех объектов нашего графика void ClearMarkers() { for(int i=0;i<ObjectsTotal();i++) if(StringFind(ObjectName(i),MrakerPrefix)==0) { ObjectDelete(ObjectName(i)); i--; } } //—————————————————————————————————————————————————————————————————————————————————————————————————————————— // установка вертикальной линии - метки операции типа op_type void PlaceMarker(int i, int op_type) { if(!ShowMARKERS) return; // показ маркеров отключен color MarkerColor; string MarkName; // __ чтобы по сортировке линиия закрытия нарисовалась ниже линии открытия if(op_type==OP_CLOSE_SELL) { MarkerColor=ColorClose; MarkName=MrakerPrefix+"__SELL_"+i; } if(op_type==OP_CLOSE_BUY) { MarkerColor=ColorClose; MarkName=MrakerPrefix+"__BUY_"+i; } if(op_type==OP_SELL) { MarkerColor=ColorSell; MarkName=MrakerPrefix+"_SELL_"+i; } if(op_type==OP_BUY) { MarkerColor=ColorBuy; MarkName=MrakerPrefix+"_BUY_"+i; } ObjectCreate(MarkName,OBJ_VLINE,0,Time[i],0); ObjectSet(MarkName,OBJPROP_WIDTH,1); if(op_type==OP_CLOSE_BUY || op_type==OP_CLOSE_SELL) ObjectSet(MarkName,OBJPROP_STYLE,STYLE_SOLID); else ObjectSet(MarkName,OBJPROP_STYLE,STYLE_DOT); ObjectSet(MarkName,OBJPROP_BACK,True); ObjectSet(MarkName,OBJPROP_COLOR,MarkerColor); } //—————————————————————————————————————————————————————————————————————————————————————————————————————————— // установка линии на графике для операции типа op_type по ценам параметра Optimizm void DrawLine(int i1,int i2, int op_type, int Optimizm) { if(!ShowZZ) return; // показ ЗЗ отключен color СurColor; string MarkName=MrakerPrefix+"_"+i1+"_"+i2; double P1,P2; // определим цены для рисования в зависимости от параметра оптимистичности Optimizm if(Optimizm<0 && op_type==OP_BUY) { P1=High[i1]; P2=Low[i2]; } if(Optimizm<0 && op_type==OP_SELL) { P1=Low[i1]; P2=High[i2]; } if(Optimizm==0) { P1=Open[i1]; P2=Open[i2]; } if(Optimizm>0 && op_type==OP_BUY) { P1=Low[i1]; P2=High[i2]; } if(Optimizm>0 && op_type==OP_SELL) { P1=High[i1]; P2=Low[i2]; } ObjectCreate(MarkName,OBJ_TREND,0,Time[i1],P1,Time[i2],P2); ObjectSet(MarkName,OBJPROP_RAY,False); // рисуем отрезки а не линии ObjectSet(MarkName,OBJPROP_BACK,False); ObjectSet(MarkName,OBJPROP_STYLE,STYLE_SOLID); ObjectSet(MarkName,OBJPROP_WIDTH,2); // зададим цвет линии в зависимости от прибыльности операции if(op_type==OP_BUY) { if(P1 <P2) СurColor = ColorProfitBuy; if(P1==P2) СurColor = ColorZeroBuy; if(P1 >P2) СurColor = ColorLossBuy; } if(op_type==OP_SELL) { if(P1 >P2) СurColor = ColorProfitSell; if(P1==P2) СurColor = ColorZeroSell; if(P1 <P2) СurColor = ColorLossSell; } ObjectSet(MarkName,OBJPROP_COLOR,СurColor); } //—————————————————————————————————————————————————————————————————————————————————————————————————————————— В параметрах индикатора есть один специфический параметр Optimizm. Он задает желаемую степень оптимистичности расчетов. Если он меньше нуля - это значит что будет выполнен пессимистический расчет: для цен покупок будут выбираться High сигнального бара, для продаж - Low. Таким образом моделируются самые плохие результаты которые мы можем получить по этим сигналам. Если его значение больше нуля - моделируется самый оптимистичный вариант расчета: когда мы покупаем по самым низким ценам а продаем по самым высоким. При значении параметра равном нулю моделируется нейтральное поведение, при котором мы открываемся и закрываемся по ценам открытия баров - именно такая ситуация будет в большинстве случаем реализовываться при торговле экспертов. Анализ результатовНу а теперь давайте посмотрим, какие у нас получаются результаты. Вот какой получается результат при объективном анализе зигзага.
Как видим - график показывает наличие восьми убыточных участков. Оно и понятно - зигзаг "работает" по самым лучшим ценам и, чтобы полностью повторить его, нам нужно задать параметр Optimizm = 1
Что нас ожидает, если мы будем торговать из рук вон плохо, можно посмотреть, задав параметр Optimizm = -1
Небольшое отступление Не ругайте меня сильно, уважаемые трейдеры, но этот индикатор может оказаться для вас хорошим кнутом, если попадет в умелые руки вашего начальства, которому, как правило, нет дела до тонкостей торговых тактик - их интересует только результат. Загрузив в тестер алгоритм сигналов ZigZag и включив Optimizm = 1 они получат цифру той максимальной прибыли, которую можно в принципе было получить с данного участка графика и которую они захотят от вас получать. И если вы всегда наторговываете меньше половины - это будет повод задуматься о том, не слишком ли прохладно вы относитесь к своим обязанностям. С другой стороны этот же инструмент может стать вашим оружием для защиты от необоснованно завышенных планов. Вы сможете аргументировано доказать что "спускаемые" вам цифры просто не реальны, и получить их нельзя ни при каких самых удачных раскладах. Как видим, использование только одного параметра Optimizm позволяет использовать индикатор для оценки потенциала тестируемого в нем индикатора сигналов. И если даже оптимистический расчет не дает прибыль - значит с индикатором сигналов нужно еще сильно поработать: подобрать ему другие параметры либо, в самом худшем случае, забросить его как бесперспективный, сэкономив себе время на разработку эксперта и деньги своего депозита, которые могли бы быть слиты, чтобы убедиться в непригодности индикатора сигналов. Таким образом, наш тестирующий индикатор позволяет сэкономить не только время, но деньги. Анализ сигналов торговых системБуферы других индикаторов - не единственный источник для заполнения сигнальных массивов, по которым работает наш тестирующий индикатор. Где-нибудь в книгах или в необъятных глубинах интернета вы можете найти описание сигналов торговой системы, для которой нет ни индикатора, ни эксперта. Это просто свод правил, которые, впрочем, поддаются легкой реализации на языке MQL4. Если вы в состоянии написать расчет сигналов такой системы и заполнить ими сигнальные буферы - тестирующий индикатор покажет вам результаты, которые вы можете получать, используя ее. Если для торговой системы уже написан код, вы можете выделить в нем расчет сигналов, по которым работает эксперт, и построить "результаты его работы" прямо на графике. Конечно, то же самое можно будет получить даже более точно в тестере стратегий MetaTrader 4, но индикатор будет гораздо быстрее производить перестроения и отображать их более наглядно, чем скупые отрезки линий тестера. Важным моментом в этом случае будет возможность совместить график полученных результатов с другими индикаторами. Вертикальные линии меток? проходя через дополнительные индикаторы, возможно подскажут вам, как можно использовать их для уточнения основных сигналов, или выявят места его неадекватной работы. В конце концов, просто методом тыка можно просто подобрать такие значения параметров, которые, возможно, устроят вас больше, чем результаты оптимизатора. Давайте возьмем в качестве примера готовый код стандартного эксперта MACD. Вот как должен выглядеть. Блок заполнения сигнальных массивов содержимое, которого скопировано и вставлено из текста индикатора: // заполним значениями сигнальные массивы и посчитаем их количество for(i=DisplayBars;i>=0;i--) { double MacdCurrent, MacdPrevious, SignalCurrent; double SignalPrevious, MaCurrent, MaPrevious; // to simplify the coding and speed up access // data are put into internal variables MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+0); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+1); SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+0); SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+1); MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+0); MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+1); // check for long position (BUY) possibility if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent>MaPrevious) sBuy[i]=1; // check for short position (SELL) possibility if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && MathAbs(MacdCurrent)>(MACDOpenLevel*Point) && MaCurrent<MaPrevious) sSell[i]=1; if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseBuy[i]=1; if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseSell[i]=1; } И вот какой результат мы получаем.
Обратите внимание - линии меток сигналов четко совпадают с точками пересечений графиков MACD. Возможно, глядя на эти совмещенные графики, вы решите что именно необходимо поправить в сигналах. Ну например: отказаться от проверки MaCurrent и MaPrevious. Небольшая коррекция кода // заполним значениями сигнальные массивы и посчитаем их количество for(i=DisplayBars;i>=0;i--) { double MacdCurrent, MacdPrevious, SignalCurrent; double SignalPrevious, MaCurrent, MaPrevious; // to simplify the coding and speed up access // data are put into internal variables MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+0); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i+1); SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+0); SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,i+1); MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+0); MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,i+1); // check for long position (BUY) possibility if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDOpenLevel*Point)) sBuy[i]=1; // check for short position (SELL) possibility if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && MathAbs(MacdCurrent)>(MACDOpenLevel*Point)) sSell[i]=1; if(MacdCurrent>0 && MacdCurrent<SignalCurrent && MacdPrevious>SignalPrevious && MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseBuy[i]=1; if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious<SignalPrevious && MathAbs(MacdCurrent)>(MACDCloseLevel*Point)) sCloseSell[i]=1; } и вы уже видите к каким результатам это приводит. Количество операций возросло c 19 до 51, правда, общий профит превратился потери, что говорит о том, что это была не самая хорошая идея по улучшению качества сигнала.
Тестирование фантазийУ каждого разработчика или трейдера в голове наверняка роятся как назойливые мухи идеи, до которых никогда не доходят руки. Тестер индикаторов поможет быстренько их визуализировать и оценить. Если окажется что идеи были правильные и полученные результаты положительные, можно будет подумать и о разработке настоящего индикатора или эксперта. В этом случае результаты тестера индикаторов будут одновременно и иллюстрацией к техническому заданию на разработку и контрольным примером, по которому можно будет выполнять приемку готового продукта. Вот в качестве примера простейшая "система": покупать когда для сигналов используется обычный индикатор МА. Условие покупки - МА растет, продажи - МА падает. Смотрите как просто можно проверить прибыльность этой идеи. Блок заполнения сигналов выглядит следующим образом: // заполним значениями сигнальные массивы и посчитаем их количество for(i=DisplayBars;i>=0;i--) { double m1=iMA(NULL,0,MAPeriod,0,MAMode,MAPrice,i+1); double m2=iMA(NULL,0,MAPeriod,0,MAMode,MAPrice,i+2); // условия открытия одновременно и условия закрытия противоположного ордера if(m2<=m1 && MathAbs(m1-m2)>0.2*Point) { sBuy[i]=1; sCloseSell[i]=1; sBuyCnt++; sSellCloseCnt++; } if(m2>=m1 && MathAbs(m1-m2)>0.2*Point) { sSell[i]=1; sCloseBuy[i]=1; sSellCnt++; sBuyCloseCnt++; } } и вот какие с ним получаются результаты:
Неплохой, но не самый лучший результат - мы ведь нафантазировали себе сумашедшую прибыль. Давайте попробуем уменьшить период МА, чтобы увеличить возможность заработка на профитных сделках. Уменьшив период с 15 до 7 бар, мы чуть ли не в два раза увеличили среднедневную прибыль:
дело осталось за малым - сделать соотношение прибыльных и убыточных сделок равным хотя бы 80% к 20%. Для этого вам придется потрудится, но уже без меня. ЗаключениеНу что же, у вас в руках еще один инструмент для экспресс-анализа индикаторов и торговых сигналов. Естественно, он никоим образом не заменяет тестер и уж тем более реальную торговлю. Все данные, полученные с его помощью, носят качественный, оценочный характер. Однако удобство работы, наглядность и скорость получаемых результатов позволяют мне предположить, что он может оказаться весьма полезным в арсенале разработчика. С его помощью можно оперативно проверять торговые идеи, не затрачивая на этот процесс много сил и времени. В известной степени он может служить своеобразным доказательством перспективности или бесперспективности тех или иных работ над торговыми сигналами и индикаторами, а в руках вдумчивого исследователя и экспериментатора он вполне может стать инструментом тонкой оптимизации параметров индикаторов.
Предупреждение:
все права на данные материалы
принадлежат MetaQuotes Software Corp. Полная или частичная перепечатка запрещена.
Огромное спасибо. Мне очень понравилась работа. Самое главное, шаблон можно использовать даже начинающим прогерам!
29.10.2008 11:12 infinum13
coaster:
... всегда приходится ждать его подтверждения ... Второй минус - это риски... space_cowboy: что-то подобное я делал когда пытался соорудить реоптимизацию т.е. запихивал эксперта в индикатор, который отображал баланс при торговле по этой тактике, а потом в нужный момент вызывал из эксперта индикатор с разными настройками, и смотрел какие настройки дают наилучший результат, далее эти настройки принимались в работу и так далее Респект
Как всегда в коментах (komposter, coaster) можно найти то, что еще хотелось бы видеть в заключении. +1 Респект.
07.10.2008 14:09 karakuts
coaster пиÑал(а):
В реале, когда наступает сигнал, всегда приходится ждать его подтверждения, а когда подтверждение пришло, то оказывается, что приходится уже открываться по совсем невыгодной цене.... Это первый минус неприменимости данного подхода на практике. Второй минус - это риски.... Такие демонстрации визуального тестирования в основном применяют ручные "трейдеры" для завлекания молодых неопытных клиентов. Индикатор написан не для того, что бы с его помощью торговать тем более на реале. Это просто инструмент для проверки "здравости идей" заложенных в другие индикаторы и сигналы ТС. Почему все видят в нем поиски грааля?!?!?! - никак не пойму :( Ну когда вы заказываете себе установку металопластиковых окон, вам сначала распечатают на бумажке прямоугольнички в котрых вы представляете себе как будут выглядеть ваши окна, какая половинка куда открывается и т.п. Но ведь эта бумажка - это не само окно! Окно будет совсем другим, а бумажка так и останется эскизом. Правдоподобным (если у вас хорошо работает воображение) но всего навсего эскизом. Так и мой индикатор - это только эскизная проверка. Да, с ее помощью можно "завлекать неопытных", но ведь этот материал размещен на форуме разработчиков, которые как я надеюсь буду применять его по назначению ;) После его написания у меня лично сэкономилась масса нервных клеток, трата времени на написание (пускай по шаблонам) новых проверочных экспертов и прогоны их в тестере теперь в прошлом - прикидки я делаю с помощью этого индикатора, а в серьезную работу попадает то, что меня заинтересует после этих прикидок.
06.10.2008 08:27 ForexTools
В истории явно видно - где должна была быть открыта позиция. История не изменяется. В реале, когда наступает сигнал, всегда приходится ждать его подтверждения, а когда подтверждение пришло, то оказывается, что приходится уже открываться по совсем невыгодной цене. А если не ждать подтверждения, то можно открыться не по системе, так как при наступлении времени закрытия бара (времени перехода динамического реала в статическую историю), индикатор может "изменить своё мнение". Это первый минус неприменимости данного подхода на практике. Второй минус - это риски. Индикатор, в основном показывает потенциальную прибыль, которую можно было-бы получить при входах по указанным сигналам, но умалчивает о рисках, т.е. об уровне стоплевела, который необходимо было-бы при этом установить, чтобы защитить свой депозит. Зачастую такие стоплевелы при сигналах на длинных свечах сводят к нулю матожидание системы. Статья понятная. Такие демонстрации визуального тестирования в основном применяют ручные "трейдеры" для завлекания молодых неопытных клиентов.
06.10.2008 00:15 coaster
granit77 пиÑал(а):
Ирония судьбы: в комментария к соседней статье ForexTools агрессивно нападал на ZZ, а сейчас "развернули доску". :)) Нападал, и буду продолжать нападать! ЗЗ - это индикатор для анализа истории и не более того. Ну в крайнем случае можно там попробовать поискать начала для волн Эллиота и прикинуть какие колена должны появится в будущем. И все! Торговать по коленам ЗЗ невозможно в принципе, поскольку колено окончательно формируется тогда, когда уже сформирована большая часть следующего, которое вы уже пропустили. Обращаю внимание всех читателей этого материала: зигзаг был выбран только с демонстрационной целью. Это средство показать возможности предложенного в моей статье индикатора. На нем наглядно видно что линии меток стоят именно на коленях ЗЗ и при желании можно ручками проверить длины отрезков и получаемую по ним сумму. И потом ведь моя статья называется "визуальное тестирование..." а не "визуальное доказательство прибыльности торговли по ЗЗ" ;) Все данные, полученные с его помощью, носят качественный, оценочный характер.
24.09.2008 19:57 ForexTools
Ирония судьбы: в комментария к соседней статье ForexTools агрессивно нападал на ZZ, а сейчас "развернули доску". :))
24.09.2008 17:56 granit77
ForexTools писал:
Именно для этого я и писал.Ну а для зеленых новичков - есть коменты. Я думаю что мы их уже достаточно "просветили".
23.09.2008 01:55 komposter
komposter пиÑал(а):
Об этом нужно было 2 раза (2 раза) и жирным шрифтом написать в статье. Прямо под картинкой где написано "99% прибыльных сделок". Через mql4.com каждый день проходит куча зеленых новичков, зачем им бросать в глаза золотую пыль? Всего не предусмотриш. Я выбирал пример, который объяснял идею этого конкретного индикатора. Потому что цель статьи - демонстрация возможностей проверок сигналов, а не то как торговать с помощью ЗЗ. И статья писалась не столько для трейдеров, сколько для разработчиков, которые имеют на плечах не поставку для шляпы, а кое что другое ;) Ну а для зеленых новичков - есть коменты. Я думаю что мы их уже достаточно "просветили".
23.09.2008 00:34 ForexTools
14 комментариев: 1 2
|