olyakish_fractals_03
Download scriptThis script is a specialized technical analysis tool designed to identify and categorize market "fractals" (turning points in price action) by comparing their relative strength, volume, and momentum. Instead of simply marking every peak or valley, it uses a logical filtering system to distinguish between different types of price movements.
Core Logic and Classification
The script scans the historical price data for fractal points. When it identifies a new high or low point, it looks back through history to find the previous opposite turning point. It then compares these two points based on two primary metrics: Volume and Money Flow Index (MFI).
Based on this comparison, the script categorizes every fractal into one of four distinct types, each represented by a specific color on your chart:
- Green Fractals: Occur when the current price movement shows both higher volume and higher momentum (MFI) than the previous move.
- Red Fractals: Occur when the current price movement shows significantly higher volume but lower momentum (MFI) compared to the previous move.
- Blue Fractals: Occur when the current price movement shows lower volume but higher momentum (MFI) compared to the previous move.
- Saddle Brown Fractals: Occur when both the volume and the momentum (MFI) are lower than those of the previous move.
Dynamic Visual Elements
Beyond just marking these points with arrows, the script includes a dynamic drawing system to help visualize trends:
- Trend Lines: The tool automatically generates and updates trend lines based on these categorized fractals. These lines help provide a visual representation of the current price structure.
- Historical Tracking: There is an option to display "Previous" trend lines (shown as dashed lines). This allows traders to see where the previous structural boundaries were located before they were updated by newer data.
- Visual Updates: As new price data arrives, the script continuously recalculates these positions, moving the trend lines in real-time to reflect the most recent market behavior while maintaining a history of the last few significant levels.
Summary for the User
Essentially, this script filters out "noise" by only highlighting fractals that meet specific volume and momentum criteria. It tells you not just where the price turned, but how it turned—whether with aggressive strength, exhausted volume, or fading momentum—allowing for a more nuanced view of market dynamics than standard fractal indicators provide.
//+------------------------------------------------------------------+
//| olyakish_fractals_03.mq4 |
//| Copyright © -2007, olyakish |
//| plutonia-dmb#yandex.ru |
//| v02 |
//| Äîáàâëåí ïðîöåíò äëÿ îòñåèâàíèÿ ôðàêòàëîâ |
//| v03 |
//| Ðèñóåò ëèíèè |
//+------------------------------------------------------------------+
#property copyright "olyakish"
#property link ""
//----
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Green // Çåëåíûé ôðàêòàë
#property indicator_color2 Red // Ïðèñåäàþùèé
#property indicator_color3 SaddleBrown // Óâÿäàþùèé
#property indicator_color4 Blue // Ôàëüøèâûé
//----
extern int Pips = 15;
extern int ShiftBars = 150;
extern string rem1 = "Ïðîöåíò äëÿ îòñåèâàíèÿ ïî îáúåìó";
extern int Percent = 110;
extern string rem2 = "Ðèñîâàòü ïðåäûäóùèå ëèíèè?";
extern bool UseOldLine = true;
double ExtLimeBuffer[];
double ExtRedBuffer[];
double ExtSaddleBrownBuffer[];
double ExtBlueBuffer[];
int i, j;
double a_Fractal[2]; // 0- ïîñëåäíèé 1-ïðåäûäóùèé
double a_MFI[2]; // 0- ïîñëåäíèé 1-ïðåäûäóùèé
double a_Volume[2]; // 0- ïîñëåäíèé 1-ïðåäûäóùèé
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int init()
{
//----
SetIndexBuffer(0, ExtLimeBuffer);
SetIndexBuffer(1, ExtRedBuffer);
SetIndexBuffer(2, ExtSaddleBrownBuffer);
SetIndexBuffer(3, ExtBlueBuffer);
//----
SetIndexStyle(0, DRAW_ARROW, 0, 2);
SetIndexStyle(1, DRAW_ARROW, 0, 2);
SetIndexStyle(2, DRAW_ARROW, 0, 2);
SetIndexStyle(3, DRAW_ARROW, 0, 2);
SetIndexArrow(0, 177);
SetIndexArrow(1, 177);
SetIndexArrow(2, 177);
SetIndexArrow(3, 177);
//----
SetIndexLabel(0, "Çåëåíûé ôðàêòàë");
SetIndexLabel(1, "Ïðèñåäàþùèé ôðàêòàë");
SetIndexLabel(2, "Óâÿäàþùèé ôðàêòàë");
SetIndexLabel(3, "Ôàëüøèâûé ôðàêòàë");
//----
ObjectCreate("Up", OBJ_TREND, 0, iTime(NULL, 0, 2), High[2],
iTime(NULL, 0, 1), High[1], 0, 0);
ObjectSet("Up", OBJPROP_COLOR, Blue);
ObjectSet("Up", OBJPROP_RAY, true);
ObjectSet("Up", OBJPROP_BACK, 1);
ObjectCreate("Down", OBJ_TREND, 0, iTime(NULL, 0, 2), Low[2],
iTime(NULL, 0, 1), Low[1], 0, 0);
ObjectSet("Down", OBJPROP_COLOR, Tomato);
ObjectSet("Down", OBJPROP_RAY, true);
ObjectSet("Down", OBJPROP_BACK, 1);
if(UseOldLine)
{
ObjectCreate("Up_Prev", OBJ_TREND, 0, iTime(NULL, 0, 2),
High[2], iTime(NULL, 0, 1), High[1],0,0);
ObjectSet("Up_Prev", OBJPROP_COLOR, Blue);
ObjectSet("Up_Prev", OBJPROP_RAY, true);
ObjectSet("Up_Prev", OBJPROP_STYLE, STYLE_DASH);
ObjectSet("Up_Prev", OBJPROP_BACK, 1);
ObjectCreate("Down_Prev", OBJ_TREND, 0, iTime(NULL, 0, 2),
Low[2], iTime(NULL, 0, 1), Low[1], 0, 0);
ObjectSet("Down_Prev", OBJPROP_COLOR, Tomato);
ObjectSet("Down_Prev", OBJPROP_RAY, true);
ObjectSet("Down_Prev", OBJPROP_STYLE, STYLE_DASH);
ObjectSet("Down_Prev", OBJPROP_BACK, 1);
}
//----
Comment("olyakish_fractals_03");
//----
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int deinit()
{
ObjectDelete("Up");
ObjectDelete("Down");
if(UseOldLine)
{
ObjectDelete("Up_Prev");
ObjectDelete("Down_Prev");
}
//----
Comment("");
//----
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
int n = 3;
while(ExtLimeBuffer[n] != NULL || ExtRedBuffer[n] != NULL ||
ExtSaddleBrownBuffer[n] != NULL || ExtBlueBuffer[n] != NULL)
{
if(n > ShiftBars)
{
n = ShiftBars;
break;
}
n++;
}
for(int i = n + 20; i >= 3; i--)
{
//-- âåðõíèå ôðàêòàëû
ArrayInitialize(a_Fractal, 0);
ArrayInitialize(a_MFI, 0);
ArrayInitialize(a_Volume, 0);
// íà i áàðå åñòü ôðàêòàë ââåðõ
if(iFractals(NULL, 0, MODE_UPPER, i) != 0)
{
// öåíà íà ôðàêòàëå
a_Fractal[0] = iFractals(NULL, 0, MODE_UPPER, i);
// îáúåì
a_Volume[0] = Volume[i] + Volume[i+1] + Volume[i+2] +
Volume[i-1] + Volume[i-2];
// MFI
a_MFI[0] = (High[i] - Low[i] + High[i-1] - Low[i-1] +
High[i-2] - Low[i-2] + High[i+1] - Low[i+1] +
High[i+2] - Low[i+2]) / a_Volume[0];
// ïîøëè èñêàòü ôðàêòàë íà âíèç ïî èñòîðèè
j = i + 1;
while(a_Fractal[1] == 0)
{
if(iFractals(NULL,0,MODE_UPPER,j)!=0)
break;
//-- Íàøëè ôðàêòàë âíèç
if(iFractals(NULL, 0, MODE_LOWER, j) != 0)
{
a_Fractal[1] = iFractals(NULL, 0, MODE_LOWER, j);
a_Volume[1] = Volume[j+2] + Volume[j+1] +
Volume[j] + Volume[j-1] + Volume[j-2];
a_MFI[1] = (High[j+1] - Low[j+1] + High[j+2] -
Low[j+2] + High[j] - Low[j] + High[j-1] -
Low[j-1] + High[j-2] - Low[j-2]) / a_Volume[1];
// èìååì ïðèñåäàþùèé ôðàêòàë (MFI - îáúåì +)
if(a_Volume[0] > a_Volume[1]*Percent / 100 &&
a_MFI[0] < a_MFI[1])
{
ExtRedBuffer[i] = High[i]; // + Pips*Point;
break;
}
// èìååì çåëåíûé ôðàêòàë (MFI + îáúåì +)
if(a_Volume[0] > a_Volume[1]*Percent / 100 &&
a_MFI[0] > a_MFI[1])
{
ExtLimeBuffer[i] = High[i]; // + Pips*Point;
break;
}
// èìååì ôàëüøèâûé ôðàêòàë (MFI + îáúåì -)
if(a_Volume[0]*Percent / 100 < a_Volume[1] &&
a_MFI[0] > a_MFI[1])
{
ExtBlueBuffer[i] = High[i]; // + Pips*Point;
break;
}
// èìååì óâÿäàþùèé ôðàêòàë (MFI - îáúåì -)
if(a_Volume[0]*Percent / 100 < a_Volume[1] &&
a_MFI[0] < a_MFI[1])
{
ExtSaddleBrownBuffer[i]=High[i]; // + Pips*Point;
break;
}
}
j++;
}
}
//--- íèæíèå ôðàêòàëû
ArrayInitialize(a_Fractal, 0);
ArrayInitialize(a_MFI, 0);
ArrayInitialize(a_Volume, 0);
// íà i áàðå åñòü ôðàêòàë âíèç
if(iFractals(NULL, 0, MODE_LOWER, i) != 0)
{
// öåíà íà ôðàêòàëå
a_Fractal[0] = iFractals(NULL, 0, MODE_LOWER, i);
// îáúåì
a_Volume[0] = Volume[i] + Volume[i+1] + Volume[i+2] +
Volume[i-1] + Volume[i-2];
// MFI
a_MFI[0] = (High[i] - Low[i] + High[i-1] - Low[i-1] +
High[i-2] - Low[i-2] + High[i+1] - Low[i+1] +
High[i+2] - Low[i+2]) / a_Volume[0];
// ïîøëè èñêàòü ôðàêòàë íà ââåðõ ïî èñòîðèè
j = i + 1;
while(a_Fractal[1] == 0)
{
if(iFractals(NULL, 0, MODE_LOWER, j) != 0)
break;
//-- Íàøëè ôðàêòàë ââåðõ
if(iFractals(NULL, 0, MODE_UPPER, j) != 0)
{
a_Fractal[1] = iFractals(NULL, 0, MODE_UPPER, j);
a_Volume[1] = Volume[j+2] + Volume[j+1] + Volume[j] +
Volume[j-1] + Volume[j-2];
a_MFI[1] = (High[j+1] - Low[j+1] + High[j+2] - Low[j+2] +
High[j]-Low[j] + High[j-1] - Low[j-1] +
High[j-2] - Low[j-2]) / a_Volume[1];
// èìååì ïðèñåäàþùèé ôðàêòàë (MFI - îáúåì +)
if(a_Volume[0] > a_Volume[1]*Percent / 100 &&
a_MFI[0] < a_MFI[1])
{
ExtRedBuffer[i] = Low[i]; // - Pips*Point;
break;
}
// èìååì çåëåíûé ôðàêòàë (MFI + îáúåì +)
if(a_Volume[0] > a_Volume[1]*Percent / 100 &&
a_MFI[0] > a_MFI[1])
{
ExtLimeBuffer[i] = Low[i]; // - Pips*Point;
break;
}
// èìååì ôàëüøèâûé ôðàêòàë (MFI + îáúåì -)
if(a_Volume[0]*Percent / 100 < a_Volume[1] &&
a_MFI[0] > a_MFI[1])
{
ExtBlueBuffer[i] = Low[i]; // - Pips*Point;
break;
}
// èìååì óâÿäàþùèé ôðàêòàë (MFI - îáúåì -)
if(a_Volume[0]*Percent / 100 < a_Volume[1] &&
a_MFI[0] < a_MFI[1])
{
ExtSaddleBrownBuffer[i] = Low[i]; // - Pips*Point;
break;
}
}
j++;
}
}
}
// îòðèñîâêà ëèíèé
double _Price[3,2];
int _Time[3,2];
ArrayInitialize(_Price, -1);
ArrayInitialize(_Time, -1);
int up = 0, down = 0;
for(i = 3; i <= 300; i++)
{
//up
if(ExtRedBuffer[i] != 2147483647 &&
iFractals(NULL, 0, MODE_UPPER, i) != NULL &&
up <= 2 &&
iFractals(NULL, 0, MODE_UPPER, i) <= ExtRedBuffer[i])
{
_Price[up,0] = ExtRedBuffer[i];
_Time[up,0] = iTime(NULL, 0, i);
up++;
}
if(ExtRedBuffer[i] != 2147483647 &&
iFractals(NULL, 0, MODE_LOWER, i) != 0 &&
down <= 2 &&
iFractals(NULL, 0, MODE_LOWER, i) >= ExtRedBuffer[i])
{
_Price[down,1] = ExtRedBuffer[i];
_Time[down,1] = iTime(NULL, 0, i);
down++;
}
}
ObjectMove("Up", 1, _Time[0,0], _Price[0,0]);
ObjectMove("Up", 0, _Time[1,0], _Price[1,0]);
//----
ObjectMove("Down", 1, _Time[0,1], _Price[0,1]);
ObjectMove("Down", 0, _Time[1,1], _Price[1,1]);
if(UseOldLine)
{
ObjectMove("Up_Prev", 1, _Time[1,0], _Price[1,0]);
ObjectMove("Up_Prev", 0, _Time[2,0], _Price[2,0]);
//----
ObjectMove("Down_Prev", 1, _Time[1,1], _Price[1,1]);
ObjectMove("Down_Prev", 0, _Time[2,1], _Price[2,1]);
}
return(0);
}
//+------------------------------------------------------------------+
Comments