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 ); } } } }