Price_Close_LD.efs
File Name: Price_Close_LD.efs
Description:
This study is based on the April 2007 article, Closing-price Divergences, by Clive Corcoran.
Formula Parameters:
- Starting Equity: 100000
- Position Size (%of Equity): 2
Notes:
The study is intended for use with equities on a daily chart interval and requires eSignal version 8.0 or later. This system is enabled for Back Testing only, not real time analysis. The starting Equity amount entered for the study will also need to be entered into the Strategy Analyzer settings. The related article is copyrighted material. If you are not a subscriber of Active Trader Magazine, please visit www.activetradermag.com.
Download File:
Price_Close_LD.efs
EFS Code:
/*************************************** Provided By : eSignal (c) Copyright 2007 Description: Closing-Price Divergences by Clive Corcoran Version 1.0 1/18/2007 Notes: * March 2007 Issue of Active Trader Magazine * Study requires version 8.0 or later. * This study is designed for back testing, not real time analysis. * This study is intended for Equities only. * The Starting Equity amount entered for the study will also need to be entered into the Strategy Analyzer settings. Formula Parameters: Default: Starting Equity 100000 Position Size (%of Equity) 2 *************************************************/ function preMain() { setPriceStudy(true); setStudyTitle("Price-Close Location Divergence"); setCursorLabelName("65th Percentile", 0); setCursorLabelName("35th Percentile", 1); setCursorLabelName("Closing Bias", 2); setCursorLabelName("Close Stop 3%", 3); setCursorLabelName("IntraBar Stop 5%", 4); setCursorLabelName("Target1 5%", 5); setCursorLabelName("Target2 7%", 6); setCursorLabelName("long count", 7); setCursorLabelName("short count", 8); setDefaultBarFgColor(Color.blue, 0); setDefaultBarFgColor(Color.blue, 1); setDefaultBarFgColor(Color.magenta, 2); setDefaultBarFgColor(Color.red, 3); setDefaultBarFgColor(Color.red, 4); setDefaultBarFgColor(Color.green, 5); setDefaultBarFgColor(Color.green, 6); //setDefaultBarThickness(2, 3); setPlotType(PLOTTYPE_FLATLINES, 3); setPlotType(PLOTTYPE_FLATLINES, 4); setPlotType(PLOTTYPE_FLATLINES, 5); setPlotType(PLOTTYPE_FLATLINES, 6); setDefaultFont("Arial", 12, null, Text.BOLD|Text.FRAME|Text.CENTER); var fp1 = new FunctionParameter("Equity", FunctionParameter.NUMBER); fp1.setName("Starting Equity"); fp1.setLowerLimit(1); fp1.setDefault(100000); var fp2 = new FunctionParameter("PosSize", FunctionParameter.NUMBER); fp2.setName("Position Size (%of Equity)"); fp2.setLowerLimit(0.1); fp2.setDefault(2); } // Global Variables var xRankC = null; var xBiasC = null; var aLongCount = new Array(21); var aShortCount = new Array(21); for (var i = 0; i < 21; i++) { aLongCount[i] = 0; aShortCount[i] = 0; } var nEquity = null; // Starting Equity var nPS = null; // Position size as % of Equity var vPosition = 0; // 0=flat, 1=long, -1=short var nEntryPrice = null; var nStop1 = null; var nStop2 = null; var nTarget1 = null; var nTarget2 = null; var bTargetBreach = false; var nLotSize = null; var nLongCount = 0; var nShortCount = 0; var nLongCount_1 = 0; var nShortCount_1 = 0; var bInit = false; // initialization flag var bBT = true; function main(Equity, PosSize) { var nState = getBarState(); if (getCurrentBarIndex() >= -1) bBT = false; // disable back testing functions if (getCurrentBarIndex() == 0) return; if(bInit == false) { nEquity = Equity; nPS = PosSize; xRankC = efsInternal("calcPercentiles"); xBiasC = efsInternal("calcBias"); bInit = true; // Prevents this code block from executing again. } //if (getCurrentBarCount() < 21) return; // Retrieve previous bar's values of Donchian Series for back testing conditions. //var n = x.getValue(-1); var x35th = getSeries(xRankC, 0); var x65th = getSeries(xRankC, 1); var nBias = xBiasC.getValue(0); var nBias_1 = xBiasC.getValue(-1); var n35th_1 = x35th.getValue(-1); var n65th_1 = x65th.getValue(-1); var bLong = false; var bShort = false; var bExitTrade = false; var nExitPrice = null; // Validate the study variables to ensure they contain valid data. if(n35th_1 == null || n65th_1 == null || nBias_1 == null) { return; // Exit the formula if variables contain invalid data. } // Record keeping if (nState == BARSTATE_NEWBAR) { nLongCount_1 = nLongCount; nShortCount_1 = nShortCount; aLongCount.pop(); aLongCount.unshift(0); aShortCount.pop(); aShortCount.unshift(0); // Long count if (close(-1) <= n35th_1 && nBias_1 > 0.10) { aLongCount[0] = 1; } // Short count if (close(-1) >= n65th_1 && nBias_1 < -0.10) { aShortCount[0] = 1; } nLongCount = 0; nShortCount = 0; for (var i = 0; i < 21; i++) { nLongCount += aLongCount[i]; nShortCount += aShortCount[i]; if (i < 5) { if (aLongCount[i] == 1) bLong = true; if (aShortCount[i] == 1) bShort = true; } } if (vPosition == 0) { nStop1 = null; nStop2 = null; nTarget1 = null; nTarget2 = null; bTargetBreach = false; } } // Back Testing logic if (getCurrentBarCount() > 21) { // study primed, begin evaluation if (nState == BARSTATE_NEWBAR) { // Exit Strategy if (vPosition != 0) { // Long Exit if (vPosition == 1) { if (bTargetBreach == false && high(0) > nTarget1) { // Profit Target1 bTargetBreach = true; bExitTrade = true; nExitPrice = Math.max(open(0), nTarget1); drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.green, null, rawtime(0)); drawText("1", AboveBar2, Color.green, null, rawtime(0)); if (bBT == true) { nEquity += (nExitPrice-nEntryPrice)*Math.round(nLotSize*.65); Strategy.doSell("Target 1", Strategy.LIMIT, Strategy.THISBAR, Math.round(nLotSize*.65), nExitPrice); } } else if (bTargetBreach == true && high(0) > nTarget2) { // Profit Target2 vPosition = 0; bExitTrade = true; nExitPrice = Math.max(open(0), nTarget2); drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.green, null, rawtime(0)); drawText("2", AboveBar2, Color.green, null, rawtime(0)); if (bBT == true) { nEquity += (nExitPrice-nEntryPrice)*Strategy.getPositionSize(); Strategy.doSell("Target 2", Strategy.LIMIT, Strategy.THISBAR, Strategy.getPositionSize(), nExitPrice); } } } if (vPosition == 1 && bExitTrade == false) { // protective stops if (close(-1) <= nStop1) { vPosition = 0; bExitTrade = true; nExitPrice = open(0); drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.red, null, rawtime(0)); drawText("1", BelowBar2, Color.red, null, rawtime(0)); if (bBT == true) { nEquity += (nExitPrice-nEntryPrice)*Strategy.getPositionSize(); Strategy.doSell("Close Stop", Strategy.STOP, Strategy.THISBAR, Strategy.getPositionSize(), nExitPrice); } } else if (low(0) <= nStop2) { vPosition = 0; bExitTrade = true; nExitPrice = Math.min(open(0), nStop2); drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.red, null, rawtime(0)); drawText("2", BelowBar2, Color.red, null, rawtime(0)); if (bBT == true) { nEquity += (nExitPrice-nEntryPrice)*Strategy.getPositionSize(); Strategy.doSell("IntraBar Stop", Strategy.STOP, Strategy.THISBAR, Strategy.getPositionSize(), nExitPrice); } } } // Short Exit if (vPosition == -1) { if (bTargetBreach == false && low(0) < nTarget1) { // Profit Target1 bTargetBreach = true; bExitTrade = true; nExitPrice = Math.min(open(0), nTarget1); drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.green, null, rawtime(0)); drawText("1", BelowBar2, Color.green, null, rawtime(0)); if (bBT == true) { nEquity += (nEntryPrice-nExitPrice)*Math.round(nLotSize*.65); Strategy.doCover("Target 1", Strategy.LIMIT, Strategy.THISBAR, Math.round(nLotSize*.65), nExitPrice); } } else if (bTargetBreach == true && low(0) < nTarget2) { // Profit Target2 vPosition = 0; bExitTrade = true; nExitPrice = Math.min(open(0), nTarget2); drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.green, null, rawtime(0)); drawText("2", BelowBar2, Color.green, null, rawtime(0)); if (bBT == true) { nEquity += (nEntryPrice-nExitPrice)*Math.abs(Strategy.getPositionSize()); Strategy.doCover("Target 2", Strategy.LIMIT, Strategy.THISBAR, Math.abs(Strategy.getPositionSize()), nExitPrice); } } } if (vPosition == -1 && bExitTrade == false) { // protective stops if (close(-1) >= nStop1) { vPosition = 0; bExitTrade = true; nExitPrice = open(0); drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.red, null, rawtime(0)); drawText("1", AboveBar2, Color.red, null, rawtime(0)); if (bBT == true) { nEquity += (nEntryPrice-nExitPrice)*Math.abs(Strategy.getPositionSize()); Strategy.doCover("Close Stop", Strategy.STOP, Strategy.THISBAR, Math.abs(Strategy.getPositionSize()), nExitPrice); } } else if (high(0) >= nStop2) { vPosition = 0; bExitTrade = true; nExitPrice = Math.max(open(0), nStop2); drawShapeRelative(0, nExitPrice, Shape.DIAMOND, null, Color.red, null, rawtime(0)); drawText("2", AboveBar2, Color.red, null, rawtime(0)); if (bBT == true) { nEquity += (nEntryPrice-nExitPrice)*Math.abs(Strategy.getPositionSize()); Strategy.doCover("IntraBar Stop", Strategy.STOP, Strategy.THISBAR, Math.abs(Strategy.getPositionSize()), nExitPrice); } } } } // Entry Strategy if (vPosition == 0 && bExitTrade == false) { // Long Signal //if (bLong == true && aLongCount[0] > aLongCount[1]) { if (bLong == true && nLongCount == 5 && nLongCount_1 == 4) { vPosition = 1; drawShape(Shape.UPARROW, BelowBar1, Color.green, rawtime(0)); if (bBT == true) { nLotSize = getLotSize(open(0)); Strategy.doLong("Long Trigger", Strategy.MARKET, Strategy.THISBAR, nLotSize); } nEntryPrice = open(0); nStop1 = nEntryPrice - (0.03*nEntryPrice); nStop2 = nEntryPrice - (0.05*nEntryPrice); nTarget1 = nEntryPrice + (0.05*nEntryPrice); nTarget2 = nEntryPrice + (0.07*nEntryPrice); } // Short Signal //if (vPosition == 0 && bShort == true && aShortCount[0] > aShortCount[1]) { if (vPosition == 0 && bShort == true && nShortCount == 5 && nShortCount_1 == 4) { vPosition = -1; drawShape(Shape.DOWNARROW, AboveBar1, Color.red, rawtime(0)); if (bBT == true) { nLotSize = getLotSize(open(0)); Strategy.doShort("Short Trigger", Strategy.MARKET, Strategy.THISBAR, nLotSize); } nEntryPrice = open(0); nStop1 = nEntryPrice + (0.03*nEntryPrice); nStop2 = nEntryPrice + (0.05*nEntryPrice); nTarget1 = nEntryPrice - (0.05*nEntryPrice); nTarget2 = nEntryPrice - (0.07*nEntryPrice); } } } } return new Array(x65th, x35th, nBias.toFixed(2), nStop1, nStop2, nTarget1, nTarget2, nLongCount+"", nShortCount+""); } var aClose = new Array(21); function calcPercentiles() { var nState = getBarState(); var n35 = null; var n65 = null; var aSort = new Array(21); if (nState == BARSTATE_NEWBAR) { aClose.pop(); aClose.unshift(close(0)); } aClose[0] = close(0); if (aClose[20] == null) return; for (var i = 0; i < 21; i++) { aSort[i] = aClose[i]; } aSort.sort(compareNumbers); n35 = aSort[7]; n65 = aSort[13]; return new Array(n35, n65); } function compareNumbers(a, b) { return a - b; } function calcBias() { var c_0 = close(0); var c_1 = close(-1); var nATR = atr(1, 0); if (close(-1) == null || nATR == null) return; return (c_0 - c_1) / nATR; } function getLotSize(Price) { return ((nPS/100) * nEquity) / Price; }