#MTF Stochastic v2.0_v2

#MTF Stochastic v2.0_v2

This script is a sophisticated financial analysis tool designed to display the Stochastic Oscillator—a common momentum indicator—across different timeframes simultaneously. While standard indicators are usually locked to the timeframe you are currently viewing, this tool allows you to "peek" into higher or lower timeframes without switching your main chart view.

Core Functionality

The primary purpose of this script is Multi-Timeframe (MTF) Analysis. It enables a trader to see the market momentum of, for example, a Daily or 4-hour chart while they are actively trading on a much smaller timeframe, like a 15-minute chart. This helps in identifying the "big picture" trend while making precise entries on small price movements.

Key Technical Features

  • Multi-Timeframe Synchronization: The tool calculates Stochastic values from various timeframes (ranging from 1 minute up to monthly charts). It automatically handles the heavy lifting of retrieving this data and aligning it with your current view.
  • Linear Interpolation: When viewing a higher timeframe on a lower timeframe chart, the data points can sometimes look "choppy" or disconnected because one high-timeframe candle covers many small ones. To solve this, the script uses a mathematical technique called Linear Interpolation. This smoothly fills in the gaps between those large data points, creating a fluid, continuous line that is much easier for the human eye to read.
  • Customizable Smoothing and Pricing: The logic allows you to choose different methods for calculating the averages (such as Simple Moving Average or Exponential Moving Average) and decide whether the indicator should be based on the "High/Low" prices or the "Close" prices of the candles.
  • Real-Time Countdown Clock: The script includes a visual "Clock" feature. It calculates the remaining time until the next candle closes on the selected higher timeframe and displays this as a live countdown text on your chart. This is highly useful for traders who need to know exactly when a high-timeframe candle will flip or finish forming.
  • Dynamic Visual Buffers: The tool manages four separate data "buffers." It distinguishes between historical (closed) candles and the current live candle, ensuring that the lines on your screen accurately represent both past history and real-time price action without overlapping or confusing the two.

Summary for the User

Essentially, this script acts as a multi-lens telescope. It takes the momentum data from any timeframe you choose, smoothes it out so it flows naturally across your current chart, and provides a live countdown timer so you can stay perfectly in sync with the broader market trends.

Indicators Used
Stochastic oscillator
Miscellaneous
Implements a curve of type %1
10 Views
0 Downloads
0 Favorites
#MTF Stochastic v2.0_v2
//+------------------------------------------------------------------+
//|                                               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_color1      Red         // %K line
#property indicator_color2      CLR_NONE    // %D line
#property indicator_color3      LightPink   // %K line of the current candle
#property indicator_color4      CLR_NONE    // %D line of the current candle
#property indicator_maximum     100
#property indicator_minimum     0
//---- input parameters
extern string note1="Chart Time Frame";
extern string note2="0=current time frame";
extern string note3="1=M1, 5=M5, 15=M15, 30=M30";
extern string note4="60=H1, 240=H4, 1440=D1";
extern string note5="10080=W1, 43200=MN1";
extern int    TimeFrame  =0;      // {1=M1, 5=M5, 15=M15, ..., 1440=D1, 10080=W1, 43200=MN1}
extern string note6="Stochastic1";
extern int    KPeriod     =5,
              DPeriod     =3,
              Slowing     =3;
extern string note7="0=SMA, 1=EMA, 2=SMMA, 3=LWMA";
extern int    MAMethod       =0;      // {0=SMA, 1=EMA, 2=SMMA, 3=LWMA}
extern string note8="0=Hi/Low, 1=Close/Close";
extern int    PriceField     =0;      // {0=Hi/Low, 1=Close/Close}
extern bool   ShowClock      =true;   // display time to candle close countdown
extern bool   ShowStochInfo  =true;
extern color  ClockColor     =Red;
extern string ClockFont      ="Arial";
extern int    ClockSize      =8;
//---- indicator buffers
double      BufferK[],
            BufferD[],
            BufferK_Curr[],
            BufferD_Curr[];
//----
string   IndicatorName="", IndicatorName2="", StochName="",
         TimeLabelName="";
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- name for DataWindow and indicator subwindow label
   switch(TimeFrame)
     {
      case 1:      IndicatorName2="M1";   break;
      case 5:      IndicatorName2="M5"; break;
      case 10:      IndicatorName2="M10"; break;
      case 15:      IndicatorName2="M15"; break;
      case 30:      IndicatorName2="M30"; break;
      case 60:      IndicatorName2="H1"; break;
      case 120:   IndicatorName2="H2"; break;
      case 240:   IndicatorName2="H4"; break;
      case 480:   IndicatorName2="H8"; break;
      case 1440:   IndicatorName2="D1"; break;
      case 10080:   IndicatorName2="W1"; break;
      case 43200:   IndicatorName2="MN1"; break;
      default:     {TimeFrame=Period(); init(); return(0);}
     }
   StochName=" Stoch("+KPeriod+","+DPeriod+","+Slowing+")";
   IndicatorName=IndicatorName2+StochName;
   IndicatorShortName(IndicatorName);
   IndicatorDigits(1);
//---- indicator lines
   SetIndexBuffer(0,BufferK);
   SetIndexBuffer(1,BufferD);
   SetIndexBuffer(2,BufferK_Curr);
   SetIndexBuffer(3,BufferD_Curr);
   SetIndexStyle(0,DRAW_LINE);
   SetIndexStyle(1,DRAW_LINE);
   SetIndexStyle(2,DRAW_LINE);
   SetIndexStyle(3,DRAW_LINE);
   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, stochD;
        if ((TimeFrame!=10) && (TimeFrame!=120) && (TimeFrame!=480)) 
        {
         stochK=iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,0,shift1);
         stochD=iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,1,shift1);
        }
        else 
        {
         switch(TimeFrame)
           {
              case 10:   
              {
               stochK=2*iStochastic(NULL,5,KPeriod,DPeriod,Slowing,MAMethod,PriceField,0,shift1);
               stochD=2*iStochastic(NULL,5,KPeriod,DPeriod,Slowing,MAMethod,PriceField,1,shift1);
               break;
              }
              case 120:   
              {
               stochK=2*iStochastic(NULL,60,KPeriod,DPeriod,Slowing,MAMethod,PriceField,0,shift1);
               stochD=2*iStochastic(NULL,60,KPeriod,DPeriod,Slowing,MAMethod,PriceField,1,shift1);
               break;
              }
              case 480:   
              {
               stochK=2*iStochastic(NULL,240,KPeriod,DPeriod,Slowing,MAMethod,PriceField,0,shift1);
               stochD=2*iStochastic(NULL,240,KPeriod,DPeriod,Slowing,MAMethod,PriceField,1,shift1);
               break;
              }
           }
        }
      //	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())
        {
           if ((TimeFrame!=10) && (TimeFrame!=120) && (TimeFrame!=480)) 
           {
            int shift2prev=iBarShift(NULL,0,iTime(NULL,TimeFrame,shift1+1));
           }
           else 
           {
            switch(TimeFrame)
              {
                 case 10:   
                 {
                  shift2prev=2*iBarShift(NULL,0,iTime(NULL,5,shift1+1));
                  break;
                 }
                 case 120:   
                 {
                  shift2prev=2*iBarShift(NULL,0,iTime(NULL,60,shift1+1));
                  break;
                 }
                 case 480:   
                 {
                  shift2prev=2*iBarShift(NULL,0,iTime(NULL,240,shift1+1));
                  break;
                 }
              }
           }
         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;
               if (ShowStochInfo)
                  text="                "+IndicatorName2+StochName+" - "+m+":"+text;
               else
                  text="                "+IndicatorName2+" - "+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, ClockSize, ClockFont, ClockColor);
              }
            else if(ShowStochInfo)
                 {
                  text="                "+IndicatorName2+StochName+text;
                  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, ClockSize, ClockFont, ClockColor);
                 }
           }
     }
//----
   return(0);
  }
//+------------------------------------------------------------------+

Comments