//+------------------------------------------------------------------+ //| TheoryPairs.mq4 | //| Copyright © 2010, Andrey Vassiliev | //| http://www.vassiliev.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2010, Andrey Vassiliev (MoneyJinn)" #property link "http://www.vassiliev.ru" //Индикатор создан на основе теории пар траекторий. Автор теории: Андрей Васильев. //Индикатор определяет возможное направление второй траектории пары и отображает //его в точке начала этой траектории. //Рекомендуемая рабочая пара валют: USD/CHF, M1 или M5. //Обсуждение индикатора и теории пар траекторий: http://forum.mql4.com/ru/36231 //Новые версии индикатора: http://www.moneyjinn.com //Почтовый адрес автора: andrey@vassiliev.ru //Публикация, перепродажа, распространение внутри любых сообществ, коммерческое //распространение индикатора или части его кода без разрешения автора запрещены! #property indicator_chart_window double PUP; double PDN; double UP; double DN; double E; //IndicatorBuffers(3); double UPB[]; double DNB[]; double EB[]; //Время начала торговой сессии. extern string StartTime="11:00"; //Время окончания торговой сессии. extern string EndTime="23:00"; //Максимальная длительность торговой сессии - 24 часа. //Время сервера ДЦ, использованного при тестировании, равно: MSK - 2, где MSK - Московское время. //Если время сервера Вашего ДЦ иное, то величины StartTime и EndTime следует скорректировать. //Количество повторов сессии внутри дня. extern int Repeats=1; //Крайние точки траекторий указывается в виде коэффициентов от длительности торговой сессии. //Это позволяет при смене длительности торговой сессии правильно определить расположение пар траекторий. //K - точка начала второй траектории пары. extern double K=0.491; //Метод анализа рабочего направления первой траектории пары. //0 - Open(t2) - Open(t1). //1 - Наибольшее из двух: High(t2) - Low(t1) или High(t1) - Low(t2). //2 - Наибольшее смещение от значения Open точки t1 в интервале до точки t2. //3 - Наибольшее из двух: наибольшее смещение от значения High точки t1 до Lowest в интервале до точки t2 // или наибольшее смещение от значения Low точки t1 до Highest в интервале до точки t2. //4 - Наибольшее изменение существующее в интервале от t1 до t2. extern int Method=3; //Минимально допустимое значение изменения на тестируемом участке. Измеряется в пипсах. //Один пипс соответствует изменению цены на 0.0001 или 0.01, в зависимости от валютной пары. extern int Delta=14; //Переход на зимнее время. extern int WinterTimeChange=-1; //Для некоторых ДЦ значение WinterTimeChange может равняться нулю. //P1 (P2,P3) - используемые параметры первой траектории. //K1 (K3,K5) - точка начала первой траектории пары. //K2 (K4,K6) - точка окончания первой траектории пары. //N1 (N2,N3) - антипара или пара. //Можно одновременно использовать несколько настроек первых //траекторий с разной длительностью и разными координатами. //При этом в точке K сигнал появится только в том случае, //если направление всех выбранных первых траекторий указывает //на одно и тоже направление второй траектории пары. extern bool P1=true; extern double K1=0.180; extern double K2=0.491; extern bool N1=true; extern bool P2=false; extern double K3=0; extern double K4=0; extern bool N2=true; extern bool P3=false; extern double K5=0; extern double K6=0; extern bool N3=true; //Фильтр подтверждения сигналов. //Режим: 0 - 2 //0 - Отключен. //Подтверждающий сигнал появляется: //1 - Если от уровня появления сигнала рынок сходил с момента его появления в его направлении //на N pips. Уровни предыдущих сигналов при появлении нового сигнала любого направления //перестают учитываться. //2 - Если с момента появления сигнала рынок сходил в его направлении //на N pips. Моменты предыдущих сигналов при появлении нового сигнала //любого направления перестают учитываться. extern int Confirm=0; //Change - уровень подтверждения движения. Измеряется в пипсах. //Один пипс соответствует изменению цены на 0.0001 или 0.01, в зависимости от валютной пары. extern int Change=16; //Наибольшая задержка сигнала равная общему числу баров прошедших с момента сигнала. extern int Pause=1; //Изображение сигналов в виде стрелок или в виде линий. extern bool Arrows=true; //Показывать сигналы с неизвестным направлением или нет. extern bool Unknown=false; //Показывать графические объекты или нет. extern bool Drawing=true; //Нумерация индикаторных буферов: (0) - вниз, (1) - вверх, (2) - не определено. datetime KT1; datetime KT2; datetime KT3; datetime KT4; datetime KT5; datetime KT6; datetime STS; datetime STE; int IndCounted; double IUP; double IDN; string Signal; datetime TS; datetime CRT; datetime CRE; int TSA; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { IndicatorBuffers(3); IndCounted=0; IUP=0; IDN=0; TS=0; CRT=0; CRE=0; int BrokerDecimal=1; if(Digits==3 || Digits==5) BrokerDecimal=10; Delta=Delta*BrokerDecimal; Change=Change*BrokerDecimal; TSA=TimeCurrent(); SetIndexBuffer(0,DNB); SetIndexBuffer(1,UPB); SetIndexBuffer(2,EB); SetIndexStyle(0,DRAW_NONE); SetIndexStyle(1,DRAW_NONE); SetIndexStyle(2,DRAW_NONE); return(0); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { if(ArraySize(UPB)>0) { ArrayInitialize(UPB,0); ArrayInitialize(DNB,0); ArrayInitialize(EB,0); } GlobalVariableSet("RESET",1); TS=0; CRT=0; CRE=0; if(Drawing==true) { int objects_amount=ObjectsTotal(); for(int b=objects_amount-1; b>=0; b --) {ObjectDelete(ObjectName(b));} WindowRedraw(); } Comment(""); return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { IndCounted=IndicatorCounted(); if(IndCounted<0){return(0);} if(IndCounted==0){deinit();} int pos=0; if(Bars>IndCounted+1){pos=(Bars-IndCounted)-1;} while(pos>=0) { if(TS==0) { TS=Time[pos]; if(TS=TS) { TS=Time[pos]; PUP=0; PDN=0; UP=0; DN=0; E=0; if(CRT>0 && Time[pos]>(CRT+Pause*Period()*60)) {CRT=0;} if(CRT==0) {Points(pos);} TRE(pos); if(Confirm==0 || Confirm>2) { UP=PUP; DN=PDN; } if(Confirm==1) { if(PUP>0) { IUP=Low[pos]; IDN=0; } if(IUP!=0) { if((High[pos]-IUP)>=(Change*Point)) { UP=Low[pos]; IUP=0; } } if(PDN>0) { IDN=High[pos]; IUP=0; } if(IDN!=0) { if((IDN-Low[pos])>=(Change*Point)) { DN=High[pos]; IDN=0; } } } if(Confirm==2) { if(PUP>0) { IUP=Low[pos]; IDN=0; } if(IUP!=0) { if(Low[pos]=(Change*Point)) { UP=Low[pos]; IUP=0; } } if(PDN>0) { IDN=High[pos]; IUP=0; } if(IDN!=0) { if(High[pos]>IDN){IDN=High[pos];} if((IDN-Low[pos])>=(Change*Point)) { DN=High[pos]; IDN=0; } } } ART(pos); } pos--; } Comment(Signal); return(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CLR(int pos) { string Name="Up"; string ObjName=Name+" "+TimeToStr(Time[pos]); if(ObjectFind(ObjName)!=-1) ObjectDelete(ObjName); Name="Dn"; ObjName=Name+" "+TimeToStr(Time[pos]); if(ObjectFind(ObjName)!=-1) ObjectDelete(ObjName); Name="Unknown"; ObjName=Name+" "+TimeToStr(Time[pos]); if(ObjectFind(ObjName)!=-1) ObjectDelete(ObjName); WindowRedraw(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ART(int pos) { //---- Создание если есть if(UP>0) { UPB[pos]=Open[pos]; Signal="Last Signal: UP Level: "+DoubleToStr((Open[pos]+(MarketInfo(Symbol(),MODE_SPREAD)*Point)),Digits)+" Spread: "+DoubleToStr(MarketInfo(Symbol(),MODE_SPREAD)*Point,Digits)+" Time: "+TimeToStr(Time[pos]); if(Drawing==true) { CLR(pos); string Name="Up"; if(Arrows==true) { SetArrow(Time[pos],Open[pos],Name,233,LimeGreen); } else { SetLine(Time[pos],Open[pos],Name,LimeGreen); } } } if(DN>0) { DNB[pos]=Open[pos]; Signal="Last Signal: DN Level: "+DoubleToStr(Open[pos],Digits)+" Spread: "+DoubleToStr(MarketInfo(Symbol(),MODE_SPREAD)*Point,Digits)+" Time: "+TimeToStr(Time[pos]); if(Drawing==true) { CLR(pos); Name="Dn"; if(Arrows==true) { SetArrow(Time[pos],Open[pos],Name,234,Red); } else { SetLine(Time[pos],Open[pos],Name,Red); } } } if(E>0 && Unknown==true) { EB[pos]=Open[pos]; if(Drawing==true) { CLR(pos); Name="Unknown"; if(Arrows==true) { SetArrow(Time[pos],Open[pos],Name,74,White); } else { SetLine(Time[pos],Open[pos],Name,White); } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void SetArrow(datetime ArrowTime,double Price,string Trend,double ArrowCode,color ArrowColor) { int err; string ArrowName=Trend+" "+TimeToStr(ArrowTime); if(ObjectFind(ArrowName)!=-1) ObjectDelete(ArrowName); if(!ObjectCreate(ArrowName,OBJ_ARROW,0,ArrowTime,Price)) { err=GetLastError(); Print("error: can't create Arrow! code #",err); return; } else { ObjectSet(ArrowName,OBJPROP_ARROWCODE,ArrowCode); ObjectSet(ArrowName,OBJPROP_COLOR,ArrowColor); WindowRedraw(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void SetLine(datetime LineTime,double Price,string Trend,color LineColor) { int err; string LineName=Trend+" "+TimeToStr(LineTime); if(ObjectFind(LineName)!=-1) ObjectDelete(LineName); if(!ObjectCreate(LineName,OBJ_VLINE,0,LineTime,Price)) { err=GetLastError(); Print("error: can't create Line! code #",err); return; } else { ObjectSet(LineName,OBJPROP_STYLE,0); ObjectSet(LineName,OBJPROP_COLOR,LineColor); ObjectSet(LineName,OBJPROP_WIDTH,1); ObjectSet(LineName,OBJPROP_BACK,true); WindowRedraw(); } } //Определение данных ближайшей сессии //Входные данные: //b - текущий бар //Результат: //STS - Начало ближайшей сессии //STE - Конец ближайшей сессии void Points(int b) { datetime Ses[][4]; ArrayResize(Ses,3*(Repeats+1)+1); ArrayInitialize(Ses,0); int t1=TimeHour(StrToTime(StartTime))*3600+TimeMinute(StrToTime(StartTime))*60; if(EndTime1){K=1;} if(K<0){K=0;} if(t2>(t1+24*3600)) {t2=(t1+24*3600);} if(t2>(t1+12*3600) && Repeats>0) {Repeats=0;} //if ((t1+p*(Repeats+1))>(24*3600)) {Repeats=MathFloor((24*3600)/p)-1;} // int ck=0; int s=0; for(int c1=0; c1<=48; c1=c1+24) { for(int c2=0; c2<=Repeats; c2++) { ck=ck+1; Ses[ck][1]= td+(t1 + c1*3600 + c2*p); Ses[ck][2]= td+(t2 + c1*3600 + c2*p); Ses[ck][3]= TFSet(td+(t1 + K*p + c1*3600 + c2*p)); if(!SummerTime(Ses[ck][1])) {Ses[ck][1]=Ses[ck][1]+WinterTimeChange*3600;} if(!SummerTime(Ses[ck][2])) {Ses[ck][2]=Ses[ck][2]+WinterTimeChange*3600;} if(!SummerTime(Ses[ck][3])) {Ses[ck][3]=TFSet(WinterTimeChange*3600+td+(t1+K*p+c1*3600+c2*p));} if(s==0) { if(Time[b]<=(Ses[ck][3]+Pause*Period()*60) && Ses[ck][3]>CRE) {s=ck; break;} } } if(s>0) {break;} } STS=Ses[s][1]; STE=Ses[s][2]; CRT=Ses[s][3]; if(CRT>0 && CRT==CRE) {s=0; CRT=0; STS=0; STE=0;} if(s>0){s=1;} return(s); } //Определение времени в заданной точке по значению коэффициента //Входные данные: //Коэффициент //STS - Начало ближайшей сессии //STE - Конец ближайшей сессии //CRT - время основной точки появления сигнала //Результат: //Точное значение времени по значению коэффициента datetime KPoint(double k,int pos) { datetime KT = TFSet(STS+((STE-STS)*k)); datetime CT = CRT - KT; int BCT=(CT/60)/Period(); return(iTime(Symbol(),0,BCT+iBarShift(Symbol(),Period(),Time[pos],false))); } //Округление значения времени под текущий таймфрейм datetime TFSet(datetime k){return((Period()*60*(MathFloor(k/60/Period()))));} //Определение направления интервала int Interval(datetime k1,datetime k2,datetime k,string i) { int n; double h1,l1,h2,l2,dd,du; //Коррекция данных if(k2k) {k1=k;} if(k2>k) {k2=k;} if(Method==0 || Method>4) { // int t1=iBarShift(Symbol(),Period(),k1,false); int t2=iBarShift(Symbol(),Period(),k2,false); h1 = iOpen(Symbol(),Period(),t1); h2 = iOpen(Symbol(),Period(),t2); du = h2-h1; if(Delta>0){if(MathAbs(du)0) {n=1;} else {n=-1;} } if(Method==1) { // t1=iBarShift(Symbol(),Period(),k1,false); t2=iBarShift(Symbol(),Period(),k2,false); h1 = iHigh(Symbol(),Period(),t1); h2 = iHigh(Symbol(),Period(),t2); l1 = iLow(Symbol(),Period(),t1); l2 = iLow(Symbol(),Period(),t2); dd = h1-l2; du = h2-l1; if(Delta>0) { if(dudd) {n=1;} else {n=-1;} } if(Method==2) { // t1=iBarShift(Symbol(),Period(),k1,false); t2=iBarShift(Symbol(),Period(),k2,false); h1=High[iHighest(NULL,0,MODE_HIGH,(t1-t2)+1,t2)]; l1=Low[iLowest(NULL,0,MODE_LOW,(t1-t2)+1,t2)]; du = h1-Open[t1]; dd = Open[t1]-l1; if(Delta>0) { if(dudd) {n=1;} else {n=-1;} } if(Method==3) { // t1=iBarShift(Symbol(),Period(),k1,false); t2=iBarShift(Symbol(),Period(),k2,false); h1=High[iHighest(NULL,0,MODE_HIGH,(t1-t2)+1,t2)]; l1=Low[iLowest(NULL,0,MODE_LOW,(t1-t2)+1,t2)]; du = h1-Low[t1]; dd = High[t1]-l1; if(Delta>0) { if(dudd) {n=1;} else {n=-1;} } if(Method==4) { // t1=iBarShift(Symbol(),Period(),k1,false); t2=iBarShift(Symbol(),Period(),k2,false); int h3=iHighest(NULL,0,MODE_HIGH,(t1-t2)+1,t2); int l3=iLowest(NULL,0,MODE_LOW,(t1-t2)+1,t2); if(Delta>0) { if(High[h3]-Low[l3]h3) {n=1;} else {n=-1;} } if(((P2==false && P3==false) || (P1==false && P3==false)) || (P1==false && P2==false)) {i=""; string ipr="";} else {ipr=" ";} if(Drawing==true) { if(n==0) { string on=i+ipr+"Trend: ~ Point: "+TimeToStr(k); ObjectCreate(on,OBJ_TREND,0,Time[t2],Close[t2],Time[t1],Open[t1]); ObjectSet(on,OBJPROP_COLOR,White); ObjectSet(on,OBJPROP_WIDTH,1); ObjectSet(on,OBJPROP_STYLE,STYLE_SOLID); ObjectSet(on,OBJPROP_RAY,false); } if(n==1) { on=i+ipr+"Trend: UP Point: "+TimeToStr(k); ObjectCreate(on,OBJ_TREND,0,Time[t2],High[t2],Time[t1],Low[t1]); ObjectSet(on,OBJPROP_COLOR,LimeGreen); ObjectSet(on,OBJPROP_WIDTH,1); ObjectSet(on,OBJPROP_STYLE,STYLE_SOLID); ObjectSet(on,OBJPROP_RAY,false); } if(n==-1) { on=i+ipr+"Trend: DN Point: "+TimeToStr(k); ObjectCreate(on,OBJ_TREND,0,Time[t2],Low[t2],Time[t1],High[t1]); ObjectSet(on,OBJPROP_COLOR,Red); ObjectSet(on,OBJPROP_WIDTH,1); ObjectSet(on,OBJPROP_STYLE,STYLE_SOLID); ObjectSet(on,OBJPROP_RAY,false); } } return(n); } //Определение направления в заданной точке по направлению контрольных отрезков //Время заданной точки CRT int CRPoint() { double Mas[4][5]; ArrayInitialize(Mas,0); Mas[1][1]=P1; Mas[1][2]=KT1; Mas[1][3]=KT2; Mas[1][4]=N1; Mas[2][1]=P2; Mas[2][2]=KT3; Mas[2][3]=KT4; Mas[2][4]=N2; Mas[3][1]=P3; Mas[3][2]=KT5; Mas[3][3]=KT6; Mas[3][4]=N3; for(int i=1;i<=3;i++) { if(Mas[i][1]==true) { int z=Interval(Mas[i][2],Mas[i][3],CRT,i+"P"); if(Mas[i][4]==true) {z=z*(-1);} Mas[i][0]=z; if(z==0){Mas[0][0]=2;} if(Mas[0][0]==0) {Mas[0][0]=z;} else {if(Mas[0][0]!=z) {Mas[0][0]=2;}} } } if(Mas[0][0]==2) {Mas[0][0]=0;} return(Mas[0][0]); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void TRE(int pos) { if(CRT>0) { if(Time[pos]>=CRT && Time[pos]<=(CRT+Pause*Period()*60)) { PUP=0; PDN=0; UP=0; DN=0; E=0; KT1 = KPoint(K1,pos); KT2 = KPoint(K2,pos); KT3 = KPoint(K3,pos); KT4 = KPoint(K4,pos); KT5 = KPoint(K5,pos); KT6 = KPoint(K6,pos); int nt=CRPoint(); if(nt>0){PUP=Open[pos];} if(nt<0){PDN=Open[pos];} if(nt==0){E=Open[pos];} CRE=CRT; CRT=0; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool SummerTime(datetime dt) { int i; if(TimeMonth(dt)>=11 || TimeMonth(dt)<=2) {return(false);} if(TimeMonth(dt)>=4 && TimeMonth(dt)<= 9) {return(true);} datetime tSeek; if(TimeMonth(dt)==10) { if(TimeDay(dt)>=20) { tSeek= StrToTime(StringTrimRight(StringTrimLeft(DoubleToStr(TimeYear(dt),0)))+".10.31 02:00"); for(i=31; i>=20; i--) { if(TimeDayOfWeek(tSeek)==0) {break;} tSeek=tSeek-86400; } if(dt>=tSeek) {return(false);} } return(true); } if(TimeMonth(dt)==3) { if(TimeDay(dt)>=20) { tSeek = StrToTime(StringTrimRight(StringTrimLeft(DoubleToStr(TimeYear(dt),0)))+".03.31 03:00"); for(i = 31; i >= 20; i-- ) { if(TimeDayOfWeek(tSeek)==0) {break;} tSeek=tSeek-86400; } if(dt>=tSeek) {return(true);} } return(false); } } //+------------------------------------------------------------------+