Cycle_KROUFR_version_001
Download scriptThis script is designed to identify and visualize the cyclical nature of market movements by analyzing how frequently and with what intensity price trends "reset" or flip direction. Instead of simply looking at whether the price is going up or down right now, it calculates the underlying rhythm of the market over time.
The logic operates through three primary stages:
1. Identifying Trend Reversals
The script begins by tracking two different types of Moving Averages (fast and slow). When these two averages cross each other, it marks a "trend reversal." The tool doesn't just look at one crossing; it tracks a specific number of these crossings (defined by the user) to establish a historical pattern. During these cycles, it records two key pieces of data:
- The Time: How many candles/bars pass between each reversal.
- The Magnitude: The distance between the highest price reached and the lowest price reached during that specific cycle.
2. Calculating Market Rhythm (Time & Deviation)
Once the script has enough data on these reversals, it calculates two essential averages:
- Average Period: It determines the average number of bars that occur between trend changes. This helps identify the "heartbeat" of the market—essentially how long a typical trend lasts before it exhausts itself and turns around.
- Point Deviation: It calculates the average intensity of these moves in price points. This tells the user how "volatile" or "wide" the typical swings are over the identified periods.
3. Generating the Cycle Indicator
The final stage uses this historical "heartbeat" to create a visual indicator (similar to a Stochastic oscillator but based on the market's unique cycle).
- It calculates a MACD (Moving Average Convergence Divergence) value, which measures momentum.
- It then compares the current MACD value against the highest and lowest values achieved during the "Average Period" identified in step 2.
- The result is a smoothed line that oscillates between 0 and 100.
Summary for the User: This tool tells you where the market currently sits within its own natural cycle. If the indicator is near the top, it suggests the current trend is nearing the end of its typical duration based on historical averages. If it is at the bottom, it suggests a new cycle may be beginning. It essentially takes the "messy" data of price history and converts it into a predictable rhythm of waves.
//+------------------------------------------------------------------+
//| 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(" Áîêîâûå îòêëîíåíèÿ: "+DoubleToStr(PointDeviation[1],0)+
" ïóíêòîâ\n Ñðåäíåå êîëè÷åñòâî áàðîâ: "+DoubleToStr(PeriodTimeAVG[1],0)+
"\n Ïåðåñå÷åíèé: "+Crosses);
}
return(0);
}
//+------------------------------------------------------------------+
Comments