July 2004
TRADERS' TIPS

Here is this month's selection of Traders' Tips, contributed by various developers of technical analysis software to help readers more easily implement some of the strategies presented in this and other issues.

You can copy these formulas and programs for easy use in your spreadsheet or analysis software. Simply "select" the desired text by highlighting as you would in any word processing program, then use your standard key command for copy or choose "copy" from the browser menu. The copied text can then be "pasted" into any open spreadsheet or other software by selecting an insertion point and executing a paste command. By toggling back and forth between an application window and the open webpage, data can be transferred with ease.

This month's tips include formulas and programs for:
 

TRADESTATION: VFI PERFORMANCE
METASTOCK: VFI PERFORMANCE
AMIBROKER: VFI PERFORMANCE
eSIGNAL: VFI PERFORMANCE
WEALTH-LAB: VFI PERFORMANCE
TRADINGSOLUTIONS: VFI PERFORMANCE
NEUROSHELL TRADER: VFI PERFORMANCE
NEOTICKER: VFI PERFORMANCE
STOCKWIZ: VFI PERFORMANCE
TECHNIFILTER PLUS: VFI PERFORMANCE
or return to July 2004 Contents


TRADESTATION: VFI PERFORMANCE

Markos Katsanos' article in this issue, "Volume Flow Indicator Performance," provides four strategies for trading the volume flow indicator (VFI). All four strategies are provided here in TradeStation EasyLanguage. In addition, Katsanos introduced a new indicator, the VFI-price divergence, which is also coded here.

Most of the calculations are performed in the function "VfiSmoothed," which was given in the TradeStation tip in the May 2004 Traders' Tips column.

When using these strategies, please remember to format your strategy properly for the maximum number of bars the study may reference. These strategies need to review a fairly large number of bars, so I used 250 bars.
 

Indicator:  VFI-Price Divergence
inputs:
 Coef( .2 ),
 VCoef( 2.5 ),
  Period( 130 ),
 VFISmoothing( 3 ),
 LinearRegPeriod( 120 ) ;
variables:
 oCutOff( 0 ), { calculated volume cutoff }
 oVC( 0 ), { trimmed volume values }
 oMF( 0 ), { difference in 'typical' price }
 oVFI( 0 ), { calculated VFI }
  MySmoothedVFI( 0 ), { smoothed VFI values }
 MyVolume( 0 ), { volume after BarInterval test }
 LRS( 0 ), { linear regression slope - price }
 LRSI( 0 ), { linear regression slope - VFI }
 KatsanosDivergence( 0 ),
 LowestVFI( 9999999 ),
  VFI1( 0 ); { always positive VFI }
MyVolume = iff( BarType < 2, Ticks, Volume ) ;
MySmoothedVFI = VFISmooth( Coef, VCoef, Period,
 VFISmoothing, MyVolume, oCutOff, oVC, oMF, oVFI ) ;
if MySmoothedVFI < LowestVFI then
 LowestVFI = MySmoothedVFI ;
VFI1 = MySmoothedVFI + AbsValue( LowestVFI )+ 10 ;
if Currentbar > LinearRegPeriod * 2 then
 begin
 if Close[ LinearRegPeriod ] > 0 then
  LRS = LinearRegSlope( close , LinearRegPeriod )
   / close[ LinearRegPeriod ] * 100 ;
 if VFI1[ LinearRegPeriod ] > 0 then
  LRSI= LinearRegSlope( VFI1, LinearRegPeriod )
   / VFI1[ LinearRegPeriod ] * 100 ;
 KatsanosDivergence =
  XAverage( LRSI - LRS, 3 ) * 100 ;
 Plot1( KatsanosDivergence ) ;
 end ;
Strategy: Katsanos VFI Cross 0
inputs:
 Coef( .2 ),
 VCoef( 2.5 ),
  Period( 5 ),
 SmoothedPeriod( 7 ) ;
variables:
 oCutOff( 0 ),
 oVC( 0 ),
 oMF( 0 ),
 oVFI( 0 ),
  MyVFI( 0 ),
 MyVolume( 0 ) ;
MyVolume = iff( BarType < 2, Ticks, Volume ) ;
MyVFI = VFISmooth( Coef, VCoef, Period,
 SmoothedPeriod, MyVolume, oCutOff, oVC, oMF, oVFI );
if MyVFI crosses over 0 then
 buy next bar at market ;
if MyVFI crosses under 0 then
 sellshort next bar at market ;
Strategy:  Katsanos VFI Divergence inputs:
 Coef( .2 ),
 VCoef( 2.5 ),
  Period( 130 ),
    VFISmoothing( 3 ),
 LinearRegPeriod( 120 ),
  TradeThreshold( 100 ) ;
variables:
 oCutOff( 0 ), { calculated volume cutoff }
 oVC( 0 ), { trimmed volume values }
 oMF( 0 ), { difference in 'typical' price }
 oVFI( 0 ), { calculated VFI}
  MySmoothedVFI( 0 ), { smoothed VFI values }
 MyVolume( 0 ), { volume after BarInterval test }
 LRS(0), {linear regression slope - normalized price}
 LRSI(0), {linear regression slope - normalized VFI}
 KatsanosDivergence( 0 ),
 LowestVFI( 9999999 ),
  VFI1( 0 ) ; { always positive VFI }
MyVolume = iff( BarType < 2, Ticks, Volume ) ;
MySmoothedVFI = VFISmooth( Coef, VCoef, Period,
 VFISmoothing , MyVolume, oCutOff, oVC, oMF, oVFI ) ;
if MySmoothedVFI < LowestVFI then
 LowestVFI = MySmoothedVFI ;
VFI1 = MySmoothedVFI + AbsValue( LowestVFI ) + 10 ;
if Currentbar > LinearRegPeriod * 2 then
 begin
 if Close[ LinearRegPeriod ] > 0 then
  LRS = LinearRegSlope( Close , LinearRegPeriod )
   / Close[ LinearRegPeriod ]*100 ;
 if VFI1[ LinearRegPeriod ] > 0 then
  LRSI = LinearRegSlope( VFI1, LinearRegPeriod )
  / VFI1[ LinearRegPeriod ]*100 ;
 KatsanosDivergence =
  XAverage( LRSI - LRS, 3 ) * 100 ;
 end ;
{ enter long }
if KatsanosDivergence[ 1 ] > TradeThreshold
 and KatsanosDivergence[ 1 ] > KatsanosDivergence
 and LRSI > 0
then
 Buy next bar at Market ;
{ exit long }
if KatsanosDivergence < 0 and LRSI < 0 then
 Sell next bar at Market ;
 
Strategy:  Katsanos VFI Pattern inputs:
 VFIEnterL( -2 ),
 MA( 40 ),
 LRPeriod( 20 ),
 LRC( 30 ),
 UB( .1 ),
 LB( -.05 ),
 VFIExitAngle( -40 ),
 VFIExitL( -2 ),
 Coef( .2 ),
 VCoef( 2.5 ),
  Period( 130 ),
  VFISmoothing( 3 ) ;
variables:
 oCutOff( 0 ),
 oVC( 0 ),
 oMF( 0 ),
 oVFI( 0 ),
  MySmoothedVFI( 0 ),
 MyVolume( 0 ) ;
MyVolume = iff( BarType < 2, Ticks, Volume ) ;
MySmoothedVFI = VFISmooth( Coef, VCoef, Period,
 VFISmoothing, MyVolume, oCutOff, oVC, oMF, oVFI ) ;
if BarNumber > 2 * Period then
 begin
 if MarketPosition = 0
  and oVFI > VFIEnterL
  and LinearRegAngleFC( oVFI, LRPeriod ) > 0
  and oVFI > XAverage( oVFI, MA )
  and LinearRegSlopeFC( C, LRC ) < UB
   * LinearRegValue( C , LRC, LRC - 1 ) / 100
  and LinearRegSlopeFC( C, LRC ) > LB
   * LinearRegValue( C, LRC, LRC - 1 ) / 100
 then
  Buy ( "BUY" ) next bar at market ;
 if LinearRegAngle( oVFI, LRPeriod ) < VFIExitAngle
  or oVFI < VFIExitL
 then
  Sell ( "VFI EXIT" ) next bar at market ;
 end ;
Strategy:  Katsanos VFI MA Cross Inputs:
 Coef( .2 ),
 VCoef( 2.5 ),
  Period( 1305 ),
 SmoothedPeriod( 3 ),
  LongVFILen( 25 ),
 ShortVFILen( 11 ) ;
variables:
 oCutOff( 0 ),
 oVC( 0 ),
 oMF( 0 ),
 oVFI( 0 ),
  MyVFI( 0 ),
 MyVolume( 0 ),
 LongMA( 0 ),
 ShortMA( 0 ) ;
MyVolume = iff( BarType < 2, Ticks, Volume ) ;
MyVFI = VFISmooth( Coef, VCoef, Period, SmoothedPeriod,
 MyVolume, oCutOff, oVC, oMF, oVFI ) ;
LongMA = XAverage( MyVFI, LongVFILen ) ;
ShortMA = XAverage( MyVFI, ShortVFILen ) ;
if ShortMA crosses over LongMA then
 buy next bar at market ;
if LongMA crosses over ShortMA then
 sell next bar at market ;


This EasyLanguage code will be posted in the file library at www.TradeStationWorld.com. Look for the file "VFI Performance.Eld." A sample chart is in Figure 1.
 


FIGURE 1: TRADESTATION, VFI-PRICE DIVERGENCE. This sample TradeStation chart shows Markos Katsanos' volume flow indicator on Foamex International (FMXI) along with the VFI-price divergence indicator.
 

--Mark Mills
MarkM@TSSec at www.TradeStationWorld.com
EasyLanguage Questions Forum
TradeStation Securities, Inc.
A subsidiary of TradeStation Group, Inc.


GO BACK


METASTOCK: VFI PERFORMANCE

See the sidebar in Markos Katsanos' article in this issue for MetaStock code for implementing the volume flow indicator, which Katsanos provided as part of his article.

--William Golson
Equis International


GO BACK


AMIBROKER: VFI PERFORMANCE

In "Volume Flow Indicator Performance," Markos Katsanos compares the results of CFI-based trading systems to OBV-based systems. All the systems presented in the article can be recreated using AmiBroker.

Listing 1 shows code that implements all four systems. The formula should be applied in AmiBroker's Automatic Analysis window. You can choose the test you would like to run by clicking on the "Parameters" button. Please do not forget to go to the "Settings" dialog to adjust backtesting parameters, such as commissions, bar interval, and so on. After that, click the "Back test" button to perform the system test. In less than a second, the backtest will be complete. Then you can choose "Show arrows for actual trades" to show the buy/sell arrows and get detailed statistics, including the well-known Sharpe ratio, ulcer index, and many others, by clicking on the "Report" button.
 


FIGURE 2: AMIBROKER, VOLUME FLOW INDICATOR. This AmiBroker screenshot shows a weekly price chart of GLW [Corning Inc.] with buy (green arrow) and sell (red arrow) signals generated by the VFI formula (upper pane) and the 26-week VFI indicator with its seven-bar EMA plus color-coded volume bars in the lower pane.


In AmiBroker, you can run not only individual backtests but also a full portfolio-level backtest. For that, you would need to "uncomment" position sizing in the formula below.
 

LISTING 1
// You can choose from one of the following types of tests
// 1 - VFI level (weekly)
// 2 - Divergence
// 3 - Break from base
// 4 - MA crossover
TestType = Param("TestType", 1, 1, 4, 1 );
function VFI( Period, VCoef )
{
 Coef = 0.2;
 inter = log( Avg ) - log( Ref( Avg, -1 ) );
 Vinter = StDev(inter, 30 );
 Cutoff = Coef * Vinter * Close;
 Vave = Ref( MA( V, Period ), -1 );
 Vmax = Vave * Vcoef;
 Vc = Min( V, VMax );
 MF = Avg - Ref( Avg, -1 );
 VCP = IIf( MF > Cutoff, VC, IIf ( MF < -Cutoff, -VC, 0 ) );
 VFIv = Sum( VCP , Period )/Vave;
 VFIv = EMA( VFIv, 3 );
 return VFIv;
}
// use 26 weeks for test 1, and 130 days otherwise
Period = IIf( TestType == 1, 26, 130 );
VCoef = 2.5;
VF = VFI( Period, VCoef );
if( TestType == 1 )
{
 // VFI level (weekly)
 Buy = EMA( VF, 7 ) > 0.01;
 Sell = EMA( VF, 7 ) < 0;
}
if( TestType == 2 )
{
 // VFI divergence
 D1 = 120; //Optimize( "DivDays", 120, 50, 300, 1 );
 P1 = VF + abs( Lowest( VF ) ) + 10;
 LRSI = LinRegSlope( P1, D1 ) / abs( Ref( P1, -D1 ) ) * 100;
 LRS = LinRegSlope( C, D1 ) / abs( Ref( C, -D1 ) ) * 100;
 DIVERG = LRSI - LRS;
 DIVERG = EMA( DIVERG, 3 ) * 100;
 Buy = Ref( Diverg, -1 ) > 100 AND Diverg < Ref( Diverg, -1 ) AND LRSI > 0;
 Sell = Diverg < 0 OR LRSI < 0;
}
if( TestType == 3 )
{
 // VFI break from base
 Buy = VF > -2 AND LinRegSlope( VF, 20 ) > 0.1 AND
       VF > EMA( VF, 40 ) AND
       LinRegSlope( C, 30 ) < Ref( C, -30 ) * 0.6 / 100 AND
       LinRegSlope( C, 30 ) > 0;
 Sell = VF < -2 OR LinRegSlope( VF, 20 ) < -0.8;
}
if( TestType == 4 )
{
 // VFI MA crossover
 SMA = EMA( VF, Optimize("SMA", 11, 2, 20, 1 ) );
 LMA = EMA( VF, Optimize("LMA", 25, 10, 40, 1 ) );
 Buy = Cross( SMA, LMA );
 Sell = Cross( LMA, SMA );
}
// Position sizing
// uncomment 2 lines below to invest max 20% to single security
// PositionSize = -20;
// SetOption("MaxOpenPositions", 5 );
--Tomasz Janeczko, AmiBroker.com
www.amibroker.com
GO BACK


eSIGNAL: VFI PERFORMANCE

This eSignal code implements the volume flow indicator as described by Markos Katsanos this issue.

This code is written for backtesting using the Strategy Analyzer feature of eSignal. The formula includes all four tests for the VFI as described in Markos Katsanos' article in this issue. When running the Strategy Analyzer, the user needs to configure the formula parameters in the Back Testing window (Tools-->Back Testing) before running the test.

The formula also includes logic for taking short positions. However, if you want to exclude short trades, you can uncheck the option "Allow Shorts" in the Back Testing window to exclude short trades for the test.

On the eSignal chart in Figure 3, the bars where long positions were triggered are designated with a dark green background and the short positions are shown in red. For those tests with exit conditions, the bar where the exit signal is triggered will have a gray background.
 


FIGURE 3: eSIGNAL, VOLUME FLOW INDICATOR. On the eSignal chart, the bars where long positions were triggered are designated with a dark green background and the short positions are shown in red. For those tests with exit conditions, the bar where the exit signal is triggered will have a gray background.
/*****************************************************************
Provided By : eSignal. (c) Copyright 2004
Study:        Back Testing Volume Flow Indicator by Markos Katsanos
Version:      1.0

5/4/2004

Formula Parameters:                 Default:
    VFI Length                      26
    MA of VFI Length                50
    MA of VFI Type                  EMA
       SMA
       EMA
    Back Test #                     1
       1 Indicator Level
       2 Divergence
       3 Break from base
       4 Indicator Direction
    BT 2 Linear Regression Length   120
    BT 3 Linear Regression Length   30
    BT 4 SMA Length                 11
    BT 4 LMA Length                 25
    Initial Account Size            10000

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


function preMain() {
    setStudyTitle("Back Test Volume Flow Indicator ");
    setShowTitleParameters(false);
    setCursorLabelName("VFI", 0);
    setCursorLabelName("VFI MA", 1);
    setDefaultBarFgColor(Color.green, 0);
    setDefaultBarFgColor(Color.blue, 1);
    setDefaultBarThickness(2, 0);
    setDefaultBarThickness(2, 1);
    addBand(0, PS_SOLID, 2, Color.black, "zero");
 
    var fp0 = new FunctionParameter("nVFIlength", FunctionParameter.NUMBER);
    fp0.setName("VFI Length");
    fp0.setLowerLimit(1);
    fp0.setDefault(26);
 
    var fp1 = new FunctionParameter("nVFImaLen", FunctionParameter.NUMBER);
    fp1.setName("MA of VFI Length");
    fp1.setLowerLimit(1);
    fp1.setDefault(50);
 
    var fp1a = new FunctionParameter("sVFImaType", FunctionParameter.STRING);
    fp1a.setName("MA of VFI Type");
    fp1a.addOption("SMA");
    fp1a.addOption("EMA");
    fp1a.setDefault("EMA");
 
    var fp2 = new FunctionParameter("nTest", FunctionParameter.NUMBER);
    fp2.setName("Back Test #: ");
    fp2.setLowerLimit(1);
    fp2.setUpperLimit(4);
    fp2.addOption(1);   // Indicator Level
    fp2.addOption(2);   // Divergence
    fp2.addOption(3);   // Break from base
    fp2.addOption(4);   // Indicator Direction
    fp2.setDefault(1);
 
    var fp3 = new FunctionParameter("nLRlength", FunctionParameter.NUMBER);
    fp3.setName("BT 2 Linear Regression Length");
    fp3.setLowerLimit(1);
    fp3.setDefault(120);

    var fp4 = new FunctionParameter("nLRlength3", FunctionParameter.NUMBER);
    fp4.setName("BT 3 Linear Regression Length");
    fp4.setLowerLimit(1);
    fp4.setDefault(30);

    var fp5 = new FunctionParameter("nSMAlength", FunctionParameter.NUMBER);
    fp5.setName("BT 4 SMA Length");
    fp5.setLowerLimit(1);
    fp5.setDefault(11);

    var fp6 = new FunctionParameter("nLMAlength", FunctionParameter.NUMBER);
    fp6.setName("BT 4 LMA Length");
    fp6.setLowerLimit(1);
    fp6.setDefault(25);

    var fp7 = new FunctionParameter("nAcctStart", FunctionParameter.NUMBER);
    fp7.setName("Initial Account Size");
    fp7.setLowerLimit(1);
    fp7.setDefault(10000);
}


var nTyp = null;                // Current typical price
var nTyp1 = null;               // Previous typical price
var nTypChg = 0;                // Current typical price change
var vVol = null;                // Current volume
var nVolSum = 0;                // Cumulative volume sum
var nVolAdj = 0;                // Current adjusted volume
var nVolMA = null;              // Current Vol MA
var nVolMA1 = null;             // Previous Vol MA
var aTypPrice = null;           // Array of changes in typical price
var aVolume = null;             // Volume array
var VFI = null;                 // Current VFI
var aVFI = null;                // Array of VFI values for EMA calc
var aEMA = null;                // Array of VFI 3EMA values
var nTestNum = 1;               // Back Test Number
var bEdit = false;


// globals for EMA
var vEMA = new Array(5);
var vEMA1 = new Array(5);
var dPercent = new Array(0, 0, 0, 0, 0);
var bPrimed = new Array(false, false, false, false, false);
//[0] = VFI, [1] = (LRSI-LRS), [2] = ShortMA VFI, [3] = LongMA VFI, [4] = EMA of VFI

// globals for back testing
var nAccount = 10000;
var nEntry = null;
var bLong = false;
var bShort = false;
var bExit = false;
var aDivPrice = null;
var aDivVFI = null;
var aLRS_LRS1 = new Array(3);
var vDivergence = null;
var vDivergence1 = null;
var aVFItest3 = null;
var aLMA = null;
var aSMA = null;
var aClose = null;


function main(nVFIlength, nVFImaLen, sVFImaType, nTest, nLRlength, nLRlength3,
            nSMAlength, nLMAlength, nAcctStart) {
    var nState = getBarState();
    var vInter = 0;
    var nCutoff = 0;
    var vMAofEMA = null;
    var dSum = 0;
    var i = 0;
 
    if (bEdit == false) {
        if (aTypPrice == null) aTypPrice = new Array(nVFIlength);
        if (aVolume == null) aVolume = new Array(nVFIlength);
        if (aEMA == null) aEMA = new Array(nVFImaLen);
        nTestNum = nTest;
        var sTestText = "";
        if (aVFI == null) {
            if (nTestNum == 1) {
                aVFI = new Array(7);
                sTestText = "Test 1: Indicator Level";
            }
            if (nTestNum > 1) {
                aVFI = new Array(3);
                if (nTestNum == 2) {
                    sTestText = "Test 2: Divergence";
                }
            }
            if (nTestNum == 3) {
                addBand(-2, PS_SOLID, 2, Color.black, "zero");
                aVFItest3 = new Array(20);
                sTestText = "Test 3: Break From Base";
            }
            if (nTestNum == 4) {
                aSMA = new Array(nSMAlength);
                aLMA = new Array(nLMAlength);
                sTestText = "Test 4: Indicator Direction";
            }
        }
        if (nTestNum == 4) {
            setCursorLabelName("SMA VFI", 0);
            setCursorLabelName("LMA VFI", 1);
            setDefaultBarFgColor(Color.navy, 0);
        }
        drawTextAbsolute(1, 15, sTestText, Color.navy, null,
            Text.RELATIVETOTOP|Text.RELATIVETOLEFT|Text.LEFT|Text.BOLD,
            null, 12, "TestNum");
        nAccount = nAcctStart;
        bEdit = true;
    }
 
    if (nState == BARSTATE_NEWBAR) {
        if (nTyp != null) {
            aTypPrice.pop();
            aTypPrice.unshift(nTypChg);
            nTyp1 = nTyp;
        }
        if (nVol != null) {
            aVolume.pop();
            aVolume.unshift(nVol);
        }
        nVolMA1 = nVolMA;
        nVolSum += nVolAdj;
        if (VFI != null) {
            aVFI.pop();
            aVFI.unshift(VFI);
        }
        if (vEMA[0] != null) {
            aEMA.pop();
            aEMA.unshift(vEMA[0]);
        }
    }
 
    nVol = volume();
    if (nVol == null) return;
    aVolume[0] = nVol;
    if (aVolume[nVFIlength-1] != null) {
        for (i = 0; i < nVFIlength; ++i) {
            dSum += aVolume[i];
        }
        nVolMA = dSum/nVFIlength;
    }
 
    nTyp = (high() + low() + close()) / 3;
    if (nTyp1 != null) {
        nTypChg = (Math.log(nTyp) - Math.log(nTyp1));
        aTypPrice[0] = nTypChg;
    }
 
    if (nVolMA == null || nVolMA1 == null) return;
 
    if (aTypPrice[nVFIlength-1] != null) {
        vInter = StDev(nVFIlength);
        nCutoff = (.2 * vInter * close());
    } else {
        return;
    }

    nVolAdj = nVol;
    //Minimal Change Cutoff
    if ((nTyp - nTyp1) >= 0 && (nTyp - nTyp1) < nCutoff) nVolAdj = 0;
    if ((nTyp - nTyp1) < 0 && (nTyp - nTyp1) > -nCutoff) nVolAdj = 0;
    // Volume curtailment
    if (nVolAdj > (2.5*nVolMA1)) nVolAdj = (2.5*nVolMA1);
 
    if (nTyp - nTyp1 < 0) nVolAdj *= -1;
    VFI = ((nVolSum + nVolAdj) / nVolMA1);
    aVFI[0] = VFI;
 
    if (aVFI[(aVFI.length)-1] != null) {
        vEMA[0] = EMA(0, VFI, aVFI.length, aVFI);
        aEMA[0] = vEMA[0];
    }
    if (aEMA[nVFImaLen-1] != null) {
        if (sVFImaType == "SMA") {
            dSum = 0;
            i = 0;
            for(i = 0; i < nVFImaLen; ++i) {
                dSum += aEMA[i];
            }
            vMAofEMA = dSum/nVFImaLen;
        } else if (sVFImaType == "EMA") {
            vEMA[4] = EMA(4, aEMA[0], aEMA.length, aEMA);
            vMAofEMA = vEMA[4];
        }
    }

    if (vEMA[0] != null && nTestNum != 4) {
        var nLine = 0;
        if (nTestNum == 3) nLine = -2
        if (vEMA[0] > nLine) {
            setBarFgColor(Color.green, 0);
        } else {
            setBarFgColor(Color.red, 0);
        }
    }
 
    // Back Testing Section
    if (getCurrentBarIndex() < 0 && vEMA != null && vEMA1 != null) { // processing historical data for back testing
        // draw entry signals
        if (bLong == true) {
            setBarBgColor(Color.darkgreen);
            //drawShapeRelative(0, vEMA1[0], Shape.UPARROW, null,
            //    Color.khaki, Shape.TOP|Shape.ONTOP);
        }
        if (bShort == true) {
            setBarBgColor(Color.maroon);
            //drawShapeRelative(0, vEMA1[0], Shape.DOWNARROW, null,
            //    Color.khaki, Shape.BOTTOM|Shape.ONTOP);
        }
        if (bExit == true) {
            setBarBgColor(Color.lightgrey);
            //drawShapeRelative(0, vEMA1[0], Shape.DIAMOND, null,
            //    Color.khaki, Shape.BOTTOM|Shape.ONTOP);
        }
 
        bLong = false;
        bShort = false;
        bExit = false;
 
        var nLotSize = Math.floor(nAccount/open(1));
 
        // Test 1   Indicator Level
        if (nTestNum == 1) {
            if (vEMA[0] > 0 && vEMA1[0] <= 0 && Strategy.isLong() == false) { // long
                if (Strategy.isShort() == true) {
                    nAccount += ( (vEntry-open(1)) * (-Strategy.getPositionSize()) );
                    Strategy.doCover("Close Short", Strategy.MARKET, Strategy.NEXTBAR, Strategy.getPositionSize());
                    nLotSize = Math.floor(nAccount/open(1))
                }
                bLong = true;
                vEntry = open(1);
                Strategy.doLong("Crossing Up", Strategy.MARKET, Strategy.NEXTBAR, nLotSize);
            } else if (vEMA[0] < 0 && vEMA1[0] >= 0 && Strategy.isShort() == false) { // short
                if (Strategy.isLong() == true) {
                    nAccount += ( (open(1)-vEntry) * (Strategy.getPositionSize()) );
                    Strategy.doSell("Close Long", Strategy.MARKET, Strategy.NEXTBAR, Strategy.getPositionSize());
                    nLotSize = Math.floor(nAccount/open(1))
                }
                bShort = true;
                vEntry = open(1);
                Strategy.doShort("Crossing Down", Strategy.MARKET, Strategy.NEXTBAR, nLotSize);
            }
        }
        // Test 2   Divergence
        if (nTestNum == 2) {
            if (aDivPrice == null) aDivPrice = new Array(nLRlength);
            if (aDivVFI == null) aDivVFI = new Array(nLRlength);
 
            if (vDivergence != null) vDivergence1 = vDivergence;
            // VFI1 conversion = VFI + Math.abs(Lowest(VFI)) + 10;
            var VFI1 = (VFI + Math.abs(Lowest()) + 10).toFixed(2)*1;
            var LRS, LRS1;
 
            aDivPrice.pop();
            aDivPrice.unshift(close());
            aDivVFI.pop();
            aDivVFI.unshift(VFI1);

            if (aDivPrice[nLRlength-1] != null && aDivVFI[nLRlength-1] != null) {
                LRS = (LinearRegressionSlope(aDivPrice) / aDivPrice[nLRlength-1]);
                LRS1 = (LinearRegressionSlope(aDivVFI) / aDivVFI[nLRlength-1]);
                aLRS_LRS1.pop();
                aLRS_LRS1.unshift((LRS1 - LRS));
                if (aLRS_LRS1[2] != null) {
                    vEMA[1] = EMA(1, aLRS_LRS1[0], 3, aLRS_LRS1);
                    vDivergence = vEMA[1] * 100;
                    if (vDivergence != null) {
                        if (Strategy.isInTrade() == false) {
                            if (vDivergence1 > 100 && vDivergence < vDivergence1 && LRS1 > 0) {  // Long entry
                                bLong = true;
                                vEntry = open(1);
                                Strategy.doLong("Long Divergence", Strategy.MARKET, Strategy.NEXTBAR, nLotSize);
                            } else if (vDivergence1 < -100 && vDivergence > vDivergence1 && LRS1 < 0) {  // Short entry
                                bShort = true;
                                vEntry = open(1);
                                Strategy.doShort("Short Divergence", Strategy.MARKET, Strategy.NEXTBAR, nLotSize);
                            }
                        } else if (Strategy.isLong()) { // exit long
                            if (vDivergence < 0 && LRS1 < 0) {
                                nAccount += ( (open(1)-vEntry) * (Strategy.getPositionSize()) );
                                bExit = true;
                                Strategy.doSell("Exit Long", Strategy.MARKET, Strategy.NEXTBAR, Strategy.getPositionSize());
                            }
                        } else if (Strategy.isShort()) {  // exit short
                            if (vDivergence > 0 && LRS1 > 0) {
                                nAccount += ( (vEntry-open(1)) * (-Strategy.getPositionSize()) );
                                bExit = true;
                                Strategy.doCover("Exit Short", Strategy.MARKET, Strategy.NEXTBAR, Strategy.getPositionSize());
                            }
                        }
                    }
                }
            }
        }
        // Test 3
        if (nTestNum == 3) {
            if (aClose == null) aClose = new Array(nLRlength3);
            var bC1Up = false;  // Condition 1
            var bC1Dn = false;
            var bC2Up = false;  // Condition 2
            var bC2Dn = false;
            var bC3Up = false;  // Condition 3
            var bC3Dn = false;
            var bC4Up = false;  // Condition 4
            var bC4Dn = false;
            // Condition 1
            if (vEMA[0] > -2) {
                bC1Up = true;
            } else if (vEMA[0] < -2) {
                bC1Dn = true;
            }
            // Condition 2
            aVFItest3.pop();
            aVFItest3.unshift(vEMA[0]);
            var nLRangle = null;
            if (aVFItest3[19] != null) {
                nLRangle = LinearRegressionSlope(aVFItest3)/100;
                nLRangle = (Math.atan(nLRangle) / (Math.PI/180));
            }
            if (nLRangle != null) {
                if (nLRangle > 0) bC2Up = true;
                if (nLRangle < 0) bC2Dn = true;
            }
            // Condition 3
            if (vEMA[0] > vMAofEMA) bC3Up = true;
            if (vEMA[0] < vMAofEMA) bC3Dn = true;
            // Condition 4
            var LRS = null;
            aClose.pop();
            aClose.unshift(close());
            if (aClose[nLRlength3-1] != null) {
                LRS = LinearRegressionSlope(aClose);
                if (LRS < (0.006*aClose[nLRlength3-1]) && LRS > 0) bC4Up = true;
                if (LRS > (-0.006*aClose[nLRlength3-1]) && LRS < 0) bC4Dn = true;
            }
            if (Strategy.isInTrade() == false) {
                if (bC1Up == true && bC2Up == true && bC3Up == true && bC4Up == true) {  // Long entry
                    bLong = true;
                    vEntry = open(1);
                    Strategy.doLong("Long Break", Strategy.MARKET, Strategy.NEXTBAR, nLotSize);
                } else if (bC1Dn == true && bC2Dn == true && bC3Dn == true && bC4Up == true) {  // Short entry
                    bShort = true;
                    vEntry = open(1);
                    Strategy.doShort("Short Break", Strategy.MARKET, Strategy.NEXTBAR, nLotSize);
                }
            } else if (Strategy.isLong()) { // exit long
                if (nLRangle <= -40 || vEMA[0] < -2) {
                    nAccount += ( (open(1)-vEntry) * (Strategy.getPositionSize()) );
                    bExit = true;
                    Strategy.doSell("Exit Long", Strategy.MARKET, Strategy.NEXTBAR, Strategy.getPositionSize());
                }
            } else if (Strategy.isShort()) {  // exit short
                if (nLRangle >= 40 || vEMA[0] > -2) {
                    nAccount += ( (vEntry-open(1)) * (-Strategy.getPositionSize()) );
                    bExit = true;
                    Strategy.doCover("Exit Short", Strategy.MARKET, Strategy.NEXTBAR, Strategy.getPositionSize());
                }
            }
        }
        // Test 4
        if (nTestNum == 4) {
            aSMA.pop();
            aSMA.unshift(vEMA[0]);
            aLMA.pop();
            aLMA.unshift(vEMA[0]);
            if (aSMA[nSMAlength-1] != null) {
                vEMA[2] = EMA(2, vEMA[0], nSMAlength, aSMA);
            }
            if (aLMA[nLMAlength-1] != null) {
                vEMA[3] = EMA(3, vEMA[0], nLMAlength, aLMA);
            }
            if (vEMA[2] > vEMA[3] && vEMA1[2] < vEMA1[3] && Strategy.isLong() == false) { // long
                if (Strategy.isShort() == true) {
                    nAccount += ( (vEntry-open(1)) * (-Strategy.getPositionSize()) );
                    Strategy.doCover("Close Short", Strategy.MARKET, Strategy.NEXTBAR, Strategy.getPositionSize());
                    nLotSize = Math.floor(nAccount/open(1))
                }
                bLong = true;
                vEntry = open(1);
                Strategy.doLong("Crossing Up", Strategy.MARKET, Strategy.NEXTBAR, nLotSize);
            } else if (vEMA[2] < vEMA[3] && vEMA1[2] > vEMA1[3] && Strategy.isShort() == false) { // short
                if (Strategy.isLong() == true) {
                    nAccount += ( (open(1)-vEntry) * (Strategy.getPositionSize()) );
                    Strategy.doSell("Close Long", Strategy.MARKET, Strategy.NEXTBAR, Strategy.getPositionSize());
                    nLotSize = Math.floor(nAccount/open(1))
                }
                bShort = true;
                vEntry = open(1);
                Strategy.doShort("Crossing Down", Strategy.MARKET, Strategy.NEXTBAR, nLotSize);
            }
        }
    }
    // End of Back Testing

    if (nTestNum != 4) {
        return new Array(vEMA[0], vMAofEMA);
    } else {
        return new Array(vEMA[2], vEMA[3]);
    }
}



/*********************
**********************
****** Functions *****
**********************
**********************/

function StDev(nLength) {
    var sumX = 0;
    var sumX2 = 0;
    for (i = 0; i < nLength; ++i) {
        sumX += aTypPrice[i];
        sumX2 += (aTypPrice[i] * aTypPrice[i])
    }
    var meanX = (sumX/nLength);
    var stdev = Math.sqrt((sumX2/nLength) - (meanX*meanX));

    return stdev;
}

function EMA(nNum, nItem, nLength, aArray) {
    var nBarState = getBarState();
    var dSum = 0.0;

    if(nBarState == BARSTATE_ALLBARS || bPrimed[nNum] == false) {
        dPercent[nNum] = (2.0 / (nLength + 1.0));
        bPrimed[nNum] = false;
    }

    if (nBarState == BARSTATE_NEWBAR) {
        vEMA1[nNum] = vEMA[nNum];
    }

    if(bPrimed[nNum] == false) {
        for(i = 0; i < nLength; i++) {
            dSum += aArray[i];
        }
        bPrimed[nNum] = true;
        return (dSum / nLength);
    } else {
        return (((nItem - vEMA1[nNum]) * dPercent[nNum]) + vEMA1[nNum]);
    }
}

function Lowest() {
    var vLowVFI = VFI;
    for (var i = 0; i < aVFI.length; ++i) {
        if (aVFI[i] != null) {
            vLowVFI = Math.min(vLowVFI, aVFI[i]);
        }
    }
 
    return vLowVFI;
}

function LinearRegressionSlope(aArray, nLength) {
    var nIndex = getCurrentBarIndex();
    var i = 0;

    if (nLength == null) nLength = aArray.length;
 
    // y = Ax + B;
    // A = SUM( (x-xAVG)*(y-yAVG) ) / SUM( (x-xAVG)^2 )
    // A = slope
    // B = yAVG - (A*xAVG);
 
    if (aArray[nLength-1] != null) {
        var xSum = 0;
        var ySum = 0;
        i = 0;
        for (i = 0; i < nLength; ++i) {
            xSum += i;
            ySum += aArray[i];
        }
        var xAvg = xSum/nLength;
        var yAvg = ySum/nLength;
        var aSum1 = 0;
        var aSum2 = 0;
        i = 0;
        for (i = 0; i < nLength; ++i) {
            aSum1 += (i-xAvg) * (aArray[i]-yAvg);
            aSum2 += (i-xAvg)*(i-xAvg);
        }
        var A = (aSum1 / aSum2);
        var B = yAvg - (A*xAvg);
    }
 
    var vSlope = (-A.toFixed(8)*100);
 
    return vSlope;
--Jason Keck
eSignal, a division of Interactive Data Corp.
800 815-8256, www.eSignal.com


GO BACK


WEALTH-LAB: VFI PERFORMANCE

Last issue, Markos Katsanos introduced a long-term money flow indicator he calls the volume flow indicator (VFI). The VFI is based on the on-balance volume (OBV). In this month's article, Katsanos tests the indicator's performance in four strategies.

The weekly performance of Corning Inc. [GLW] in test 1 was quite impressive, although waiting weeks and weeks for the VFI to cross zero in order to exit a trade seemed to be a painfully long period to wait to collect sometimes very large profits. This lack of efficiency motivated the creation of a modified stop and reverse version of the zero-crossing methodology, to which we added yet another twist -- exiting a trade when VFI breaks its trend.

The VFI long & short ChartScript, which is available to run at the Wealth-Lab website, will enter a trade only when VFI crosses zero. However, it automatically attempts to find trends in VFI based on a major peak/trough occurring prior to entry and the next one after entry. A trendline value is projected from these peaks (when short) or troughs (when long) and when VFI crosses the trend, the position is exited. If a trend has not yet developed, then we simply exit and reverse when VFI crosses zero. Figure 4 demonstrates the technique.

FIGURE 4: WEALTH-LAB, VOLUME FLOW INDICATOR. The VFI long & short script reverses when VFI crosses zero and attempts to maximize gain by dynamically locating trends in VFI itself. The trendlines are drawn automatically.


The trend-break method (test 3 in the article) worked out quite well on Corning Inc. However, we noticed that this interpretation can prematurely exit other strongly trending stocks, and largely for this reason, we were inclined to heed Katsanos' advice about not using VFI as an overbought/oversold indicator to reverse the position.

Katsanos also reintroduced Michael Harris's profitability metric. Though Wealth-Lab is complete with scores of standard metrics, this particular measure of profitability is not one of them. However, in WLB 3.0, you can add any metric that you wish to the Performance report by programming it in a PerfScript, of which the result can be seen in Figure 5.

FIGURE 5: WEALTH-LAB, VOLUME FLOW INDICATOR. Wealth-Lab's standard Performance report is replete with metrics, and you can even add your own using Performance Scripts, as we have done with "Profitability."
Here is the WealthScript code:
{ VFI Long & Short ChartScript }
{$I 'VFI'}
const UseTrend = true;  // Use 'false' for zero crossings only
const SwingPts = 4;
var Bar, StartBar, p, VFIema, VFIPane, EntryBar, PTBar1, PTBar2: integer;
var Projected: float;
var Found, bLongSAR: boolean;
{ PeakSupport/TroughSupport find the peaks/trough for the trend line }
procedure TroughSupport( Bar, EntryBar, TestSer: integer );
begin
  PTBar1 := TroughBar( EntryBar, TestSer, SwingPts );
  PTBar2 := TroughBar( Bar, TestSer, SwingPts );
  Found := PTBar2 <> PTBar1;
end;
procedure PeakSupport( Bar, EntryBar, TestSer: integer );
begin
  PTBar1 := PeakBar( EntryBar, TestSer, SwingPts );
  PTBar2 := PeakBar( Bar, TestSer, SwingPts );
  Found := PTBar2 <> PTBar1;
end;
{ This exit routine also resets variables and draws the VFI trend line }
procedure ExitTrade( Bar, p, Color: integer; IsLong: boolean; SignalName: string );
begin
  Found := false;
  SetBackgroundColor( Bar, Color );
  if SignalName = 'TrendX' then
    DrawLine( PTBar1, @VFIema[PTBar1], Bar, @VFIema[Bar], VFIPane, #Red, #Thin );
  if IsLong then
    SellAtMarket( Bar + 1, p, SignalName )
  else
    CoverAtMarket( Bar + 1, p, SignalName );
end;
{ Script execution begins here }
SetPeakTroughMode( #AsPoint );
UseUpdatedEMA( true );
if IsWeekly then
begin
  VFIema := EMASeries( VFISeries( 26, 3, 0.2, 2.5 ), 7 );
  StartBar := 89;
end else
begin
  VFIema := EMASeries( VFISeries( 130, 3, 0.2, 2.5 ), 40 );
  StartBar := 300;
end;
VFIPane := CreatePane( 125, false, true );
PlotSeriesLabel( VFIema, VFIPane, #Teal, #Thick, 'EMA(VFI)' );
DrawHorzLine( 0, VFIPane, #Black, #Dotted );
for Bar := StartBar to BarCount - 1 do
begin
  if LastPositionActive then  { Exit Rules }
  begin
    p := LastPosition;
    bLongSAR := PositionLong( p );
    EntryBar := PositionEntryBar( p );
  { Exit on zero-crossing or trend break, whichever is first }
    if bLongSAR then
    begin
      if not Found then
        TroughSupport( Bar, EntryBar, VFIema );
      if CrossUnderValue( Bar, VFIema, 0 ) then
        ExitTrade( Bar, p, #RedBkg, bLongSAR, 'ZeroX' )
      else if Found and UseTrend then
      begin
        Projected := LineExtendY( PTBar1, @VFIema[PTBar1], PTBar2, @VFIema[PTBar2], Bar );
        if @VFIema[Bar] < Projected then
          ExitTrade( Bar, p, #BlueBkg, bLongSAR, 'TrendX' );
      end;
    end
    else
    begin
      if not Found then
        PeakSupport( Bar, EntryBar, VFIema );
      if CrossOverValue( Bar, VFIema, 0 ) then
        ExitTrade( Bar, p, #RedBkg, bLongSAR, 'ZeroX' )
      else if Found and UseTrend then
      begin
        Projected := LineExtendY( PTBar1, @VFIema[PTBar1], PTBar2, @VFIema[PTBar2], Bar );
        if @VFIema[Bar] > Projected then
          ExitTrade( Bar, p, #BlueBkg, bLongSAR, 'TrendX' );
      end;
    end;
  end;
{ Entry logic }
  if not bLongSAR then
    if CrossOverValue( Bar, VFIema, 0 ) then
      BuyAtMarket( Bar + 1, '' );
  if bLongSAR then
    if CrossUnderValue( Bar, VFIema, 0 ) then
      ShortAtMarket( Bar + 1, '' );
end;


 -- Robert Sucher, Wealth-Lab, Inc.
www.wealth-lab.com


GO BACK


TRADINGSOLUTIONS: VFI PERFORMANCE

In his article "Volume Flow Indicator Performance," Markos Katsanos presents several entry/exit systems for testing the performance of the volume flow indicator, which he introduced in the June 2004 issue.

As a reminder, the calculation of the volume flow indicator (VFI) is as follows:
 

Name: Volume Flow Indicator
Short Name: VFI
Inputs: Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff
Formula:
EMA (Div (Sum (If (GT (Abs (Change (Typical (Close,High,Low),1)), Mult3 (0.2, StDev
 (Change (Ln (Typical (Close, High, Low)),1),30), Close)), Mult (Min (Volume, Mult
 (Lag (MA (Volume, Period for VFI),1), Maximum Volume Cutoff)), Sign (Change (Typical
 (Close, High, Low),1))),0), Period for VFI), Lag (MA (Volume, Period for VFI),1)),3)


This month's article introduces a new indicator, the divergence LRS indicator. A subvalue of this, called LRSI, is also used directly from entry/exit systems. Here is the calculation of these indicators:
 

Name: Lowest From Beginning
Short Name: LowestFB
Inputs: Value
Formula:
If (IsNull (Lag (Value, 1)), Value, Min (Value, Prev (1)))
Name: VFI LRS Indicator
Short Name: VFILRSI
Inputs: Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff, Days for Divergence
Formula:
Mult (Div (Slope (Add3 (VFI (Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff),
 Abs (LowestFB (VFI (Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff))), 10),
 Days for Divergence), Abs (Lag (Add3 (VFI (Close, High, Low, Volume, Period for VFI,
 Maximum Volume Cutoff), Abs (LowestFB (VFI (Close, High, Low, Volume, Period for VFI,
 Maximum Volume Cutoff))), 10), Days for Divergence))), 100)
Name: Divergence LRS Indicator
Short Name: Diverg
Inputs: Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff, Days for Divergence
Formula:
Mult (EMA (Sub (VFILRSI (Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff,
 Days for Divergence), Mult (Div (Slope (Close, Days for Divergence), Abs (Lag (Close,
 Days for Divergence))), 100)), 3), 100)


Katsanos' article introduces four different entry/exit systems for testing the viability of the VFI and comparing it to on-balance volume (OBV).
 

Name: VFI Test1. VFI>0
Inputs: Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff
Enter Long:
1. GT(EMA(VFI (Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff), 7, 0)
Exit Long:
1. LT(EMA(VFI (Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff), 7, 0)
Name: VFI Test2. Divergence
Inputs: Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff, Days for Divergence
Enter Long (when ALL true):
1. GT(Lag(Diverg(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff,
      Days for Divergence), 1), 100)
2. LT(Diverg(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff,
      Days for Divergence), Lag(Diverg(Close, High, Low, Volume, Period for VFI,
      Maximum Volume Cutoff, Days for Divergence), 1)
3. GT(VFILRSI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff,
      Days for Divergence), 0)
Exit Long (when ANY true):
1. LT(Diverg(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff,
      Days for Divergence), 0)
2. LT(VFILRSI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff,
      Days for Divergence), 0)
Name: VFI Test3. Break from base (VFI)
Inputs: Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff
Enter Long (when ALL true):
1. GT(VFI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff), -2)
2. GT(Slope(VFI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff), 20), 0.1)
3. GT(VFI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff),
      EMA(VFI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff), 40))
4. LT(Slope(Close, 30), Div(Mult(Lag(Close, 30), 0.6), 100))
5. GT(Slope(Close, 30)
Exit Long (when ANY true):
1. LT(VFI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff), -2)
2. LT(Slope(VFI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff), 20), -0.8)
Name: VFI Test3. Break from base (OBV)
Inputs: Close, Volume
Enter Long (when ALL true):
1. GT(Slope(OBV(Close, Volume), 20), 0.1)
2. GT(OBV(Close, Volume), EMA(OBV(Close, Volume), 40))
3. LT(Slope(Close, 30), Div(Mult(Lag(Close, 30), 0.6), 100))
4. GT(Slope(Close, 30)
Exit Long (when ANY true):
1. LT(Slope(OBV(Close, Volume), 20), -0.8)
Name: VFI Test4. MA crossover
Inputs: Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff,
        Short EMA Period, Long EMA Period
Enter Long:
1. CrossAbove(EMA(VFI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff),
      Short EMA Period), EMA(VFI(Close, High, Low, Volume, Period for VFI,
      Maximum Volume Cutoff), Long EMA Period))
Exit Long:
1. CrossAbove(EMA(VFI(Close, High, Low, Volume, Period for VFI, Maximum Volume Cutoff),
      Long EMA Period), EMA(VFI(Close, High, Low, Volume, Period for VFI,
      Maximum Volume Cutoff), Short EMA Period))


These functions are available in a function file that can be downloaded from the TradingSolutions website (www.tradingsolutions.com) in the Solution Library section. As with many indicators, indicators and systems such as these can make good inputs to neural network predictions.

--Gary Geniesse
NeuroDimension, Inc.
800 634-3327, 352 377-5144
https://www.tradingsolutions.com


GO BACK


NEUROSHELL TRADER: VFI PERFORMANCE

The trading systems described by Markos Katsanos in "Volume Flow Indicator Performance" are easily implemented in NeuroShell Trader. It should be noted that these systems use the VFI custom indicator, which was described in last month's Traders' Tips.

Test 1: indicator level
To recreate the first test -- the indicator level trading system -- for the volume flow indicator in NeuroShell Trader, select "New Trading Strategy ..." from the Insert menu and enter the following long entry and exit conditions in the appropriate locations of the Trading Strategy Wizard:
 

Generate a buy long MARKET order if ALL of the following are true:
CrossAbove ( ExpAvg ( VFI, 7), 0)
Generate a sell long MARKET order if ALL of the following are true:
CrossBelow ( ExpAvg ( VFI, 7), 0)


Test 2: divergence
To implement the second test--the divergence trading system--in NeuroShell Trader, you should first create the divergence indicator in a chart and then create a Trading Strategy based on that indicator and its components. To recreate the divergence indicator, select "New Indicator ..." from the Insert menu and use the Indicator Wizard to create each of the following:
 

LRS:
     Divide ( LinRegSlope ( Close, 120 ), Lag ( Close, 120 ) )
LRSI:
     Divide ( LinRegSlope ( VFI, 120 ), Lag ( VFI, 120 ) )
DIVERGENCE:
     Multiply2 ( ExpAvg ( Subtract ( LRSI, LRS ), 3 ), 100 )


To recreate the divergence trading system test for the volume flow indicator in NeuroShell Trader, select "New Trading Strategy ..." from the Insert menu and enter the following long entry and exit conditions in the appropriate locations of the Trading Strategy Wizard:
 

Generate a buy long MARKET order if ALL of the following are true:
A>B ( Lag ( DIVERGENCE, 1 ), 100 )
A<B ( DIVERGENCE, Lag ( DIVERGENCE, 1 ) )
A>B ( LRSI, 0 )
Generate a sell long MARKET order if ONE of the following are true:
A<B ( DIVERGENCE, 0 )
A<B ( LRSI, 0 )


Test 3: Break from base
To recreate the third test -- the break from base trading system -- for the volume flow indicator in NeuroShell Trader, select "New Trading Strategy ..." from the Insert menu and enter the following long entry and exit conditions in the appropriate locations of the Trading Strategy Wizard:
 

Generate a buy long MARKET order if ALL of the following are true:
A>B ( VFI, -2 )
A>B ( LinRegSlope ( VFI, 20 ), 0.1 )
A>B ( VFI, ExpAvg ( VFI, 40 ) )
A<B ( LinRegSlope ( Close, 30 ), Multiply ( 0.006, Lag ( Close, 30 ) ) )
A>B ( LinRegSlope ( Close, 30 ), 0 )
Generate a sell long MARKET order if ONE of the following are true:
A<B ( LinRegSlope (VFI, 20), -0.8 )
A<B ( VFI, -2 )


Test 4: Indicator direction
To recreate test 4 -- the indicator direction trading system -- for the volume flow indicator in NeuroShell Trader, select "New Trading Strategy ..." from the Insert menu and enter the following long entry and exit conditions in the appropriate locations of the Trading Strategy Wizard:
 

Generate a buy long MARKET order if ALL of the following are true:
ExpAvgCrossAbove (VFI, 11, 25 ) )
Generate a sell long MARKET order if ALL of the following are true:
ExpAvgCrossBelow (VFI, 11, 25 ) )


Users of NeuroShell Trader can go to the STOCKS & COMMODITIES section of the NeuroShell Trader free technical support website to download a sample chart that includes the volume flow custom indicator (Figure 6).

FIGURE 6: NEUROSHELL TRADER, VOLUME FLOW INDICATOR. Here's a sample chart in NeuroShell Trader displaying all four trading strategies discussed by Markos Katsanos in his article this issue. The techniques implement the volume flow indicator.

 
--Marge Sherald, Ward Systems Group, Inc.
301 662-7950, sales@wardsystems.com
www.neuroshell.com


GO BACK


NEOTICKER: VFI PERFORMANCE

The NeoTicker Backtest EZ power indicator will allow users to implement the four testing systems presented in "Volume Flow Indicator Performance" by Markos Katsanos in this issue, with just a few lines of formula.

Test 1: Indicator level
The first test requires no additional indicator programming. To start the test, first add the Backtest EZ indicator to the weekly data series. At the "Add indicator" window in Long Entry and Long Exit field, enter the corresponding formula (Listing 1). At the "System" tab, change initial capital, interest, commission, and testing date range according to the article's criteria. After all the information is filled in, press Apply at the "Add indicator" window to start the system calculation. After the calculation is completed, NeoTicker Backtest EZ plots the equity curve of the VFI crossover zero system (Figure 7). Right-click on this equity curve to access the NeoTicker built-in system statistic report presented in the System Performance Viewer.
 


FIGURE 7: NEOTICKER, VOLUME FLOW INDICATOR. After the calculation is completed, NeoTicker Backtest EZ plots the equity curve of the VFI crossover zero system.


Test 2: Divergence
This test requires an additional indicator called the divergence LRS indicator (Listing 2). This indicator returns two plots. This indicator has one integer parameter, divergence period. The first plot is divergence; the second plot is LRSI. These two values are returned because the divergence system requires these two calculations.

After the divergence LRS indicator is verified and installed, the next step is to add the Backtest EZ indicator on a daily data series. At the Long Entry and Long Exit field, type in the corresponding formulas (Listing 3), set all other settings according to the criteria in the article, and hit Apply to get the system testing results (Figure 8).

FIGURE 8: NEOTICKER, VOLUME FLOW INDICATOR. Hit Apply to get the system testing results.
Test 3: Break from base (indicator direction and level)
This test can be done simply with the standard VFI indicator along with formula code in the Backtest EZ Long Entry and Long Exit fields (Listing 4). When adding Backtest EZ, fill in the entry and exit rule and set the system setting according to the article to get the system results (Figure 9).

FIGURE 9: NEOTICKER, VOLUME FLOW INDICATOR. When adding Backtest EZ, fill in the entry and exit rule and set the system setting according to the article to get the system results.


Test 4: Indicator direction
The last test can be done with the standard VFI indicator and formula code in the Backtest EZ entry and exit field (Listing 5). Complete the remaining settings in the system tab, and hit Apply to get the testing result.
 

Listing 1
Long Entry: xaboveconst(VFI.Plot2(0,data1,26,0.2,2.5,7),0)
Long Exit: xbelowconst(VFI.Plot2(0,data1,26,0.2,2.5,7),0)
Listing 2
$D1 := if(param1 > 200, 200, if(param1 < 2, 2, param1));
P1 := VFI(0,data1,130,0.2,2.5,3) +
      absvalue(lowest(VFI(0,data1,130,0.2,2.5,3))) + 10;
LRSI := linslope(0,P1,$D1)/absvalue(P1($D1))*100;
LRS  := linslope(0,data1,$D1)/absvalue(data1($D1))*100;
myDiverg := (LRSI-LRS);
plot1 := qc_xaverage(myDiverg, 3)*100;
plot2 := LRSI;
Listing 3
Long Entry: (diverg(1,data1,120)>100) and (diverg(0,data1,120)<diverg(1,data1,120))
 and (diverg.Plot2(0,data1,120)>0)
Long Exit: (diverg(0,data1,120)<0) and (diverg.Plot2(0,data1,120)<0)
Listing 4
Long Entry: (VFI(0,data1,130,0.2,2.5,3) > -2)
 and (linslope(VFI(0,data1,130,0.2,2.5,3),20)>0.1)
 and (VFI(0,data1,130,0.2,2.5,3)>qc_xaverage(VFI(0,data1,130,0.2,2.5,3),40))
 and (linslope(c,30)<(c(30)*0.6/100)) and (linslope(c,30)>0)
Long Exit: (VFI(0,data1,130,0.2,2.5,3) < -2) or
(linslope(VFI(0,data1,130,0.2,2.5,3),20) < -0.8)
Listing 5
Long Entry: xabove (qc_xaverage (VFI(0,data1,130,0.2,2.5,3), 11),
 qc_xaverage (VFI(0,data1,130,0.2,2.5,3), 25))
Long Exit: xbelow (qc_xaverage (VFI(0,data1,130,0.2,2.5,3), 11),
 average (VFI(0,data1,130,0.2,2.5,3), 25))


A package file that contains a group of charts showing all four testing Backtest EZ indicators along with the formula language indicators will be available for download from TickQuest's website as well as the Yahoo! NeoTicker user group file area at https://groups.yahoo.com/group/neoticker/.

--Kenneth Yuen, TickQuest Inc.
www.tickquest.com


GO BACK


STOCKWIZ: VFI PERFORMANCE

Here is the StockWiz formula for backtesting the volume flow indicator (VFI). This formula is based on test 4 in Markos Katsanos' article in this issue, "Volume Flow Indicator Performance."

The program tests all the companies in your working group. The formula calculates the 15- and 80-day simple moving averages of the volume flow indicator for each company and issues buy signals (if the 15-day SMA rises above the 80-day SMA) and sell signals (if the 15-day SMA falls below the 80-day SMA).

We start with the first 300 prices and then we move forward the time frame under study two weeks or 10 business days at a time. For each time frame, we check our system and buy or sell the current company based on the trading rules discussed in the previous paragraph.
 
 

(CLEAR)
(GRIDFIELD "Ticker" "STRING" "10")
(GRIDFIELD "Name"  "STRING" "20")
(GRIDFIELD "StartingAmount" "FLOAT" "0")
(GRIDFIELD "EndingAmount"  "FLOAT" "0")
(GRIDFIELD "NumOfTrades"   "FLOAT" "0")
(GRIDFIELD "VFIsystemPerformance" "FLOAT" "0")
(GRIDFIELD "BuyHoldPerformance"   "FLOAT" "0")
# Load the first company in the worksheet
(SOURCE "WORKING_GROUP")
(SET I 0)
(SET STATUS (LOADFIRST))
(GOTO %TOP  (EQ STATUS 0))
(GOTO %ERROR (TRUE))
# Load data for the current company
%TOP:
(SET HIGH      (GETVECTOR (CURRENT) "HIGH"))
(SET LOW       (GETVECTOR (CURRENT) "LOW"))
(SET CLOSE    (GETVECTOR (CURRENT) "CLOSE"))
(SET VOLUME (GETVECTOR (CURRENT) "VOLUME"))
# We start trading each company with $10,000 in cash.
# Fees are $10 per trade.
(SET PRINCIPAL 10000.0)
(SET CASH PRINCIPAL)
(SET SHARES 0.0)
(SET COMMISSION 0.0)
(SET TRADES 0.0)
(SET VALUE 0.0)
(SET COSTPERTRADE 10.0)
# Skip over this company if not enough data is available
(SET LASTDATE (LASTDATE))
(GOTO %NEXT (ISVNA CLOSE))
(GOTO %NEXT (LT (VSIZE CLOSE) 300))
(GOTO %NEXT (BADDATA CLOSE LASTDATE))
(GOTO %EXIT (ESCAPE))
# Calculate the Volume Flow Indicator
(SET TP0 (EVAL CLOSE "(High(i)+Low(i)+Close(i))/3.0"))
(SET TP_current (EVAL CLOSE "(LOG TP0(i))"))
(SET TP1 (EVAL CLOSE "(High(i-1)+Low(i-1)+Close(i-1))/3.0"))
(SET TP_previous (EVAL CLOSE "(LOG TP1(i))"))
(SET TPL (VSUB TP_current TP_previous))
(SET CUT (VSMUL CLOSE (STDDEV TPL)))
(SET CUTOFF (VSMUL CUT 0.2))
(SET TP_chg (VSUB TP0 TP1))
(SET D (VSIZE CLOSE))
%AGAIN1:
(SET T (VSIZE TP_chg))
(SET T (SUB T D))
(SET TP_chg-i (VGET TP_chg T))
(SET C (VSIZE CUTOFF))
(SET C (SUB C D))
(SET CUTOFF-i (VGET CUTOFF C))
(GOTO %STEP1 (GT TP_chg-i CUTOFF-i))
(GOTO %STEP2 (LT TP_chg-i CUTOFF-i))
(GOTO %STEP3 (EQ TP_chg-i CUTOFF-i))
%STEP1: (SET VOL VOLUME)
              (GOTO %AGAIN2 (TRUE))
%STEP2: (SET VOL (VSMUL VOLUME -1.0))
              (GOTO %AGAIN2 (TRUE))
%STEP3: (SET VOL (VSMUL VOLUME 0.0))
              (GOTO %AGAIN2 (TRUE))
%AGAIN2:
(SET D (SUB D 1))
(GOTO %AGAIN1 (GT D 0.0))
(GOTO %SUM     (EQ D 0.0))
%SUM:
(SET isize (VSIZE VOL))
(SET i 1)
(SET VLM CLOSE)
%AGAIN:
(VSET VLM i (ADD (VGET VLM (SUB i 1)) (VGET VOL i)))
(SET i (ADD i 1))
(GOTO %AGAIN (LT i isize))
(SET VOL_MA (SHIFTR (MOVAVG VOLUME 50) 1))
(SET VFI (EMOVAVG (VDIV VLM VOL_MA) 3))
# Load the first range for the working vector. We check the
# VFI data for the first 300 trading days.
(SET R1 (BEGDATE CLOSE))
(SET R2 (DATEBADD R1 300))
%NEXTD:
(SET R1 (DATEBSUB R2 300))
(SET WV (VEC2VEC CLOSE R1 R2))
(SET VFI-N (VEC2VEC VFI R1 R2))
# Show a progress report to the user
(SET LASTCLOSE (LAST WV))
(SET VALUE (MUL SHARES LASTCLOSE))
(SET TOTAL (ADD CASH VALUE))
(SET TICKER (CURRENT))
(SET MESSAGE TICKER)
(STATUSBAR 1 MESSAGE)
(GOTO %EXIT (ESCAPE))
# The trading rules: buy shares when the 15-day SMA of the
# VFI is above the 80-day SMA and sell when the opposite
# condition exists.
(SET SMA15 (MOVAVG VFI-N 15))
(SET LAST_SMA15 (LAST SMA15))
(SET SMA80 (MOVAVG VFI-N 80))
(SET LAST_SMA80 (LAST SMA80))
(GOTO %BUY  (GT LAST_SMA15 LAST_SMA80))
(GOTO %SELL (LE LAST_SMA15 LAST_SMA80))
(GOTO %SHIFT (TRUE))
# Buy trade
%BUY:
(GOTO %SHIFT (LE CASH LASTCLOSE))
(SET SHARESTOBUY (DIV CASH LASTCLOSE))
(SET SHARES (ADD SHARES SHARESTOBUY))
(SET TRADES (ADD TRADES 1))
(SET COMMISSION (ADD COMMISSION COSTPERTRADE))
(SET CASH (SUB CASH COMMISSION))
(SET CASH 0.0)
(GOTO %SHIFT (TRUE))
# Sell trade
%SELL:
(GOTO %SHIFT (LE SHARES 0.0))
(SET TRADES (ADD TRADES 1))
(SET COMMISSION (ADD COMMISSION COSTPERTRADE))
(SET COST (MUL LASTCLOSE SHARES))
(SET CASH (SUB CASH COMMISSION))
(SET CASH (ADD CASH COST))
(SET SHARES 0.0)
(GOTO %SHIFT (TRUE))
# Add two weeks (ten business days) to our working range
%SHIFT:
(SET R2 (DATEBADD R2 10))
(SET POINTS (BDAYS (BEGDATE CLOSE) R2))
(GOTO %NEXTD (LE POINTS (VSIZE CLOSE)))
# Write the output data to the columns in the worksheet
(GRID TICKER "Name" (GETSTRING "NAME"))
(GRID TICKER "StartingAmount" (DBL2STR PRINCIPAL 0))
(GRID TICKER "EndingAmount" (DBL2STR TOTAL 0))
(GRID TICKER "NumOfTrades" (DBL2STR TRADES 0))
(SET PL1 (PERCENT TOTAL PRINCIPAL))
(SET P-L  (SUB PL1 100.0))
(GRID TICKER "VFIsystemPerformance" (DBL2STR P-L 2))
(SET INITIAL (VGET CLOSE 0))
(GOTO %NEXT (EQ INITIAL 0.0))
(SET LC (VSIZE CLOSE))
(SET LC (SUB LC 1))
(SET LASTCL (VGET CLOSE LC))
(SET BH (DIV LASTCL INITIAL))
(SET BH (SUB BH 1))
(SET B-H (MUL BH 100))
(GRID TICKER "BuyHoldPerformance" (DBL2STR B-H 2))
# Exit the program if the user clicks on the 'Cancel' button
(GOTO %EXIT (ESCAPE))
# Load the next company in the worksheet
%NEXT:
(SET STATUS (LOADNEXT))
(SET I (ADD I 1))
(GOTO %TOP (EQ STATUS 0))
%ERROR: (MESSAGE "An error has occurred - Unable to continue")
%EXIT:     (EXIT STATUS)
--Steve Kalhas
StockWiz.com
GO BACK


TECHNIFILTER PLUS: VFI PERFORMANCE

Here are the TechniFilter Plus formulas discussed in "Volume Flow Indicator Performance" by Markos Katsanos.

To use different time periods, simply change the parameter as required.
 

NAME: VFI
SWITCHES: multiline
PARAMETERS: .2,130,2.5
FORMULA:
[1]: (H+L+C)/3  {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1  {INTER}
[3]: [2]|30   {VINTER}
[4]: &1*[3]*C   {CUTOFF}
[5]: VA&2Y1   {VAVE}
[6]: [5]*&3   {VMAX}
[7]: IF_THEN(V<[6],V,[6]) {VC}
[8]: [1]-[1]Y1   {MF}
[9]: -[4]   {-CUTOFF}
[10]: (([8]>[4])*([7]))+((1-([8]>[4]))*((([8]<[9])*((-[7])))+((1-([8]<[9]))*(0))))
[11]: ([10]F&2)/[5]
[12]: [11]X3   {VFI}
NAME: VFI_colour_Volume
SWITCHES: multiline
PARAMETERS: .2,50,2.5
FORMULA:
[1]: (H+L+C)/3  {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1  {INTER}
[3]: [2]|30   {VINTER}
[4]: &1*[3]*C   {CUTOFF}
[5]: VA&2Y1   {VAVE}
[6]: [5]*&3   {VMAX}
[7]: IF_THEN(V<[6],V,[6]) {VC}
[8]: [1]-[1]Y1   {MF}
[9]: -[4]   {-CUTOFF}
[10]: (IF_THEN([8]>[4],[7],-1))u2*V {c}{nc}{h}  {rgb#32768} {Colour Green }
[11]: (IF_THEN([8]<[9],[7],-1))u2*V {c}{h}  {rgb#255} {Colour Red}
[12]: (IF_THEN([8]<[4] & [8]>[9],[7],-1))u2*V {c}{h}  {rgb#16711680} {Colour Blue}
{This formulas colours all the bars simultaneously}
VFI_BreakfromBase system
TEST TYPE: equal
DATE RANGE: all
POSITION LIMIT: none
ENTRY FEE: 33
EXIT FEE: 33
INITIAL INVESTMENT: 10000
FORMULAS
[1] Date
[2] VFI Buy(.2,130,2.5,120)
[1]: (H+L+C)/3  {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1  {INTER}
[3]: [2]|30   {VINTER}
[4]: &1*[3]*C   {CUTOFF}
[5]: VA&2Y1   {VAVE}
[6]: [5]*&3   {VMAX}
[7]: IF_THEN(V<[6],V,[6]) {VC}
[8]: [1]-[1]Y1   {MF}
[9]: -[4]   {-CUTOFF}
[10]:  (([8]>[4])*([7]))+((1-([8]>[4]))*((([8]<[9])*((-[7])))+((1-([8]<[9]))*(0))))
[11]: ([10]F&2)/[5]
[12]: [11]X3   {VFI}
[13]: [12]d20
[14]: [12]x40
[15]: cd30 < cy30 *.6 /100 & CD30 >0
[16]: [12]>-2 &[13]>.1 & [12]>[14]  & [15]=1
[3] VFI Sell(.2,130,2.5,120)
[1]: (H+L+C)/3  {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1  {INTER}
[3]: [2]|30   {VINTER}
[4]: &1*[3]*C   {CUTOFF}
[5]: VA&2Y1   {VAVE}
[6]: [5]*&3   {VMAX}
[7]: IF_THEN(V<[6],V,[6]) {VC}
[8]: [1]-[1]Y1   {MF}
[9]: -[4]   {-CUTOFF}
[10]:  (([8]>[4])*([7]))+((1-([8]>[4]))*((([8]<[9])*((-[7])))+((1-([8]<[9]))*(0))))
[11]: ([10]F&2)/[5]
[12]: [11]X3   {VFI}
[13]: [12]d20
[14]: [12] < -2  ^ [13]< -.8
RULES--------

  r1: Buy
buy long all on Close
at signal: Buy     [2] = 1 & shares=0 & CurrentIndex >= 300
  r2: Sell
stop long all on Close
at signal: Stop     [3] = 1
Scanning the market for VFI signals
The following Market Scan (TechniFilter filter report) can be used to filter out (screen) stocks using the various VFI signals used in the trading strategies in Katsanos' article. This report includes all the formulas used, and includes both daily and weekly formulas.
 


 
FIGURE 10: BREAK FROM BASE. Arrows painted from the strategy test indicate buys and sells. The color of the volume bars is based on the VFI signals.
NAME: VFI Signals
UNITS TO READ: 999
FORMULAS
[1] Symbol
[2] Closing Price
       c
[3] VFIDivgLRSUp(.2,130,2.5,120)
 [1]: (H+L+C)/3   {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1   {INTER}
[3]: [2]|30    {VINTER}
[4]: &1*[3]*C    {CUTOFF}
[5]: VA&2Y1    {VAVE}
[6]: [5]*&3    {VMAX}
[7]: IF_THEN(V<[6],V,[6])  {VC}
[8]: [1]-[1]Y1    {MF}
[9]: -[4]    {-CUTOFF}
[10]:  (([8]>[4])*([7]))+((1-([8]>[4]))*((([8]<[9])*((-[7])))+((1-([8]<[9]))*(0))))
[11]: ([10]F&2)/[5]
[12]: [11]X3    {VFI}
[13]: Cu13
[14]: [12] + (([12]n[13])u0)+10 {P1}
[15]: [14]d&4 /([14]Y&4)u0 * 100 {LRSI}
[16]: Cd&4 /CY&4u0 * 100  {LRS}
[17]: [15]-[16]    {DIVERG}
[18]: [17]X3*100
[19]: ([18]y1 > 100) & ([18]< [18]y1) & [15]>0
[4] VFIDivgLRSDn(.2,130,2.5,120)
[1]: (H+L+C)/3   {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1   {INTER}
[3]: [2]|30    {VINTER}
[4]: &1*[3]*C    {CUTOFF}
[5]: VA&2Y1    {VAVE}
[6]: [5]*&3    {VMAX}
[7]: IF_THEN(V<[6],V,[6])  {VC}
[8]: [1]-[1]Y1    {MF}
[9]: -[4]    {-CUTOFF}
[10]:  (([8]>[4])*([7]))+((1-([8]>[4]))*((([8]<[9])*((-[7])))+((1-([8]<[9]))*(0))))
[11]: ([10]F&2)/[5]
[12]: [11]X3    {VFI}
[13]: Cu13
[14]: [12] + (([12]n[13])u0)+10 {P1}
[15]: [14]d&4 /([14]Y&4)u0 * 100 {LRSI}
[16]: Cd&4 /CY&4u0 * 100  {LRS}
[17]: [15]-[16]    {DIVERG}
[18]: [17]X3*100
[19]: ([17]<0) ^ [15]<0
[5] VFIBrkFrmBaseUP(.2,130,2.5,120)
[1]: (H+L+C)/3  {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1  {INTER}
[3]: [2]|30   {VINTER}
[4]: &1*[3]*C   {CUTOFF}
[5]: VA&2Y1   {VAVE}
[6]: [5]*&3   {VMAX}
[7]: IF_THEN(V<[6],V,[6]) {VC}
[8]: [1]-[1]Y1   {MF}
[9]: -[4]   {-CUTOFF}
[10]:  (([8]>[4])*([7]))+((1-([8]>[4]))*((([8]<[9])*((-[7])))+((1-
         ([8]<[9]))*(0))))
[11]: ([10]F&2)/[5]
[12]: [11]X3   {VFI}
[13]: [12]d20
[14]: [12]x40
[15]: cd30 < cy30 *.6 /100 & CD30 >0
[16]: [12]>-2 &[13]>.1 & [12]>[14]  & [15]=1
[6] VFIBrkFrmBaseDn(.2,130,2.5,120)
[1]: (H+L+C)/3  {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1  {INTER}
[3]: [2]|30   {VINTER}
[4]: &1*[3]*C[5]: VA&2Y1   {VAVE}
[6]: [5]*&3   {VMAX}
[7]: IF_THEN(V<[6],V,[6]) {VC}
[8]: [1]-[1]Y1   {MF}
[9]: -[4]   {-CUTOFF}
[10]:  (([8]>[4])*([7]))+((1-([8]>[4]))*((([8]<[9])*((-[7])))+((1-([8]<[9]))*(0))))
[11]: ([10]F&2)/[5]
[12]: [11]X3   {VFI}
[13]: [12]d20
[14]: [12] < -2  ^ [13]< -.8
 [7] VFIMACrossover(.2,130,2.5,11,25)
[1]: (H+L+C)/3  {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1  {INTER}
[3]: [2]|30   {VINTER}
[4]: &1*[3]*C   {CUTOFF}
[5]: VA&2Y1   {VAVE}
[6]: [5]*&3   {VMAX}
[7]: IF_THEN(V<[6],V,[6]) {VC}
[8]: [1]-[1]Y1   {MF}
[9]: -[4]   {-CUTOFF}
[10]:  (([8]>[4])*([7]))+((1-([8]>[4]))*((([8]<[9])*((-[7])))+((1-([8]<[9]))*(0))))
[11]: ([10]F&2)/[5]
[12]: [11]X3   {VFI}
[13]: [12]x&4   {SMA}
[14]: [12]x&5   {LMA}
[15]: ([13]-[14])U2-Ty1
   {CUTOFF}
 [8] VFICrs0(.2,26,2.5)
[1]: (H+L+C)/3  {TYPICAL PRICE}
[2]: [1]u9-[1]u9y1  {INTER}
[3]: [2]|30   {VINTER}
[4]: &1*[3]*C   {CUTOFF}
[5]: VA&2Y1   {VAVE}
[6]: [5]*&3   {VMAX}
[7]: IF_THEN(V<[6],V,[6]) {VC}
[8]: [1]-[1]Y1   {MF}
[9]: -[4]   {-CUTOFF}
[10]:
(([8]>[4])*([7]))+((1-([8]>[4]))*((([8]<[9])*((-[7])))+((1-([8]<[9]))*(0))))
[11]: ([10]F&2)/[5]   {VFI}
[12]: [11]X3X7
[13]: ([12]-0)U2-Ty1
FILTERS
       [1] VFIDivergUp  [3] = 1
       [2] VFIDivergDn  [4] = 1
       [3] VFIBreakUPUpBase  [5]=1
       [4] VFIBreakUPDNBase  [6]=1
       [5] VFIMACrossUp  [7] = 1
       [6] VFIMACrossDn  [7] = -1
       [7] VFIZeroCrossUp  [8] = 1
       [8] VFIZeroCrossDn  [8] = -1


Visit the home of Technifilter Plus at www.technifilter.com to download these formulas, filter reports, and the other three trading strategies discussed in the article: VFI MA crossover, VFI break above zero, and VFI divergence.

--Benzie Pikoos, Brightspark
+61 8 9375-1178 , sales@technifilter.com
www.technifilter.com


GO BACK


All rights reserved. © Copyright 2004, Technical Analysis, Inc.


Return to July 2004 Contents