![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() ![]() |
![]() |
leonid553 |
![]()
Сообщение
#1
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
В мультивалютном советнике Rosh-a "ProtoType-IX" приведен пример определения тренда по четырем последним экстремумам. http://codebase.mql4.com/ru/1256
В аннотации указано: "Данный советник торговал без алгоритмических ошибок на чемпионате по автотрейдингу 2006 года. Требует для работы индикатор NRTR GATOR. Может являться примером мультивалютного эксперта и, надеюсь, облегчит написание такового новичкам в MQL4." Похоже пришла пора разобраться с ТРЕНДОМ, - как это делается. Хотя бы "методом тыка". Для примера можно взять любой простейший эксперт и использовать приемы определения тренда из советника "ProtoType-IX". (см. пост №2) Возьмем оттуда всё, что касается тренда и вставим в любой простейший советник. В результате получим: Function "GetSymbolString" is not referenced and will be removed from exp-file Function "PeriodNumber" is not referenced and will be removed from exp-file Function "TrendByWPR" is not referenced and will be removed from exp-file Function "SetArrow" is not referenced and will be removed from exp-file Function "SetUpArrows" is not referenced and will be removed from exp-file Function "TrendExist" is not referenced and will be removed from exp-file Мы получили шесть функций, которые вычисляются, но пока не принимают участия в торговле нашего эксперта. Поскольку, наш эксперт пусть будет НЕ МУЛЬТИВАЛЮТНЫЙ, то первая функция нам неинтересна. Вторая функция, - пожалуй, тоже, т.к. она задает таймфрейм. Но оставим пока всё как есть. Начнем с самого начала. Во внешних нашего эксперта параметрах мы добавляем: Код extern int PeriodWPR=8; extern double CriteriaWPR=25; extern int ATRPeriod=40;// период ATR для индикатора extern double kATR=0.5; extern int ZeroBar=8; // выход в безубыток через ZeroBar баров extern double MinTargetinSpread=5.0; extern double TP_SL_Criteria=2.0; extern int MaxOpenedOrders=3; extern double MaxOrderSize=5.0; Понятно что пока чего-то не хватает а что-то будет лишним. Надеюсь разберемся... Далее (после внешних параметров) задаем по аналогии глобальные переменные: Код int LastUpArray[13,7]; int PreLastUpArray[13,7]; int LastDownArray[13,7]; int PreLastDownArray[13,7]; double Complextrend[13,7];// собираем все тренды (Z,A и N тренды) в одно значение. double TPvsSL[13,7];// отношение TakeProfit к StopLoss на данном символе и таймфрейме int BestTPvsSLSymbol[20]; // лучшие символы по соотношению TP/SL int BestTPvsSLPeriod[20]; // лучшие таймфреймы по соотношению TP/SL //-------------------------------------------- string SymbolsArray[13]={"","USDCHF","GBPUSD","EURUSD","USDJPY","AUDUSD", "USDCAD","EURGBP","EURAUD","EURCHF","EURJPY","GBPJPY","GBPCHF"}; int TrendOnSymbol[13,7]; // тренд по символу и таймфрейму int MyBarsArrays[13,7];// храним количество баров по инструменту и таймфрейму int TimeNullArrays[13,7];// храним время Time[0] по инструменту и таймфрейму Не будем пока особо вникать. Посмотрим дальше... |
leonid553 |
![]()
Сообщение
#2
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
Прежде всего (как я уже говорил), возьмем простейший эксперт-заготовку, код которого будет понятен всем присутствующим, - кому интересно. Пусть это будет советник на индикаторе Стохастик.
Вход в длинную позицию, - пересечение главной линией линии сигнальной снизу вверх! Вход в короткую позицию, - пересечение главной линией линии сигнальной сверху вниз. Предусмотрим отдельные расчеты для длинных и коротких позиций. И работу по ценам открытия. Ну и трейлинг стоп конечно... Код советника - в закачке. И вот результат теста с приведенными ниже параметрами. На котировках Хистори Центр с янв. 2003г. по сей день. Замечу, что оптимизация была до 31 авг. 2007г. Далее (почти +400) - пробег вне выборки за сентябрь! Stochastic_Signal Символ GBPUSD (Great Britain Pound vs US Dollar) Период 30 Минут (M30) (2003.01.01 - 2007.10.06) Параметры K_period=4; D_period=17; K_period_=10; D_period_=20; Slowing=2; TP=162; SL=72; TP_sell=123; SL_sell=83; Lot=0.1; Slippage=3; UseTrailing=true; lMinProfit=50; sMinProfit=60; lTrailingStop=58; sTrailingStop=59; lTrailingStep=8; sTrailingStep=3; Начальный депозит 10000.00 Чистая прибыль 9722.54 Общая прибыль 47921.52 Общий убыток -38198.98 Прибыльность 1.25 Матожидание выигрыша 8.49 Абсолютная просадка 1077.12 Максимальная просадка 1329.56 (12.97%) Относительная просадка 12.97% (1329.56) Всего сделок 1145 Короткие позиции (% выигравших) 315 (58.41%) Длинные позиции (% выигравших) 830 (50.24%) Прибыльные сделки (% от всех) 601 (52.49%) Убыточные сделки (% от всех) 544 (47.51%) Самая большая прибыльная сделка 162.98 убыточная сделка -88.95 Средняя прибыльная сделка 79.74 убыточная сделка -70.22 Максимальное количество непрерывных выигрышей (прибыль) 12 (775.99) непрерывных проигрышей (убыток) 9 (-646.85) Максимальная непрерывная прибыль (число выигрышей) 775.99 (12) непрерывный убыток (число проигрышей) -646.85 (9) Средний непрерывный выигрыш 2 непрерывный проигрыш 2 Эскизы прикрепленных изображений Прикрепленные файлы ![]() |
leonid553 |
![]()
Сообщение
#3
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
С внешними параметрами и глобальными переменными мы уже определились в пост №1.
Посмотрим дальше. Придется ещё добавить функции по символу и таймфрейму. Возможно, потом мы их уберем, а пока код нашего эксперта будет начинаться так: Код //|Stochastic_Signal_Trend.mq4.mq4 //| leonid553 & co //| http://www.tradersforum.net.ru/ //+------------------------------------------------------------------+ #property copyright "leonid553 & co" #property link "http://www.tradersforum.net.ru/" //---- input parameters--------- extern int MagicNum =96784; extern int K_period =4; extern int D_period =17; extern int K_period_ =10; extern int D_period_ =20; extern int Slowing=3; //------------------------------ extern int TP=130; extern int SL=57; extern int TP_sell=130; extern int SL_sell=57; extern double Lot=0.1; extern int Slippage=2; //-------------------------------- extern bool UseTrailing = true;//трейлинг стоп extern int lMinProfit = 55; extern int sMinProfit = 55; extern int lTrailingStop = 58; extern int sTrailingStop = 60; extern int lTrailingStep = 5; extern int sTrailingStep = 5; //----------------------------------- extern int PeriodWPR=8; extern double CriteriaWPR=25; extern int ATRPeriod=40;// период ATR для индикатора extern double kATR=0.5; extern int ZeroBar=8; // выход в безубыток через ZeroBar баров extern double MinTargetinSpread=5.0; extern double TP_SL_Criteria=2.0; extern int MaxOpenedOrders=3; extern double MaxOrderSize=5.0; //------------------------------------- int LastUpArray[13,7]; int PreLastUpArray[13,7]; int LastDownArray[13,7]; int PreLastDownArray[13,7]; double Complextrend[13,7];// собираем все тренды (Z,A и N тренды) в одно значение. double TPvsSL[13,7];// отношение TakeProfit к StopLoss на данном символе и таймфрейме int BestTPvsSLSymbol[20]; // лучшие символы по соотношению TP/SL int BestTPvsSLPeriod[20]; // лучшие таймфреймы по соотношению TP/SL //-------------------------------------------- string SymbolsArray[13]={"","USDCHF","GBPUSD","EURUSD","USDJPY","AUDUSD","USDCAD","EURGBP", "EURAUD","EURCHF","EURJPY","GBPJPY","GBPCHF"}; int TrendOnSymbol[13,7]; // тренд по символу и таймфрейму int MyBarsArrays[13,7];// храним количество баров по инструменту и таймфрейму int TimeNullArrays[13,7];// храним время Time[0] по инструменту и таймфрейму //------------------- //-- Подключаемые модули -- #include <stdlib.mqh> //------------------- int ticket; //**************************************************************** //+------------------------------------------------------------------+ //| string SymbolByNumber | //+------------------------------------------------------------------+ string GetSymbolString(int Number) { //---- string res=""; res=SymbolsArray[Number]; //---- return(res); } //+------------------------------------------------------------------+ //| возвращает период | //+------------------------------------------------------------------+ int PeriodNumber(int number) { int per_min; switch (number) { case 0: per_min=PERIOD_M1;break; case 1: per_min=PERIOD_M5;break; case 2: per_min=PERIOD_M15;break; case 3: per_min=PERIOD_M30;break; case 4: per_min=PERIOD_H1;break; case 5: per_min=PERIOD_H4;break; default: per_min=PERIOD_D1;break; } return(per_min); } //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- () |
leonid553 |
![]()
Сообщение
#4
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
Далее вне функции int start() вставляем начало функции определения тренда:
Код //-------------------------------------------------------------------+ //| определение тренда по четырем последним экстремумам | //+------------------------------------------------------------------+ int TrendByWPR(int SymbolNumber,int period_counter) { //---- int res=0; string StringSymbol=GetSymbolString(SymbolNumber); int PeiodMinute=PeriodNumber(period_counter); int curPos, LastUpPos, PreLastUpPos, LastDownPos, PreLastDownPos, LastPeak, newPos; double LastPeakWPR=-1000; bool FindUp=true,FindDown=true,SearchCompleted=false; double CurWPR=iWPR(StringSymbol,PeiodMinute,PeriodWPR,0); //---- Т.е. пока задаем переменные. Здесь пока всё ясно, за исключением строки double LastPeakWPR=-1000; ![]() Почему именно =-1000 ? Странно! Ну ладно, - пойдем дальше.... ![]() |
Dimi |
![]()
Сообщение
#5
|
![]() Группа: Активный участник Сообщений: 236 Регистрация: 12.4.2006 Пользователь №: 14 Спасибо сказали: 2 раз(а) ![]() |
Привет! Эта переменная походу нигде не участвует в вычислениях LastPeakWPR=-1000; Хотел посмотреть для чего она нужна просмотрел весь код советника Rosh-a так и не нашел, удалил и скомпилировал. Показало что ошибок нет!!!
|
leonid553 |
![]()
Сообщение
#6
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
Да действительно! Эта переменная не задействована. Убираем....
А вот перед определением тренда ещё нужно поставить функцию появления нового бара: Код //+------------------------------------------------------------------+ //| признак появления нового бара на периоде номер period_counter | //+------------------------------------------------------------------+ bool isNewBar(int SymbolNumber,int period_counter) { bool res=false; if (IsTesting()) { if (MyBarsArrays[SymbolNumber,period_counter]!= iBars(GetSymbolString(SymbolNumber),PeriodNumber(period_counter))) { MyBarsArrays[SymbolNumber,period_counter]= iBars(GetSymbolString(SymbolNumber),PeriodNumber(period_counter)); //Print("Код ошибки в isNewBar=",GetLastError()); //Print("isNewBar SymbolNumber=",SymbolNumber," period_counter=", //period_counter," MyBarsArrays[SymbolNumber,period_counter]=", //MyBarsArrays[SymbolNumber,period_counter], //"iBars(GetSymbolString(SymbolNumber),PeriodNumber(period_counter))=", //iBars(GetSymbolString(SymbolNumber),PeriodNumber(period_counter)) ); res=true; } } else { if (TimeNullArrays[SymbolNumber,period_counter]!= iTime(GetSymbolString(SymbolNumber),PeriodNumber(period_counter),0)) { TimeNullArrays[SymbolNumber,period_counter]= iTime(GetSymbolString(SymbolNumber),PeriodNumber(period_counter),0); res=true; } } return(res); } |
leonid553 |
![]()
Сообщение
#7
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
Начинаем вникать в определение тренда по индикатору WPR:
Код //======= определим - где мы находимся в данный момент if (CurWPR<=CriteriaWPR-100) {//ЕСЛИ значение индикатора WPR на текущем баре меньше или // равно CriteriaWPR-100, то - FindDown=false; LastPeak=0; } if (CurWPR>=-CriteriaWPR) {//ЕСЛИ значение индикатора WPR на текущем баре больше или // равно >=-CriteriaWPR, то - FindUp=false; LastPeak=0; } // ================ начинаем поиск пичков-донышков Заметим, что так. наз. КритерийWPR=25 мы уже задали во внешних параметрах. И не будем забывать, что WPR на графике располагается в минусовой зоне т.е. имеет шкалу от 0 до "-100". Иначе говоря, если индюк WPR лежит в областях меньше "-75" либо больше "-25", то : FindUp=false; LastPeak=0; Получается что "-25" и "-75" - это своего рода границы зон перекупленности/перепроданности... Эскизы прикрепленных изображений |
leonid553 |
![]()
Сообщение
#8
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
Продолжаем....
Код // ================ начинаем поиск пичков-донышков while(!SearchCompleted && curPos<Bars) { if (iWPR(StringSymbol,PeiodMinute,PeriodWPR,curPos)>=-CriteriaWPR && LastPeak<0) { FindUp=false; LastPeak=curPos; curPos++; continue; } if (iWPR(StringSymbol,PeiodMinute,PeriodWPR,curPos)<=CriteriaWPR-100 && LastPeak<0) { FindDown=false; LastPeak=curPos; curPos++; continue; } if (iWPR(StringSymbol,PeiodMinute,PeriodWPR,curPos)>=-CriteriaWPR && FindUp) {//искали верхушку и нашли newPos=curPos; while(iWPR(StringSymbol,PeiodMinute,PeriodWPR,curPos)>CriteriaWPR-100 && curPos<Bars) {// теперь нужно найти донышко, чтобы между ними найти точный пичок curPos++; } if (LastUpPos==0) { LastUpPos=Highest(StringSymbol,PeiodMinute,MODE_HIGH,curPos-LastPeak,LastPeak); LastPeak=LastUpPos; } else { PreLastUpPos=Highest(StringSymbol,PeiodMinute,MODE_HIGH,curPos-LastPeak,LastPeak); LastPeak=PreLastUpPos; } curPos=newPos; FindUp=false; FindDown=true; curPos++; continue; }//============== if (iWPR(StringSymbol,PeiodMinute,PeriodWPR,curPos)<=CriteriaWPR-100 && FindDown) { newPos=curPos; while(iWPR(StringSymbol,PeiodMinute,PeriodWPR,curPos)<-CriteriaWPR && curPos<Bars) { curPos++; } if (LastDownPos==0) { LastDownPos=Lowest(StringSymbol,PeiodMinute,MODE_LOW,curPos-LastPeak,LastPeak); LastPeak=LastDownPos; } else { PreLastDownPos=Lowest(StringSymbol,PeiodMinute,MODE_LOW,curPos-LastPeak,LastPeak); LastPeak=PreLastDownPos; } curPos=newPos; FindDown=false; FindUp=true; curPos++; continue; } if (PreLastDownPos!=0 && PreLastUpPos!=0) SearchCompleted=true; curPos++; } if (Symbol()==StringSymbol && Period()==PeiodMinute) { Comment("LastUpPos=",LastUpPos," PreLastUpPos",PreLastUpPos," LastDownPos=",LastDownPos," PreLastDownPos=",PreLastDownPos," Время ",TimeToStr(CurTime())); SetUpArrows(LastUpPos,PreLastUpPos,LastDownPos,PreLastDownPos); } LastUpArray[SymbolNumber,period_counter]=LastUpPos; PreLastUpArray[SymbolNumber,period_counter]=PreLastUpPos; LastDownArray[SymbolNumber,period_counter]=LastDownPos; PreLastDownArray[SymbolNumber,period_counter]=PreLastDownPos; if (High[LastUpPos]-High[PreLastUpPos]>=kATR*iATR(StringSymbol,PeiodMinute,ATRPeriod,LastUpPos)&&Low[LastDownPos]>Low[PreLastDownPos]) res=1; if (Low[PreLastDownPos]-Low[LastDownPos]>=kATR*iATR(StringSymbol,PeiodMinute,ATRPeriod,LastDownPos)&&High[PreLastUpPos]>High[LastUpPos]) res=-1; return(res); } Действительно, этот алгоритм определяет наличие "пичков и донышек", перебирая последовательно бары с нулевого. Причем, ищет экстремумы в "зонах перекупленности/перепроданности", согласно показаниям индикатора WPR. Тут всё понятно... А также, задействует, неким образом, значения индикатора ATR с периодом=40 (по умолч) и коэффициент kATR=0.5; Каким образом?, - пока не стал вникать. Итак, мы нашли два "пичка" и два "донышка" ... |
leonid553 |
![]()
Сообщение
#9
|
![]() Группа: Активный участник Сообщений: 2 002 Регистрация: 14.4.2006 Из: г.Самара Пользователь №: 28 Спасибо сказали: 11 раз(а) ![]() |
Далее, - отображаем найденные экстремумы на графике! К сожалению, картинка получится не совсем наглядной, т.к. из-за "дебильных" движений цены в прошедшую пятницу по этим экстремумам трудно сделать вывод о наличии или отсутствии тренда.
Тем не менее, - алгоритм эксперта будет отображать стрелками найденные пички и донышке, - см. рис - Код /+------------------------------------------------------------------+ //| поставим стрелку | //+------------------------------------------------------------------+ void SetArrow(datetime _time,double _price,string _Description ,int _arrowType, color _arrowColor) { if (ObjectFind(_Description)==-1) { ObjectCreate(_Description,OBJ_ARROW,0,_time,_price); ObjectSet(_Description,OBJPROP_ARROWCODE,_arrowType); ObjectSet(_Description,OBJPROP_COLOR,_arrowColor); } else { ObjectSet(_Description,OBJPROP_TIME1,_time); ObjectSet(_Description,OBJPROP_PRICE1,_price); } return; } //+------------------------------------------------------------------+ //| установить стрелки экстермумов | //+------------------------------------------------------------------+ void SetUpArrows(int firstUpBar, int secondUpBar,int firstDownBar, int secondDownBar) { //---- SetArrow(Time[firstUpBar],High[firstUpBar],"FirstUp",241,Blue); SetArrow(Time[secondUpBar],High[secondUpBar],"SecondUp",241,Blue); SetArrow(Time[firstDownBar],Low[firstDownBar],"FirstDown",242,Red); SetArrow(Time[secondDownBar],Low[secondDownBar],"SecondDown",242,Red); //---- return(0); } Эскизы прикрепленных изображений |
Moriarty |
![]()
Сообщение
#10
|
![]() Группа: Активный участник Сообщений: 19 Регистрация: 27.9.2007 Пользователь №: 1 488 Спасибо сказали: 0 раз(а) ![]() |
Продолжаем.... Действительно, этот алгоритм определяет наличие "пичков и донышек", перебирая последовательно бары с нулевого. Причем, ищет экстремумы в "зонах перекупленности/перепроданности", согласно показаниям индикатора WPR. Тут всё понятно... А также, задействует, неким образом, значения индикатора ATR с периодом=40 (по умолч) и коэффициент kATR=0.5; Каким образом?, - пока не стал вникать. Итак, мы нашли два "пичка" и два "донышка" ... Имхо всё черезчур усложнено. Все три последних функции можно описать всего лишь в нескольких строках. У Роша сделаны универсальные функции, нам же они не нужны. Да и с самого начала можно 70% кода убрать, а то опять будем тестить экспов сутками. Может я конечно и ошибаюсь, но попробую сейчас по быстрому написать код, определяющий пики/донышки по Т3 сглаженому ВПРу. А вообще, думаю не совсем правильно использовать ВПР для определения тренда. Есть масса других, менее затратных и более точных определений тренда... P.S. Сейчас попробую написать определение Hi/Low ВПРа. Далее, - отображаем найденные экстремумы на графике! К сожалению, картинка получится не совсем наглядной, т.к. из-за "дебильных" движений цены в прошедшую пятницу по этим экстремумам трудно сделать вывод о наличии или отсутствии тренда. Тем не менее, - алгоритм эксперта будет отображать стрелками найденные пички и донышке, - см. рис - А если подключить ещё и АТР, то косяков станет ещё меньше. P.S. Кстати, а зачем использовать чужой код (и пытаться понять его), если можно написать свой, ничуть не хуже и полностью понимаемый ??? Сообщение отредактировал Moriarty - 7.10.2007, 17:57 |
![]() ![]() |
![]() |
Текстовая версия | Сейчас: 13.3.2025, 15:04 |