2004 Mar: TriPatternRank.efs

ICE Data Services -


TriPatternRank.efs 
  

File Name: TriPatternRank.efs


Description:
Based on Mechanically Recognizing Triangular Formations by Giorgos Siligardos, Ph.D. This article appeared in the March 2004 issue of Stock & Commodities.


Formula Parameters:
Swing: # of Bars - 1
Swing: Wave Type - %Change in Price [%Change in Price, %Retracement]
Swing: Wave Percentage - 20%
Swing High Price Source - Close [Open, High, Low, Close]
Swing Low Price Source - Close [Open, High, Low, Close]
Line Thickness - 2
Confirmed Swing Line Color - Blue
Developing Swing Line Color - Yellow

Notes:
The related article is copyrighted material. If you are not a subscriber of Stocks & Commodities, please visit www.traders.com.

This formula has a minor modification made to it since the publication of the article. The logic for current developing leg of the zig zag has been modified to draw B-r line from point B to current bar close (r).

Download File:
TriPatternRank.efs




EFS Code:






/*****************************************************************Provided By : eSignal. (c) Copyright 2004Study:        Triangular Pattern RankVersion:      1.11/21/2004Formula Parameters:                 Default:    * Swing: # of Bars              1        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              % Change in Price        (% Retracement, % Change in Price)    * Swing: Wave Percentage        20        The number 3 represents 3.0%.  The number 0.03         represents 0.0003%.    * Swing High Price Source       Close    * Swing Low Price Source        Close    * Line Thickness                2    * Confirmed Swing Line Color    Blue    * Developing Swing Line Color   YellowNotes:1.1 *Modified logic for current developing leg of the zig zag     to draw B-r line from B to current bar close (r).*****************************************************************/function preMain() {    setPriceStudy(true);    setStudyTitle("Triangular Pattern Rank ");    setShowCursorLabel(false);    setShowTitleParameters(false);    setDefaultBarFgColor(Color.cyan);    //setComputeOnClose();        var fp1 = new FunctionParameter("nNum", FunctionParameter.NUMBER);    fp1.setName("Swing: # of Bars");    fp1.setLowerLimit(1);    fp1.setDefault(1);        var fp2a = new FunctionParameter("sWaveType", FunctionParameter.STRING);    fp2a.setName("Swing: Wave Type");    fp2a.addOption("% Retracement");    fp2a.addOption("% Change in Price");    fp2a.setDefault("% Change in Price");        var fp2 = new FunctionParameter("nRet", FunctionParameter.NUMBER);    fp2.setName("Swing: Wave Percentage");    fp2.setLowerLimit(0);    fp2.setDefault(20);    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("Close");    var fp4 = new FunctionParameter("sLowSource", FunctionParameter.STRING);    fp4.setName("Swing Low Price Source");    fp4.addOption("High");    fp4.addOption("Low");    fp4.addOption("Close");    fp4.setDefault("Close");    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.yellow);}var cntr = 0;           // image counter for swing linesvar bInit = false;      // initialization routine completionvar nNumBars = null;    // number of bars for defining swingsvar sWaveTypeG = null;  // wave type for confirming swingsvar nRetpcnt = null;    // percent retracement for defining swingsvar nThicknessG = null; // line thicknessvar cColorCon = null;   // confirmed swing colorvar cColorDev = null;   // developing swing colorvar sHSource = null;    // price source for high swingsvar sLSource = null;    // price source for low swingsvar x1a = null;         // x-coordinate for point a of developing line 1var x1b = null;         // x-coordinate for point b of developing line 1var x2a = null;         // x-coordinate for point a of developing line 2var x2b = null;         // x-coordinate for point b of developing line 2var y1a = null;         // y-coordinate for point a of developing line 1var y1b = null;         // y-coordinate for point b of developing line 1var y2a = null;         // y-coordinate for point a of developing line 2var y2b = null;         // y-coordinate for point b of developing line 2var vLastSwing = null;  // tracking swing type of last confirmed swingvar nScntr = 0;         // bar counter for swing confirmationvar nSpace = null;      // space between labels and barsvar A = null;           // Linear Regression y = Ax + Bvar B = null;           // Linear Regression y = Ax + Bvar r2 = 0;             // Linear Regression r-squaredvar MA5 = null;         // 5 period MA Studyvar SS = 0;             // Small Swings countervar nTPR = 0;           // Triangular Pattern Rankfunction main(nNum, sWaveType, nRet, sHighSource, sLowSource, nThickness, cColor1, cColor2) {    var nState = getBarState();    var nIndex = getCurrentBarIndex();    var h = getValue(sHighSource);    var l = getValue(sLowSource);    var c = close();    // 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;    }    //Initialization    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 (cColorDev == null) cColorDev = cColor2;    if (sHSource == null) sHSource = sHighSource;    if (sLSource == null) sLSource = sLowSource;    if (x1a == null) x1a = 0;    if (y1a == null) y1a = c;    if (nSpace == null) {        nSpace = ((high() - low())*.2);        TFlabels(false, "NA");    }    if (MA5 == null) MA5 = new MAStudy(5, 0, "Close", MAStudy.SIMPLE);    if (bInit == false) {        bInit = Init(h,l,c);    }    // Swings    if (nState == BARSTATE_NEWBAR) {        nScntr += 1;        // confirm Swings        if (nScntr > nNumBars) {            confirmSwings();            if (bInit == true) {                doLine("dev1");                doLine("dev2");            }        }    }    checkSwings(h, l);    if (bInit == true) doLine("dev2");        //Linear Regression    RegTriangle();    return MA5.getValue(MAStudy.MA);}/***********************//******  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);        x1a = x2a;        y1a = y2a;        x1b = x2b;        y1b = y2b;        x2a = x1b;        y2a = 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, cColorDev, sType);    }        // dev2    if (sType == "dev2") {        if (x2a != 0 && x2a != x2b) {            drawLineRelative(x2a, y2a, 0, close(), PS_SOLID,                 nThicknessG, cColorDev, sType);        } else {            removeLine(sType);        }    }        return;}function TFlabels(bTF, nSS) {    drawTextAbsolute(2, 100, "TF = "+bTF, Color.maroon, null,         Text.BOLD|Text.ONTOP|Text.LEFT|Text.BOTTOM|Text.RELATIVETOBOTTOM,        null, 14, "TF");    var nR = (Math.abs(y2a-y2b) / Math.abs(y1b-y1a));    if (nR > 0) {        nR = (100*nR).toFixed(2) + "%";    } else {        nR = "NA";    }    drawTextAbsolute(2, 80, "TPR = "+nTPR, Color.maroon, null,         Text.BOLD|Text.ONTOP|Text.LEFT|Text.BOTTOM|Text.RELATIVETOBOTTOM,        null, 14, "TPR");    drawTextAbsolute(2, 40, "%Ret = "+nR, Color.maroon, null,         Text.BOLD|Text.ONTOP|Text.LEFT|Text.BOTTOM|Text.RELATIVETOBOTTOM,        null, 14, "Ret");    drawTextAbsolute(2, 20, "SS = "+nSS, Color.maroon, null,         Text.BOLD|Text.ONTOP|Text.LEFT|Text.BOTTOM|Text.RELATIVETOBOTTOM,        null, 14, "SS");    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;}function RegTriangle() {    var nState = getBarState();    var nIndex = getCurrentBarIndex();    var i = 0;        // y = Ax + B;    // A = SUM( (x-xAVG)*(y-yAVG) ) / SUM( (x-xAVG)^2 )    // B = yAVG - (A*xAVG)    // Slope = -1 * A        if (nScntr < 10 || nScntr > 60) {        //removeLine("reg");        removeLine("Up");        removeLine("Dn");        nTPR = 0;        TFlabels(false, 0);    } else {        var aReg = close(0, -nScntr);        var vClose = aReg[0];        if (aReg[nScntr-1] != null) {            LinReg(aReg, aReg.length, true);            // Reg            //drawLineRelative(0, B, -(nScntr-1), (A*(nScntr-1)) + B, PS_SOLID, 1, Color.blue, "reg");            //Up and Down indicators            var aUp = new Array(nScntr);            var aDn = new Array(nScntr);            var RegValue = B;   // Reg indicator values            SS = 0; // Small Swings            i = 0;            for (i = 0; i < nScntr; ++i) {                if (aReg[i] > RegValue) {                    aUp[i] = aReg[i];                }                if (aReg[i] < RegValue) {                    aDn[i] = aReg[i];                }                if (i < nScntr-1) {                    var vMA0 = MA5.getValue(MAStudy.MA, -i);                    var vMA1 = MA5.getValue(MAStudy.MA, (-i-1));                    if (vMA0 > RegValue && vMA1 <= RegValue + A) SS += 1;                    if (vMA0 < RegValue && vMA1 >= RegValue + A) SS += 1;                }                RegValue += A;            }            i = 0;            var j = 0;            for (i = 0; i < nScntr; ++i) {                if (aUp[i] == null) {                    j = 0;                    for (j = i+1; j < nScntr; ++j) {                        if (aUp[j] != null) {                            aUp[i] = aUp[j];                            j = nScntr;                        }                    }                }                if (aDn[i] == null) {                    j = 0;                    for (j = i+1; j < nScntr; ++j) {                        if (aDn[j] != null) {                            aDn[i] = aDn[j];                            j = nScntr;                        }                    }                }            }            LinReg(aUp, aUp.length, false);            var UpSlope = -A;            drawLineRelative(0, B, -(nScntr-1), (A*(nScntr-1)) + B, PS_SOLID, 2, Color.red, "Up");            LinReg(aDn, aDn.length, false);            var DnSlope = -A;            drawLineRelative(0, B, -(nScntr-1), (A*(nScntr-1)) + B, PS_SOLID, 2, Color.red, "Dn");        }        /*** Triangular Formation (TF) ***/        var bTF = true;        var pcntRetracement = (Math.abs(y2a-y2b) / Math.abs(y1b-y1a));        if (SS < 3) bTF = false;        if (UpSlope >= 0 || DnSlope <= 0) bTF = false;        if (pcntRetracement > 0.50) bTF = false;        if (bTF == false) nTPR = 0;                /*** Triangular Pattern Rank (TPR) ***/        if (bTF == true) {            nTPR = 1;            //rule 1            if (nScntr >= 15 && nScntr <= 30) nTPR += 2;            if (nScntr > 30 && nScntr <= 55) nTPR += 1;            //rule 2            if (r2 <= 0.2) nTPR += 2;            if (r2 > 0.2 && r2 <= 0.5) nTPR += 1;            //rule 3            if (pcntRetracement <= 0.20) nTPR += 4;            if (pcntRetracement > 0.20 && pcntRetracement <= 0.38) nTPR += 3;            //rule 4            var aVol = volume(0, -nScntr);            LinReg(aVol, aVol.length, false);            if (-A < 0) nTPR += 4;        }        TFlabels(bTF, SS);    }        return;}function LinReg(vArray, nLength, bR2) {    var Len = nLength;    var xSum = 0;    var ySum = 0;    var i = 0;    for (i = 0; i < nLength; ++i) {        if (vArray[i] == null) Len -= 1;    }    for (i = 0; i < Len; ++i) {        xSum += i;        ySum += vArray[i];    }    var xAvg = xSum/Len;    var yAvg = ySum/Len;    var aSum1 = 0;    var aSum2 = 0;    var aSum3 = 0;    i = 0;    for (i = 0; i < Len; ++i) {        aSum1 += (i-xAvg) * (vArray[i]-yAvg);         aSum2 += (i-xAvg)*(i-xAvg);        aSum3 += (vArray[i]-yAvg)*(vArray[i]-yAvg);    }        A = (aSum1 / aSum2);    B = yAvg - (A*xAvg);        // r-squared    if (bR2 == true) r2 = (aSum1*aSum1) / (aSum2*aSum3);        return;}