//+------------------------------------------------------------------+
//|                                        AbsoluteStrength_v1.1.mq4 |
//|                           Copyright © 2006, TrendLaboratory Ltd. |
//|            http://finance.groups.yahoo.com/group/TrendLaboratory |
//|                                       E-mail: igorad2004@list.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, TrendLaboratory Ltd."
#property link      "http://finance.groups.yahoo.com/group/TrendLaboratory"

#property indicator_separate_window
#property indicator_buffers   2
#property indicator_color1    LightBlue
#property indicator_width1    2 
#property indicator_color2    Tomato
#property indicator_width2    2
#property indicator_minimum   0
#property indicator_maximum   1
//---- input parameters
enum asMode
{
   as_rsi,   // Use RSI mode 
   as_stoch, // Use stochastic mode
   as_adx    // Use ADX mode 
};
extern ENUM_TIMEFRAMES TimeFrame  = PERIOD_CURRENT;
extern asMode Mode             =  as_rsi; // 0-RSI method; 1-Stoch method; 2-ADX method
extern int    Length           = 10; // Period of evaluation
extern int    Smooth           =  5; // Period of smoothing
extern int    Signal           =  5; // Period of Signal Line
extern int    Price            =  0; // Price mode : 0-Close,1-Open,2-High,3-Low,4-Median,5-Typical,6-Weighted
extern ENUM_MA_METHOD ModeMA   =  MODE_LWMA; // Mode of Moving Average
extern double OverBought       =  0; // OverBought Level
extern double OverSold         =  0; // OverSold Level 
extern bool   alertsOn         = false;
extern bool   alertsOnCurrent  = true;
extern bool   alertsMessage    = true;
extern bool   alertsSound      = false;
extern bool   alertsEmail      = false;
extern bool   ShowArrows       = false;
extern string arrowsIdentifier = "abs Arrows1";
extern double arrowsUpperGap   = 1.0;
extern double arrowsLowerGap   = 1.0;
extern color  arrowsUpColor    = LimeGreen;
extern color  arrowsDnColor    = Red;
extern int    arrowsUpCode     = 241;
extern int    arrowsDnCode     = 242;
  
double Bulls[];
double Bears[];
double AvgBulls[];
double AvgBears[];
double SmthBulls[];
double SmthBears[];
double SigBulls[];
double SigBears[];

bool     returnBars;
string   indicatorFileName;

//------------------------------------------------------------------
//
//------------------------------------------------------------------
int init()
{
   IndicatorBuffers(8);
   SetIndexBuffer(0,SigBulls); SetIndexStyle(0,DRAW_HISTOGRAM); SetIndexLabel(0,"Bulls");
   SetIndexBuffer(1,SigBears); SetIndexStyle(1,DRAW_HISTOGRAM); SetIndexLabel(1,"Bears");
   SetIndexBuffer(2,SmthBulls);
   SetIndexBuffer(3,SmthBears);
   SetIndexBuffer(4,Bulls);
   SetIndexBuffer(5,Bears);
   SetIndexBuffer(6,AvgBulls);
   SetIndexBuffer(7,AvgBears);
   SetIndexDrawBegin(0,Length+Smooth+Signal);
   SetIndexDrawBegin(1,Length+Smooth+Signal);
   SetIndexDrawBegin(2,Length+Smooth+Signal);
   SetIndexDrawBegin(3,Length+Smooth+Signal);

         //
         //
         //
         //
         //
                  
         indicatorFileName = WindowExpertName();
         returnBars        = (TimeFrame==-99);
         TimeFrame         = MathMax(TimeFrame,_Period);
         
         //
         //
         //
         //
         //

   IndicatorShortName(timeFrameToString(TimeFrame)+" AbsoluteStrength("+Mode+","+Length+","+Smooth+","+Signal+","+ModeMA+")");
   return(0);
}

//
//
//
//
//

int deinit() 
{  
   deleteArrows(); 
   
return(0); 
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double trend[];
int start()
{
   int r,counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = MathMin(Bars-counted_bars,Bars-1);
         if (returnBars) { SigBulls[0] = limit+1; return(0); }

   //
   //
   //
   //
   //
   
   if (TimeFrame==Period())
   {
      if (ArraySize(trend)!=Bars) ArrayResize(trend,Bars);
      for(int shift=limit; shift>=0; shift--)
      {
         double Price1 = iMA(NULL,0,1,0,MODE_SMA,Price,shift);
         double Price2 = iMA(NULL,0,1,0,MODE_SMA,Price,shift+1); 
      
         if (Mode==0)
         {
            Bulls[shift] = 0.5*(MathAbs(Price1-Price2)+(Price1-Price2));
            Bears[shift] = 0.5*(MathAbs(Price1-Price2)-(Price1-Price2));
            continue;
         }
         if (Mode==1)
         {
            Bulls[shift] = Price1 - Low[Lowest(NULL,0,MODE_LOW,Length,shift)];
            Bears[shift] = High[Highest(NULL,0,MODE_HIGH,Length,shift)] - Price1;
            continue;
         }
         if (Mode==2)
         {
            Bulls[shift] = 0.5*(MathAbs(High[shift]-High[shift+1])+(High[shift]-High[shift+1]));
            Bears[shift] = 0.5*(MathAbs(Low[shift+1]-Low[shift])+(Low[shift+1]-Low[shift]));
         }
      }

      //
      //
      //
      //
      //
         
      for( shift=limit; shift>=0; shift--)
      {
         AvgBulls[shift]=iMAOnArray(Bulls,0,Length,0,ModeMA,shift);     
         AvgBears[shift]=iMAOnArray(Bears,0,Length,0,ModeMA,shift);
      }
      for( shift=limit, r=Bars-shift-1; shift>=0; shift--,r++)
      {
         SmthBulls[shift]=iMAOnArray(AvgBulls,0,Smooth,0,ModeMA,shift);     
         SmthBears[shift]=iMAOnArray(AvgBears,0,Smooth,0,ModeMA,shift);
         SigBulls[shift] = EMPTY_VALUE;
         SigBears[shift] = EMPTY_VALUE;
         trend[r] = trend[r-1];
            if (SmthBulls[shift]>SmthBears[shift]) trend[r] =  1;
            if (SmthBulls[shift]<SmthBears[shift]) trend[r] = -1;
            if (trend[r]== 1) SigBulls[shift] = 1;
            if (trend[r]==-1) SigBears[shift] = 1;
            
            //
            //
            //
            //
            //
            
            if (ShowArrows)
               {
                 deleteArrow(Time[shift]);
                 if (trend[r] != trend[r-1])
                 {
                   if (trend[r] == 1)  drawArrow(shift,arrowsUpColor,arrowsUpCode,false);
                   if (trend[r] ==-1)  drawArrow(shift,arrowsDnColor,arrowsDnCode, true);
                 }
              }
      }
      
      manageAlerts();
      return(0);
   }
   
   //
   //
   //
   //
   //

   limit = MathMax(limit,MathMin(Bars,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/Period()));
   for (int i=limit;i>=0;i--)
   {
      int y = iBarShift(NULL,TimeFrame,Time[i]);
         SigBulls[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Mode,Length,Smooth,Signal,Price,ModeMA,OverBought,OverSold,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,ShowArrows,arrowsIdentifier,arrowsUpperGap,arrowsLowerGap,arrowsUpColor,arrowsDnColor,arrowsUpCode,arrowsDnCode,0,y);
         SigBears[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Mode,Length,Smooth,Signal,Price,ModeMA,OverBought,OverSold,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,ShowArrows,arrowsIdentifier,arrowsUpperGap,arrowsLowerGap,arrowsUpColor,arrowsDnColor,arrowsUpCode,arrowsDnCode,1,y);
   }
   return(0);         
}



//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//

void manageAlerts()
{
   if (alertsOn)
   {
      if (alertsOnCurrent)
            int forBar = 0;
      else      forBar = 1; forBar = Bars-forBar-1;
      if (trend[forBar]!=trend[forBar-1])
      {
         if (trend[forBar]== 1) doAlert(0,"up");
         if (trend[forBar]==-1) doAlert(0,"down");
      }            
   }
}

//
//
//
//
//
 
void doAlert(int forBar, string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
      if (previousAlert != doWhat || previousTime != Time[forBar]) {
          previousAlert  = doWhat;
          previousTime   = Time[forBar];

          //
          //
          //
          //
          //

          message =  timeFrameToString(_Period)+" "+Symbol()+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" absolute strength changed trend to "+doWhat;
             if (alertsMessage) Alert(message);
             if (alertsEmail)   SendMail(StringConcatenate(Symbol(),"  absolute strength"),message);
             if (alertsSound)   PlaySound("alert2.wav");
      }
}

//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,bool up)
{
   string name = arrowsIdentifier+":"+Time[i];
   double gap  = iATR(NULL,0,20,i);   
   
      //
      //
      //
      //
      //
      
      ObjectCreate(name,OBJ_ARROW,0,Time[i],0);
         ObjectSet(name,OBJPROP_ARROWCODE,theCode);
         ObjectSet(name,OBJPROP_COLOR,theColor);
         if (up)
               ObjectSet(name,OBJPROP_PRICE1,High[i] + arrowsUpperGap * gap);
         else  ObjectSet(name,OBJPROP_PRICE1,Low[i]  - arrowsLowerGap * gap);
}

//
//
//
//
//

void deleteArrows()
{
   string lookFor       = arrowsIdentifier+":";
   int    lookForLength = StringLen(lookFor);
   for (int i=ObjectsTotal()-1; i>=0; i--)
   {
      string objectName = ObjectName(i);
         if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
   }
}

//
//
//
//
//

void deleteArrow(datetime time)
{
   string lookFor = arrowsIdentifier+":"+time; ObjectDelete(lookFor);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}