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.
Other code appearing in articles in this issue is posted in the Subscriber Area of our website at https://technical.traders.com/sub/sublogin.asp. Login requires your last name and subscription number (from mailing label). Once logged in, scroll down to beneath the “Optimized trading systems” area until you see “Code from articles.” From there, code can be copied and pasted into the appropriate technical analysis program so that no retyping of code is required for subscribers.
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 web page, data can be transferred with ease.
For this month’s Traders’ Tips, the focus is John Ehlers & Ric Way’s article in this issue, “Strategies With SwamiCharts.” Source code for Swami Charts renditions of several classic technical indicators (Aroon, CCI, RSI, and stochastics) for TradeStation and NinjaTrader may be downloaded for free from SwamiCharts.com. Thinkorswim users will find SwamiCharts indicators available on the thinkorswim platform. In addition, some EasyLanguage code for TradeStation is provided in Ehlers & Way’s article elsewhere in this issue. (Subscribers will also find the same code at the Subscriber Area of our website, Traders.com.) Presented here is additional code and possible implementations for other software.
In “Setting Strategies With SwamiCharts” in this issue, authors John Ehlers & Ric Way describe the use of SwamiCharts to examine market structure and analyze market waves and market trend. (The indicators are available at their website, www.swamicharts.com.) Presented here are three indicators corresponding to the ones introduced in their article.
To download the EasyLanguage code for the indicators, first navigate to the EasyLanguage FAQs and Reference Posts Topic in the EasyLanguage support forum (https://www.tradestation.com/Discussions/Topic.aspx?Topic_ID=47452), scroll down, and click on the link labeled “Traders’ Tips, TASC.” Then select the appropriate link for the month and year. The ELD filename is “_SwamiCharts_Apr2012.eld.”
The code is also shown below.
_BandPassFilter_JE (Indicator) { TASC, April, 2012 } { John Ehlers, Ric Way } { Band Pass Filter } inputs: Price(( High + Low ) / 2 ), Period( 20 ), BPDdelta( 0.1 ) ; variables: BPGamma( 0 ), BPAlpha( 0 ), BPBeta( 0 ), BP( 0 ) ; BPBeta = Cosine( 360 / Period ) ; BPGamma = 1 / Cosine( 720 * BPDdelta / Period ) ; BPAlpha = BPGamma - SquareRoot( BPGamma * BPGamma - 1 ) ; BP = 0.5 * ( 1 - BPAlpha ) * ( Price - Price[2] ) + BPBeta * ( 1 + BPAlpha ) * BP[1] - BPAlpha * BP[2] ; Plot1( BP ) ; Plot2( 0 ) ; { From "Empirical Mode Decomposition," March 2010 Stocks & Commodities } _CoronaSwingPos_JE (Indicator) { TASC, April, 2012 } { John Ehlers, Ric Way } { Corona Chart Swing Position written by John F. Ehlers copyright (c) 2008 The swing position indicator shows the phasing of the data within the dominant cycle. A value of -5 means the cycle is at its valley, while a value of +5 means the cycle is at its peak. In a pure cycle, the swing position will trace out the shape of a sine wave. } inputs: Price( ( High + Low ) / 2 ), LineR( 180 ), LineG( 255 ), LineB( 210 ), FuzzR( 0 ), FuzzG( 172 ), FuzzB( 64 ) ; variables: BPDelta( 0.1 ), BPGamma( 0 ), alpha( 0 ), BPBeta( 0 ), N( 0 ), Period( 0 ), MaxAmpl( 0 ), Num( 0 ), Denom( 0 ), DC( 0 ), DomCyc( 0 ), Color1( 0 ), Color2( 0 ), Color3( 0 ), alpha1( 0 ), HP( 0 ), SmoothHP( 0 ), gamma2( 0 ), alpha2( 0 ), beta2( 0 ), delta2( 0.1 ), BP2( 0 ), Q2( 0 ), Lead60( 0 ), HL( 0 ), LL( 0 ), count( 0 ), Psn( 0 ), Width( 0 ) ; arrays: IArray[60]( 0 ), OldI[60]( 0 ), OlderI[60]( 0 ), Q[60]( 0 ), OldQ[60]( 0 ), OlderQ[60]( 0 ), Real[60]( 0 ), OldReal[60]( 0 ), OlderReal[60]( 0 ), Imag[60]( 0 ), OldImag[60]( 0 ), OlderImag[60]( 0 ), Ampl[60]( 0 ), OldAmpl[60]( 0 ), DB[60]( 0 ), OldDB[60]( 0 ), Raster[50]( 0 ), OldRaster[50]( 0 ) ; alpha1 = ( 1 - Sine( 360 / 30 ) ) / Cosine( 360 / 30 ); HP = 0.5 * ( 1 + alpha1 ) * ( Price - Price[1] ) + alpha1 * HP[1] ; SmoothHP = ( HP + 2 * HP[1] + 3 * HP[2] + 3 * HP[3] + 2 * HP[4] + HP[5] ) / 12 ; if CurrentBar < 7 then SmoothHP = Price - Price[1] ; if CurrentBar = 1 then SmoothHP = 0 ; BPDelta = -0.015 * CurrentBar + 0.5 ; if BPDelta < 0.1 then BPDelta = 0.1 ; if CurrentBar > 12 then begin for N = 12 to 60 begin BPBeta = Cosine( 720 / N ) ; BPGamma = 1 / Cosine( 1440 * BPDelta / N ) ; alpha = BPGamma - SquareRoot( BPGamma * BPGamma - 1 ) ; Q[N] = ( 0.5 * N / 6.28318 ) * ( SmoothHP - SmoothHP[1] ) ; IArray[N] = SmoothHP ; Real[N] = 0.5 * ( 1 - alpha ) * ( IArray[N] - OlderI[N] ) + BPBeta * ( 1 + alpha ) * OldReal[N] - alpha * OlderReal[N] ; Imag[N] = 0.5 * ( 1 - alpha ) * ( Q[N] - OlderQ[N] ) + BPBeta * ( 1 + alpha )* OldImag[N] - alpha * OlderImag[N] ; Ampl[N] = ( Real[N] * Real[N] + Imag[N] * Imag[N] ) ; end ; end ; for N = 12 to 60 begin OlderI[N] = OldI[N] ; OldI[N] = IArray[N] ; OlderQ[N] = OldQ[N] ; OldQ[N] = Q[N] ; OlderReal[N] = OldReal[N] ; OldReal[N] = Real[N] ; OlderImag[N] = OldImag[N] ; OldImag[N] = Imag[N] ; OldAmpl[N] = Ampl[N] ; OldDB[N] = DB[N] ; end; for N = 1 to 50 begin OldRaster[N] = Raster[N] ; end ; MaxAmpl = Ampl[12] ; for N = 12 to 60 begin if Ampl[N] > MaxAmpl then MaxAmpl = Ampl[N] ; end; for N = 12 to 60 begin if MaxAmpl <> 0 and (Ampl[N] / MaxAmpl) > 0 then DB[N] = -10 * Log( 0.01 / ( 1 - 0.99 * Ampl[N] / MaxAmpl ) ) / Log( 10 ) ; DB[N] = 0.33 * DB[N] + 0.67 * OldDB[N] ; if DB[N] > 20 then DB[N] = 20 ; end ; Num = 0 ; Denom = 0 ; for N = 12 to 60 begin if DB[N] <= 6 then begin Num = Num + N * ( 20 - DB[N] ) ; Denom = Denom + ( 20 - DB[N] ) ; end ; if Denom <> 0 then DC = 0.5 * Num / Denom ; end ; DomCyc = Median( DC, 5 ) ; if DomCyc < 6 then DomCyc = 6 ; beta2 = Cosine( 360 / DomCyc ) ; gamma2 = 1 / Cosine( 720 * delta2 / DomCyc ) ; alpha2 = gamma2 - SquareRoot( gamma2 * gamma2 - 1 ) ; BP2 = 0.5 * ( 1 - alpha2 ) * ( Price - Price[2] ) + beta2 * ( 1 + alpha2 ) * BP2[1] - alpha2 * BP2[2] ; Q2 = ( DomCyc / 6.28318 ) * ( BP2 - BP2[1] ) ; Lead60 = 0.5 * BP2 + 0.866 * Q2 ; HL = Lead60 ; LL = Lead60 ; for count = 0 to 50 begin if Lead60[count] > HL then HL = Lead60[count] ; if Lead60[count] < LL then LL = Lead60[count] ; end ; Psn = ( Lead60 - LL ) / ( Hl - LL ) ; HL = Psn ; LL = Psn ; for count = 0 to 20 begin if Psn[count] > HL then HL = Psn[count] ; if Psn[count] < LL then LL = Psn[count] ; end ; if HL - LL > .85 then Width = .01 else Width = 0.15 * ( HL - LL ) ; for N = 1 to 50 begin Raster[N] = 20 ; if N < Round( 50 * Psn, 0 ) then Raster[N] = 0.5 * ( Power( ( 20 * Psn - 0.4 * N ) / Width, 0.95 ) + 0.5 * OldRaster[N] ) ; if N > Round( 50 * Psn, 0 ) then Raster[N] = 0.5 * ( Power( ( -20 * Psn + 0.4 * N ) / Width, 0.95 ) + 0.5 * OldRaster[N] ) ; if N = Round( 50 * Psn, 0 ) then Raster[N] = 0.5 * OldRaster[N] ; if Raster[N] < 0 then Raster[N] = 0 ; if Raster[N] > 20 then Raster[N] = 20 ; if HL - LL > 0.8 then Raster[N] = 20 ; OldRaster[N] = Raster[N] ; end ; Plot1( 10 * Psn - 5, "S51", RGB( LineR, LineG, LineB ), 0, 2 ) ; for N = 1 to 50 begin if Raster[N] <= 10 then begin Color1 = LineR + Raster[N]* (FuzzR - LineR) / 10 ; Color2 = LineG + Raster[N]* (FuzzG - LineG) / 10 ; Color3 = LineB + Raster[N]* (FuzzB - LineB) / 10 ; END; if Raster[N] > 10 then begin Color1 = FuzzR*(2 - Raster[N] / 10); Color2 = FuzzG*(2 - Raster[N] / 10); Color3 = FuzzB*(2 - Raster[N] / 10); END; if N = 2 then Plot2( 0.2 * N - 5, "S2", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 3 then Plot3( 0.2 * N - 5, "S3", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 4 then Plot4( 0.2 * N - 5, "S4", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 5 then Plot5( 0.2 * N - 5, "S5", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 6 then Plot6( 0.2 * N - 5, "S6", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 7 then Plot7( 0.2 * N - 5, "S7", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 8 then Plot8( 0.2 * N - 5, "S8", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 9 then Plot9( 0.2 * N - 5, "S9", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 10 then Plot10( 0.2 * N - 5, "S10", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 11 then Plot11( 0.2 * N - 5, "S11", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 12 then Plot12( 0.2 * N - 5, "S12", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 13 then Plot13( 0.2 * N - 5, "S13", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 14 then Plot14( 0.2 * N - 5, "S14", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 15 then Plot15( 0.2 * N - 5, "S15", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 16 then Plot16( 0.2 * N - 5, "S16", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 17 then Plot17( 0.2 * N - 5, "S17", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 18 then Plot18( 0.2 * N - 5, "S18", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 19 then Plot19( 0.2 * N - 5, "S19", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 20 then Plot20( 0.2 * N - 5, "S20", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 21 then Plot21( 0.2 * N - 5, "S21", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 22 then Plot22( 0.2 * N - 5, "S22", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 23 then Plot23( 0.2 * N - 5, "S23", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 24 then Plot24( 0.2 * N - 5, "S24", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 25 then Plot25( 0.2 * N - 5, "S25", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 26 then Plot26( 0.2 * N - 5, "S26", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 27 then Plot27( 0.2 * N - 5, "S27", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 28 then Plot28( 0.2 * N - 5, "S28", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 29 then Plot29( 0.2 * N - 5, "S29", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 30 then Plot30( 0.2 * N - 5, "S30", RGB( Color1, Color2, Color3 ), 0, 5 ) ; If N = 31 then Plot31( 0.2 * N - 5, "S31", RGB( Color1, Color2, Color3 ), 0, 5 ) ; If N = 32 then Plot32( 0.2 * N - 5, "S32", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 33 then Plot33( 0.2 * N - 5, "S33", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 34 then Plot34( 0.2 * N - 5, "S34", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 35 then Plot35( 0.2 * N - 5, "S35", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 36 then Plot36( 0.2 * N - 5, "S36", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 37 then Plot37( 0.2 * N - 5, "S37", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 38 then Plot38( 0.2 * N - 5, "S38", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 39 then Plot39( 0.2 * N - 5, "S39", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 40 then Plot40( 0.2 * N - 5, "S40", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 41 then Plot41( 0.2 * N - 5, "S41", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 42 then Plot42( 0.2 * N - 5, "S42", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 43 then Plot43( 0.2 * N - 5, "S43", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 44 then Plot44( 0.2 * N - 5, "S44", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 45 then Plot45( 0.2 * N - 5, "S45", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 46 then Plot46( 0.2 * N - 5, "S46", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 47 then Plot47( 0.2 * N - 5, "S47", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 48 then Plot48( 0.2 * N - 5, "S48", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 49 then Plot49( 0.2 * N - 5, "S49", RGB( Color1, Color2, Color3 ), 0, 5 ) ; if N = 50 then Plot50( 0.2 * N - 5, "S50", RGB( Color1, Color2, Color3 ), 0, 5 ) ; end ; _MarketMode_JE (Indicator) { TASC, April, 2012 } { John Ehlers, Ric Way } inputs: Price( ( High + Low ) /2 ), Period( 20 ), BPDelta( 0.5 ), Fraction( 0.1 ) ; variables: BPAlpha( 0 ), BPBeta( 0 ), BPGamma( 0 ), BP( 0 ), MeanCalc( 0 ), Peak( 0 ), Valley( 0 ), AvgPeak( 0 ), AvgValley( 0 ) ; BPBeta = Cosine( 360 / Period ) ; BPGamma = 1 / Cosine( 720 * BPDelta / Period ) ; BPAlpha = BPGamma - SquareRoot( BPGamma * BPGamma - 1 ) ; BP = 0.5 * ( 1 - BPAlpha ) * ( Price - Price[2] ) + BPBeta * ( 1 + BPAlpha ) * BP[1] - BPAlpha * BP[2] ; MeanCalc = Average( BP, 2 * Period ) ; Peak = Peak[1] ; Valley = Valley[1] ; if BP[1] > BP and BP[1] > BP[2] then Peak = BP[1] ; if BP[1] < BP and BP[1] < BP[2] then Valley = BP[1] ; AvgPeak = Average( Peak, 50 ) ; AvgValley = Average( Valley, 50 ) ; Plot1( MeanCalc, "Mean" ) ; Plot2( Fraction * AvgPeak, "Peak" ) ; Plot6( Fraction * AvgValley, "Valley" ) ; { From "Empirical Mode Decomposition" S&C March }
A sample chart implementing the SwamiCharts indicators is shown in Figure 1.
FIGURE 1: TRADESTATION, SWAMICHARTS INDICATORS. A daily bar chart of @ES.D along with the _CoronaSwingPos_JE and _MarketMode_JE indicators is shown here.
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.
For this month’s Traders’ Tip, we’ve provided the formulas, Corona_Chart_Swing_Position.efs, Market_Mode_Indicator.efs, and SwamiCharts_Market_Mode.efs based on the formula code from John Ehlers & Ric Way’s article in this issue, “Setting Strategies With SwamiCharts.”
The SwamiCharts_Market_Mode.efs study contains formula parameters to set the values for the fastest period, lowest period, delta, fraction, price, and line thickness, which may be configured through the Edit Chart window (right-click on the chart and select Edit Chart). The Market_Mode_Indicator.efs study contains formula parameters to set the values for length, delta, fraction and price. The SwamiCharts_Market_Mode.efs study contains one formula parameter to toggle the View Line.
To discuss this study or download complete copies 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 scripts (EFS) are also available for copying and pasting below.
Corona_Chart_Swing_Position.efs /********************************* Provided By: eSignal (Copyright c eSignal), a division of Interactive Data Corporation. 2012. 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: Setting Strategies With SwamiCharts Version: 1.00 13/02/2012 Notes: The swing position indicator shows the phasing of the data within the dominant cycle. A value of -5 means the cycle is at its valley. A value of +5 means the cycle is at its peak. In a pure cycle the Swing Position will trace out the shape of a sine wave. The related article is copyrighted material. If you are not a subscriber of Stocks & Commodities, please visit www.traders.com. Formula Parameters: Default: View Line True **********************************/ var fpArray = new Array(); var bInit = false; var bVersion = null; function preMain() { setPriceStudy(false); setShowCursorLabel(false); setShowTitleParameters( false ); setStudyTitle("Corona Chart Swing Position"); setDefaultBarThickness(3, 50); var x=0; fpArray[x] = new FunctionParameter("ViewLine", FunctionParameter.BOOLEAN); with(fpArray[x++]){ setName("View Line"); setDefault(true); } } var nLineR = 180; var nLineG = 255; var nLineB = 210; var nFuzzR = 0; var nFuzzG = 172; var nFuzzB = 64; var xPrice = null; var nRef_Global = 0; var ndelta = 0.1; var ngamma = 0; var nalpha = 0; var nbeta = 0; var nN = 0; var nPeriod = 0; var nMaxAmpl = 0; var nNum = 0; var nDenom = 0; var nDC = 0; var nDomCyc = 0; var nColor1 = 0; var nColor2 = 0; var nColor3 = 0; var nalpha1 = 0; var xHP = null; var nSmoothHP = 0; var nSmoothHP1 = 0; var ngamma2 = 0; var nalpha2 = 0; var nbeta2 = 0; var ndelta2 = 0.1; var nBP2 = 0; var nBP2_1 = 0; var nBP2_2 = 0; var nQ2 = 0; var nHL = 0; var nLL = 0; var ncount = 0; var nWidth = 0; var nCalc_HP_Ref = 0; var xResultArray = new Array(51); var aI = new Array(61); var aOldI = new Array(61); var aOlderI = new Array(61); var aQ = new Array(61); var aOldQ = new Array(61); var aOlderQ = new Array(61); var aReal = new Array(61); var aOldReal = new Array(61); var aOlderReal = new Array(61); var aImag = new Array(61); var aOldImag = new Array(61); var aOlderImag = new Array(61); var aAmpl = new Array(61); var aOldAmpl = new Array(61); var aDB = new Array(61); var aOldDB = new Array(61); var aDC = new Array(61); var aPsn = new Array(61); var aRaster = new Array(51); var aOldRaster = new Array(51); var aLead60 = new Array(51); function main(ViewLine) { var nResCounter = 0; var nState = getBarState(); var pi = 3.1415926; var nCounter = 0; if (bVersion == null) bVersion = verify(); if (bVersion == false) return; if (nState == BARSTATE_ALLBARS) { resetVars(); } nalpha1 = (1 - (Math.sin(pi * (360 / 30) / 180)) / (Math.cos(pi * (360 / 30) / 180))); if ( bInit == false ) { bShowDC = ViewLine; xPrice = hl2(); xHP = efsInternal("Calc_HP", xPrice, nalpha1); bInit = true; drawTextPixel( 10, 10,"J Corona Chart Swing Position", Color.black, null, Text.RELATIVETOLEFT | Text.RELATIVETOTOP, "Name" ,10, -10 ); } if (getCurrentBarCount() < 5) return; if (nState == BARSTATE_NEWBAR) { nSmoothHP1 = nSmoothHP; aDC.pop(); aDC.unshift(nDC); aLead60.pop(); aLead60.unshift(0.5 * nBP2 + 0.866 * nQ2); aPsn.pop(); aPsn.unshift((aLead60[0] - nLL) / (nHL - nLL)); nBP2_2 = nBP2_1; nBP2_1 = nBP2; for (nN = 12; nN <= 60; nN++) { aOlderI[nN] = aOldI[nN]; aOldI[nN] = aI[nN]; aOlderQ[nN] = aOldQ[nN]; aOldQ[nN] = aQ[nN]; aOlderReal[nN] = aOldReal[nN]; aOldReal[nN] = aReal[nN]; aOlderImag[nN] = aOldImag[nN]; aOldImag[nN] = aImag[nN]; aOldAmpl[nN] = aAmpl[nN]; aOldDB[nN] = aDB[nN]; } } nSmoothHP = 0 if (xPrice.getValue(-1) != null) nSmoothHP = xPrice.getValue(0) - xPrice.getValue(-1); if (xHP.getValue(-5) != null) { nSmoothHP = (xHP.getValue(0) + 2 * xHP.getValue(-1) + 3 * xHP.getValue(-2) + 3 * xHP.getValue(-3) + 2 * xHP.getValue(-4) + xHP.getValue(-5)) / 12; } ndelta = (-0.015) * getCurrentBarCount() + 0.5; if (ndelta < 0.1) ndelta = 0.1; if (getCurrentBarCount() > 12) { for (nN = 12; nN <= 60; nN++) { nbeta = Math.cos(pi * (720 / nN) / 180); ngamma = 1 / Math.cos(pi * (1440 * ndelta / nN) / 180); nalpha = ngamma - Math.sqrt(ngamma * ngamma - 1); aQ[nN] = (0.5 * nN / 6.28318) * (nSmoothHP - nSmoothHP1); aI[nN] = nSmoothHP; aReal[nN] = 0.5 * (1 - nalpha) * (aI[nN] - aOlderI[nN]) + nbeta * (1 + nalpha) * aOldReal[nN] - nalpha * aOlderReal[nN]; aImag[nN] = 0.5 * (1 - nalpha) * (aQ[nN] - aOlderQ[nN]) + nbeta * (1 + nalpha) * aOldImag[nN] - nalpha * aOlderImag[nN]; aAmpl[nN] = (aReal[nN] * aReal[nN] + aImag[nN] * aImag[nN]); } } nMaxAmpl = aAmpl[12]; for (nN = 12; nN <= 60; nN++) { if (aAmpl[nN] > nMaxAmpl) nMaxAmpl = aAmpl[nN]; } for (nN = 12; nN <= 60; nN++) { if (nMaxAmpl != 0 && (aAmpl[nN] / nMaxAmpl) > 0) aDB[nN] = (-10) * Math.log(0.01 / (1 - 0.99 * aAmpl[nN] / nMaxAmpl)) / Math.log(10); aDB[nN] = 0.33 * aDB[nN] + 0.67 * aOldDB[nN]; if (aDB[nN] > 20) aDB[nN] = 20; } nNum = 0; nDenom = 0; for (nN = 12; nN <= 60; nN++) { if (aDB[nN] <= 6) { nNum = nNum + nN * (20 - aDB[nN]); nDenom = nDenom + (20 - aDB[nN]); } if (nDenom != 0) { nDC = 0.5 * nNum / nDenom; aDC[0] = nDC; } } nDomCyc = Median(aDC, 5); if (nDomCyc < 6) nDomCyc = 6; nbeta2 = Math.cos(pi * (360 / nDomCyc) / 180); ngamma2 = 1 / Math.cos(pi * (720 * ndelta2 / nDomCyc) / 180); nalpha2 = ngamma2 - Math.sqrt(ngamma2 * ngamma2 - 1); nBP2 = 0.5 * (1 - nalpha2) * (xPrice.getValue(0) - xPrice.getValue(-1)) + nbeta2 * (1 + nalpha2) * nBP2_1 - nalpha2 * nBP2_2; nQ2 = (nDomCyc / 6.28318)*(nBP2 - nBP2_1); aLead60[0] = 0.5 * nBP2 + 0.866 * nQ2; nHL = aLead60[0]; nLL = aLead60[0]; for (ncount = 0; ncount < 51; ncount++) { if (aLead60[ncount] > nHL) nHL =aLead60[ncount]; if (aLead60[ncount] < nLL) nLL = aLead60[ncount]; } aPsn[0] = (aLead60[0] - nLL) / (nHL - nLL); nHL = aPsn[0]; nLL = aPsn[0]; for (ncount = 0; ncount < 21; ncount++) { if (aPsn[ncount] > nHL) nHL = aPsn[ncount]; if (aPsn[ncount] < nLL) nLL = aPsn[ncount]; } if (nHL - nLL > 0.85) { nWidth = 0.01 } else { nWidth = 0.15 * (nHL - nLL);} for (nN = 1; nN < 51; nN++) { aRaster[nN] = 20; if (nN < Math.round(50 * aPsn[0])) aRaster[nN] = 0.5 * (Math.pow(((20 * aPsn[0] - 0.4 * nN) / nWidth), 0.95) + 0.5 * aOldRaster[nN]); if (nN > Math.round(50 * aPsn[0])) aRaster[nN] = 0.5 * (Math.pow((((-20) * aPsn[0] + 0.4 * nN) / nWidth), 0.95) + 0.5 * aOldRaster[nN]); if (nN == Math.round(50 * aPsn[0])) aRaster[nN] = 0.5 * aOldRaster[nN]; if (aRaster[nN] < 0) aRaster[nN] = 0; if (aRaster[nN] > 20) aRaster[nN] = 20; if (nHL - nLL > 0.8) aRaster[nN] = 20; aOldRaster[nN] = aRaster[nN]; } for (nN = 1; nN < 51; nN++) { if (aRaster[nN] <= 10) { nColor1 = Math.round(nLineR + aRaster[nN] * (nFuzzR - nLineR) / 10); nColor2 = Math.round(nLineG + aRaster[nN] * (nFuzzG - nLineG) / 10); nColor3 = Math.round(nLineB + aRaster[nN] * (nFuzzB - nLineB) / 10); } if (aRaster[nN] > 10) { nColor1 = Math.round(nFuzzR * (2 - aRaster[nN] / 10)); nColor2 = Math.round(nFuzzG * (2 - aRaster[nN] / 10)); nColor3 = Math.round(nFuzzB * (2 - aRaster[nN] / 10)); } xResultArray[nResCounter++] = 0.2 * nN - 5; setBarFgColor(Color.RGB(nColor1, nColor2, nColor3), nResCounter-1); setPlotType(PLOTTYPE_LINE, nResCounter-1); setBarThickness(5, nResCounter-1); } if (bShowDC == true) { xResultArray[nResCounter++] = (10 * aPsn[0] - 5); setBarFgColor(Color.RGB(nLineR, nLineG, nLineB), nResCounter-1); } return xResultArray; } function resetVars() { nRef_Global = 0; ndelta = 0.1; ngamma = 0; nalpha = 0; nbeta = 0; nN = 0; nPeriod = 0; nMaxAmpl = 0; nNum = 0; nDenom = 0; nDC = 0; nDomCyc = 0; nColor1 = 0; nColor2 = 0; nColor3 = 0; nalpha1 = 0; nSmoothHP = 0; nSmoothHP1 = 0; ngamma2 = 0; nalpha2 = 0; nbeta2 = 0; ndelta2 = 0.1; nBP2 = 0; nBP2_1 = 0; nBP2_2 = 0; nQ2 = 0; nHL = 0; nLL = 0; ncount = 0; nWidth = 0; nCalc_HP_Ref = 0; for (var i = 0; i < 61; i++) { if (i < 51) xResultArray[i] = null; aI[i] = 0; aOldI[i] = 0; aOlderI[i] = 0; aQ[i] = 0; aOldQ[i] = 0; aOlderQ[i] = 0; aReal[i] = 0; aOldReal[i] = 0; aOlderReal[i] = 0; aImag[i] = 0; aOldImag[i] = 0; aOlderImag[i] = 0; aAmpl[i] = 0; aOldAmpl[i] = 0; aDB[i] = 0; aOldDB[i] = 0; aDC[i] = 0; aPsn[i] = 0; } for (var i = 0; i < 51; i++) { aRaster[i] = 0; aOldRaster[i] = 0; aLead60[i] = 0; } return; } // calcHP globals var nPrevHP = null; var nCurrHP = null; function Calc_HP(x, nAlpha1) { var nHP = null; if (getCurrentBarCount() <= 5 ) { nCurrHP = x.getValue(0); return nCurrHP; } else { if (x.getValue(-1) == null) return null; if (getBarState() == BARSTATE_NEWBAR) nPrevHP = nCurrHP; nCurrHP = ( 0.5*(1 + nAlpha1)*(x.getValue(0) - x.getValue(-1)) + nAlpha1*nPrevHP ); return nCurrHP; } } function Median(myArray, Length) { var aArray = new Array(Length); var nMedian = null; for (var i = 0; i < Length; i++) { aArray[i] = myArray[i]; } aArray = aArray.sort(compareNumbers); nMedian = aArray[Math.round((Length-1)/2)]; return nMedian; } function compareNumbers(a, b) { return a - b } function verify() { var b = false; if (getBuildNumber() < 779) { drawTextAbsolute(5, 35, "This study requires version 8.0 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; }
Market_Mode_Indicator.efs /********************************* Provided By: eSignal (Copyright c eSignal), a division of Interactive Data Corporation. 2012. 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: Setting Strategies With SwamiCharts Version: 1.00 13/02/2012 Formula Parameters: Default: Length 20 Delta 0.5 Fraction 0.1 Price hl2 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(); var bInit = false; var bVersion = null; function preMain() { setPriceStudy(false); setShowCursorLabel(true); setShowTitleParameters(false); setStudyTitle("Market Mode Indicator"); setCursorLabelName("Mean", 0); setDefaultBarFgColor(Color.red, 0); setPlotType(PLOTTYPE_LINE, 0); setDefaultBarThickness(2, 0); setCursorLabelName("Peak", 1); setDefaultBarFgColor(Color.blue, 1); setPlotType(PLOTTYPE_LINE, 1); setDefaultBarThickness(2, 1); setCursorLabelName("Valley", 2); setDefaultBarFgColor(Color.blue, 2); setPlotType(PLOTTYPE_LINE, 2); setDefaultBarThickness(2, 2); var x=0; fpArray[x] = new FunctionParameter("Length", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Length"); setLowerLimit(1); setDefault(20); } fpArray[x] = new FunctionParameter("Delta", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Delta"); setLowerLimit(0.00001); setDefault(0.5); } fpArray[x] = new FunctionParameter("Fraction", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Fraction"); setLowerLimit(0.00001); setDefault(0.1); } fpArray[x] = new FunctionParameter("Price", FunctionParameter.STRING); with(fpArray[x++]){ setName("Price Source"); addOption("open"); addOption("high"); addOption("low"); addOption("close"); addOption("hl2"); addOption("hlc3"); addOption("ohlc4"); setDefault("hl2"); } } var xEmpiricalModeDecomposition_Mean = null; var xEmpiricalModeDecomposition_Peak = null; var xEmpiricalModeDecomposition_Valley = null; function main(Length, Delta, Fraction, Price) { var nBarState = getBarState(); var nEmpiricalModeDecomposition_Mean = 0; var nEmpiricalModeDecomposition_Peak = 0; var nEmpiricalModeDecomposition_Valley = 0; if (bVersion == null) bVersion = verify(); if (bVersion == false) return; if (nBarState == BARSTATE_ALLBARS) { if (Length == null) Length = 20; if (Delta == null) Delta = 0.5; if (Fraction == null) Fraction = 0.1; if (Price == null) Price = "hl2"; } if (bInit == false) { xEmpiricalModeDecomposition_Mean = efsInternal("Calc_EmpiricalModeDecomposition", Length, Delta, Fraction, Price); xEmpiricalModeDecomposition_Peak = getSeries(xEmpiricalModeDecomposition_Mean, 1); xEmpiricalModeDecomposition_Valley = getSeries(xEmpiricalModeDecomposition_Mean, 2); bInit = true; } nEmpiricalModeDecomposition_Mean = xEmpiricalModeDecomposition_Mean.getValue(0); nEmpiricalModeDecomposition_Peak = xEmpiricalModeDecomposition_Peak.getValue(0); nEmpiricalModeDecomposition_Valley = xEmpiricalModeDecomposition_Valley.getValue(0); if (nEmpiricalModeDecomposition_Mean == null || nEmpiricalModeDecomposition_Peak == null || nEmpiricalModeDecomposition_Valley == null) return; return new Array(nEmpiricalModeDecomposition_Mean, nEmpiricalModeDecomposition_Peak, nEmpiricalModeDecomposition_Valley); } var bSecondInit = false; var xMean = null; var xAvrPeak = null; var xAvrValley = null; function Calc_EmpiricalModeDecomposition(Length, Delta, Fraction, Price) { var nMean = 0; var nAvrPeak = 0; var nAvrValley = 0; if (bSecondInit == false) { xMean = efsInternal("Calc_Mean_Peak_Valley", Length, Delta, Price); xAvrPeak = sma(50, getSeries(xMean, 1)); xAvrValley = sma(50, getSeries(xMean, 2)); bSecondInit = true; } nMean = xMean.getValue(0); nAvrPeak = xAvrPeak.getValue(0); nAvrValley = xAvrValley.getValue(0); if (nMean == null || nAvrPeak == null || nAvrValley == null) return; nAvrPeak = Fraction * nAvrPeak; nAvrValley = Fraction * nAvrValley; return new Array(nMean, nAvrPeak, nAvrValley); } var bMPVInit = false; var nPeak = 0; var nValley = 0; function Calc_Mean_Peak_Valley(Length, Delta, Price) { var nMean = 0; var BP = 0; var BP1 = 0; var BP2 = 0; if (bMPVInit == false) { xBandpassFilter = efsInternal("Calc_BandpassFilter", Length, Delta, Price); xMean = sma(2 * Length, xBandpassFilter); bMPVInit = true; } nMean = xMean.getValue(0); BP = xBandpassFilter.getValue(0); BP1 = xBandpassFilter.getValue(-1); BP2 = xBandpassFilter.getValue(-2); if (BP1 > BP && BP1 > BP2) { nPeak = BP1; } if (BP1 < BP && BP1 < BP2) { nValley = BP1; } return new Array(nMean, nPeak, nValley); } var bThirdInit = false; var xPrice = null; function Calc_BandpassFilter(Length, Delta, Price) { var gamma = 0; var alpha = 0; var beta = 0; var BP = 0; var BP1 = ref(-1); var BP2 = ref(-2); if (bThirdInit == false) { xPrice = eval(Price)(); bThirdInit = true; } if (xPrice.getValue(-2) == null) return; beta = Math.cos(Math.PI * (360 / Length) / 180); gamma = 1 / Math.cos(Math.PI * (720 * Delta / Length) / 180); alpha = gamma - Math.sqrt(gamma * gamma - 1); BP = 0.5 * (1 - alpha) * (xPrice.getValue(0) - xPrice.getValue(-2)) + beta * (1 + alpha) * BP1 - alpha * BP2; return BP; } function verify() { var b = false; if (getBuildNumber() < 779) { drawTextAbsolute(5, 35, "This study requires version 8.0 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; }
SwamiCharts_Market_Mode.efs /********************************* Provided By: eSignal (Copyright © eSignal), a division of Interactive Data Corporation. 2012. 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: Setting Strategies With SwamiCharts Version: 1.00 13/02/2012 Formula Parameters: Default: Fastest Period 12 Lowest Period 48 Delta 0.5 Fraction 0.1 Price hl2 Line Thickness 5 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(); var bInit = false; var bVersion = null; function preMain() { setStudyTitle("Swami Market Mode"); setShowCursorLabel(false); setPriceStudy(false); setShowTitleParameters(false); setComputeOnClose(true); var x=0; fpArray[x] = new FunctionParameter("gFastPeriod", FunctionParameter.NUMBER); with(fpArray[x++]) { setName("Fastest Period"); setLowerLimit(1); setUpperLimit(20); setDefault(12); } fpArray[x] = new FunctionParameter("gSlowPeriod", FunctionParameter.NUMBER); with(fpArray[x++]) { setName("Lowest Period"); setLowerLimit(40); setUpperLimit(100); setDefault(48); } fpArray[x] = new FunctionParameter("gDelta", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Delta"); setLowerLimit(0.00001); setDefault(0.5); } fpArray[x] = new FunctionParameter("gFraction", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Fraction"); setLowerLimit(0.00001); setDefault(0.1); } fpArray[x] = new FunctionParameter("gPrice", FunctionParameter.STRING); with(fpArray[x++]){ setName("Price Source"); addOption("open"); addOption("high"); addOption("low"); addOption("close"); addOption("hl2"); addOption("hlc3"); addOption("ohlc4"); setDefault("hl2"); } fpArray[x] = new FunctionParameter("gLineThickness", FunctionParameter.NUMBER); with(fpArray[x++]) { setName("Line Thickness"); setLowerLimit(1); setUpperLimit(20); setDefault(5); } } var resArray = null; var xMeanArray = null; function main(gFastPeriod, gSlowPeriod, gDelta, gFraction, gPrice, gLineThickness) { var nBarState = getBarState(); if (bVersion == null) bVersion = verify(); if (bVersion == false) return; if (!bInit) { resArray = new Array(); xMeanArray = new Array(); for (var i = gFastPeriod; i <= gSlowPeriod; i++) { resArray.push(i); var xBandpassFilter = efsInternal("Calc_BandpassFilter", i, gDelta, gPrice); var xMean = sma(2 * i, xBandpassFilter); xMeanArray.push(xMean); setDefaultBarThickness(gLineThickness, i - gFastPeriod); } bInit = true; } for (var i = 0; i <= gSlowPeriod - gFastPeriod; i++) { var nMean = xMeanArray[i].getValue(0); if (nMean == null) return; var colorR = 255; var colorG = 255; var colorB = 0; if (nMean > 0) { if (nMean <= 1) colorR = -255 * nMean + 255; else colorR = 0; } else { if (nMean >= -1) colorG = 255 * nMean + 255; else colorG = 0; } setBarFgColor(Color.RGB(colorR, colorG, colorB), i); } return resArray; } var bSecondInit = false; var xPrice = null; function Calc_BandpassFilter(Length, gDelta, gPrice) { var gamma = 0; var alpha = 0; var beta = 0; var BP = 0; var BP1 = ref(-1); var BP2 = ref(-2); if (!bSecondInit) { xPrice = eval(gPrice)(); bSecondInit = true; } if (xPrice.getValue(-2) == null) return; beta = Math.cos(Math.PI * (360 / Length) / 180); gamma = 1 / Math.cos(Math.PI * (720 * gDelta / Length) / 180); alpha = gamma - Math.sqrt(gamma * gamma - 1); BP = 0.5 * (1 - alpha) * (xPrice.getValue(0) - xPrice.getValue(-2)) + beta * (1 + alpha) * BP1 - alpha * BP2; return BP; } function verify() { var b = false; if (getBuildNumber() < 779) { drawTextAbsolute(5, 35, "This study requires version 8.0 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; }
A sample chart is shown in Figure 2.
FIGURE 2: eSIGNAL, SWAMICHARTS INDICATORS
This Traders’ Tip is based on “Setting Strategies With SwamiCharts” by John Ehlers & Ric Way in this issue.
Our rendition of the SwamiCharts market mode indicator in WealthScript C# code is conveniently available for customers through the Strategy Download feature. However, since the EasyLanguage code was not provided in Ehlers & Way’s article for the SwamiCharts version of the market mode indicator, it seems that the yellow levels in our implementation corresponding to the cycle mode are not properly represented by our current color-coding algorithm, in which we’ve used an inverse Fisher transform to clip the trend/cycle amplitude ratio so that it remains between -1 and +1, the red and green levels, respectively (Figure 3).
FIGURE 3: WEALTH-LAB, SWAMICHARTS MARKET MODE INDICATOR IMPLEMENTATION. Our attempt at the SwamiCharts market mode chart probably requires more work to better identify the swing trading opportunities (shown in yellow).
Wealth-Lab 6 Strategy Code (C#): using System; using System.Collections.Generic; using System.Text; using System.Drawing; using WealthLab; using WealthLab.Indicators; namespace WealthLab.Strategies { public class SwamiMarketMode : WealthScript { StrategyParameter _plotWidth; StrategyParameter _delta; StrategyParameter _fraction; public SwamiMarketMode() { _plotWidth = CreateParameter("Plot Width", 6, 2, 10, 1); _delta = CreateParameter("Delta", 0.5, 0.05, 1, 0.05); _fraction = CreateParameter("Fraction", 0.1, 0.05, 1, 0.05); } public DataSeries BandPassSeries(DataSeries ds, int period, double delta) { DataSeries res = new DataSeries(ds, "BandPassSeries(" + ds.Description + "," + period + "," + delta + ")"); double beta = Math.Cos(2 * Math.PI / period); double gamma = 1/ Math.Cos(4 * Math.PI * delta / period); double alpha = gamma - Math.Sqrt(gamma * gamma - 1d); for (int bar = 2; bar < ds.Count; bar++) { res[bar] = 0.5 * (1 - alpha) * (ds[bar] - ds[bar - 2]) + beta * (1 + alpha) * res[bar - 1] - alpha * res[bar - 2]; } return res; } public void SwamiMarketModeHeatMap(Bars bars, int plotThickness) { const double k = 1; int r = 0; int g = 0; int b = 0; string s = Bars.ToString() + ")"; DataSeries swMktMode = new DataSeries(bars, "swami(" + s); DataSeries[] swami = new DataSeries[49]; // Create and plot the heatmap series (change bar colors later) HideVolume(); HidePaneLines(); ChartPane swPane = CreatePane(50, false, false ); for( int n = 12; n < 49; n++ ) { swami[n] = swMktMode + n; swami[n].Description = "SwamiSto." + n.ToString(); PlotSeries(swPane, swami[n], Color.LightGray, LineStyle.Solid, plotThickness); } for (int n = 12; n < 49; n++) { DataSeries bp = BandPassSeries(AveragePrice.Series(bars), n, _delta.Value); DataSeries mean = SMA.Series(bp, 2 * n); DataSeries peak = new DataSeries(Bars, "peak()"); DataSeries valley = new DataSeries(Bars, "valley()"); double pk = 0d; double v = 0d; for(int bar = 2; bar < Bars.Count; bar++) { if( bp[bar-1] > bp[bar] && bp[bar-1] > bp[bar-2] ) pk = bp[bar - 1]; if( bp[bar-1] < bp[bar] && bp[bar-1] < bp[bar-2] ) v = bp[bar-1]; peak[bar] = pk; valley[bar] = v; } int avgPer = (int)(2.5 * n); DataSeries avgPeak = _fraction.Value * SMA.Series(peak, avgPer); DataSeries avgValley = _fraction.Value * SMA.Series(valley, avgPer); for(int bar = 4; bar < Bars.Count; bar++) { double amp = avgPeak[bar] - avgValley[bar]; if (amp == 0) continue; // ratio of trend slope to cycle amplitude double ratio = mean[bar] / amp; // Inverse Fisher Transform ratio = (Math.Exp(2 * ratio) - 1)/ (Math.Exp(2 * ratio) + 1); if (ratio > 0) { r = Convert.ToInt32(255 * (k - ratio)); g = 255; } else { r = 255; g = Convert.ToInt32(255 * (k + ratio)); } SetSeriesBarColor(bar, swami[n], Color.FromArgb(r, g, b)); } } } protected override void Execute() { SwamiMarketModeHeatMap(Bars, _plotWidth.ValueInt); } } }
In “Setting Strategies With SwamiCharts” in this issue, authors John Ehlers & Ric Way present new examples of their SwamiCharts, which were introduced in last month’s S&C article, “Introducing SwamiCharts.”
The AmiBroker code for the first chart type presented in their article, corona charts, can be found in the October 2008 Traders’ Tips section (which can be found at Traders.com). Our implementation of the SwamiCharts market mode indicator is shown here. To use it, enter the formula in the AFL Editor, then press the Insert Indicator button to see a chart (Figure 4).
PI = 3.1415926; function BandPass( input, period, delta ) { beta = cos( 2 * PI / period ); gamma = 1 / cos( 4 * delta / period ); alpha = gamma - sqrt( gamma * gamma - 1 ); bp = 0; mom = input - Ref( input, -2 ); for( i = 2; i < BarCount; i++ ) bp[ i ] = 0.5 * ( 1 - alpha ) * mom[ i ] + beta * ( 1 + alpha ) * bp[ i - 1 ] - alpha * bp[ i - 2 ]; return bp; } delta = 0.5; fraction = Param("fraction", 0.1, 0, 1, 0.01 ); for ( period = 10; period < 50; period++ ) { bp = BandPass( ( H + L )/2, period, delta ); mean = MA( bp, 2 * period ); bp1 = Ref( bp, -1 ); bp2 = Ref( bp, -2 ); pk = ValueWhen( bp1 > bp AND bp1 > bp2, bp1 ); Vl = ValueWhen( bp1 < bp AND bp1 < bp2, bp1 ); AvgPk = MA( pk, 50 ); AvgVl = MA( Vl, 50 ); amp = ( AvgPk - AvgVl ); i3 = mean / ( fraction * amp ); indicator = 1 + Min( 1, Max( -1, i3 ) ); Color = ColorHSB( 32 * indicator, 255, 255 ); N = period; PlotOHLC( N, N+1, N, N, "", Color, styleCloud | styleNoLabel ); } Title = "Market Mode Swami chart";
FIGURE 4: AMIBROKER, SWAMICHARTS MARKET MODE INDICATOR. Here is a daily chart of SPY (upper pane) with the SwamiCharts market mode indicator (lower pane).
Last month, we presented a neural network approach to implement John Ehlers & Ric Way’s SwamiCharts based on their article in the March 2012 S&C, “Introducing SwamiCharts.” This month, we once again used the neural networks in NeuroShell Trader to transform the visual discretionary information in SwamiCharts into an analytical trading system, based on their article in this issue, “Setting Strategies With SwamiCharts.”
We applied the bandpass filter indicator described in the article to daily, weekly, and monthly time frames of the close. (We used the NeuroShell Trader Power User version, which can incorporate different time frames in the same trading system.) We selected those three different bandpass filter indicators as inputs to a neural network in order to predict the one-bar percent change in the open. We then combined the trading signals from the neural network with trading rules that made sure the market mode indicator was below the upper trend indicator and above the lower trend indicator, which were described in Ehlers & Way’s March 2010 article in S&C, “Empirical Mode Decomposition.”
No scripting, coding, or programming of any kind was involved. The chart was created using the wizards in NeuroShell Trader.
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 5.
FIGURE 5: NEUROSHELL TRADER, SWAMICHARTS INDICATORS. This NeuroShell Trader chart displays the neural network prediction that used bandpass filters of the close for three different time frames as inputs to the net. The neural network trading signals were then filtered by the Market Mode indicator to determine when to trade the cycle.
The AIQ code based on David Garrard’s article from the May 2011 S&C, “Putting a Stop To It,” is provided at the TradersEdgeSystems.com website.
Coding stops for backtesting can be daunting, especially the average true range (ATR) stops discussed by the author. I have provided code for the following types of stops for both longs and shorts:
The exits can be combined by joining the rule names using the “and” keyword.
In my implementation of the ATR-based stops, I lock the ATR at its value on the signal day (that is, the day before the entry day) to prevent the stop from moving once the position is entered, should the ATR value increase.
These stops can only be used for backtesting, since they use the application fields of position values that are filled only upon running a backtest. The stop values have not been coded so as to be able to be displayed on an EDS custom report. To do so requires coding in the stock symbol and the entry price, and this would likely be done only for actual trades.
The code and EDS file can be downloaded from www.TradersEdgeSystems.com/traderstips.htm.
!PUTTING A STOP TO IT !Author: David Garrard, TASC May 2011 !Coded by: Richard Denning 2/14/2012 !www.TradersEdgesystems.com !NOTE: ALL STOPS ARE FOR END OF DAY TRADING WHERE THE EXIT ! OCCURS NEXT DAY AT OPEN AFTER EXIT CONDITION IS TRUE ! ***THESE STOPS ONLY WORK IN BACKTESTING*** ! ***THE STOP VALUES CANNOT BE DISPLAYED IN A REPORT*** !ABREVIATIONS: C is [close]. C1 is valresult(C,1). O is [open]. H is [high]. L is [low]. PEP is {position entry price}. !returns entry price PHP is {position high price}. !returns highest close of position so far PLP is {position low price}. !returns lowest close of position so far PD is {position days}. !returns number of bars position held !INPUTS: SLP is 7. SLATR is 2. TSP is 20. TSATR is 4. ATRlen is 20. !AVERAGE TRUE RANGE HD if hasdatafor(ATRlen+20) >= ATRlen. TR is Max(H - L,max(abs(C1 - L),abs(C1 - H))). ATR is iff(HD,simpleavg(TR,ATRlen),0). ATRsig is valresult(ATR,PD). !value of ATR on signal bar !!FOR EXITING LONG POSITIONS: !StopLoss Longs: StopLossLongs if C / PEP <= (1 - SLP/100). StopLossATRlongs if PEP - C >= SLATR * ATRsig. !Trailing Stops Longs: TrailStopLongs if C / PHP <= (1 - TSP/100). TrailStopATRlongs if PHP - C >= TSATR * ATRsig. !!FOR EXITING SHORT POSITIONS: !StopLoss Shorts: StopLossShorts if C / PEP >= (1 + SLP/100). StopLossATRshorts if C - PEP >= SLATR * ATRsig. !TrailingStop Shorts: TrailStopShorts if C / PLP >= (1 + TSP/100). TrailStopATRshorts if C - PLP >= TSATR * ATRsig.
The TradersStudio code for John Ehlers & Ric Way’s article in this issue, “Setting Strategies With SwamiCharts,” is provided at the websites noted below. From there, you can download the following code files:
Function: “EHLERS_CORONA_SWING(outputType)” computes the following values:
If outputType = 1 Then = DomCyc If outputType = 2 Then = SPP If outputType = 3 Then = Color1 If outputType = 4 Then = Color2 If outputType = 5 Then = Color3 If < 1 or > 5 then = CSN (default)
Indicator plot: “EHLERS_CORONA_SWING_IND(plotType)” for displaying the swing output types as follows:
If plotType = 1 displays the dominant cycle If plotType = 2 displays SPP If plotTypw = 3 displays the three-color numbers RGB
Function: “EHLERS_MARKET_MODE(outputType)” computes the following values:
If outputType = 1 then = Mean If outputType = 2 then = Fraction*AvgPeak If outputType = 3 then = Fraction*AvgValley
Indicator plot: “EHLERS_MARKET_MODE_IND()” for displaying the three outputTypes from the Market Mode function.
Note that I did not attempt to duplicate the SwamiCharts displayed in Ehlers & Way’s article due to time constraints, and only the code presented in the article has been converted to TradersStudio code. The possible ways to use this code are yet to be determined.
The code files are available from the following sites:
The code is also shown here:
'SETTING STRATEGIES WITH SWAMI CHARTS 'Author: John Ehlers, TASC April 2012 'Coded by: Richard Denning 2/12/2012 'www.TradersEdgeSystems.com Function EHLERS_CORONA_SWING(outputType) 'If outputType = 1 Then = DomCyc 'If outputType = 2 Then = CSN 'If outputType = 3 Then = Color1 'If outputType = 4 Then = Color2 'If outputType = 5 Then = Color3 'If < 1 or > 5 then = CSN (default) Dim Price As BarArray Dim LineR,LineG,LineB Dim FuzzR,FuzzG, FuzzB Dim delta As BarArray Dim gamma As BarArray Dim alpha As BarArray Dim beta As BarArray Dim Period As BarArray Dim MaxAmpl As BarArray Dim Num As BarArray Dim Denom As BarArray Dim DC As BarArray Dim DomCyc As BarArray Dim Color1 As BarArray Dim Color2 As BarArray Dim Color3 As BarArray Dim alpha1 As BarArray Dim HP As BarArray Dim SmoothHP As BarArray Dim gamma2 As BarArray Dim alpha2 As BarArray Dim beta2 As BarArray Dim delta2 As BarArray Dim BP2 As BarArray Dim Q2 As BarArray Dim Lead60 As BarArray Dim HL As BarArray Dim LL As BarArray Dim Psn As BarArray Dim CSN As BarArray Dim Width, Count Dim N, TScurrentBar Dim I As Array Dim OldI As Array Dim OlderI As Array Dim Q As Array Dim OldQ As Array Dim OlderQ As Array Dim Real As Array Dim OldReal As Array Dim OlderReal As Array Dim Imag As Array Dim OldImag As Array Dim OlderImag As Array Dim Ampl As Array Dim OldAmpl As Array Dim DB As Array Dim OldDB As Array Dim Raster As Array Dim OldRaster As Array Dim adc As Array Price = H+L/2 LineR = 180 LineG = 255 LineB = 210 FuzzR = 0 FuzzG = 172 FuzzB = 64 delta = 0.1 delta2 = 0.1 TScurrentBar = CurrentBar + 1 ReDim (I, 61) ReDim (OldI, 61) ReDim (OlderI, 61) ReDim (Q, 61) ReDim (OldQ, 61) ReDim (OlderQ, 61) ReDim (Real, 61) ReDim (OldReal, 61) ReDim (OlderReal, 61) ReDim (Imag, 61) ReDim (OldImag, 61) ReDim (OlderImag, 61) ReDim (Ampl, 61) ReDim (OldAmpl, 61) ReDim (DB, 61) ReDim (OldDB, 61) ReDim (Raster, 51) ReDim (OldRaster, 51) ReDim (adc, 5) If BarNumber=FirstBar Then gamma = 0 alpha = 0 beta = 0 N = 0 MaxAmpl = 0 Num = 0 Denom = 0 DC = 0 DomCyc = 0 alpha1 = 0 HP = 0 SmoothHP = 0 For N = 0 To 60 I[N] = 0 OldI[N] = 0 OlderI[N] = 0 Q[N] = 0 OldQ[N] = 0 OlderQ[N]=0 Real[N] = 0 OldReal[N] = 0 OlderReal[N] = 0 Imag[N] = 0 OldImag[N] = 0 OlderImag[N] = 0 Ampl[N] = 0 OldAmpl[N] = 0 DB[N] = 0 OldDB[N] = 0 Next For N = 0 To 50 Raster[N] = 0 OldRaster[N] = 0 Next For N = 0 To 4 adc[N] = 0 Next End If I = GValue501 OldI = GValue502 OlderI = GValue503 Q = GValue504 OldQ = GValue505 OlderQ = GValue506 Real = GValue507 OldReal = GValue508 OlderReal = GValue509 Imag = GValue510 OldImag = GValue511 OlderImag = GValue512 Ampl = GValue513 OldAmpl = GValue514 DB = GValue515 OldDB = GValue516 Raster = GValue517 OldRaster = GValue518 alpha1 = (1 - Sin(DegToRad(360/30))) / Cos(DegToRad(360/30)) HP = .5*(1 + alpha1)*(Price - Price[1]) + alpha1*HP[1] SmoothHP = (HP + 2*HP[1] + 3*HP[2] + 3*HP[3] + 2*HP[4] + HP[5]) / 12 If TScurrentBar < 7 Then SmoothHP = Price - Price[1] End If If TScurrentBar = 1 Then SmoothHP = 0 End If delta = -.015 * (TScurrentBar) + .5 If delta < .1 Then delta = .1 If TScurrentBar > 12 Then For N = 12 To 60 beta = Cos(DegToRad(720 / N)) gamma = 1 / Cos(DegToRad(1440*delta / N)) alpha = gamma - Sqr(gamma*gamma - 1) Q[N] = (.5*N / 6.28318)*(SmoothHP - SmoothHP[1]) I[N] = SmoothHP Real[N] = .5*(1 - alpha)*(I[N] - OlderI[N]) + beta*(1 + alpha)*OldReal[N] - alpha*OlderReal[N] Imag[N] = .5*(1 - alpha)*(Q[N] - OlderQ[N]) + beta*(1 + alpha)*OldImag[N] - alpha*OlderImag[N] Ampl[N] = (Real[N]*Real[N] + Imag[N]*Imag[N]) Next For N = 12 To 60 OlderI[N] = OldI[N] OldI[N] = I[N] OlderQ[N] = OldQ[N] OldQ[N] = Q[N] OlderReal[N] = OldReal[N] OldReal[N] = Real[N] OlderImag[N] = OldImag[N] OldImag[N] = Imag[N] OldAmpl[N] = Ampl[N] OldDB[N] = DB[N] Next For N = 1 To 50 OldRaster[N] = Raster[N] Next MaxAmpl = Ampl[12] For N = 12 To 60 If Ampl[N] > MaxAmpl Then MaxAmpl = Ampl[N] End If Next Dim myWatch1 Dim myWatch2 Dim myWatch3 For N = 12 To 60 'Assert(False) myWatch1 = DB[N] myWatch2 = Ampl[N] myWatch3 = OldDB[N] If MaxAmpl <> 0 And (Ampl[N] / MaxAmpl) > 0 Then DB[N] = -10*Log(.01 / (1 - .99*Ampl[N] / MaxAmpl)) / Log(10) End If DB[N] = 0.33 * DB[N] + 0.67 * OldDB[N] If DB[N] > 20 Then DB[N] = 20 Next Num = 0 Denom = 0 For N = 12 To 60 If DB[N] <= 6 Then Num = Num + N*(20 - DB[N]) Denom = Denom + (20 - DB[N]) End If If Denom <> 0 Then DC = .5*Num / Denom End If Next For N = 0 To 4 adc[N] = DC[N] Next DomCyc = Median(adc) If DomCyc < 6 Then DomCyc = 6 End If 'EhlersDomCyc = DomCyc If DomCyc > 0 Then beta2 = Cos(DegToRad(360 / DomCyc)) gamma2 = 1 / Cos(DegToRad(720*delta2 / DomCyc)) alpha2 = gamma2 - Sqr(gamma2*gamma2 - 1) BP2 = .5*(1 - alpha2)*(Price - Price[2]) + beta2*(1 + alpha2)*BP2[1] - alpha2*BP2[2] Q2 = (DomCyc / 6.28318)*(BP2 - BP2[1]) Lead60 = .5*BP2 + .866*Q2 HL = Lead60 LL = Lead60 For Count = 0 To 50 If Lead60[Count] > HL Then HL = Lead60[Count] End If If Lead60[Count] < LL Then LL = Lead60[Count] End If Next Psn = (Lead60 - LL) / (HL - LL) CSN = 10*Psn-5 HL = Psn LL = Psn For Count = 0 To 20 If Psn[Count] > HL Then HL = Psn[Count] End If If Psn[Count] < LL Then LL = Psn[Count] End If Next If HL - LL > .85 Then Width = .01 Else Width = .15*(HL - LL) End If For N = 1 To 50 Raster[N] = 20 If N < Round(50*Psn,0) And Width <> 0 Then Raster[N] = 0.5*( ((20*Psn - .4*N)/ Width)^0.95 + 0.5*OldRaster[N]) End If If N > Round(50*Psn,0) And Width <> 0 Then Raster[N] = 0.5*( ((-20*Psn + .4*N)/ Width)^0.95 + 0.5*OldRaster[N]) End If If N = Round(50*Psn,0) Then Raster[N] = 0.5*OldRaster[N] End If If Raster[N] < 0 Then Raster[N] = 0 End If If Raster[N] > 20 Then Raster[N] = 20 End If If HL - LL > .8 Then Raster[N] = 20 End If OldRaster[N] = Raster[N] Next For N = 1 To 50 If Raster[N] <= 10 Then Color1 = LineR + Raster[N]*(FuzzR - LineR) / 10 Color2 = LineG + Raster[N]*(FuzzG - LineG) / 10 Color3 = LineB + Raster[N]*(FuzzB - LineB) / 10 End If If Raster[N] > 10 Then Color1 = FuzzR*(2 - Raster[N] / 10) Color2 = FuzzG*(2 - Raster[N] / 10) Color3 = FuzzB*(2 - Raster[N] / 10) End If Next End If End If If outputType = 1 Then EHLERS_CORONA_SWING = DomCyc Else If outputType = 2 Then EHLERS_CORONA_SWING = CSN Else If outputType = 3 Then EHLERS_CORONA_SWING = Color1 Else If outputType = 4 Then EHLERS_CORONA_SWING = Color2 Else If outputType = 5 Then EHLERS_CORONA_SWING = Color3 Else EHLERS_CORONA_SWING = CSN End If End If End If End If End If GValue501 = I GValue502 = OldI GValue503 = OlderI GValue504 = Q GValue505 = OldQ GValue506 = OlderQ GValue507 = Real GValue508 = OldReal GValue509 = OlderReal GValue510 = Imag GValue511 = OldImag GValue512 = OlderImag GValue513 = Ampl GValue514 = OldAmpl GValue515 = DB GValue516 = OldDB GValue517 = Raster GValue518 = OldRaster End Function '-------------------------------------------------------------- Sub EHLERS_CORONA_SWING_IND(plotType) 'If plotType = 1 displays the Dominant Cycle 'If plotType = 2 displays SPP 'If plotTypw = 3 displays the three color numbers R G B Dim DomCyc As BarArray Dim SPP As BarArray Dim Color1 As BarArray Dim Color2 As BarArray Dim Color3 As BarArray DomCyc = EHLERS_CORONA_SWING(1) SPP = EHLERS_CORONA_SWING(2) Color1 = EHLERS_CORONA_SWING(3) Color2 = EHLERS_CORONA_SWING(4) Color3 = EHLERS_CORONA_SWING(5) If plotType = 1 Then plot1(DomCyc) plot2(25) plot3(25) Else If plotType = 2 Then plot1(SPP) plot2(0) plot3(0) Else If plotType = 3 Then plot1(Color1) plot2(Color2) plot3(Color3) End If End If End If End Sub '------------------------------------------------------------- Function EHLERS_MARKET_MODE(outputType) 'If outputType = 1 then = Mean 'If outputType = 2 then = Fraction*AvgPeak 'If outputType = 3 then = Fraction*AvgValley Dim Period, delta, Fraction Dim alpha As BarArray Dim beta As BarArray Dim gamma As BarArray Dim BP As BarArray Dim Mean As BarArray Dim Peak As BarArray Dim Valley As BarArray Dim AvgPeak As BarArray Dim AvgValley As BarArray Dim Price As BarArray Period = 85 delta = .4 Fraction = .1 Price = (H+L)/2 If Period > 0 And Price > 0 And Price[1] > 0 And Price[2] > 0 Then beta = Cos(DegToRad(360 / Period)) If Cos(DegToRad(720*delta / Period)) <> 0 Then gamma = 1 / Cos(DegToRad(720*delta / Period)) Else gamma = gamma[1] End If If gamma*gamma-1 > 0 Then alpha = gamma - Sqr(gamma*gamma - 1) Else alpha = alpha[1] End If BP = 0.5*(1 - alpha)*(Price - Price[2]) + beta*(1 + alpha)*BP[1] - alpha*BP[2] 'Print FormatDateTime(Date), " ", BP, "", BP[1] Assert(BP <> Empty) Mean = Average(BP, 2*Period, 0) 'Print FormatDateTime(Date), " ", Mean Peak = Peak[1] Valley = Valley[1] If BP[1] > BP And BP[1] > BP[2] Then Peak = BP[1] If BP[1] < BP And BP[1] < BP[2] Then Valley = BP[1] AvgPeak = Average(Peak, 50, 0) AvgValley = Average(Valley, 50, 0) If outputType =1 Then EHLERS_MARKET_MODE = Mean Else If outputType = 2 Then EHLERS_MARKET_MODE = Fraction*AvgPeak Else If outputType = 3 Then EHLERS_MARKET_MODE = Fraction*AvgValley Else EHLERS_MARKET_MODE = Mean End If End If End If End If End Function '------------------------------------------------------------------------------------------- Sub EHLERS_MARKET_MODE_IND() Dim Mean As BarArray,fAvgPeak As BarArray,fAvgValley As BarArray Mean = EHLERS_MARKET_MODE(1) fAvgPeak = EHLERS_MARKET_MODE(2) fAvgValley = EHLERS_MARKET_MODE(3) Plot1(Mean) Plot2(fAvgPeak) Plot3(fAvgValley) End Sub '------------------------------------------------------------------
The SwamiWave and related indicators, as discussed in “Setting Strategies With SwamiCharts” by John Ehlers & Ric Way in this issue, has been implemented as an indicator available for download at www.ninjatrader.com/SC/April2012SC.zip.
Once you have it downloaded, from within the NinjaTrader Control Center window, select the menu File → Utilities →Import NinjaScript and select the downloaded file. This file is for NinjaTrader version 7 or greater.
You can review the indicator source code by selecting the menu Tools → Edit NinjaScript → Indicator from within the NinjaTrader Control Center window and selecting SwamiWave, BPF, or MarketMode.
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 6.
FIGURE 6: NINJATRADER, SWAMICHARTS INDICATOR. This screenshot shows the “SwamiWave” indicator applied to a daily chart of the emini S&P (ES 03-12).
In their article in this issue, “Setting Strategies With SwamiCharts,” John Ehlers & Ric Way expand on their previous work with heatmaps and cycles, giving us an excellent introduction to their SwamiCharts swing wave and market mode indicators. Our Advanced Cycle Trader plugin provides robust heatmaps of this type alongside many other powerful cycle trading tools.
To complement their article, we have provided OmniLanguage code for the market mode indicator and its associated heatmap. While OmniLanguage is an excellent tool to code trading ideas into systems and indicators, it is not optimized for intensive graphics. Thus, to help mitigate this fact, some minor optimizations to the code have been performed by creating a third indicator called “OptimizedMarketMode” for use in the SwamiMM heatmap (Figure 7).
FIGURE 7: OMNITRADER, SWAMICHARTS INDICATORS. Here is a chart of AAPL plotted along with the SwamiMM and market mode indicators. Note how the indicator correctly alerts swing traders to the series of medium-term cycles as the upward trend dissipates in mid-February.
To use the software, copy the three files to the VBA folder of your OmniTrader or VisualTrader directory. The next time you start OT or VT, these indicators will be available for use. If desired, the calculations can be modified using the OmniLanguage IDE.
For more information on our Advanced Cycle Trader plugin and source code for this article, visit www.omnitrader.com/CycleTrader. The code is also shown below.
'************************************************************** '* SwamiMM (SwamiMM.txt) '* by Jeremy Williams '* February 14, 2012 '* '* Adapted from Technical Analysis of Stocks and Commodities '* April 2012 '* '* Summary: '* '* This indicator plots a Heatmap of the Market Mode '* Indicator, to help identify which cycles are being '* overpowered by the trend. Green areas show where the '* trend is too bullish for the given cycle. Similarly for '* bearish trends and Red areas. The yellow regions show '* which cycles potentially could overpower the trend. '* '* For more information see "Introducing SwamiCharts" in '* the March 2012 edition of Technical Analysis of Stocks '* and Commodities. '* '* Notes: '* '* This indicator requires the OptimizedMarketMode Indicator '* (OptimizedMarketMode.txt) to function. This can be found at: '* '* www.omnitrader.com/ProSI '* '* This indicator is only a visual tool and does not '* return a value. '* '************************************************************** #Indicator #Param "Fract",.25 ' Setup Plot area Y- Axis from 4 to 48 corresponding with the ' period of the Market Mode used. SetScales(4,48) ' Process the 4 period Market Mode Dim oColor4 As Object Dim myMM4 As Single myMM4 = OptimizedMarketMode(4,0.41421,0,Fract) ' Color heatmap line based on value If myMM4 < .50 Then oColor4 = Color.FromARGB(255,255*2*myMM4,0) Else oColor4 = Color.FromARGB(255*(2-2*myMM4),255,0) End If ' Plot line for period 4 Market Mode Plot("4",4,oColor4,10) ' Contiune similarly for other periods. Dim oColor5 As Object Dim myMM5 As Single myMM5 = OptimizedMarketMode(5,0.50953,0.30902,Fract) If myMM5 < .50 Then oColor5 = Color.FromARGB(255,255*2*myMM5,0) Else oColor5 = Color.FromARGB(255*(2-2*myMM5),255,0) End If Plot("5",5,oColor5,10) Dim oColor6 As Object Dim myMM6 As Single myMM6 = OptimizedMarketMode(6,0.57735,0.5,Fract) If myMM6 < .50 Then oColor6 = Color.FromARGB(255,255*2*myMM6,0) Else oColor6 = Color.FromARGB(255*(2-2*myMM6),255,0) End If Plot("6",6,oColor6,10) Dim oColor7 As Object Dim myMM7 As Single myMM7 = OptimizedMarketMode(7,0.62834,0.62349,Fract) If myMM7 < .50 Then oColor7 = Color.FromARGB(255,255*2*myMM7,0) Else oColor7 = Color.FromARGB(255*(2-2*myMM7),255,0) End If Plot("7",7,oColor7,10) Dim oColor8 As Object Dim myMM8 As Single myMM8 = OptimizedMarketMode(8,0.66818,0.70711,Fract) If myMM8 < .50 Then oColor8 = Color.FromARGB(255,255*2*myMM8,0) Else oColor8 = Color.FromARGB(255*(2-2*myMM8),255,0) End If Plot("8",8,oColor8,10) Dim oColor9 As Object Dim myMM9 As Single myMM9 =OptimizedMarketMode(9,0.70021,0.76604,Fract) If myMM9 < .50 Then oColor9 = Color.FromARGB(255,255*2*myMM9,0) Else oColor9 = Color.FromARGB(255*(2-2*myMM9),255,0) End If Plot("9",9,oColor9,10) Dim oColor10 As Object Dim myMM10 As Single myMM10 = OptimizedMarketMode(10,0.72654,0.80902,Fract) If myMM10 < .50 Then oColor10 = Color.FromARGB(255,255*2*myMM10,0) Else oColor10 = Color.FromARGB(255*(2-2*myMM10),255,0) End If Plot("10",10,oColor10,10) Dim oColor11 As Object Dim myMM11 As Single myMM11 = OptimizedMarketMode(11,0.74859,0.84125,Fract) If myMM11 < .50 Then oColor11 = Color.FromARGB(255,255*2*myMM11,0) Else oColor11 = Color.FromARGB(255*(2-2*myMM11),255,0) End If Plot("11",11,oColor11,10) Dim oColor12 As Object Dim myMM12 As Single myMM12 = OptimizedMarketMode(12,0.76733,0.86603,Fract) If myMM12 < .50 Then oColor12 = Color.FromARGB(255,255*2*myMM12,0) Else oColor12 = Color.FromARGB(255*(2-2*myMM12),255,0) End If Plot("12",12,oColor12,10) Dim oColor13 As Object Dim myMM13 As Single myMM13 = OptimizedMarketMode(13,0.78345,0.88546,Fract) If myMM13 < .50 Then oColor13 = Color.FromARGB(255,255*2*myMM13,0) Else oColor13 = Color.FromARGB(255*(2-2*myMM13),255,0) End If Plot("13",13,oColor13,10) Dim oColor14 As Object Dim myMM14 As Single myMM14 = OptimizedMarketMode(14,0.79747,0.90097,Fract) If myMM14 < .50 Then oColor14 = Color.FromARGB(255,255*2*myMM14,0) Else oColor14 = Color.FromARGB(255*(2-2*myMM14),255,0) End If Plot("14",14,oColor14,10) Dim oColor15 As Object Dim myMM15 As Single myMM15 = OptimizedMarketMode(15,0.80978,0.91355,Fract) If myMM15 < .50 Then oColor15 = Color.FromARGB(255,255*2*myMM15,0) Else oColor15 = Color.FromARGB(255*(2-2*myMM15),255,0) End If Plot("15",15,oColor15,10) Dim oColor16 As Object Dim myMM16 As Single myMM16 = OptimizedMarketMode(16,0.82068,0.92388,Fract) If myMM16 < .50 Then oColor16 = Color.FromARGB(255,255*2*myMM16,0) Else oColor16 = Color.FromARGB(255*(2-2*myMM16),255,0) End If Plot("16",16,oColor16,10) Dim oColor17 As Object Dim myMM17 As Single myMM17 = OptimizedMarketMode(17,0.83039,0.93247,Fract) If myMM17 < .50 Then oColor17 = Color.FromARGB(255,255*2*myMM17,0) Else oColor17 = Color.FromARGB(255*(2-2*myMM17),255,0) End If Plot("17",17,oColor17,10) Dim oColor18 As Object Dim myMM18 As Single myMM18 = OptimizedMarketMode(18,0.8391,0.93969,Fract) If myMM18 < .50 Then oColor18 = Color.FromARGB(255,255*2*myMM18,0) Else oColor18 = Color.FromARGB(255*(2-2*myMM18),255,0) End If Plot("18",18,oColor18,10) Dim oColor19 As Object Dim myMM19 As Single myMM19 = OptimizedMarketMode(19,0.84696,0.94582,Fract) If myMM19 < .50 Then oColor19 = Color.FromARGB(255,255*2*myMM19,0) Else oColor19 = Color.FromARGB(255*(2-2*myMM19),255,0) End If Plot("19",19,oColor19,10) Dim oColor20 As Object Dim myMM20 As Single myMM20 = OptimizedMarketMode(20,0.85408,0.95106,Fract) If myMM20 < .50 Then oColor20 = Color.FromARGB(255,255*2*myMM20,0) Else oColor20 = Color.FromARGB(255*(2-2*myMM20),255,0) End If Plot("20",20,oColor20,10) Dim oColor21 As Object Dim myMM21 As Single myMM21 = OptimizedMarketMode(21,0.86057,0.95557,Fract) If myMM21 < .50 Then oColor21 = Color.FromARGB(255,255*2*myMM21,0) Else oColor21 = Color.FromARGB(255*(2-2*myMM21),255,0) End If Plot("21",21,oColor21,10) Dim oColor22 As Object Dim myMM22 As Single myMM22 = OptimizedMarketMode(22,0.8665,0.95949,Fract) If myMM22 < .50 Then oColor22 = Color.FromARGB(255,255*2*myMM22,0) Else oColor22 = Color.FromARGB(255*(2-2*myMM22),255,0) End If Plot("22",22,oColor22,10) Dim oColor23 As Object Dim myMM23 As Single myMM23 = OptimizedMarketMode(23,0.87195,0.96292,Fract) If myMM23 < .50 Then oColor23 = Color.FromARGB(255,255*2*myMM23,0) Else oColor23 = Color.FromARGB(255*(2-2*myMM23),255,0) End If Plot("23",23,oColor23,10) Dim oColor24 As Object Dim myMM24 As Single myMM24 = OptimizedMarketMode(24,0.87698,0.96593,Fract) If myMM24 < .50 Then oColor24 = Color.FromARGB(255,255*2*myMM24,0) Else oColor24 = Color.FromARGB(255*(2-2*myMM24),255,0) End If Plot("24",24,oColor24,10) Dim oColor25 As Object Dim myMM25 As Single myMM25 = OptimizedMarketMode(25,0.88162,0.96858,Fract) If myMM25 < .50 Then oColor25 = Color.FromARGB(255,255*2*myMM25,0) Else oColor25 = Color.FromARGB(255*(2-2*myMM25),255,0) End If Plot("25",25,oColor25,10) Dim oColor26 As Object Dim myMM26 As Single myMM26 = OptimizedMarketMode(26,0.88592,0.97094,Fract) If myMM26 < .50 Then oColor26 = Color.FromARGB(255,255*2*myMM26,0) Else oColor26 = Color.FromARGB(255*(2-2*myMM26),255,0) End If Plot("26",26,oColor26,10) Dim oColor27 As Object Dim myMM27 As Single myMM27 = OptimizedMarketMode(27,0.88992,0.97304,Fract) If myMM27 < .50 Then oColor27 = Color.FromARGB(255,255*2*myMM27,0) Else oColor27 = Color.FromARGB(255*(2-2*myMM27),255,0) End If Plot("27",27,oColor27,10) Dim oColor28 As Object Dim myMM28 As Single myMM28 = OptimizedMarketMode(28,0.89365,0.97493,Fract) If myMM28 < .50 Then oColor28 = Color.FromARGB(255,255*2*myMM28,0) Else oColor28 = Color.FromARGB(255*(2-2*myMM28),255,0) End If Plot("28",28,oColor28,10) Dim oColor29 As Object Dim myMM29 As Single myMM29 = OptimizedMarketMode(29,0.89714,0.97662,Fract) If myMM29 < .50 Then oColor29 = Color.FromARGB(255,255*2*myMM29,0) Else oColor29 = Color.FromARGB(255*(2-2*myMM29),255,0) End If Plot("29",29,oColor29,10) Dim oColor30 As Object Dim myMM30 As Single myMM30 = OptimizedMarketMode(30,0.9004,0.97815,Fract) If myMM30 < .50 Then oColor30 = Color.FromARGB(255,255*2*myMM30,0) Else oColor30 = Color.FromARGB(255*(2-2*myMM30),255,0) End If Plot("30",30,oColor30,10) Dim oColor31 As Object Dim myMM31 As Single myMM31 = OptimizedMarketMode(31,0.90347,0.97953,Fract) If myMM31 < .50 Then oColor31 = Color.FromARGB(255,255*2*myMM31,0) Else oColor31 = Color.FromARGB(255*(2-2*myMM31),255,0) End If Plot("31",31,oColor31,10) Dim oColor32 As Object Dim myMM32 As Single myMM32 = OptimizedMarketMode(32,0.90635,0.98079,Fract) If myMM32 < .50 Then oColor32 = Color.FromARGB(255,255*2*myMM32,0) Else oColor32 = Color.FromARGB(255*(2-2*myMM32),255,0) End If Plot("32",32,oColor32,10) Dim oColor33 As Object Dim myMM33 As Single myMM33 = OptimizedMarketMode(33,0.90906,0.98193,Fract) If myMM33 < .50 Then oColor33 = Color.FromARGB(255,255*2*myMM33,0) Else oColor33 = Color.FromARGB(255*(2-2*myMM33),255,0) End If Plot("33",33,oColor33,10) Dim oColor34 As Object Dim myMM34 As Single myMM34 = OptimizedMarketMode(34,0.91162,0.98297,Fract) If myMM34 < .50 Then oColor34 = Color.FromARGB(255,255*2*myMM34,0) Else oColor34 = Color.FromARGB(255*(2-2*myMM34),255,0) End If Plot("34",34,oColor34,10) Dim oColor35 As Object Dim myMM35 As Single myMM35 = OptimizedMarketMode(35,0.91404,0.98393,Fract) If myMM35 < .50 Then oColor35 = Color.FromARGB(255,255*2*myMM35,0) Else oColor35 = Color.FromARGB(255*(2-2*myMM35),255,0) End If Plot("35",35,oColor35,10) Dim oColor36 As Object Dim myMM36 As Single myMM36 = OptimizedMarketMode(36,0.91633,0.98481,Fract) If myMM36 < .50 Then oColor36 = Color.FromARGB(255,255*2*myMM36,0) Else oColor36 = Color.FromARGB(255*(2-2*myMM36),255,0) End If Plot("36",36,oColor36,10) Dim oColor37 As Object Dim myMM37 As Single myMM37 = OptimizedMarketMode(37,0.9185,0.98562,Fract) If myMM37 < .50 Then oColor37 = Color.FromARGB(255,255*2*myMM37,0) Else oColor37 = Color.FromARGB(255*(2-2*myMM37),255,0) End If Plot("37",37,oColor37,10) Dim oColor38 As Object Dim myMM38 As Single myMM38 = OptimizedMarketMode(38,0.92056,0.98636,Fract) If myMM38 < .50 Then oColor38 = Color.FromARGB(255,255*2*myMM38,0) Else oColor38 = Color.FromARGB(255*(2-2*myMM38),255,0) End If Plot("38",38,oColor38,10) Dim oColor39 As Object Dim myMM39 As Single myMM39 = OptimizedMarketMode(39,0.92252,0.98705,Fract) If myMM39 < .50 Then oColor39 = Color.FromARGB(255,255*2*myMM39,0) Else oColor39 = Color.FromARGB(255*(2-2*myMM39),255,0) End If Plot("39",39,oColor39,10) Dim oColor40 As Object Dim myMM40 As Single myMM40 = OptimizedMarketMode(40,0.92439,0.98769,Fract) If myMM40 < .50 Then oColor40 = Color.FromARGB(255,255*2*myMM40,0) Else oColor40 = Color.FromARGB(255*(2-2*myMM40),255,0) End If Plot("40",40,oColor40,10) Dim oColor41 As Object Dim myMM41 As Single myMM41 = OptimizedMarketMode(41,0.92617,0.98828,Fract) If myMM41 < .50 Then oColor41 = Color.FromARGB(255,255*2*myMM41,0) Else oColor41 = Color.FromARGB(255*(2-2*myMM41),255,0) End If Plot("41",41,oColor41,10) Dim oColor42 As Object Dim myMM42 As Single myMM42 = OptimizedMarketMode(42,0.92786,0.98883,Fract) If myMM42 < .50 Then oColor42 = Color.FromARGB(255,255*2*myMM42,0) Else oColor42 = Color.FromARGB(255*(2-2*myMM42),255,0) End If Plot("42",42,oColor42,10) Dim oColor43 As Object Dim myMM43 As Single myMM43 = OptimizedMarketMode(43,0.92948,0.98934,Fract) If myMM43 < .50 Then oColor43 = Color.FromARGB(255,255*2*myMM43,0) Else oColor43 = Color.FromARGB(255*(2-2*myMM43),255,0) End If Plot("43",43,oColor43,10) Dim oColor44 As Object Dim myMM44 As Single myMM44 = OptimizedMarketMode(44,0.93103,0.98982,Fract) If myMM44 < .50 Then oColor44 = Color.FromARGB(255,255*2*myMM44,0) Else oColor44 = Color.FromARGB(255*(2-2*myMM44),255,0) End If Plot("44",44,oColor44,10) Dim oColor45 As Object Dim myMM45 As Single myMM45 = OptimizedMarketMode(45,0.93252,0.99027,Fract) If myMM45 < .50 Then oColor45 = Color.FromARGB(255,255*2*myMM45,0) Else oColor45 = Color.FromARGB(255*(2-2*myMM45),255,0) End If Plot("45",45,oColor45,10) Dim oColor46 As Object Dim myMM46 As Single myMM46 = OptimizedMarketMode(46,0.93393,0.99069,Fract) If myMM46 < .50 Then oColor46 = Color.FromARGB(255,255*2*myMM46,0) Else oColor46 = Color.FromARGB(255*(2-2*myMM46),255,0) End If Plot("46",46,oColor46,10) Dim oColor47 As Object Dim myMM47 As Single myMM47 = OptimizedMarketMode(47,0.9353,0.99108,Fract) If myMM47 < .50 Then oColor47 = Color.FromARGB(255,255*2*myMM47,0) Else oColor47 = Color.FromARGB(255*(2-2*myMM47),255,0) End If Plot("47",47,oColor47,10) Dim oColor48 As Object Dim myMM48 As Single myMM48 = OptimizedMarketMode(48,0.9366,0.99144,Fract) If myMM48 < .50 Then oColor48 = Color.FromARGB(255,255*2*myMM48,0) Else oColor48 = Color.FromARGB(255*(2-2*myMM48),255,0) End If Plot("48",48,oColor48,10) Return 0 ' Return the value calculated by the indicator
'************************************************************** '* Market Mode (MarketMode.txt) '* by Jeremy Williams '* February 14, 2012 '* '* Adapted from Technical Analysis of Stocks and Commodities '* April 2012 '* '* Summary: '* '* This indicator is used to determine whether the market '* is in a trending or a cyclical mode. This is accomplished '* by comparing the average value of price, after being filtered '* to the peaks and valleys of that filtered price. The filter '* used in this indicator is a second order butterworth filter. '* For more information on this calculation see "Introducing '* SwamiCharts" (March 2012) and "Empirical Mode Decomposition" '* (March 2010) from Technical Analysis of Stocks and Commodities. '* '* Parameters: '* '* Periods- Sets the number of periods used for the center-band '* of the filter '* Delta- Sets the width of the pass-band of the filter '* Fract- Set the cutoff Ratio for determining the various modes '* '************************************************************** #Indicator #Param "Period",20 #Param "Delta",.1 #Param "Fract",.25 Dim fValue As Single Dim fBeta As Single DIm fGamma As Single Dim fAlpha As Single Dim BP As Single Dim fMean As Single Dim fPeak As Single Dim fValley As Single Dim fAvgPeak As Single Dim fAvgValley As Single Dim fOutVal As Single ' Calculate Parameters for Bandpass Filter fValue = (H+L)/2 fBeta = Cosine(6.28 / Period) fGamma = 1 / Cosine(2*6.28*Delta / Period) fAlpha = fGamma-SquareRoot(fGamma*fGamma - 1) ' Implement Filter and Measure the Trend components BP = .5*(1-fAlpha)*(fValue-fValue[2])+fBeta*(1+fAlpha)*BP[1]-fAlpha*BP[2] fMean = SMA(BP, 2*Period) fPeak = fPeak[1] fValley = fValley[1] If BP[1] > BP and BP[1] > BP[2] Then fPeak = BP[1] If BP[1] < BP and BP[1] < BP[2] Then fValley = BP[1] fAvgPeak = SMA(fPeak, 50) fAvgValley = SMA(fValley, 50) ' Calculate The Ratio If fMean > 0 and fAvgPeak> 0 Then fOutVal = fMean/(fAvgPeak*Fract) Else If fMean < 0 And fAvgValley < 0 Then fOutVal = -fMean/(fAvgValley*Fract) Else fOutVal = 0 End If ' Plot The Indicator Plot("Mode",fMean) Plot("Peak",Fract*fAvgPeak) Plot("Valley",Fract*fAvgValley) Plot("Ratio",fOutVal) Return fOutVal
'************************************************************** '* Market Mode (MarketMode.txt) '* by Jeremy Williams '* February 14, 2012 '* '* Adapted from Technical Analysis of Stocks and Commodities '* April 2012 '* '* Summary: '* '* This indicator is an optimized version of the Market Mode '* Indicator for use with the SwamiMM indicator. It uses preset '* calculate parameters to reduce the computational load when '* plotting the heatmap. '* '* For more information on this calculation see "Introducing '* SwamiCharts" (March 2012) and "Empirical Mode Decomposition" '* (March 2010) from Technical Analysis of Stocks and Commodities. '* '* Parameters: '* '* Period- Sets the number of periods used for the center-band '* of the filter '* A- First parameter for bandpass filter '* B- Second parameter for bandpass filter '* Fract- Sets the cutoff Ratio for determining the various modes '* '************************************************************** #Indicator #Param "Period",20 #Param "A",.854 #Param "B",.951 #Param "Fract",.25 Dim fValue As Single Dim fBeta As Single DIm fGamma As Single Dim fAlpha As Single Dim BP As Single Dim fMean As Single Dim fPeak As Single Dim fValley As Single Dim fAvgPeak As Single Dim fAvgValley As Single Dim fOutVal As Single fValue = (H+L)/2 'Calculate the Filtered Values, Peaks, and Trend BP = .5*(1-A)*(fValue-fValue[2])+B*(1+A)*BP[1]-A*BP[2] fMean = SMA(BP, 2*Period) fPeak = fPeak[1] fValley = fValley[1] If BP[1] > BP and BP[1] > BP[2] Then fPeak = BP[1] If BP[1] < BP and BP[1] < BP[2] Then fValley = BP[1] fAvgPeak = SMA(fPeak, 50) fAvgValley = SMA(fValley, 50) 'Set the Values for coloring If fMean > fAvgPeak*Fract Then fOutVal = 1 Else If fMean < fAvgValley*Fract Then fOutVal = 0 Else fOutVal = .5 End If 'Return The Value Return fOutVal
This tip is based on John Ehlers & Ric Way’s article in this issue, “Setting Strategies With SwamiCharts.”
The heat map display of SwamiCharts adds an extra dimension to how information is displayed. In this example, the authors show how this effect for market modes of multiple periods can illustrate the complexity of underlying cycles, whilst enhancing market timing.
The Updata code for this indicator 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 below into the Updata Custom editor and save it.
Imports Microsoft.VisualBasic Imports System.Windows.Forms Imports System.Drawing Imports Updata Imports System.IO Imports System.Text Public Class Updata_TestIndicator Implements ICustomIndicator Public Sub init() Implements ICustomIndicator.init End Sub Public Function getLines(ByVal iLineStyles() As LineStyles, ByVal iChartStyles() As ChartStyles, ByVal sNames() As String, ByVal iColours() As Integer, ByVal iColours2() As Integer) As Integer Implements ICustomIndicator.getLines iLineStyles(0) = LineStyles.Dot iChartStyles(0) = ChartStyles.Chart iColours(0) = Color.Red.ToArgb() iColours2(0) = Color.Red.ToArgb() sNames(0) = "Swami Chart" getLines = 1 End Function Public Function queryForParameters(ByVal iRets() As Updata.VariableTypes, ByVal sNames() As String, ByVal sDescrips() As String, ByVal defaults As Object()) As Integer Implements ICustomIndicator.queryForParameters iRets(0) = VariableTypes.PriceVariable sNames(0) = "Period" sDescrips(0) = "Period" defaults(0) = CType(20, Integer) iRets(1) = VariableTypes.PriceVariable sNames(1) = "Fraction" sDescrips(1) = "Fraction" defaults(1) = CType(0.1, Double) iRets(2) = VariableTypes.PriceVariable sNames(2) = "Delta" sDescrips(2) = "Delta" defaults(2) = CType(0.5, Double) queryForParameters = 3 End Function Private Colour1(60, 1) As Integer Private Colour2(60, 1) As Integer Public Function recalculateAll(ByVal dSrc()() As Double, ByVal oParams() As Object, ByVal dRet()()() As Double, ByVal iTradeTypes()() As Integer, ByVal dTradeOpenPrices()() As Double, ByVal dTradeClosePrices()() As Double, ByVal iTradeAmounr()() As Integer, ByVal dStopLevels()() As Double) As Boolean Implements ICustomIndicator.recalculateAll If dSrc.Length = 0 Then recalculateAll = False End If 'Vars dim InputPeriod as Integer dim PVPeriod as Integer dim i,k as Integer dim inc as Integer dim beta(60) as Single dim gamma(60) as Single dim alpha(60) as Single dim price(dRet(0).Length-1) as Single dim Avg(60,dRet(0).Length-1) as Single dim BP(60,dRet(0).Length-1) as Single dim Peak(60,dRet(0).Length-1) as Single dim Valley(60,dRet(0).Length-1) as Single dim AvgPeak(60,dRet(0).Length-1) as Single dim AvgValley(60,dRet(0).Length-1) as Single dim FracAvgPeak(60,dRet(0).Length-1) as Single dim FracAvgValley(60,dRet(0).Length-1) as Single ReDim Colour1(60, dRet(0).Length-1) ReDim Colour2(60, dRet(0).Length-1) dim Dist(60) As Single dim Width(60) as Single dim Centre(60) as Single dim Period As Integer = CType(oParams(0), Integer) dim Fraction As Single = CType(oParams(1), Single) dim delta As Single = CType(oParams(2), Single) For i = 50 To dRet(0).Length-1 inc +=1 For Period=10 To 60 InputPeriod=2*Period PVPeriod=System.Math.Round(2.5*Period) price(i)=(dSrc(i)(1)+dSrc(i)(2))/2 beta(Period) = System.Math.Cos(2*System.Math.Pi/Period) gamma(Period) = 1/System.Math.Cos(4*System.Math.Pi*delta/Period) alpha(Period) = gamma(Period) - System.Math.Sqrt(gamma(Period)*gamma(Period)-1) 'Trend Component BP(Period,i)=0.5*(1-alpha(Period))*(price(i)-price(i-2))+beta(Period)*(1+alpha(Period))*BP(Period,i-1)-alpha(Period)*BP(Period,i-2) 'Running Avg Calc If inc>=InputPeriod Avg(Period,i) = Average(BP,InputPeriod,i,Period) End If If BP(Period,i-1)>BP(Period,i) And BP(Period,i-1)>BP(Period,i-2) Peak(Period,i)=BP(Period,i-1) ElseIf BP(Period,i-1)<BP(Period,i) And BP(Period,i-1)<BP(Period,i-2) Valley(Period,i)=BP(Period,i-1) Else Peak(Period,i)=Peak(Period,i-1) Valley(Period,i)=Valley(Period,i-1) End If If inc>=(2.5*Period) AvgPeak(Period,i) = Average(Peak,PVPeriod,i,Period) AvgValley(Period,i) = Average(Valley,PVPeriod,i,Period) FracAvgPeak(Period,i) = Fraction*Average(Peak,PVPeriod,i,Period) FracAvgValley(Period,i) = Fraction*Average(Valley,PVPeriod,i,Period) Width(Period) = FracAvgPeak(Period,i)-FracAvgValley(Period,i) Centre(Period) = (FracAvgPeak(Period,i)+FracAvgValley(Period,i))/2 'Colour Palette If Avg(Period,i)>Centre(Period) if Avg(Period,i)>Centre(Period)+Width(Period) Dist(Period)=1 Colour1(Period, i) = 0 Colour2(Period, i) = 255 else Dist(Period)=(Avg(Period,i)-Centre(Period))/Width(Period) Colour1(Period, i) = System.Math.Max(255*(1-Dist(Period)),0) Colour2(Period, i) = 255 end if Else if Avg(Period,i)<Centre(Period)-Width(Period) Dist(Period)=1 Colour1(Period, i) = 255 Colour2(Period, i) = 0 else Dist(Period)=(Centre(Period)-Avg(Period,i))/Width(Period) Colour1(Period, i) = 255 Colour2(Period, i) = System.Math.Max(255*(1-Dist(Period)),0) end if End If End If Next Period 'force plot range For k = 0 To dRet(0)(i).Length - 1 dRet(0)(i)(k) = 10 If i Mod 2 = 0 Then dRet(0)(i)(k) = 60 End If Next k Next i recalculateAll = True End Function ' reserved for future support Public Function recalculateLast(ByVal dSrc()() As Double, ByVal oParams() As Object, ByVal dRet()()() As Double) As Boolean Implements ICustomIndicator.recalculateLast recalculateLast = False End Function ' Averaging Function Public Function Average(TimeSeries(,) As Single,AvgPeriod As Integer,StartPoint As Integer,Instance As Integer) dim n as integer dim TempSum as double dim AvgRet as double For n=0 To AvgPeriod-1 TempSum=TempSum+TimeSeries(Instance,StartPoint-n) Next n AvgRet=TempSum/AvgPeriod Return AvgRet End Function Public Function paint(ByVal g As System.Drawing.Graphics, ByVal oParams() As Object, ByVal ds()()() As Double, ByVal iFirstVisible As Integer, ByVal iLastVisible As Integer, ByVal c As iGraphFunctions, ByVal iLineNum As Integer) As Boolean Implements ICustomIndicator.paint If iLineNum = 1 Then paint = False Else 'Line Conditions Dim x, y, y2, i, Period As Integer Dim pLastPoint As Point dim a As Integer 'now show the colour spectrum Using brush As SolidBrush = New SolidBrush(Color.fromArgb(0, 0, 0)) For period = 10 To 60 y = c.DataToY(period) y2 = c.DataToY(period + 1) For i = iFirstVisible To iLastVisible brush.Color = Color.fromArgb(Colour1(period, i), Colour2(period, i), 0) x = c.DataToX(i) If i <> iFirstVisible Then If y - y2 > 1 Then g.FillRectangle(brush, x, y2, x - pLastPoint.x + 1, y - y2 + 1) Else g.FillRectangle(brush, x, y2, x - pLastPoint.x + 1, 1) End If End If pLastPoint = New Point(x, y) Next i Next period End Using paint = True End If End Function End Class
A sample chart is shown in Figure 8.
FIGURE 8: UPDATA, MARKET MODE SWAMICHART. This chart shows the DJIA with the market mode SwamiChart. Uptrends are colored green, downtrends are red, and yellow shows ideal periods for swing trading. The indicator parameters can be altered according to preference. This set shows an alignment across all uptrend modes.
The SwamiCharts market mode indicator presented by John Ehlers & Ric Way in their article in this issue (“Setting Strategies With SwamiCharts”) can easily be used with our online charting tool at www.tradesignalonline.com.
At www.tradesignalonline.com, check the Infopedia section for our lexicon. You will see the indicator there, which you can make available for your personal account. Simply click on it and select “open script.” The indicator will be immediately available for you to apply on any chart you wish.
The code is also shown below. A sample chart is shown in Figure 9.
Bandpass Filter.eqi Meta: TrigMode( TrigModeDegrees ); Inputs: Price((H+L)/2), Period(20), delta(.1); Vars: gamma(0), alpha(0), beta(0), BP(0); beta = Cosine(360 / Period); gamma = 1 / Cosine(720*delta / Period); alpha = gamma - SquareRoot(gamma*gamma - 1); BP = .5*(1 - alpha)*(Price - Price[2]) + beta*(1 + alpha)*BP[1]- alpha*BP[2]; DrawLine(BP, "Bandpass Filter", StyleSolid, 1, red); DrawLIne(0, "Zero", StyleDash, 1, Black );
Corona Chart Swing Position.eqi Meta: TrigMode( TrigModeDegrees ); Inputs: Price((H+L)/2), LineR(180), LineG(255), LineB(210), FuzzR(0), FuzzG(172), FuzzB(64); Vars: delta(0.1), gamma(0), alpha(0), beta(0), N(0), Period(0), MaxAmpl(0), Num(0), Denom(0), DC(0), DomCyc(0), Color1(0), Color2(0), Color3(0), alpha1(0), HP(0), SmoothHP(0), gamma2(0), alpha2(0), beta2(0), delta2(.1), BP2(0), Q2(0), Lead60(0), HL(0), LL(0), count(0), Psn(0), Width(0); Arrays: I[60](0), OldI[60](0), OlderI[60](0), Q[60](0), OldQ[60](0), OlderQ[60](0), Real[60](0), OldReal[60](0), OlderReal[60](0), Imag[60](0), OldImag[60](0), OlderImag[60](0), Ampl[60](0), OldAmpl[60](0), DB[60](0), OldDB[60](0), Raster[50](0), OldRaster[50](0); alpha1 = (1 - Sine (360 / 30)) / Cosine(360 / 30); HP = .5*(1 + alpha1)*(Price - Price[1]) + alpha1*HP[1]; SmoothHP = (HP + 2*HP[1] + 3*HP[2] + 3*HP[3] + 2*HP[4] + HP[5]) / 12; IF CurrentBar < 7 Then SmoothHP = Price - Price[1]; IF CurrentBar = 1 THEN SmoothHP = 0; delta = -.015*CurrentBar + .5; If delta < .1 then delta = .1; If CurrentBar > 12 Then Begin For N = 12 to 60 Begin beta = Cosine(720 / N); gamma = 1 / Cosine(1440*delta / N); alpha = gamma - SquareRoot(gamma*gamma - 1); Q[N] = (.5*N / 6.28318)*(SmoothHP - SmoothHP[1]); I[N] = SmoothHP; Real[N] = .5*(1 - alpha)*(I[N] - OlderI[N]) + beta*(1 + alpha)*OldReal[N] - alpha*OlderReal[N]; Imag[N] = .5*(1 - alpha)*(Q[N] - OlderQ[N]) + beta*(1 + alpha)*OldImag[N] - alpha*OlderImag[N]; Ampl[N] = (Real[N]*Real[N] + Imag[N]*Imag[N]); End; End; For N = 12 to 60 Begin OlderI[N] = OldI[N]; OldI[N] = I[N]; OlderQ[N] = OldQ[N]; OldQ[N] = Q[N]; OlderReal[N] = OldReal[N]; OldReal[N] = Real[N]; OlderImag[N] = OldImag[N]; OldImag[N] = Imag[N]; OldAmpl[N] = Ampl[N]; OldDB[N] = DB[N]; End; For N = 1 to 50 OldRaster[N] = Raster[N]; MaxAmpl = Ampl[12]; If MaxAmpl = 0 Then MaxAmpl = 0.01; For N = 12 to 60 Begin If Ampl[N] > MaxAmpl then MaxAmpl = Ampl[N]; End; For N = 12 to 60 Begin If MaxAmpl <> 0 Then Begin If (Ampl[N] / MaxAmpl) > 0 Then DB[N] = -10*Log(.01 / (1 - .99*Ampl[N] / MaxAmpl)) / Log(10); End; DB[N] = .33*DB[N] + .67*OldDB[N]; If DB[N] > 20 then DB[N] = 20; End; Num = 0; Denom = 0; For N = 12 to 60 Begin If DB[N] <= 6 Then Begin Num = Num + N*(20 - DB[N]); Denom = Denom + (20 - DB[N]); End; If Denom <> 0 Then DC = .5*Num / Denom; End; DomCyc = Median(DC, 5); If DomCyc < 6 Then DomCyc = 6; beta2 = Cosine(360 / DomCyc); gamma2 = 1 / Cosine(720*delta2 / DomCyc); alpha2 = gamma2 - SquareRoot(gamma2*gamma2 - 1); BP2 = .5*(1 - alpha2)*(Price - Price[2]) + beta2*(1 + alpha2)*BP2[1] - alpha2*BP2[2]; Q2 = (DomCyc / 6.28318)*(BP2 - BP2[1]); Lead60 = .5*BP2 + .866*Q2; HL = Lead60; LL = Lead60; For count = 0 to 50 Begin If Lead60[count] > HL then HL = Lead60[count]; If Lead60[count] < LL then LL = Lead60[count]; End; Psn = (Lead60 - LL) / (Hl - LL); HL = Psn; LL = Psn; For count = 0 to 20 Begin If Psn[count] > HL then HL = Psn[count]; If Psn[count] < LL then LL = Psn[count]; End; If HL - LL > .85 Then Width = .01 Else Width = .15*(HL - LL); //End; If Width = 0 then Width = 0.01; For N = 1 to 50 Begin Raster[N] = 20; Begin If N < Round(50*Psn,0) Then Raster[N] = .5*(Power((20*Psn- .4*N)/ Width, .95) + .5*OldRaster[N]); If N > Round(50*Psn,0) Then Raster[N] = .5*(Power((-20*Psn+ .4*N)/ Width, .95) + .5*OldRaster[N]); If N = Round(50*Psn,0) Then Raster[N] = .5*OldRaster[N]; End; //If Date = 20080401 Then Print(Date); If Raster[N] < 0 Then Raster[N] = 0; If Raster[N] > 20 Then Raster[N] = 20; If HL - LL > .8 then Raster[N] = 20; OldRaster[N] = Raster[N]; End; Plot1(10*Psn-5, "S51", RGB(LineR, LineG, LineB),0,2); For N = 1 to 50 Begin IF Raster[N] <= 10 THEN Begin Color1 = LineR + Raster[N]*(FuzzR - LineR) / 10; Color2 = LineG + Raster[N]*(FuzzG - LineG) / 10; Color3 = LineB + Raster[N]*(FuzzB - LineB) / 10; END; IF Raster[N] > 10 THEN Begin Color1 = FuzzR*(2 - Raster[N] / 10); Color2 = FuzzG*(2 - Raster[N] / 10); Color3 = FuzzB*(2 - Raster[N] / 10); END; If N = 1 Then Plot1(N, "S1", RGB(Color1, Color2, Color3),Color3,5); If N = 2 Then Plot2(.2*N-5, "S2", RGB(Color1, Color2, Color3), 0,5); If N = 3 Then Plot3(.2*N-5, "S3", RGB(Color1, Color2, Color3), 0,5); If N = 4 Then Plot4(.2*N-5, "S4", RGB(Color1, Color2, Color3), 0,5); If N = 5 Then Plot5(.2*N-5, "S5", RGB(Color1, Color2, Color3), 0,5); If N = 6 Then Plot6(.2*N-5, "S6", RGB(Color1, Color2, Color3), 0,5); If N = 7 Then Plot7(.2*N-5, "S7", RGB(Color1, Color2, Color3), 0,5); If N = 8 Then Plot8(.2*N-5, "S8", RGB(Color1, Color2, Color3), 0,5); If N = 9 Then Plot9(.2*N-5, "S9", RGB(Color1, Color2, Color3), 0,5); If N = 10 Then Plot10(.2*N-5, "S10", RGB(Color1, Color2, Color3),0,5); If N = 11 Then Plot11(.2*N-5, "S11", RGB(Color1, Color2, Color3),0,5); If N = 12 Then Plot12(.2*N-5, "S12", RGB(Color1, Color2, Color3),0,5); If N = 13 Then Plot13(.2*N-5, "S13", RGB(Color1, Color2, Color3),0,5); If N = 14 Then Plot14(.2*N-5, "S14", RGB(Color1, Color2, Color3),0,5); If N = 15 Then Plot15(.2*N-5, "S15", RGB(Color1, Color2, Color3),0,5); If N = 16 Then Plot16(.2*N-5, "S16", RGB(Color1, Color2, Color3),0,5); If N = 17 Then Plot17(.2*N-5, "S17", RGB(Color1, Color2, Color3),0,5); If N = 18 Then Plot18(.2*N-5, "S18", RGB(Color1, Color2, Color3),0,5); If N = 19 Then Plot19(.2*N-5, "S19", RGB(Color1, Color2, Color3),0,5); If N = 20 Then Plot20(.2*N-5, "S20", RGB(Color1, Color2, Color3),0,5); If N = 21 Then Plot21(.2*N-5, "S21", RGB(Color1, Color2, Color3),0,5); If N = 22 Then Plot22(.2*N-5, "S22", RGB(Color1, Color2, Color3),0,5); If N = 23 Then Plot23(.2*N-5, "S23", RGB(Color1, Color2, Color3),0,5); If N = 24 Then Plot24(.2*N-5, "S24", RGB(Color1, Color2, Color3),0,5); If N = 25 Then Plot25(.2*N-5, "S25", RGB(Color1, Color2, Color3),0,5); If N = 26 Then Plot26(.2*N-5, "S26", RGB(Color1, Color2, Color3),0,5); If N = 27 Then Plot27(.2*N-5, "S27", RGB(Color1, Color2, Color3),0,5); If N = 28 Then Plot28(.2*N-5, "S28", RGB(Color1, Color2, Color3),0,5); If N = 29 Then Plot29(.2*N-5, "S29", RGB(Color1, Color2, Color3),0,5); If N = 30 Then Plot30(.2*N-5, "S30", RGB(Color1, Color2, Color3),0,5); If N = 31 Then Plot31(.2*N-5, "S31", RGB(Color1, Color2, Color3),0,5); If N = 32 Then Plot32(.2*N-5, "S32", RGB(Color1, Color2, Color3),0,5); If N = 33 Then Plot33(.2*N-5, "S33", RGB(Color1, Color2, Color3),0,5); If N = 34 Then Plot34(.2*N-5, "S34", RGB(Color1, Color2, Color3),0,5); If N = 35 Then Plot35(.2*N-5, "S35", RGB(Color1, Color2, Color3),0,5); If N = 36 Then Plot36(.2*N-5, "S36", RGB(Color1, Color2, Color3),0,5); If N = 37 Then Plot37(.2*N-5, "S37", RGB(Color1, Color2, Color3),0,5); If N = 38 Then Plot38(.2*N-5, "S38", RGB(Color1, Color2, Color3),0,5); If N = 39 Then Plot39(.2*N-5, "S39", RGB(Color1, Color2, Color3),0,5); If N = 40 Then Plot40(.2*N-5, "S40", RGB(Color1, Color2, Color3),0,5); If N = 41 Then Plot41(.2*N-5, "S41", RGB(Color1, Color2, Color3),0,5); If N = 42 Then Plot42(.2*N-5, "S42", RGB(Color1, Color2, Color3),0,5); If N = 43 Then Plot43(.2*N-5, "S43", RGB(Color1, Color2, Color3),0,5); If N = 44 Then Plot44(.2*N-5, "S44", RGB(Color1, Color2, Color3),0,5); If N = 45 Then Plot45(.2*N-5, "S45", RGB(Color1, Color2, Color3),0,5); If N = 46 Then Plot46(.2*N-5, "S46", RGB(Color1, Color2, Color3),0,5); If N = 47 Then Plot47(.2*N-5, "S47", RGB(Color1, Color2, Color3),0,5); If N = 48 Then Plot48(.2*N-5, "S48", RGB(Color1, Color2, Color3),0,5); If N = 49 Then Plot49(.2*N-5, "S49", RGB(Color1, Color2, Color3),0,5); If N = 50 Then Plot50(.2*N-5, "S50", RGB(Color1, Color2, Color3),0,5); End;
Market Mode Indicator.eqi Inputs: Price((H+L)/2), Period(20), delta(.5), Fraction(.1); Vars: alpha(0), beta(0), gamma(0), BP(0), I(0), Mean(0), Peak(0), Valley(0), AvgPeak(0), AvgValley(0); beta = Cosine(360 / Period); gamma = 1 / Cosine(720*delta / Period); alpha = gamma -SquareRoot(gamma*gamma - 1); BP = .5*(1 - alpha)*(Price - Price[2]) + beta*(1 + alpha)*BP[1] - alpha*BP[2]; Mean = Average(BP, 2*Period); Peak = Peak[1]; Valley = Valley[1]; If BP[1] > BP and BP[1] > BP[2] Then Peak = BP[1]; If BP[1] < BP and BP[1] < BP[2] Then Valley = BP[1]; AvgPeak = Average(Peak, 50); AvgValley = Average(Valley, 50); Plot1(Mean); Plot2(Fraction*AvgPeak); Plot6(Fraction*AvgValley);
FIGURE 9: TRADESIGNAL ONLINE, SWAMICHARTS INDICATORS. Here is a sample TradeSignal Online chart showing the SwamiCharts stochastics, SwamiCharts bandpass, and SwamiCharts market mode indicator on the daily chart of Daimler AG.