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
        
    	const decimal StopLossPercent = 0.012m;
    	const decimal TakeProfitPercent = 1.0m;
    	
        private OrderTicket CurrentOrder;
    	private OrderTicket StopLoss;
    	private OrderTicket ProfitTarget;
    	
    	
        // these are open/close minute bars
        // we'll set the open at the beginning of each day to detect gaps
        TradeBar open;
        // we'll set the close at the end of each day
        TradeBar close;
        private RateOfChangePercent ROCP_1_CFO ;
            decimal price = 0;
        decimal price_1 = 0;
        decimal price_01 = 1;
    	private string symbol="SPY";
    	
    	private string symbol_1="SPY";
        private  decimal gapChange=0.0m;
        private  decimal ROCP_CFO=0.0m;
        
        
        RollingWindow<TradeBar> _window = new RollingWindow<TradeBar>(2);
        //Set the consolidator period:
        private TimeSpan _barPeriod = TimeSpan.FromDays(1);
        
        //Consolidator Class:
        private Consolidator _consolidator;
        //Initialize the data and resolution you require for your strategy:
        
        /// <summary>
        /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
        /// </summary>
        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);
            
            ROCP_1_CFO = new RateOfChangePercent("SPY", 5); // 252 trading days in a US year
            // RegisterIndicator(symbol,  Resolution.Minute, Field.Close);
            RegisterIndicator(symbol, ROCP_1_CFO, Resolution.Minute, Field.Close);
            
              //Setup Consolidator bar bar
            _consolidator = new Consolidator(_barPeriod);
        }


        /// <param name="data">TradeBars IDictionary object with your stock data</param>
        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;
            price = data[symbol].Close;
            price_1 = data[symbol_1].Close;
           //Get fresh cash balance: Set purchase quantity to equivalent 10% of portfolio.
            decimal cash = Portfolio.Cash;
            
            int holdings = Portfolio[symbol_1].Quantity;
            
            
            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)))
            {
                   Console.WriteLine(Time + " - GapUp: " + gapChange.ToString("0.000") );
                   Console.WriteLine(Time + " - CFO:   " + ROCP_CFO);
                   
                   
                   //quantity = Convert.ToInt32((cash * 1.0m)/ price_1);
                   // Calculate quantity based on available cash
            	   var quantity = (int) (Portfolio.Cash / price_1);
            	   

                   
                   price_01=price_1;
                   
                   
                   CurrentOrder = Order(symbol_1,  quantity);
                   //Log(Time.ToShortDateString() + "> Go Long >  Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " + ROCP_CFO.Samples); 


            	  // Set StopLoss order
                   StopLoss = StopMarketOrder(symbol_1, -quantity, price_1 * (1m - StopLossPercent));
                   
                   // Set Profit Target 
                   ProfitTarget = LimitOrder(symbol_1, -quantity,  price_1 * (1m + TakeProfitPercent));
           	            
           	            
                   Log( "ROCP_1_CFO: " + ROCP_1_CFO );
                   
                   
                   
                   Log( "holdings: " + holdings );
                   Log( "PT order id: " + ProfitTarget.OrderId);
                   Log( "StopLoss order id: " + StopLoss.OrderId);
            }
            
            
    
            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);
            }
            
            // at 3:58 liquidate
            if (Portfolio.Invested && Time.TimeOfDay == new TimeSpan(15, 58, 0)  && (holdings != 0))
            {
                Console.WriteLine(Time + " EOD order:   "  + holdings );
                Log( "3:58pm holdings: " + holdings );
                Liquidate();
            }
        }

        // If the StopLoss or ProfitTarget is filled, cancel the other
        // If you don't do this, then  the ProfitTarget or StopLoss order will remain outstanding
        // indefinitely, which will cause very bad behaviors in your algorithm
        public override void OnOrderEvent(OrderEvent orderEvent)
		{
			// Ignore OrderEvents that are not closed
			if (!orderEvent.Status.IsClosed())
			{
				return;
			}
			
			// Defensive check
			if (ProfitTarget == null || StopLoss == null)
			{
				return;
			}
			
			var filledOrderId = orderEvent.OrderId;

			// If the ProfitTarget order was filled, close the StopLoss order
			if (ProfitTarget.OrderId == filledOrderId)
			{
                Console.WriteLine(Time +" ProfitTarget is filled " +ProfitTarget.OrderId + " Filled Order is  " + filledOrderId );
                Log( "ProfitTarget is filled " +ProfitTarget.OrderId );
				StopLoss.Cancel();
			}

			// If the StopLoss order was filled, close the ProfitTarget
			if (StopLoss.OrderId == filledOrderId)
			{   
				Console.WriteLine(Time +  " StopLoss Order is filled " +StopLoss.OrderId + " Filled Order is  " + filledOrderId );
                Log( "StopLoss Order is filled " +StopLoss.OrderId );
				ProfitTarget.Cancel();
			}
			
		}
    }
}
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;
        }
    }

}