VBSM

 

Hi


I am looking for a VBSM indicator (volume based buy and sell momentum) for MT5. Is there any equivalent here?

Screenshot of Trading view VBSM attached.

Thanks

Momentum - Oscillators - Technical Indicators - Price Charts, Technical and Fundamental Analysis - MetaTrader 5 Help
Momentum - Oscillators - Technical Indicators - Price Charts, Technical and Fundamental Analysis - MetaTrader 5 Help
  • www.metatrader5.com
The Momentum Technical Indicator measures the change of price of a financial instrument over a given time span. There are basically two ways to use...
Files:
vbsm.png  166 kb
 
David Mackay:

Hi


I am looking for a VBSM indicator (volume based buy and sell momentum) for MT5. Is there any equivalent here?

Screenshot of Trading view VBSM attached.

Thanks

If the TV indicator has a source code maybe it can be converted.

 
Lorentzos Roussos #:

If the TV indicator has a source code maybe it can be converted.

Pine Script v5:

//credit to TV script thread #oG3G1T09

//@version=5
indicator(title="Volume Based Buy and Sell Momentum by 2tm", shorttitle="VBSM", overlay=false)

// Inputs
EMA_Len = input.int(25, title="Length", minval=1)

// Calculations
xROC = ta.roc(close, 1)

// Initialize variables for self-referencing
var float nRes1 = 0.0
var float nRes2 = 0.0

// Logic for nRes1 and nRes2
nRes1 := volume < volume[1] ? nRes1 + xROC : nRes1
nRes2 := volume > volume[1] ? nRes2 + xROC : nRes2

nRes3 = nRes1 + nRes2
nResEMA3 = ta.sma(nRes1, EMA_Len) + ta.sma(nRes2, EMA_Len)

// Plotting
PNVI = plot(nRes3, color=color.blue, title="PVI + NVI")
PEMA = plot(nResEMA3, color=color.red, title="EMA")

// Dynamic Color for Fill
pCol = nRes3 > nResEMA3 ? color.new(color.blue, 70) : color.new(color.red, 70)

fill(PNVI, PEMA, color=pCol, title="Momentum Fill")
 

Converted with MQL5 AI. Compiles with 0 errors and 0 warnings. Shows on a chart without drawing filling:

//+------------------------------------------------------------------+
//|                                                  VBSM.mq5        |
//|            Volume Based Buy and Sell Momentum by 2tm              |
//|                        (Pine Script Conversion)                   |
//+------------------------------------------------------------------+
#property copyright "Converted from Pine Script by MetaTrader Assistant"
#property link      ""
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   2

//--- Plot 1: PVI + NVI (nRes3)
#property indicator_label1  "PVI + NVI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- Plot 2: SMA composite (nResEMA3)
#property indicator_label2  "SMA"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

//--- Hidden fill buffers (use DRAW_FILLING on plot 2 via code)
#property indicator_label3  "Momentum Fill"
#property indicator_type3   DRAW_FILLING
#property indicator_color3  clrBlue, clrRed

//--- input parameters
input int      InpLength = 25;           // Length

//--- indicator buffers
double         BufferPviNvi[];           // nRes3 = nRes1 + nRes2
double         BufferEma[];              // nResEMA3 = SMA(nRes1) + SMA(nRes2)
double         BufferFill1[];            // Same as nRes3 (for fill)
double         BufferFill2[];            // Same as nResEMA3 (for fill)

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Indicator buffers mapping
   SetIndexBuffer(0, BufferPviNvi, INDICATOR_DATA);
   SetIndexBuffer(1, BufferEma,    INDICATOR_DATA);
   SetIndexBuffer(2, BufferFill1,  INDICATOR_DATA);
   SetIndexBuffer(3, BufferFill2,  INDICATOR_DATA);

//--- Configure filling colors
   PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_FILLING);
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, 0, clrBlue);   // when BufferPviNvi > BufferEma
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, 1, clrRed);    // when BufferPviNvi <= BufferEma

//--- Set empty value
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, 0.0);
   PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, 0.0);

//--- Short name
   IndicatorSetString(INDICATOR_SHORTNAME, "VBSM(" + (string)InpLength + ")");

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 &volume[],
                const int &spread[])
  {
   if(rates_total < 2)
      return(0);

   int start = (prev_calculated == 0) ? 1 : prev_calculated - 1;

   //--- Local static arrays to persist nRes1 and nRes2 across bars (like Pine var)
   static double nRes1[];
   static double nRes2[];

   //--- Initialize or resize static arrays
   if(ArraySize(nRes1) != rates_total)
     {
      ArrayResize(nRes1, rates_total);
      ArrayResize(nRes2, rates_total);
      if(prev_calculated == 0)
        {
         ArrayInitialize(nRes1, 0.0);
         ArrayInitialize(nRes2, 0.0);
        }
     }

   //--- Temporary SMA accumulators
   double ma1 = 0.0, ma2 = 0.0;

   for(int i = start; i < rates_total; i++)
     {
      //--- Rate of Change (%): roc(close, 1) = (close / close[1] - 1) * 100
      double xROC = (close[i - 1] > 0.0) ? ((close[i] / close[i - 1]) - 1.0) * 100.0 : 0.0;

      //--- Carry forward previous values (Pine var default: keep last value)
      nRes1[i] = nRes1[i - 1];
      nRes2[i] = nRes2[i - 1];

      //--- nRes1: accumulates xROC when volume decreases
      if(tick_volume[i] < tick_volume[i - 1])
         nRes1[i] += xROC;

      //--- nRes2: accumulates xROC when volume increases
      if(tick_volume[i] > tick_volume[i - 1])
         nRes2[i] += xROC;

      //--- Volume unchanged: neither accumulator changes (already carried forward)

      //--- nRes3 = nRes1 + nRes2
      BufferPviNvi[i] = nRes1[i] + nRes2[i];
      BufferFill1[i]  = BufferPviNvi[i];

      //--- Calculate SMAs on the fly using a simple sum over the window
      if(i >= InpLength - 1)
        {
         ma1 = 0.0;
         ma2 = 0.0;
         for(int k = 0; k < InpLength; k++)
           {
            ma1 += nRes1[i - k];
            ma2 += nRes2[i - k];
           }
         BufferEma[i]   = (ma1 / InpLength) + (ma2 / InpLength);
        }
      else
        {
         BufferEma[i] = 0.0;
        }

      BufferFill2[i] = BufferEma[i];
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Ryan L Johnson #:

Converted with MQL5 AI. Compiles with 0 errors and 0 warnings. Shows on a chart without drawing filling:

The bug is trivial.

Can you fix it with AI help ? (I mean without checking the code yourself).

 
Alain Verleyen #:

The bug is trivial.

Can you fix it with AI help ? (I mean without checking the code yourself).

Fixed with MQL5 AI:

//+------------------------------------------------------------------+
//|                                                  VBSM.mq5        |
//|            Volume Based Buy and Sell Momentum by 2tm              |
//|                        (Pine Script Conversion)                   |
//+------------------------------------------------------------------+
#property copyright "Converted from Pine Script by MetaTrader Assistant"
#property link      ""
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   3

//--- Plot 1: PVI + NVI (nRes3)
#property indicator_label1  "PVI + NVI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- Plot 2: SMA composite (nResEMA3)
#property indicator_label2  "SMA"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

//--- Hidden fill buffers (use DRAW_FILLING on plot 2 via code)
#property indicator_label3  "Momentum Fill"
#property indicator_type3   DRAW_FILLING
#property indicator_color3  clrBlue, clrRed

//--- input parameters
input int      InpLength = 25;           // Length

//--- indicator buffers
double         BufferPviNvi[];           // nRes3 = nRes1 + nRes2
double         BufferEma[];              // nResEMA3 = SMA(nRes1) + SMA(nRes2)
double         BufferFill1[];            // Same as nRes3 (for fill)
double         BufferFill2[];            // Same as nResEMA3 (for fill)

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Indicator buffers mapping
   SetIndexBuffer(0, BufferPviNvi, INDICATOR_DATA);
   SetIndexBuffer(1, BufferEma,    INDICATOR_DATA);
   SetIndexBuffer(2, BufferFill1,  INDICATOR_DATA);
   SetIndexBuffer(3, BufferFill2,  INDICATOR_DATA);

//--- Configure filling colors
   PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_FILLING);
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, 0, clrBlue);   // when BufferPviNvi > BufferEma
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, 1, clrRed);    // when BufferPviNvi <= BufferEma

//--- Set empty value
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, 0.0);
   PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, 0.0);

//--- Short name
   IndicatorSetString(INDICATOR_SHORTNAME, "VBSM(" + (string)InpLength + ")");

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 &volume[],
                const int &spread[])
  {
   if(rates_total < 2)
      return(0);

   int start = (prev_calculated == 0) ? 1 : prev_calculated - 1;

   //--- Local static arrays to persist nRes1 and nRes2 across bars (like Pine var)
   static double nRes1[];
   static double nRes2[];

   //--- Initialize or resize static arrays
   if(ArraySize(nRes1) != rates_total)
     {
      ArrayResize(nRes1, rates_total);
      ArrayResize(nRes2, rates_total);
      if(prev_calculated == 0)
        {
         ArrayInitialize(nRes1, 0.0);
         ArrayInitialize(nRes2, 0.0);
        }
     }

   //--- Temporary SMA accumulators
   double ma1 = 0.0, ma2 = 0.0;

   for(int i = start; i < rates_total; i++)
     {
      //--- Rate of Change (%): roc(close, 1) = (close / close[1] - 1) * 100
      double xROC = (close[i - 1] > 0.0) ? ((close[i] / close[i - 1]) - 1.0) * 100.0 : 0.0;

      //--- Carry forward previous values (Pine var default: keep last value)
      nRes1[i] = nRes1[i - 1];
      nRes2[i] = nRes2[i - 1];

      //--- nRes1: accumulates xROC when volume decreases
      if(tick_volume[i] < tick_volume[i - 1])
         nRes1[i] += xROC;

      //--- nRes2: accumulates xROC when volume increases
      if(tick_volume[i] > tick_volume[i - 1])
         nRes2[i] += xROC;

      //--- Volume unchanged: neither accumulator changes (already carried forward)

      //--- nRes3 = nRes1 + nRes2
      BufferPviNvi[i] = nRes1[i] + nRes2[i];
      BufferFill1[i]  = BufferPviNvi[i];

      //--- Calculate SMAs on the fly using a simple sum over the window
      if(i >= InpLength - 1)
        {
         ma1 = 0.0;
         ma2 = 0.0;
         for(int k = 0; k < InpLength; k++)
           {
            ma1 += nRes1[i - k];
            ma2 += nRes2[i - k];
           }
         BufferEma[i]   = (ma1 / InpLength) + (ma2 / InpLength);
        }
      else
        {
         BufferEma[i] = 0.0;
        }

      BufferFill2[i] = BufferEma[i];
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Ryan L Johnson #:

Fixed with MQL5 AI:

Ok good. Only the plots count was adjusted ? (That's the bug I had seen).
 
Alain Verleyen #:
Ok good. Only the plots count was adjusted ? (That's the bug I had seen).
Yes. I noticed the same thing, but I was manually coding an EA prior to fixing it with MQL5 AI.
 

One more (final) version here...

AI hardcoded the filling colors which could not be set by way of Inputs nor Colors tabs of the indicator window (despite having appeared on the Colors tab). I manually added color type Inputs for filling in this one:

Files:
VBSM.mq5  6 kb
 
Ryan L Johnson #:

One more (final) version here...

AI hardcoded the filling colors which could not be set by way of Inputs nor Colors tabs of the indicator window (despite having appeared on the Colors tab). I manually added color type Inputs for filling in this one:

You don't need to use PlotIndexSetInteger(x, PLOT_LINE_COLOR,...) if the color can only be changed by the user.

And if you need to know the color set by the user to use it elsewhere in your code, you can use :

color P2C1 = (color)PlotIndexGetInteger(2,PLOT_DRAW_TYPE,0);
color P2C2 = (color)PlotIndexGetInteger(2,PLOT_DRAW_TYPE,1);

So for your indicator it could just be :

...
//input color    FillClrUp = clrMediumBlue;
//input color    FillClrDn = clrMaroon;

//--- indicator buffers
double         BufferPviNvi[];           // nRes3 = nRes1 + nRes2
double         BufferEma[];              // nResEMA3 = SMA(nRes1) + SMA(nRes2)
double         BufferFill1[];            // Same as nRes3 (for fill)
double         BufferFill2[];            // Same as nResEMA3 (for fill)

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Indicator buffers mapping
   SetIndexBuffer(0, BufferPviNvi, INDICATOR_DATA);
   SetIndexBuffer(1, BufferEma,    INDICATOR_DATA);
   SetIndexBuffer(2, BufferFill1,  INDICATOR_DATA);
   SetIndexBuffer(3, BufferFill2,  INDICATOR_DATA);

//--- Configure filling colors
   PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_FILLING);
   //PlotIndexSetInteger(2, PLOT_LINE_COLOR, 0, FillClrUp);   // when BufferPviNvi > BufferEma
   //PlotIndexSetInteger(2, PLOT_LINE_COLOR, 1, FillClrDn);    // when BufferPviNvi <= BufferEma
  ...