Traders' Tip text
The
weekly & daily MACD (W&D MACD) oscillator by Vitali Apirine from December 2017 issue of Stocks & Commodities combines the two MACD oscillators (weekly and daily) on a daily chart. Author suggests that relative daily MACD line crossovers, weekly and daily centerline crossovers and divergences can be used to generate trading signals.
The latter (divegence detection) is the basis of our example trading system. A bearish divergence forms when a security records a higher high (or a series of them) and the weekly W&D MACD line forms a lower high (and vice versa for a bullish divergence). As Vitali Apirine notes, weekly MACD divergences are more important than daily MACD divergences.
You can make your own conclusions regarding the efficiency of indicator's application to spot medium-term divergences on the chart if you run enclosed C# Strategy code.
Figure 1.
A divegence in Procter & Gambler stock (PG) with three tops that formed in a year.
C# Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using TASCIndicators;
namespace WealthLab.Strategies
{
/*
Divergence: price sets a lowest low but the indicator fails to confirm the new low and turns up
*/
public class WDMACD_Divergence : WealthScript
{
private StrategyParameter paramHighest;
private StrategyParameter paramExitDays;
private StrategyParameter paramDailyLength1;
private StrategyParameter paramDailyLength2;
private StrategyParameter paramWeeklyLength1;
private StrategyParameter paramWeeklyLength2;
public WDMACD_Divergence()
{
paramHighest = CreateParameter("Highest high of", 130, 60, 300, 10);
paramExitDays = CreateParameter("Exit after", 20, 1, 50, 1);
paramDailyLength1 = CreateParameter("Daily Length 1",12,2,300,20);
paramDailyLength2 = CreateParameter("Daily Length 2",26,2,300,20);
paramWeeklyLength1 = CreateParameter("Weekly Length 1",60,2,300,20);
paramWeeklyLength2 = CreateParameter("Weekly Length 2",130,2,300,20);
}
protected override void Execute()
{
if( Bars.Scale != BarScale.Daily )
{
DrawLabel(PricePane, "Switch to Daily scale");
Abort();
}
bool peak = false; int peakBar = -1;
int high = paramHighest.ValueInt;
bool trough = false; int troughBar = -1;
int low = paramHighest.ValueInt;
int days = paramExitDays.ValueInt;
var RDM = RelativeDailyMACD.Series(Close,paramDailyLength1.ValueInt,paramDailyLength2.ValueInt,
paramWeeklyLength1.ValueInt,paramWeeklyLength2.ValueInt);
var WM = WeeklyMACD.Series(Close,paramWeeklyLength1.ValueInt,paramWeeklyLength2.ValueInt);
HideVolume(); LineStyle solid = LineStyle.Solid;
ChartPane paneWDMACDPane1 = CreatePane(40,true,true);
PlotSeries(paneWDMACDPane1,RDM,Color.FromArgb(255,0,100,0),LineStyle.Solid,2);
PlotSeries(paneWDMACDPane1,WM,Color.FromArgb(255,0,0,0),LineStyle.Solid,2);
DrawHorzLine(paneWDMACDPane1,0,Color.Blue,LineStyle.Solid,1);
Lowest indicatorLowest = Lowest.Series( WM, low );
Lowest hLow = Lowest.Series( Low, low );
for(int bar = GetTradingLoopStartBar(130); bar < Bars.Count; bar++)
{
if (!IsLastPositionActive)
{
/* 1st peak: both price and indicator */
if( peak == false )
{
if( ( High[bar-1] == Highest.Series( High, high )[bar-1] )
& ( WM[bar-1] == Highest.Series( WM, high )[bar-1] )
& TurnDown( bar, High ) & TurnDown( bar, WM ) )
{
peak = true; peakBar = bar-1;
}
}
if( peak == true )
{
if( ( High[bar] != Highest.Series( High, high )[bar] )
& ( WM[bar] == Highest.Series( WM, high )[bar] ) )
peak = false;
}
/* 2nd peak: price high not confirmed by the indicator */
if( peak == true )
{
if( ( High[bar-1] == Highest.Series( High, high )[bar-1] )
& ( High[bar-1] >= High[peakBar] )
& ( WM[bar-1] != Highest.Series( WM, high )[bar-1] )
& ( WM[bar-1] < WM[peakBar] ) &
TurnDown( bar, High ) & TurnDown( bar, WM ) )
{
peak = false;
ShortAtMarket( bar+1 );
/* Highlight divergence */
for (int b = peakBar; b <= bar; b++)
SetPaneBackgroundColor( paneWDMACDPane1, b, Color.FromArgb( 30, Color.LightCoral ) );
DrawLine( PricePane, peakBar, High[peakBar], bar-1, High[bar-1], Color.Red, solid, 2 );
DrawLine( paneWDMACDPane1, peakBar, WM[peakBar], bar-1, WM[bar-1], Color.Blue, solid, 2 );
}
}
/* 1st trough: both price and indicator */
if( trough == false )
{
if( ( Low[bar-1] == Lowest.Series( Low, low )[bar-1] )
& ( WM[bar-1] == Lowest.Series( WM, low )[bar-1] )
& TurnUp( bar, Low ) & TurnUp( bar, WM ) )
{
trough = true; troughBar = bar-1;
}
}
if( trough == true )
{
if( ( Low[bar] != Lowest.Series( Low, low )[bar] )
& ( WM[bar] == Lowest.Series( WM, low )[bar] ) )
trough = false;
}
/* 2nd trough: price low not confirmed by the indicator */
if( trough == true )
{
if( ( Low[bar-1] == Lowest.Series( Low, low )[bar-1] )
& ( Low[bar-1] <= Low[troughBar] )
& ( WM[bar-1] != Lowest.Series( WM, low )[bar-1] )
& ( WM[bar-1] > WM[troughBar] ) &
TurnUp( bar, Low ) & TurnUp( bar, WM ) )
{
trough = false;
BuyAtMarket( bar+1 );
/* Highlight divergence */
for (int b = troughBar; b <= bar; b++)
SetPaneBackgroundColor( paneWDMACDPane1, b,
Color.FromArgb( 30, Color.LightGreen ) );
DrawLine( PricePane, troughBar, Low[troughBar],
bar-1, Low[bar-1], Color.Blue, solid, 2 );
DrawLine( paneWDMACDPane1, troughBar, WM[troughBar],
bar-1, WM[bar-1], Color.Red, solid, 2 );
}
}
} else
{
/* Exit after N days */
Position p = LastPosition;
if ( bar+1 - p.EntryBar >= days )
ExitAtMarket( bar+1, p, "Timed" );
}
}
}
}
}
Eugene (Gene Geren)
Wealth-Lab team
www.wealth-lab.com