2005 Apr: Trading Moving Average Pullbacks (MAPS.efs)

ICE Data Services -

MAPS.efs  
EFSLibrary - Discussion Board  

File Name: MAPS.efs

Description:
This formula is based on the April 2005 article, Success Amid Risk - Trading Moving Average Pullbacks, by Steve Palmquist.

Formula Parameters:

  • MA Length: 30
  • MA Source: Close
  • MA Type: SIMPLE
  • Pullback Percent Envelope: 1%
  • Trend Bars: 30

Notes:
This study is back testing compatiblle for the Strategy Analyzer. The related article is copyrighted material. If you are not a subscriber of Stocks & Commodities, please visit www.traders.com.

Download File:
MAPS.efs


EFS Code:

/***************************************
Provided By : eSignal (c) Copyright 2005
Description:  Moving Average Pullback System - by Steve Palmquist

Version 1.0  2/10/2005

Notes:
April 2005 Issue - "Success Amid Risk - Trading Moving Average Pullbacks"

Formula Parameters:                 Defaults:
MA Length                           30
MA Source                           Close
MA Type                             SIMPLE
Pullback Percent Envelope           1%
Trend Bars                          30
***************************************/

function preMain() {
    setPriceStudy(true);
    setStudyTitle("Moving Average Pullback System ");
    setShowTitleParameters(false);
    setCursorLabelName("+1\%", 0);
    setCursorLabelName("MA", 1);
    setCursorLabelName("-1\%", 2); 
    setCursorLabelName("Trend Count", 3);
    setDefaultBarFgColor(Color.blue, 0);
    setDefaultBarFgColor(Color.red, 1);
    setDefaultBarFgColor(Color.blue, 2);
    setDefaultBarFgColor(Color.grey, 3);
    
    var fp1 = new FunctionParameter("nLength", FunctionParameter.NUMBER);
        fp1.setName("MA Length");
        fp1.setDefault(30);
        fp1.setLowerLimit(1);
    var fp2 = new FunctionParameter("sSource", FunctionParameter.STRING);
        fp2.setName("MA Source");
        fp2.setDefault("Close");
        fp2.addOption("Open");
        fp2.addOption("High");
        fp2.addOption("Low");
        fp2.addOption("Close");
        fp2.addOption("HL/2");
        fp2.addOption("HLC/3");
        fp2.addOption("OHLC/4");
    var fp3  = new FunctionParameter("type", FunctionParameter.STRING);
        fp3.setName("MA Type");
        fp3.setDefault("SIMPLE");
        fp3.addOption("SIMPLE");
        fp3.addOption("EXPONENTIAL");
        fp3.addOption("WEIGHTED");
        fp3.addOption("VOLUMEWEIGHTED");
    var fp4 = new FunctionParameter("nPBpercent", FunctionParameter.NUMBER);
        fp4.setName("Pullback Percent Envelope");
        fp4.setDefault(1);
        fp4.setLowerLimit(0);
        fp4.setUpperLimit(100);
    var fp5 = new FunctionParameter("nTrendBars", FunctionParameter.NUMBER);
        fp5.setName("Number of Bars for Trend");
        fp5.setDefault(30);
        fp5.setLowerLimit(1);
}

var study = null;
var bt = true;      // back testing on
var nTrendCntr = 0;
var nTrendCntr1 = 0;// previous bar's nTrendCntr
var sSide = 0;      // 1 = obove MA, -1 = below MA
var sSide1 = 0;     // previous bar's sSide
var bInit = true;   // initialization routine.
var bLongTrigger = false;
var bShortTrigger = false;
var vPosition = 0;  // 0 = no position, 1 = long, -1 = short
var nTriggerIndex = null;
var nBarCount = 0;  // bar counter for exit strategy

function main(nLength, sSource, type, nPBpercent, nTrendBars) {    
    var nState = getBarState();

    if (nState == BARSTATE_ALLBARS || bInit == true) {
        study = new MAStudy(nLength, 0, sSource, eval("MAStudy." + type));
        if (close(0) > vMA) sSide = 1;
        else sSide = -1;
        setCursorLabelName("+" + nPBpercent + "\%", 0);
        setCursorLabelName("-" + nPBpercent + "\%", 2);
        bt = true;
        bInit = false;
    }
    
    var vMA = study.getValue(MAStudy.MA);
    var vMA1 = study.getValue(MAStudy.MA, -1);
    if (vMA == null || vMA1 == null) return;
    
    if (nState == BARSTATE_NEWBAR) {
        nTrendCntr1 = nTrendCntr;
        nTrendCntr += 1;
        sSide1 = sSide;
        nBarCount += 1;
        if (getCurrentBarIndex() < 0) bt = true;
        else bt = false;
    }
    
    if (sSide == 1 && low(-1) < vMA1) sSide = -1;
    else if (sSide == -1 && high(-1) > vMA1) sSide = 1;
    
    if (nState == BARSTATE_NEWBAR && bLongTrigger == false && bShortTrigger == false) {
        if (nTrendCntr1 >= nTrendBars) {
            if (sSide1 == 1 && vPosition != 1) {
                if ( Math.abs((low(-1) - vMA1)/vMA1) <= (nPBpercent/100) ) {
                    bLongTrigger = true;
                    nTriggerIndex = getCurrentBarIndex();
                }
            } else if (sSide1 == -1 && vPosition != -1) {
                if ( Math.abs((vMA1 - high(-1))/vMA1) <= (nPBpercent/100) ) {
                    bShortTrigger = true;
                    nTriggerIndex = getCurrentBarIndex();
                }
            }
        }
    }
    
    // Position Exit
    if (vPosition != 0 && nBarCount == 3) {
        if (vPosition == 1) {
            longExit();
        } else if (vPosition == -1) {
            shortExit();
        }
    }
    
    // Position Entry
    if (getCurrentBarIndex() == nTriggerIndex) {
        if (bLongTrigger == true) {
            if (high(0) > high(-1)) longEntry();
        } else if (bShortTrigger == true) {
            if (low(0) < low(-1)) shortEntry();
        }
    } else {
        bLongTrigger = false;
        bShortTrigger = false;
    }

    if (vPosition == 1) setBarBgColor(Color.green);
    if (vPosition == -1) setBarBgColor(Color.red); 
    
    if (sSide1 != sSide) nTrendCntr = 0;  // reset trend
    
    return new Array(((nPBpercent/100)*vMA)+vMA, vMA, vMA-((nPBpercent/100)*vMA), nTrendCntr+"");
}

/***** Support Functions *****/

function longEntry() {
    bLongTrigger = false;
    vPosition = 1;
    setBarBgColor(Color.green);
    var nEntryPrice = high(-1);
    if (open(0) > nEntryPrice) nEntryPrice = open(0);
    if (bt == true) {
        Strategy.doLong("Buy", Strategy.LIMIT, Strategy.THISBAR, null, nEntryPrice);
    }
    nBarCount = 0;
    return;
}

function shortEntry() {
    bShortTrigger = false;
    vPosition = -1
    setBarBgColor(Color.red);
    var nEntryPrice = low(-1);
    if (open(0) < nEntryPrice) nEntryPrice = open(0);
    if (bt == true) {
        Strategy.doShort("Short", Strategy.LIMIT, Strategy.THISBAR, null, nEntryPrice);
    }
    nBarCount = 0;
    return;
}

function longExit() {
    vPosition = 0;
    if (bt == true) Strategy.doSell("Long Stop", Strategy.MARKET, Strategy.THISBAR);
    return;
}

function shortExit() {
    vPosition = 0;
    if (bt == true) Strategy.doCover("Short Stop", Strategy.MARKET, Strategy.THISBAR);
    return;
}