Ind-NRTR-3Period
Download scriptThis script is a multi-timeframe technical analysis tool designed to identify and visualize market trends across three different time horizons: the 1-hour (H1), 4-hour (H4), and Daily (D1) periods. Its primary purpose is to track market momentum by establishing "ceilings" and "floors" based on historical price volatility.
Core Logic Overview
The tool operates by analyzing price action to determine whether the market is in an upward or downward trend. It uses a dynamic approach where the boundaries of these trends are not fixed; instead, they adjust automatically as new price data becomes available.
1. Trend Detection and Volatility Calculation The script uses an Average True Range (ATR) calculation to measure market volatility. By multiplying this volatility by a user-defined multiplier, the tool calculates how far the price can move before a trend change is considered "significant." This prevents the indicator from reacting to minor market noise and focuses on substantial movements.
2. Dynamic Ceiling and Floor Management
- In an Uptrend: The script establishes a "Ceiling" (the high point) and a "Buy Buffer" (a support level below the current price). If the price breaks above the ceiling, the indicator recognizes new upward momentum and refreshes the levels.
- In a Downtrend: The script establishes a "Floor" (the low point) and a "Sell Buffer" (a resistance level above the current price). If the price drops below the floor, it acknowledges new downward momentum and updates the levels accordingly.
3. Trend Reversal Logic The logic includes specific triggers to switch the trend status:
- If the market is currently in an uptrend but breaks significantly "down" past its established buffer, the script flips the status to a downtrend and creates a new floor.
- Conversely, if it is in a downtrend but breaks "up" past its buffer, it flips to an uptrend and establishes a new ceiling.
4. Multi-Timeframe Synchronization One of the most sophisticated aspects of this script is how it handles different timeframes. Because H1, H4, and D1 charts have different amounts of data points, the script performs a synchronization process. It maps the data from the higher timeframes back onto the lower timeframe view. This allows a trader to see the "big picture" (Daily trends) simultaneously with the "immediate picture" (Hourly trends) on a single chart window.
Visual Output
The script translates this complex logic into visual cues for the user:
- Trend Markers: It places specific arrows or symbols on the chart to indicate where trend shifts and boundary breaks occur.
- Real-time Data: The script provides a text summary on the chart display, showing the current calculated values for all three timeframes (H1, H4, and D1), allowing for a quick glance at market sentiment across different scales.
//+------------------------------------------------------------------+
//| !Ind-NRTR-3Periods.mq4 |
//| Copyright © 2005, LeonSi |
//| http://www.expert-mt4.nm.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, LeonSi"
#property link "http://www.expert-mt4.nm.ru"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 DarkViolet
#property indicator_color2 LawnGreen
#property indicator_color3 Orange
//---- input parameters
extern int PerATR=40;
extern double kATR=2.0;
extern bool Info=true;
extern int Limit=350;
//---- buffers
double buffer_h1[];
double buffer_h4[];
double buffer_d1[];
double SellBuffer[];
double BuyBuffer[];
double Ceil[];
double Floor[];
double Trend[];
int sm_Bars;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
//---- indicators
IndicatorBuffers(8);
SetIndexLabel(0,"H1 Period");
SetIndexLabel(1,"H4 Period");
SetIndexLabel(2,"D1 Period");
SetIndexStyle(5,DRAW_ARROW);
SetIndexArrow(5,251);
SetIndexBuffer(5,SellBuffer);
SetIndexEmptyValue(5,0.0);
SetIndexStyle(6,DRAW_ARROW);
SetIndexArrow(6,251);
SetIndexBuffer(6,BuyBuffer);
SetIndexEmptyValue(6,0.0);
SetIndexStyle(7,DRAW_ARROW);
SetIndexArrow(7,159);
SetIndexBuffer(7,Ceil);
SetIndexEmptyValue(7,0.0);
SetIndexStyle(3,DRAW_ARROW);
SetIndexArrow(3,159);
SetIndexBuffer(3,Floor);
SetIndexEmptyValue(3,0.0);
SetIndexBuffer(4,Trend);
SetIndexEmptyValue(4,0);
SetIndexStyle(0,DRAW_ARROW,0,0);
SetIndexArrow(0,159);
SetIndexBuffer(0,buffer_h1);
SetIndexEmptyValue(0,0.0);
SetIndexStyle(1,DRAW_ARROW,0,0);
SetIndexArrow(1,159);
SetIndexBuffer(1,buffer_h4);
SetIndexEmptyValue(1,0.0);
SetIndexStyle(2,DRAW_ARROW,0,0);
SetIndexArrow(2,159);
SetIndexBuffer(2,buffer_d1);
SetIndexEmptyValue(2,0.0);
//----
return(0);
}
//+------------------------------------------------------------------+
//| ïðîáèòèå âåðõà ÄÀÓÍòðåíäà |
//+------------------------------------------------------------------+
bool BreakDown(int timeframe, int shift)
{
bool result=false;
if (iClose(Symbol(),timeframe,shift)>SellBuffer[shift+1]) result=true;
return(result);
}
//+------------------------------------------------------------------+
//| ïðîáèòèå äíà ÀÏòðåíäà |
//+------------------------------------------------------------------+
bool BreakUp(int timeframe, int shift)
{
bool result=false;
if (iClose(Symbol(),timeframe,shift)<BuyBuffer[shift+1]) result=true;
return(result);
}
//+------------------------------------------------------------------+
//| âçÿòèå íîâîãî ìèíèìóìà ïî ÄÀÓÍòðåíäó |
//+------------------------------------------------------------------+
bool BreakFloor(int timeframe, int shift)
{
bool result=false;
if (iHigh(Symbol(),timeframe,shift)<Floor[shift+1]) result=true;
return(result);
}
//+------------------------------------------------------------------+
//| âçÿòèå íîâîãî ìàêñèìóìà ïî ÀÏòðåíäó |
//+------------------------------------------------------------------+
bool BreakCeil(int timeframe, int shift)
{
bool result=false;
if(iLow(Symbol(),timeframe,shift)>Ceil[shift+1]) result=true;
return(result);
}
//+------------------------------------------------------------------+
//| îïðåäåëåíèå ïðåäûäóùåãî òðåíäà |
//+------------------------------------------------------------------+
bool Uptrend(int timeframe, int shift)
{
bool result=false;
if (Trend[shift+1]==1) result=true;
if (Trend[shift+1]==-1) result=false;
if ((Trend[shift+1]!=1)&&(Trend[shift+1]!=-1)) Print("Âíèìàíèå! Òðåíä íå îïðåäåëåí, òàêîãî áûòü íå ìîæåò. Áàð îò êîíöà ",(Bars-shift));
return(result);
}
//+------------------------------------------------------------------+
//| âû÷èñëåíèå âîëàòèëüíîñòè |
//+------------------------------------------------------------------+
double ATR(int timeframe, int iPer,int shift)
{
return(iATR(Symbol(),timeframe,iPer,shift));
}
//+------------------------------------------------------------------+
//| óñòàíîâêà íîâîãî óðîâíÿ ïîòîëêà |
//+------------------------------------------------------------------+
void NewCeil(int timeframe, int shift)
{
Ceil[shift]=iClose(Symbol(),timeframe,shift);
Floor[shift]=0.0;
}
//+------------------------------------------------------------------+
//| óñòàíîâêà íîâîãî óðîâíÿ ïîëà |
//+------------------------------------------------------------------+
void NewFloor(int timeframe, int shift)
{
Floor[shift]=iClose(Symbol(),timeframe,shift);
Ceil[shift]=0.0;
}
//+------------------------------------------------------------------+
//| óñòàíîâêà óðîâíÿ ïîääåðæêè ÀÏòðåíäà |
//+------------------------------------------------------------------+
void SetBuyBuffer(int timeframe, int shift)
{
BuyBuffer[shift]=iClose(Symbol(),timeframe,shift)-kATR*ATR(timeframe, PerATR,shift);
SellBuffer[shift]=0.0;
}
//+------------------------------------------------------------------+
//| óñòàíîâêà óðîâíÿ ïîääåðæêè ÄÀÓÍòðåíäà |
//+------------------------------------------------------------------+
void SetSellBuffer(int timeframe, int shift)
{
SellBuffer[shift]=iClose(Symbol(),timeframe,shift)+kATR*ATR(timeframe, PerATR,shift);
BuyBuffer[shift]=0.0;
}
//+------------------------------------------------------------------+
//| ðåâåðñ òðåíäà è óñòàíîâêà íîâûõ óðîâíåé |
//+------------------------------------------------------------------+
void NewTrend(int timeframe, int shift)
{
if (Trend[shift+1]==1)
{
Trend[shift]=-1;
NewFloor(timeframe, shift);
SetSellBuffer(timeframe, shift);
}
else
{
Trend[shift]=1;
NewCeil(timeframe, shift);
SetBuyBuffer(timeframe, shift);
}
if ((Trend[shift+1]!=1)&&(Trend[shift+1]!=-1)) Print("Âíèìàíèå! Òðåíä íå îïðåäåëåí, òàêîãî áûòü íå ìîæåò");
}
//+------------------------------------------------------------------+
//| ïðîäîëæåíèå òðåíäà |
//+------------------------------------------------------------------+
void CopyLastValues(int timeframe, int shift)
{
SellBuffer[shift]=SellBuffer[shift+1];
BuyBuffer[shift]=BuyBuffer[shift+1];
Ceil[shift]=Ceil[shift+1];
Floor[shift]=Floor[shift+1];
Trend[shift]=Trend[shift+1];
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
double timeframe;
double iPeriod[3]={PERIOD_H1,PERIOD_H4,PERIOD_D1};
int counted_bars, limit, i, cnt;
limit=MathMin(iBars(Symbol(),PERIOD_H1)-PerATR-1,iBars(Symbol(),PERIOD_H4)-PerATR-1);
limit=MathMin(iBars(Symbol(),PERIOD_D1)-PerATR-1,limit);
if(Limit<limit) limit=Limit;
for(i=0; i<=2; i++)
{
timeframe=iPeriod[i];
if(iClose(Symbol(),timeframe,limit+1)>=iOpen(Symbol(),timeframe,limit+1))
{
Trend[limit+1]=1;
Ceil[limit+1]=iClose(Symbol(),timeframe,limit+1);
BuyBuffer[limit+1]=iClose(Symbol(),timeframe,limit+1)-kATR*ATR(timeframe, PerATR,limit+1);
}
if(iClose(Symbol(),timeframe,limit+1)<iOpen(Symbol(),timeframe,limit+1))
{
Trend[limit+1]=-1;
Floor[limit+1]=iClose(Symbol(),timeframe,limit+1);
SellBuffer[limit+1]=iClose(Symbol(),timeframe,limit+1)+kATR*ATR(timeframe, PerATR,limit+1);
}
//----
for(cnt=limit; cnt>=0; cnt--)
{
if(Uptrend(timeframe, cnt))
{
if(BreakCeil(timeframe, cnt))
{
NewCeil(timeframe, cnt);
SetBuyBuffer(timeframe, cnt);
Trend[cnt]=1;
continue;
}
if(BreakUp(timeframe, cnt))
{
NewTrend(timeframe, cnt);
continue;
}
CopyLastValues(timeframe, cnt);
}
else
{
if(BreakFloor(timeframe, cnt))
{
NewFloor(timeframe, cnt);
SetSellBuffer(timeframe, cnt);
Trend[cnt]=-1;
continue;
}
if(BreakDown(timeframe, cnt))
{
NewTrend(timeframe, cnt);
continue;
}
CopyLastValues(timeframe, cnt);
}
}
paste(i,limit);
}
if(Info==true) Comment("H1=",buffer_h1[0]," \n",
"H4=",buffer_h4[0]," \n",
"D1=",buffer_d1[0]);
//----
return(0);
}
//+------------------------------------------------------------------+
void paste(int frame, int limit)
{
//---- H1
int z, y;
switch(frame)
{
case 0:
for(z=0; z<limit; z++) buffer_h1[z]=MathMax(SellBuffer[z],BuyBuffer[z]);
//---- H4
case 1:
y=0;
for(z=0; z<limit; z++)
{
buffer_h4[z]=MathMax(SellBuffer[y],BuyBuffer[y]);
if(iTime(Symbol(),PERIOD_H1,z)==iTime(Symbol(),PERIOD_H4,y)) y++;
}
//---- D1
case 2:
y=0;
for(z=0; z<limit; z++)
{
buffer_d1[z]=MathMax(SellBuffer[y],BuyBuffer[y]);
if(iTime(Symbol(),PERIOD_H1,z)==iTime(Symbol(),PERIOD_D1,y)) y++;
}
}
}
Comments