//+------------------------------------------------------------------+
//|                               Embeded_Obv_ObvRsi_EA_LBW_file.mq5 |
//|                                  Copyright 2026, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//#property indicator_chart_window
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots 1

#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

double ObvBuf[];

input bool UseRealVolume = false;
input ENUM_APPLIED_PRICE ObvPrice = PRICE_WEIGHTED;

input color  OBV_Color = clrDodgerBlue;
input int    OBV_Width = 1;
input ENUM_LINE_STYLE OBV_Style = STYLE_SOLID;


double m_obv[];
ENUM_APPLIED_PRICE m_obvPrice;
int m_volumeMode;

#define USE_REAL_VOLUME 1
#define USE_TICK_VOLUME 0

double AppliedPrice(const double &open[],
                    const double &high[],
                    const double &low[],
                    const double &close[],
                    const int i)
{
   switch(m_obvPrice)
   {
      case PRICE_OPEN:    return open[i];
      case PRICE_HIGH:    return high[i];
      case PRICE_LOW:     return low[i];
      case PRICE_MEDIAN:  return (high[i]+low[i]) / 2.0;
      case PRICE_TYPICAL: return (high[i]+low[i]+close[i]) / 3.0;
      case PRICE_WEIGHTED:return (high[i]+low[i]+close[i]+close[i]) / 4.0;
      default:            return close[i];
   }
}

bool Compute(const double &open[],
             const double &high[],
             const double &low[],
             const double &close[],
             const long   &tick_volume[],
             const long   &real_volume[],
             const int     size)
{
   for(int i=0;i<size;i++)
   {
      double price      = AppliedPrice(open,high,low,close,i);
      double prev_price = (i==0 ? price : AppliedPrice(open,high,low,close,i-1));

      long vol_i = (m_volumeMode == USE_REAL_VOLUME ? real_volume[i] : tick_volume[i]);
      double vol = (double)vol_i;

      if(i==0)
         m_obv[i] = 0.0;
      else
      {
         double prev_obv = m_obv[i-1];

         if(price > prev_price)
            m_obv[i] = prev_obv + vol;
         else if(price < prev_price)
            m_obv[i] = prev_obv - vol;
         else
            m_obv[i] = prev_obv;
      }
   }
   return true;
}

int OnInit()
{
   SetIndexBuffer(0, ObvBuf, INDICATOR_DATA);
   PlotIndexSetString(0, PLOT_LABEL, "OBV_APPLIED");
   
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, OBV_Color);
   PlotIndexSetInteger(0, PLOT_LINE_STYLE, OBV_Style);
   PlotIndexSetInteger(0, PLOT_LINE_WIDTH, OBV_Width);

   m_obvPrice   = ObvPrice;
   m_volumeMode = (UseRealVolume ? USE_REAL_VOLUME : USE_TICK_VOLUME);

   return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &real_volume[],
                const int &spread[])
{
   ArrayResize(m_obv, rates_total);
   ArraySetAsSeries(m_obv, false);

   Compute(open, high, low, close, tick_volume, real_volume, rates_total);

   for(int i=0; i<rates_total; i++)
      ObvBuf[i] = m_obv[i];

   return(rates_total);
}

