Traders' Tip text
In June 2017 issue of the Stocks & Commodities magazine, Domenico D'Errico shares a method that can give an insight about the possible dynamics of a futures trading session – ahead of it.
Figure 1.
On the chart of ES, the night session is colored in black, the first hour of trading is in red, the remaining main trading session is in blue, and the session from 15:15 pm to midnight is in gray. The subchart plots the cumulative night volume as histogram and its five-day moving average (red line).Use “parameter slider” at the bottom to adjust the number of sessions to average the nightly volume.
Although the C# code that implements his "Night and Day" breakout strategy can be copied into Wealth-Lab 6, for your simplicity we recommend to download it straight from the application's "Open Strategy" dialog. We hope that this strategy becomes a good addition to the trader's arsenal:
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using System.Linq;
using System.Globalization;
namespace WealthLab.Strategies
{
public class NightAndDayStrategy : WealthScript
{
private int GetTime(int bar)
{
return Date[bar].Hour * 100 + Date[bar].Minute;
}
private string NumberAsK(double volume)
{
return volume.ToString("#,##0,K", CultureInfo.InvariantCulture);
}
private StrategyParameter paramAverageNights;
public NightAndDayStrategy()
{
paramAverageNights = CreateParameter("Avg. Nights", 5, 1, 20, 1);
}
protected override void Execute()
{
if ( Bars.IsIntraday )
{
// Variables
int firstHourStart = -1, firstHourEnd = -1, average = paramAverageNights.ValueInt;
double firstHourRangeHigh = 0, firstHourRangeLow = 0;
var aNightVolume = new DataSeries(Bars,"Average Night Volume");
var cNightVolume = new DataSeries(Bars,"Cumulative Night Volume");
var ls = LineStyle.Solid;
var lstVolumes = new List<double>(); // holds cumulative volume for each session
bool canTrade = false;
Font font = new Font("Verdana",10,FontStyle.Bold);
// Plotting
HideVolume();
ChartPane cvPane = CreatePane(20,false,false);
PlotSeries(cvPane,cNightVolume,Color.Brown,LineStyle.Histogram,2);
PlotSeries(cvPane,aNightVolume,Color.Red,ls,2);
for(int bar = GetTradingLoopStartBar(1); bar < Bars.Count; bar++)
{
// Save current time into variable to avoid repeated function calls
int t = GetTime(bar);
// Volatility bias is night volume is not lower than the night volume average of the last N days
bool volatilityBias = false;
// Propagate average night volume
if( aNightVolume[bar] == 0 )
aNightVolume[bar] = aNightVolume[bar - 1];
// Aftermarket
if( (t > 1515) && (t <= 2359) )
SetBarColor( bar, Color.Silver );
// Night session
if( (t >= 0000) && (t <= 0830) )
{
SetBarColor( bar, Color.Black );
// Reset night volume
if(t == 0000)
cNightVolume[bar] = 0;
else
cNightVolume[bar] = cNightVolume[bar-1];
// Cumulate night volume series
cNightVolume[bar] += Volume[bar];
if(t == 0830)
{
firstHourStart = bar;
lstVolumes.Add(cNightVolume[bar]);
}
}
// First hour
if( (t > 0830) && (t <= 0930) )
{
// Average nightly volume for last N sessions
var avgNightlyVolume = lstVolumes.Skip(Math.Max(0, lstVolumes.Count() - average)).Sum() / (double)average;
aNightVolume[bar] = avgNightlyVolume;
// Volatility filter
volatilityBias = avgNightlyVolume > cNightVolume[firstHourStart] ? false : true;
SetBarColor( bar, Color.Red );
if(t == 0930)
firstHourEnd = bar;
if( (firstHourStart > -1) && (firstHourEnd > -1) )
{
if( bar == firstHourEnd ) // get the highest high and the lowest low after first hour
{
// First hour range
firstHourRangeHigh = Highest.Value(bar, High, firstHourEnd-firstHourStart );
firstHourRangeLow = Lowest.Value(bar, Low, firstHourEnd-firstHourStart );
DrawLine( PricePane, firstHourStart, firstHourRangeHigh, firstHourEnd, firstHourRangeHigh, Color.Blue, ls, 2 );
DrawLine( PricePane, firstHourStart, firstHourRangeLow, firstHourEnd, firstHourRangeLow, Color.Red, ls, 2 );
AnnotateBar("Volatility bias: " + volatilityBias.ToString(),bar,true, Color.Blue,Color.Transparent,font);
AnnotateBar("Avg.Vol: " + NumberAsK(avgNightlyVolume) + ", Cum.Vol: " + NumberAsK(cNightVolume[firstHourStart]),
bar,true, Color.Blue,Color.Transparent,font);
// Minimum required trading sessions
bool calculationIsValid = lstVolumes.Count >= average;
// Can only trade between 9:30 and 15:15 if volatility bias is high
if( volatilityBias && calculationIsValid )
canTrade = true;
}
}
}
// Main session
if( (t > 0930) && (t <= 1515) )
SetBarColor( bar, Color.Blue );
// Reset trading condition until new session
if( t > 1515 )
canTrade = false;
// Trading
if( IsLastPositionActive )
{
Position p = LastPosition;
// Exit at 15:15
if( ( t >= 1515) )
ExitAtMarket( bar+1, p, "15:15" );
}
else
{
// Take trades if volatility bias is positive and time is OK
if( canTrade )
{
if( BuyAtStop(bar+1, firstHourRangeHigh + 0.01, volatilityBias.ToString() ) == null )
ShortAtStop(bar+1, firstHourRangeLow - 0.01, volatilityBias.ToString() );
}
}
}
}
else
{
DrawLabel( PricePane, "Works on intraday data only!", Color.Red );
}
}
}
}
Eugene (Gene Geren)
Wealth-Lab team
www.wealth-lab.com