2014 Dec: Detecting Flags in Intraday Charts by Markos Katsanos

ICE Data Services -

IntradayFlagStrategy.efs  

EFSLibrary - Discussion Board  

File Name: IntradayFlagStrategy.efs

Description:
Detecting Flags in Intraday Charts by Markos Katsanos

Formula Parameters:

IntradayFlagStrategy.efs

  • Max Flag Duration: 15
  • Max ATR in lowest point in flag: 2.5
  • Max Pole Duration: 23
  • Bars for Uptrend leading to flag: 70
  • Min ATR Height of the pole: 5.5
  • Min distance between flags: 50
  • Min volatility change: 5
  • Profit Target constant (K): 1.2
  • Time exit bars: 100
  • ATRLL: 3
  • BSEMIN: 5
  • ATRTRAIL: 3
  • TRAILBARS: 5
  • BSEINACT: 70
  • ATRINACT: 4
  • Enter Position Color: Color.lime
  • Exit Position Color: Color.red

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

Download File:
IntradayFlagStrategy.efs

IntradayFlagStrategy.efs

EFS Code:
IntradayFlagStrategy.efs

/*********************************
Provided By:  
    Interactive Data Corporation (Copyright В© 2014) 
    All rights reserved. This sample eSignal Formula Script (EFS)
    is for educational purposes only. Interactive Data Corporation
    reserves the right to modify and overwrite this EFS file with 
    each new release. 

Description:        
    Detecting Flags In Intraday Charts by Markos Katsanos

Version:            1.00  10/07/2014

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

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

var fpArray = new Array(); 

function preMain(){

    setStudyTitle("IntradayFlagStrategy");
    setPriceStudy(true);
     
    var x = 0;

    fpArray[x] = new FunctionParameter("fpMaxFlDur", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("Max Flag Duration");
        setDefault(15);
    };

    fpArray[x] = new FunctionParameter("fpFlagMin", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("Max ATR in lowest point in flag");
        setDefault(2.5);
    };

    fpArray[x] = new FunctionParameter("fpPX", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("Max Pole Duration");
        setDefault(23);
    };

    fpArray[x] = new FunctionParameter("fpUptBars", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("Bars for Uptrend leading to flag");
        setDefault(70);
    };

    fpArray[x] = new FunctionParameter("fpPoleMin", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("Min ATR Height of the pole");
        setDefault(5.5);
    };

    fpArray[x] = new FunctionParameter("fpDistBFlags", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("Min distance between flags");
        setDefault(50);
    };

    fpArray[x] = new FunctionParameter("fpATRMin", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("Min volatility change");
        setDefault(5);
    };

    fpArray[x] = new FunctionParameter("fpK", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("Profit Target constant (K)");
        setDefault(1.2);
    };

    fpArray[x] = new FunctionParameter("fpTimeExit", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("Time exit bars");
        setDefault(100);
    };

    fpArray[x] = new FunctionParameter("fpCap1", FunctionParameter.STRING);
    with(fpArray[x++]){

        setName("Stop loss below flag parameters:");
    };

    fpArray[x] = new FunctionParameter("fpATRLL", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("    ATRLL");
        setDefault(3);
    };

    fpArray[x] = new FunctionParameter("fpBSEMIN", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("    BSEMIN");
        setDefault(5);
    };

    fpArray[x] = new FunctionParameter("fpCap2", FunctionParameter.STRING);
    with(fpArray[x++]){

        setName("Trailing stop parameters:");
    };

    fpArray[x] = new FunctionParameter("fpATRTRAIL", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("   ATRTRAIL");
        setDefault(3);
    };

    fpArray[x] = new FunctionParameter("fpTRAILBARS", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("    TRAILBARS");
        setDefault(5);
    };

    fpArray[x] = new FunctionParameter("fpCap3", FunctionParameter.STRING);
    with(fpArray[x++]){

        setName("Inactivity exit parameter:");
    };

    fpArray[x] = new FunctionParameter("fpBSEINACT", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("    BSEINACT");
        setDefault(70);
    };

    fpArray[x] = new FunctionParameter("fpATRINACT", FunctionParameter.NUMBER);
    with(fpArray[x++]){

        setName("    ATRINACT");
        setDefault(4);
    };

    fpArray[x] = new FunctionParameter("fpLongColor", FunctionParameter.COLOR);
    with(fpArray[x++]){

        setName("Enter Position Color");    
        setDefault(Color.lime);
    };
    
    fpArray[x] = new FunctionParameter("fpShortColor", FunctionParameter.COLOR);
    with(fpArray[x++]){

        setName("Exit Position Color");    
        setDefault(Color.red);
    };
}

setComputeOnClose();
var bInit = false;
var bVersion = null;

var xClose = null;
var xLow = null;
var xHighestIndexBar = null;
var xTrueRange = null;
var xATR = null;
var xLowestUPT = null;
var xHighestTrail = null;

var BarSinseEntry = null;
var BarSinceExit = 0;
var EntryPrice = null;

var prLinearRegSlopeX2 = null;

function main(fpMaxFlDur, fpFlagMin, fpPX, fpUptBars, fpPoleMin,
              fpDistBFlags, fpATRMin, fpK, fpTimeExit, 
              fpATRLL, fpBSEMIN, fpATRTRAIL, fpTRAILBARS,
              fpBSEINACT, fpATRINACT, fpLongColor, fpShortColor){

    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;

    var nX1 = null;
    var nX2 = null;
    var nOffset = -2;
    var nBottom = null;
    var nPole = null;
    
    if (getBarState() == BARSTATE_ALLBARS){
        BarSinseEntry = null;
        BarSinceExit = 0;
        EntryPrice = null;
        prLinearRegSlopeX2 = null;
    }
    
    if (!bInit){

        xClose = close();
        xLow = low();
        xOpen = open();
                    
        xHighestIndexBar = efsInternal("Calc_HighestBar", xClose, fpMaxFlDur);
        xTrueRange = efsInternal("Calc_TrueRange");
        xATR = sma(40, xTrueRange);
        xLowestUPT = lowest(fpUptBars, xLow);
        xHighestTrail = highest(fpTRAILBARS);

        bInit = true; 
    };

    var nClose = xClose.getValue(0);
    var nNextOpen = xOpen.getValue(1); 
    var nHighestTrail = xHighestTrail.getValue(0);  

    nX1 =  xHighestIndexBar.getValue(nOffset);
      
    if (nX1 == null)
        return;
    
    nX1 = nX1 + -nOffset
    
    nX2 =  nX1 + 1;
          
    var nLF = lowest(nX2).getValue(0);
    var nTop = highest(nX2).getValue(-2);
       
    var xLinearRegSlopeX1 = efsInternal("Calc_LinearRegression_Slope", xClose, nX1);

    var nPrLinearRegSlope = xLinearRegSlopeX1.getValue(-1);
    var nATR = xATR.getValue(0);

    if (nLF == null || nTop == null || nPrLinearRegSlope == null || nATR == null || nHighestTrail == null)
        return;

    if (nPrLinearRegSlope < 0 && (nTop - nLF) < fpFlagMin * nATR)
        nX2 = nX1 + 1;
    else
        nX2 = 100;
    
    if (nX2 > 2 && nX2 <= fpMaxFlDur){
                
        var xLowestIndexBar = efsInternal("Calc_LowestBar", xClose, fpPX + nX2)
        var nY23 = xLowestIndexBar.getValue(0);
       
        nBottom = lowest(fpPX + nX2).getValue(0);

        if (nY23 == null || nBottom == null)
            return;

        nPole = nTop - nBottom;
              
        
        if (nPole > fpPoleMin * nATR && nY23 > nX2){
            
            nTop = highest(nX2).getValue(-2);
            var nFlagBot = lowest(nX2).getValue(0);
            var nLowestUPT = xLowestUPT.getValue(0);

            var nLinearRegSlopeX1 = xLinearRegSlopeX1.getValue(0);

            var xLinearRegSlopeX2 = efsInternal("Calc_LinearRegression_Slope", xClose, nX1 - 1);
            var nLinearRegSlopeX2 = xLinearRegSlopeX2.getValue(-2);
                
            if (nLinearRegSlopeX2 != null)
                prLinearRegSlopeX2 = nLinearRegSlopeX2;
            
            if (nLinearRegSlopeX2 == null)
                nLinearRegSlopeX2 = prLinearRegSlopeX2;

            var nATR_Y23 = xATR.getValue(-nY23)

            if (nTop == null || nLowestUPT == null || nATR_Y23 == null){
                return;
            }

            var nUPT1 = nBottom - nLowestUPT;

            var nLRSX1 = nLinearRegSlopeX1 * 100;
            var nLRSX2 = nLinearRegSlopeX2 * 100;
                

            if (getCurrentBarIndex() != 0){
                         
                if ((!Strategy.isInTrade()) &&
                    (nTop - nLF < fpFlagMin * nATR && (nLRSX1 < 0 || nLRSX2 < 0)) &&
                    (nPole > fpPoleMin * nATR) &&
                    (nUPT1 > 0) &&
                    ( (BarSinceExit == 0) || ( (getCurrentBarCount() - BarSinceExit) > fpDistBFlags) )&&
                    (nATR / nATR_Y23 - 1) * 100 > fpATRMin) {
                            
                    nPrice = highest(nX1).getValue(0);
                    if (nPrice == null)
                        return;
                            
                    nPrice = Math.max(nNextOpen, nPrice);

                    Strategy.doLong("Flag", Strategy.STOP, Strategy.NEXTBAR, Strategy.DEFAULT, nPrice)
                    if (Strategy.isInTrade()){
                        drawShapeRelative(1, BelowBar1, Shape.UPTRIANGLE, null, fpLongColor, Text.PRESET, getCurrentBarCount()+"Flag");
                        drawTextRelative(1, BelowBar2, "Flag", fpLongColor, null, Text.PRESET|Text.CENTER, null, null, getCurrentBarCount()+"Flag_Text");
                        EntryPrice = nPrice;
                        BarSinseEntry = getCurrentBarCount()+1;
                        return;
                    }     
                }    
            }
        }
    }

    if (Strategy.isInTrade()){
        var nBSE = getCurrentBarCount() - BarSinseEntry;
        var nX3 = (xHighestIndexBar.getValue(-(nBSE + 2))) - nBSE + 1;
        nX3 = nX3 + nBSE + 2;
        nTop = highest(nX3).getValue(-(nBSE + 1));
        nBottom = lowest(fpPX + nX3).getValue(-(nBSE + 1));
        nPole = (nTop - nBottom)/(nBottom + 0.0001) * 100;
        var nTargetPer = fpK * nPole;
        var nPrTarget = (1 + nTargetPer / 100) * EntryPrice;
        var nL3 = lowest( nX3, low()).getValue(-nBSE);
        
        if (nClose >= nPrTarget){
            Strategy.doSell("pTARGET", Strategy.CLOSE, Strategy.THISBAR);
            drawShapeRelative(0, AboveBar1, Shape.DOWNTRIANGLE, null, fpShortColor, Text.PRESET, getCurrentBarIndex()+"XLall_t");
            drawTextRelative(0, AboveBar2, "pTARGET", fpShortColor, null, Text.PRESET|Text.CENTER, null, null, getCurrentBarIndex()+"XLall_ts");
            BarSinceExit = getCurrentBarCount();
            return;
        }
        
        if (nBSE > fpBSEMIN){
            var nSell = nL3 - fpATRLL * nATR;
                        
            nSell = Math.min(nNextOpen, nSell);
                    
            Strategy.doSell("UNDER FLAG", Strategy.STOP, Strategy.NEXTBAR, Strategy.DEFAULT, nSell)
            if (!Strategy.isInTrade()){
            drawShapeRelative(1, AboveBar1, Shape.DOWNTRIANGLE, null, fpShortColor, Text.PRESET, getCurrentBarIndex()+"XLall_u");
            drawTextRelative(1, AboveBar2, "UNDER FLAG", fpShortColor, null, Text.PRESET|Text.CENTER, null, null, getCurrentBarIndex()+"XLall_ut");
            BarSinceExit = getCurrentBarCount();
            return;
            }
        }

        if (nClose < nHighestTrail - fpATRTRAIL * nATR){
            Strategy.doSell("TRAIL", Strategy.MARKET, Strategy.NEXTBAR)
            drawShapeRelative(1, AboveBar1, Shape.DOWNTRIANGLE, null, fpShortColor, Text.PRESET, getCurrentBarIndex()+"XLall_tr");
            drawTextRelative(1, AboveBar2, "TRAIL", fpShortColor, null, Text.PRESET|Text.CENTER, null, null, getCurrentBarIndex()+"XLall_trt");
            BarSinceExit = getCurrentBarCount() + 1;
            return;
        } 

        if (nBSE > fpBSEINACT && nClose < EntryPrice + fpATRINACT*nATR){
            Strategy.doSell("INACTIVITY", Strategy.MARKET, Strategy.NEXTBAR)
            drawShapeRelative(1, AboveBar1, Shape.DOWNTRIANGLE, null, fpShortColor, Text.PRESET, getCurrentBarIndex()+"XLall_i");
            drawTextRelative(1, AboveBar2, "INACTIVITY", fpShortColor, null, Text.PRESET|Text.CENTER, null, null, getCurrentBarIndex()+"XLall_it");
            BarSinceExit = getCurrentBarCount();
            return;
        }
        
        if (nBSE > fpTimeExit){
            Strategy.doSell("TIME", Strategy.MARKET, Strategy.NEXTBAR)
            drawShapeRelative(1, AboveBar1, Shape.DOWNTRIANGLE, null, fpShortColor, Text.PRESET, getCurrentBarIndex()+"XLall_m");
            drawTextRelative(1, AboveBar2, "TIME", fpShortColor, null, Text.PRESET|Text.CENTER, null, null, getCurrentBarIndex()+"XLall_mt");
            BarSinceExit = getCurrentBarCount();
            return;
        }  
    }
    return;
}


function Calc_HighestBar(xSource, nLength){

    var nBarNumber = 0;
    var nBarValue = xSource.getValue(0);

    for (i = 1; i <= nLength - 1; i++){
        var nSource = xSource.getValue(-i);
        if (nSource == null)
            return;
        if (nSource > nBarValue){
            nBarValue = nSource;
            nBarNumber = i;
        }
    }
    
    return nBarNumber;
}

function Calc_LowestBar(xSource, nLength){
    
    var nBarNumber = 0;
    var nBarValue = xSource.getValue(0);

    for (i = 1; i <= nLength - 1; i++){
        var nSource = xSource.getValue(-i);
        if (nSource == null)
            return;
        if (nSource < nBarValue){
            nBarValue = nSource;
            nBarNumber = i;
        }
    }
    
    return nBarNumber;
}


function Calc_LinearRegression_Slope(xSourse, nPeriod)
{
    if (getCurrentBarCount() < nPeriod) 
        return;
    
    var nPer = 1;
    var nTime = 0;
    var nTSq = 0;
    var nPrice = 0;
    var nTimePrice = 0;
    var nVal = 0;
    var nSlope = 0;
       
    for (var i = 0; i < nPeriod; i++)
    {
        nTime += nPer;
        nVal = xSourse.getValue(-(nPeriod - 1) + i);  
        nPrice += nVal;
        nTimePrice += (nVal * nPer);
        nTSq += (nPer * nPer);
        nPer++;
    }  
    
    nPer--;
    
    nSlope = ((nPer * nTimePrice) - (nTime * nPrice)) / ((nPer * nTSq) - (nTime * nTime));
    
    return nSlope;
}

var xClose = null;
var xHigh = null;
var xLow = null;

function Calc_TrueRange(){

    if (getBarState() == BARSTATE_ALLBARS)
    {
        xClose = close();
        xHigh = high();
        xLow = low();
    }

    var nPrClose = xClose.getValue(-1);

    if (nPrClose == null)
        return;

    var nHigh = xHigh.getValue(0);
    var nLow = xLow.getValue(0);

    var nTrueHigh = null;
    var nTrueLow = null;

    if (nPrClose > nHigh)
        nTrueHigh = nPrClose
    else
        nTrueHigh = nHigh;

    if (nPrClose < nLow)
        nTrueLow = nPrClose
    else
        nTrueLow = nLow;

    var nReturnValue = nTrueHigh - nTrueLow;   
    
    return nReturnValue;
}


function verify(){
    
    var b = false;
    if (getBuildNumber() < 779){
        
        drawTextAbsolute(5, 35, "This study requires version 8.0 or later.", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "error");
        drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=http://www.esignal.com/download/default.asp", 
            Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT,
            null, 13, "upgrade");
        return b;
    } 
    else
        b = true;
    
    return b;
}