//+------------------------------------------------------------------+
//| MTF Stochastic.mq4 |
//| 2007, Christof Risch (iya) |
//| Stochastic indicator from any timeframe. |
//+------------------------------------------------------------------+
// Change Log:
// 2.1 2012 07 24 Modified to display only the Signal line (smoothed sma)
// cr: 2012 07 20 Added NextHigherAuto to automatically seletc the next higher time frame
// Added HidePctD to suppress the Slow line, prn
#property link "http://www.forexfactory.com/showthread.php?t=30109"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 Green //C'255,255,255' // White // %K line
#property indicator_color2 Red //Yellow // DimGray // %D line
#property indicator_color3 Green // C'255,255,255' // White // %K line of the current candle
#property indicator_color4 Red //Yellow // DimGray // %D line of the current candle
#property indicator_level1 80
#property indicator_level2 20
#property indicator_level3 50
#property indicator_levelcolor DarkSlateGray
#property indicator_maximum 100
#property indicator_minimum 0
//---- input parameters
extern bool NextHigherAuto = true;
extern bool HidePctK = false;
extern bool HidePctD = false;
extern int TimeFrame = 0, // {1=M1, 5=M5, 15=M15, ..., 1440=D1, 10080=W1, 43200=MN1}
KPeriod = 11,
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 = false; // display time to candle close countdown
extern color ClockColor = Red;
//---- indicator buffers
double BufferK[],
BufferD[],
BufferK_Curr[],
BufferD_Curr[];
//----
string IndicatorName = "",
TimeLabelName = "";
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
if ( TimeFrame == 0 )
TimeFrame = Period();
if ( NextHigherAuto ) TimeFrame = GetHigherTimeFrame( TimeFrame ) ;
//---- 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);}
}
IndicatorName = IndicatorName+" Stoch("+KPeriod+","+DPeriod+","+Slowing+")";
IndicatorShortName(IndicatorName);
IndicatorDigits(1);
string TimeFrameStr = TF2Str(TimeFrame);
//---- indicator lines
SetIndexBuffer(0,BufferK);
SetIndexBuffer(1,BufferD);
SetIndexBuffer(2,BufferK_Curr);
SetIndexBuffer(3,BufferD_Curr);
SetIndexStyle(0,DRAW_LINE,EMPTY,1);
//SetIndexStyle(0,DRAW_NONE);
SetIndexStyle(2,DRAW_LINE,EMPTY,1);
//SetIndexStyle(2,DRAW_NONE);
if ( ! HidePctK )
{
SetIndexStyle(0,DRAW_LINE,EMPTY,1);
SetIndexStyle(2,DRAW_LINE,EMPTY,1);
SetIndexLabel(0,TimeFrameStr+" %K line");
SetIndexLabel(2,TimeFrameStr+" %K CurrBar");
}
else
{
SetIndexStyle(0,DRAW_NONE);
SetIndexStyle(2,DRAW_NONE);
SetIndexLabel(0,NULL);
SetIndexLabel(2,NULL);
}
if ( ! HidePctD )
{
SetIndexStyle(1,DRAW_LINE,EMPTY,1);
SetIndexStyle(3,DRAW_LINE,EMPTY,1);
SetIndexLabel(1,TimeFrameStr+" %D Signal");
SetIndexLabel(3,TimeFrameStr+" %D CurrBar");
}
else
{
SetIndexStyle(1,DRAW_NONE);
SetIndexStyle(3,DRAW_NONE);
SetIndexLabel(1,NULL);
SetIndexLabel(3,NULL);
}
}
//+------------------------------------------------------------------+
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);
}
string TF2Str(int iPeriod) {
switch(iPeriod) {
case PERIOD_M1: return("M1");
case PERIOD_M5: return("M5");
case PERIOD_M15: return("M15");
case PERIOD_M30: return("M30");
case PERIOD_H1: return("H1");
case PERIOD_H4: return("H4");
case PERIOD_D1: return("D1");
case PERIOD_W1: return("W1");
case PERIOD_MN1: return("MN1");
default: return("M"+iPeriod);
}
return(0);
}
int GetHigherTimeFrame(int CurrentPeriod )
{
if ( CurrentPeriod == 0 ) CurrentPeriod = Period();
if( CurrentPeriod == 1 ) { return(5); }
else if( CurrentPeriod == 5 ) { return(15); }
else if( CurrentPeriod == 15 ) { return(30); }
else if( CurrentPeriod == 30 ) { return(60); }
else if( CurrentPeriod == 60 ) { return(240); }
else if( CurrentPeriod == 240 ) { return(1440); }
else if( CurrentPeriod == 1440 ) { return(10080); }
else if( CurrentPeriod == 10080 ) { return(43200); }
else if( CurrentPeriod == 43200 ) { return(43200); }
} // int GetHigherTimeFrame()