Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$0.00
using System.Threading.Tasks;

namespace QuantConnect 
{   
    /*
    *   Basic Template Algorithm
    *
    *   The underlying QCAlgorithm class has many methods which enable you to use QuantConnect.
    *   We have explained some of these here, but the full base class can be found at:
    *   https://github.com/QuantConnect/Lean/tree/master/Algorithm
    */
    public class GapOnOpen : QCAlgorithm
    {
    	
        private SecurityExchange Exchange;

        private Dictionary<Symbol, TradeBar> lastClose;
        private GapEvaluator gapEvaluator;

        public override void Initialize() {
            SetStartDate(2017, 2, 1);
            SetEndDate(DateTime.Now.AddDays(-1));

            SetCash(25000);

            gapEvaluator = new GapEvaluator(0.005m, false);

            AddSecurity(SecurityType.Equity, "SPY");
            
            // S&P500 simulation
            //AddUniverse(coarse => (from c in coarse orderby c.DollarVolume descending select c.Symbol).Take(500));
            AddUniverse(coarse => (from c in coarse orderby c.DollarVolume descending select c.Symbol).Take(150));

            Exchange = Securities["SPY"].Exchange;

            Debug(Exchange.Hours.MarketHours[DayOfWeek.Monday].Segments.First().Start.ToString());

            Schedule.On(DateRules.EveryDay(), TimeRules.BeforeMarketClose(Symbol("SPY")), AtMarketClose);
            Schedule.On(DateRules.EveryDay(), TimeRules.AfterMarketOpen(Symbol("SPY"), 61), AfterMarketOpen);
        }
        
        private void AtMarketClose() {
			var lastCandles = History(TimeSpan.FromHours(1), Resolution.Hour).ToArray();
            lastClose = new Dictionary<Symbol, TradeBar>();

            Parallel.Invoke(GC.Collect);

            if(!lastCandles.Any()) return;

            var slice = lastCandles.First();


            foreach(var bar in slice.Bars) {
                if(!lastClose.ContainsKey(bar.Key)) {
                    lastClose.Add(bar.Key, bar.Value);
                }
            }
        }

        private void AfterMarketOpen() {
            if(lastClose == null) return;

            var history = History(TimeSpan.FromHours(1), Resolution.Hour).ToArray();
            
            if(!history.Any()) return;

            var newCandles = history.First();

            foreach(var candle in newCandles.Bars) {
                if(!lastClose.ContainsKey(candle.Key)) {
                    //Debug($"Key {candle.Key.Value} not contained");
                    continue;
                }
                var oldCandle = lastClose[candle.Key];

                var gapQuality = 0m;
                var gapDirection = gapEvaluator.EvaluateGap(oldCandle, candle.Value, out gapQuality);
                if(gapDirection != GapType.None) {
                    Debug($"{candle.Value.Time} => Gap found for Symbol {candle.Key.Value}: {gapDirection}");
                }
            }
        }

       public override void OnData(Slice data) {
            
        }
    }
}
namespace QuantConnect {
	
	public enum GapType {
		None,
		Up,
		Down
	}
	
    public class GapEvaluator {
    	public decimal GapThreshold { get; set; }

        public bool AccountHighLowDifference { get; set; }

        public GapEvaluator(decimal gapThreshold, bool accountHighLowDifference) {
            GapThreshold = gapThreshold;
            AccountHighLowDifference = accountHighLowDifference;
        }

        public GapType EvaluateGap(TradeBar older, TradeBar newer, out decimal quality) {
            var gapDistance = (newer.Open - older.Close) / older.Close;
            
            if(Math.Abs(gapDistance) < GapThreshold) {
                quality = 0;
                return GapType.None;
            }

            var gapType = gapDistance < 0 ? GapType.Down : GapType.Up;

            decimal highLowDistance = 0;

            if(gapType == GapType.Up) {
                highLowDistance = (newer.Low - older.High) / older.High;
            } else {
                highLowDistance = (older.Low - newer.High) / newer.High;
            }

            quality = gapDistance + (AccountHighLowDifference ? highLowDistance : 0);

            return gapType;
        }
    }

}