VolumeFlowIndicator.efs
File Name: VolumeFlowIndicator.efs
Description:
Based on Using Money Flow to Stay With the Trend by Markos Katsanos. This article appeared in the June 2004 issue of Stock & Commodities.
Formula Parameters:
- VFI Length - 30
- MA of VFI Length - 50
Notes:
The related article is copyrighted material. If you are not a subscriber of Stocks & Commodities, please visit www.traders.com.
Version 1.1
This formula has been modified 5/4/2004. An input parameter for the VFI length was added and the MA length of volume for volume curtailment is set to the same length.
Download File:
VolumeFlowIndicator.efs
EFS Code:
/***************************************************************** Provided By : eSignal. (c) Copyright 2004 Study: Volume Flow Indicator by Markos Katsanos Version: 1.1 4/8/2004 Notes: 1.1 5/4/2004 * Added input parameter for VFI length and set MA length of volume for volume curtailment to the same length. Formula Parameters: Default: VFI Length 30 MA of VFI Length 50 *****************************************************************/ function preMain() { setStudyTitle("Volume Flow Indicator "); setShowTitleParameters(false); setCursorLabelName("VFI", 0); setCursorLabelName("VFI MA", 1); setDefaultBarFgColor(Color.green, 0); setDefaultBarFgColor(Color.blue, 1); setDefaultBarThickness(2, 0); setDefaultBarThickness(1, 1); addBand(0, PS_SOLID, 1, Color.black, "zero"); var fp0 = new FunctionParameter("nVFIlength", FunctionParameter.NUMBER); fp0.setName("VFI Length"); fp0.setLowerLimit(1); fp0.setDefault(26); var fp1 = new FunctionParameter("nVFImaLen", FunctionParameter.NUMBER); fp1.setName("MA of VFI Length"); fp1.setLowerLimit(1); fp1.setDefault(50); } var nTyp = null; // Current typical price var nTyp1 = null; // Previous typical price var nTypChg = 0; // Current typical price change var vVol = null; // Current volume var nVolSum = 0; // Cumulative volume sum var nVolAdj = 0; // Current adjusted volume var nVolMA = null; // Current Vol MA var nVolMA1 = null; // Previous Vol MA var aTypPrice = null; // Array of changes in typical price var aVolume = null; // Volume array var VFI = null; // Current VFI var aVFI = null; // Array of VFI values for EMA calc var aVFI = new Array(3); // Array of VFI values for EMA calc var aEMA = null; // Array of VFI 3EMA values // globals for EMA var vEMA = null; var vEMA1 = null; var dPercent = 0.0; var bPrimed = false; var bEdit = false; function main(nVFIlength, nVFImaLen) { var nState = getBarState(); var vInter = 0; var nCutoff = 0; var vMAofEMA = null; var dSum = 0; var i = 0; if (bEdit == false) { if (aTypPrice == null) aTypPrice = new Array(nVFIlength); if (aVolume == null) aVolume = new Array(nVFIlength); if (aEMA == null) aEMA = new Array(nVFImaLen); bEdit = true; } if (nState == BARSTATE_NEWBAR) { if (nTyp != null) { aTypPrice.pop(); aTypPrice.unshift(nTypChg); nTyp1 = nTyp; } if (nVol != null) { aVolume.pop(); aVolume.unshift(nVol); } nVolMA1 = nVolMA; nVolSum += nVolAdj; if (VFI != null) { aVFI.pop(); aVFI.unshift(VFI); } if (vEMA != null) { aEMA.pop(); aEMA.unshift(vEMA); } } nVol = volume(); if (nVol == null) return; aVolume[0] = nVol; if (aVolume[nVFIlength-1] != null) { for (i = 0; i < nVFIlength; ++i) { dSum += aVolume[i]; } nVolMA = dSum/nVFIlength; } nTyp = (high() + low() + close()) / 3; if (nTyp1 != null) { nTypChg = (Math.log(nTyp) - Math.log(nTyp1)); aTypPrice[0] = nTypChg; } if (nVolMA == null || nVolMA1 == null) return; if (aTypPrice[nVFIlength-1] != null) { vInter = StDev(nVFIlength); nCutoff = (.2 * vInter * close()); } else { return; } nVolAdj = nVol; //Minimal Change Cutoff if ((nTyp - nTyp1) >= 0 && (nTyp - nTyp1) < nCutoff) nVolAdj = 0; if ((nTyp - nTyp1) < 0 && (nTyp - nTyp1) > -nCutoff) nVolAdj = 0; // Volume curtailment if (nVolAdj > (2.5*nVolMA1)) nVolAdj = (2.5*nVolMA1); if (nTyp - nTyp1 < 0 && nVolAdj > 0) nVolAdj *= -1; VFI = ((nVolSum + nVolAdj) / nVolMA1); aVFI[0] = VFI; if (aVFI[2] != null) { vEMA = EMA(); aEMA[0] = vEMA; } if (aEMA[nVFImaLen-1] != null) { dSum = 0; i = 0; for(i = 0; i < nVFImaLen; ++i) { dSum += aEMA[i]; } vMAofEMA = dSum/nVFImaLen; } if (vEMA != null) { if (vEMA >= 0) { setBarFgColor(Color.green, 0); } else { setBarFgColor(Color.red, 0); } } return new Array(vEMA, vMAofEMA); } /***** Functions *****/ function StDev(nLength) { //var nLength = 30; var sumX = 0; var sumX2 = 0; for (i = 0; i < nLength; ++i) { sumX += aTypPrice[i]; sumX2 += (aTypPrice[i] * aTypPrice[i]) } var meanX = (sumX/nLength); var stdev = Math.sqrt((sumX2/nLength) - (meanX*meanX)); return stdev; } function EMA() { var nBarState = getBarState(); var dSum = 0.0; var nLength = 3; if(nBarState == BARSTATE_ALLBARS || bPrimed == false) { dPercent = (2.0 / (nLength + 1.0)); bPrimed = false; } if (nBarState == BARSTATE_NEWBAR) { vEMA1 = vEMA; } if(bPrimed == false) { for(i = 0; i < nLength; i++) { dSum += aVFI[i]; } bPrimed = true; return (dSum / nLength); } else { return (((VFI - vEMA1) * dPercent) + vEMA1); } }