Overall Statistics
#region imports
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Globalization;
    using System.Drawing;
    using QuantConnect;
    using QuantConnect.Algorithm.Framework;
    using QuantConnect.Algorithm.Framework.Selection;
    using QuantConnect.Algorithm.Framework.Alphas;
    using QuantConnect.Algorithm.Framework.Portfolio;
    using QuantConnect.Algorithm.Framework.Execution;
    using QuantConnect.Algorithm.Framework.Risk;
    using QuantConnect.Parameters;
    using QuantConnect.Benchmarks;
    using QuantConnect.Brokerages;
    using QuantConnect.Util;
    using QuantConnect.Interfaces;
    using QuantConnect.Algorithm;
    using QuantConnect.Indicators;
    using QuantConnect.Data;
    using QuantConnect.Data.Consolidators;
    using QuantConnect.Data.Custom;
    using QuantConnect.DataSource;
    using QuantConnect.Data.Fundamental;
    using QuantConnect.Data.Market;
    using QuantConnect.Data.UniverseSelection;
    using QuantConnect.Notifications;
    using QuantConnect.Orders;
    using QuantConnect.Orders.Fees;
    using QuantConnect.Orders.Fills;
    using QuantConnect.Orders.Slippage;
    using QuantConnect.Scheduling;
    using QuantConnect.Securities;
    using QuantConnect.Securities.Equity;
    using QuantConnect.Securities.Future;
    using QuantConnect.Securities.Option;
    using QuantConnect.Securities.Forex;
    using QuantConnect.Securities.Crypto;
    using QuantConnect.Securities.Interfaces;
    using QuantConnect.Storage;
    using QuantConnect.Data.Custom.AlphaStreams;
    using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm;
    using QCAlgorithmFrameworkBridge = QuantConnect.Algorithm.QCAlgorithm;
#endregion

namespace QuantConnect.Algorithm.CSharp
{
   
    public class FuturesAlgo: QCAlgorithm
    {      
		#region Global Vars
        private Future ContinuousContract;
        private Future ContinuousContract_1;
        private Security CurrentContract;
		private Symbol CurrentContract_Symbol;
        private Security PreviousContract;
        private AverageDirectionalIndex AdxFast;
        private AverageDirectionalIndex AdxSlow;
        private AverageDirectionalIndex AdxUltra;
		private decimal Tolerance = .02m;
		private bool IsLong = false;
		private bool IsShort = false;
        private bool IsFlat = true;
        ExponentialMovingAverage _ema;
        Decimal AdxFast_Plus_1 = 0.0m; // I declared these as decimals as the adx values are also decimals and needed the same type to do math later. Not sure if we need to recast as double or floats?
        Decimal AdxFast_Minus_1 = 0.0m;
        Decimal AdxFast_Adx_1 = 0.0m;
        Decimal AdxSlow_Plus_1 = 0.0m;
        Decimal AdxSlow_Minus_1 = 0.0m;
        Decimal AdxSlow_Adx_1 = 0.0m;
        Decimal AdxUltra_Plus_1 = 0.0m;
        Decimal AdxUltra_Minus_1 = 0.0m;
        private TradeBar slowbar;
        private TradeBar fastbar;
        private TradeBarConsolidator slow_consolidator;
        private TradeBarConsolidator fast_consolidator;
        Decimal AdxSlow_Adx_Lastbar = 0.0m;
        Decimal AdxSlow_Plus_Lastbar = 0.0m;
        Decimal AdxSlow_Minus_Lastbar = 0.0m;
        Decimal AdxFast_Adx_Lastbar = 0.0m;
        Decimal AdxFast_Plus_Lastbar = 0.0m;
        Decimal AdxFast_Minus_Lastbar = 0.0m;
        Decimal AdxFast_Adx; // Added these which are the ADX indicators in addition to the +/- that you had already
        Decimal AdxSlow_Adx;
        Decimal AdxFast_Plus;
        Decimal AdxFast_Minus;
        Decimal AdxSlow_Plus;
        Decimal AdxSlow_Minus;
        Decimal AdxSlow_Plus_from_last = 0.0m;
        Decimal AdxSlow_Minus_from_last = 0.0m;
        Decimal AdxFast_Plus_from_last = 0.0m;
        Decimal AdxFast_Minus_from_last = 0.0m;
        int slow_time;
        int fast_time;
        #endregion

        public override void Initialize()
        {
            //SetTimeZone(TimeZones.LosAngeles);
			SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin);// changed to Cash. Not sure if it mattered
            SetStartDate(2021, 01, 01);
            //SetEndDate(2022, 6 ,20);
			SetCash(100000);
            
            
            ContinuousContract = AddFuture(Futures.Indices.SP500EMini,
                fillDataForward: true,
                resolution: Resolution.Second,
                dataNormalizationMode: DataNormalizationMode.Raw,
                extendedMarketHours: true,
                dataMappingMode: DataMappingMode.OpenInterest, //changed to Open Interest as this is more indicative of when we should switch the trade to new contract than just last day
                contractDepthOffset: 0);
            //ContinuousContract.SetFilter(0,90);

            //var CurrentContract = ContinuousContract;           

            fast_time = GetParameter("Fast", 180);
            slow_time = GetParameter("Slow", 3600);
            AdxFast = ADX(ContinuousContract.Symbol, fast_time , Resolution.Second);
            AdxSlow = ADX(ContinuousContract.Symbol, slow_time , Resolution.Second);
            //AdxUltra = ADX(ContinuousContract.Symbol, 1 , Resolution.Second); // This is maybe important later. Ignore for now

            slow_consolidator = new TradeBarConsolidator(TimeSpan.FromSeconds(slow_time));
            slow_consolidator.DataConsolidated += SlowBarHandler;
            SubscriptionManager.AddConsolidator(ContinuousContract.Symbol, slow_consolidator);
            
            fast_consolidator = new TradeBarConsolidator(TimeSpan.FromSeconds(fast_time));
            fast_consolidator.DataConsolidated += FastBarHandler;
            SubscriptionManager.AddConsolidator(ContinuousContract.Symbol, fast_consolidator);
            
			SetWarmUp(AdxSlow.WarmUpPeriod);
            SetWarmup(AdxFast.WarmUpPeriod);
            //OnWarmupFinished(FastBarHandler);
        }

        public override void OnData(Slice data)
        {   
            if(!AdxSlow.IsReady || !AdxFast.IsReady)
            {
                return;
            }

            SetContract(data);

            AdxFast_Adx = AdxFast.Current.Value; 
            AdxSlow_Adx = AdxSlow.Current.Value;
            AdxFast_Plus = AdxFast.PositiveDirectionalIndex.Current.Value;
            AdxFast_Minus = AdxFast.NegativeDirectionalIndex.Current.Value;
            AdxSlow_Plus = AdxSlow.PositiveDirectionalIndex.Current.Value;
            AdxSlow_Minus = AdxSlow.NegativeDirectionalIndex.Current.Value;
            var AdxFast_Plus_Dif = AdxFast_Plus-AdxFast_Plus_1;
            var AdxFast_Minus_Dif = AdxFast_Minus-AdxFast_Minus_1;
            var dif = Math.Abs(AdxSlow_Plus-AdxSlow_Minus);
            int max_vol = GetParameter("max_vol", 15);
            //var AdxUltra_Plus = AdxUltra.PositiveDirectionalIndex.Current.Value;
            //var AdxUltra_Minus = AdxUltra.NegativeDirectionalIndex.Current.Value;
            //var Ultra_dif = Math.Abs(AdxUltra_Plus-AdxUltra_Minus);
            AdxSlow_Plus_from_last = AdxSlow_Plus- AdxSlow_Plus_Lastbar;
            AdxSlow_Minus_from_last = AdxSlow_Minus - AdxSlow_Minus_Lastbar;
            AdxFast_Plus_from_last = AdxFast_Plus - AdxFast_Plus_Lastbar;
            AdxFast_Minus_from_last = AdxFast_Minus - AdxFast_Minus_Lastbar;
        
            
            if (AdxFast_Adx_1 == 0) //we pass this to any variable of _Previous that is defined as 0 so that it skips the first loop
            {
                AdxFast_Adx_Lastbar = AdxFast_Adx;
                AdxFast_Plus_Lastbar = AdxFast_Plus;
                AdxFast_Minus_Lastbar = AdxFast_Minus;
                AdxSlow_Adx_Lastbar = AdxSlow_Adx;
                AdxSlow_Plus_Lastbar = AdxSlow_Plus;
                AdxSlow_Minus_Lastbar = AdxSlow_Minus;
                goto after_flat;
            }

            foreach (var changedEvent in data.SymbolChangedEvents.Values)
            {
                Debug($"{Time} - SymbolChanged event: {changedEvent}");
                if (Time.TimeOfDay == TimeSpan.Zero)
                {
                    continue;
                }
                throw new Exception($"{Time} unexpected symbol changed event {changedEvent}!");
            }

            after_trade:
            if (IsFlat && AdxFast_Adx_1 != 0)
            {
                if(AdxFast_Plus_Lastbar < AdxFast_Minus_Lastbar /*Plus at end of FastConsolidated Bar was less than minus*/  && AdxFast_Plus != AdxFast_Plus_Lastbar /* We assign current value at end of last consolidated bar so do not trigger in that bar*/&& AdxFast_Plus > AdxFast_Minus /*currently Plus > Minus so, we have a positive crossover*/ && AdxSlow_Plus_from_last < max_vol /*We didn't see too big of a volatility spoke between now and when the last bar closed*/&& AdxSlow_Plus != AdxSlow_Plus_Lastbar) 
                {
                    Buy(CurrentContract_Symbol, 1);
                    IsFlat = false;
                    IsLong = true;
                    //goto after_trade;
                }
                if(AdxFast_Minus_Lastbar < AdxFast_Plus_Lastbar && AdxFast_Plus != AdxFast_Plus_Lastbar && AdxFast_Minus > AdxFast_Plus && AdxSlow_Minus_from_last < max_vol && AdxSlow_Plus != AdxSlow_Plus_Lastbar)
                {
                    Sell(CurrentContract_Symbol, 1);
                    IsFlat = false;
                    IsShort = true;
                    //goto after_trade;
                }
            }

            if(IsLong && AdxSlow_Minus != AdxSlow_Minus_Lastbar && AdxFast_Plus != AdxFast_Plus_Lastbar && ((AdxSlow_Adx_Lastbar < AdxSlow_Plus_Lastbar && AdxSlow_Plus < AdxSlow_Adx && AdxSlow_Adx <20)||(AdxFast_Minus > 26 && AdxFast_Minus_from_last > 20)))// The PlusSlow goes below the Adx and was previously greater
            {
                Liquidate(CurrentContract_Symbol);
                //Sell(CurrentContract_Symbol, 1);// you had buy -1 to close the long, changed to sell 1
                IsFlat = true;
                IsLong = false;
                IsShort = false;
                goto after_trade;
            }

            if(IsShort && AdxSlow_Minus != AdxSlow_Minus_Lastbar && AdxFast_Plus != AdxFast_Plus_Lastbar && ((AdxSlow_Adx_Lastbar < AdxSlow_Minus_Lastbar && AdxSlow_Minus < AdxSlow_Adx && AdxSlow_Adx<20)||(AdxFast_Plus > 26 && AdxFast_Plus_from_last > 20)))// Same as above but with the MinusSlow
            {
                Liquidate(CurrentContract_Symbol);
                //Buy(CurrentContract_Symbol, 1);
                IsFlat = true;
                IsLong = false;
                IsShort = false;
                goto after_trade;
            }
            /*if (AdxSlow.IsReady)
            {
                Plot("My Indicators", "positivedirectionalindex", AdxSlow.PositiveDirectionalIndex);
                Plot("My Indicators", "negativedirectionalindex", AdxSlow.NegativeDirectionalIndex);
                Plot("My Indicators", "averagedirectionalindex", AdxSlow.Current.Value);
            }*/
            after_flat:

            AdxFast_Adx_1 = AdxFast_Adx; // these were 0.0 in the first pass, assuming this will update them after the first? correct me if I'm wrong. 
            AdxSlow_Adx_1 = AdxSlow_Adx;
            AdxFast_Plus_1 = AdxFast_Plus;
            AdxFast_Minus_1 = AdxFast_Minus;
            AdxSlow_Plus_1 = AdxSlow_Plus;
            AdxSlow_Minus_1 = AdxSlow_Minus;
            PreviousContract = CurrentContract;
        }
        
        private void SetContract(Slice slice)
        {
            CurrentContract = Securities[ContinuousContract.Mapped];
            CurrentContract_Symbol = CurrentContract.Symbol;

            if(PreviousContract!= null && CurrentContract != PreviousContract )
            {
                Liquidate(PreviousContract.Symbol);
            }
        }

        private void FastBarHandler(object sender, TradeBar consolidated)
        {
            /*if (fastbar != null)
            {
                AdxFast_Adx_Lastbar = AdxFast_Adx;
                AdxFast_Plus_Lastbar = AdxFast_Plus;
                AdxFast_Minus_Lastbar = AdxFast_Minus;
            }*/
            AdxFast_Adx_Lastbar = AdxFast_Adx;
            AdxFast_Plus_Lastbar = AdxFast_Plus;
            AdxFast_Minus_Lastbar = AdxFast_Minus;
            fastbar = consolidated;
        }
        private void SlowBarHandler(object sender, TradeBar consolidated)
        {   
            /*if (slowbar != null)
            {
                AdxSlow_Adx_Lastbar = AdxSlow_Adx;
                AdxSlow_Plus_Lastbar = AdxSlow_Plus;
                AdxSlow_Minus_Lastbar = AdxSlow_Minus;
            }*/
            AdxSlow_Adx_Lastbar = AdxSlow_Adx;
            AdxSlow_Plus_Lastbar = AdxSlow_Plus;
            AdxSlow_Minus_Lastbar = AdxSlow_Minus;
            slowbar = consolidated;
        }
        public void OnData(TradeBars bars)
        {
            // we need to declare this method
        }
        public void Update(IBaseData data)
        {

        }
	}
}