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