Overall Statistics
Total Trades
24
Average Win
0.33%
Average Loss
-0.62%
Compounding Annual Return
-1.108%
Drawdown
2.600%
Expectancy
-0.234
Net Profit
-1.751%
Sharpe Ratio
-0.638
Loss Rate
50%
Win Rate
50%
Profit-Loss Ratio
0.53
Alpha
-0.013
Beta
0.02
Annual Standard Deviation
0.017
Annual Variance
0
Information Ratio
-0.945
Tracking Error
0.107
Treynor Ratio
-0.534
Total Fees
$131.56
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Data.Consolidators; 
using System.Collections; 
using QuantConnect.Securities;  
using QuantConnect.Models;  

namespace QuantConnect.Algorithm.Examples
{
    /// <summary>
    /// Algorithm that detects over night gaps
    /// </summary>
    public class GapAlgorithm : QCAlgorithm
    {
    	//parameters go here
    	private const decimal StopLossPercent = 0.012m;
    	private const decimal TakeProfitPercent = 0.01m;//1.0m;
    	private const string symbol = "SPY";
    	private const string symbol_1 = "SPY";
        
        // these are open/close minute bars
        // we'll set the open at the beginning of each day to detect gaps
        private TradeBar open;
        // we'll set the close at the end of each day
        private TradeBar close;
        private RateOfChangePercent ROCP_1_CFO ;
        private decimal price = 0;
        private decimal price_1 = 0;
        private decimal gapChange=0.0m;
        private decimal ROCP_CFO=0.0m;
        
        private RollingWindow<TradeBar> _window = new RollingWindow<TradeBar>(2);
        
        //Consolidator Class:
        private Consolidator _consolidator;
        //Set the consolidator period:
        private TimeSpan _barPeriod = TimeSpan.FromDays(1);
        
        
        public override void Initialize()
        {
        	SetStartDate(2004, 01, 01);
            //SetStartDate(2009, 01, 01);
          	//SetStartDate(1998, 01, 01);
            //SetStartDate(2002, 07, 03);
            //SetStartDate(2016, 01, 03);
            //SetEndDate(2016, 02, 01);
       		SetEndDate(2005, 08, 01);
            //SetEndDate(DateTime.Now.Date.AddDays(-1));
            //SetEndDate(2016, 11, 05);
            
            AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
            AddSecurity(SecurityType.Equity, symbol_1, Resolution.Minute);
            
            // 252 trading days in a US year
            ROCP_1_CFO = ROCP(symbol, 5, Resolution.Minute, Field.Close);
            
            //Setup Consolidator bar
            _consolidator = new Consolidator(_barPeriod);
            
            // schedule an event to fire every trading day for a security
            // the time rule here tells it to fire 2 minutes before SPY's market close
            Schedule.On(DateRules.EveryDay("SPY"), TimeRules.BeforeMarketClose("SPY", 2), () =>
            {
            	if(!Portfolio.Invested) return;
                Log("Liquidate all holdings 2 min before close.");
            	Liquidate();
            });
        }

		public void OnData(TradeBars data)
        {
        	//Date gets updated until the consolidator period and then returns true:
            if (_consolidator.Update(data["SPY"]))
            { 
                var bar = _consolidator.Bar;
                _window.Add(bar);
                if (!_window.IsReady) return;
            }
      
            // populate our opening price variable
            if (open == null || open.Time.Date != Time.Date)
            {
                // when TryGetValue succeeds it will populate the 'open'
                // variable with our first minute bar of the day (at 9:31, the bar that spans from 9:30->9:31)
                // if it fails then 'open' will have a value of null
                data.TryGetValue("SPY", out open);
            
                if (open != null && close != null && open.Time.Date != close.Time.Date)
                {
                    // The close of yesterday is greater than the open today.
                    // Gap_Down = Close[1] > Open[0]
                    //bool gapDown = close.Close > open.Open;
                    //decimal gapChange = open.Open/close.Close - 1m;
                    gapChange = open.Open/close.Close - 1m;
                }
            }
            
            if (!_window.IsReady) return;
            
            //Get fresh cash balance: Set purchase quantity to equivalent 10% of portfolio.
            var cash = Portfolio.Cash;
            var holdings = Portfolio[symbol_1].Quantity;
            
            price = data[symbol].Close;
            price_1 = data[symbol_1].Close;
            ROCP_CFO = price / open.Open-1.0m;

            if (( gapChange > 0.001m  && Time.TimeOfDay == new TimeSpan(9, 40, 0) )
                && ( ROCP_CFO>0.001m && price  > _window[0].High ) && ((holdings < 0 || holdings == 0)))
            {
               	Debug(Time + " -> GapUp: " + gapChange.ToString("0.000") );
                Debug(Time + " -> CFO:   " + ROCP_CFO);
            	
            	SetHoldings(symbol_1,  1m);
            }
            
            if (Time.TimeOfDay.TotalHours == 16)
            {
                // when TryGetValue succeeds it will populate the 'close'
                // variable with our final minute bar of the day (at $:00)
                // if it fails then 'close' will have a value of null
                data.TryGetValue("SPY", out close);
            }
        }

		public override void OnOrderEvent(OrderEvent orderEvent)
		{
			// Only process filled orders
			if (!orderEvent.Status.IsFill()) return;
			
			var orderId = orderEvent.OrderId;
			var orderTicket = Transactions.GetOrderTicket(orderId);
			var price = orderTicket.AverageFillPrice;
			
			Log(string.Format("{0} -> {1}-{2} order (#{3}) filled at ${4}",
			    Time, orderEvent.Direction, orderTicket.OrderType, orderId, price.ToString("0.00")));
			
		    // When a buy market order is filled, create stop and limit orders
        	if (orderEvent.Direction == OrderDirection.Buy)
			{
				var quantity = orderTicket.Quantity;
				
				// Set StopLoss order
                StopMarketOrder(symbol_1, -quantity, price * (1m - StopLossPercent));
                   
                // Set Profit Target 
                LimitOrder(symbol_1, -quantity,  price * (1m + TakeProfitPercent));
			}
			// Cancel all open orders
			else
			{
				Transactions.CancelOpenOrders(symbol_1);
			}
		}
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using QuantConnect.Securities;
using QuantConnect.Models;

namespace QuantConnect 
{
    
    /*
    *   TimeSpanConsolidator Helper Routine: Assemble generic timespan bar lengths: e.g. 10 minutes:
    *
    *   1. Setup the new Consolidator class with the timespan period:
    *   var _consolidator = new Consolidator(TimeSpan.FromMinutes(10));
    *
    *   2. Add in the data with the update routine. It will return true when bar ready
    *   if (_consolidator.Update(data["MSFT"])) {   UseBar    }
    */
    public class Consolidator 
    {
        private TradeBar _resultBar;
        private TradeBar _workingBar;
        private DateTime _start;
        private TimeSpan _period;
        
        //Result:
        public TradeBar Bar
        {
            get
            {
                return _resultBar;
            }
        }
        
        //Constructor: Set the period we'd like to scan
        public Consolidator(TimeSpan span) 
        {
            this._period = span;
            this._resultBar = new TradeBar();
            this._workingBar = new TradeBar(new DateTime(), "", Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0);
        }
        
        //Submit this bar, return true if we've started a new one.
        public bool Update(TradeBar newBar)
        {
            //Intialize:
            if (_start == new DateTime()) 
            {
                _start = newBar.Time;
            }
            
            //While we're less than end date, keep adding to this bar:
            if (newBar.Time < (_start + _period))
            {
                //Building bar:
                AddToBar(newBar);
                return false;
            } 
            else 
            {
                //Completed bar: start new one:
                _resultBar = _workingBar;
                //Create a new bar:
                _workingBar = new TradeBar(newBar.Time, newBar.Symbol, Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0);
                //Start of this bar:
                _start = newBar.Time;
                AddToBar(newBar);
                return true;
            }
        }
        
        //Add to a tradebar
        private void AddToBar(TradeBar newBar)
        {
            //Add this data to working bar:
            if (_workingBar.Time == new DateTime()) _workingBar.Time = newBar.Time;
            if (_workingBar.Symbol == "") _workingBar.Symbol = newBar.Symbol;
            if (_workingBar.Open == Decimal.Zero) _workingBar.Open = newBar.Open;
            if (newBar.High > _workingBar.High) _workingBar.High = newBar.High;
            if (newBar.Low < _workingBar.Low) _workingBar.Low = newBar.Low;
            _workingBar.Close = newBar.Close;
            _workingBar.Volume = newBar.Volume;
        }
    }

}