The Barishpoltz Channel is a technical analysis tool designed to automatically identify and visualize price trends by constructing geometric channels on a trading chart. Instead of requiring a trader to manually draw lines to define support and resistance, this script uses mathematical logic to detect significant structural points in price action and connect them to form a visual "corridor."
Core Logic and Functionality
1. Automatic Peak Detection (Fractals) The script begins by scanning historical price data to identify "peaks" (high points) and "troughs" (low points). It looks for specific structural points where the price reaches a local maximum or minimum relative to the bars immediately surrounding it. These points act as the anchor marks for the channel.
2. Structural Mapping and Connection Once the peaks and troughs are identified, the script performs a complex search to find the most relevant pairs to connect. It looks for:
- Proximity: Ensuring that the points selected are close enough to be logically related but far enough apart to form a meaningful trend.
- Sequence: Organizing these points chronologically to ensure the channel moves forward in time rather than jumping back and forth.
3. Boundary Validation (The "Clearance" Check) A critical part of this script's logic is its verification process. Before drawing a line between two points, it performs a "Border Check." It mathematically calculates the slope of the proposed line and then scans all the price bars in between those two points.
- If any price bar breaks through the proposed line (i.e., if the price "pokes" outside the corridor), the script rejects that connection.
- It only confirms a channel if the price stays consistently contained within the boundaries of the two points being connected. This ensures that the resulting channel represents a genuine period of trend stability rather than an arbitrary line that cuts through price action.
4. Visual Output Once a valid, unbroken connection is found, the script renders three distinct elements on your chart:
- Top Border: A solid line representing the upper limit of the price corridor.
- Bottom Border: A solid line representing the lower limit of the price corridor.
- Fractal Markers: Visual indicators (arrows) highlighting the specific peak or trough points that were used to calculate the channel's geometry.
Summary for the User
In essence, this tool automates the "trend-line" drawing process. It scans the market history, identifies significant turning points, and draws a "tunnel" around the price action. By ensuring that no price bars violate the boundaries of these tunnels, it filters out "noisy" connections to provide a more reliable visual representation of the current market trend.
//+------------------------------------------------------------------+
//| Barishpoltz Channel.mq4 |
//| SaiborEye |
//| |
//+------------------------------------------------------------------+
#property copyright "SaiborEye"
#property link ""
/*
Âàðèàíò èíäèêàòîðà, èñïîëüçóþùåãî ôðàêòàëû ïðè ïîñòðîåíèè è îòîáðàæåíèå
ñêîëüçÿùèõ êàíàëîâ Áàðèøïîëüöà. Äàííûé ðåëèç ïðåäíàçíà÷åí
äëÿ ïðèêëàäíîé îöåíêè âîçìîæíîñòè îòêàçà îò ðó÷íîãî ïîñòðîåíèÿ, âûÿâëåíèÿ è
êîððåêöèè ñëàáûõ ìåñò, ïðåäëîæåíèÿ ïî ââîäó äîïîëíèòåëüíûõ ïàðàìåòðîâ
*/
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Gold
#property indicator_color2 Coral
#property indicator_color3 Aquamarine
//---- input parameters
extern int RightLevel = 3; // Îòñòóï îò ïðàâîé ãðàíèöû ãðàôèêà (Íîìåð áàðà, 0 - ïîñëåäíèé, íå ñôîðìèðîâàâøèéñÿ)
extern int BetweenPeaks = 4; // Ìèíèìàëüíîå ðàññòîÿíèå ìåæäó ýêñòðåìóìàìè (êîëè÷åñòâî áàðîâ)
extern int MaxLength = 600; // Ìàêñèìàëüíàÿ ðàçðåøåííàÿ äëèíà êàíàëà (êîëè÷åñòâî áàðîâ)
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0,DRAW_SECTION);
SetIndexBuffer(0,ExtMapBuffer1);
SetIndexEmptyValue(0,0.0);
SetIndexLabel(0,"Top Border");
SetIndexStyle(1,DRAW_SECTION);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexEmptyValue(1,0.0);
SetIndexLabel(1,"Bottom Border");
SetIndexStyle(2,DRAW_ARROW,STYLE_SOLID,3);
SetIndexBuffer(2,ExtMapBuffer3);
SetIndexEmptyValue(2,0.0);
SetIndexArrow(2,159);
SetIndexLabel(2,"Fractal");
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
int CheckBorders(int X1, int X2, int X3, double Y1, double Y2, double Y3, bool TwoTop)
{
int x, limit;
if (X1>X2)
limit=X1;
else
limit=X2;
if (limit>2)
limit=2;
if(TwoTop)
{// TOP TWO
for(x=RightLevel; x<limit; x++)
{// LINE LOOP-1
if(Y2+(x*1.0-X2*1.0)*(Y1-Y2)/(X1*1.0-X2*1.0)<High[x])
return (1);
}// LINE LOOP-1
for(x=RightLevel; x<limit; x++)
{// LINE LOOP-2
if(Y3+(x*1.0-X3*1.0)*(Y1-Y2)/(X1*1.0-X2*1.0)>Low[x])
return (-1);
}// LINE LOOP-2
return (0);
}// TOP TWO
if(!TwoTop)
{// BOTTOM TWO
for(x=RightLevel; x<limit; x++)
{// LINE LOOP-3
if(Y2+(x*1.0-X2*1.0)*(Y1-Y2)/(X1*1.0-X2*1.0)>Low[x])
return (-1);
}// LINE LOOP-3
for(x=RightLevel;x<limit;x++)
{// LINE LOOP-4
if(Y3+(x*1.0-X3*1.0)*(Y1-Y2)/(X1*1.0-X2*1.0)<High[x])
return (1);
}// LINE LOOP-4
return (0);
}// BOTTOM TWO
return (-1);}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int PosX1[2],PosX2,pos,pos1,pos2,limit;
double value;
bool Flag;
int TopPeaksPos[];
int TopPeaksIndex;
int BottomPeaksPos[];
int BottomPeaksIndex;
//----
limit=MaxLength;
if (limit>Bars-2)
limit=Bars-2;
if(RightLevel<2)
RightLevel=2;
ArrayResize(TopPeaksPos,limit);
ArrayResize(BottomPeaksPos,limit);
TopPeaksIndex=0;
BottomPeaksIndex=0;
ArrayInitialize(ExtMapBuffer1,0.0);
ArrayInitialize(ExtMapBuffer2,0.0);
ArrayInitialize(ExtMapBuffer3,0.0);
//----
for(pos=RightLevel; pos<limit; pos++)
{// MAIN SEEK LOOP
if (High[pos]>High[pos-1] && High[pos]>High[pos-2])
{
if(High[pos]>High[pos+1]&&High[pos]>High[pos+2])
{
TopPeaksPos[TopPeaksIndex]=pos;
TopPeaksIndex++;
}
}
if (Low[pos]<Low[pos-1] && Low[pos]<Low[pos-2])
{
if(Low[pos]<Low[pos+1]&&Low[pos]<Low[pos+2])
{
BottomPeaksPos[BottomPeaksIndex]=pos;
BottomPeaksIndex++;
}
}
}// MAIN SEEK LOOP
//----
if (BottomPeaksIndex<TopPeaksIndex)
limit=BottomPeaksIndex;
else
limit=TopPeaksIndex;
for (pos=0; pos<limit; pos++)
{// SEEK LOOP
if (TopPeaksPos[pos]<BottomPeaksPos[pos])
{// TOP NEARLY
for(pos1=pos; pos1<TopPeaksIndex; pos1++)
{// SECOND POINT SEEK
for(pos2=0; pos2<BottomPeaksIndex; pos2++)
{
if(BottomPeaksPos[pos2]<=TopPeaksPos[pos1])
{
if(BottomPeaksPos[pos2]>=TopPeaksPos[pos])
{
if(TopPeaksPos[pos1]-TopPeaksPos[pos]>BetweenPeaks)
{
if(CheckBorders(TopPeaksPos[pos], TopPeaksPos[pos1], BottomPeaksPos[pos2], High[TopPeaksPos[pos]], High[TopPeaksPos[pos1]], Low[BottomPeaksPos[pos2]], TRUE)==0)
{// DRAWING
ExtMapBuffer1[0] = (0-TopPeaksPos[pos])*(High[TopPeaksPos[pos1]]-High[TopPeaksPos[pos]])/(TopPeaksPos[pos1]-TopPeaksPos[pos])+High[TopPeaksPos[pos]];
ExtMapBuffer1[TopPeaksPos[pos1]] = High[TopPeaksPos[pos1]];
ExtMapBuffer2[0] = Low[BottomPeaksPos[pos2]]+(0-BottomPeaksPos[pos2])*(High[TopPeaksPos[pos1]]-High[TopPeaksPos[pos]])/(TopPeaksPos[pos1]-TopPeaksPos[pos]);
ExtMapBuffer2[TopPeaksPos[pos1]] = Low[BottomPeaksPos[pos2]]+(TopPeaksPos[pos1]-BottomPeaksPos[pos2])*(High[TopPeaksPos[pos1]]-High[TopPeaksPos[pos]])/(TopPeaksPos[pos1]-TopPeaksPos[pos]);
ExtMapBuffer3[TopPeaksPos[pos]] = High[TopPeaksPos[pos]];
ExtMapBuffer3[TopPeaksPos[pos1]] = High[TopPeaksPos[pos1]];
ExtMapBuffer3[BottomPeaksPos[pos2]] = Low[BottomPeaksPos[pos2]];
return (0);
}// DRAWING
}
}
}
}
}// SECOND POINT SEEK
}
else
{// BOTTOM NEARLY
for(pos1=pos; pos1<BottomPeaksIndex; pos1++)
{// SECOND POINT SEEK
for(pos2=0; pos2<TopPeaksIndex; pos2++)
{
if(TopPeaksPos[pos2]<=BottomPeaksPos[pos1])
{
if(TopPeaksPos[pos2]>=BottomPeaksPos[pos])
{
if(BottomPeaksPos[pos1]-BottomPeaksPos[pos]>BetweenPeaks)
{
if(CheckBorders(BottomPeaksPos[pos], BottomPeaksPos[pos1], TopPeaksPos[pos2], Low[BottomPeaksPos[pos]], Low[BottomPeaksPos[pos1]], High[TopPeaksPos[pos2]], FALSE)==0)
{// DRAWING
ExtMapBuffer1[0] = (0-BottomPeaksPos[pos])*(Low[BottomPeaksPos[pos1]]-Low[BottomPeaksPos[pos]])/(BottomPeaksPos[pos1]-BottomPeaksPos[pos])+Low[BottomPeaksPos[pos]];
ExtMapBuffer1[BottomPeaksPos[pos1]] = Low[BottomPeaksPos[pos1]];
ExtMapBuffer2[0] = High[TopPeaksPos[pos2]]+(0-TopPeaksPos[pos2])*(Low[BottomPeaksPos[pos1]]-Low[BottomPeaksPos[pos]])/(BottomPeaksPos[pos1]-BottomPeaksPos[pos]);
ExtMapBuffer2[BottomPeaksPos[pos1]] = High[TopPeaksPos[pos2]]+(BottomPeaksPos[pos1]-TopPeaksPos[pos2])*(Low[BottomPeaksPos[pos1]]-Low[BottomPeaksPos[pos]])/(BottomPeaksPos[pos1]-BottomPeaksPos[pos]);
ExtMapBuffer3[BottomPeaksPos[pos]] = Low[BottomPeaksPos[pos]];ExtMapBuffer3[BottomPeaksPos[pos1]]=Low[BottomPeaksPos[pos1]];
ExtMapBuffer3[TopPeaksPos[pos2]] = High[TopPeaksPos[pos2]];
return (0);
}// DRAWING
}
}
}
}
}// SECOND POINT SEEK
}// BOTTOM NEARLY
}// SEEK LOOP
return(0);
}
//+------------------------------------------------------------------+
Comments