FiboRetracement3D_001
Download scriptThis script is designed as a technical analysis tool for the MetaTrader trading platform. Its primary purpose is to automatically identify significant price structural points—specifically high and low "fractals"—and use them to plot automated Fibonacci Retracement levels on a price chart.
Core Logic and Workflow
The logic operates by scanning historical price data to establish the "boundaries" of current market movements. Here is the step-by-step breakdown of how the script processes this information:
1. Identification of Structural Peaks and Valleys
Instead of simply looking at every high or low price, the script looks for Fractals. A fractal is a point where the price reaches a local maximum or minimum relative to its neighbors (based on user-defined left and right "look-back" periods).
- Upper Boundaries: It identifies the highest points in recent price action.
- Lower Boundaries: It identifies the lowest points in recent price action.
2. Dynamic Level Tracking
The script maintains a running record of these upper and lower levels. If a new fractal is formed that is higher than the previous peak (for the top) or lower than the previous valley (for the bottom), the script updates its reference point. It also includes a "filter" mechanism to ensure that minor price fluctuations don't trigger unnecessary updates, focusing instead on meaningful structural shifts.
3. Automatic Fibonacci Mapping
Once the most relevant peaks and valleys are identified, the script performs three main actions:
- Primary Trend Mapping: It identifies the primary start and end points of a major price move to draw a standard Fibonacci retracement.
- Secondary Trend Mapping: It looks for a subsequent movement from those points to draw a secondary Fibonacci level.
- Calculation of Sub-Levels: While the script tracks several internal price ratios (such as 1/2, 1/3, 2/3, etc.), its primary visual output is the automatic creation and updating of two distinct Fibonacci objects on your chart.
4. Visual Representation
The logic ensures that as new price data arrives, the Fibonacci objects are not just redrawn; they are moved and resized dynamically.
- Object 1: Represents the main retracement based on the most significant recent high/low move.
- Object 2: Represents a secondary retracement based on the subsequent price action.
Summary for the User
In plain terms, this script removes the manual work of "guessing" where to put your Fibonacci levels. It automatically scans the history of the candles, finds the most significant turning points (fractals), and draws the retracement lines for you. As the market moves and creates new highs or lows, the script recalculates these points in real-time to keep your technical analysis up to date.
//+------------------------------------------------------------------+
//| FiboRetracement.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1 Black
#property indicator_color2 Black
#property indicator_color3 Black
#property indicator_color4 Black
#property indicator_color5 Black
#property indicator_color6 Black
#property indicator_color7 Black
#property indicator_color8 Black
//---- input parameters
extern int TimeFrame=60;
extern int nLeft=50;
extern int nRight=50;
extern int filter=10;
extern color Fibo1Color=DodgerBlue;
extern int Fibo1Width=1;
extern color Fibo2Color=Yellow;
extern int Fibo2Width=1;
//---- buffers
double UpBuffer[];
double DnBuffer[];
double f_2[];
double f_3[];
double f_4[];
double f_5[];
double f_6[];
string fibo,fibo2;
//----
int draw_begin1=0, draw_begin2=0, d_b3=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
double nfUp;
//---- indicators
IndicatorBuffers(8);
SetIndexStyle(0,DRAW_LINE,0,3);
SetIndexStyle(1,DRAW_LINE,0,3);
SetIndexStyle(2,DRAW_LINE,2);
SetIndexStyle(3,DRAW_LINE,2);
SetIndexStyle(4,DRAW_LINE,2);
SetIndexStyle(5,DRAW_LINE,2);
SetIndexStyle(6,DRAW_LINE,2);
SetIndexBuffer(0,UpBuffer);
SetIndexBuffer(1,DnBuffer);
SetIndexBuffer(2,f_2);
SetIndexBuffer(3,f_3);
SetIndexBuffer(4,f_4);
SetIndexBuffer(5,f_5);
SetIndexBuffer(6,f_6);
fibo="Fibo "+TimeFrame;
fibo2="Fibo2 "+TimeFrame;
//---- name for DataWindow and indicator subwindow label
string short_name; //îáÿâëåíèå ïåðåìåííîé short_name òèïà "ñòðîêîâûé"
//ïåðåìåííîé short_name ïðèñâàèâàåì ñòðîêîâîå çíà÷åíèå ðàâíîå âûðàæåíèþ
short_name="rvmFractalsLevel("+nLeft+","+nRight+","+filter+")";
IndicatorShortName(short_name); //äëÿ îòîáðàæåíèÿ íà ãðàôèêå ïðèñâîèì èíäèêàòîðó êðàòêîå
//íàèìåíîâàíèå
//äëÿ îòîáðàæåíèÿ íà ãðàôèêå ïðèñâîèì ìåòêå îòîáðàæàþùåé çíà÷åíèÿ 0 áóôåðà èìÿ Up Channel
SetIndexLabel(0,"Up Level ("+nLeft+","+nRight+","+filter+")");
//äëÿ îòîáðàæåíèÿ íà ãðàôèêå ïðèñâîèì ìåòêå îòîáðàæàþùåé çíà÷åíèÿ 1 áóôåðà èìÿ Down Channel
SetIndexLabel(1,"Down Level ("+nLeft+","+nRight+","+filter+")");
SetIndexLabel(2,"f_2 ("+nLeft+","+nRight+","+filter+")");
SetIndexLabel(3,"f_3 ("+nLeft+","+nRight+","+filter+")");
SetIndexLabel(4,"f_4 ("+nLeft+","+nRight+","+filter+")");
SetIndexLabel(5,"f_5 ("+nLeft+","+nRight+","+filter+")");
SetIndexLabel(6,"f_6 ("+nLeft+","+nRight+","+filter+")");
//---- Çäåñü îïðåäåëèì íà÷àëüíûå òî÷êè äëÿ ïðîðèñîâêè èíäèêàòîðà
int n,k,i,Range=nLeft+nRight+1;
//ïåðåáåðåì ñâå÷êè îò (âñåãî ñâå÷åê ìèíóñ ìèíèìóì ñâå÷åê ñëåâà) äî (ìèíèìóì ñâå÷åê ñïðàâà)
for(n=iBars(NULL,TimeFrame)-1-nLeft;n>=nRight;n--)
{
//âåðõíèå ôðàêòàëû
//åñëè íà÷àëî îòðèñîâêè âåðõíåãî óðîâíÿ íå îïðåäåëåíî
if(draw_begin1==0)
{
//òåêóùàÿ ñâå÷à ìàêñèìóì íà ëîêàëüíîì ïðîìåæóòêå?
if(iHigh(NULL,TimeFrame,n)>=iLow(NULL,TimeFrame,Highest(NULL,TimeFrame,MODE_HIGH,Range,n-nRight)))
{
int fRange=nvnLeft(n,nLeft)+nvnRight(n,nRight)+1;
//åñëè îíà æå - ôðàêòàë
if(iHigh(NULL,TimeFrame,n)>=iHigh(NULL,TimeFrame,Highest(NULL,TimeFrame,MODE_HIGH,fRange,n-nvnRight(n,nRight))))
{
draw_begin1=iBars(NULL,TimeFrame)-n;//íà÷àëî îòðèñîâêè âåðõíåãî óðîâíÿ îïðåäåëåíî
for(i=iBars(NULL,TimeFrame)-1;i>draw_begin1;i--)
{
UpBuffer[i]=iHigh(NULL,TimeFrame,iBars(NULL,TimeFrame)-draw_begin1);
}
}
}//êîíåö äåéñòâèé åñëè if(iHigh(NULL,TimeFrame,n)>=iHigh(NULL,TimeFrame,Highest(NULL,TimeFrame,MODE_HIGH,Range,n-nRight))=èñòèíà
}//êîíåö óñëîâèÿ if(draw_begin1==0)
//íèæíèå ôðàêòàëû
//åñëè íà÷àëî îòðèñîâêè íèæíåãî óðîâíÿ íå îïðåäåëåíî
if(draw_begin2==0)
{
//òåêóùàÿ ñâå÷à ìèíèìóì íà ëîêàëüíîì ïðîìåæóòêå?
if(iLow(NULL,TimeFrame,n)<=iLow(NULL,TimeFrame,Lowest(NULL,TimeFrame,MODE_LOW,Range,n-nRight)))
{
fRange=nvnLeft(n,nLeft)+nvnRight(n,nRight)+1;
//åñëè îíà æå - ôðàêòàë
if(iLow(NULL,TimeFrame,n)<=iLow(NULL,TimeFrame,Lowest(NULL,TimeFrame,MODE_HIGH,fRange,n-nvnRight(n,nRight))))
{
draw_begin2=iBars(NULL,TimeFrame)-n;//íà÷àëî îòðèñîâêè íèæíåãî óðîâíÿ îïðåäåëåíî
for(i=iBars(NULL,TimeFrame)-1;i>draw_begin2;i--)
{
DnBuffer[i]=iLow(NULL,TimeFrame,iBars(NULL,TimeFrame)-draw_begin2);
}
}
}//êîíåö óñëîâèÿ if(iLow(NULL,TimeFrame,n)<=iLow(NULL,TimeFrame,Lowest(NULL,TimeFrame,MODE_LOW,Range,n-nRight)))=true
}//êîíåö óñëîâèÿ if(draw_begin2==0)
//åñëè îáà íà÷àëà îòðèñîâêè óðîâíåé îïðåäåëåíû, âûõîäèì èç öèêëà for(n=iBars(NULL,TimeFrame)-1-nLeft;n>=nRight;n--)
if(draw_begin1>0&&draw_begin2>0) break;
}//êîíåö öèêëà for(n=iBars(NULL,TimeFrame)-1-nLeft;n>=nRight;n--)
//----
if(draw_begin1>draw_begin2)
{
d_b3=draw_begin1;
}
else
{
d_b3=draw_begin2;
}
SetIndexDrawBegin(0,draw_begin1); //óñòàíîâêà íà÷àëüíîé òî÷êè ïðîðèñîâêè äëÿ 0 áóôåðà
SetIndexDrawBegin(1,draw_begin2); //óñòàíîâêà íà÷àëüíîé òî÷êè ïðîðèñîâêè äëÿ 1 áóôåðà
SetIndexDrawBegin(2,d_b3);
SetIndexDrawBegin(3,d_b3);
SetIndexDrawBegin(4,d_b3);
SetIndexDrawBegin(5,d_b3);
SetIndexDrawBegin(6,d_b3);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
double UpStage=0.0,DnStage=0.0;
int i,j,fRange,Range=nLeft+nRight+1;
int counted_bars=IndicatorCounted();
//----
//ïåðåáèðàåì ñâå÷êè îò (iBars(NULL,TimeFrame)-counted_iBars(NULL,TimeFrame)-nLeft) äî (nRight) âêëþ÷èòåëüíî
for(i=iBars(NULL,TimeFrame)-1-counted_bars-nLeft;i>=nRight;i--)
{
//åñëè ñâå÷à ëîêàëüíûé ìàêñèìóì
if(iHigh(NULL,TimeFrame,i)>=iHigh(NULL,TimeFrame,Highest(NULL,TimeFrame,MODE_HIGH,Range,i-nRight)))
{
//Print(TimeToStr(iTime(NULL,TimeFrame,i)), "******Ëîêàëüíûé ìàêñèìóì");
fRange=nvnLeft(i,nLeft)+nvnRight(i,nRight)+1;
//åñëè îíà æå - ôðàêòàë
if(iHigh(NULL,TimeFrame,i)>=iHigh(NULL,TimeFrame,Highest(NULL,TimeFrame,MODE_HIGH,fRange,i-nvnRight(i,nRight))))
{
UpStage=iHigh(NULL,TimeFrame,i);
//Print(" îíà æå ôðàêòàë");
}
else
{
if(iHigh(NULL,TimeFrame,i)<=UpBuffer[i+1])
{
UpStage=UpBuffer[i+1];
//Print(" íå ôðàêòàë, íî íèæå ïðåäûäóùåãî óðîâíÿ");
}
else
{
UpStage=nfUp(i);
//Print(" íå ôðàêòàë, âûøå ïðåäûäóùåãî óðîâíÿ");
}
}
}
else
{
//Print(TimeToStr(iTime(NULL,TimeFrame,i)), "******íå ëîêàëüíûé ìàêñèìóì");
if(iHigh(NULL,TimeFrame,i)<=UpBuffer[i+1])
{
UpStage=UpBuffer[i+1];
//Print(" íèæå ïðåäûäóùåãî óðîâíÿ");
}
else
{
UpStage=nfUp(i);
//Print(" âûøå ïðåäûäóùåãî óðîâíÿ");
}
}
//åñëè ñâå÷à ëîêàëüíûé ìèíèìóì
if(iLow(NULL,TimeFrame,i)<=iLow(NULL,TimeFrame,Lowest(NULL,TimeFrame,MODE_LOW,Range,i-nRight)))
{
fRange=nvnLeft(i,nLeft)+nvnRight(i,nRight)+1;
//Print(TimeToStr(iTime(NULL,TimeFrame,i))," ",nvnLeft(i,nLeft)," ",nvnRight(i,nRight)+1);
//åñëè îíà æå - ôðàêòàë
if(iLow(NULL,TimeFrame,i)<=iLow(NULL,TimeFrame,Lowest(NULL,TimeFrame,MODE_HIGH,fRange,i-nvnRight(i,nRight))))
{
DnStage=iLow(NULL,TimeFrame,i);
}
else
{
if(iLow(NULL,TimeFrame,i)>=DnBuffer[i+1])
{
DnStage=DnBuffer[i+1];
}
else
{
DnStage=nfDn(i);
}
}
}
else
{
if(iLow(NULL,TimeFrame,i)>=DnBuffer[i+1])
{
DnStage=DnBuffer[i+1];
}
else
{
DnStage=nfDn(i);
}
}
UpBuffer[i]=UpStage;
DnBuffer[i]=DnStage;
//---- ðàñ÷åò îñòàëüíûõ áóôåðîâ
f_2[i]=NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])/6,4);
f_3[i]=NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])/3,4);
f_4[i]=NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])/2,4);
f_5[i]=NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])*2/3,4);
f_6[i]=NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])*5/6,4);
}//êîíåö öèêëà for(i=iBars(NULL,TimeFrame)-counted_bars-nLeft;i>=nRight;i--)
for(i=nRight-1;i>=0;i--)
{
if(iHigh(NULL,TimeFrame,i)<=UpBuffer[i+1])
{
UpStage=UpBuffer[i+1];
}
else
{
UpStage=nfUp(i);
}
if(iLow(NULL,TimeFrame,i)>=DnBuffer[i+1])
{
DnStage=DnBuffer[i+1];
}
else
{
DnStage=nfDn(i);
}
UpBuffer[i]=UpStage;
DnBuffer[i]=DnStage;
//---- ðàñ÷åò îñòàëüíûõ áóôåðîâ
f_2[i] =NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])/6,4);
f_3[i] =NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])/3,4);
f_4[i] =NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])/2,4);
f_5[i] =NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])*2/3,4);
f_6[i] =NormalizeDouble(DnBuffer[i]+(UpBuffer[i]-DnBuffer[i])*5/6,4);
}
//---- ïîñòðîåíèå âååðà Ôèáîíà÷÷è
double LastUp, LastDn, st_h, st_l, st_3, y1, y2, y3;
int tmp, x1=0, x2=0, x3=0, cb, dn_x, up_x;
LastDn=DnBuffer[0];
for(cb=1;cb<=iBars(NULL,TimeFrame)-1;cb++)
{
if(tmp!=1 && LastDn>DnBuffer[cb])
{
tmp=1;
continue;
}
if(tmp==1 && DnBuffer[cb]>DnBuffer[cb-1])
{
tmp=0;
dn_x=cb-1;
break;
}
}
LastUp=UpBuffer[0];
for(cb=1;cb<=iBars(NULL,TimeFrame)-1;cb++)
{
if(tmp!=1 && LastUp<UpBuffer[cb])
{
tmp=1;
continue;
}
if(tmp==1 && UpBuffer[cb]<UpBuffer[cb-1])
{
tmp=0;
up_x=cb-1;
break;
}
}
st_h=iHigh(NULL,TimeFrame,Highest(NULL,TimeFrame,MODE_HIGH,MathMax(dn_x,up_x),0));
st_l=iLow(NULL,TimeFrame,Lowest(NULL,TimeFrame,MODE_LOW,MathMax(dn_x,up_x),0));
//y1=MathMin(iOpen(NULL,TimeFrame,x1),)x1));
//y1=MathMax(iClose(NULL,TimeFrame,x1),iClose(NULL,TimeFrame,x1));
for(cb=MathMax(dn_x,up_x)-1;cb>=0;cb--)
{
if(iHigh(NULL,TimeFrame,cb)==st_h || iLow(NULL,TimeFrame,cb)==st_l)
{
if(iHigh(NULL,TimeFrame,cb)==st_h && (x1==0 || x2==0) )
{
if(x1==0)
{
x1=cb;
y1=iHigh(NULL,TimeFrame,x1);
continue;
}
else
{
x2=cb;
y2=iHigh(NULL,TimeFrame,x2);
break;
}
}
else
{
if(x1==0)
{
x1=cb;
y1=iLow(NULL,TimeFrame,x1);
continue;
}
else
{
x2=cb;
y2=iLow(NULL,TimeFrame,x2);
break;
}
}
}
}
//Print("x1="+x1+" y1="+y1+" x2="+x2+" y2="+y2);
if( ObjectFind(fibo)!=-1 )
{
ObjectSet(fibo,OBJPROP_TIME1,iTime(NULL,TimeFrame,x1));
ObjectSet(fibo,OBJPROP_PRICE1,y1);
ObjectSet(fibo,OBJPROP_TIME2,iTime(NULL,TimeFrame,x2));
ObjectSet(fibo,OBJPROP_PRICE2,y2);
}
else
{
ObjectCreate(fibo,OBJ_FIBO,0,iTime(NULL,TimeFrame,x1),y1,iTime(NULL,TimeFrame,x2),y2);
ObjectSet(fibo,OBJPROP_COLOR,Fibo1Color);
ObjectSet(fibo,OBJPROP_STYLE,STYLE_DOT);
ObjectSet(fibo,OBJPROP_WIDTH,Fibo1Width);
}
//----- à ýòî îòðèñîâêà âñïîìîãàòåëüíîãî âååðà ôèáîíà÷÷è
if(y2>y1)
{
st_3=iLow(NULL,TimeFrame,Lowest(NULL,TimeFrame,MODE_LOW,x2,0));
}
else
{
st_3=iHigh(NULL,TimeFrame,Highest(NULL,TimeFrame,MODE_HIGH,x2,0));
}
for(cb=0;cb<x2;cb++)
{
if(y2>y1 && iLow(NULL,TimeFrame,cb)==st_3)
{
x3=cb;
y3=iLow(NULL,TimeFrame,cb);
break;
}
else
{
if(y2<y1 && iHigh(NULL,TimeFrame,cb)==st_3)
{
x3=cb;
y3=iHigh(NULL,TimeFrame,cb);
break;
}
}
}
if( ObjectFind(fibo2)!=-1 )
{
ObjectSet(fibo2,OBJPROP_TIME1,iTime(NULL,TimeFrame,x2));
ObjectSet(fibo2,OBJPROP_PRICE1,y2);
ObjectSet(fibo2,OBJPROP_TIME2,iTime(NULL,TimeFrame,x3));
ObjectSet(fibo2,OBJPROP_PRICE2,y3);
}
else
{
ObjectCreate(fibo2,OBJ_FIBO,0,iTime(NULL,TimeFrame,x2),y2,iTime(NULL,TimeFrame,x3),y3);
ObjectSet(fibo2,OBJPROP_COLOR,Fibo2Color);
ObjectSet(fibo2,OBJPROP_STYLE,STYLE_DOT);
ObjectSet(fibo2,OBJPROP_WIDTH,Fibo2Width);
}
//----
return(0);
}
double nfUp(int i)
{
int l,flag=0;
double Price=0.0;
for(l=i+1;l<Bars-draw_begin1-1;l++)
{
if(filter>0)
{
if(iClose(NULL,TimeFrame,i)<=UpBuffer[l]+(UpBuffer[l]-DnBuffer[l])*filter/100)
{
Price=UpBuffer[l];
flag=1;
//Print(TimeToStr(iTime(NULL,TimeFrame,i))," ",l," ",Bars," ",Price," ",UpBuffer[l));
}
}
else
{
if(iHigh(NULL,TimeFrame,i)<=UpBuffer[l])
{
Price=UpBuffer[l];
flag=1;
}
}
if(Price>0) break;
}
if(flag==0) Price=iHigh(NULL,TimeFrame,i);
return(Price);
}
double nfDn(int i)
{
int l,flag=0;
double Price=0.0;
for(l=i+1;l<Bars-draw_begin2-1;l++)
{
if(filter>0)
{
if(iClose(NULL,TimeFrame,i)>=DnBuffer[l]-(UpBuffer[l]-DnBuffer[l])*filter/100)
{
Price=DnBuffer[l];
flag=1;
}
}
else
{
if(iLow(NULL,TimeFrame,i)>=DnBuffer[l])
{
Price=DnBuffer[l];
flag=1;
}
}
if(Price>0) break;
}
if(flag==0) Price=iLow(NULL,TimeFrame,i);
return(Price);
}
int nvnLeft(int i,int n)
{
int k=0,l;
for(l=i+1;l<=iBars(NULL,TimeFrame)-1;l++)
{
if(iHigh(NULL,TimeFrame,l)<iHigh(NULL,TimeFrame,l+1)&&iLow(NULL,TimeFrame,l)>iLow(NULL,TimeFrame,l+1)) continue;
k++;
if(k==n)
{
k=l-i;
break;
}
}
return(k);
}
int nvnRight(int i,int n)
{
int k=0,l;
for(l=i-1;l>=0;l--)
{
if(iHigh(NULL,TimeFrame,l)<iHigh(NULL,TimeFrame,l+1)&&iLow(NULL,TimeFrame,l)>iOpen(NULL,TimeFrame,l+1)) continue;
k++;
if(k==n)
{
k=i-l;
break;
}
}
return(k);
}
int deinit()
{
ObjectDelete(fibo);
ObjectDelete(fibo2);
return(0);
}
Comments