You guys have been a tremendous help. I'm so glad I found this community. Below is the code for a volitilty quality indicator I have. I wish to be able to turn off the Solid line divergences and the histogram as I only use the dotted line divergences on the chart. The code won't let me turn off the solid lines by using "none" as the color without turning off the dotted divergence lines. The histogram I can just minimize the window so that really isn't an issue. I'm just trying to keep my chart uncluttered as best I can.
Code: Select all
//+------------------------------------------------------------------+
//| Volatility quality.mq4 |
//| |
//| |
//| Volatility quality index originaly developed by |
//| Thomas Stridsman (August 2002 Active Trader Magazine) |
//+------------------------------------------------------------------+
#property copyright "www.forex-station.com"
#property link "www.forex-station.com"
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1 PaleVioletRed
#property indicator_color2 PaleVioletRed
#property indicator_color3 DeepSkyBlue
#property indicator_color4 DeepSkyBlue
#property indicator_color5 Silver
#property indicator_width1 2
#property indicator_width3 2
#property indicator_width5 2
#property indicator_levelcolor DarkGray
//
//
//
//
//
extern string TimeFrame = "Current time frame";
extern int PriceSmoothing = 5;
extern int PriceSmoothingMethod = MODE_LWMA;
extern double Filter = 0.05;
extern bool divergenceVisible = true;
extern bool divergenceOnValuesVisible = true;
extern bool divergenceOnChartVisible = true;
extern color divergenceBullishColor = Green;
extern color divergenceBearishColor = OrangeRed;
extern string divergenceUniqueID = "vq diverge1";
extern bool HistogramOnSlope = false;
extern bool Interpolate = true;
extern bool alertsOn = false;
extern bool alertsOnSlope = false;
extern bool alertsOnCurrent = true;
extern bool alertsMessage = true;
extern bool alertsSound = false;
extern bool alertsEmail = false;
//
//
//
//
//
double Upa[];
double Upb[];
double Dna[];
double Dnb[];
double sumVqi[];
double Vqi[];
double trend[];
double slope[];
int timeFrame;
string indicatorFileName;
bool returnBars;
bool calculateValue;
string shortName;
//+------------------------------------------------------------------
//|
//+------------------------------------------------------------------
//
//
//
//
//
int init()
{
IndicatorBuffers(8);
SetIndexBuffer(0,Dna); SetIndexStyle(0,DRAW_HISTOGRAM);
SetIndexBuffer(1,Dnb); SetIndexStyle(1,DRAW_HISTOGRAM);
SetIndexBuffer(2,Upa); SetIndexStyle(2,DRAW_HISTOGRAM);
SetIndexBuffer(3,Upb); SetIndexStyle(3,DRAW_HISTOGRAM);
SetIndexBuffer(4,sumVqi);
SetIndexBuffer(5,Vqi);
SetIndexBuffer(6,trend);
SetIndexBuffer(7,slope);
SetLevelValue(0,0);
PriceSmoothing = MathMax(PriceSmoothing,1);
//
//
//
//
//
indicatorFileName = WindowExpertName();
returnBars = (TimeFrame=="returnBars"); if (returnBars) return(0);
calculateValue = (TimeFrame=="calculateValue");
if (calculateValue)
{
int s = StringFind(divergenceUniqueID,":",0);
shortName = divergenceUniqueID;
divergenceUniqueID = StringSubstr(divergenceUniqueID,0,s);
return(0);
}
timeFrame = stringToTimeFrame(TimeFrame);
//
//
//
//
//
shortName = divergenceUniqueID+": "+timeFrameToString(timeFrame)+" Volatility quality zero line ";
IndicatorShortName(shortName);
return(0);
}
//
//
//
//
//
int deinit()
{
int lookForLength = StringLen(divergenceUniqueID);
for (int i=ObjectsTotal()-1; i>=0; i--)
{
string objectName = ObjectName(i);
if (StringSubstr(objectName,0,lookForLength) == divergenceUniqueID) ObjectDelete(objectName);
}
return(0);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
int start()
{
int counted_bars=IndicatorCounted();
int i,limit;
if(counted_bars<0) return(-1);
if(counted_bars>0) counted_bars--;
limit = MathMin(Bars-counted_bars,Bars-1);
if (returnBars) { Dna[0] = limit+1; return(0); }
double pipMultiplier = MathPow(10,_Digits%2);
//
//
//
//
//
if (calculateValue || timeFrame == Period())
{
for(i=limit; i>=0; i--)
{
if (i==(Bars-1))
{
Vqi[i] = 0;
sumVqi[i] = 0;
continue;
}
//
//
//
//
//
double cHigh = iMA(NULL,0,PriceSmoothing,0,PriceSmoothingMethod,PRICE_HIGH ,i);
double cLow = iMA(NULL,0,PriceSmoothing,0,PriceSmoothingMethod,PRICE_LOW ,i);
double cOpen = iMA(NULL,0,PriceSmoothing,0,PriceSmoothingMethod,PRICE_OPEN ,i);
double cClose = iMA(NULL,0,PriceSmoothing,0,PriceSmoothingMethod,PRICE_CLOSE,i);
double pClose = iMA(NULL,0,PriceSmoothing,0,PriceSmoothingMethod,PRICE_CLOSE,i+1);
double trueRange = MathMax(cHigh,pClose)-MathMin(cLow,pClose);
double range = cHigh-cLow;
if (range != 0 && trueRange!=0)
double vqi = ((cClose-pClose)/trueRange + (cClose-cOpen)/range)*0.5;
else vqi = Vqi[i+1];
//
//
//
//
//
Vqi[i] = MathAbs(vqi) * (cClose - pClose+cClose - cOpen) * 0.5;
sumVqi[i] = Vqi[i];
Dna[i] = EMPTY_VALUE;
Dnb[i] = EMPTY_VALUE;
Upa[i] = EMPTY_VALUE;
Upb[i] = EMPTY_VALUE;
if (Filter > 0) if (fabs(sumVqi[i]-sumVqi[i+1]) < Filter*Point*pipMultiplier) sumVqi[i] = sumVqi[i+1];
//
//
//
//
//
trend[i] = trend[i+1];
slope[i] = slope[i+1];
if (sumVqi[i] > 0) trend[i] = 1;
if (sumVqi[i] < 0) trend[i] = -1;
if (sumVqi[i] > sumVqi[i+1]) slope[i] = 1;
if (sumVqi[i] < sumVqi[i+1]) slope[i] = -1;
if (divergenceVisible)
{
CatchBullishDivergence(sumVqi,i);
CatchBearishDivergence(sumVqi,i);
}
if (HistogramOnSlope)
{
if (trend[i]== 1 && slope[i] == 1) Upa[i] = sumVqi[i];
if (trend[i]== 1 && slope[i] ==-1) Upb[i] = sumVqi[i];
if (trend[i]==-1 && slope[i] ==-1) Dna[i] = sumVqi[i];
if (trend[i]==-1 && slope[i] == 1) Dnb[i] = sumVqi[i];
}
else
{
if (trend[i]== 1) Upa[i] = sumVqi[i];
if (trend[i]==-1) Dna[i] = sumVqi[i];
}
}
manageAlerts();
return(0);
}
//
//
//
//
//
limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,timeFrame,indicatorFileName,"returnBars",0,0)*timeFrame/Period()));
for(i=limit; i>=0; i--)
{
int y = iBarShift(NULL,timeFrame,Time[i]);
sumVqi[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",PriceSmoothing,PriceSmoothingMethod,Filter,divergenceVisible,divergenceOnValuesVisible,divergenceOnChartVisible,divergenceBullishColor,divergenceBearishColor,shortName,Interpolate,4,y);
trend[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",PriceSmoothing,PriceSmoothingMethod,Filter,divergenceVisible,divergenceOnValuesVisible,divergenceOnChartVisible,divergenceBullishColor,divergenceBearishColor,shortName,Interpolate,6,y);
slope[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",PriceSmoothing,PriceSmoothingMethod,Filter,divergenceVisible,divergenceOnValuesVisible,divergenceOnChartVisible,divergenceBullishColor,divergenceBearishColor,shortName,Interpolate,7,y);
Dna[i] = EMPTY_VALUE;
Dnb[i] = EMPTY_VALUE;
Upa[i] = EMPTY_VALUE;
Upb[i] = EMPTY_VALUE;
//
//
//
//
//
if (!Interpolate || y==iBarShift(NULL,timeFrame,Time[i-1])) continue;
//
//
//
//
//
datetime time = iTime(NULL,timeFrame,y);
for(int n = 1; i+n < Bars && Time[i+n] >= time; n++) continue;
for(int k = 1; k < n; k++)
sumVqi[i+k] = sumVqi[i] + (sumVqi[i+n] - sumVqi[i]) * k/n;
}
for (i=limit;i>=0;i--)
{
if (HistogramOnSlope)
{
if (trend[i]== 1 && slope[i] == 1) Upa[i] = sumVqi[i];
if (trend[i]== 1 && slope[i] ==-1) Upb[i] = sumVqi[i];
if (trend[i]==-1 && slope[i] ==-1) Dna[i] = sumVqi[i];
if (trend[i]==-1 && slope[i] == 1) Dnb[i] = sumVqi[i];
}
else
{
if (trend[i]== 1) Upa[i] = sumVqi[i];
if (trend[i]==-1) Dna[i] = sumVqi[i];
}
}
manageAlerts();
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//
//
//
//
//
void manageAlerts()
{
if (!calculateValue && alertsOn)
{
if (alertsOnCurrent)
int whichBar = 0;
else whichBar = 1; whichBar = iBarShift(NULL,0,iTime(NULL,timeFrame,whichBar));
//
//
//
//
//
if (alertsOnSlope)
{
if (slope[whichBar] != slope[whichBar+1])
{
if (slope[whichBar] == 1) doAlert(whichBar,"slope changed to up");
if (slope[whichBar] ==-1) doAlert(whichBar,"slope changed to down");
}
}
else
{
if (trend[whichBar] != trend[whichBar+1])
{
if (trend[whichBar] == 1) doAlert(whichBar,"crossed zero line up");
if (trend[whichBar] ==-1) doAlert(whichBar,"crossed zero line 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 = StringConcatenate(Symbol()," ",timeFrameToString(timeFrame)," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," VQ oscillator ",doWhat);
if (alertsMessage) Alert(message);
if (alertsEmail) SendMail(StringConcatenate(Symbol(),"VQ"),message);
if (alertsSound) PlaySound("alert2.wav");
}
}
//+------------------------------------------------------------------
//|
//+------------------------------------------------------------------
//
//
//
//
//
void CatchBullishDivergence(double& values[], int i)
{
i++;
ObjectDelete(divergenceUniqueID+"l"+DoubleToStr(Time[i],0));
ObjectDelete(divergenceUniqueID+"l"+"os" + DoubleToStr(Time[i],0));
if (!IsIndicatorLow(values,i)) return;
//
//
//
//
//
int currentLow = i;
int lastLow = GetIndicatorLastLow(values,i+1);
if (values[currentLow] > values[lastLow] && Low[currentLow] < Low[lastLow])
{
if(divergenceOnChartVisible) DrawPriceTrendLine("l",Time[currentLow],Time[lastLow],Low[currentLow],Low[lastLow],divergenceBullishColor,STYLE_SOLID);
if(divergenceOnValuesVisible) DrawIndicatorTrendLine("l",Time[currentLow],Time[lastLow],values[currentLow],values[lastLow],divergenceBullishColor,STYLE_SOLID);
}
if (values[currentLow] < values[lastLow] && Low[currentLow] > Low[lastLow])
{
if(divergenceOnChartVisible) DrawPriceTrendLine("l",Time[currentLow],Time[lastLow],Low[currentLow],Low[lastLow], divergenceBullishColor, STYLE_DOT);
if(divergenceOnValuesVisible) DrawIndicatorTrendLine("l",Time[currentLow],Time[lastLow],values[currentLow],values[lastLow], divergenceBullishColor, STYLE_DOT);
}
}
//
//
//
//
//
void CatchBearishDivergence(double& values[], int i)
{
i++;
ObjectDelete(divergenceUniqueID+"h"+DoubleToStr(Time[i],0));
ObjectDelete(divergenceUniqueID+"h"+"os" + DoubleToStr(Time[i],0));
if (IsIndicatorPeak(values,i) == false) return;
//
//
//
//
//
int currentPeak = i;
int lastPeak = GetIndicatorLastPeak(values,i+1);
if (values[currentPeak] < values[lastPeak] && High[currentPeak]>High[lastPeak])
{
if (divergenceOnChartVisible) DrawPriceTrendLine("h",Time[currentPeak],Time[lastPeak],High[currentPeak],High[lastPeak],divergenceBearishColor,STYLE_SOLID);
if (divergenceOnValuesVisible) DrawIndicatorTrendLine("h",Time[currentPeak],Time[lastPeak],values[currentPeak],values[lastPeak],divergenceBearishColor,STYLE_SOLID);
}
if(values[currentPeak] > values[lastPeak] && High[currentPeak] < High[lastPeak])
{
if (divergenceOnChartVisible) DrawPriceTrendLine("h",Time[currentPeak],Time[lastPeak],High[currentPeak],High[lastPeak], divergenceBearishColor, STYLE_DOT);
if (divergenceOnValuesVisible) DrawIndicatorTrendLine("h",Time[currentPeak],Time[lastPeak],values[currentPeak],values[lastPeak], divergenceBearishColor, STYLE_DOT);
}
}
//
//
//
//
//
bool IsIndicatorPeak(double& values[], int i) { return(values[i] >= values[i+1] && values[i] > values[i+2] && values[i] > values[i-1]); }
bool IsIndicatorLow( double& values[], int i) { return(values[i] <= values[i+1] && values[i] < values[i+2] && values[i] < values[i-1]); }
int GetIndicatorLastPeak(double& values[], int shift)
{
for(int i = shift+5; i<Bars; i++)
if (values[i] >= values[i+1] && values[i] > values[i+2] && values[i] >= values[i-1] && values[i] > values[i-2]) return(i);
return(-1);
}
int GetIndicatorLastLow(double& values[], int shift)
{
for(int i = shift+5; i<Bars; i++)
if (values[i] <= values[i+1] && values[i] < values[i+2] && values[i] <= values[i-1] && values[i] < values[i-2]) return(i);
return(-1);
}
//+------------------------------------------------------------------
//|
//+------------------------------------------------------------------
//
//
//
//
//
void DrawPriceTrendLine(string first,datetime t1, datetime t2, double p1, double p2, color lineColor, double style)
{
string label = divergenceUniqueID+first+"os"+DoubleToStr(t1,0);
if (Interpolate) t2 += Period()*60-1;
ObjectDelete(label);
ObjectCreate(label, OBJ_TREND, 0, t1+Period()*60-1, p1, t2, p2, 0, 0);
ObjectSet(label, OBJPROP_RAY, false);
ObjectSet(label, OBJPROP_COLOR, lineColor);
ObjectSet(label, OBJPROP_STYLE, style);
}
//
//
//
//
//
void DrawIndicatorTrendLine(string first,datetime t1, datetime t2, double p1, double p2, color lineColor, double style)
{
int indicatorWindow = WindowFind(shortName);
if (indicatorWindow < 0) return;
if (Interpolate) t2 += Period()*60-1;
string label = divergenceUniqueID+first+DoubleToStr(t1,0);
ObjectDelete(label);
ObjectCreate(label, OBJ_TREND, indicatorWindow, t1+Period()*60-1, p1, t2, p2, 0, 0);
ObjectSet(label, OBJPROP_RAY, false);
ObjectSet(label, OBJPROP_COLOR, lineColor);
ObjectSet(label, OBJPROP_STYLE, style);
}
//+-------------------------------------------------------------------
//|
//+-------------------------------------------------------------------
//
//
string sTfTable[] = { "M1","M5","M15","M30","H1","H4","D1","W1","MN" };
int iTfTable[] = { 1,5,15,30,60,240,1440,10080,43200 };
//
//
//
//
//
int stringToTimeFrame(string tfs) {
tfs = stringUpperCase(tfs);
for (int i=ArraySize(iTfTable)-1; i>=0; i--)
if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
return(Period());
}
//
//
//
//
//
string timeFrameToString(int tf) {
for (int i=ArraySize(iTfTable)-1; i>=0; i--)
if (tf==iTfTable[i]) return(sTfTable[i]);
return("");
}
//
//
//
//
//
string stringUpperCase(string str) {
string s = str;
for (int length=StringLen(str)-1; length>=0; length--) {
int tchar = StringGetChar(s, length);
if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
s = StringSetChar(s, length, tchar - 32);
else if(tchar > -33 && tchar < 0)
s = StringSetChar(s, length, tchar + 224);
}
return(s);
}