//+------------------------------------------------------------------+
//| 2011 MJ                                                          |
//+------------------------------------------------------------------+



#property indicator_separate_window
#property indicator_buffers   4
#property  indicator_minimum 0
#property  indicator_maximum 1
#property indicator_color1 Red 
#property indicator_color2 Blue
#property indicator_color3 Silver
#property indicator_color4 Black
#property indicator_width1 5
#property indicator_width2 5
#property indicator_width3 5
#property indicator_width4 5

//===================================
//---- indicator parameters
//===================================

extern string ______________0____________ = "==General Settings==";
extern int       overBoughtLevel =  80;
extern int       overSoldLevel    =  20;
extern string __note0__="==AllBetweenOverBoughtSold==";
extern string __note0a__="direction check only if all included";
extern string __note0b__="Stochs are between OverBoughtSold";
extern bool AllBetweenOverBoughtSold=true;
extern string ______________0a____________ = "==MinNumberSameDirection==";
extern string __note0c__="e.g. 4 stochs are included";
extern string __note0d__="MinNumberSameDirection 3";
extern string __note0e__="Alert when any 3 or more out";
extern string __note0f__="of the 4 have the same direction";
extern string __note0g__="1 or greater";
extern int MinNumberSameDirection=3;
extern bool ConsiderOnlyClosedCandles=false;
extern bool CheckOnlyAtNewChartBar=true;
extern string ______________0b____________= "==Alert==";
extern string __note__ = "only up or down direction count";
extern bool		UseAdditionalSoundAlert	= true;
extern string SoundFileName="alert.wav";


extern string ______________0c____________= "=== STOCH SETTINGS ===";
extern string    __note3__  = "All DPeriod is set to 1";          // DPerid is not taken into account
extern string __note4__ = "MAMethods: 0=sma, 1=ema, 2=smma, 3=lwma";
extern string __note5__ = "PriceField:0=high/low, 1=close/close";
extern string ______________1____________ = "==STOCH 1==";
extern bool includeStoch1 = false;
extern int Stoch1_TimeFrame = 1;
extern int     Stoch1_KPeriod     = 14;
extern int       Stoch1_Slowing     =  3;
extern int       Stoch1_MAMethod    =   0;
extern int       Stoch1_PriceField  =   0;

extern string ______________2____________ = "==STOCH 2==";
extern bool includeStoch2 = true;
extern int Stoch2_TimeFrame = 5;
extern int     Stoch2_KPeriod     =  14;
extern int       Stoch2_Slowing     =  3;
extern int       Stoch2_MAMethod    =   0;
extern int       Stoch2_PriceField  =   0;

extern string ______________3____________ = "==STOCH 3==";
extern bool includeStoch3 = true;
extern int Stoch3_TimeFrame = 15;
extern int     Stoch3_KPeriod     =  14;
extern int       Stoch3_Slowing     =  3;
extern int       Stoch3_MAMethod    =   0;
extern int       Stoch3_PriceField  =   0;


extern string ______________4____________ = "==STOCH 4==";
extern bool includeStoch4 = true;
extern int Stoch4_TimeFrame = 30;
extern int     Stoch4_KPeriod     =  14;
extern int       Stoch4_Slowing     =  3;
extern int       Stoch4_MAMethod    =   0;
extern int       Stoch4_PriceField  =   0;


extern string ______________5____________ = "==STOCH 5==";
extern bool includeStoch5 = false;
extern int Stoch5_TimeFrame = 60;
extern int     Stoch5_KPeriod     =  14;
extern int       Stoch5_Slowing     =  3;
extern int       Stoch5_MAMethod    =   0;
extern int       Stoch5_PriceField  =   0;


extern string ______________6____________ = "==STOCH 6==";
extern bool includeStoch6 = false;
extern int Stoch6_TimeFrame = 240;
extern int     Stoch6_KPeriod     =  14;
extern int       Stoch6_Slowing     =  3;
extern int       Stoch6_MAMethod    =   0;
extern int       Stoch6_PriceField  =   0;





double Stoch1_percentK, Stoch1_percentK_previous,Stoch2_percentK, Stoch2_percentK_previous,Stoch3_percentK, Stoch3_percentK_previous,Stoch4_percentK, Stoch4_percentK_previous,Stoch5_percentK, Stoch5_percentK_previous,Stoch6_percentK, Stoch6_percentK_previous;
string LastDirection="None";

double UP[];
double DOWN[];
double BOTH[];
double SPECIAL[];

//----
int  DPeriod     =  1;          // DPerid is not taken into account

int startShift;
bool alertflag=0;
int NumberOfIncludedStochs=0; 
int SmallestStochTimeFrame;

bool _error=false;
//+----------------------------------------------------------------------------+
//|                                                                            |
//|  Custom indicator initialization function                                  |
//|                                                                            |
//+----------------------------------------------------------------------------+
int init()
{
   
   SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(0,UP);
   SetIndexLabel(0,NULL);
   
   
   SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(1,DOWN);
   SetIndexLabel(1,NULL);
   
   SetIndexStyle(2,DRAW_HISTOGRAM);
   SetIndexBuffer(2,BOTH);
   SetIndexLabel(2,NULL);
      
   SetIndexStyle(3,DRAW_HISTOGRAM);
   SetIndexBuffer(3,SPECIAL);
   SetIndexLabel(3,NULL);      
 

	IndicatorShortName("MultiStochDirectionAlert_mj"); 
    IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS));
     

//===SOME INPUT CHECKS
    // Stoch1_TimeFrame smallest and all in order
    if(Stoch1_TimeFrame >= Stoch2_TimeFrame || Stoch2_TimeFrame >= Stoch3_TimeFrame  || Stoch3_TimeFrame >= Stoch4_TimeFrame || Stoch4_TimeFrame >= Stoch5_TimeFrame || Stoch5_TimeFrame >= Stoch6_TimeFrame)
        {
        if(alertflag == 0) {Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@ ERROR!! All 6 Stoch TimeFrame setting must start from smallest to greatest: each one greater than the previous."); alertflag = 1;}
        _error=true;
        return;
        }
        
    // SET NumberOfIncludedStochs and SmallestStochTimeFrame  (need to start at the top for the SmallestStochTimeFrame to be correct)
    if (includeStoch6) {NumberOfIncludedStochs++; SmallestStochTimeFrame=Stoch6_TimeFrame;}
    if (includeStoch5) {NumberOfIncludedStochs++; SmallestStochTimeFrame=Stoch5_TimeFrame;}
    if (includeStoch4) {NumberOfIncludedStochs++; SmallestStochTimeFrame=Stoch4_TimeFrame;}
    if (includeStoch3) {NumberOfIncludedStochs++; SmallestStochTimeFrame=Stoch5_TimeFrame;}
    if (includeStoch2) {NumberOfIncludedStochs++; SmallestStochTimeFrame=Stoch2_TimeFrame;}
    if (includeStoch1) {NumberOfIncludedStochs++; SmallestStochTimeFrame=Stoch1_TimeFrame;}
    
    
    
    // Check Chart Period not above Stoch1 TimeFrame 
    if(Period() > SmallestStochTimeFrame)
        {
        if(alertflag == 0) {Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@ ERROR!! Chart Period may not be greater than SmallestStochTimeFrame: "+SmallestStochTimeFrame); alertflag = 1;}
        _error=true;        
        return;
        }
   

    //  CHECK input MinNumberSameDirection
    if(MinNumberSameDirection > NumberOfIncludedStochs)
        {
        if(alertflag == 0) {Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@ ERROR!! MinNumberSameDirection: " + MinNumberSameDirection + " may not be greater than the number of included Stochs: " +NumberOfIncludedStochs); alertflag = 1;}
        _error=true;
        return;
        }

    if(MinNumberSameDirection < 0)
        {
        if(alertflag == 0) {Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@ ERROR!! MinNumberSameDirection: " + MinNumberSameDirection + " must be 0 or greater"); alertflag = 1;}
        _error=true;        
        return;
        }

    // CHECK SPECIAL CASE
    if(MinNumberSameDirection == 0 && !AllBetweenOverBoughtSold)
        {
        if(alertflag == 0) {Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@ ERROR!! MinNumberSameDirection: " + MinNumberSameDirection + " SPECIAL CASE: you MUST also enable < AllBetweenOverBoughtSold = true > "); alertflag = 1;}
        _error=true;        
        return;
        }
        
        


    // set correct Start Shift
    
    if (ConsiderOnlyClosedCandles)
        {
        startShift=1;
        }
    else
        {
        startShift=0;
        }
        
        
    // INFO 
    Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@ INFO!! LastDirection Reset to NONE!! You have: < " + NumberOfIncludedStochs + " > Stochastic included for consideration.");

   
           

    return(0);
}
//+----------------------------------------------------------------------------+



//+----------------------------------------------------------------------------+
//|                                                                            |
//|  Custom indicator deinitialization function                                |
//|                                                                            |
//+----------------------------------------------------------------------------+
int deinit()
{
   return(0);
}
//+----------------------------------------------------------------------------+


//+----------------------------------------------------------------------------+
//|                                                                            |
//|  Custom indicator iteration function                                       |
//|                                                                            |
//+----------------------------------------------------------------------------
int start()
    {
    
    if (_error)
        {    
        PlaySound(SoundFileName);
        return;
        }
        
    if (CheckOnlyAtNewChartBar && !NewBar())
        {
        return;
        }
        
    if (includeStoch1)
        {
        Stoch1_percentK = iStochastic(NULL,Stoch1_TimeFrame,Stoch1_KPeriod,DPeriod,Stoch1_Slowing,Stoch1_MAMethod,Stoch1_PriceField,MODE_MAIN,startShift);
        Stoch1_percentK_previous = iStochastic(NULL,Stoch1_TimeFrame, Stoch1_KPeriod,DPeriod,Stoch1_Slowing,Stoch1_MAMethod,Stoch1_PriceField,MODE_MAIN,startShift+1);
        }

    if (includeStoch2)
        {
        Stoch2_percentK = iStochastic(NULL,Stoch2_TimeFrame,Stoch2_KPeriod,DPeriod,Stoch2_Slowing,Stoch2_MAMethod,Stoch2_PriceField,MODE_MAIN,startShift);
        Stoch2_percentK_previous = iStochastic(NULL,Stoch2_TimeFrame, Stoch2_KPeriod,DPeriod,Stoch2_Slowing,Stoch2_MAMethod,Stoch2_PriceField,MODE_MAIN,startShift+1);
        }

    if (includeStoch3)
        {
        Stoch3_percentK = iStochastic(NULL,Stoch3_TimeFrame,Stoch3_KPeriod,DPeriod,Stoch3_Slowing,Stoch3_MAMethod,Stoch3_PriceField,MODE_MAIN,startShift);
        Stoch3_percentK_previous = iStochastic(NULL,Stoch3_TimeFrame, Stoch3_KPeriod,DPeriod,Stoch3_Slowing,Stoch3_MAMethod,Stoch3_PriceField,MODE_MAIN,startShift+1);
        }

    if (includeStoch4)
        {
        Stoch4_percentK = iStochastic(NULL,Stoch4_TimeFrame,Stoch4_KPeriod,DPeriod,Stoch4_Slowing,Stoch4_MAMethod,Stoch4_PriceField,MODE_MAIN,startShift);
        Stoch4_percentK_previous = iStochastic(NULL,Stoch4_TimeFrame, Stoch4_KPeriod,DPeriod,Stoch4_Slowing,Stoch4_MAMethod,Stoch4_PriceField,MODE_MAIN,startShift+1);
        }

    if (includeStoch5)
        {
        Stoch5_percentK = iStochastic(NULL,Stoch5_TimeFrame,Stoch5_KPeriod,DPeriod,Stoch5_Slowing,Stoch5_MAMethod,Stoch5_PriceField,MODE_MAIN,startShift);
        Stoch5_percentK_previous = iStochastic(NULL,Stoch5_TimeFrame, Stoch5_KPeriod,DPeriod,Stoch5_Slowing,Stoch5_MAMethod,Stoch5_PriceField,MODE_MAIN,startShift+1);
        }

    if (includeStoch6)
        {
        Stoch6_percentK = iStochastic(NULL,Stoch6_TimeFrame,Stoch6_KPeriod,DPeriod,Stoch6_Slowing,Stoch6_MAMethod,Stoch6_PriceField,MODE_MAIN,startShift);
        Stoch6_percentK_previous = iStochastic(NULL,Stoch6_TimeFrame, Stoch6_KPeriod,DPeriod,Stoch6_Slowing,Stoch6_MAMethod,Stoch6_PriceField,MODE_MAIN,startShift+1);
        }

      
      
//--CHECK AllBetweenOverBoughtSold 
    if (AllBetweenOverBoughtSold)
        {
        bool _all_between_OverBoughtSold=true;

    
        if (_all_between_OverBoughtSold)
            {
            if (includeStoch1) 
                {
                if (Stoch1_percentK > overBoughtLevel || Stoch1_percentK < overSoldLevel)
                    {
                    _all_between_OverBoughtSold=false;
                      }
                    }
                }
        
            if (includeStoch2) 
                {
                if (_all_between_OverBoughtSold)
                    {
                    if (Stoch2_percentK > overBoughtLevel || Stoch2_percentK < overSoldLevel)
                        {
                        _all_between_OverBoughtSold=false;
                        }
                    }
                }

            if (includeStoch3) 
                {
                if (_all_between_OverBoughtSold)
                    {
                    if (Stoch3_percentK > overBoughtLevel || Stoch3_percentK < overSoldLevel)
                        {
                        _all_between_OverBoughtSold=false;
                        }
                    }
                }

            if (includeStoch4) 
                {
                if (_all_between_OverBoughtSold)
                    {
                    if (Stoch4_percentK > overBoughtLevel || Stoch4_percentK < overSoldLevel)
                        {
                        _all_between_OverBoughtSold=false;
                        }
                    }
                }

            if (includeStoch5) 
                {
                if (_all_between_OverBoughtSold)
                    {
                    if (Stoch5_percentK > overBoughtLevel || Stoch5_percentK < overSoldLevel)
                        {
                        _all_between_OverBoughtSold=false;
                        }
                    }
                }

            if (includeStoch6) 
                {
                if (_all_between_OverBoughtSold)
                    {
                    if (Stoch6_percentK > overBoughtLevel || Stoch6_percentK < overSoldLevel)
                        {
                        _all_between_OverBoughtSold=false;
                        }
                    }
                }
        
            }



if(MinNumberSameDirection > 0)
    {

//--CHECK AllDirections
    int UpDirection=0;
    int DownDirection=0; 


    //Stoch1 is always included
    //UP
    if (includeStoch1) 
        {        
        if (Stoch1_percentK > Stoch1_percentK_previous)
            {
            UpDirection++;
            }   
        if (Stoch1_percentK < Stoch1_percentK_previous)
            {
            DownDirection++;
            }  
        } 
    if (includeStoch2) 
        {
        if (Stoch2_percentK > Stoch2_percentK_previous)
            {
            UpDirection++;
            }
        if (Stoch2_percentK < Stoch2_percentK_previous)
            {
            DownDirection++;
            }   
        }    
      
    if (includeStoch3) 
        {
        if (Stoch3_percentK > Stoch3_percentK_previous)
            {
            UpDirection++;
            }
        if (Stoch3_percentK < Stoch3_percentK_previous)
            {
            DownDirection++;
            }   
        }    

    if (includeStoch4) 
        {
        if (Stoch4_percentK > Stoch4_percentK_previous)
            {
            UpDirection++;
            }
        if (Stoch4_percentK < Stoch4_percentK_previous)
            {
            DownDirection++;
            }   
        }    

    if (includeStoch5) 
        {
        if (Stoch5_percentK > Stoch5_percentK_previous)
            {
            UpDirection++;
            }
        if (Stoch5_percentK < Stoch5_percentK_previous)
            {
            DownDirection++;
            }   
        }    

    if (includeStoch6) 
        {
        if (Stoch6_percentK > Stoch6_percentK_previous)
            {
            UpDirection++;
            }
        if (Stoch6_percentK < Stoch6_percentK_previous)
            {
            DownDirection++;
            }   
        }    
    }
    
//== do the Alerter
    UP[startShift]=EMPTY_VALUE;
    DOWN[startShift]=EMPTY_VALUE;
    BOTH[startShift]=EMPTY_VALUE;
    SPECIAL[startShift]=EMPTY_VALUE;



//___________CHECK AllBetweenOverBoughtSold 
    if (AllBetweenOverBoughtSold)
        {
        if (_all_between_OverBoughtSold)
            {
            if (MinNumberSameDirection > 0)
                {
                // check same number
                if (UpDirection == DownDirection)
                    {
                     if (UpDirection >=MinNumberSameDirection)
                       {
                        // ALTER OK: BOTH DIRECTIONS
                        BOTH[startShift]=1;
                        // Fire the alert     
                        if(LastDirection !="BOTH") 
                            {
                            Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@  Direction: < BOTH >   UP: " +UpDirection + " DOWN: "+DownDirection);  // both are the same    
                            if(UseAdditionalSoundAlert)
                                {
                                PlaySound(SoundFileName);
                                }                
                            }
                        LastDirection="BOTH";  
                        }
                    }   
                // more UP
                else if (UpDirection > DownDirection)     
                    {
                     if (UpDirection >=MinNumberSameDirection)
                       {
                        // ALTER OK: UP DIRECTIONS
                        UP[startShift]=1;
                        // Fire the alert     
                        if(LastDirection !="UP") 
                            {
                            Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@  Direction: < UP >   UP: " +UpDirection + " DOWN: "+DownDirection);    
                            if(UseAdditionalSoundAlert)
                                {
                                PlaySound(SoundFileName);
                                }                
                            }
                        LastDirection="UP";  
                        }
                    }   
                // more DOWN     
                else if (DownDirection > UpDirection) 
                    {
                     if (DownDirection >=MinNumberSameDirection)
                       {
                        // ALTER OK: DOWN DIRECTIONS
                        DOWN[startShift]=1;
                        // Fire the alert     
                        if(LastDirection !="DOWN") 
                            {
                            Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@  Direction: < DOWN >   DOWN: " +DownDirection + " UP: "+UpDirection);     
                            if(UseAdditionalSoundAlert)
                                {
                                PlaySound(SoundFileName);
                                }                
                            }
                        LastDirection="DOWN";  
                        }
                    }   
                }
            // SPECIAL CASE
            else if (MinNumberSameDirection == 0)
               {
                // ALTER OK: DOWN DIRECTIONS
                SPECIAL[startShift]=1;
                // Fire the alert     
                // No need to check for LastDirection
                    {
                    Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@  SPECIAL CASE: < MinNumberSameDirection == 0 > All Stochs between OverBoughtSold area");      
                    if(UseAdditionalSoundAlert)
                        {
                        PlaySound(SoundFileName);
                        }                
                    }
                }        
            }
        }
//___________no overbought/sold check
    else 
        {
        // check same number
        if (UpDirection == DownDirection)
            {
             if (UpDirection >=MinNumberSameDirection)
               {
                // ALTER OK: BOTH DIRECTIONS
                BOTH[startShift]=1;
                // Fire the alert     
                if(LastDirection !="BOTH") 
                    {
                    Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@  Direction: < BOTH >   UP: " +UpDirection + " DOWN: "+DownDirection);  // both are the same      
                    if(UseAdditionalSoundAlert)
                        {
                        PlaySound(SoundFileName);
                        }                
                    }
                LastDirection="BOTH";  
                }
            }   
        // more UP
        else if (UpDirection > DownDirection)     
            {
             if (UpDirection >=MinNumberSameDirection)
               {
                // ALTER OK: UP DIRECTIONS
                UP[startShift]=1;
                // Fire the alert     
                if(LastDirection !="UP") 
                    {
                    Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@  Direction: < UP >   UP: " +UpDirection + " DOWN: "+DownDirection);      
                    if(UseAdditionalSoundAlert)
                        {
                        PlaySound(SoundFileName);
                        }                
                    }
                LastDirection="UP";  
                }
            }   
        // more DOWN     
        else if (DownDirection > UpDirection) 
            {
             if (DownDirection >=MinNumberSameDirection)
               {
                // ALTER OK: DOWN DIRECTIONS
                DOWN[startShift]=1;
                // Fire the alert     
                if(LastDirection !="DOWN") 
                    {
                    Alert("MultiStochDirectionAlert_mj: " + Symbol() + "@  Direction: < DOWN >   DOWN: " +DownDirection + " UP: "+UpDirection);       
                    if(UseAdditionalSoundAlert)
                        {
                        PlaySound(SoundFileName);
                        }                
                    }
                LastDirection="DOWN";  
                }
            }   
        }

                         
         
   return(0);
}




bool NewBar()
    {
    static datetime dt = 0;
    if (Time[0] != dt)
        {
        dt = Time[0];
        return(true);
    }
    return(false);
}