//+------------------------------------------------------------------+ 
//|              PowerTrend MultiTimeFrame MACD                      | 
//|                                                                  | 
//|   Copyright © 2008, Tim Hyder aka Hiachiever                     |
//|                                                                  |
//|   PO BOX 768, Hillarys, Western Australia, Australia, 6923       |
//|                                                                  |
//|   GIFTS AND DONATIONS ACCEPTED                                   | 
//|   All my indicators should be considered donationware. That is   |
//|   you are free to use them for your personal use, and are        |
//|   under no obligation to pay for them. However, if you do find   |
//|   this or any of my other indicators help you with your trading  |
//|   then any Gift or Donation as a show of appreciation is         |
//|   gratefully accepted.                                           |
//|                                                                  |
//|   Gifts or Donations also keep me motivated in producing more    |
//|   great free indicators. :-)                                     |
//|                                                                  |
//|   PayPal - hiachiever@gmail.com                                  |  
//+------------------------------------------------------------------+ 
//mod 2009fxtsd
//20090309fxtsd 1.1 obos lv
//20090311+adx  1.2

#property copyright "Copyright © 2007, Tim Hyder."
#property link      "http://www.the4xtrader.com"

#define vers    "20090309 1.2 //18.Feb.2008"
#define major   1
#define minor   0

#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 10
#property indicator_buffers 4 
#property indicator_color1 Blue        //MACD.Above0.Up - Strong Up
#property indicator_color2 Red         //MACD.Below0.Down - Strong Down
#property indicator_color3 RoyalBlue   //MACD.Above0.Dn - Weak Up
#property indicator_color4 DarkOrange  //MACD.Below0.Up  - Weak mDn

//extern string NOTE1 = " --- TimeFrame Settings ---";
//extern string NOTETF = "Enter 0 to display current TF";
extern int TimeFrame = 0;
//extern string NOTE2 = " --- Display Settings ---";
//extern string NOTEVS = "Vertically positions indicator";
extern int     ind.Vert.Level = 1.0;
extern int     ind.Bar.Type   = 7;

//extern string NOTEMACD = " --- MACD Settings ---";
extern string BarType      = "1CCI 2MACD 3OsMA";
extern string indicators   = "4MOM 5RSI  6STO 7ADX";


extern int  ADX_Period      = 14; //11


extern int CCI_Period = 14;
extern int RSI_Period = 13;
extern int Mom_Period = 14;


extern int Macd_Fast = 12;
extern int Macd_Slow = 26;
extern int Macd_Sig  = 9;
extern string OsmaMacdSto    = "msLineMode 0Main 1SigLn" ;
//extern string NoteMACD1a = " -- Signal Lines = (True) || Histogram = (False) -- ";
//extern bool UseSignalLines = true;
extern int  STO_KPeriod      =  5;    
extern int  STO_DPeriod      =  3;    // Sensivity Factor for Fast Line
extern int  STO_Slowing      =  3;    // Sensivity Factor for Slow Line
extern int  STO_price        =  0;    // sto: 0 - Low/High or 1 - Close/Close
extern int  STO_MAmethod     =  0;    

extern bool    OBOSlvMode     = false;    //overbought/sold levels
extern double     OBLv = 70;             
extern double     OSLv = 30;
extern int        ADX_Level   = 20; //if obos mode DIoverbought/sold levels = ADX_Level 


extern string   MA_Method_ = "SMA0 EMA1 SMMA2 LWMA3";
extern string   note_Price = "0C 1O 2H 3L 4Md 5Tp 6WghC: Md(HL/2)4,Tp(HLC/3)5,Wgh(HLCC/4)6|sto:0LH 1CC";


extern int  msLineMode = 0;          //0main 1signal
extern int  price      = 0;          


//extern string NOTEDISPLAY = " --- Other Display options ---";
extern int MaxBars = 1000;
//extern string DISPLAYFVS1 = "FineVertShift allows Time Frame label";
//extern string DISPLAYFVS2 = "to be moved up and down";
extern double TFLabelVSadjust = -0.6;

//colour of time frame label on far right of indicator
extern color   TFTextColor    = White;
extern color   TFSameTFColor  = Lime;
extern int     TFTextFontSize = 6;

extern string NOTEALERTS = " --- Alerts ---";
extern bool AllowBoxAlerts   = false;
extern bool AllowSoundAlerts = false;
extern string LongSound =  "stops.wav"; //alert.wav
extern string ShortSound = "alert2.wav";
extern bool AllowEmailAlerts = false;
extern bool ZeroCrssOnly     = false;
extern int  alertsOnBar       = 1;


//---- buffers
double bufStrongUp[], bufWeakUp[] ;
double bufStrongDn[], bufWeakDn[];

string ShortName = "";
extern string Prefix = "TH Bar-";
int ArrowSize = 110;
int BarWidth = 0;
datetime LastTime = -1;
int TFrame, Window,Lv0;
//Four constants used in one of the functions below
int MACD.Above0.Up = 1 ,MACD.Above0.Dn = 2 ,MACD.Below0.Dn = 3,MACD.Below0.Up = 4;
string indName;
//---------------------------------------------------------------------------------------------------------------

void init()
{  
  IndicatorBuffers(4);
  SetIndexStyle(0, DRAW_ARROW, 0, BarWidth);
  SetIndexStyle(1, DRAW_ARROW, 0, BarWidth);
  SetIndexStyle(2, DRAW_ARROW, 0, BarWidth);
  SetIndexStyle(3, DRAW_ARROW, 0, BarWidth);
  
  SetIndexArrow(0, ArrowSize);
  SetIndexArrow(1, ArrowSize);
  SetIndexArrow(2, ArrowSize);
  SetIndexArrow(3, ArrowSize);
  
  SetIndexBuffer(0, bufStrongUp);
  SetIndexBuffer(1, bufStrongDn);
  SetIndexBuffer(2, bufWeakUp);
  SetIndexBuffer(3, bufWeakDn);
    
  SetIndexEmptyValue(0, 0.0);
  SetIndexEmptyValue(1, 0.0);
  SetIndexEmptyValue(2, 0.0);
  SetIndexEmptyValue(3, 0.0);

  SetIndexLabel(0, NULL);
  SetIndexLabel(1, NULL);
  SetIndexLabel(2, NULL);
  SetIndexLabel(3, NULL);

  IndicatorDigits(0);
 
  //Verify Time Values entered by user
  TFrame = CheckTimeFrame(TimeFrame);
  
  //---- name for DataWindow and indicator subwindow label
  //VertShift = GetNextIndicatorNo(Prefix);
  ShortName = Prefix + ind.Vert.Level;
  IndicatorShortName(ShortName);

}   

void deinit()
{
  int total = ObjectsTotal();  
  for (int i=total-1; i >= 0; i--) 
  {
    string name = ObjectName(i);
    if (StringFind(name, Prefix) == 0) ObjectDelete(name);
  }
}

void start()
{ 
   int i,tf,x,y=0;
   datetime TimeArray[];
   int MD;

   Window = WindowFind(ShortName);
   //This indicator is designed to display mutliple TFs in 1 indicator Window
   //When suqsequent indicators are dropped on the same Window
   //as a previous one WindowFind returns -1 ie can't find it.
   //This loop is to loop through the windows and find the window reference
   //The purpose behind all of this is to fix the problem of the TF labels
   //not being displayed for indicator 2,3,4 etc because of the Window reference
   if (Window == -1) 
   {
      for (i=0; i<20; i++)
      {
         x = WindowFind(Prefix + i);  
         if (x > 0)
         {
            Window = x;
            break;
         }
      }
   }   

   int counted_bars=IndicatorCounted();
   //---- check for possible errors
   if (counted_bars < 0) return(-1);
   //---- the last counted bar will be recounted
   if (counted_bars > 0) counted_bars--;
   int limit = Bars - counted_bars;
       limit = MathMax(limit,TimeFrame/Period());
       limit = MathMin(limit, MaxBars);

  //-------------------------------1----------------------------------------   
  
   // Plot defined time frame on to current time frame
   ArrayCopySeries(TimeArray,MODE_TIME,Symbol(),TimeFrame); 
   
   for(i=0,y=0;i<limit;i++)
   {
      if (Time[i]<TimeArray[y]) y++;

      /***********************************************************   
         Add your main indicator loop below.  You can reference an existing
         function with its name or an indicator with its iName  or iCustom.
         Rule 1:  Add extern inputs above for all neccesary values   
         Rule 2:  Use 'TFrame' for the indicator time frame
         Rule 3:  Use 'y' for your indicator's shift value
       **********************************************************/  
      MD = GetMACD(TFrame,y);

      bufStrongUp[i] = 0.0;
      bufWeakUp[i]   = 0.0;
      bufStrongDn[i] = 0.0;
      bufWeakDn[i]   = 0.0;

      if       (MD == MACD.Above0.Up) bufStrongUp[i]  = ind.Vert.Level;
      else if  (MD == MACD.Above0.Dn) bufWeakUp[i]    = ind.Vert.Level;
      else if  (MD == MACD.Below0.Dn) bufStrongDn[i]  = ind.Vert.Level;
      else if  (MD == MACD.Below0.Up) bufWeakDn[i]    = ind.Vert.Level;
  }//End For Loop
  
  CreateTFLabel(TFrame);
 
  string MailSubject = "TH Bar" ;
  string msg = "TH Bar "+indName+" TF" +(TimeFrame)+" on " +Symbol()+" M"+Period()  ;
  
  int bar = alertsOnBar;
  
  if (LastTime != Time[0])
  {
    //-> Lime
    if (bufStrongUp[bar] != 0 && bufStrongUp[bar+1] == 0)
    {
      msg = msg + " (>0up) Strong Up Trend; ";
      if (AllowSoundAlerts) PlaySound(LongSound);
      if (AllowBoxAlerts) Alert(msg);
      if (AllowEmailAlerts) SendMail(MailSubject, msg);
    }

    //<- Lime
    if (bufStrongUp[bar] == 0 && bufStrongUp[bar+1] != 0 && !ZeroCrssOnly)
    {
      msg = msg + " (>0dn) week UpTrend; ";
      if (AllowSoundAlerts) PlaySound(LongSound);
      if (AllowBoxAlerts) Alert(msg);
      if (AllowEmailAlerts) SendMail(MailSubject, msg);
    }

    //-> Red
    if (bufStrongDn[bar] != 0 && bufStrongDn[bar+1] == 0)
    {
      msg = msg + "  (<0dn) Strong Down Trend; ";
      if (AllowSoundAlerts) PlaySound(ShortSound);
      if (AllowBoxAlerts) Alert(msg);
      if (AllowEmailAlerts) SendMail(MailSubject, msg);
    }

    //<- Red
    if (bufStrongDn[bar] == 0 && bufStrongDn[bar+1] != 0 && !ZeroCrssOnly)
    {
      msg = msg +  " (<0up) week DownTrend ; ";
      if (AllowSoundAlerts) PlaySound(ShortSound);
      if (AllowBoxAlerts) Alert(msg);
      if (AllowEmailAlerts) SendMail(MailSubject, msg);
    }
    
    LastTime = Time[0];
  }
   

  return(0);
}
  
  
void CreateTFLabel(int TF)
{


            switch (ind.Bar.Type)
         {
            case 1: indName = " CCI ("+CCI_Period+")";  break;
            case 2: indName = " MACD ("+Macd_Fast+","+Macd_Slow+","+Macd_Sig+")"; break;
            case 3: indName = " OsMA ("+Macd_Fast+","+Macd_Slow+","+Macd_Sig+")"; break;
            case 4: indName = " MOM ("+Mom_Period+")";  break;
            case 5: indName = " RSI ("+RSI_Period+")";  break;
            case 6: indName = " STO ("+STO_KPeriod+","+STO_DPeriod+","+STO_Slowing+")"; break;
            case 7: indName = " ADX ("+ADX_Period+")"; break;

         }


   string txt = TF2Str(TF)+indName;
   //if(UseSignalLines) txt = txt;
   double TimeDiff = Time[0]-Time[1];  
   string name = Prefix+ind.Vert.Level+"_TF_"+txt;
   color labelcolor = TFTextColor;
   string fontname = "Arial";

   //If Tf = Chart Period change TF Label colour so that it can be easily identified
   if (TF == Period())
   {
      labelcolor = TFSameTFColor;
      fontname = "Arial Bold";
      TFLabelVSadjust = -0.7;
   }
         
   if(ind.Vert.Level<TFLabelVSadjust) TFLabelVSadjust = 0; //TFLabelVS = TF Label Vertical Shift
   
   if (ObjectFind(name) == -1)
   {  
     ObjectCreate(name, OBJ_TEXT, Window, iTime(NULL,0,0)+12*TimeDiff, ind.Vert.Level-TFLabelVSadjust);
     ObjectSetText(name, txt,TFTextFontSize,fontname, labelcolor);
   }
   else
     ObjectSet(name, OBJPROP_TIME1, iTime(NULL,0,0)+12*TimeDiff);
}

string TF2Str(int period) 
{
  switch (period) 
  {
    case PERIOD_M1:  return("M1");
    case PERIOD_M5:  return("M5");
    case PERIOD_M15: return("M15");
    case PERIOD_M30: return("M30");
    case PERIOD_H1:  return("H1");
    case PERIOD_H4:  return("H4");
    case PERIOD_D1:  return("D1");
    case PERIOD_W1:  return("W1");
    case PERIOD_MN1: return("MN");
  }
  return (Period());
} 

int CheckTimeFrame(int TimeFrame)
{
   int result;

   if (TimeFrame == 0) 
      result = Period();   
   else
   {
      switch(TimeFrame) 
      {
         case 1    : result = PERIOD_M1;  break; 
         case 5    : result = PERIOD_M5;  break;
         case 15   : result = PERIOD_M15; break;
         case 30   : result = PERIOD_M30; break;
         case 60   : result = PERIOD_H1;  break;
         case 240  : result = PERIOD_H4;  break;
         case 1440 : result = PERIOD_D1;  break;
         case 7200 : result = PERIOD_W1;  break;
         case 28800: result = PERIOD_MN1; break;
         default  : result = Period(); break; //Error so return current TF
      }
   }
   return(result);
}

int GetMACD(int TF, int shift)
{


  double      ADX  =iADX(NULL,TF,ADX_Period,price,0,shift);
  double      PADX =iADX(NULL,TF,ADX_Period,price,1,shift);
  double      NADX =iADX(NULL,TF,ADX_Period,price,2,shift);
              
  double      ADX1 =iADX(NULL,TF,ADX_Period,price,0,shift+1);
  double      PADX1=iADX(NULL,TF,ADX_Period,price,1,shift+1);
  double      NADX1=iADX(NULL,TF,ADX_Period,price,2,shift+1);

  double      d, d1;    if    (PADX>NADX) { d = ADX;   d1 = ADX1;}
                        else              { d =-ADX;   d1 =-ADX1;}


   double      cci   =iCCI(NULL, TF, CCI_Period,price, shift);
   double      cci1  =iCCI(NULL, TF, CCI_Period,price, shift+1);
  
   double macd =  iMACD(NULL,TF,Macd_Fast,Macd_Slow,Macd_Sig,price,msLineMode,shift); 
   double macd1=  iMACD(NULL,TF,Macd_Fast,Macd_Slow,Macd_Sig,price,msLineMode,shift+1);    
   double osma =  iOsMA(NULL,TF,Macd_Fast,Macd_Slow,Macd_Sig,price,shift); 
   double osma1=  iOsMA(NULL,TF,Macd_Fast,Macd_Slow,Macd_Sig,price,shift+1);    
   
   double  mom    =iMomentum(NULL,TF,Mom_Period,price,shift);
   double  mom1   =iMomentum(NULL,TF,Mom_Period,price,shift+1);

   double   rsi   =iRSI(NULL, TF, RSI_Period,price, shift); 
   double   rsi1  =iRSI(NULL, TF, RSI_Period,price, shift+1); 
  
   double stoch  = iStochastic(NULL,TF,STO_KPeriod,STO_DPeriod,STO_Slowing,STO_MAmethod,STO_price ,msLineMode,shift);
   double stoch1 = iStochastic(NULL,TF,STO_KPeriod,STO_DPeriod,STO_Slowing,STO_MAmethod,STO_price ,msLineMode,shift+1);

   double  MACDM,   MACDSIG;      


      switch(ind.Bar.Type) 
      {
         case 1:  MACDM=cci;   MACDSIG=cci1;    Lv0=0;   break; 
         case 2:  MACDM=macd;  MACDSIG=macd1;   Lv0=0;   break; 
         case 3:  MACDM=osma;  MACDSIG=osma1;   Lv0=0;   break; 
         case 4:  MACDM=mom;   MACDSIG=mom1;    Lv0=100; break;
         case 5:  MACDM=rsi;   MACDSIG=rsi1;    Lv0=50;  break; 
         case 6:  MACDM=stoch; MACDSIG=stoch1;  Lv0=50;  break;
         case 7:  MACDM=d;     MACDSIG=d1;      Lv0=0;   OBLv= ADX_Level;  OSLv= -ADX_Level;    
                                                         break;
                                                         

      }
//extern string BarType = "1cci 2macd 3osma"; "4mom 5rsi  6sto 7adx"; 



      if (MACDM>Lv0)
      {
         if (OBOSlvMode) MACDSIG=OBLv; 
         if (MACDM>MACDSIG)   return(MACD.Above0.Up); 
         else                 return(MACD.Above0.Dn);  
      }
      else 
      {
         if (OBOSlvMode) MACDSIG=OSLv;
         if (MACDM<MACDSIG)   return(MACD.Below0.Dn);
         else                 return(MACD.Below0.Up);
      }


}