This script is a technical analysis tool designed to identify and visualize market cycles by analyzing the underlying rhythm of price movements. Rather than looking at simple price action, it attempts to calculate the "heartbeat" of the market to determine when trends are likely to repeat or shift.
Core Logic Overview
The logic operates in three distinct phases: identifying trend changes, measuring the dimensions of those trends, and calculating a cycle-based oscillator.
1. Trend Identification and Measurement
The script begins by monitoring two different moving averages (fast and slow). When these lines cross each other, the script marks a "trend change." It specifically looks for these intersections to define the boundaries of a market cycle.
During these cycles, the script performs two specific calculations:
- Time Duration: It tracks how many bars (time units) occur between each trend crossing.
- Price Deviation: It measures the distance between the highest and lowest price points reached during those same cycles.
2. Statistical Averaging
Instead of looking at just the most recent move, the script looks back at a pre-defined number of previous crossings (based on the "Crosses" setting). It averages these historical data points to determine:
- The Average Cycle Length: How many bars, on average, does it take for the market to complete a trend shift?
- The Average Deviation: How much price movement typically occurs within those cycles?
3. Stochastic Cycle Calculation
Once the script knows the "average" length of a cycle, it uses this information to create a custom oscillator. It looks at the MACD (a standard momentum indicator) and compares its current value against its high and low points over that specific average cycle length.
This produces a percentage-based value (0 to 100) that represents where the current price action sits within its historical "rhythm."
Final Output
The result is a smooth line on your chart that tells you where the market is currently positioned in its expected cycle. By visualizing this, the logic aims to show whether the market is nearing the end of a typical trend or if it is just beginning a new phase based on historical averages. It also provides a live comment on the screen showing the current average deviation and the number of bars per cycle.
//+------------------------------------------------------------------+
//| Cycle_KROUFR_version.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008 | Grayman77, zIG, akadex"
#property link "ForexResearch"
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1 20
#property indicator_level2 50
#property indicator_level3 80
#property indicator_buffers 1
#property indicator_color1 DarkOrchid
//---- input parameters
extern int FastMA=12;
extern int SlowMA=24;
extern int Crosses=50;
extern bool Comments=true;
//---- buffers
double MA[];
double MCD[];
double MAfast[],MAslow[];
double Cross[];
double max_min[];
double PointDeviation[];
double PeriodTimeAVG[];
//---- var
double smconst,ST,max,min;
int ShiftFirstCross; // ñìåùåíèå ïåðâîãî ïåðåñå÷åíèÿ c íà÷àëà èñòîðèè
int ShiftCrossesCross; // ñìåùåíèå (Crosses+1)-ãî ïåðåñå÷åíèÿ c íà÷àëà èñòîðèè (ïåðâîå - ïðîïóñêàåì)
int k;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
// string short_name;
//---- indicator line
IndicatorBuffers(8);
SetIndexBuffer(0, MA);
SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,2,DarkOrchid);
SetIndexBuffer(1, MCD);
SetIndexBuffer(2, MAfast);
SetIndexBuffer(3, MAslow);
SetIndexBuffer(4, Cross);
SetIndexBuffer(5, max_min);
SetIndexBuffer(6, PointDeviation);
SetIndexBuffer(7, PeriodTimeAVG);
SetIndexEmptyValue(0,0.0);
SetIndexEmptyValue(1,0.0);
SetIndexEmptyValue(2,0.0);
SetIndexEmptyValue(3,0.0);
SetIndexEmptyValue(4,0.0);
SetIndexEmptyValue(5,0.0);
SetIndexEmptyValue(6,0.0);
SetIndexEmptyValue(7,0.0);
ShiftFirstCross=0;
ShiftCrossesCross=0;
k=0;
max=0.;
min=1000000.;
return(0);
}
int deinit()
{
Comment("");
return(0);
}
//+------------------------------------------------------------------+
//| Schaff Trend Cycle |
//+------------------------------------------------------------------+
int start()
{
int counted_bars=IndicatorCounted();
int i,j,limit,NumberCross,BarsCross;
double prev,MinMACD,MaxMACD,delta,Sum_max_min;
if(Bars<=SlowMA) return(-1);
//---- ïîñëåäíèé ïîñ÷èòàííûé áàð áóäåò ïåðåñ÷èòàí
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;
if(limit>Bars-SlowMA-1) limit=Bars-SlowMA-1;
//+------------------------------------------------------------------+
//| Time AVG |
//+------------------------------------------------------------------+
for(i=limit;i>0;i--)
{
Cross[i]=0.;
// Âû÷èñëèòü çíà÷åíèÿ ñðåäíèõ è ïîìåñòèòü â áóôåðû
MAfast[i]=iMA(NULL,Period(),FastMA,0,MODE_SMA,PRICE_CLOSE,i);
MAslow[i]=iMA(NULL,Period(),SlowMA,0,MODE_SMA,PRICE_CLOSE,i);
// Íàéòè ïåðåñå÷åíèÿ ñðåäíèõ
if(MAfast[i]>=MAslow[i] && MAfast[i+1]<MAslow[i+1]) // áûñòðàÿ ïåðåñåêàåò ìåäëåííóþ ñíèçó ââåðõ
{
// Åñëè ýòî ïåðâîå íàéäåííîå ïåðåñå÷åíèå - çàïîìíèòü åãî ñìåùåíèå
if(ShiftFirstCross==0) ShiftFirstCross=i;
// Åñëè åùå íå íàéäåíî Crosses+1 ïåðåñå÷åíèå
if(ShiftCrossesCross==0)
{
k++;
// åñëè íàéäåíî - çàïîìíèòü
if(k==Crosses+1) ShiftCrossesCross=i;
}
// Çàïîìíèòü ôàêò ïåðåñå÷åíèÿ â áóôåðå
Cross[i]=1.;
// Çàïîìíèòü ðàçíîñòü max-min â áóôåðå
max_min[i]=max-min;
// Ñáðîñèòü çíà÷åíèÿ max è min
max=0.;
min=1000000.;
}
if(MAfast[i]<=MAslow[i] && MAfast[i+1]>MAslow[i+1]) // áûñòðàÿ ïåðåñåêàåò ìåäëåííóþ ñâåðõó âíèç
{
// Åñëè ýòî ïåðâîå íàéäåííîå ïåðåñå÷åíèå - çàïîìíèòü åãî ñìåùåíèå
if(ShiftFirstCross==0) ShiftFirstCross=i;
// Åñëè åùå íå íàéäåíî Crosses+1 ïåðåñå÷åíèå
if(ShiftCrossesCross==0)
{
k++;
// åñëè íàéäåíî - çàïîìíèòü
if(k==Crosses+1) ShiftCrossesCross=i;
}
// Çàïîìíèòü ôàêò ïåðåñå÷åíèÿ â áóôåðå
Cross[i]=-1.;
// Çàïîìíèòü ðàçíîñòü max-min â áóôåðå
max_min[i]=max-min;
// Ñáðîñèòü çíà÷åíèÿ max è min
max=0.;
min=1000000.;
}
// Âûáèðàåì ìàêñèìàëüíóþ öåíó (èç High) ìåæäó ïåðåñå÷åíèÿìè è ìèíèìàëüíóþ èç Low
if(max<High[i]) max=High[i];
if(min>Low[i]) min=Low[i];
}
// Ñ÷èòàåì ñòàòèñòèêó
if(limit>ShiftCrossesCross) limit=ShiftCrossesCross;
for(i=limit;i>0;i--)
{
// Íàéòè ïåðâîå ïåðåñå÷åíèå (ñïðàâà íàëåâî)
j=i;
while(Cross[j]==0.) j++;
// Íàéòè ñëåäóþùèå Crosses ïåðåñå÷åíèé
NumberCross=0;
BarsCross=0;
Sum_max_min=0.;
while(NumberCross<Crosses)
{
// Åñëè íàéäåíî î÷åðåäíîå ïåðåñå÷åíèå
if(Cross[j]!=0.)
{
NumberCross++; // óâåëè÷èòü íà 1 ñ÷åò÷èê ïåðåñå÷åíèé
Sum_max_min=Sum_max_min+max_min[j];
}
j++;
BarsCross++;
}
// Èòîãîâûå çíà÷åíèÿ Time AVG
PeriodTimeAVG[i]=BarsCross/Crosses; // ñðåäíåå êîë-âî áàðîâ ìåæäó ïåðåñå÷åíèÿìè
PointDeviation[i]=NormalizeDouble(Sum_max_min/Crosses/2./Point,0); // ñð. îòêëîíåíèå
}
//+------------------------------------------------------------------+
//| Cycle |
//+------------------------------------------------------------------+
for(i=limit;i>=0;i--)
{
// Âû÷èñëèòü MACD
MCD[i]=iMA(NULL,0,FastMA,0, MODE_EMA, PRICE_TYPICAL, i)-
iMA(NULL,0,SlowMA,0, MODE_EMA, PRICE_TYPICAL, i);
// Íàéòè ìàêñ. è ìèí. çíà÷åíèÿ MACD íà ïåðèîäå TimeAVG
MinMACD=MCD[i];
MaxMACD=MCD[i];
for(j=i+1;j<i+PeriodTimeAVG[i+1];j++)
{
if(MCD[j]<MinMACD) MinMACD=MCD[j];
if(MCD[j]>MaxMACD) MaxMACD=MCD[j];
}
// Âû÷èñëèòü ñòîõàñòèê îò MACD
delta=MaxMACD-MinMACD;
if(delta==0.) // ïðîâåðêà äëÿ èñêëþ÷åíèÿ äåëåíèÿ íà 0
ST=50.;
else // åñëè íå 0 - äåëèì
{
ST=(MCD[i]-MinMACD)/delta*100;
}
// Çàïîëíèòü áóôåð
prev=MA[i+1];
MA[i]=(2./(1.+PeriodTimeAVG[i+1]/2.))*(ST-prev)+prev;
//Âûâåñòè êîììåíòàðèè
if (!IsTesting() && Comments)
Comment(" Deviation: "+DoubleToStr(PointDeviation[1],0)+
" points\n Average Amount of Bars : "+DoubleToStr(PeriodTimeAVG[1],0)+
"\n Crosses: "+Crosses);
}
return(0);
}
//+------------------------------------------------------------------+
Comments