2007 Apr: Closing-price Divergences

ICE Data Services -

Price_Close_LD.efs  

EFSLibrary - Discussion Board  

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