MTF_Stochastic_v2.0hio
Download scriptThis tool is designed to help traders visualize momentum on a single chart without having to constantly switch between different timeframes. Its core purpose is to take technical data from a higher (or lower) timeframe—such as a Daily or Weekly trend—and project it onto your current active chart.
Core Functionality
Multi-Timeframe Integration The script allows you to select any specific timeframe (e.g., moving from a 1-minute chart to viewing 4-hour data). It calculates the "Stochastic Oscillator," which is a standard technical indicator used to determine if an asset is overbought or oversold. By displaying this data from different timeframes simultaneously, it helps traders see the "big picture" while executing trades on smaller, faster scales.
Smooth Data Visualization (Linear Interpolation) One of the most sophisticated features of this script is how it handles the gap between timeframes. Normally, if you view Weekly data on a Daily chart, the price would look like a series of "steps" because the data only changes once a week.
This script solves that problem using linear interpolation. It mathematically calculates the points between the high and low timeframe values and fills in the gaps. This results in a smooth, continuous line rather than jagged jumps, making it much easier to see the gradual flow of the trend.
Dynamic Visual Updates The logic is built to automatically update as new price data arrives. It distinguishes between "closed" candles (historical data) and the "current" candle.
- Historical Lines: These represent confirmed data from past periods.
- Current Candle Tracking: The script provides a real-time look at the ongoing timeframe's movement, showing where the momentum is heading right now.
User Experience Features
Smart Coloring & Labeling The script includes an automatic styling system. Depending on which timeframe you choose to view, the indicator will change its colors (such as Lime, Red, or Gold) to ensure high visibility and clear distinction between different data sets. It also automatically labels itself so you can easily identify which specific timeframe you are currently observing.
Live Countdown Clock To help with timing, the script includes an optional visual clock. This shows a real-time countdown until the next candle closes on the selected higher timeframe. For example, if you are watching the Weekly trend, this clock tells you exactly how many minutes and seconds remain until the current weekly candle finishes, allowing for better synchronization of trades with market cycles.
//+------------------------------------------------------------------+
//| MTF Stochastic.mq4 |
//| 2007, Christof Risch (iya) |
//| Stochastic indicator from any timeframe. |
//+------------------------------------------------------------------+
#property link "http://www.forexfactory.com/showthread.php?t=30109"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_level1 23.6
#property indicator_level2 38.2
#property indicator_level3 50
#property indicator_level4 61.8
#property indicator_level5 76.4
#property indicator_levelcolor SlateGray
#property indicator_maximum 100
#property indicator_minimum 0
//---- input parameters
extern int TimeFrame = 0, // {1=M1, 5=M5, 15=M15, ..., 1440=D1, 10080=W1, 43200=MN1}
KPeriod = 14,
DPeriod = 3,
Slowing = 3,
MAMethod = 0, // {0=SMA, 1=EMA, 2=SMMA, 3=LWMA}
PriceField = 0; // {0=Hi/Low, 1=Close/Close}
extern bool ShowClock = true; // display time to candle close countdown
extern color ClockColor = Red;
//---- indicator buffers
double BufferK[],
BufferD[],
BufferK_Curr[],
BufferD_Curr[];
//----
string IndicatorName = "",
TimeLabelName = "";
int color1 = Black;
int color2 = Black;
int color3 = Black;
int color4 = Black;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- name for DataWindow and indicator subwindow label
switch(TimeFrame)
{
case 1: IndicatorName="Period M1"; break;
case 5: IndicatorName="Period M5"; break;
case 15: IndicatorName="Period M15"; break;
case 30: IndicatorName="Period M30"; break;
case 60: IndicatorName="Period H1"; break;
case 240: IndicatorName="Period H4"; break;
case 1440: IndicatorName="Period D1"; break;
case 10080: IndicatorName="Period W1"; break;
case 43200: IndicatorName="Period MN1"; break;
default: {TimeFrame = Period(); init(); return(0);}
}
if (TimeFrame==15){
color1 = DimGray; // %K line
color2 = Blue; // %D line
color3 = DimGray; // %K line of the current candle
color4 = DodgerBlue; // %D line of the current candle
ClockColor = Blue;
}
if (TimeFrame==30){
color1 = DimGray; // %K line
color2 = Lime; // %D line
color3 = DimGray; // %K line of the current candle
color4 = LightGreen; // %D line of the current candle
ClockColor = Lime;
}
if (TimeFrame==60){
color1 = DimGray; // %K line
color2 = Red; // %D line
color3 = DimGray; // %K line of the current candle
color4 = OrangeRed; // %D line of the current candle
ClockColor = Red;
}
if (TimeFrame==240){
color1 = DimGray; // %K line
color2 = Yellow; // %D line
color3 = DimGray; // %K line of the current candle
color4 = Gold; // %D line of the current candle
ClockColor = Yellow;
}
IndicatorName = IndicatorName+" Stoch("+KPeriod+","+DPeriod+","+Slowing+")";
IndicatorShortName(IndicatorName);
IndicatorDigits(1);
//---- indicator lines
SetIndexBuffer(0,BufferK);
SetIndexBuffer(1,BufferD);
SetIndexBuffer(2,BufferK_Curr);
SetIndexBuffer(3,BufferD_Curr);
SetIndexStyle(0,DRAW_NONE,EMPTY,2,color1);
SetIndexStyle(1,DRAW_LINE,EMPTY,2,color2);
SetIndexStyle(2,DRAW_NONE,EMPTY,1,color3);
SetIndexStyle(3,DRAW_LINE,EMPTY,1,color4);
//SetIndexStyle(
SetIndexLabel(0,IndicatorName+" %K line");
SetIndexLabel(1,IndicatorName+" %D Signal");
SetIndexLabel(2,IndicatorName+" %K current candle");
SetIndexLabel(3,IndicatorName+" %D current candle");
}
//+------------------------------------------------------------------+
int deinit()
{
if(TimeLabelName!="")
if(ObjectFind (TimeLabelName) != -1)
ObjectDelete(TimeLabelName);
}
//+------------------------------------------------------------------+
//| MTF Stochastic |
//+------------------------------------------------------------------+
int start()
{
//----
// counted bars from indicator time frame
static int countedBars1 = 0;
//----
// counted bars from display time frame
if(Bars-1-IndicatorCounted() > 1 && countedBars1!=0)
countedBars1 = 0;
int bars1 = iBars(NULL,TimeFrame),
start1 = bars1-1-countedBars1,
limit1 = iBarShift(NULL,TimeFrame,Time[Bars-1]);
if(countedBars1 != bars1-1)
{
countedBars1 = bars1-1;
ArrayInitialize(BufferK_Curr,EMPTY_VALUE);
ArrayInitialize(BufferD_Curr,EMPTY_VALUE);
if(TimeLabelName!="")
if(ObjectFind (TimeLabelName) != -1)
ObjectDelete(TimeLabelName);
}
if(start1 > limit1 && limit1 != -1)
start1 = limit1;
//----
// 3... 2... 1... GO!
for(int i = start1; i >= 0; i--)
{
int shift1 = i;
if(TimeFrame < Period())
shift1 = iBarShift(NULL,TimeFrame,Time[i]);
int time1 = iTime (NULL,TimeFrame,shift1),
shift2 = iBarShift(NULL,0,time1);
double stochK = iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,0,shift1),
stochD = iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,1,shift1);
//----
// old (closed) candles
if(shift1>=1)
{
BufferK[shift2] = stochK;
BufferD[shift2] = stochD;
}
//----
// current candle
if((TimeFrame >=Period() && shift1<=1)
|| (TimeFrame < Period() &&(shift1==0||shift2==1)))
{
BufferK_Curr[shift2] = stochK;
BufferD_Curr[shift2] = stochD;
}
//----
// linear interpolatior for the number of intermediate bars, between two higher timeframe candles.
int n = 1;
if(TimeFrame > Period())
{
int shift2prev = iBarShift(NULL,0,iTime(NULL,TimeFrame,shift1+1));
if(shift2prev!=-1 && shift2prev!=shift2)
n = shift2prev - shift2;
}
//----
// apply interpolation
double factor = 1.0 / n;
if(shift1>=1)
if(BufferK[shift2+n]!=EMPTY_VALUE && BufferK[shift2]!=EMPTY_VALUE)
{
for(int k = 1; k < n; k++)
{
BufferK[shift2+k] = k*factor*BufferK[shift2+n] + (1.0-k*factor)*BufferK[shift2];
BufferD[shift2+k] = k*factor*BufferD[shift2+n] + (1.0-k*factor)*BufferD[shift2];
}
}
//----
// current candle
if(shift1==0)
if(BufferK_Curr[shift2+n]!=EMPTY_VALUE && BufferK_Curr[shift2]!=EMPTY_VALUE)
{
for(k = 1; k < n; k++)
{
BufferK_Curr[shift2+k] = k*factor*BufferK_Curr[shift2+n] + (1.0-k*factor)*BufferK_Curr[shift2];
BufferD_Curr[shift2+k] = k*factor*BufferD_Curr[shift2+n] + (1.0-k*factor)*BufferD_Curr[shift2];
}
//----
// candle time countdown
if(ShowClock)
{
int m,s;
s = iTime(NULL,TimeFrame,0)+TimeFrame*60 - TimeCurrent();
m = (s-s%60)/60;
s = s%60;
string text;
if(s<10) text = "0"+s;
else text = ""+s;
text = " "+m+":"+text;
int window = WindowFind(IndicatorName);
if(window==-1)
window = WindowOnDropped() ;
TimeLabelName = IndicatorName+" Time Counter "+window;
if(ObjectFind (TimeLabelName) == -1)
ObjectCreate(TimeLabelName, OBJ_TEXT, window, Time[shift2], BufferK_Curr[shift2]+3);
else
ObjectMove (TimeLabelName, 0, Time[shift2], BufferK_Curr[shift2]+3);
ObjectSetText (TimeLabelName, text, 8, "Verdana", ClockColor);
}
}
}
return(0);
}
Comments