Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 7

//+------------------------------------------------------------------+

//| OBV2.mq4 |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_maximum 1
#property indicator_minimum 0
#property strict

//
//
//
//
//

enum enMaTypes
{
ma_sma, // Simple moving average
ma_ema, // Exponential moving average
ma_smma, // Smoothed MA
ma_lwma, // Linear weighted MA
ma_tema // Triple exponential moving average - TEMA
};

extern ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;// Time frame to use


extern int SignalPeriod = 13; // Obv Ma signal period
extern enMaTypes SignalMaMode = ma_lwma; // average type
extern int HistoWidth = 3; // Histogram bars width
extern color UpHistoColor = clrDodgerBlue; // Up Histogram color
extern color DnHistoColor = clrRed; // Down histogram color
extern bool alertsOn = false; // Turn alerts on?
extern bool alertsOnCurrent = false; // Alerts on a current
bar?
extern bool alertsMessage = true; // Alerts should show
pop-up message?
extern bool alertsSound = false; // Alerts should play
alert sound?
extern bool alertsEmail = false; // Alerts should send
email?
extern bool arrowsVisible = false; // Arrows visible?
extern string arrowsIdentifier = "obv arrows1"; // Arrows unique ID
extern double arrowsDisplacement = 1.0; // Arros displacement
(gap)
extern color arrowsUpColor = clrLimeGreen; // Arrows up color
extern color arrowsDnColor = clrRed; // Arrows down color

//
//
//
//

double hu[],hd[],obv[],ma[],trend[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind)
iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,SignalPeriod,SignalMaMode,H
istoWidth,UpHistoColor,DnHistoColor,alertsOn,alertsOnCurrent,alertsMessage,alertsSo
und,alertsEmail,arrowsVisible,arrowsIdentifier,arrowsDisplacement,arrowsUpColor,arr
owsDnColor,_buff,_ind)
//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
//
//
//
//

int init()
{
IndicatorBuffers(6);
SetIndexBuffer(0,hu); SetIndexStyle(0,
DRAW_HISTOGRAM,EMPTY,HistoWidth,UpHistoColor);
SetIndexBuffer(1,hd); SetIndexStyle(1,
DRAW_HISTOGRAM,EMPTY,HistoWidth,DnHistoColor);
SetIndexBuffer(2,obv);
SetIndexBuffer(3,ma);
SetIndexBuffer(4,trend);
SetIndexBuffer(5,count);

indicatorFileName = WindowExpertName();
TimeFrame = fmax(TimeFrame,_Period);

IndicatorShortName(timeFrameToString(TimeFrame)+" obv ma");


return(0);
}
int deinit()
{
string lookFor = arrowsIdentifier+":";
int lookForLength = StringLen(lookFor);
for (int i=ObjectsTotal()-1; i>=0; i--)
{
string objectName = ObjectName(i);
if (StringSubstr(objectName,0,lookForLength) == lookFor)
ObjectDelete(objectName);
}
return(0);
}

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

int start()
{
int i,counted_bars=IndicatorCounted();
if(counted_bars<0) return(-1);
if(counted_bars>0) counted_bars--;
int limit = fmin(Bars-counted_bars,Bars-1); count[0]=limit;
if (TimeFrame!=_Period)
{
limit = (int)fmax(limit,fmin(Bars-
1,_mtfCall(6,0)*TimeFrame/_Period));
for (i=limit;i>=0 && !_StopFlag; i--)
{
int y = iBarShift(NULL,TimeFrame,Time[i]);
hu[i] = _mtfCall(0,y);
hd[i] = _mtfCall(1,y);
}
return(0);
}

//
//
//
//
//

for (i=limit; i>=0; i--)


{
if (i==(Bars-1))
{ obv[i] = (double)Volume[i]; }
else { if((High[i] == Low[i]) || (Open[i] == Close[i]) || (Close[i] ==
Close[i+1])) { obv[i] = obv[i+1]; }

else { if (Close[i] > Open[i])


obv[i] = obv[i+1] + (Volume[i] * (Close[i] - Open[i]) / (High[i]
- Low[i]));
else obv[i] = obv[i+1] - (Volume[i] * (Open[i] - Close[i]) / (High[i]
- Low[i])); } }
ma[i] = iCustomMa(SignalMaMode,obv[i],SignalPeriod,i,0);
hu[i] = EMPTY_VALUE;
hd[i] = EMPTY_VALUE;
trend[i] = (i<Bars-1) ? (obv[i]>ma[i]) ? 1 : (obv[i]<ma[i]) ? -1 :
trend[i+1] : 0;
if (trend[i] == 1) hu[i] = 1;
if (trend[i] ==-1) hd[i] = 1;
manageArrow(i);
}
manageAlerts();
return(0);
}

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

#define _maInstances 1
#define _maWorkBufferx1 1*_maInstances
#define _maWorkBufferx2 2*_maInstances
#define _maWorkBufferx3 3*_maInstances

double iCustomMa(int mode, double price, double length, int r, int instanceNo=0)
{
int bars = Bars; r = bars-r-1;
switch (mode)
{
case ma_sma : return(iSma(price,(int)length,r,bars,instanceNo));
case ma_ema : return(iEma(price,length,r,bars,instanceNo));
case ma_smma : return(iSmma(price,(int)length,r,bars,instanceNo));
case ma_lwma : return(iLwma(price,(int)length,r,bars,instanceNo));
case ma_tema : return(iTema(price,(int)length,r,bars,instanceNo));
default : return(price);
}
}

//
//
//
//
//

double workSma[][_maWorkBufferx2];
double iSma(double price, int period, int r, int _bars, int instanceNo=0)
{
if (ArrayRange(workSma,0)!= _bars) ArrayResize(workSma,_bars); instanceNo *= 2;
int k;

workSma[r][instanceNo+0] = price;
workSma[r][instanceNo+1] = price; for(k=1; k<period && (r-k)>=0; k++) workSma[r]
[instanceNo+1] += workSma[r-k][instanceNo+0];
workSma[r][instanceNo+1] /= 1.0*k;
return(workSma[r][instanceNo+1]);
}

//
//
//
//
//

double workEma[][_maWorkBufferx1];
double iEma(double price, double period, int r, int _bars, int instanceNo=0)
{
if (ArrayRange(workEma,0)!= _bars) ArrayResize(workEma,_bars);

workEma[r][instanceNo] = price;
if (r>0 && period>1)
workEma[r][instanceNo] = workEma[r-1][instanceNo]+(2.0/
(1.0+period))*(price-workEma[r-1][instanceNo]);
return(workEma[r][instanceNo]);
}

//
//
//
//
//

double workSmma[][_maWorkBufferx1];
double iSmma(double price, double period, int r, int _bars, int instanceNo=0)
{
if (ArrayRange(workSmma,0)!= _bars) ArrayResize(workSmma,_bars);

workSmma[r][instanceNo] = price;
if (r>1 && period>1)
workSmma[r][instanceNo] = workSmma[r-1][instanceNo]+(price-workSmma[r-1]
[instanceNo])/period;
return(workSmma[r][instanceNo]);
}

//
//
//
//
//

double workLwma[][_maWorkBufferx1];
double iLwma(double price, double period, int r, int _bars, int instanceNo=0)
{
if (ArrayRange(workLwma,0)!= _bars) ArrayResize(workLwma,_bars);

workLwma[r][instanceNo] = price; if (period<=1) return(price);


double sumw = period;
double sum = period*price;

for(int k=1; k<period && (r-k)>=0; k++)


{
double weight = period-k;
sumw += weight;
sum += weight*workLwma[r-k][instanceNo];
}
return(sum/sumw);
}

double workTema[][_maWorkBufferx3];
#define _tema1 0
#define _tema2 1
#define _tema3 2

double iTema(double price, double period, int r, int bars, int instanceNo=0)
{
if (period<=1) return(price);
if (ArrayRange(workTema,0)!= bars) ArrayResize(workTema,bars); instanceNo*=3;

//
//
//
//
//

workTema[r][_tema1+instanceNo] = price;
workTema[r][_tema2+instanceNo] = price;
workTema[r][_tema3+instanceNo] = price;
double alpha = 2.0 / (1.0+period);
if (r>0)
{
workTema[r][_tema1+instanceNo] = workTema[r-1][_tema1+instanceNo]
+alpha*(price -workTema[r-1][_tema1+instanceNo]);
workTema[r][_tema2+instanceNo] = workTema[r-1][_tema2+instanceNo]
+alpha*(workTema[r][_tema1+instanceNo]-workTema[r-1][_tema2+instanceNo]);
workTema[r][_tema3+instanceNo] = workTema[r-1][_tema3+instanceNo]
+alpha*(workTema[r][_tema2+instanceNo]-workTema[r-1][_tema3+instanceNo]); }
return(workTema[r][_tema3+instanceNo]+3.0*(workTema[r][_tema1+instanceNo]-
workTema[r][_tema2+instanceNo]));
}

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

void manageAlerts()
{
if (alertsOn)
{
int whichBar = 1; if (alertsOnCurrent) whichBar = 0;
if (trend[whichBar] != trend[whichBar+1])
{
if (trend[whichBar] == 1) doAlert(whichBar,"up");
if (trend[whichBar] == -1) doAlert(whichBar,"down");
}
}
}

//
//
//
//
//

void doAlert(int forBar, string doWhat)


{
static string previousAlert="nothing";
static datetime previousTime;
string message;

if (previousAlert != doWhat || previousTime != Time[forBar]) {


previousAlert = doWhat;
previousTime = Time[forBar];

//
//
//
//
//

message = timeFrameToString(_Period)+Symbol()+" at
"+TimeToStr(TimeLocal(),TIME_SECONDS)+" obv ma trend changed to "+doWhat;
if (alertsMessage) Alert(message);
if (alertsEmail) SendMail(Symbol()+" obv ma ",message);
if (alertsSound) PlaySound("alert2.wav");
}
}

//
//
//
//
//
void manageArrow(int i)
{
if (arrowsVisible)
{
string lookFor = arrowsIdentifier+":"+(string)Time[i]; ObjectDelete(lookFor);
if (i<(Bars-1) && trend[i]!=trend[i+1])
{
if (trend[i] == 1) drawArrow(i,arrowsUpColor,241,false);
if (trend[i] ==-1) drawArrow(i,arrowsDnColor,242,true);
}
}
}

//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,bool up)


{
string name = arrowsIdentifier+":"+(string)Time[i];
double gap = iATR(NULL,0,20,i);

//
//
//
//
//

ObjectCreate(name,OBJ_ARROW,0,Time[i],0);
ObjectSet(name,OBJPROP_ARROWCODE,theCode);
ObjectSet(name,OBJPROP_COLOR,theColor);

if (up)
ObjectSet(name,OBJPROP_PRICE1,High[i] + arrowsDisplacement * gap);
else ObjectSet(name,OBJPROP_PRICE1,Low[i] - arrowsDisplacement * gap);
}

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

string sTfTable[] = {"M1","M5","M10","M15","M30","H1","H4","D1","W1","MN"};


int iTfTable[] = {1,5,10,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)


{
for (int i=ArraySize(iTfTable)-1; i>=0; i--)
if (tf==iTfTable[i]) return(sTfTable[i]);
return("");
}

You might also like