/***************************************Provided By : eSignal (Copyright ) eSignal), a division of Interactive Data Corporation. 2007. All rights reserved. This sample eSignal Formula Script (EFS) is for educational purposes only and may be modified and saved under a new file name. eSignal is not responsible for the functionality once modified. eSignal reserves the right to modify and overwrite this EFS file with each new release. Description: Trading Trendline Breaks, Part 2 by Sylvain VervoortVersion 1.0 7/9/2007Notes:* Study is a modified version of eSignal's RealTimeSwings.efs, which incorporates Vervoort's strategy signals based on ZigZag indicator.* Study provides historical analysis only, see author's notes in the article.* Description of Swing Labels: At Swing Highs - Points (% Retracement) Price (Number of Bars) At Swing Lows - Price (Number of Bars) Points (% Retracement)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 False * Display % Retracement Label False * Number of Historical Labels 100*****************************************************************/function preMain() { setPriceStudy(true); setStudyTitle("Trend Line Breaks "); //setShowCursorLabel(false); setShowTitleParameters(false); //TASC mod setCursorLabelName("PD", 0); setCursorLabelName("PU", 1); setDefaultBarFgColor(Color.red, 0); //PD setDefaultBarFgColor(Color.green, 1); //PU setDefaultBarThickness(2, 0); setDefaultBarThickness(2, 1); setPlotType(PLOTTYPE_FLATLINES, 0); setPlotType(PLOTTYPE_FLATLINES, 1); 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("% Change in Price"); var fp2 = new FunctionParameter("nRet", FunctionParameter.NUMBER); fp2.setName("Swing: Wave Percentage"); fp2.setLowerLimit(0); fp2.setDefault(7); 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("Open"); 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.red); var fp8 = new FunctionParameter("bSwingLabels", FunctionParameter.STRING); fp8.setName("Display Swing Labels"); fp8.addOption("True"); fp8.addOption("False"); fp8.setDefault("False"); var fp9 = new FunctionParameter("bRetLabel", FunctionParameter.STRING); fp9.setName("Display \% Retracement Label"); fp9.addOption("True"); fp9.addOption("False"); fp9.setDefault("False"); 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 inputsvar 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 cColordev1 = 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 swing (H or L)var nScntr = 0; // bar counter for swing confirmationvar nLcntr = 0; // label counter for swing labelsvar aSwingsIndex = new Array(4); // tracks current swings indexes for last 4 swingsvar aSwingsPrice = new Array(4); // tracks current swing prices for last 4 swingsvar nNumLabelsG = null; // max number of swing labelsvar bSwingLabelsG = null; // controls swing labels displayvar vSpace = null; // spacer for Labels//TASC modvar bBT = true; // back test flagvar vPosition = 0; // 0=flat, 1=long, -1=shortvar nPD = null;var nPU = null;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; //TASC mod setDefaultBarThickness(nThickness, 0); setDefaultBarThickness(nThickness, 1); 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"); } //TASC mod - back testing conditions if (nIndex == 0) bBT = false; if (nState == BARSTATE_NEWBAR) { if (vPosition != 1 && nPU != null && close(-1) >= nPU && vLastSwing == "L") { // long signal if (bBT == true) Strategy.doLong("long", Strategy.MARKET, Strategy.THISBAR); vPosition = 1; drawShape(Shape.UPARROW, BelowBar1, Color.green); drawText("Long", BelowBar2, Color.green, Text.FRAME|Text.BOLD, rawtime(0)); } else if (vPosition != -1 && nPD != null && close(-1) <= nPD && vLastSwing == "H") { // short signal if (bBT == true) Strategy.doShort("short", Strategy.MARKET, Strategy.THISBAR); vPosition = -1; drawShape(Shape.DOWNARROW, AboveBar1, Color.red); drawText("Short", AboveBar2, Color.red, Text.FRAME|Text.BOLD, rawtime(0)); } } return new Array(nPD, nPU);}/****** 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); //TASC mod if (aSwingsPrice[0] != null && vLastSwing != null) { if (vLastSwing == "H") { nPD = aSwingsPrice[1] - (aSwingsPrice[1]*0.05); } else if (vLastSwing == "L") { nPU = aSwingsPrice[1] + (aSwingsPrice[1]*0.05); } } } // 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;} |