2004 Jun: VolumeFlowIndicator.efs

ICE Data Services -

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);
    }
}