//+------------------------------------------------------------------+
//|                                                 Enhanced_OBV.mq4 |
//|                                  Copyright © 2012, Andrew Sumner |
//|             includes elements of LHDT_OBV Copyright © 2012, LHDT |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2012, Andrew Sumner"

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 DodgerBlue

//---- input parameters
extern string appPrice1 = "----APPLIED PRICE----";
extern string appPrice2 = "0=Close 1=Open 2=High 3=Low 4=(H+L)/2 5=(H+L+C)/3 6=(H+L+2C)/4";
extern int appliedPrice = 0;
extern bool useEnhanced = true;
extern bool smoothVolume = false;
//---- buffers
double ExtOBVBuffer[];
double smVolume;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   string sShortName;
   //---- indicator buffer mapping
   SetIndexBuffer(0, ExtOBVBuffer);
   //---- indicator line
   SetIndexStyle(0, DRAW_LINE);
   //---- sets default precision format for indicators visualization
   IndicatorDigits(0);
   //---- name for DataWindow and indicator subwindow label
   sShortName = "Enhanced OBV";
   IndicatorShortName(sShortName);
   SetIndexLabel(0, sShortName);
  
   return(0);
}
//+------------------------------------------------------------------+
//| On Balance Volume                                                |
//+------------------------------------------------------------------+
int start()
{
   int    i, nLimit, nCountedBars;
   double v1, v2;

   //---- bars count that does not changed after last indicator launch.
   nCountedBars = IndicatorCounted();
   //---- last counted bar will be recounted
   if (nCountedBars > 0) nCountedBars--;
   nLimit = Bars - nCountedBars - 1;
   
   for (i = nLimit; i >= 0; i--)
   {

      smVolume = Volume[i];

      if (smoothVolume == true)
         smVolume = (High[i] - Low[i]) * Volume[i];

      if (i == Bars - 1)
      {
         ExtOBVBuffer[i] = smVolume;
         if (useEnhanced == true)
         {
            if (High[i] - Low[i] > 0)
            {
               v1 = (smVolume * ((High[i] - Open[i]) / (High[i] - Low[i])));
               v2 = (smVolume * ((Open[i] - Low[i]) / (High[i] - Low[i])));
            }
            else
            {
               v1 = 0;
               v2 = 0;
            }
            ExtOBVBuffer[i] = v1 - v2;
         }
      }
      else
      {
         double dCurrentPrice = GetAppliedPrice(appliedPrice, i);
         double dPreviousPrice = GetAppliedPrice(appliedPrice, i + 1);

         if (useEnhanced == true)
         {
            if (High[i] - Low[i] > 0)
            {
               v1 = (smVolume * ((High[i] - Open[i]) / (High[i] - Low[i])));
               v2 = (smVolume * ((Open[i] - Low[i]) / (High[i] - Low[i])));
            }
            else
            {
               v1 = 0;
               v2 = 0;
            }
            ExtOBVBuffer[i] = ExtOBVBuffer[i + 1] + (v1 - v2);
         }
         else
         {
            if (dCurrentPrice == dPreviousPrice)
               ExtOBVBuffer[i] = ExtOBVBuffer[i + 1];
            else
            {
               if (dCurrentPrice < dPreviousPrice)
                  ExtOBVBuffer[i] = ExtOBVBuffer[i + 1] - smVolume;
               else
                  ExtOBVBuffer[i] = ExtOBVBuffer[i + 1] + smVolume;
            }
         }
      }
   }

   return(0);
}

double GetAppliedPrice(int nAppliedPrice, int nIndex)
{
   double dPrice;

   switch (nAppliedPrice)
   {
   case 0:
      dPrice = Close[nIndex];
      break;
   case 1:
      dPrice = Open[nIndex];
      break;
   case 2:
      dPrice = High[nIndex];
      break;
   case 3:
      dPrice = Low[nIndex];
      break;
   case 4:
      dPrice = (High[nIndex] + Low[nIndex]) / 2.0;
      break;
   case 5:
      dPrice = (High[nIndex] + Low[nIndex] + Close[nIndex]) / 3.0;
      break;
   case 6:
      dPrice = (High[nIndex] + Low[nIndex] + 2 * Close[nIndex]) / 4.0;
      break;
   case 7:
      dPrice = (High[nIndex] + Low[nIndex] + 2 * Close[nIndex]) / 4.0;
      break;
   default:
      dPrice = 0.0;
   }

   return(dPrice);
}
//+------------------------------------------------------------------+
