//+------------------------------------------------------------------+
//| HeikenAshiOscillator.mq4
//+------------------------------------------------------------------+

#property copyright "Copyright � Pointzero"
#property link      "Pointzero"

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 DodgerBlue
#property indicator_color2 Red
#property indicator_color3 Teal
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 1
#define MaMetod 2

//-------------------------------
// External variables
//-------------------------------
extern string TimeFrame = "Current time frame";
extern int    AvPeriod = 2;

//-------------------------------
// Buffers
//-------------------------------

double FextMapBuffer1[];
double FextMapBuffer2[];
double FextMapBuffer3[];
double FextMapBuffer4[];
double FextMapBuffer5[];

string indicatorFileName;
bool   returnBars;
bool   calculateValue;
int    timeFrame;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//|------------------------------------------------------------------|
int init()
{
   // Total buffers
   IndicatorBuffers(5);
   
   // Visible buffers
   SetIndexStyle(0,DRAW_HISTOGRAM, 0, indicator_width1, indicator_color1);
   SetIndexBuffer(0, FextMapBuffer1);
   SetIndexStyle(1,DRAW_HISTOGRAM, 0, indicator_width2, indicator_color2);
   SetIndexBuffer(1, FextMapBuffer2);
   SetIndexStyle(3,DRAW_LINE, 0, indicator_width3, indicator_color3);
   SetIndexBuffer(2,FextMapBuffer3);    
   
   // Internal
   SetIndexBuffer(3,FextMapBuffer4);  
   SetIndexBuffer(4,FextMapBuffer5);     

      //
      //
      //
      //
      //
      
         indicatorFileName = WindowExpertName();
         calculateValue    = TimeFrame=="calculateValue"; if (calculateValue) { return(0); }
         returnBars        = TimeFrame=="returnBars";     if (returnBars)     { return(0); }
         timeFrame         = stringToTimeFrame(TimeFrame);
      
      //
      //
      //
      //
      //
               
   
   // My name
   
   IndicatorShortName(timeFrameToString(timeFrame)+" Heiken Ashi Oscillator");
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   int 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) { FextMapBuffer1[0] = MathMin(limit+1,Bars-1); return(0); }

   
   // Check heiken ashi for past to present
   if (calculateValue || timeFrame == Period())
   {
      for(int pos = limit; pos >= 0; pos--)
      {  
      // Open and close 
      double open = iCustom(Symbol(), 0, "Heiken Ashi", 2, pos);
      double close = iCustom(Symbol(), 0, "Heiken Ashi", 3, pos);
      
      // Median
      FextMapBuffer4[pos] = (open + close) / 2;
      
      // Difference
      FextMapBuffer5[pos] = FextMapBuffer4[pos] - FextMapBuffer4[pos+1];

      // If bearish
      if(open > close)
      {
         FextMapBuffer2[pos] = FextMapBuffer5[pos];
         FextMapBuffer1[pos] = 0;
         
      // If bullish
      } else {
         
         FextMapBuffer1[pos] = FextMapBuffer5[pos];
         FextMapBuffer2[pos] = 0;
      }
   }
   // Apply average
   for(int i=0; i<Bars; i++) FextMapBuffer3[i] = iMAOnArray(FextMapBuffer5, Bars, AvPeriod, 0, MaMetod, i);
   return(0);
   }
   
   //
   //
   //
   //
   //
   
   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,timeFrame,indicatorFileName,"returnBars",0,0)*timeFrame/Period()));
   for(i=limit; i>=0; i--)
   {
      int y = iBarShift(NULL,timeFrame,Time[i]);
         FextMapBuffer1[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",AvPeriod,0,y);
         FextMapBuffer2[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",AvPeriod,1,y);
         FextMapBuffer3[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",AvPeriod,2,y);
   }
   return(0);
}

//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   tfs = stringUpperCase(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}
string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//
//
//
//
//

string stringUpperCase(string str)
{
   string   s = str;

   for (int length=StringLen(str)-1; length>=0; length--)
   {
      int char = StringGetChar(s, length);
         if((char > 96 && char < 123) || (char > 223 && char < 256))
                     s = StringSetChar(s, length, char - 32);
         else if(char > -33 && char < 0)
                     s = StringSetChar(s, length, char + 224);
   }
   return(s);
}