Overall Statistics
using System.Collections.Concurrent;

namespace QuantConnect 
{   
    
    public class FractalDimmension : QCAlgorithm
    {
        
        string tradeSymbol = "SPY";
        
        //Data Required 
        List<string> _symbols = new List<string>() { "SPY" };
        TradeBars _bars = new TradeBars();
        
        //global vars
        Minimum _min;
        Maximum _max;
        Sum _sum;
        SimpleMovingAverage _sma;
        StandardDeviation _sd;
        decimal _fractalDimmension;
        decimal _chaosIndex;
        
        BollingerBands _bb;
        DateTime lastTradeTime;
        decimal _delta;
        
        //Initialize the data and resolution you require for your strategy:
        public override void Initialize()
        {
            //Start and End Date range for the backtest:
            SetStartDate(2010, 1, 1);
            SetEndDate(DateTime.Now.AddDays(-1));
            
            //Cash allocation
            SetCash(100000);
            
            //Add as many securities as you like. All the data will be passed into the event handler:
            foreach (var symbol in _symbols) {
                AddSecurity(SecurityType.Equity, symbol, Resolution.Daily);
                //Securities[symbol].TransactionModel = new CustomTransactionModel();
                Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.Raw);
            }
            //_symbols.AddRange(_forexSymbols);
            
            //updated inside OnData
            _bb = new BollingerBands(100, 1);
            _sd = new StandardDeviation(30);
            _sum = new Sum(10);
            _sma = new SimpleMovingAverage(30);
            _min = MIN(tradeSymbol, 10, Resolution.Daily);
            _max = MAX(tradeSymbol, 10, Resolution.Daily);
        }

        //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
        public void OnData(TradeBars data) 
        {   
            UpdateBars(data);
            if (_bars.Count != _symbols.Count) return;
            //foreach(var symbol in _symbols)
            //{
            //if (_consolidator.Update(_bars[tradeSymbol]))
            //{
                try
                {
                    
                    _delta = _max - _min;
                    
                    //updating custom indies
                    TradeBar bar;
                    if (_bars.TryGetValue(tradeSymbol, out bar))
                    {
                        _bb.Update(bar.Time, _delta);
                        _sum.Update(bar.Time, _bars[tradeSymbol].High-_bars[tradeSymbol].Low);
                    }
                    
                    if(_delta != 0)
                    {
                        _fractalDimmension = _sum / _delta;
                    }
                    
                    if (_bars.TryGetValue(tradeSymbol, out bar))
                    {
                        _sma.Update(bar.Time, _fractalDimmension);
                        _sd.Update(bar.Time, _fractalDimmension);
                    }
                    
                    if(_sd != 0)
                    {
                        _chaosIndex = (_fractalDimmension - _sma)/_sd;
                    }
                    
                    //indies
                    Plot("Indicators", "FractalDimmension", _fractalDimmension);
                    
                    //exit
                    //if((data[tradeSymbol].Time-lastTradeTime).TotalDays > 5)
                    if(Portfolio[tradeSymbol].IsLong && _fractalDimmension > _sma)
                    {
                        Liquidate(tradeSymbol);
                        //Log("Liquidated at "+_bars[tradeSymbol].Time);
                    } else
                    if(Portfolio[tradeSymbol].IsShort && _chaosIndex > 0)
                    {
                        Liquidate(tradeSymbol);
                        //Log("Liquidated at "+_bars[tradeSymbol].Time);
                    }
                    
                    //entries
                    /*if(!Portfolio[tradeSymbol].Invested && _chaosIndex < -1)
                    {
                        SetHoldings(tradeSymbol, -0.85);
                        if (LiveMode)
                        {
                            //Notify.Email("info@supernovacapital.com", "QC Bought", "Bought: "+Time.ToString("u"));
                        }
                        lastTradeTime = data[tradeSymbol].Time;
                        //Log("Bought at "+_bars[tradeSymbol].Time+" index time "+_indTime);
                    } else*/
                    if(!Portfolio[tradeSymbol].Invested && _fractalDimmension < _sma)
                    {
                        SetHoldings(tradeSymbol, 0.85);
                        lastTradeTime = data[tradeSymbol].Time;
                    }
                    
                    
                }
                catch(Exception err)
                {
                    Log("ERROR. "+err.Message);
                }
            
                
            //}//end of consolidator check
            
                
            //} // end of foreach
            
            
        } // end of ondata
        
        //Update the global "_bars" object
        private void UpdateBars(TradeBars data) 
        {
            foreach (var bar in data.Values)
            {
                if (!_bars.ContainsKey(bar.Symbol))
                {
                    _bars.Add(bar.Symbol, bar);
                }
                _bars[bar.Symbol] = bar;
            }
        }
            
    } // end of algo
    
} //end of namesace