This script is designed to function as a technical analysis tool, specifically a Stochastic Oscillator. Its primary purpose is to help traders identify potential momentum shifts and "overbought" or "oversold" conditions by analyzing the relationship between recent price highs and lows.
How the Logic Works
The logic operates through a multi-step calculation process that transforms raw price data into visual signals:
1. Identifying Extremes (Highs and Lows) The script first looks back over a specific number of previous price bars (defined by the "KPeriod" setting). During this look-back, it scans for the highest high and the lowest low reached during that timeframe. By constantly tracking these peaks and valleys, the script establishes a range of movement for the asset.
2. Calculating the Main Line (%K) Once the highs and lows are identified, the script calculates the relative position of the current closing price within that range. It specifically looks at how much "room" is left between the close and the high, compared to the total distance between the high and low. This value is then converted into a percentage.
- The result is normalized (shifted) so that it centers around a specific midpoint, making it easier for a user to see when the price is moving toward an extreme upper or lower boundary.
3. Smoothing the Data (Signal Line) Because raw price movements can be volatile and "jittery," the script applies a secondary calculation called a Simple Moving Average to the Main Line. This creates a "Signal Line." Think of this as a smoothed-out version of the main data; it helps filter out minor market noise so that only significant trends are highlighted.
4. Visual Representation (Histogram) Finally, the script calculates the difference between the Main Line and the Signal Line. This difference is displayed as a histogram.
- When the histogram bars are large, it indicates a widening gap between the current price momentum and its average trend.
- When the bars shrink or cross over each other, it can suggest that the momentum is slowing down or reversing.
Summary of Components
- Main Line: Shows the current "speed" and position of the price relative to recent highs/lows.
- Signal Line: Acts as a baseline to confirm whether the Main Line's movement is significant enough to act on.
- Histogram: Provides a quick visual cue of the distance between the current price momentum and its average, helping to identify potential turning points in the market.
//+------------------------------------------------------------------+
//| Stochastic.mq4 |
//| Copyright © 2004, MetaQuotes Software Corp. |
//| http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net/"
#property indicator_separate_window
#property indicator_minimum -50
#property indicator_maximum 50
#property indicator_buffers 3
#property indicator_color1 LightSeaGreen
#property indicator_color2 Red
#property indicator_color3 Blue
//---- input parameters
extern int KPeriod=14;
extern int DPeriod=3;
extern int Slowing=3;
//---- buffers
double MainBuffer[];
double SignalBuffer[];
double HistoBuffer[];
double HighesBuffer[];
double LowesBuffer[];
//----
int draw_begin1=0;
int draw_begin2=0;
int draw_begin3=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
string short_name;
//---- 2 additional buffers are used for counting.
IndicatorBuffers(5);
SetIndexBuffer(3, HighesBuffer);
SetIndexBuffer(4, LowesBuffer);
//---- indicator lines
SetIndexStyle(0,DRAW_LINE);
SetIndexBuffer(0, MainBuffer);
SetIndexStyle(1,DRAW_LINE);
SetIndexBuffer(1, SignalBuffer);
SetIndexStyle(2,DRAW_HISTOGRAM);
SetIndexBuffer(2, HistoBuffer);
//---- name for DataWindow and indicator subwindow label
short_name="Sto("+KPeriod+","+DPeriod+","+Slowing+")";
IndicatorShortName(short_name);
SetIndexLabel(0,short_name);
SetIndexLabel(1,"Signal");
//----
draw_begin1=KPeriod+Slowing;
draw_begin2=draw_begin1+DPeriod;
draw_begin3=draw_begin1+DPeriod;
SetIndexDrawBegin(0,draw_begin1);
SetIndexDrawBegin(1,draw_begin2);
SetIndexDrawBegin(2,draw_begin3);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Stochastic oscillator |
//+------------------------------------------------------------------+
int start()
{
int i,k;
int counted_bars=IndicatorCounted();
double price;
//----
if(Bars<=draw_begin2) return(0);
//---- initial zero
if(counted_bars<1)
{
for(i=1;i<=draw_begin1;i++) MainBuffer[Bars-i]=0;
for(i=1;i<=draw_begin2;i++) SignalBuffer[Bars-i]=0;
}
//---- minimums counting
i=Bars-KPeriod;
if(counted_bars>KPeriod) i=Bars-counted_bars-1;
while(i>=0)
{
double min=1000000;
k=i+KPeriod-1;
while(k>=i)
{
price=Low[k];
if(min>price) min=price;
k--;
}
LowesBuffer[i]=min;
i--;
}
//---- maximums counting
i=Bars-KPeriod;
if(counted_bars>KPeriod) i=Bars-counted_bars-1;
while(i>=0)
{
double max=-1000000;
k=i+KPeriod-1;
while(k>=i)
{
price=High[k];
if(max<price) max=price;
k--;
}
HighesBuffer[i]=max;
i--;
}
//---- %K line
i=Bars-draw_begin1;
if(counted_bars>draw_begin1) i=Bars-counted_bars-1;
while(i>=0)
{
double sumlow=0.0;
double sumhigh=0.0;
for(k=(i+Slowing-1);k>=i;k--)
{
sumlow+=Close[k]-LowesBuffer[k];
sumhigh+=HighesBuffer[k]-LowesBuffer[k];
}
if(sumhigh==0.0) MainBuffer[i]=100.0-50;
else MainBuffer[i]=sumlow/sumhigh*100-50;
i--;
}
//---- last counted bar will be recounted
if(counted_bars>0) counted_bars--;
int limit=Bars-counted_bars;
//---- signal line is simple movimg average
for(i=0; i<limit; i++)
SignalBuffer[i]=iMAOnArray(MainBuffer,Bars,DPeriod,0,MODE_SMA,i);
for(i=0; i<limit; i++)
HistoBuffer[i]=MainBuffer[i]-SignalBuffer[i];
//----
return(0);
}
//+------------------------------------------------------------------+
Comments