//+------------------------------------------------------------------+
//|                                                     MIDAS_v1.mq4 |
//|                                                       Akif TOKUZ |
//| Implementation is based on article "Introducing the MIDAS Method |
//| of Technical Analysis" by Dr. Paul Levine.                       |
//|                                                      06.08.2009  |
//+------------------------------------------------------------------+
#property copyright "Akif TOKUZ"
#property link      "akifusenet@gmail.com"

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Magenta
#property indicator_color2 Magenta
#property indicator_color3 FireBrick
#property indicator_color4 Yellow
#property indicator_width1 2
#property indicator_width2 1
#property indicator_width3 2
#property indicator_width4 2
#property indicator_style2 2

//---- input parameters
extern datetime   StartDate=D'2009.08.06 00:00';
extern bool       ShowVWAP=true;
extern bool       ShowTopFinder=false;
extern double     TopFinderVolumeNumBars=30; 
extern bool       ShowShiftedVWAP=false;
extern double     shift=20;
extern bool       ShowAveragePrice=false;

//---- indicator buffers
double VWAP[];
double TopFinder[];
double VWAPShift[];
double AvgPrice[];
double CumVol[];//not displayed
double CumPVol[];//not displayed

//---- global variables for holding up values at fixed "start day"
double CumPVol_J=-1;
double CumVol_J=-1;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   IndicatorBuffers(6);

   SetIndexBuffer(0,VWAP);
   SetIndexBuffer(1,VWAPShift);   
   SetIndexBuffer(2,TopFinder);   
   SetIndexBuffer(3,AvgPrice);
   SetIndexBuffer(4,CumVol);
   SetIndexBuffer(5,CumPVol);   
   
   if (ShowVWAP==true)   SetIndexStyle(0,DRAW_LINE);
   else SetIndexStyle(0,DRAW_NONE);
   
   if (ShowShiftedVWAP==true)   SetIndexStyle(1,DRAW_LINE);
   else SetIndexStyle(1,DRAW_NONE);

   if (ShowTopFinder==true)   SetIndexStyle(2,DRAW_LINE);
   else SetIndexStyle(2,DRAW_NONE); 
   
   if (ShowAveragePrice==true)   SetIndexStyle(3,DRAW_LINE);
   else SetIndexStyle(3,DRAW_NONE);

    
   string short_name="MIDAS";
   IndicatorShortName(short_name);
   
   SetIndexLabel(0,"VWAP");
   SetIndexLabel(1,"AvgPrice");
   SetIndexLabel(2,"TopFinder");
   SetIndexLabel(3,"VWAPShift");
   SetIndexLabel(4,"CumVol");
   SetIndexLabel(5,"CumPVol");

 
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }


//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int i;
   int counted_bars=IndicatorCounted();
   double d;
   double e;
   double result;
   double x;
   double D;
  
   //---- check for possible errors
   if(counted_bars<0) return(-1);

   for (i=Bars-counted_bars-1; i>=0; i--)
   {
      AvgPrice[i]=(High[i]+Low[i])/2;
      CumVol[i]=CumVol[i+1]+Volume[i];
      CumPVol[i]=CumPVol[i+1]+Volume[i]*AvgPrice[i];
      
      if (StartDate <= Time[i])
      {
          if ((CumPVol_J==-1)&&(CumVol_J==-1))        // save starting day values
          {
            CumPVol_J = CumPVol[i];
            CumVol_J = CumVol[i];          
            VWAP[i]=AvgPrice[i];                      // at the start day we need to put initial values                     
            VWAPShift[i]=VWAP[i]+VWAP[i]*shift/10000; // which are calculated differently             
            TopFinder[i]=AvgPrice[i];                 // (check Dr. Levine's lectures)
          }else
          {      
            VWAP[i]=( CumPVol[i] - CumPVol_J ) / ( CumVol[i] - CumVol_J );             
            VWAPShift[i]=VWAP[i]+VWAP[i]*shift/10000;
                         
            d=( CumVol[i] - CumVol_J );                  // calculate TopFinder
            D=TopFinderVolumeNumBars*(CumVol[i]/Bars);   // multiply TopFinderVolumeNumBars input with average volume per bar
            e=d*(1-d/D);                                 // when d/D gets close to 1, e will be zero.
            
            x=CumVol[i]-e;
            if (d/D<0.9999)                              // protection from division by zero
            {
                  for (int j=0;j<Bars-counted_bars-1;j++)
                  {
                     if (CumVol[j]<x) break;
                  }
                  
                  if (j!=0) // Zero bar check
                  {
                     // interpolation required to find the exact value (again check Dr. Levine's lectures)
                     result=  CumPVol[j]*(x - CumVol[j-1])/(CumVol[j] - CumVol[j-1]) + 
                              CumPVol[j-1]*(x - CumVol[j])/(CumVol[j-1] - CumVol[j]);
                     TopFinder[i]=( CumPVol[i] - result ) / e;             
                  }            
            }            
         }
      }
   }
  
  //---- done
  return(0);
   }
//+------------------------------------------------------------------+