#property copyright "Copyright S.Projects" #property link "http://trader.snowseed.com" #property indicator_separate_window #property indicator_buffers 1 #property indicator_color1 Red #property indicator_minimum 0 #property indicator_maximum 1 // indicator parameters extern int nClvPeriod = 27; extern int nClvMa = 7; // At the very beginning of the chart, before the MA // had enough data to draw itself properly, do not display int nDrawBeginBar; // indicator buffers double arrExtMapBuffer[]; // We are using this variable to store the number of bars // for which the chart is already drawn. The difference // between the total number of bars and this number is // the number of bars to draw (usually, 1) int nExtCountedBars = 0; //////////////////////// int init() { string strIndicatorShortName; strIndicatorShortName = "CLV(" + nClvPeriod + ", " + nClvMa + ")"; IndicatorShortName(strIndicatorShortName); // drawing settings SetIndexStyle(0, DRAW_LINE); SetIndexShift(0, 0); IndicatorDigits(4); // Skip drawing at the beginning of a chart nDrawBeginBar = MathMax(nClvPeriod, nClvMa); SetIndexDrawBegin(0, nDrawBeginBar); // indicator buffers mapping SetIndexBuffer(0, arrExtMapBuffer); return(0); } /////////////////////////// int start() { // Not enough points on a chart if(Bars <= nDrawBeginBar) return(0); // See if we have new data to plot (if a new tick came, // and it is the first tick of a new bar nExtCountedBars = IndicatorCounted(); if(nExtCountedBars < 0) return(-1); // Last counted bar will be recounted // Note, that here we force the last bar to be recounted. // You may comment this code, if you only want to do it // at the beginning of a new bar. I only keep this code // for compatibility with a little mess created by official // tutorials: see comment below (*) if(nExtCountedBars > 0) nExtCountedBars--; Clv(); return(0); } /////////////////// // For the selected period: // CLV = ((Close - Low) - (High - Close)) / (High - Low) void Clv() { // (*) Note the line below. If we use // "int nPos = Bars - nExtCountedBars;" the last bar // will be recounted every tick. If there is no "- 1", // only the beginning of a new bar triggers the code. int nPos = Bars - nExtCountedBars; // Note, that nPos is always > 0. It means, that Close[nPos] // is never Close[0], so we don't make a mistake by "looking // into the future". Note also, that we assign the value // to the arrExtMapBuffer[nPos]. It means, that when calling // this indicator from the expert, we need to use shift // >= 1. If we want to be able to call it with shift == 0, // we need to rewrite the code below, using // arrExtMapBuffer[nPos - 1]. The Close[...] and all other // functions obtaining data, should still use [nPos]. while(nPos > 0 && nPos < ArraySize(Low)) { double dClose = Close[nPos]; double dLow = Low[ArrayMinimum(Low, nClvPeriod, nPos)]; double dHigh = High[ArrayMaximum(High, nClvPeriod, nPos)]; arrExtMapBuffer[nPos] = 0; if(dHigh - dLow != 0) arrExtMapBuffer[nPos] = (((dClose - dLow) - (dHigh - dClose)) / (dHigh - dLow)) / 2 + 0.5; else arrExtMapBuffer[nPos] = 0; nPos--; } if(nClvMa > 1) Ema(arrExtMapBuffer); } /////////////////// void Ema(double& arr[]) { double dPr = 2.0 / (nClvMa + 1); int nPos = Bars - nExtCountedBars; while(nPos > 0) { if(nPos == Bars - 2) arrExtMapBuffer[nPos + 1] = arr[nPos + 1]; arrExtMapBuffer[nPos] = arr[nPos] * dPr + arrExtMapBuffer[nPos + 1] * (1 - dPr); nPos--; } } ///////////////////
Sample
Analysis
Market Information Used:
Series array that contains close prices for each bar
Series array that contains the lowest prices of each bar
Series array that contains the highest prices of each bar
Indicator Curves created:
Implements a curve of type DRAW_LINE
Indicators Used:
Custom Indicators Used:
Order Management characteristics:
Other Features: