Overall Statistics
using System;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Securities.Future;
using QuantConnect.Indicators;

namespace QuantConnect.Algorithm.CSharp
{
    /// <summary>
    /// EMA cross with SP500 E-mini futures
    /// In this example, we demonstrate how to trade futures contracts using
    /// a equity to generate the trading signals
    /// It also shows how you can prefilter contracts easily based on expirations.
    /// It also shows how you can inspect the futures chain to pick a specific contract to trade.
    /// </summary>
    /// <meta name="tag" content="using data" />
    /// <meta name="tag" content="futures" />
    /// <meta name="tag" content="indicators" />
    /// <meta name="tag" content="strategy example" />
    public class FuturesMomentumAlgorithm : QCAlgorithm
    {
        private const decimal _tolerance = 0.001m;

        private ExponentialMovingAverage _fast;
        private ExponentialMovingAverage _slow;
        private SimpleMovingAverage[] _ribbon;
        private RelativeStrengthIndex _rsi;
        private AroonOscillator _aroon;
        
        private bool _long = true;
        private decimal _price;
        private string _symbol = "SPY";
        private bool _orderHold = true;
        
        private bool _tradeShort = true;
        private bool _tradeLong = true;
        private SecurityPortfolioManager _previousPortfolio = null;
        
        private decimal _vix;

        public bool IsReady { get { return _fast.IsReady && _slow.IsReady; } }
        public bool IsUpTrend { get { return IsReady && _fast > _slow * (1 + _tolerance); } }
        public bool IsDownTrend { get { return IsReady && _fast < _slow * (1 + _tolerance); } }
 

        public override void Initialize()
        {
            SetStartDate(2017, 10, 1);
            SetEndDate(DateTime.Now);
            SetCash(40000);
            SetWarmUp(Math.Max(24, 48));

			//VIX volatility
			//AddData<Quandl>("CBOE/VIX");
			AddData<QuandlVix>("CBOE/VIX");
			
            // Adds SPY to be used in our EMA indicators
            AddSecurity(SecurityType.Equity, _symbol, Resolution.Minute);
            var equity = AddEquity(_symbol, Resolution.Minute);
            _fast = EMA(equity.Symbol, 24, Resolution.Hour);
            _slow = EMA(equity.Symbol, 5, Resolution.Daily);
            _aroon = AROON(_symbol, 24, Resolution.Hour);
            
            var ribbonCount = 8;
            var ribbonInterval = 15;
            _ribbon = Enumerable.Range(0, ribbonCount).Select(x => SMA(_symbol, (x + 1)*ribbonInterval, Resolution.Daily)).ToArray();

			_rsi = RSI(_symbol, 14,  MovingAverageType.Simple, Resolution.Daily);

            // Adds the future that will be traded and
            // set our expiry filter for this futures chain
            var future = AddFuture(Futures.Indices.SP500EMini);
            future.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
            
            var benchmark = AddEquity(_symbol);
            SetBenchmark(benchmark.Symbol);
            
            Securities[_symbol].TransactionModel = new ConstantFeeTransactionModel(1);
            
            //Brokerage model and account type:
			SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin);
        }
        
        public bool IsExecuteBeforeMarketClosure 
        {
        	get 
        	{
        		var exchange = Securities[_symbol].Exchange;
        		bool isMarketOpen = exchange.DateTimeIsOpen(Time);
        		//bool isExecuteBeforeMarketClosure = isMarketOpen 
        		//	&& exchange.DateTimeIsOpen(Time.AddMinutes(10)) 
        		//	&& !exchange.DateTimeIsOpen(Time.AddMinutes(15));
        		//return isExecuteBeforeMarketClosure;
        		return isMarketOpen;
        	} 
        }
        public void OnData(Quandl data) 
        {
        	if (data.Symbol=="CBOE/VIX")
			{
				_vix=data.Value;
				Plot("Data-vix", "VIX", _vix);
			}
        }
 		public void OnData(TradeBars data)
        {   
        	if(data.ContainsKey(_symbol))
        	{
            	_price = data[_symbol].Close;
        	}
            
            if (!_slow.IsReady) return;	
       		
       		//avoid random start
       		if(_orderHold && Math.Abs(_fast - _slow) >= 0.05m)
       		{
       			_orderHold = false;
       			Log("OrderHold = false");
       			Plot("Data", "Price", _price);
   				Plot("Data", _fast, _slow);
       		}
        }
        public override void OnData(Slice slice)
        {
        	if (!_slow.IsReady || !_rsi.IsReady) return;
        	
        	if(_orderHold) return;

        	if(_tradeLong)
        	{
            if (!Portfolio.Invested && IsUpTrend)
            {
                foreach (var chain in slice.FutureChains)
                {
                    // find the front contract expiring no earlier than in 90 days
                    var contract = (
                        from futuresContract in chain.Value.OrderBy(x => x.Expiry)
                        where futuresContract.Expiry > Time.Date.AddDays(90)
                        select futuresContract
                        ).FirstOrDefault();

                    // if found, trade it
                    if (contract != null)
                    {
                    	if(IsExecuteBeforeMarketClosure)
                    	{
                        	MarketOrder(contract.Symbol, 1);
                        	_long = true;
                    	}
                    }
                }
            }

            if (Portfolio.Invested && _long && IsDownTrend)
            {
            	if(IsExecuteBeforeMarketClosure)
                    	{
                			Liquidate();
                    	}
            }
        	}
            
            if(_tradeShort)
            {
            if (!Portfolio.Invested && IsDownTrend)
            {
                foreach (var chain in slice.FutureChains)
                {
                    // find the front contract expiring no earlier than in 90 days
                    var contract = (
                        from futuresContract in chain.Value.OrderBy(x => x.Expiry)
                        where futuresContract.Expiry > Time.Date.AddDays(90)
                        select futuresContract
                        ).FirstOrDefault();

                    // if found, trade it
                    if (contract != null)
                    {
                    	if(IsExecuteBeforeMarketClosure)
                    	{
                        	MarketOrder(contract.Symbol, -1);
                        	_long = false;
                    	}
                    }
                }
            }

            if (Portfolio.Invested && !_long && IsUpTrend)
            {
            	if(IsExecuteBeforeMarketClosure)
               	{
                	Liquidate();
                }
            }
            }
            if(_previousPortfolio != null)
            {
            	//Dictionary<Symbol, SecurityHolding>
            	foreach (var holding in Portfolio.Values)
            	{
            		if(holding != null)
            		{
            		foreach (var previousHolding in _previousPortfolio.Values)
            		{
            			if(previousHolding != null)
            			{
            			if(holding.Quantity != previousHolding.Quantity)// ||
            			//	futureHolding.IsLong != previousFutureHolding.IsLong ||
            			//futureHolding.IsShort != previousFutureHolding.IsShort)
            			{
            				Log("Holdings Changed");
            				Plot("Indicator Signal", "Trend", IsDownTrend ? -1 : IsUpTrend ? 1 : 0);
            				Plot("Holdings", "Qty", holding.Quantity);
            				Plot("Data", "Price", _price);
   							Plot("Data", _fast, _slow);
            			}
            			}
            		}
            		}
            	}
            }
            _previousPortfolio = Portfolio;
        }

        public override void OnEndOfDay()
        {
  
            if (!_slow.IsReady || !_rsi.IsReady) return;
            
            //Plot("EMA", "Price", _price);
   			//Plot("EMA", _fast, _slow);
   			//Plot("Ribbon", _ribbon);
   			//Plot("RSI", _rsi);
   			//Plot("AROON", _aroon.AroonUp, _aroon.AroonDown);
   			
   			//var price = Identity(_symbol);
			//PlotIndicator(_symbol, _price, _fast, _slow);
        }

        public override void OnOrderEvent(OrderEvent orderEvent)
        {
            Log(orderEvent.ToString());
        }
        

    }
    public class QuandlVix : Quandl 
	{
    	public QuandlVix() : base(valueColumnName: "vix close") { }
	}	
}