CycleIdentifier

Download script
Author:
CycleIdentifier

This script is designed to analyze market trends by identifying "cycles"—essentially recognizing the repetitive waves of price movement. Instead of just looking at the raw price, it interprets whether the market is moving in significant large-scale cycles or smaller, more rapid fluctuations.

Core Analytical Logic

The logic operates on three distinct layers of data processing:

1. Trend Smoothing and Filtering The script first cleans up "market noise" by applying a moving average to the price. It uses this smoothed price as its primary baseline. Additionally, it offers an optional secondary filter (using either a Smooth Moving Average or an RSI indicator) to determine the underlying momentum. This ensures that the tool responds to actual structural shifts rather than minor, insignificant price wobbles.

2. Multi-Layer Cycle Detection The script tracks two different types of cycles simultaneously:

  • Minor Cycles: These identify shorter-term price fluctuations. The logic monitors how quickly the smoothed price moves from one peak to another. If a move is large enough to exceed a specific "Sweep" threshold (a percentage or point distance), it flags a completed cycle.
  • Major Cycles: These track much broader, long-term trends. By using a higher strength multiplier, the script ignores minor fluctuations and only registers signals when the market makes significant structural moves.

3. Dynamic State Switching The script uses a "state machine" approach to keep track of the market's direction. It remembers where the previous peak or valley was and compares the current price against those historical points.

  • When the price breaks above a previous high in a specific way, the logic triggers a "Buy" cycle signal.
  • When the price drops below a previous low significantly, it triggers a "Sell" cycle signal.

Visual Representation

The script translates these mathematical findings into visual data on your chart:

  • Histograms: These act as visual markers for the identification of Buy and Sell cycles (both Major and Minor).
  • Trend Lines: The logic identifies specific segments to draw lines, helping to visualize the path and boundaries of the current price cycle.

Summary of Behavior

In simple terms, this script acts like an automated "trend detective." It filters out the noise of the market, calculates how much distance a price wave must travel to be considered significant, and then marks those movements on your screen as either Major or Minor cycles. This allows you to see the underlying structure of the market's "heartbeat" rather than just the chaotic movement of individual candles.

Indicators Used
Moving average indicatorRelative strength index
Miscellaneous
Implements a curve of type %1
16 Views
0 Downloads
0 Favorites
CycleIdentifier
//+------------------------------------------------------------------+
//|                                              CycleIdentifier.mq4 |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
//----
#property indicator_separate_window
#property indicator_buffers 6
//----
#property indicator_color1 DarkGray
#property indicator_color2 Lime
#property indicator_color3 Red
#property indicator_color4 DarkGreen
#property indicator_color5 Brown
//----
#property indicator_minimum -1.2
#property indicator_maximum 1.2
//----
extern int       PriceActionFilter=1;
extern int       Length=3;
extern int       MajorCycleStrength=4;
extern bool      UseCycleFilter=false;
extern int       UseFilterSMAorRSI=1;
extern int       FilterStrengthSMA=12;
extern int       FilterStrengthRSI=21;
//----
double LineBuffer[];
double MajorCycleBuy[];
double MajorCycleSell[];
double MinorCycleBuy[];
double MinorCycleSell[];
double ZL1[];
//----
double CyclePrice=0.0, Strength =0.0, SweepA=0.0, SweepB=0.0;
int Switch=0, Switch2=0,   SwitchA=0, SwitchB=0, SwitchC=0, SwitchD=0, SwitchE=0, SwitchAA=0, SwitchBB=0;
double Price1BuyA=0.0, Price2BuyA=0.0;
int Price1BuyB=1.0, Price2BuyB=1.0;
double Price1SellA=0.0, Price2SellA=0.0;
int Price1SellB=0.0, Price2SellB=0.0;
bool ActiveSwitch=True, BuySwitchA=FALSE, BuySwitchB=FALSE, SellSwitchA=FALSE, SellSwitchB=FALSE;
int BuySellFac=01;
bool Condition1, Condition2, Condition3, Condition6;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
  int init()  
  {
   SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,2);
   SetIndexBuffer(0,LineBuffer);
   SetIndexStyle(1,DRAW_HISTOGRAM,STYLE_SOLID,3);
   SetIndexBuffer(1,MajorCycleBuy);
   SetIndexStyle(2,DRAW_HISTOGRAM,STYLE_SOLID,3);
   SetIndexBuffer(2,MajorCycleSell);
   SetIndexStyle(3,DRAW_HISTOGRAM,STYLE_SOLID,1);
   SetIndexBuffer(3,MinorCycleBuy);
   SetIndexStyle(4,DRAW_HISTOGRAM,STYLE_SOLID,1);
   SetIndexBuffer(4,MinorCycleSell);
   SetIndexStyle(5,DRAW_NONE);
   SetIndexBuffer(5,ZL1);
   SetIndexEmptyValue(1,0.0);
   SetIndexEmptyValue(2,0.0);
   SetIndexEmptyValue(3,0.0);
   SetIndexEmptyValue(4,0.0);
   SetIndexEmptyValue(5,0.0);
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int deinit() {return(0);}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
  int start() 
  {
   int counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   // if(counted_bars>0) counted_bars--;
   // int position=Bars-1;
   int position=Bars-counted_bars;
   if (position<0) position=0;
//----
   int rnglength=250;
   double range=0.0, srange=0.0;
   for(int pos=position; pos >=0; pos--)
     {
      srange=0.0;
      int j=0;
      for(int i=0;i<rnglength;i++)
        {
         j++;
         int posr=pos + i;
         if (posr>=Bars)
            break;
         srange=srange + (High[posr] - Low[posr]);
        }
      range=srange/j * Length;
      int BarNumber=Bars-pos; //??????????
      if (BarNumber < 0)
         BarNumber=0;
      CyclePrice=iMA(NULL, 0, PriceActionFilter, 0, MODE_SMMA, PRICE_CLOSE, pos);
      if (UseFilterSMAorRSI==1)
         ZL1[pos]=ZeroLag(CyclePrice,FilterStrengthSMA, pos);
      if (UseFilterSMAorRSI==2)
         ZL1[pos]=ZeroLag( iRSI(NULL, 0, 14, CyclePrice, FilterStrengthRSI ), FilterStrengthRSI, pos);
      if (ZL1[pos] > ZL1[pos+1])
         SwitchC=1;
      if (ZL1[pos] < ZL1[pos+1])
         SwitchC=2;
      if (BarNumber<=1)
        {
         if (Strength==0)
            SweepA =range;
         else
            SweepA=Strength;
         Price1BuyA =CyclePrice;
         Price1SellA =CyclePrice;
        }
      /* ***************************************************************** */
      if (BarNumber > 1)
        {
         if (Switch > -1)
           {
            if (CyclePrice < Price1BuyA)
              {
               if (UseCycleFilter && (SwitchC==2) && BuySwitchA )
                 {
                  MinorCycleBuy[pos + BarNumber - Price1BuyB]=0; //MinorBuySell
                  LineBuffer[pos + BarNumber - Price1BuyB ]=0; //line
                 }
               if (!UseCycleFilter && BuySwitchA)
                 {
                  MinorCycleBuy[pos +BarNumber - Price1BuyB]=0;
                  LineBuffer[pos +BarNumber - Price1BuyB]=0;
                 }
               Price1BuyA=CyclePrice;
               Price1BuyB=BarNumber;
               BuySwitchA=TRUE;
              }
            else if (CyclePrice > Price1BuyA)
                 {
                  SwitchA=BarNumber - Price1BuyB;
                  if (!UseCycleFilter)
                    {
                     MinorCycleBuy[pos +SwitchA]=-1;//MinorBuySell - DarkGreen
                     LineBuffer[pos +SwitchA]=-1;//line
                    }
                  if (UseCycleFilter && SwitchC ==1)
                    {
                     MinorCycleBuy[pos +SwitchA]=-1;  //MinorBuySell
                     LineBuffer[pos +SwitchA]=-1; //line
                     SwitchD=1;
                    }
                  else
                    {
                     SwitchD=0;
                    }
                  BuySwitchA=TRUE;
                  double cyclePrice1=iMA(NULL, 0, PriceActionFilter, 0, MODE_SMMA, PRICE_CLOSE, pos + SwitchA);
                  if (ActiveSwitch)
                    {
                     Condition1=CyclePrice - cyclePrice1>=SweepA;
                    }
                  else
                    {
                     Condition1=CyclePrice>=cyclePrice1 * (1 + SweepA/1000);
                    }
                  if (Condition1 && SwitchA>=BuySellFac)
                    {
                     Switch= - 1;
                     Price1SellA=CyclePrice;
                     Price1SellB=BarNumber;
                     SellSwitchA=FALSE;
                     BuySwitchA=FALSE;
                    }
                 }
           }
         if(Switch < 1)
           {
            if (CyclePrice > Price1SellA)
              {
               if (UseCycleFilter && SwitchC==1 && SellSwitchA )
                 {
                  MinorCycleSell[pos +BarNumber - Price1SellB]=0; //MinorBuySell
                  LineBuffer[pos +BarNumber - Price1SellB ]=0; //line
                 }
               if (!UseCycleFilter && SellSwitchA )
                 {
                  MinorCycleSell[pos +BarNumber - Price1SellB]=0;//MinorBuySell
                  LineBuffer[pos +BarNumber - Price1SellB]=0;//line
                 }
               Price1SellA=CyclePrice;
               Price1SellB=BarNumber;
               SellSwitchA=TRUE;
              }
            else if (CyclePrice < Price1SellA)
                 {
                  SwitchA=BarNumber - Price1SellB;
                  if (!UseCycleFilter)
                    {
                     MinorCycleSell[pos +SwitchA]=1; // MinorBuySell darkRed
                     LineBuffer[pos +SwitchA]=1; //"CycleLine"
                    }
                  if (UseCycleFilter && (SwitchC==2))
                    {
                     MinorCycleSell[pos +SwitchA]=1;//MinorBuySell darkRed
                     LineBuffer[pos +SwitchA]=1;//CycleLine
                     SwitchD =2;
                    }
                  else
                     SwitchD =0;
                  SellSwitchA=TRUE;
                  double cyclePrice2=iMA(NULL, 0, PriceActionFilter, 0, MODE_SMMA, PRICE_CLOSE, pos + SwitchA);
                  if (ActiveSwitch)
                     Condition1=(cyclePrice2 - CyclePrice)>=SweepA;
                  else
                     Condition1=CyclePrice<=(cyclePrice2 * (1 - SweepA/1000));
                  if (Condition1 && SwitchA>=BuySellFac)
                    {
                     Switch=1;
                     Price1BuyA=CyclePrice;
                     Price1BuyB=BarNumber;
                     SellSwitchA=FALSE;
                     BuySwitchA=FALSE;
                    }
                 }
             }
         }
      LineBuffer[pos]=0;
      MinorCycleBuy[pos]=0;
      MinorCycleSell[pos]=0;
//----
      if (BarNumber==1)
        {
         if (Strength==0)
            SweepB =range *  MajorCycleStrength;
         else
            SweepB=Strength * MajorCycleStrength;
         Price2BuyA=CyclePrice;
         Price2SellA=CyclePrice;
        }
      if (BarNumber > 1)
        {
         if (Switch2  >  - 1)
           {
            if (CyclePrice < Price2BuyA)
              {
               if (UseCycleFilter && SwitchC==2 && BuySwitchB )
                 {
                  MajorCycleBuy [pos +BarNumber - Price2BuyB]=0; //MajorBuySell,green
                  //		      LineBuffer[pos + BarNumber - Price2BuyB ] = 0; //line -----
                 }
               if (!UseCycleFilter && BuySwitchB )
                 {
                  MajorCycleBuy [pos +BarNumber - Price2BuyB]=0;//MajorBuySell,green
                  //			      LineBuffer[pos + BarNumber - Price2BuyB ] = 0; //line-----------
                 }
               Price2BuyA=CyclePrice;
               Price2BuyB=BarNumber;
               BuySwitchB=TRUE;
              }
            else if (CyclePrice > Price2BuyA)
                 {
                  SwitchB=BarNumber - Price2BuyB;
                  if (!UseCycleFilter)
                    {
                     MajorCycleBuy [pos +SwitchB]=-1; //MajorBuySell green
                     //               LineBuffer[pos + SwitchB] = -1; //line--------------
                    }
                  if (UseCycleFilter && SwitchC ==1)
                    {
                     MajorCycleBuy [pos +SwitchB]=-1; //MajorBuySell green
                     //             LineBuffer[pos + SwitchB] = -1; //line-----------------
                     SwitchE =1;
                    }
                  else
                     SwitchE =0;
                  BuySwitchB=TRUE;
                  double cyclePrice3=iMA(NULL, 0, PriceActionFilter, 0, MODE_SMMA, PRICE_CLOSE, pos + SwitchB);
                  if (ActiveSwitch)
                     Condition6=CyclePrice - cyclePrice3>=SweepB;
                  else
                     Condition6=CyclePrice>=cyclePrice3 * (1 + SweepB/1000);
                  if (Condition6 && SwitchB>=BuySellFac)
                    {
                     Switch2= - 1;
                     Price2SellA=CyclePrice;
                     Price2SellB=BarNumber;
                     SellSwitchB=FALSE;
                     BuySwitchB=FALSE;
                    }
                 }
             }
         if (Switch2  < 1)
           {
            if (CyclePrice  > Price2SellA )
              {
               if (UseCycleFilter && SwitchC ==1 && SellSwitchB )
                 {
                  MajorCycleSell [pos +BarNumber - Price2SellB]=0; //"MajorBuySell",red 
                  //			      LineBuffer[pos + BarNumber - Price2SellB ] = 0; //line -----
                 }
               if (!UseCycleFilter && SellSwitchB )
                 {
                  MajorCycleSell [pos +BarNumber - Price2SellB]=0;//"MajorBuySell",red 
                  //              LineBuffer[pos + BarNumber - Price2SellB ] = 0; //line -----
                 }
               Price2SellA=CyclePrice;
               Price2SellB=BarNumber;
               SellSwitchB=TRUE;
              }
            else if (CyclePrice < Price2SellA)
                 {
                  SwitchB=BarNumber - Price2SellB ;
                  if (!UseCycleFilter)
                    {
                     MajorCycleSell[pos + SwitchB]=1; //"MajorBuySell",red 
                     // 		      LineBuffer[pos + SwitchB ] = 1; //line -----
                    }
                  if (UseCycleFilter && SwitchC ==2)
                    {
                     MajorCycleSell [pos + SwitchB]=1; //"MajorBuySell",red 
                     //		      LineBuffer[pos + SwitchB ] = 1; //line -----
                     SwitchE =2;
                    }
                  else
                     SwitchE =0;
                  SellSwitchB=TRUE;
                  double cyclePrice4=iMA(NULL, 0, PriceActionFilter, 0, MODE_SMMA, PRICE_CLOSE, pos + SwitchB);
                  if (ActiveSwitch)
                     Condition6=cyclePrice4 - CyclePrice>=SweepB;
                  else
                     Condition6=CyclePrice<=cyclePrice4 * (1.0 - SweepB/1000.0);
                  if (Condition6 && SwitchB>=BuySellFac)
                    {
                     Switch2=1;
                     Price2BuyA=CyclePrice;
                     Price2BuyB=BarNumber;
                     SellSwitchB=FALSE;
                     BuySwitchB=FALSE;
                    }
                 }
             }
         }
      LineBuffer[pos]=0;
      MajorCycleSell[pos]=0;
      MajorCycleBuy[pos]=0;
     }
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double ZeroLag(double price, int length, int pos)
  {
   if (length < 3)
     {
      return(price);
     }
   double aa=MathExp(-1.414*3.14159/length);
   double bb=2*aa*MathCos(1.414*180/length);
   double CB=bb;
   double CC=-aa*aa;
   double CA=1 - CB - CC;
   double CD=CA*price + CB*ZL1[pos+1] + CC*ZL1[pos+2];
   return(CD);
  }
//+------------------------------------------------------------------+

Comments