TRADERS’ TIPS
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.
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.
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.
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
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.
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; }
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.
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"); } } } } }
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.
FIGURE 4: NEUROSHELL TRADER. This sample NeuroShell Trader chart displays the regression divergence indicator and trading system.
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.
FIGURE 5: NINJATRADER. The DivergenceSystem strategy takes four trades on a daily DXJ chart after calculating divergence from the FXY and SPY.
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.
FIGURE 6: UPDATA. The intermarket system discussed in “Trading The Nikkei” in this issue is applied to the DXJ index.
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
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 );