TRADERS’ TIPS
For this month’s Traders’ Tips, the focus is Domenico D’Errico’s article in this issue, “Daytrading With Night Volume.” Here, we present the June 2017 Traders’ Tips code with possible implementations in various software.
The Traders’ Tips section is provided to help the reader implement a selected technique from an article in this issue or another recent issue. The entries here are contributed by software developers or programmers for software that is capable of customization.
In “Daytrading With Night Volume” in this issue, author Domenico D’Errico presents a method for forecasting the volatility of an upcoming equity index futures day session based on the trading volume of the previous overnight session. He presents his statistical analysis showing that the day session volume is correlated to the night session volume and that the day session range is correlated to the day session volume.
D’Errico suggests that anticipating the daily range will be useful to the daytrader. Here, we are providing the EasyLanguage code for an indicator to show the overnight volume. We are also providing EasyLanguage code for a breakout strategy that uses the volume information as a filtering mechanism.
Strategy: Overnight Volume Breakout // Overnight Volume Strategy // TASC JUN 2017 // Daytrading With Night Volume // Domenico D'Errico using elsystem ; using elsystem.collections ; inputs: OverNightStartTime( 0 ), OverNightEndTime( 830 ), BreakoutStartTime( 830 ), BreakoutEndTime( 930 ), NoEntriesAfterTime( 1400 ), VolumeAvgLength( 5 ), VolRatioUP( 1 ) ; variables: double OverNightTotalVolume( 0 ), double OverNightVolumeAverage( 0 ), double FirstHourHigh( 0 ), double FirstHourLow( 0 ), bool OverNightVolTime( false ), bool BreakoutRangeTime( false ), vector OverNightVolume( null ) ; ; once begin OverNightVolume = new vector ; end ; OverNightVolTime = ( OverNightStartTime < OverNightEndTime and Time >= OverNightStartTime and Time <= OverNightEndTime ) or ( OverNightStartTime > OverNightEndTime and ( Time >= OverNightStartTime or Time <= OverNightEndTime ) ) ; if not OverNightVolTime[1] and OverNightVolTime then begin OverNightTotalVolume = ticks ; end else if OverNightVolTime then begin OverNightTotalVolume += ticks ; end ; if Time[1] < OverNightEndTime and Time >= OverNightEndTime and BarStatus( DataNum + 1 ) = 2 then begin if OverNightVolume.Count >= VolumeAvgLength then OverNightVolumeAverage = Average( OverNightVolume, VolumeAvgLength ) * VolRatioUP ; OverNightVolume.insert( 0, OverNightTotalVolume astype double ) ; end ; BreakoutRangeTime = Time >= BreakoutStartTime and Time <= BreakoutEndTime ; if not BreakoutRangeTime[1] and BreakoutRangeTime then begin FirstHourHigh = High ; FirstHourLow = Low ; end else if BreakoutRangeTime then begin FirstHourHigh = MaxList( High, FirstHourHigh ) ; FirstHourLow = MinList( Low, FirstHourLow ) ; end ; if OverNightTotalVolume > OverNightVolumeAverage and Time >= BreakOutEndTime and Time<= NoEntriesAfterTime and MarketPosition = 0 then begin Buy next bar at FirstHourHigh Stop ; SellShort next bar at FirstHourLow Stop ; end ; SetExitOnClose ; Indicator: Cumulative Overnight Volume // Cumulative Volume Indicator // TASC JUN 2017 // Daytrading With Night Volume // Domenico D'Errico using elsystem ; using elsystem.collections ; inputs: OverNightStartTime( 0 ), OverNightEndTime( 830 ), VolumeAvgLength( 5 ), VolRatioUP( 1 ) ; variables: double OverNightTotalVolume( 0 ), double OverNightVolumeAverage( 0 ), double FirstHourHigh( 0 ), double FirstHourLow( 0 ), bool OverNightVolTime( false ), bool BreakoutRangeTime( false ), vector OverNightVolume( null ) ; ; once begin OverNightVolume = new vector ; end ; OverNightVolTime = ( OverNightStartTime < OverNightEndTime and Time >= OverNightStartTime and Time <= OverNightEndTime ) or ( OverNightStartTime > OverNightEndTime and ( Time >= OverNightStartTime or Time <= OverNightEndTime ) ) ; if not OverNightVolTime[1] and OverNightVolTime then begin OverNightTotalVolume = ticks ; end else if OverNightVolTime then begin OverNightTotalVolume += ticks ; end ; if Time[1] < OverNightEndTime and Time >= OverNightEndTime and BarStatus( DataNum + 1 ) = 2 then begin if OverNightVolume.Count >= VolumeAvgLength then OverNightVolumeAverage = Average( OverNightVolume, VolumeAvgLength ) * VolRatioUP ; OverNightVolume.insert( 0, OverNightTotalVolume astype double ) ; end ; if OverNightVolTime then Plot1( OverNightTotalVolume ) ; if OverNightTotalVolume > OverNightVolumeAverage then SetPlotColor( 1 , Yellow ) ; Plot2( OverNightVolumeAverage ) ;
To download the EasyLanguage code for the indicator and function in this article please visit our TradeStation and EasyLanguage Support Forum. The code from this article can be found here https://community.tradestation.com/Discussions/Topic.aspx?Topic_ID=147651. The ELD filename is “TASC_JUN2017.ELD.”
For more information about EasyLanguage in general, please see https://www.tradestation.com/EL-FAQ.
A sample chart is shown in Figure 1.
FIGURE 1: TRADESTATION. The overnight volume strategy and indicator are applied to a 15-minute chart of the S&P 500 emini futures.
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.
Domenico D’Errico’s article in this issue, “Daytrading With Night Volume,” expands on the standard first-hour breakout system by adding a volume filter. The article includes an example chart with time sessions colored differently, a summation of the nighttime volume, and a five-day average of that volume. Shown here are the formulas to create such a chart in MetaStock. These formulas assume you are using a 15-minute chart.
Night Session (midnight to 8:30 AM) Color: Black Formula: time:= (Hour()*100) + Minute(); time <= 830 First Hour (8:30 AM to 9:30 AM) Color: Red Formula: time:= (Hour()*100) + Minute(); time <= 930 AND time > 830 Main Session (9:30 AM to 3:15 PM) Color: Blue Formula: time:= (Hour()*100) + Minute(); time <= 1515 AND time > 930 Evening Session (3:15 PM to midnight) Color: Grey Formula: time:= (Hour()*100) + Minute(); time > 315
Buy signal: symbol: up arrow formula: time:= (Hour()*100) + Minute(); night:= time <= 830; nightvol:= If(night, Sum( If(night, V, 0), 36), 0); avgnightvol:= (ValueWhen(1, time=830, nightvol)+ ValueWhen(2, time=830, nightvol)+ ValueWhen(3, time=830, nightvol)+ ValueWhen(4, time=830, nightvol)+ ValueWhen(5, time=830, nightvol))/5; h1top:= ValueWhen(1, time=930, HHV(H,4)); ValueWhen(1, time=830, nightvol)>avgnightvol AND time >930 AND time <=1445 AND H > h1top AND Ref(HighestSince(1, time=930, H),-1) <=h1top Sell Short signal: symbol: down arrow formula: time:= (Hour()*100) + Minute(); night:= time <= 830; nightvol:= If(night, Sum( If(night, V, 0), 36), 0); avgnightvol:= (ValueWhen(1, time=830, nightvol)+ ValueWhen(2, time=830, nightvol)+ ValueWhen(3, time=830, nightvol)+ ValueWhen(4, time=830, nightvol)+ ValueWhen(5, time=830, nightvol))/5; h1bot:= ValueWhen(1, time=930, LLV(L,4)); ValueWhen(1, time=830, nightvol)>avgnightvol AND time >930 AND time <=1445 AND L < h1bot AND Ref(LowestSince(1, time=930, L),-1) <=h1bot Close all open positions: symbol: Exit sign formula: time:= (Hour()*100) + Minute(); closeout:= time >= 1515; closeout AND Ref(closeout=0, -1)
The formula below will create an indicator that plots two lines. After it has been added to the chart, change the lower line to a Histogram line style. Then change the upper line to a dotted line and set the color to Red.
Night Session Volume: time:= (Hour()*100) + Minute(); night:= time <= 830; nightvol:= If(night, Sum( If(night, V, 0), 36), 0); avgnightvol:= (ValueWhen(1, time=830, nightvol)+ ValueWhen(2, time=830, nightvol)+ ValueWhen(3, time=830, nightvol)+ ValueWhen(4, time=830, nightvol)+ ValueWhen(5, time=830, nightvol))/5; nightvol; avgnightvol
The chart in Figure 2 shows a 15-minute chart of ESc1 (emini S&P continuous contract) with both the expert and indicator.
FIGURE 2: METASTOCK. This sample chart shows the ESc1 with an expert and indicator.
For this month’s Traders’ Tip, we’ve provided a study based on the formula described in Domenico D’Errico’s article in this issue, “Daytrading With Night Volume.” The author presents a method of forecasting a day session’s volatility based on the prior night session’s volume.
The study contains formula parameters that may be configured through the edit chart window (right-click on the chart and select “edit chart”). A sample chart is shown in Figure 3.
FIGURE 3: eSIGNAL. Here is an example of the study plotted on an intraday chart of ES.
To discuss this study or download a complete copy of the formula code, please visit the EFS Library Discussion Board forum under the forums link from the support menu at www.esignal.com or visit our EFS KnowledgeBase at https://www.esignal.com/support/kb/efs/. The eSignal formula script (EFS) is also available for copying & pasting below.
/********************************* Provided By: eSignal (Copyright c eSignal), a division of Interactive Data Corporation. 2016. All rights reserved. This sample eSignal Formula Script (EFS) is for educational purposes only and may be modified and saved under a new file name. eSignal is not responsible for the functionality once modified. eSignal reserves the right to modify and overwrite this EFS file with each new release. Description: Daytrading With Night Volume by Domenico D'Errico Version: 1.00 04/12/2017 Formula Parameters: Default: Length 5 Night Session Open 23:00 Day Session Open 08:30 Day Session Close 15:00 Volume Ratio 1 Strategy Type First Hour BreakOut Notes: The related article is copyrighted material. If you are not a subscriber of Stocks & Commodities, please visit www.traders.com. **********************************/ var fpArray = new Array(); function preMain(){ setPriceStudy(false); setColorPriceBars(true); setDefaultPrecision(0,0); setDefaultPriceBarColor(Color.RGB(0,148,255)); setStudyTitle("Night&Day"); setPlotType(PLOTTYPE_HISTOGRAM); setCursorLabelName("CumVol"); var x=0; fpArray[x] = new FunctionParameter("Length", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Length"); setDefault(5); setLowerLimit(1); } fpArray[x] = new FunctionParameter("NightO", FunctionParameter.STRING); with(fpArray[x++]){ setName("Night Session Open"); setDefault("23:00"); } fpArray[x] = new FunctionParameter("DayO", FunctionParameter.STRING); with(fpArray[x++]){ setName("Day Session Open"); setDefault("08:30"); } fpArray[x] = new FunctionParameter("DayC", FunctionParameter.STRING); with(fpArray[x++]){ setName("Day Session Close"); setDefault("15:00"); } fpArray[x] = new FunctionParameter("VolRatio", FunctionParameter.NUMBER); with(fpArray[x++]){ setName("Volume Ratio"); setDefault(1); setLowerLimit(1); } fpArray[x] = new FunctionParameter("StrategyType", FunctionParameter.STRING); with(fpArray[x++]){ setName("Strategy Type"); setDefault("First Hour BreakOut"); addOption("First Hour BreakOut"); addOption("Night & Day"); } } var bInit = false; var bVersion = null; var xHigh = null; var xLow = null; var xClose = null; var xVol = null; var aNightVol = null; var nCurrNightVol = 0; var nLastVol = 0; var nNightSessionOpen = null; var nDaySessionOpen = null; var nDaySessionClose = null; var nFirstHourHighest = null; var nFirstHourLowest = null; function main(Length, NightO, DayO, DayC, StrategyType){ if (bVersion == null) bVersion = verify(); if (bVersion == false) return; if (getBarState() == BARSTATE_ALLBARS){ bInit = false; } if (!bInit){ xHigh = high(); xLow = low(); xClose = close(); xVol = volume(); aNightVol = new Array(Length, 0); nFirstHourHighest = null; nFirstHourLowest = null; nCurrNightVol = 0; nLastVol = 0; nNightSessionOpen = TimeStringToNumber(NightO); nDaySessionOpen = TimeStringToNumber(DayO); nDaySessionClose = TimeStringToNumber(DayC); bInit = true; } var nHigh = xHigh.getValue(0); var nLow = xLow.getValue(0); var nClose = xClose.getValue(0); var barTime = hour(0) * 100 + minute(0); if (getBarState() == BARSTATE_NEWBAR){ if (barTime == nNightSessionOpen) nCurrNightVol = 0; nLastVol = nCurrNightVol; } nCurrNightVol = nLastVol + xVol.getValue(0); if (barTime == nDaySessionOpen){ for (var i = Length - 1; i > 0; i--){ aNightVol[i] = aNightVol[i - 1]; } aNightVol[0] = nCurrNightVol; nFirstHourLowest = nLow; } if (barTime >= nDaySessionOpen && barTime <= TimeMath(nDaySessionOpen, "add", 60)){ if (nHigh > nFirstHourHighest) nFirstHourHighest = nHigh; if (nLow < nFirstHourLowest) nFirstHourLowest = nLow; setPriceBarColor(Color.red); } if (getCurrentBarIndex() != 0){ if(barTime >= TimeMath(nDaySessionOpen, "add", 60 + parseInt(getInterval())) && barTime < TimeMath(nDaySessionClose, "sub", parseInt(getInterval()))){ if (!Strategy.isInTrade()){ if (StrategyType == "First Hour BreakOut"){ if (nHigh > nFirstHourHighest){ Strategy.doLong("First Hour BreakUP", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT); nFirstHourHighest = 0; } else if (nLow < nFirstHourLowest){ Strategy.doShort("First Hour BreakDN", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT); nFirstHourLowest = 0; } } else if (StrategyType == "Night & Day" && aNightVol[0] > AvgVolume(aNightVol, Length)){ if (nHigh > nFirstHourHighest){ Strategy.doLong("N & D BreakUP", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT); nFirstHourHighest = 0; } else if (nLow < nFirstHourLowest){ Strategy.doShort("N & D BreakDN", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT); nFirstHourLowest = 0; } } } } if (barTime >= TimeMath(nDaySessionClose, "add", parseInt(getInterval()))){ if (Strategy.isLong()) Strategy.doSell("Exit BreakUP", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT); else if (Strategy.isShort()) Strategy.doCover("Exit BreakDN", Strategy.CLOSE, Strategy.THISBAR, Strategy.DEFAULT); } } if (barTime < nDaySessionOpen) setPriceBarColor(Color.black); else if (barTime > nDaySessionClose) setPriceBarColor(Color.grey); return nCurrNightVol; } function TimeStringToNumber(timeStr){ var tempTime = new Array(); tempTime = timeStr.split(':',2); if (tempTime[0][0] == '0') tempTime[0] = tempTime[0].substr(1); if (tempTime[1][0] == '0') tempTime[1] = tempTime[1].substr(1); tempTime = (parseInt(tempTime[0]) * 100) + parseInt(tempTime[1]); return tempTime; } function AvgVolume(aVolume, Length){ var sumVol = 0; for (var i = 0; i < Length; i++){ sumVol += aVolume[i]; } return (sumVol / Length); } function TimeMath(timeVal, type, value){ if (type == "add"){ timeVal += (value % 60 + Math.floor(value / 60) * 100); } else if (type == "sub"){ timeVal -= Math.floor(value / 60) * 100; if (value % 60 > timeVal % 100) timeVal -= (100 - (60 - value % 60)); } return timeVal; } function verify(){ var b = false; if (getBuildNumber() < 3742){ drawTextAbsolute(5, 35, "This study requires version 12.1 or later.", Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT, null, 13, "error"); drawTextAbsolute(5, 20, "Click HERE to upgrade.@URL=https://www.esignal.com/download/default.asp", Color.white, Color.blue, Text.RELATIVETOBOTTOM|Text.RELATIVETOLEFT|Text.BOLD|Text.LEFT, null, 13, "upgrade"); return b; } else b = true; return b; }
In “Daytrading With Night Volume” in this issue, author Domenico D’Errico shares a method that can provide insight about the possible dynamics of a futures trading session—ahead of it.
Use the parameter slider in Wealth-Lab at the bottom to adjust the number of sessions to average the nightly volume.
Although the C# code that implements the night & day breakout strategy can be copied into Wealth-Lab 6, for your simplicity, we recommend downloading it straight from the application’s open strategy dialog. We hope that this strategy becomes a good addition to the trader’s arsenal.
A sample chart is in Figure 4.
FIGURE 4: WEALTH-LAB. On this sample 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 a histogram and its five-day moving average (red line).
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++) { // 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( (GetTime(bar) > 1515) && (GetTime(bar) <= 2359) ) SetBarColor( bar, Color.Silver ); // Night session if( (GetTime(bar) >= 0000) && (GetTime(bar) <= 0830) ) { SetBarColor( bar, Color.Black ); // Reset night volume if(GetTime(bar) == 0000) cNightVolume[bar] = 0; else cNightVolume[bar] = cNightVolume[bar-1]; // Cumulate night volume series cNightVolume[bar] += Volume[bar]; if(GetTime(bar) == 0830) { firstHourStart = bar; lstVolumes.Add(cNightVolume[bar]); } } // First hour if( (GetTime(bar) > 0830) && (GetTime(bar) <= 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(GetTime(bar) == 0930) firstHourEnd = bar; if( (firstHourStart > -1) && (firstHourEnd > -1) ) { if( bar == firstHourEnd ) // get the highest high and the lowest low after first 30-min { // 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( (GetTime(bar) > 0930) && (GetTime(bar) <= 1515) ) SetBarColor( bar, Color.Blue ); // Reset trading condition until new session if( GetTime(bar) > 1515 ) canTrade = false; // Trading if( IsLastPositionActive ) { Position p = LastPosition; // Exit at 15:15 if( ( GetTime(bar) >= 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 ); } } } }
In “Daytrading With Night Volume” in this issue, author Domenico D’Errico shows a trading technique based on volume breakouts. A ready-to-use AmiBroker formula that implements a simple trading system and chart based on the method described is presented here.
// times adjusted for IQFeed timestamps SetBarsRequired( sbrAll ); Strategy = 1; // select strategy you wish tn = TimeNum(); CumulativeVolume = SumSince( tn == 234500, Volume ); color = IIf( tn <= 91500, colorBlack, IIf( tn <= 101500, colorRed, IIf( tn > 154500, colorGrey50, colorDarkBlue ) ) ); ntn = tn == 91500; Night0 = ValueWhen( ntn, CumulativeVolume, 1 ); Night1 = ValueWhen( ntn, CumulativeVolume, 2 ); Night2 = ValueWhen( ntn, CumulativeVolume, 3 ); Night3 = ValueWhen( ntn, CumulativeVolume, 4 ); Night4 = ValueWhen( ntn, CumulativeVolume, 5 ); AvgNight = ( Night4 + Night3 + Night2 + Night1 ) / 4; if( ParamToggle( "Type", "Price|CumVol" ) == 0 ) { Plot( C, Date(), color, styleCandle ); } else { Plot( IIf( tn < 91500, CumulativeVolume, 0 ), "N0", colorDarkGrey, styleHistogram | styleLeftAxisScale, 4 ); Plot( AvgNight, "AM", colorDarkRed, styleDashed | styleLeftAxisScale ); } Top = ValueWhen( tn == 101500, HighestSince( ntn, High ) ); Bot = ValueWhen( tn == 101500, LowestSince( ntn, Low ) ); MidSession = tn >= 103000 AND tn < 154500; if( Strategy == 1 ) { //First Hour BreakOut Buy = MidSession AND Close > Top; Short = MidSession AND Close < Bot; } if( Strategy == 2 ) { VolRatioUp = 1; Buy = MidSession AND Night0 > VolRatioUp * AvgNight AND Close > Top; Short = MidSession AND Night0 > VolRatioUp * AvgNight AND Close < Bot; } ClosePosTime = tn == 160000; Sell = ClosePosTime; Cover = ClosePosTime; Buy = ExRem( Buy, Sell ); Sell = ExRem( Sell, Buy ); PlotShapes( Buy*shapeUpArrow, colorGreen, 0, L ); PlotShapes( Sell*shapeDownArrow, colorRed, 0, H );
A sample chart is shown in Figure 5.
FIGURE 5: AMIBROKER. Here is a sample 15-minute ES chart with the different trading sessions marked in different colors. The generated trading signals and cumulative nightly volume replicates a chart from D’Errico’s article in this issue.
The daytrading with night volume trading system as described by Domenico D’Errico in his article in this issue, “Daytrading With Night Volume,” can be easily implemented in NeuroShell Trader. Simply select new trading strategy from the insert menu and enter the following in the appropriate locations of the trading strategy wizard:
BUY LONG CONDITIONS: [All of which must be true] X<=Time<=Y(Date,10:45:00 AM,4:00:00 PM) A>B(SelectiveLag(Sub(CumSum(Volume,0),SelectiveLag(CumSum(Volume,0),Time=X(Date,12:00:00 AM),1)), Time=X(Date,9:30:00 AM),1), SelectiveAvg( Sub( CumSum(Volume,0), SelectiveLag( CumSum( Volume,0), Time=X(Date,12:00:00 AM),1)), Time=X(Date,9:30:00 AM),5)) A>B(Close,SelectiveLag(PriceHigh(High,4),Time=X(Date,10:30:00 AM),1)) SELL LONG CONDITIONS: Time=X(Date,4:15:00 PM) SELL SHORT CONDITIONS: X<=Time<=Y(Date,10:45:00 AM,4:00:00 PM) A>B(SelectiveLag(Sub(CumSum(Volume,0),SelectiveLag(CumSum(Volume,0),Time=X(Date,12:00:00 AM),1)), Time=X(Date,9:30:00 AM),1), SelectiveAvg( Sub( CumSum(Volume,0), SelectiveLag( CumSum( Volume,0), Time=X(Date,12:00:00 AM),1)), Time=X(Date,9:30:00 AM),5)) A<B(Close,SelectiveLag(PriceLow(Low,4),Time=X(Date,10:30:00 AM),1)) COVER SHORT CONDITIONS: [All of which must be true] X<=Time<=Y(Date,10:45:00 AM,4:00:00 PM)
Note that the times were adjusted to EST. If you have NeuroShell Trader Professional, you can also choose whether the parameters should be optimized. After backtesting the trading strategy, use the detailed analysis button to view the backtest and trade-by-trade statistics for the strategy.
Users of NeuroShell Trader can go to the Stocks & Commodities section of the NeuroShell Trader free technical support website to download a copy of this or any previous Traders’ Tips.
A sample chart is shown in Figure 6.
FIGURE 6: NEUROSHELL TRADER. This example NeuroShell Trader chart shows the daytrading with night volume system.
The TradersStudio code based on Domenico D’Errico’s article in this issue, “Daytrading With Night Volume,” is provided at www.TradersEdgeSystems.com/traderstips.htm and is also shown below.
The following code file is provided in the download:
I ran four tests using five-minute bar data on the ES that was compressed to 15-minute bars over the period 7/16/2009 to 7/17/2014.
FIGURE 7: TRADERSSTUDIO. Here is an equity curve for Strategy 1 with both longs and shorts allowed.
FIGURE 8: TRADERSSTUDIO. Here is an equity curve for Strategy 1 with longs only allowed.
FIGURE 9: TRADERSSTUDIO. Here is an equity curve for Strategy 2 with both longs and shorts allowed.
FIGURE 10: TRADERSSTUDIO. Here is an equity curve for Stategy 2 with longs only allowed.
My test confirmed the author’s results that the night volume filter improved the results and also reduced the number of trades. Please note that slippage and commissions were not deducted from the test results. The tests were done solely for comparison purposes.
The code for use in TradersStudio is shown here:
'Day Trading with Night Volume 'Night and Day Demo Strategy 'Author: Domenico D'Errico, TASC June 2017 'Code by: Richard Denning, 4/13/17 'www.TradersEdgeSystems.com Sub DAY_NIGHT(Strategy, VolRatioUP, BarsPerHour, AllowShorts) Dim CumulativeVol As BarArray Dim AvgNight As BarArray Dim Top Dim Bot Dim count Dim OneHourBeforeMidnight Dim MainOpen Dim EndFirstHour Dim MainEnd OneHourBeforeMidnight = 2300 MainOpen = 630 EndFirstHour = MainOpen + 100 MainEnd = 1300 'Price Levels If Time=MigrateTime(EndFirstHour) Then Top=0 Bot=999999 count=0 GValue503=0 GValue504=99999 For count=0 To BarsPerHour - 1 If High[count]>Top Then Top=High[count] End If If Low[count]<Bot Then Bot=Low[count] End If GValue503=Top GValue504=Bot Next End If 'Signals 'Fist Hour Breakout If Strategy=1 Then If Time>=MigrateTime(EndFirstHour+15) And Time<MigrateTime(MainEnd) Then Top = GValue503 Bot = GValue504 If Close > Top Then Buy("BrkUp", 1, 0, Market, Day) End If If Close < Bot And AllowShorts=1 Then Sell("BrkDn", 1, 0, Market, Day) End If End If End If 'Night and Day If Strategy=2 Then Dim Night As Array Dim Day_ As Array ReDim (Night, 6) ReDim (Day_, 6) If BarNumber = FirstBar Then count=0 For count=0 To 5 Night[count]=0 Day_[count]=0 Next GValue501 = 0 GValue502 = 0 End If Night = GValue501 Day_ = GValue502 If Time = MigrateTime(OneHourBeforeMidnight) Then CumulativeVol=0 End If CumulativeVol=CumulativeVol+Vol If Time=MigrateTime(MainOpen) Then Night[4]=Night[3] Night[3]=Night[2] Night[2]=Night[1] Night[1]=Night[0] Night[0]=CumulativeVol End If AvgNight=(Night[4]+Night[3]+Night[2]+Night[1])/4 If Night[0] > VolRatioUP*AvgNight Then If Time>=MigrateTime(EndFirstHour+15) And Time<MigrateTime(MainEnd) Then Top = GValue503 Bot = GValue504 If Close > Top Then Buy("BrkUp_", 1, 0, Market, Day) End If If Close < Bot And AllowShorts=1 Then Sell("BrkDn_", 1, 0, Market, Day) End If End If End If End If 'Exits for both strategies If Time=MigrateTime(MainEnd) Then If GetMarketPosBack(0)= 1 Then ExitLong("", "", 1, 0, Market, Day) End If If GetMarketPosBack(0)=-1 Then ExitShort("", "", 1, 0, Market, Day) End If End If GValue501 = Night GValue502 = Day_ End Sub
The night and day strategy, as discussed by Domenico D’Errico in “Daytrading With Night Volume” in this issue, is available for download at the following links for NinjaTrader 8 and for NinjaTrader 7.
Once the file is downloaded, you can import the strategy in NinjaTrader 8 from within the Control Center by selecting Tools → Import → NinjaScript Add-On and then selecting the downloaded file for NinjaTrader 8. To import in NinjaTrader 7 from within the Control Center window, select the menu File → Utilities → Import NinjaScript and select the downloaded file.
You can review the strategy’s source code in NinjaTrader 8 by selecting the menu New → NinjaScript Editor → Strategies from within the Control Center window and selecting the NightAndDay file. You can review the strategy’s source code in NinjaTrader 7 by selecting the menu Tools → Edit NinjaScript → Strategy from within the Control Center window and selecting the NightAndDay file.
NinjaScript uses compiled DLLs that run native, not interpreted, which provides you with the highest performance possible.
A sample NinjaTrader chart implementing the strategy is shown in Figure 11.
FIGURE 11: NINJATRADER. The NightAndDay strategy displays the long entry and exit after a volatile night on an ES 06-17 15-minute chart for April 4, 2017.
In “Daytrading With Night Volume” in this issue, author Domenico D’Errico proposes that the nighttime session for a contract’s volume is correlated to the successive day session’s volume range and volatility. The author proposes that by looking for excesses in the night session’s volume compared to an average value, it might be possible to find a better selection of breakout trades.
The Updata code based on this article is in the Updata library and may be downloaded by clicking the custom menu and system library. Those who cannot access the library due to a firewall may paste the code given here into the Updata custom editor and save it.
'Night & Day Demo Strategy NAME "" "" PARAMETER "Mult." @MULT=1 DISPLAYSTYLE 2LINES INDICATORTYPE CHART PLOTSTYLE2 MOUNTAIN COLOUR RGB(200,0,0) #VOLUME=0 #NIGHT0=0 #NIGHT1=0 #NIGHT2=0 #NIGHT3=0 #NIGHT4=0 @AVGVOL=0 @MAX=-1 @MIN=100000 FOR #CURDATE=0 TO #LASTDATE IF (#CURHOUR=8 AND #CURMINUTE<30) OR #CURHOUR<8 #VOLUME=#VOLUME+VOL #NIGHT0=#VOLUME @MAX=MAX(@MAX,HIGH(1)) @MIN=MIN(@MIN,LOW(1)) ENDIF IF (#CURHOUR=8 AND #CURMINUTE=30) #NIGHT4=#NIGHT3 #NIGHT3=#NIGHT2 #NIGHT2=#NIGHT1 #NIGHT1=#NIGHT0 @AVGVOL=(#NIGHT0+#NIGHT1+#NIGHT2+#NIGHT3+#NIGHT4)/5 #VOLUME=0 ENDIF '@AVGVOL=(#NIGHT0+#NIGHT1+#NIGHT2+#NIGHT3+#NIGHT4)/5 IF #NIGHT0>@MULT*@AVGVOL IF (#CURHOUR>8 AND #CURHOUR<10) IF HIGH>@MAX COVER @MAX BUY @MAX ENDIF IF LOW<@MIN SELL @MIN SHORT @MIN ENDIF ENDIF ENDIF IF ORDERISOPEN!=0 AND #CURDAY != HIST(#CURDAY,-1) SELL CLOSE COVER CLOSE ENDIF @PLOT=@AVGVOL @PLOT2=#VOLUME NEXT
A sample Updata chart implementing the strategy is shown in Figure 12.
FIGURE 12: UPDATA. Here, the night & day strategy is applied to FTSE-100 futures data in 30-minute resolution.