TRADERS’ TIPS

July 2017

Tips Article Thumbnail

For this month’s Traders’ Tips, the focus is Markos Katsanos’s article in this issue, “Trading The Nikkei.” Here, we present the July 2017 Traders’ Tips code with possible implementations in various software.

The Traders’ Tips section is provided to help the reader implement a selected technique from an article in this issue or another recent issue. The entries here are contributed by software developers or programmers for software that is capable of customization.


logo

TRADESTATION: JULY 2017

In “Trading The Nikkei” in this issue, author Markos Katsanos explores the relationship between exchange rates and related equity indices. In particular, he analyzes the correlation between the Japanese yen (USD/JPY) and the Nikkei 225 index.

The author has developed a novel approach for analyzing divergences in the correlation between markets. In the article, he includes some EasyLanguage code for a TradeStation strategy, which we are also including here for convenience. In addition, we are providing an indicator based on the author’s work to help users visualize the signals generated by the strategy.

Strategy: Correlation Divergence
// Correlation Divergence
// Markos Katsanos
// TASC JUL 2017

inputs:
	SEC2( Close of Data2 ),// FXY
	SEC3( Close of Data3 ),//SPY
	STD(25), 
	OB(90),//STOCHASIC
	D1(3), //ROC DAYS
	D2(25), //MA LR DAYS
	DIVDAYS(50),// REGRESSION DAYS
	IMDAYS(50),// DIVERGENCE MOMENTUM DAYS
	CR3CR(.8), //CORRELATION WITH SEC3
	DIVCRIT(75),
	LAG(3), // DIVERGENCE CRITICAL
	STP(1.5), // STOP LOSS %
	EXIT(11); // TIME EXIT DAYS
variables:
	MA1(0),IM2(0),DIVSHORT(0),
	STOC(0),OS(0),LR(0),
	DIV2(0),RS1(0),RS2(0),
	b2(0),PRED2(0),a2(0),
	RS3(0),CR2(0),CR3(0);

OS = 100-OB ;
DIVSHORT = 100 - DIVCRIT ;
stoc = ( Average( Close - 
	Lowest( Low, STD ), 3 ) * 100 ) /
	( Average( Highest( High, STD )- 
	Lowest( Low, STD ), 3 ) ) ;
MA1 = Average( Close, D2 ) ;
LR = 100 * LinearRegSLOPE( Close, D2 ) ;
//REGRESSION
IF CurrentBar > D1 + D2 then
	begin
	RS1 = (Close / Close[D1] - 1 ) * 100 ;
	RS2 = ( SEC2 / SEC2[D1] - 1 ) * 100 ;
	RS3 = ( SEC3 / SEC3[D1] - 1 ) * 100 ;
	CR2 = CorrelationMK( RS1, RS2, DIVDAYS ) ;
	CR3 = CorrelationMK( RS1, RS3, DIVDAYS ) ;
	b2 = CR2 * StandardDev( RS1, DIVDAYS, 1 )
	 / ( StandardDev( RS2, DIVDAYS, 1 ) + .001 ) ;
	a2 = Average( RS1, DIVDAYS )
	 - b2 * Average( RS2, DIVDAYS ) ;
	PRED2 = b2 * RS2 + a2 ;
	DIV2 = PRED2 - RS1 ;
	end ;
IM2 = ( Average( DIV2 - 
	Lowest( DIV2, IMDAYS ), 2 ) * 100 ) /
	( Average( Highest( DIV2, IMDAYS ) - 
	Lowest( DIV2, IMDAYS ), 2 ) + .01 ) ;

if CurrentBar > DIVDAYS + D1 + IMDAYS then 
	begin
	//BUY
	if IM2[LAG] > DIVCRIT and IM2 < IM2[LAG] 
	and IM2 > DIVSHORT and CR3 < CR3CR 
	and ( LR >= LR[1] or Close > MA1 ) then 
		Buy ("DIVJPY") this bar at Close ;
	//SHORT
	if IM2[LAG] < DIVSHORT and IM2>IM2[LAG] 
	and IM2<DIVCRIT and CR3 < CR3CR and 
	(LR <= LR[1] or Close < MA1 ) then 
		SellShort ("NDIVJPY") this bar at Close ;
	end ;

//EXIT
if BarsSinceEntry > 3 and 
	Close < Close[BarsSinceEntry] * ( 1 - STP / 100 )
	and	STOC > OS then 
		Sell ("STOP") next bar at Market ;

IF BarsSinceEntry > 7 and 
	Close < Highest( Close, BarsSinceEntry ) 
	* ( 1 - STP / 100 ) then 
		Sell ("TRAIL") next bar at Market ;

IF BarsSinceEntry > 3 and 
	Close > Close[BarsSinceEntry] * ( 1 + STP / 100 ) 
	and STOC < OB then 
		BuyToCover ("INITIAL STOP") 
			next bar at Market ;

IF BarsSinceEntry > 7 and 
	Close > Lowest( Close,BarsSinceEntry ) 
	* ( 1 + STP / 100 ) then 
	BuyToCover ("TRAIL COVER") next bar at Market ;

If BarsSinceEntry >= EXIT then 
	begin
	Sell ("TIME") all shares 
		this bar at close ;
	BuyToCover ("TIMEX") all shares 
		this bar at close ;
	end ;	


Indicator: Correlation Divergence
// Correlation Divergence
// Markos Katsanos
// TASC JUL 2017

inputs:
	SEC2( Close of Data2 ),// FXY
	SEC3( Close of Data3 ),//SPY
	D1( 3 ), //ROC DAYS
	DIVDAYS( 50 ),// REGRESSION DAYS
	IMDAYS( 50 ),// DIVERGENCE MOMENTUM DAYS
	CR3CR( .8 ) ; //CORRELATION WITH SEC3
	
variables:
	IM2(0),
	DIV2(0),RS1(0),RS2(0),
	b2(0),PRED2(0),a2(0),
	RS3(0),CR2(0),CR3(0);

//REGRESSION
RS1 = ( Close / Close[D1] - 1 ) * 100 ;
RS2 = ( SEC2 / SEC2[D1] - 1 ) * 100 ;
RS3 = ( SEC3 / SEC3[D1] - 1 ) * 100 ;
CR2 = CorrelationMK( RS1, RS2, DIVDAYS ) ;
CR3 = CorrelationMK( RS1, RS3, DIVDAYS ) ;
b2 = CR2 * StandardDev( RS1, DIVDAYS, 1 ) 
	/ ( StandardDev( RS2, DIVDAYS, 1 ) + .001 ) ;
a2 = Average( RS1, DIVDAYS ) 
	- b2 * Average( RS2, DIVDAYS ) ;
PRED2 = b2 * RS2 + a2 ;
DIV2 = PRED2 - RS1 ;

IM2 = ( Average( DIV2 - 
	Lowest( DIV2, IMDAYS ), 2 ) * 100 ) /
	( Average( Highest( DIV2, IMDAYS ) - 
	Lowest( DIV2, IMDAYS ), 2 ) + .01 ) ;

Plot1( IM2, "RegDiv" ) ;
Plot2( 75, "Upper" ) ;
Plot3( 25, "Lower" ) ;


Function: Correlation MK
{ CORRELATIONMK : Pearson's 
Correlation Function
Copyright 2009, 
Markos Katsanos. 
All rights reserved.
For more information see 
Intermarket Trading Strategies, Wiley,
2009 }

Inputs:
	SEC1( NumericSeries ),
	SEC2( NumericSeries ),
	D1( NumericSimple ); // days for correlation

Variables:
	D2(20),Q1(0),Q2(0),
	Q3(0),Q2Q3(0),R(0);
if CurrentBar >= D1 then 
	begin
	Q1 = Summation((SEC1*(SEC2)),D1)
		-(Summation(SEC1,D1)
		* Summation(SEC2,D1)/D1);

	Q2 = Summation(((SEC2)*(SEC2)),D1) 
		- (Summation(SEC2,D1)
		* Summation(SEC2,D1)/D1);

	Q3 = Summation((SEC1*SEC1),D1) 
		- (Summation(SEC1,D1)
		* Summation(SEC1,D1)/D1);

	if Q2*Q3 > 0 then 
		Q2Q3=SquareRoot(Q2*Q3);
	if Q2Q3 <> 0 then 
		begin
		R=Q1/Q2Q3;
		if R <= 1 and  R >= -1 then
		CorrelationMK = R ;
		end ;
	end ;
	

To download the EasyLanguage code for the strategy and indicator as well as a configured TradeStation workspace as discussed in the article, please visit our TradeStation and EasyLanguage support forum. The code for this article can be found here: https://community.tradestation.com/Discussions/Topic.aspx?Topic_ID=147651. The ELD filename is “TASC_JUL2017.ELD.”

For more information about EasyLanguage in general, please see https://www.tradestation.com/EL-FAQ.

A sample chart is shown in Figure 1.

Sample Chart

FIGURE 1: TRADESTATION. The correlation divergence strategy and accompanying indicator are applied to a daily chart of DXJ, FXY, and SPY.

This article is for informational purposes. No type of trading or investment recommendation, advice, or strategy is being made, given, or in any manner provided by TradeStation Securities or its affiliates.

—Doug McCrary
TradeStation Securities, Inc.
www.TradeStation.com

BACK TO LIST

logo

METASTOCK: JULY 2017

Markos Katsanos’ article in this issue, “Trading The Nikkei,” presents a system for correlating currency with market strength. The formulas for implementing this system in MetaStock are shown here. Due to the complexity of the formulas, two helper formulas must be created first before the trade signal formulas can be written.

The entry and exit signal formula have values set for the stop percentage and length of the trades. If you wish to use different values, you must change those numbers in both the entry and exit signal or else the signals will not correctly align.

Indicators:

- ?DXJ System CR2 helper
s1:= Security("ONLINE:FXY", C);
D1:= 50;
RS1:= (C/Ref(C, -D1) -1)*100;
RS2:= (s1/Ref(s1, -D1) -1)*100;
Q1:= Sum((RS1*RS2), D1)- ((Sum(RS1,D1)*Sum(RS2,D1))/D1);
Q2:= Sum((RS2*RS2), D1)- ((Sum(RS2,D1)*Sum(RS2,D1))/D1);
Q3:= Sum((RS1*RS1), D1)- ((Sum(RS1,D1)*Sum(RS1,D1))/D1);
Q2Q3:= If(Q2 * Q3 > 0, Sqrt(If(Q2=0, 1, Abs(Q2))*If(Q3=0, 1, Abs(Q3))), -1);
R:= If(Q2Q3 = -1, 0, Q1/Q2Q3);
If(R<-1, -1, If(R > 1, 1, R))



- ?DXJ System CR3 helper
s1:= Security("ONLINE:SPY", C);
D1:= 50;
RS1:= (C/Ref(C, -D1) -1)*100;
RS2:= (s1/Ref(s1, -D1) -1)*100;
Q1:= Sum((RS1*RS2), D1)- ((Sum(RS1,D1)*Sum(RS2,D1))/D1);
Q2:= Sum((RS2*RS2), D1)- ((Sum(RS2,D1)*Sum(RS2,D1))/D1);
Q3:= Sum((RS1*RS1), D1)- ((Sum(RS1,D1)*Sum(RS1,D1))/D1);
Q2Q3:= If(Q2 * Q3 > 0, Sqrt(If(Q2=0, 1, Abs(Q2))*If(Q3=0, 1, Abs(Q3))), -1);
R:= If(Q2Q3 = -1, 0, Q1/Q2Q3);
If(R<-1, -1, If(R > 1, 1, R))

Trading Signals:

Enter Long:
s1:= Security("ONLINE:FXY", C);
stp:= 1.5; {Stop Percentage}
exit:= 11; {Maximum bars in trade}
stoc:= (Mov(C-LLV(L,25),3,S)*100)/Mov(HHV(H,25)-LLV(L,25),3,S);
LR:= 100*LinRegSlope(C, 25);
RS1:= (C/Ref(C, -3) -1)*100;
RS2:= (s1/Ref(s1, -3) -1)*100;
CR2:= Fml("- ?DXJ System CR2 helper");
CR3:= Fml("- ?DXJ System CR3 helper");
b2:= CR2*Stdev(RS1, 50)/Stdev(RS2,50) + 0.001;
a2:= Mov(RS2, 50, S)- b2*Mov(RS2,50,S);
pred2:= b2*RS2+a2;
div2:= pred2-RS1;
IM2:= (Mov(div2-LLV(div2,50),2,S)*100)/
(Mov(HHV(div2,50)-LLV(div2,50),2,S)+.01);
lstop:= 1- stp/100;
el:= Ref(IM2,-3)>75 AND IM2<Ref(IM2,-3) AND IM2>25 AND
CR3<0.8 AND (LR>= Ref(LR,-1) OR C>Mov(C,25,S));
ltrade:= If(PREV<=0, If(el, C, 0),
If(BarsSince(PREV<=0)>3 AND C < PREV*lstop, -1,
If(BarsSince(PREV<=0)>7 AND C < HighestSince(1, PREV<=0, C*lstop), -2,
If(BarsSince(PREV<=0)>=exit, -3, PREV))));
ltrade>0 AND Ref(ltrade<=0, -1)


Exit Long:
s1:= Security("ONLINE:FXY", C);
stp:= 1.5; {Stop Percentage}
exit:= 11; {Maximum bars in trade}
stoc:= (Mov(C-LLV(L,25),3,S)*100)/Mov(HHV(H,25)-LLV(L,25),3,S);
LR:= 100*LinRegSlope(C, 25);
RS1:= (C/Ref(C, -3) -1)*100;
RS2:= (s1/Ref(s1, -3) -1)*100;
CR2:= Fml("- ?DXJ System CR2 helper");
CR3:= Fml("- ?DXJ System CR3 helper");
b2:= CR2*Stdev(RS1, 50)/Stdev(RS2,50) + 0.001;
a2:= Mov(RS2, 50, S)- b2*Mov(RS2,50,S);
pred2:= b2*RS2+a2;
div2:= pred2-RS1;
IM2:= (Mov(div2-LLV(div2,50),2,S)*100)/
(Mov(HHV(div2,50)-LLV(div2,50),2,S)+.01);
lstop:= 1- stp/100;
el:= Ref(IM2,-3)>75 AND IM2<Ref(IM2,-3) AND IM2>25 AND
CR3<0.8 AND (LR>= Ref(LR,-1) OR C>Mov(C,25,S));
ltrade:= If(PREV<=0, If(el, C, 0),
If(BarsSince(PREV<=0)>3 AND C < PREV*lstop, -1,
If(BarsSince(PREV<=0)>7 AND C < HighestSince(1, PREV<=0, C*lstop), -2,
If(BarsSince(PREV<=0)>=exit, -3, PREV))));
ltrade<0



Enter Short:
s1:= Security("ONLINE:FXY", C);
stp:= 1.5; {Stop Percentage}
exit:= 11; {Maximum bars in trade}
stoc:= (Mov(C-LLV(L,25),3,S)*100)/Mov(HHV(H,25)-LLV(L,25),3,S);
LR:= 100*LinRegSlope(C, 25);
RS1:= (C/Ref(C, -3) -1)*100;
RS2:= (s1/Ref(s1, -3) -1)*100;
CR2:= Fml("- ?DXJ System CR2 helper");
CR3:= Fml("- ?DXJ System CR3 helper");
b2:= CR2*Stdev(RS1, 50)/Stdev(RS2,50) + 0.001;
a2:= Mov(RS2, 50, S)- b2*Mov(RS2,50,S);
pred2:= b2*RS2+a2;
div2:= pred2-RS1;
IM2:= (Mov(div2-LLV(div2,50),2,S)*100)/
(Mov(HHV(div2,50)-LLV(div2,50),2,S)+.01);
sstop:= 1+ stp/100;
es:= Ref(IM2,-3)<25 AND IM2>Ref(IM2,-3) AND IM2<75 AND
CR3<0.8 AND (LR<=Ref(LR,-1) OR C<Mov(C,25,S));
strade:= If(PREV<=0, If(es, C, 0),
If(BarsSince(PREV<=0)>3 AND C > PREV*sstop, -1,
If(BarsSince(PREV<=0)>7 AND C > LowestSince(1, PREV<=0, C*sstop), -2,
If(BarsSince(PREV<=0)>=exit, -3, PREV))));
strade>0 AND Ref(strade<=0, -1)


Exit Short:
s1:= Security("ONLINE:FXY", C);
stp:= 1.5; {Stop Percentage}
exit:= 11; {Maximum bars in trade}
stoc:= (Mov(C-LLV(L,25),3,S)*100)/Mov(HHV(H,25)-LLV(L,25),3,S);
LR:= 100*LinRegSlope(C, 25);
RS1:= (C/Ref(C, -3) -1)*100;
RS2:= (s1/Ref(s1, -3) -1)*100;
CR2:= Fml("- ?DXJ System CR2 helper");
CR3:= Fml("- ?DXJ System CR3 helper");
b2:= CR2*Stdev(RS1, 50)/Stdev(RS2,50) + 0.001;
a2:= Mov(RS2, 50, S)- b2*Mov(RS2,50,S);
pred2:= b2*RS2+a2;
div2:= pred2-RS1;
IM2:= (Mov(div2-LLV(div2,50),2,S)*100)/
(Mov(HHV(div2,50)-LLV(div2,50),2,S)+.01);
sstop:= 1+ stp/100;
es:= Ref(IM2,-3)<25 AND IM2>Ref(IM2,-3) AND IM2<75 AND
CR3<0.8 AND (LR<=Ref(LR,-1) OR C<Mov(C,25,S));
strade:= If(PREV<=0, If(es, C, 0),
If(BarsSince(PREV<=0)>3 AND C > PREV*sstop, -1,
If(BarsSince(PREV<=0)>7 AND C > LowestSince(1, PREV<=0, C*sstop), -2,
If(BarsSince(PREV<=0)>=exit, -3, PREV))));
strade<0

—William Golson
MetaStock Technical Support
www.metastock.com

BACK TO LIST

logo

eSIGNAL: JULY 2017

For this month’s Traders’ Tip, we’re providing the study Regression_Divergence.efs based on the formula described in Markos Katsanos’ article in this issue, “Trading The Nikkei.” In the article, the author presents a strategy based the correlation between the Nikkei 225 Index and the Japanese yen.

The EFS study contains formula parameters that may be configured through the edit chart window (right-click on the chart and select “edit chart”). A sample chart is shown in Figure 2.

Sample Chart

FIGURE 2: eSIGNAL. Here is an example of the study plotted on a daily chart of DXJ.

To discuss this study or download a complete copy of the formula code, please visit the EFS library discussion board forum under the forums link from the support menu at www.esignal.com or visit our EFS KnowledgeBase at https://www.esignal.com/support/kb/efs/. The eSignal formula script (EFS) is also available for copying & pasting here:

/*********************************
Provided By:  
eSignal (Copyright c eSignal), a division of Interactive Data 
Corporation. 2016. All rights reserved. This sample eSignal 
Formula Script (EFS) is for educational purposes only and may be 
modified and saved under a new file name.  eSignal is not responsible
for the functionality once modified.  eSignal reserves the right 
to modify and overwrite this EFS file with each new release.

Description:        
    Trading The Nikkei by Markos KatsaOS

Version:            1.00  05/12/2017

Formula Parameters:                     Default:
Security 1                              FXY
Security 2                              SPY
Div Length                              50
RLength                                 50
ROC Length                              3
Stoc Length                             25
MA&LR Length                            25
OB                                      90
Correlation                             0.8
DivCrit                                 75
Lag                                     3
Stop Loss (%)                           1.5
Exit Days                               11


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(){
    setPriceStudy(false);
    setStudyTitle("RegressionDivergence");
    setIntervalsBackfill(true);
    
    var x=0;
    fpArray[x] = new FunctionParameter("S1", FunctionParameter.STRING);
        with (fpArray[x++]){
        setName("Security 1");
        addOption(" ");
        addOption("FXY");
        setDefault("FXY");
        }
    
    fpArray[x] = new FunctionParameter("S2", FunctionParameter.STRING);
        with (fpArray[x++]){
        setName("Security 2");
        addOption(" ");
        addOption("SPY");
        setDefault("SPY");
        }
    
    fpArray[x] = new FunctionParameter("DLength", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("Div Length");
        setDefault(50);
        setLowerLimit(1);
        }
    
    fpArray[x] = new FunctionParameter("RLength", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("RLength");
        setDefault(50);
        setLowerLimit(1);
        }

    fpArray[x] = new FunctionParameter("ROCLength", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("RoC Length");
        setDefault(3);
        setLowerLimit(1);
        }
    
    fpArray[x] = new FunctionParameter("SLength", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("Stoc Length");
        setDefault(25);
        setLowerLimit(1);
        }
    
    fpArray[x] = new FunctionParameter("MLLength", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("MA&LR Length");
        setDefault(25);
        setLowerLimit(1);
        }

    fpArray[x] = new FunctionParameter("OB", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("OB");
        setDefault(90);
        setLowerLimit(1);
        }

    fpArray[x] = new FunctionParameter("Corr", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("Correlation");
        setDefault(0.8);
        setLowerLimit(0.1);
        }

    fpArray[x] = new FunctionParameter("DivCrit", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("DivCrit");
        setDefault(75);
        setLowerLimit(1);
        }

    fpArray[x] = new FunctionParameter("Lag", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("Lag");
        setDefault(3);
        setLowerLimit(1);
        }

    fpArray[x] = new FunctionParameter("StLoss", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("Stop Loss (%)");
        setDefault(1.5);
        setLowerLimit(0.1);
        }
    
    fpArray[x] = new FunctionParameter("Exit", FunctionParameter.NUMBER);
	with(fpArray[x++]){
        setName("Exit Days");
        setDefault(11);
        setLowerLimit(1);
        }
}

var bInit = false;
var bVersion = null;

var xCloseSeries1 = null;
var xCloseSeries2 = null;
var xStochactic = null;
var xSMA = null;
var xLR = null;

var xRoCMain = null;
var xRoC1 = null;
var xRoC2 = null;
var xCR1 = null;
var xCR2 = null;

var xRegr = null;
var xIM = null;

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

var DivShort = 0;
var OS = 0;

var nEntryBarN = 0;


function main(S1, S2, DLength, RLength, ROCLength, SLength, MLLength, OB, Corr, DivCrit, Lag, StLoss, Exit){
    if (bVersion == null) bVersion = verify();
    if (bVersion == false) return;
    
    if (getCurrentBarCount() <= (RLength + DLength + ROCLength)) return;
    
    if (getBarState() == BARSTATE_ALLBARS){
        DivShort = 0;
        OS = 0;
        nEntryBarN = 0;
        
        bInit = false;
    }
    
    if (!bInit){
        xClose = close();
        xCloseSeries1 = close(sym(S1));
        xCloseSeries2 = close(sym(S2));
        xHigh= high();
        xLow =low();
        
        xStochactic = efsInternal("CustStochastic", xClose, xHigh, xLow, SLength);
        xSMA = sma(MLLength, xClose);
        xLR = efsInternal("LRSlopeM", MLLength, xClose);
        xRoCMain = efsInternal("ROCM", xClose, ROCLength);
        xRoC1 = efsInternal("ROCM", xCloseSeries1, ROCLength);
        xRoC2 = efsInternal("ROCM", xCloseSeries2, ROCLength);
        xCR1 = efsInternal("CorrelationMK", xRoCMain, xRoC1, RLength);
        xCR2 = efsInternal("CorrelationMK", xRoCMain, xRoC2, RLength);
        
        xRegr = efsInternal("Regression", xCR1, xRoCMain, xRoC1, RLength);
        xIM = efsInternal("CalcIM", xRegr, DLength);
        
        DivShort = 100 - DivCrit;
        OS = 100 - OB;
        
        addBand(DivCrit, PS_DASH, 1, Color.grey, 1);
        addBand(DivShort, PS_DASH, 1, Color.grey, 2);
        
        bInit = true;
    }

    if (getCurrentBarIndex != 0){
        if (!Strategy.isInTrade()){
            if (xIM.getValue(-Lag) > DivCrit && xIM.getValue(0) < xIM.getValue(-Lag)
                                            && xIM.getValue(0) > DivShort
                                            && xCR2.getValue(0) < Corr
                                            && (xLR.getValue(0) >= xLR.getValue(-1) || xClose.getValue(0) > xSMA.getValue(0))){
                Strategy.doLong("DIVJPY", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
                nEntryBarN = getCurrentBarCount();
            }
            else if (xIM.getValue(-Lag) < DivShort && xIM.getValue(0) > xIM.getValue(-Lag)
                                                    && xIM.getValue(0) < DivCrit
                                                    && xCR2.getValue(0) < Corr
                                                    && (xLR.getValue(0) <= xLR.getValue(-1) || xClose.getValue(0) < xSMA.getValue(0))){
                Strategy.doShort("NDIVJPY", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT);
                nEntryBarN = getCurrentBarCount();
            }
        }
        else {
            var nBarsSinceEntry = getCurrentBarCount() - nEntryBarN;
        
            if (nBarsSinceEntry > 3){
                if (Strategy.isLong() && xStochactic.getValue(0) > OS && xClose.getValue(0) < xClose.getValue(-nBarsSinceEntry) * (1 - StLoss/100))
                    Strategy.doSell("STOP", Strategy.MARKET, Strategy.NEXTBAR, Strategy.DEFAULT);

                else if (Strategy.isShort() && xStochactic.getValue(0) < OB && xClose.getValue(0) > xClose.getValue(-nBarsSinceEntry) * (1 + StLoss/100))
                    Strategy.doCover("INITIAL STOP", Strategy.MARKET, Strategy.NEXTBAR, Strategy.DEFAULT);
            }
        
            if (nBarsSinceEntry > 7 && Strategy.isInTrade()){
                if (Strategy.isLong() && xClose.getValue(0) < hhv(nBarsSinceEntry, xClose, 0) * (1 - StLoss/100))
                    Strategy.doSell("TRAIL", Strategy.MARKET, Strategy.NEXTBAR, Strategy.DEFAULT);
                
                else if (Strategy.isShort() && xClose.getValue(0) > llv(nBarsSinceEntry, xClose, 0) * (1 + StLoss/100))
                    Strategy.doCover("TRAIL COVER", Strategy.MARKET, Strategy.NEXTBAR, Strategy.DEFAULT);
            }
        
            if (nBarsSinceEntry >= Exit && Strategy.isInTrade()){
                if (Strategy.isLong()) Strategy.doSell("TIME", Strategy.CLOSE, Strategy.THISBAR, Strategy.ALL);
                else if (Strategy.isShort()) Strategy.doCover("TIMEX", Strategy.CLOSE, Strategy.THISBAR, Strategy.ALL);
            }
        
            if (!Strategy.isInTrade()) nEntryBarN = 0;
        }
    }

    if (Strategy.isLong()) setBarBgColor(Color.RGB(0,60,0));
    else if (Strategy.isShort()) setBarBgColor(Color.RGB(170,46,46));

    return xIM.getValue(0);
}

var xSTDDev1 = null;
var xSTDDev2 = null;
var xAvgRoC1 = null;
var xAvgRoC2 = null;

var xInit = false;

function Regression(xCR1, xRoC1, xRoC2, Length){
    if (!xInit){
        xSTDDev1 = stdDev(Length, xRoC1);
        xSTDDev2 = stdDev(Length, xRoC2);
        xAvgRoC1 = sma(Length, xRoC1);
        xAvgRoC2 = sma(Length, xRoC2);
        
        xInit = true;
    }

    var b2 = xCR1.getValue(0) * xSTDDev1.getValue(0) / (xSTDDev2.getValue(0) + 0.001);
    var a2 = xAvgRoC1.getValue(0) - b2 * xAvgRoC2.getValue(0);

    return (b2 * xRoC2.getValue(0) + a2) - xRoC1.getValue(0);
}

function CustStochastic(xClose, xHigh, xLow, Length){
    var nStoc = null;
    
    nStoc = (sma(3, efsInternal("SeriesSub", xClose, llv(Length, xLow))) * 100) /
            (sma(3, efsInternal("SeriesSub", hhv(Length, xHigh), llv(Length, xLow))));
    
    return nStoc;
}

function CalcIM(xRegr, Length){
    var IM = sma(2, efsInternal("SeriesSub", xRegr, llv(Length, xRegr))) * 100 /
                (sma(2, efsInternal("SeriesSub", hhv(Length, xRegr), llv(Length, xRegr))) + 0.01);
    return IM;
}

function SeriesSub(xSeries1, xSeries2){
    return xSeries1.getValue(0) - xSeries2.getValue(0);
}

function LRSlopeM(Length, xClose){
    var SL = 0;
    var SumBars = Length * (Length - 1) * 0.5;
    var SumSqrBars = (Length - 1) * Length * (2 * Length - 1) / 6;
    var Sum1 = 0;
    var SumY = 0;
    var i = 0;

    for (i = 0; i < Length; i++) {
        Sum1 += i * xClose.getValue(-i);
        SumY += xClose.getValue(-i);
    }
    var Sum2 = SumBars * SumY;
    var Num1 = Length * Sum1 - Sum2;
    var Num2 = SumBars * SumBars - Length * SumSqrBars;
    SL = Num1 / Num2;
    return SL * 100;
}

function ROCM(xSeries, Length){
    if (xSeries.getValue(-Length) != null)
        return (xSeries.getValue(0) / xSeries.getValue(-Length) - 1) * 100;
}

function CorrelationMK(xSeries1, xSeries2, Length){
    var nQ1 = Sum(efsInternal("SeriesMP", xSeries1, xSeries2), Length) - 
                (Sum(xSeries1, Length) * Sum(xSeries2, Length) / Length);
    var nQ2 = Sum(efsInternal("SeriesMP", xSeries2, xSeries2), Length) - 
                (Sum(xSeries2, Length) * Sum(xSeries2, Length) / Length);
    var nQ3 = Sum(efsInternal("SeriesMP", xSeries1, xSeries1), Length) - 
                (Sum(xSeries1, Length) * Sum(xSeries1, Length) / Length);
    
    if (nQ2 * nQ3 > 0) var nQ2Q3 = Math.sqrt(nQ2 * nQ3);
    if (nQ2Q3 != 0){
        var nR = nQ1 / nQ2Q3;
        if (nR <= 1 && nR >= -1) return nR;
    }
}

function Sum(xSeries, Length){
    if (xSeries.getValue(-Length) != null){
        var sum = 0;
        for (var i = 0; i < Length; i++){
            sum += xSeries.getValue(-i);
        }
        return sum;
    }
}

function SeriesMP(xSeries1, xSeries2){
    if (xSeries1.getValue(0) != null && xSeries2.getValue(0) != null)
        return xSeries1.getValue(0) * xSeries2.getValue(0);
}

function verify(){
    var b = false;
    if (getBuildNumber() < 3742){
        drawTextAbsolute(5, 35, "This study requires version 12.1 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=https://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;
}

—Eric Lippert
eSignal, an Interactive Data company
800 779-6555, www.eSignal.com

BACK TO LIST

logo

WEALTH-LAB: JULY 2017

We’ve added the regression divergence indicator discussed in Markos Katsanos’ article in this issue, “Trading The Nikkei,” to the Wealth-Lab TASCIndicators library for easy reference in any strategy.

Buy signals are produced when the divergence crosses above 75 and turns down during the next three days. The opposite event, that is, the crossing under 25 and turning up, generates short signals. A sample chart implementing the strategy is shown in Figure 3.

Sample Chart

FIGURE 3: WEALTH-LAB. Shown here are sample trades generated by the intermarket divergence system, with the 50-day regression divergence indicator plotted on the top.

You can get the companion strategy’s C# code by downloading it right from Wealth-Lab’s open strategy dialog.


using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using TASCIndicators;

namespace WealthLab.Strategies
{
	public class MyStrategy : WealthScript
	{
		private StrategyParameter slider1;
		private StrategyParameter slider2;
		private StrategyParameter slider3;
		
		public MyStrategy()
		{
			slider1 = CreateParameter("Regression Period",50,2,300,20);
			slider2 = CreateParameter("Div.Mom. Period",50,2,300,20);
			slider3 = CreateParameter("ROC Period",3,2,300,20);
		}
		
		protected override void Execute()
		{
			var fxy = GetExternalSymbol("FXY",true);
			var spy = GetExternalSymbol("SPY",true);			
			var rd = RegressionDivergence.Series(Bars,fxy,spy,slider1.ValueInt,slider2.ValueInt,slider3.ValueInt);
			
			int STD = 25, OB = 90,//STOCHASIC
			D1 = 3, //ROC DAYS
			D2 = 25, //MA LR DAYS
			DIVDAYS = 50,// REGRESSION DAYS
			IMDAYS = 50;// DIVERGENCE MOMENTUM DAYS
			double CR3CR = 0.8; //CORRELATION WITH SEC3
			int DIVCRIT = 75, LAG = 3; // DIVERGENCE CRITICAL
			double STP = 1.5; // STOP LOSS %
			int EXIT = 11; // TIME EXIT DAYS
			var ls = LineStyle.Solid;
			
			var OS=100-OB;
			var DIVSHORT = 100-DIVCRIT;
			var STOC=(SMA.Series(Close-Lowest.Series(Low,STD),3)*100)/(SMA.Series(Highest.Series(High,STD)-Lowest.Series(Low,STD),3));
			//STOC = StochK.Series(Bars,3);
			var MA1=SMA.Series(Close,D2);
			var LR=100*LinearRegSlope.Series(Close,D2);

			var RS1 =(Close/(Close>>D1)-1)*100;
			var RS2 =(fxy.Close/(fxy.Close>>D1)-1)*100;
			var RS3 =(spy.Close/(spy.Close>>D1)-1)*100;
			var CR2 = Correlation.Series(RS1,RS2,DIVDAYS);
			var CR3 = Correlation.Series(RS1,RS3,DIVDAYS);
			
			//var pop = StdDevCalculation.Population;
			//var b2=CR2*StdDev.Series(RS1,DIVDAYS,pop)/(StdDev.Series(RS2,DIVDAYS,pop)+0.001);
			//var a2=SMA.Series(RS1,DIVDAYS)-b2*SMA.Series(RS2,DIVDAYS);
			//var PRED2=b2*RS2+a2;
			//var DIV2=PRED2-RS1;
			//var IM2=(SMA.Series(DIV2 - Lowest.Series(DIV2,IMDAYS), 2) * 100)/(SMA.Series(Highest.Series(DIV2, IMDAYS) - Lowest.Series(DIV2, IMDAYS),2)+0.01);

			ChartPane rdPane = CreatePane(40,true,true);
			PlotSeries(rdPane,rd,Color.FromArgb(255,255,0,0),LineStyle.Solid,1);
			DrawHorzLine(rdPane,DIVSHORT,Color.Brown,ls,1);
			DrawHorzLine(rdPane,DIVCRIT,Color.CadetBlue,ls,1);
			
			for(int bar = GetTradingLoopStartBar(60); bar < Bars.Count; bar++)
			{
				if (IsLastPositionActive)
				{
					Position p = LastPosition;
					int barssinceentry = bar+1 - p.EntryBar;

					if( barssinceentry>= EXIT )
						ExitAtClose(bar,Position.AllPositions,"TIME");
					else
						if( p.PositionType == PositionType.Long )
					{
						if( barssinceentry>3 && Close[bar]<Close[bar-barssinceentry]*(1.0-STP/100d) && STOC[bar]>OS)
							SellAtMarket(bar+1,p,"STOP");

						if( barssinceentry>7 && Close[bar]<Highest.Series(Close,barssinceentry)[bar]*(1.0-STP/100d) )
							SellAtMarket(bar+1,p,"TRAIL");
					}
					else
					{
						if( barssinceentry>3 && Close[bar]>Close[bar-barssinceentry]*(1.0+STP/100d) && STOC[bar]<OB)
							CoverAtMarket(bar+1,p,"INITIAL STOP");

						if( barssinceentry>7 && Close[bar]>Lowest.Series(Close,barssinceentry)[bar]*(1.0+STP/100d) )
							CoverAtMarket(bar+1,p,"TRAIL COVER");					
					}
				}
				else
				{
					if( (rd[bar-LAG]>DIVCRIT) && (rd[bar]<rd[bar-LAG]) && (rd[bar]>DIVSHORT) &&
						(CR3[bar]<CR3CR) && (LR[bar]>=LR[bar-1] || Close[bar]>MA1[bar]) )
						BuyAtClose(bar,"DIVJPY");

					if( (rd[bar-LAG]<DIVSHORT) && (rd[bar]>rd[bar-LAG]) && (rd[bar]<DIVCRIT) &&
						(CR3[bar]<CR3CR) && (LR[bar]<=LR[bar-1] || Close[bar]<MA1[bar]) )
						ShortAtClose(bar,"NDIVJPY");
				}
			}			
		}
	}
}

—Eugene (Gene Geren)
Wealth-Lab team, MS123, LLC
www.wealth-lab.com

BACK TO LIST

logo

NEUROSHELL TRADER: JULY 2017

The regression divergence indicator described in Markos Katsanos’ article in this issue, “Trading The Nikkei,” can be easily implemented in NeuroShell Trader.

To recreate the regression divergence indicator, select new indicator from the insert menu, use the indicator wizard to set up the following indicators, and select other instrument data to choose the other security (in this case, FXY).

RS1:	%Change( Close, 3 ) 
RS2:	%Change( FXY Close, 3 )
DIV2:	Sub ( Add2( Mult2( LinXYReg Slope ( RS2, RS1, 50 ), RS2 ), 
LinXYReg Y Intercept( RS2, RS1, 50 ) ), RS1 )
REGDIV:	Mul2( Divide( Avg( Sub( DIV2, Min(DIV2,50)),2), Add2( Avg ( Range(Div2,50),2),0.01)),100)

To recreate the divergence system, select new trading strategy from the insert menu and enter the following in the appropriate locations of the trading strategy wizard:

BUY LONG CONDITIONS: [All of which must be true]
A>B ( Lag( REGDIV, 1 ), 75 )
A<B ( Momentum( REGDIV, 1), 0 )
A>B ( REGDIV, 25 )
A<B ( LinXYReg Correlation( SPY close, close, 50), 0.8 )
Or2( A>=B ( Momentum( LinRegSlope ( Close, 25 ), 1 ), 0 ), A>B( Close, Avg(Close,25 ) )

LONG STOP PRICES:
EntryPrice%(Trading Strategy,1.5)
IfThenElse(BarsSinceAct>=X(Trading Strategy,7),TrailPrice%(Trading Strategy,1.5),*)

SELL LONG CONDITIONS:
BarsSinceFill>=X(Trading Strategy,11)

SELL SHORT CONDITIONS: [All of which must be true]
A<B ( Lag( REGDIV, 1 ), 25 )
A>B ( Momentum ( REGDIV, 1), 0 )
A<B ( REGDIV, 75 )
A<B ( LinXYReg Correlation( SPY close, close, 50), 0.8 )
Or2( A<=B ( Momentum( LinRegSlope ( Close, 25 ), 1 ), 0 ), A<B( Close, Avg(Close,25 ) )

SHORT STOP PRICES:
EntryPrice%(Trading Strategy,1.5)
IfThenElse(BarsSinceAct>=X(Trading Strategy,7),TrailPrice%(Trading Strategy,1.5),*)

COVER SHORT CONDITIONS:
BarsSinceFill>=X(Trading Strategy,11)

If you have NeuroShell Trader Professional, you can also choose whether the parameters should be optimized. After backtesting the trading strategy, use the detailed analysis button to view the backtest and trade-by-trade statistics for the strategy.

Users of NeuroShell Trader can go to the Stocks & Commodities section of the NeuroShell Trader free technical support website to download a copy of this or any previous Traders’ Tips.

A sample chart is shown in Figure 4.

Sample Chart

FIGURE 4: NEUROSHELL TRADER. This sample NeuroShell Trader chart displays the regression divergence indicator and trading system.

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

BACK TO LIST

logo

NINJATRADER: JULY 2017

The DivergenceSystem strategy, as discussed in “Trading The Nikkei” by Markos Katsanos in this issue, is available for download at the following links for NinjaTrader 8 and NinjaTrader 7:

Once the file is downloaded, you can import the strategy in NinjaTader 8 from within the Control Center by selecting Tools → Import → NinjaScript Add-On and then selecting the downloaded file for NinjaTrader 8. To import in NinjaTrader 7, from within the Control Center window, select the menu File → Utilities → Import NinjaScript and select the downloaded file.

You can review the strategy’s source code in NinjaTrader 8 by selecting the menu New → NinjaScript Editor → Strategies from within the Control Center window and selecting the DivergenceSystem file. You can review the strategy’s source code in NinjaTrader 7 by selecting the menu Tools → Edit NinjaScript → Strategy from within the Control Center window and selecting the DivergenceSystem file.

NinjaScript uses compiled DLLs that run native, not interpreted, which provides you with the highest performance possible.

A sample chart implementing the strategy is shown in Figure 5.

Sample Chart

FIGURE 5: NINJATRADER. The DivergenceSystem strategy takes four trades on a daily DXJ chart after calculating divergence from the FXY and SPY.

—Raymond Deux & Jim Dooms
NinjaTrader, LLC
www.ninjatrader.com

BACK TO LIST

logo

UPDATA: JULY 2017

Our contribution this month is based on Markos Katsanos’ article in this issue, “Trading The Nikkei.”

In the article, the author proposes an intermarket system for trading the Nikkei index based on correlations, and divergences therein, between it and the Japanese yen. This system also makes use of the Pearson correlation function.

The Updata code for this article is in the Updata library and may be downloaded by clicking the custom menu and indicator library. Those who cannot access the library due to a firewall may paste the code shown here into the Updata custom editor and save it.

DISPLAYSTYLE LINE
INDICATORTYPE CHART
NAME "" ""
PARAMETER "FXY" ~SEC2=SELECT  
PARAMETER "SPY" ~SEC3=SELECT
PARAMETER "STD" #STD=25
PARAMETER "ROC" #ROC=3   
PARAMETER "MA LRS" #MALRS=25
PARAMETER "REGRESSION DAYS" #DIVDAYS=50
PARAMETER "MOMENTUM DAYS" #IMDAYS=50
PARAMETER "CORREL. SEC3" @CR3CR=0.8 
PARAMETER "LAG" #LAG=3
PARAMETER "STOP %" @STP=1.5
PARAMETER "STOP DAYS" #EXIT=11
@MA1=0
@IM2=0
@DIVSHORT=0
@STOC=0
@OS=0
@LR=0
@DIV2=0
@RS1=0
@RS2=0
@b2=0
@PRED2=0
@a2=0
@RS3=0
@CR2=0 
@CR3=0
FOR #CURDATE=0 TO #LASTDATE
   
   @RS1=((CLOSE/CLOSE(#MALRS))-1)*100
   @RS2=((~SEC2/HIST(~SEC2,#MALRS))-1)*100
   @RS3=((~SEC3/HIST(~SEC3,#MALRS))-1)*100
   @MA1=SGNL(CLOSE,#MALRS,M)
   @IM2=(SGNL(@DIV2 - PLOW(@DIV2,#IMDAYS), 2,M) * 100)/(SGNL(PHIGH(@DIV2, #IMDAYS) - PLOW(@DIV2, #IMDAYS),2,M)+.01)
   @STOC=(SGNL(CLOSE-PLOW(LOW,#STD),3,M)*100)/(SGNL(PHIGH(HIGH,#STD)-PLOW(LOW,#STD),3,M))
   @LR=(LSR(#DIVDAYS,0,0)-LSR(#DIVDAYS,0,#DIVDAYS))/#DIVDAYS
   @DIV2=@PRED2-@RS1
   @b2=@CR2*StdDev(@RS1,#DIVDAYS)/(StdDev(@RS2,#DIVDAYS)+.001)
   @PRED2=@b2*@RS2+@a2
   @a2=SGNL(@RS1,#DIVDAYS,M)-@b2*SGNL(@RS2,#DIVDAYS,M)
   @CR2=CORREL_MK(@RS1,@RS2,#DIVDAYS) 
   @CR3=CORREL_MK(@RS1,@RS3,#DIVDAYS)  
   @PLOT=@IM2  
   'Longs 
   IF HIST(@IM2,#LAG)>75 AND @IM2<HIST(@IM2,#LAG) AND @IM2>25 AND @CR3<@CR3CR AND (@LR>=HIST(@LR,1) OR CLOSE>@MA1)  
      BUY CLOSE
   ENDIF 
   'Shorts 
   IF HIST(@IM2,#LAG)<75 AND @IM2>HIST(@IM2,#LAG) AND @IM2<75 AND @CR3<@CR3CR AND (@LR<=HIST(@LR,1) OR CLOSE<@MA1) 
      SHORT CLOSE
   ENDIF 
    
   IF ORDERISOPEN>3 AND CLOSE<CLOSE(ORDERISOPEN)*(1-@STP/100) AND @STOC>75
      SELL CLOSE
   ENDIF
   IF ORDERISOPEN>7 AND CLOSE<PHIGH(CLOSE,ORDERISOPEN)*(1-@STP/100)
      SELL CLOSE 
   ENDIF
   IF ORDERISOPEN>3 AND CLOSE>CLOSE(ORDERISOPEN)*(1+@STP/100) AND @STOC<75
      COVER CLOSE
   ENDIF
   IF ORDERISOPEN>7 AND CLOSE>PLOW(CLOSE,ORDERISOPEN)*(1+@STP/100)
      COVER CLOSE
   ENDIF 
  
NEXT

A sample chart is shown in Figure 6.

Sample Chart

FIGURE 6: UPDATA. The intermarket system discussed in “Trading The Nikkei” in this issue is applied to the DXJ index.

—Updata support team
support@updata.co.uk
www.updata.co.uk

BACK TO LIST

logo

TRADERSSTUDIO: JULY 2017

The TradersStudio code based on Markos Katsanos’ article in this issue, “Trading The Nikkei,” is provided at www.TradersEdgeSystems.com/traderstips.htm and is also shown below.

The following code files are provided in the download:

The code is shown here:

'TRADING THE NIKKEI
'Author: Markos Katsanos, TASC July 2017
'Coded by: Richard Denning 5/15/17
'www.TradersEdgeSystems.com

Function LinearRegSlope(Price As BarArray, SLen) As BarArray
    Dim X As BarArray
    Dim Num1 As BarArray
    Dim Num2 As BarArray
    Dim SumBars As BarArray
    Dim SumSqrBars As BarArray
    Dim SumY As BarArray
    Dim Sum1 As BarArray
    Dim Sum2 As BarArray
    Dim Slope As BarArray
    Dim Intercept As BarArray

    If BarNumber=FirstBar Then
        X = 0
        Num1 = 0
        Num2 = 0
        SumBars = 0
        SumSqrBars = 0
        SumY = 0
        Sum1 = 0
        Sum2 = 0
        Slope = 0
        Intercept = 0
    End If

    If SLen = 0 Then
        LinearRegSlope = 0
    End If
    SumBars = 0
    SumSqrBars = 0
    SumY = 0
    Sum1 = 0
    Sum2 = 0
    SumY = Summation(Price, SLen)
    SumBars = SLen * (SLen - 1) * .5
    SumSqrBars = (SLen - 1) * SLen * (2 * SLen - 1) / 6
    For X = 0 To SLen - 1
        Sum1 = Sum1 + X * Price[X]
    Next
    Sum2 = SumBars * SumY
    Num1 = SLen * Sum1 - Sum2
    Num2 = SumBars * SumBars -SLen * SumSqrBars
    If Num2 <> 0 Then
        Slope = Num1 / Num2
    Else
        Slope = 0
    End If
    LinearRegSlope = Slope
End Function
'--------------------------------------------------------
Function CORRELATIONMK(SEC1 As BarArray, SEC2 As BarArray, D1)
   
    Dim Q1
    Dim Q2
    Dim Q3
    Dim Q2Q3
    Dim R

    If CurrentBar > D1 Then
        Q1=Summation((SEC1*(SEC2)),D1)-(Summation(SEC1,D1)*Summation(SEC2,D1)/D1)
        Q2=Summation(((SEC2)*(SEC2)),D1) - (Summation(SEC2,D1)*Summation(SEC2,D1)/D1)
        Q3=Summation((SEC1*SEC1),D1) - (Summation(SEC1,D1)*Summation(SEC1,D1)/D1)
        If Q2*Q3 >0 Then
            Q2Q3=Sqr(Q2*Q3)
        End If
        If Q2Q3 <> 0 Then
            R=Q1/Q2Q3
            If R <= 1 And R >= -1 Then
                CORRELATIONMK=R
            End If
        End If
    End If
End Function
'------------------------------------------------------------------------------------
Sub NIKKEI( STD, OB, D1, D2, DIVDAYS, IMDAYS, CR3CR, DIVCRIT, LAG, STP, EXITBARS)
 'STD = 25
 'OB = 90
 'D1 = 3
 'D2 = 25
 'DIVDAYS = 50
 'IMDAYS = 50
 'CR3CR = .8
 'DIVCRIT = 75
 'LAG = 3
 'STP = 1.5
 'EXITBARS = 11
    Dim SEC2 As BarArray 'FXY
    Dim SEC3 As BarArray 'SPY
    Dim MA1
    Dim IM2 As BarArray
    Dim DIVSHORT
    Dim STOC
    Dim OS
    Dim LR As BarArray
    Dim DIV2
    Dim RS1 As BarArray
    Dim RS2 As BarArray
    Dim b2
    Dim PRED2
    Dim a2
    Dim RS3 As BarArray
    Dim CR2
    Dim CR3
    SEC2 = Close Of Independent1 'FXY
    SEC3 = Close Of Independent2 'SPY
    If BarNumber=FirstBar Then    
        MA1 = 0
        IM2 = 0
        DIVSHORT = 0
        STOC = 0
        OS = 0
        LR = 0
        DIV2 = 0
        RS1 = 0
        RS2 = 0
        b2 = 0
        PRED2 = 0
        a2 = 0
        RS3 = 0
        CR2 = 0
        CR3 = 0
    End If
    OS=100-OB
    DIVSHORT=100-DIVCRIT
    STOC=(Average(C-Lowest(L, STD, 0), 3, 0)*100)/ (Average(Highest(H, STD, 0)-Lowest(L, STD, 0), 3, 0))
    MA1=Average(C, D2, 0)
    LR=100*LinearRegSLOPE(C, D2)
    If BarNumber>D1+D2 Then
        RS1=(C/C[D1]-1)*100
        RS2=(SEC2/SEC2[D1]-1)*100
        RS3=(SEC3/SEC3[D1]-1)*100
        CR2=CORRELATIONMK(RS1,RS2,DIVDAYS)
        CR3=CORRELATIONMK(RS1,RS3,DIVDAYS)
        b2=CR2*StdDev(RS1,DIVDAYS,1)/(StdDev(RS2,DIVDAYS,1)+.001)
        a2=Average(RS1, DIVDAYS, 0)-b2*Average(RS2, DIVDAYS, 0)
        PRED2=b2*RS2+a2
        DIV2=PRED2-RS1
    End If
    IM2=(Average(DIV2 - Lowest(DIV2, IMDAYS, 0), 2, 0)* 100)/ (Average(Highest(DIV2, IMDAYS, 0)- Lowest(DIV2, IMDAYS, 0), 2, 0)+.01)
    If BarNumber>DIVDAYS+D1+IMDAYS Then
        If IM2[LAG]>DIVCRIT And IM2<IM2[LAG] And IM2>DIVSHORT And CR3<CR3CR  And (LR>=LR[1] Or C>MA1) Then
            Buy("DIVJPY", 1, 0, Market, Day)
        End If
        If IM2[LAG]<DIVSHORT And IM2>IM2[LAG] And IM2<DIVCRIT And CR3<CR3CR And (LR<=LR[1] Or C<MA1) Then
            Sell("NDIVJPY", 1, 0, Market, Day)
        End If
    End If
    If BarsSinceEntry>3 And C<C[BarsSinceEntry]*(1-STP/100) And STOC>OS Then
        ExitLong("STOP", "", 1, 0, Market, Day)
    End If
    If BarsSinceEntry>=7 And C< Highest(C, BarsSinceEntry, 0)*(1-STP/100) Then
        ExitLong("TRAIL", "", 1, 0, Market, Day)
    End If
    If BarsSinceEntry>=3 And C>C[BarsSinceEntry]*(1+STP/100) And STOC<OB Then
        ExitShort("INITIAL STOP", "", 1, 0, Market, Day)
    End If
    If BarsSinceEntry>=7 And C>Lowest(C, BarsSinceEntry, 0)*(1+STP/100) Then
        ExitShort("TRAIL COVER", "", 1, 0, Market, Day)
    End If
    If BarsSinceEntry>=EXITBARS Then
        ExitLongAllPos("TIME", "", 0, Close, Day)
        ExitShortAllPos("TIMEX", "", 0, Close, Day)
    End If
End Sub

—Richard Denning
info@TradersEdgeSystems.com
for TradersStudio

BACK TO LIST

logo

AMIBROKER: JULY 2017

In “Trading The Nikkei” in this issue, author Markos Katsanos demonstrates a system based on the correlation between the Nikkei 225 and the Japanese yen. A ready-to-use formula that implements this simple trading system is presented here. Enter the formula in the formula editor in AmiBroker and press backtest to test the system.

Amibroker Code

Version( 6.20 ); 

function CorrelationMK( sec1, sec2, d1 ) 
{ 
     Q1 = Sum( sec1 * sec2, d1 ) - Sum( sec1, d1 ) * Sum( sec2, d1 ) / d1; 
     Q2 = Sum( sec2 * sec2, d1 ) - Sum( sec2, d1 ) * Sum( sec2, d1 ) / d1; 
     Q3 = Sum( sec1 * sec1, d1 ) - Sum( sec1, d1 ) * Sum( sec1, d1 ) / d1; 

     Q2Q3 = sqrt( Max( 0.0001, Q2 * Q3 ) ); 

     R = Q1 / Q2Q3; 

     return Max( -1, Min( 1, R ) ); 
} 

sec2 = Foreign( "FXY", "C" ); 
sec3 = Foreign( "SPY", "C" ); 

std = 25; 
ob = 90; 
d1 = 3; 
d2 = 25; 
divdays = 25; 
imdays = 50; 
cr3cr = 0.8; 
divcrit = 75; 
lag = 3; 
stp = 1.5; 
exit = 11; 

os = 100 - ob; 
divshort = 100 - divcrit; 
stoc = 100 * MA( C - LLV( L, std ), 3 ) / ( MA( HHV( H, std ) - LLV( L, std ), 3 ) ); 
MA1 = MA( C, D2 ); 
LR = 100 * LinRegSlope( C, D2 ); 

RS1 = ( C / Ref( C, -D1 ) - 1 ) * 100; 
RS2 = ( SEC2 / Ref( SEC2, -D1 ) - 1 ) * 100; 
RS3 = ( SEC3 / Ref( SEC3, -D1 ) - 1 ) * 100; 
CR2 = CorrelationMK( RS1, RS2, DIVDAYS ); 
CR3 = CorrelationMK( RS1, RS3, DIVDAYS ); 
b2 = CR2 * StDev( RS1, DIVDAYS ) / ( StDev( RS2, DIVDAYS ) + .001 ); 
a2 = MA( RS1, DIVDAYS ) - b2 * MA( RS2, DIVDAYS ); 
PRED2 = b2 * RS2 + a2; 
DIV2 = PRED2 - RS1; 

IM2 = 100 * MA( DIV2 - LLV( DIV2, IMDAYS ), 2 ) / ( MA( HHV( DIV2, IMDAYS ) - LLV( DIV2, IMDAYS ), 2 ) + .01 ); 

Buy = Ref( IM2, -LAG ) > DIVCRIT AND IM2 < Ref( IM2, -LAG ) AND IM2 > DIVSHORT 
       AND CR3 < CR3CR AND( LR >= Ref( LR, -1 ) OR C > MA1 ); 

Short = Ref( IM2, -LAG )< DIVSHORT AND IM2>Ref( IM2, -LAG ) AND IM2 < DIVCRIT 
         AND CR3 < CR3CR AND( LR <= Ref( LR, -1 ) OR C < MA1 ); 

BuyPrice = ShortPrice = Close; 
CoverPrice = SellPrice = Open; 

SetOption( "ActivateStopsImmediately", False ); 

Sell = Cover = 0; // exits by stops only 

// loss stop activated 3 days after entry 
//ApplyStop( stopTypeLoss, stopModePercent, stp, False, False, 0, 3 ); 
// trailing stop activated from 7th dat 
ApplyStop( stopTypeTrailing, stopModePercent, stp, False, False, 0, 7 ); 
// 11 bar stop 
ApplyStop( stopTypeNBar, stopModeBars, exit, False );

—Tomasz Janeczko, AmiBroker.com
www.amibroker.com

BACK TO LIST

Originally published in the July 2017 issue of
Technical Analysis of STOCKS & COMMODITIES magazine.
All rights reserved. © Copyright 2017, Technical Analysis, Inc.