RealTimeSwings.efs

ICE Data Services -

RealTimeSwings.efs  

File Name: RealTimeSwings.efs

Description:
This formula identifies swing points on a daily or intra-day basis. On intra-day intervals, the developing legs (last two legs) will update in real time. This type of study is also referred to as the Zig Zag. The main difference with this study is that the user can define swing points with a combination of user-defined inputs.

Formula Parameters:

  • Swing: # of Bars - 5
    (Number must be greater than 0. Determines the number of bars to either side of the swing point that must not exceed the swing bar's max or min value).
  • Swing: Wave Type - % Retracement
    (options are: % Retracement or % Change in Price. % Change in Price requires the price to move a minimum percentage from the previously identified swing point. % Retracement requires the price to move a minimum percentage of the distance between the 2 previously identified swing points.)
  • Swing: Wave Percentage - 30
    (The percentage requirement for the selected wave type.)
  • Swing High Price Source - High
    (options are: Open, High, Low, Close)
  • Swing Low Price Source - Low
    (options are: Open, High, Low, Close)
  • Line Thickness - 2
  • Confirmed Swing Line Color - Blue
  • Developing Swing Line Color - Red
  • Confirmed Swing Line Color - Blue
  • Developing Swing Line Color - Red
  • Display Swing Labels - True
  • Display % Retracement Label - True
  • Number of Historical Labels - 100

Notes:
To replicate the more common Zig Zag study on a 30 min chart of INTC for example, enter 1 for # of Bars, select % Change in Price and 1.5 for Wave Percentage. Another combination that works well across various intra-day intervals is a # of Bars of 10 with % Change in Price and a Wave Percentage of 0. The chart image below is using the default values above.

 

Download File:
RealTimeSwings.efs



EFS Code:

/*****************************************************************
Provided By : eSignal. (c) Copyright 2004
Study:        Real Time Swings
Version:      1.1

Formula Parameters:                 Default:
    * Swing: # of Bars              5
        This is the minimum number of bars required to define a 
        swing point.  This number is for both sides of the swing 
        point (i.e. 5 bars on the left and right of the swing bar).
    * Swing: Wave Type              % Retracement
        (% Retracement, % Change in Price)
    * Swing: Wave Percentage        30
        The number 5 will be treated as 5.0%.  The number 0.05 will 
        be treated as 0.0005%.
    * Swing High Price Source       High
    * Swing Low Price Source        Low
    * Line Thickness                2
    * Confirmed Swing Line Color    Blue
    * Developing Swing Line Color   Red
    * Display Swing Labels          True
    * Display % Retracement Label   True
    * Number of Historical Labels   100

Notes:

1.1 3/24/2004
* Added labels to display point value, % retracement, number of bars
  and price level of swings.  The number of historical labels is set 
  to 100 for performance reasons.  Increase this number to view more
  historical labels.
* Added labels to display current swing's % retracement.

    Description of Swing Labels:
    At Swing Highs -  Points (% Retracement)
                      Price (Number of Bars)

    At Swing Lows -   Price (Number of Bars)
                      Points (% Retracement)


*****************************************************************/

function preMain() {
    setPriceStudy(true);
    setStudyTitle("Real Time Swings ");
    setShowCursorLabel(false);
    setShowTitleParameters(false);
    
    var fp1 = new FunctionParameter("nNum", FunctionParameter.NUMBER);
    fp1.setName("Swing: # of Bars");
    fp1.setLowerLimit(1);
    fp1.setDefault(5);
    
    var fp2a = new FunctionParameter("sWaveType", FunctionParameter.STRING);
    fp2a.setName("Swing: Wave Type");
    fp2a.addOption("% Retracement");
    fp2a.addOption("% Change in Price");
    fp2a.setDefault("% Retracement");
    
    var fp2 = new FunctionParameter("nRet", FunctionParameter.NUMBER);
    fp2.setName("Swing: Wave Percentage");
    fp2.setLowerLimit(0);
    fp2.setDefault(30);

    var fp3 = new FunctionParameter("sHighSource", FunctionParameter.STRING);
    fp3.setName("Swing High Price Source");
    fp3.addOption("Open");
    fp3.addOption("High");
    fp3.addOption("Low");
    fp3.addOption("Close");
    fp3.setDefault("High");

    var fp4 = new FunctionParameter("sLowSource", FunctionParameter.STRING);
    fp4.setName("Swing Low Price Source");
    fp4.addOption("Open");
    fp4.addOption("High");
    fp4.addOption("Low");
    fp4.addOption("Close");
    fp4.setDefault("Low");

    var fp5 = new FunctionParameter("nThickness", FunctionParameter.NUMBER);
    fp5.setName("Line Thickness");
    fp5.setLowerLimit(1);
    fp5.setDefault(2);

    var fp6 = new FunctionParameter("cColor1", FunctionParameter.COLOR);
    fp6.setName("Confirmed Swing Line Color");
    fp6.setDefault(Color.blue);

    var fp7 = new FunctionParameter("cColor2", FunctionParameter.COLOR);
    fp7.setName("Developing Swing Line Color");
    fp7.setDefault(Color.red);    

    var fp8 = new FunctionParameter("bSwingLabels", FunctionParameter.STRING);
    fp8.setName("Display Swing Labels");
    fp8.addOption("True");
    fp8.addOption("False");
    fp8.setDefault("True");    

    var fp9 = new FunctionParameter("bRetLabel", FunctionParameter.STRING);
    fp9.setName("Display \% Retracement Label");
    fp9.addOption("True");
    fp9.addOption("False");
    fp9.setDefault("True");    

    var fp10 = new FunctionParameter("nNumLabels", FunctionParameter.NUMBER);
    fp10.setName("Number of Historical Labels");
    fp10.setLowerLimit(1);
    fp10.setDefault(100);    
}

var bEdit = true;       // tracks change of user inputs
var cntr = 0;           // image counter for swing lines
var bInit = false;      // initialization routine completion
var nNumBars = null;    // number of bars for defining swings
var sWaveTypeG = null;  // wave type for confirming swings
var nRetpcnt = null;    // percent retracement for defining swings
var nThicknessG = null; // line thickness
var cColorcon = null;   // confirmed swing color
var cColordev1 = null;  // developing swing color
var sHSource = null;    // price source for high swings
var sLSource = null;    // price source for low swings
var x1a = null;         // x-coordinate for point a of developing line 1
var x1b = null;         // x-coordinate for point b of developing line 1
var x2a = null;         // x-coordinate for point a of developing line 2
var x2b = null;         // x-coordinate for point b of developing line 2
var y1a = null;         // y-coordinate for point a of developing line 1
var y1b = null;         // y-coordinate for point b of developing line 1
var y2a = null;         // y-coordinate for point a of developing line 2
var y2b = null;         // y-coordinate for point b of developing line 2
var vLastSwing = null;  // tracking swing type of last confirmed swing
var nScntr = 0;         // bar counter for swing confirmation
var nLcntr = 0;         // label counter for swing labels
var aSwingsIndex = new Array(4); // tracks current swings indexes for last 4 swings
var aSwingsPrice = new Array(4); // tracks current swing prices for last 4 swings
var nNumLabelsG = null; // max number of swing labels
var bSwingLabelsG = null;  // controls swing labels display
var vSpace = null;      // spacer for Labels

function main(nNum, sWaveType, nRet, sHighSource, sLowSource, 
              nThickness, cColor1, cColor2, bSwingLabels, bRetLabel, nNumLabels) {
    var nState = getBarState();
    var nIndex = getCurrentBarIndex();
    var h = getValue(sHighSource);
    var l = getValue(sLowSource);
    var c = close();
    var i = 0;

    // record keeping
    if (nState == BARSTATE_NEWBAR) {
        if (cntr > 100) cntr = 0;
        if (x1a != null) x1a -= 1;
        if (x1b != null) x1b -= 1;
        if (x2a != null) x2a -= 1;
        if (x2b != null) x2b -= 1;
        i = 0;
        for (i = 0; i < 3; ++i) {
            if (aSwingsIndex[i] != null) aSwingsIndex[i] -= 1;
        }
    }

    //Initialization
    if (bEdit == true) {
        if (nNumBars == null) nNumBars = nNum;
        if (sWaveTypeG == null) sWaveTypeG = sWaveType;
        if (nRetpcnt == null) nRetpcnt = nRet/100;
        if (nThicknessG == null) nThicknessG = nThickness;
        if (cColorcon == null) cColorcon = cColor1;
        if (cColordev1 == null) cColordev1 = cColor2;
        if (sHSource == null) sHSource = sHighSource;
        if (sLSource == null) sLSource = sLowSource;
        if (x1a == null) x1a = 0;
        if (y1a == null) y1a = c;
        if (nNumLabelsG == null) nNumLabelsG = nNumLabels;
        if (bSwingLabelsG == null) bSwingLabelsG = bSwingLabels;
        nLcntr = nNumLabels;
        // Initialize vSpace
        var OM = (close() * 0.005); //offset multiplier
        var sInterval = getInterval();
        if (sInterval == "D") OM = OM*3;
        if (sInterval == "W") OM = OM*20;
        if (sInterval == "M") OM = OM*30;
        var TimeFrame = parseInt(sInterval);
        if (TimeFrame >= 1 && TimeFrame <= 5) {
            OM = OM*(TimeFrame/15);
        } else if (TimeFrame > 5 && TimeFrame <= 15) {
            OM = OM*(TimeFrame/10);
        }else if (TimeFrame > 15) {
            OM = OM*(TimeFrame/5);
        }
        if (!isNaN(TimeFrame)) OM = (OM/TimeFrame)*3;
        vSpace = OM;
        bEdit = false;
    }
    if (bInit == false) {
        bInit = Init(h,l,c);
    }

    // Swings
    if (nState == BARSTATE_NEWBAR) {
        nScntr += 1;
        // confirmed Swings
        if (nScntr > nNumBars) {
            confirmSwings();
            if (bInit == true) {
                doLine("dev1");
                doLine("dev2");
            }
        }
    }
    
    checkSwings(h, l);

    if (bInit == true) {
        doLine("dev1");
        doLine("dev2");
    }

    // % Retracement Label
    var nWaveRet = (Math.abs(y2a-y2b) / Math.abs(y1b-y1a))*100;
    if (x1b == x2b) nWaveRet = 0.0;
    if (bRetLabel == "True") {
        var sWaveRetText = " \%Retraced: " + nWaveRet.toFixed(2) + " ";
        drawTextRelative(2, y2b, sWaveRetText, cColordev1, null,
            Text.BOLD|Text.LEFT|Text.VCENTER|Text.FRAME, "Arial", 10, "Ret");
    }

    return;
}



/******  Functions *****/
/***********************/

function Init(h,l,c) {
    if (close(-(nNumBars*2)) == null) {
        return false;
    } else {
        // Find initial line.
        // The initial line will be the first high or low swing,
        // which has the greater difference of the swing point to
        // the close of the first bar.
        var Index = getCurrentBarIndex()
        var hIndex = Index;
        var lIndex = Index;
        var j = nNumBars*2;
        var aHigh = getValue(sHSource, 0, -j);
        var aLow = getValue(sLSource, 0, -j);
        var vHH = aHigh[0];
        var vLL = aLow[0];
        var tempIndex = Index;
        var i = 0;
        for (i = 0; i < j; ++i) {
            if (aHigh[i] > vHH) {
                vHH = aHigh[i];
                hIndex = tempIndex;
            }
            if (aLow[i] < vLL) {
                vLL = aLow[i];
                lIndex = tempIndex;
            }
            tempIndex -= 1;
        }

        if (vHH - y1a > y1a - vLL) {
            vLastSwing = "L";
            x1b = hIndex - Index;
            y1b = vHH;
            doLine("dev1");
            x2a = x1b;
            y2a = vHH;
            x2b = 0;
            y2b = c;
            doLine("dev2");
        } else {
            vLastSwing = "H";
            x1b = lIndex - Index;
            y1b = vLL;
            doLine("dev1");
            x2a = x1b;
            y2a = vLL;
            x2b = 0;
            y2b = c;
            doLine("dev2");
        }        
    }
    
    if (vLastSwing != null) {
        return true;
    } else {
        return false;
    }
}

function doLine(sType) {
    //confirmed
    if (sType == "con") {
        cntr += 1;
        drawLineRelative(x1a, y1a, x1b, y1b, PS_SOLID, 
            nThicknessG, cColorcon, sType+cntr);
        //Swing Labels
        if (bSwingLabelsG == "True") doSwingLabels(sType);
        x1a = x2a;
        y1a = y2a;
        x1b = x2b;
        y1b = y2b;
        x2a = x1b;
        y2a = y1b;
        aSwingsIndex.pop();
        aSwingsIndex.unshift(x1b);
        aSwingsPrice.pop();
        aSwingsPrice.unshift(y1b);
        if (vLastSwing == "H") y2b = getValue(sHSource);
        if (vLastSwing == "L") y2b = getValue(sLSource);
    }

    // dev1
    if (sType == "dev1") {
        drawLineRelative(x1a, y1a, x1b, y1b, PS_SOLID, 
            nThicknessG, cColordev1, sType);
        aSwingsIndex[0] = x1b;
        aSwingsPrice[0] = y1b;
        //Swing Labels
        if (bSwingLabelsG == "True") doSwingLabels(sType);
    }
    
    // dev2    
    if (sType == "dev2") {
        if (x2a != 0 && x2a != x2b) {
            if ( (vLastSwing == "H" && sHSource == "Close") || (vLastSwing == "L" && sLSource == "Close") ) {
                x2b = 0;
                y2b = close();
            }
            drawLineRelative(x2a, y2a, x2b, y2b, PS_SOLID, 
                nThicknessG, cColordev1, sType);
        } else {
            removeLine(sType);
        }
    }
    
    return;
}

function doSwingLabels(sType) {
    var sTagNamePts = "SwingPtsDev";
    var sTagNameRet = "SwingRetDev";
    var sTagNamePr = "SwingPrDev";
    var sTagNameBars = "SwingBarsDev";
    var nWaveRet = ((Math.abs(aSwingsPrice[1]-aSwingsPrice[0]) / Math.abs(aSwingsPrice[1]-aSwingsPrice[2])) * 100);
    var nBars = (aSwingsIndex[0] - aSwingsIndex[1]);
    
    if (sType == "con") {
        //nWaveRet = (Math.abs(y2a-y2b) / Math.abs(y1b-y1a));
        nLcntr += 1;
        if (nLcntr > nNumLabelsG) nLcntr = 1;
        sTagNamePts = "SwingPts"+sType+nLcntr;
        sTagNameRet = "SwingRet"+sType+nLcntr;
        sTagNamePr = "SwingPr"+sType+nLcntr;
        sTagNameBars = "SwingBars"+sType+nLcntr;
    }
    
    var pts = (y1b-y1a).toFixed(2);
    if (y1a < y1b) { // swing high
        drawTextRelative(x1b, y1b+vSpace, pts + " ", eval("cColor"+sType), null, 
            Text.BOTTOM|Text.RIGHT, "Arial", 10, sTagNamePts); // Points
        if (!isNaN(nWaveRet)) {
            drawTextRelative(x1b, y1b+vSpace, "| ("+nWaveRet.toFixed(2)+"\%)", eval("cColor"+sType), null, 
                Text.BOTTOM|Text.LEFT, "Arial", 10, sTagNameRet); // % Retracement
        }
        drawTextRelative(x1b, y1b+vSpace, y1b.toFixed(2) + " ", eval("cColor"+sType), null,
            Text.TOP|Text.RIGHT, "Arial", 10, sTagNamePr); // Price
        if (!isNaN(nBars)) {
            drawTextRelative(x1b, y1b+vSpace, "| ("+nBars+" Bars)", eval("cColor"+sType), null,
                Text.TOP|Text.LEFT, "Arial", 10, sTagNameBars); // Number of Bars
        }
    } else { // swing low
        drawTextRelative(x1b, y1b-vSpace, pts + " ", eval("cColor"+sType), null, 
            Text.TOP|Text.RIGHT, "Arial", 10, sTagNamePts); // Points
        if (!isNaN(nWaveRet)) {
            drawTextRelative(x1b, y1b-vSpace, "| ("+nWaveRet.toFixed(2)+"\%)", eval("cColor"+sType), null, 
                Text.TOP|Text.LEFT, "Arial", 10, sTagNameRet); // % Retracement
        }
        drawTextRelative(x1b, y1b-vSpace, y1b.toFixed(2) + " ", eval("cColor"+sType), null,
            Text.BOTTOM|Text.RIGHT, "Arial", 10, sTagNamePr); // Price
        if (!isNaN(nBars)) {
            drawTextRelative(x1b, y1b-vSpace, "| ("+nBars+" Bars)", eval("cColor"+sType), null,
                Text.BOTTOM|Text.LEFT, "Arial", 10, sTagNameBars); // Number of Bars
        }
    }
    return;
}

function confirmSwings() {
    if (x1b != x2b) {   // underdeveloped dev1 line
        if (sWaveTypeG == "% Retracement") {
            var nWave = (Math.abs(y2a-y2b) / Math.abs(y1b-y1a));
        } else {
            var nWave = (Math.abs(y2a-y2b) / y1b);
        }
        if (vLastSwing == "L" && nWave >= nRetpcnt ) {
            // Swing High
            nScntr = 0;
            vLastSwing = "H";
            doLine("con");
        } else if (vLastSwing == "H" && nWave >= nRetpcnt ) {
            // Swing Low
            nScntr = 0;
            vLastSwing = "L";
            doLine("con");
        }
    }
    
    return;
}

function checkSwings(h, l) {
    // dev1
    if (vLastSwing == "L") {         // find Swing High
        if (h >= y1b) {  // higher high, no swing
            nScntr = 0;
            x1b = 0;
            y1b = h;
            doLine("dev1");
            x2a = 0;
            y2a = h;
        }
    } else if (vLastSwing == "H") {  // find Swing Low
        if (l <= y1b) {  // Lower low, no swing
            nScntr = 0;
            x1b = 0;
            y1b = l;
            doLine("dev1");
            x2a = 0;
            y2a = l;
        }
    }
    // dev2
    if (nScntr == 0) {
        x2b = 0;
        if (vLastSwing == "H") y2b = h;
        if (vLastSwing == "L") y2b = l;
    } else {
        if (vLastSwing == "H" && h >= y2b) {
            y2b = h; x2b = 0;
        } else if (vLastSwing == "L" && l <= y2b) {
            y2b = l; x2b = 0;
        }
    }
    return;
}