Wealth-Lab Wiki

API ChartStyles Community Components Community Indicators IndexDefinitions Knowledge Base Misc Optimizers Pending Deletion PosSizers Providers Standard Indicators TASC Traders Tips TASCIndicators Tutorial Videos Visualizers
RSS

Navigation


Quick Search
»
Advanced Search »


TASC 2016-09 | Measuring Market Cycles (Ehlers)

RSS

Traders' Tip text

We’ve coded Ehlers Autocorrelation Periodogram from September 2016 issue of Stocks & Commodities for Wealth-Lab 6 (.NET). To view the picture of spectral activity enhanced by using MESA with the same conditions, drag respective "parameter slider" on the bottom left of the screen.

The dominant cycle periods and periods where there were no useful cycles are represented by differently colored ranges: from yellow at the maximum amplitude to black as ice cold.

Image

Figure 1 shows how the measured cycle periods change over time on the Daily chart of AXP (American Express).

Revision A 08/01/2016

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

namespace WealthLab.Strategies { public class TASC201609 : WealthScript { private StrategyParameter paramEnhance;

public TASC201609() { paramEnhance = CreateParameter("Enhance Resolution", 0, 0, 1, 1); } protected override void Execute() { bool EnhanceResolution = paramEnhance.ValueInt == 0 ? false : true; DataSeries HP = new DataSeries(Bars, "HP"); DataSeries Filt = new DataSeries(Bars, "Filt"); DataSeries DominantCycle = new DataSeries(Bars, "DominantCycle");

double Deg2Rad = Math.PI / 180.0; double cosInDegrees = Math.Cos((.707 * 360 / 48d) * Deg2Rad); double sinInDegrees = Math.Sin((.707 * 360 / 48d) * Deg2Rad); double alpha1 = (cosInDegrees + sinInDegrees - 1) / cosInDegrees; double a1 = Math.Exp(-1.414 * Math.PI / 8.0); double b1 = 2.0 * a1 * Math.Cos((1.414 * 180d / 8.0) * Deg2Rad); double c2 = b1; double c3 = -a1 * a1; double c1 = 1 - c2 - c3;

for (int bar = 2; bar < Bars.Count; bar++) { HP[bar] = 0.5*(1 + alpha1)*(Close[bar] - Close[bar-1]) + alpha1*HP[bar-1]; //Smooth with a SuperSmoother Filter Filt[bar] = c1*(HP[bar] + HP[bar-1]) / 2 + c2*Filt[bar-1] + c3*Filt[bar-2]; } DataSeries[] ds = new DataSeries[48]; ChartPane tp = CreatePane(50,false,false); for( int n = 0; n < 48; n++ ) { ds[n] = new DataSeries(Bars,n.ToString()); for( int bar = 0; bar < Bars.Count; bar++ ) ds[n][bar] = n; PlotSeries(tp, ds[n], Color.Black, LineStyle.Solid, 16); } HideVolume(); for( int bar = 0; bar < Bars.Count; bar++) { SetPaneBackgroundColor(PricePane,bar,Color.Black); int AvgLength = 3, M = 0; double X = 0, Y = 0, Sx = 0, Sy = 0, Sxx = 0, Syy = 0, Sxy = 0; double[] Corr = new double[70]; double[] CosinePart = new double[70]; double[] SinePart = new double[70]; double[] SqSum = new double[70]; double[,] R = new double[70,2]; double[] Pwr = new double[70]; //Pearson correlation for each value of lag for(int Lag = 0; Lag <= 48; Lag++) { //Set the averaging length as M M = AvgLength; if( AvgLength == 0 ) M = Lag; Sx = 0; Sy = 0; Sxx = 0; Syy = 0; Sxy = 0;

for(int count = 0; count <= M-1; count++) { X = bar-count < 0 ? 0 : Filt[bar-count]; //Y = bar-Lag+count < 0 ? 0 : Filt[bar-Lag+count]; Y = bar-(Lag+count) < 0 ? 0 : Filt[bar-(Lag+count)]; // Rev.A Sx = Sx + X; Sy = Sy + Y; Sxx = Sxx + X*X; Sxy = Sxy + X*Y; Syy = Syy + Y*Y; }

if( (M*Sxx - Sx*Sx)*(M*Syy - Sy*Sy) > 0 ) Corr[Lag] = (M*Sxy-Sx*Sy)/Math.Sqrt((M*Sxx - Sx*Sx)*(M*Syy - Sy*Sy)); }

//Compute the Fourier Transform for each Correlation for(int Period = 0; Period <= 48; Period++) { CosinePart[Period] = 0; SinePart[Period] = 0;

for(int N = 3; N <= 48; N++) { double _cosInDegrees = Math.Cos(((double)N * 360 / (double)Period) * Deg2Rad); double _sinInDegrees = Math.Sin(((double)N * 360 / (double)Period) * Deg2Rad); CosinePart[Period] = CosinePart[Period] + Corr[N]*_cosInDegrees; SinePart[Period] = SinePart[Period] + Corr[N]*_sinInDegrees; }

SqSum[Period] = CosinePart[Period]*CosinePart[Period] + SinePart[Period]*SinePart[Period]; } for(int Period = 8; Period <= 48; Period++) { R[Period, 1] = R[Period, 0]; R[Period, 0] = 0.2*SqSum[Period]*SqSum[Period] + 0.8*R[Period,1]; }

//Find Maximum Power Level for Normalization double MaxPwr = 0; for(int Period = 8; Period <= 48; Period++) { if( R[Period, 0] > MaxPwr ) MaxPwr = R[Period, 0]; } for(int Period = 8; Period <= 48; Period++) { Pwr[Period] = R[Period, 0] / MaxPwr; } //Optionally increase Display Resolution by raising the NormPwr to //a higher mathematically power (since the maximum amplitude is //unity, cubing all amplitudes further reduces the smaller ones) if( EnhanceResolution ) { for(int Period = 8; Period <= 48; Period++) { Pwr[Period] = Math.Pow(Pwr[Period], 3); } }

//Compute the dominant cycle using the CG of the spectrum double PeakPwr = 0, Spx = 0, Sp = 0; for(int Period = 8; Period <= 48; Period++) { if( Pwr[Period] > PeakPwr ) PeakPwr = Pwr[Period]; }

//Plot as a Heatmap double Color1 = 255, Color2 = 0, Color3 = 0; for(int Period = 8; Period < 48; Period++) { if( Pwr[Period] > 0.5 ) { Color1 = 255; Color2 = 255*(2*Pwr[Period] - 1); } else { Color1 = 2*255*Pwr[Period]; Color2 = 0; } Color1 = Math.Min((int)Color1,255); Color1 = Math.Max((int)Color1,0); Color2 = Math.Min((int)Color2,255); Color2 = Math.Max((int)Color2,0); Color3 = Math.Min((int)Color3,255); Color3 = Math.Max((int)Color3,0); SetSeriesBarColor(bar, ds[Period], Color.FromArgb(100,(int)Color1,(int)Color2,(int)Color3) ); } } } } }

Eugene
Wealth-Lab team
www.wealth-lab.com

Important Disclaimer: The information provided by Wealth-Lab is strictly for informational purposes and is not to be construed as advice or solicitation to buy or sell any security.  The owner of Wealth-Lab.com assumes no liability resulting from the use of the material contained herein for investment purposes. By using this web site, you agree to the terms of this disclaimer and our Terms of Use.

Used under license from FMR Corp. Copyright 2008 FMR Corp. All rights reserved.


ScrewTurn Wiki. Some of the icons created by FamFamFam.