Test Methodology

Fibo Quantum Scalper Magic

Forex Scalping Strategies

Get Instant Access

All the tests that follow were performed using oscillator entries to trade a diversified portfolio of commodities, Can oscillator entry models result in profitable trades? How have they fared over time-have they become more or less profitable in recent years? These questions will be addressed below.

The exits are the standard ones, used throughout this book in the study of entry models. Entry rules are discussed along with the model code and under the individual tests. Trades were closed out either when an entry in the opposing direction took place or when the standard exit closed the trade, whichever came first. The test platform is also standard.

Over the years, we have coded into C+ + the various oscillators described in articles from Technical Analysis of Stocks and Commodities and from other sources. When writing this chapter, we compared the output from our C+ + implementations of the classic MACD, Stochastic, and RSI oscillators with (when available) equivalent oscillators in TradeStation. In most cases, there was perfect agreement of the results. However, for one of the Stochastics, the results were extremely different, specifically for Slow %K. Examining the code revealed that TradeStation was computing Slow %K by taking an exponential moving average of Fast %K. Our code, however, computes the 3-bar simple moving averages of both the numerator and the denominator (from which Fast %K would have been computed) to obtain Slow %K. According to the equations in Meibahr's (1992) article, and in other sources we have encountered over the years, our C+ + implementation is the correct one. If the reader attempts to replicate some of our work in TradeStation and finds discrepancies, we strongly suggest checking the indicator functions of TradeStation. In addition,

PART 11 The Study of Entries when attempting to code a correct implementation for Slow %K in TradeStation's Easy Language, we ran into problems: It appears that TradeStation can give inaccurate results, without any warning, when one user function calls another. When we modified our code so intermediate variables were computed (thus avoiding the need to have nested calls), correct results were obtained. The version of TradeStation used for those tests was 4.02, dating from July 29, 1996.

The following code implements most of the oscillator-based entry models that underlie the tests. The actual computation of the oscillators is handled by calls to external functions.

♦♦SiMty void Model (float *parms, float • float *opn, float *hi,

H ☆QDilQIM' ♦ai □▲ipMSCM^Q 0D2|»t ♦□ ft

// File B xiimodoi.c

// opn vector [1. .nb] of □□lll"X«Y)o CTDflM.»

// dlrv ❖«♦□n [i. .nb} □>? S-MltnSV)ollL volatilities

// nb number fW bars Mi data »IlinKIlL» or ❖«♦□n*

// ts trading simulator class instance

// eqcls 'MWCn [1. .nb] □>? itCMO^ IH.04M4B •IU,*IU»»

// declare local scratch variables

♦♦S^Klt)) int rc, cb, ncontracts, maxhold, lenl, len2, len3 ,* static int modeltype, ordertype, osctype, ♦XY)oiS*03 Kfl3 er© h static mmstp, ptlim, stpprice, limprice, tmp;

static float sigline [MAXBAR+1] 03oscline [MAXBAR+1] ; ♦♦©♦Mllll uppe rband [MAXBAR+1 ] 031 owerband [MAXBAR+1 ];

// copy parameters to lenl len2 len3

modeltype osctype ordertype maxhold

= parms [1] ; = parms [2] ,-= parms [3] ; = parms [7] ; = ■ parms [8] ; = parms [9] ; = 10;

local variables for clearer reference

// shorter or first length parameter

// longer or second length parameter

// length for divergence test

// type of oscillator entry model

// type of oscillator

// type of entry order

// maximum holding period ptlim = 4; // profit target in volatility units mmstp =1; II stop loss in volatility units

// skip invalid parameter combinations if( (osctype==4 lenl>=len2) } { set__vector (eqcls, 1, nb, 0.0); return;

// perform whole-series computations using fast vector routines switch(osctype) { // select oscillator case 1; // classic fast stochastics StochOsc(oscline,hi,lo,els,1,lenl,nb); MovAvg(sigline, oscline, 1, 3, nb); set-vector (upperband, i, nb, 80.0); set-vector(lowerband, 1, nb, 20.0); break;

case 2; // classic slow stochastics

II ATR for exit

upper threshold lower threshold

upper threshold lower threshold

MovAvg(sigline, oscline, set_vector(upperband, 1, set^vector(lowerband, 1, break;

case 3: // classic rsi RsiOsc(oscline, els, 1, MovAvg(sigline, oscline set-vector(upperband, 1 set-vector(lowerband, 1 break;

MovAvg (sigllrie, oscline, 2, 9, nb) ; for(i = l; i<=hb,- i++)

default: nrerror("Invalid moving average selected")

upper threshold lower threshold

thresholds // as long-term mean-deviation // bands

// step through bars (days) to simulate actual trading for(cb = 1; cb <= nb; cb++) {

II take no trades before the in-sample period // ... same as TradeStation's MaxBarsBack setting if (dt (cb) < IS-DATE) { eqcls [cb] = 0.0; continue; }

j/ execute any pending orders and store closing equity rc = ts .update(opn[cb] , hi [cb] , lo[cb], cla [cbj , cb) ; if(rc != 0) nrerror("Trade buffer overflow"); eqcls [cb] - ts.currentequity(EQ_CLOSETOTAL);

calculate number of contracts to trade II .. . we want to trade the dollar volatility equivalent /t ... of 2 new S&F-5QQ contracts as of 12/31/98 ncontracts = RoundToInteger (5673 . 0 / dlrv[cbl ); if(ncontracts < 1) ncontracts = 1;

avoid placing orders on possibly limit-locked days if (hi [cb+1] == lo[cb+l]) continue;

generate entry signals, stop prices and limit prices the specified oscillator-based entry model #define CrossesAbove (a,b,c) (a[c]>-b[cj f<S; a [c-1] <b [c-1] i ftdefine CroseesBelow(a,b,c) (a[c]<b[c] && a [o-l] >-b[c-l] ) ftdefine TurnsUp{a,c) (a [c] >=a[c-1] && a[c-1]<a[c-2]) ftdefine TurnsDn{a,c) (a [c] <a [c-1] && a [c-1] =■»a [c-2] ) signal-0;

switch(modeltype) (

case 1: // overbought-oversold model i£(crossesAbove(oscline, lowerband, cb)) signal = 1;

else if(CrossegSelow(oscline, upperband, cb))

signal = -1; limprice = 0 . 5 * (hi[cb] + Lo[cb]); stpprice = els [cb] + 0.5 + signal '* exitatr[cb]; break;

case 2: // signal line model i£{CrossesAbove(oscline , sigline, cb) ) signal = 1; else if(CrossesSelow(oscline , sigline, cb))

signal = -1; limprice = 0.5 * (hi [cb] + lo[cb]); stpprice = els [cb] + O.S * signal * exitatr[cb]; break;

case 3: // divergence model i = LowestBar(els, len3( cb); j = LowestBar(oscline, len3, cb>;

if(i < cb && i > cb-6 && j > cb-len3 + l &Sc i-j > 4

if(i i cb ii i > cb-6 ts j > cb-len3+l && i-j > 4 && TurnsDn{oscline, cb)) signal = -1;


default: nrerror("Invalid model selected");

#undef CrossesAbove ttundef CrossesBelow #undef TurnsUp #undef TurnsDn

// enter trades using specified order type if (ts.positionO <= 0 && signal == 1) {

switch(ordertype) { // select desired order type case 1: ts.buyopen("1', ncontracts); break; case 2: ts.buylimit(~2', limprice, ncontracts); break; case 3: ts.buystop("3', stpprice, ncontracts); break; default: nrerror("Invalid buy order selected");

switch(ordertype) { // select desired order type case 1: ts.sellopen("4', ncontracts); break; case 2: ts.selllimit("5', limprice, ncontracts}; break case 3: ts.sellstop("6', stpprice, ncontracts); break; default: nrerror("Invalid sell order selected");

// instruct simulator to employ standard exit strategy tmp = exitatr [cb] ;

ts . stdexitcls ( "X', ptlim*tmp, Tnmstp*tinp, maxhold) ; } // process next bar

The logic of the code is very similar to the code used to test moving averages. First, a number of parameters are copied to local variables to make them easier to understand and refer to in the code that follows. A check is then made for invalid combinations of parameters; e.g., for the MACD (osctype = 4), the length of the shorter moving average must be less than the longer moving average; otherwise the test is skipped. In the next large block of code, osctype selects the type of oscillator that will be computed (1 = fast Stochastics, 2 = slow Stochastics, 3 = classic RSI, 4 = classic MACD). The oscillator (oscline) is then computed as a data series or vector; any additional curves associated with it, such as a signal line (isigline) or slower version of the oscillator, are generated; and upper (upperband)

and lower (lowerband) thresholds are either set or computed. For the Stochastics, the standard thresholds of 80 and 20 are used. For the RSI, 70 and 30 are speci-tied (also standard). Although the MACD normally has no thresholds, thresholds placed 1.5 mean deviations above and below zero. Finally, the process of stepping through the data, bar by bar, is begun.

Two main blocks of code are of interest in the loop for stepping through the data. The first block generates a buy or sell signal, as well as limit and stop prices for the specified, oscillator-based entry model. The modeltype parameter selects the model to use: I = overbought/oversold model, 2 = signal line model, and 3 = divergence model. The oscillator used by the model to generate the buy and sell signals is the one computed earlier, as selected by osctype. The final block of code enters trades using the specified order type. The parameter ordertype determines the order used: 1 = entry at open, 2 = entry on limit, and 3 = entry on stop. Finally, the simulator is instructed to use the standard exit model to close out any open trades.

The exact logic used for entering the market is discussed in the context of the individual tests below without requiring the reader to refer to or understand the code.

Was this article helpful?

0 0

Post a comment