Overall Statistics
using QuantConnect.Algorithm;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Orders;
using QuantConnect.Securities;
using System;
using System.Collections.Generic;
using System.Linq;

namespace QuantConnect
{
    public class ConsolidationAlgorithm : QCAlgorithm
    {
        private const decimal stop_loss = 100m;
        private const decimal take_profit = 200m;

        // Tradebar  quoteBar;

        private const string RootSP500 = Futures.Indices.Dow30EMini;
        private readonly HashSet<Symbol> _futureContracts = new HashSet<Symbol>();

        private decimal new_SL = 0.0m;
        private decimal new_TP = 0.0m;
        // int quantity = 1;
        int count = 0;
        int loss = 1;
        public Symbol _symbol = QuantConnect.Symbol.Create(RootSP500, SecurityType.Future, Market.USA);
        private Dictionary<FuturesContract, WilliamsPercentR> _williamsRs;
        //MyMarginModel = FutureMarginModel



        public override void Initialize()
        {
            SetStartDate(year: 2013, month: 10, day: 7);
            SetEndDate(year: 2014, month: 10, day: 11);
            SetCash(startingCash: 350000);
            // Portfolio.MarginCallModel = MarginCallModel.Null;
            SetBrokerageModel(Brokerages.BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin);
                
            var futureSP500 = AddFuture(RootSP500);
            futureSP500.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(value: 91));
            futureSP500.MarginModel = new PatternDayTradingMarginModel() ;
            
            SetBenchmark(x => 0);
            _williamsRs = _williamsRs = new Dictionary<FuturesContract, WilliamsPercentR>();
        }



        public override void OnData(Slice slice)
        {
            foreach (var chain in slice.FutureChains)
            {
                foreach (var contract in chain.Value)
                {
                    if (!_futureContracts.Contains(contract.Symbol))
                    {
                        _futureContracts.Add(contract.Symbol);
                        var consolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(5));

                        consolidator.DataConsolidated += OnDataConsolidated;
                        SubscriptionManager.AddConsolidator(contract.Symbol, consolidator);


                        _williamsRs[contract] = (new WilliamsPercentR(14));

                        RegisterIndicator(contract.Symbol, _williamsRs[contract], consolidator);

                        //Log("|||||Added new consolidator for " + contract.Symbol.Value);
                    }
                }
            }
        }

        private void OnDataConsolidated(object sender, TradeBar quoteBar)
        {

            // Log("OnDataConsolidated called");

            var indicators = _williamsRs.Where(x => x.Key.Symbol == quoteBar.Symbol).ToList();
            decimal price = quoteBar.Value;
            // Log("price" + quoteBar.Value);

            foreach (var willR in indicators)
            {
                if (willR.Key.Expiry < Time)
                {
                    // Drop expirxed indicators
                    //var msg = string.Format("Drop Williams R for {0} at expiration.", willR.Key.Symbol);
                    //Log(msg);
                    _williamsRs.Remove(willR.Key);
                }
                else
                {
                    //var msg = string.Format("Williams R for {0} is {1:F4}", willR.Key.Symbol, willR.Value.Current.Value);
                    //Log(msg);

                    if (willR.Value.IsReady)
                    {
                        if (willR.Value <= -80.0 && count <= 5)
                        {
                            count++;
                            //Log("Counting Oversold " + count);
                        }
                        else
                        {
                            count = 0;
                            //Log("Reset Count" + count);
                        }

                        if (count == 5 && !Portfolio.HoldStock)
                        {
								int quantity =1  ;
                                MarketOrder(willR.Key.Symbol, quantity);
                                Log("Ordering ES Mini : " + quantity);
                        }
                    }
                    if (Portfolio.HoldStock)
                    {
                        // Log("price " + price);
                        // Log("new_SL " + new_SL);
                        // Log("new_TP" + new_TP); 
                        if (price < new_SL)
                        {
                            //Log("SL " + new_SL);
                            loss++;
                            Log("Stop_Loss_Counter " + loss);
                            Liquidate();

                        }
                        else if (price > new_TP)
                        {
                            loss = 1;
                            Log("Take Profit: Reset " + loss);
                            Liquidate();
                        }
                    }
                }
            }
        }
        public override void OnOrderEvent(OrderEvent fill)
        {
            // Only process filled orders
            if (!fill.Status.IsFill()) return;

            var orderId = fill.OrderId;

            // Only considers thisOrder
            // if(thisOrder.OrderId != orderId) return;

            var orderTicket = Transactions.GetOrderTicket(orderId);
            var fill_price = orderTicket.AverageFillPrice;
            var quantity = orderTicket.QuantityFilled;

            // Debug("Order Price " + fill_price) ;
            decimal SL = (fill_price - stop_loss);
            decimal TP = (fill_price + take_profit);

            // Debug("Stop Loss " + SL) ;
            // Debug("Take Profit " + TP) ;

            // Do not use StopMarketOrder LimitOrder, but use a line
            new_SL = SL;
            new_TP = TP;
        }
    }
}