Overall Statistics
Total Trades
1
Average Win
0%
Average Loss
0%
Compounding Annual Return
15.566%
Drawdown
9.600%
Expectancy
0
Net Profit
0%
Sharpe Ratio
1.257
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0.016
Beta
0.984
Annual Standard Deviation
0.12
Annual Variance
0.014
Information Ratio
0.886
Tracking Error
0.016
Treynor Ratio
0.153
Total Fees
$2.55
namespace QuantConnect 
{   
    public class MultiTimeFrameRollingWindowIndicatorAlgorithm : QCAlgorithm
    {
        private int _period = 30;
        private Dictionary<int, RollingWindow<IndicatorSuiteState>> _window = new Dictionary<int, RollingWindow<IndicatorSuiteState>>();

        public override void Initialize()
        {
            SetStartDate(2016, 1, 1);

            AddEquity("SPY", Resolution.Minute);

            foreach (var minute in new int[] { 5, 10, 15, 20, 30 })
            {
                // Create Consolidator
                var consolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(minute));

                // Create indicators
                var suite = new IndicatorSuite(minute.ToString(), 14, 14, 10, 20);

                // Add new rolling window to the _window dictionary
                _window.Add(minute, new RollingWindow<IndicatorSuiteState>(_period));

                // Register indicators to the consolidator to be updated at its frequency
                RegisterIndicator("SPY", suite, consolidator);

                // Updates the rolling window using an anonymous method
                consolidator.DataConsolidated += (s, bar) =>
                {
                    if (!suite.IsReady) return;

                    // Uses a wrapper to save only the state of the indicator suite
                    _window[bar.Period.Minutes].Add(new IndicatorSuiteState(suite));
                };

                // Add the consolidator to the subscription manager to get updated with data from security 
                SubscriptionManager.AddConsolidator("SPY", consolidator);
            }
        }

        public override void OnData(Slice data)
        {
            if (!Portfolio.HoldStock) SetHoldings("SPY", 1);
        }

        // At end of day, plot the indicators for visual sanity check
        public override void OnEndOfDay()
        {
            if (!_window[30].IsReady) return;

            // Last IndicatorSuite (index 0) of the 30 min consolidator
            var suite = _window[30][0];
            Plot("Indicators", "ADX", suite.ADX.Current);
            Plot("Indicators", "RSI", suite.RSI.Current);
            Plot("Indicators", "Fast SMA", suite.FastSMA.Current);
            Plot("Indicators", "Slow SMA", suite.SlowSMA.Current);
        }
    }

    public class IndicatorSuite : BarIndicator
    {
        public AverageDirectionalIndex ADX;
        public RelativeStrengthIndex RSI;
        public SimpleMovingAverage FastSMA;
        public SimpleMovingAverage SlowSMA;

        public override bool IsReady { get { return ADX.IsReady && RSI.IsReady && FastSMA.IsReady && SlowSMA.IsReady; } }

        public IndicatorSuite(string name, int adxPeriod, int rsiPeriod, int fastSmaPeriod, int slowSmaPeriod)
            : base(name)
        {
            ADX = new AverageDirectionalIndex("", adxPeriod);
            RSI = new RelativeStrengthIndex(rsiPeriod);
            FastSMA = new SimpleMovingAverage(fastSmaPeriod);
            SlowSMA = new SimpleMovingAverage(slowSmaPeriod);
        }

        protected override decimal ComputeNextValue(IBaseDataBar input)
        {
            ADX.Update(input);
            RSI.Update(input.EndTime, input.Value);
            FastSMA.Update(input.EndTime, input.Value);
            SlowSMA.Update(input.EndTime, input.Value);

            return 0;
        }
    }

    public class IndicatorSuiteState
    {
        public AverageDirectionalIndexState ADX;
        public RelativeStrengthIndexState RSI;
        public SimpleMovingAverageState FastSMA;
        public SimpleMovingAverageState SlowSMA;

        public IndicatorSuiteState(IndicatorSuite suite)
        {
            ADX = new AverageDirectionalIndexState(suite.ADX);
            RSI = new RelativeStrengthIndexState(suite.RSI);
            FastSMA = new SimpleMovingAverageState(suite.FastSMA);
            SlowSMA = new SimpleMovingAverageState(suite.SlowSMA);
        }

        public class AverageDirectionalIndexState
        {
            public readonly string Name;
            public readonly IndicatorDataPoint Current;
            public readonly IndicatorBase<IndicatorDataPoint> NegativeDirectionalIndex;
            public readonly IndicatorBase<IndicatorDataPoint> PositiveDirectionalIndex;

            public AverageDirectionalIndexState(AverageDirectionalIndex adx)
            {
                Name = adx.Name;
                Current = adx.Current;
                NegativeDirectionalIndex = adx.NegativeDirectionalIndex;
                PositiveDirectionalIndex = adx.PositiveDirectionalIndex;       
            }

            public override string ToString()
            {
                return Name + ":" + Current;
            }
        }

        public class RelativeStrengthIndexState
        {
            public readonly string Name;
            public readonly IndicatorDataPoint Current;

            public RelativeStrengthIndexState(RelativeStrengthIndex rsi)
            {
                Name = rsi.Name;
                Current = rsi.Current;
            }

            public override string ToString()
            {
                return Name + ":" + Current;
            }
        }

        public class SimpleMovingAverageState
        {
            public readonly string Name;
            public readonly IndicatorDataPoint Current;

            public SimpleMovingAverageState(SimpleMovingAverage sma)
            {
                Name = sma.Name;
                Current = sma.Current;
            }

            public override string ToString()
            {
                return Name + ":" + Current;
            }
        }
    }
}