Overall Statistics
Total Trades
128
Average Win
2.05%
Average Loss
-1.36%
Compounding Annual Return
5.003%
Drawdown
25.400%
Expectancy
0.351
Net Profit
74.384%
Sharpe Ratio
0.417
Loss Rate
46%
Win Rate
54%
Profit-Loss Ratio
1.51
Alpha
0.024
Beta
0.365
Annual Standard Deviation
0.141
Annual Variance
0.02
Information Ratio
-0.214
Tracking Error
0.174
Treynor Ratio
0.161
Total Fees
$475.60
using System;
using System.Collections;
using System.Collections.Generic;
using QuantConnect.Securities;
using QuantConnect.Models;

namespace QuantConnect 
{
    
    /*
    *   TimeSpanConsolidator Helper Routine: Assemble generic timespan bar lengths: e.g. 10 minutes:
    *
    *   1. Setup the new Consolidator class with the timespan period:
    *   var _consolidator = new Consolidator(TimeSpan.FromMinutes(10));
    *
    *   2. Add in the data with the update routine. It will return true when bar ready
    *   if (_consolidator.Update(data["MSFT"])) {   UseBar    }
    */
    public class Consolidator 
    {
        private TradeBar _resultBar;
        private TradeBar _workingBar;
        private DateTime _start;
        private TimeSpan _period;
        
        //Result:
        public TradeBar Bar
        {
            get
            {
                return _resultBar;
            }
        }
        
        //Constructor: Set the period we'd like to scan
        public Consolidator(TimeSpan span) 
        {
            this._period = span;
            this._resultBar = new TradeBar();
            this._workingBar = new TradeBar(new DateTime(), "", Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0);
        }
        
        //Submit this bar, return true if we've started a new one.
        public bool Update(TradeBar newBar)
        {
            //Intialize:
            if (_start == new DateTime()) 
            {
                _start = newBar.Time;
            }
            
            //While we're less than end date, keep adding to this bar:
            if (newBar.Time < (_start + _period))
            {
                //Building bar:
                AddToBar(newBar);
                return false;
            } 
            else 
            {
                //Completed bar: start new one:
                _resultBar = _workingBar;
                //Create a new bar:
                _workingBar = new TradeBar(newBar.Time, newBar.Symbol, Decimal.Zero, Decimal.MinValue, Decimal.MaxValue, 0, 0);
                //Start of this bar:
                _start = newBar.Time;
                AddToBar(newBar);
                return true;
            }
        }
        
        //Add to a tradebar
        private void AddToBar(TradeBar newBar)
        {
            //Add this data to working bar:
            if (_workingBar.Time == new DateTime()) _workingBar.Time = newBar.Time;
            if (_workingBar.Symbol == "") _workingBar.Symbol = newBar.Symbol;
            if (_workingBar.Open == Decimal.Zero) _workingBar.Open = newBar.Open;
            if (newBar.High > _workingBar.High) _workingBar.High = newBar.High;
            if (newBar.Low < _workingBar.Low) _workingBar.Low = newBar.Low;
            _workingBar.Close = newBar.Close;
            _workingBar.Volume = newBar.Volume;
        }
    }

}                        
namespace QuantConnect 
{   
    public class DivergenceIndex : QCAlgorithm
    {
        //primary instrument to trade
        string symbol = "SPY";
        
        StandardDeviation _sd;
        SimpleMovingAverage _smaNorm;
        SimpleMovingAverage _slowing;
        StandardDeviation _sdNorm;
        RollingWindow<TradeBar> _window = new RollingWindow<TradeBar>(40);
        
        DateTime lastTradeTime;
        decimal _delta;
        decimal _deltaFast;
        decimal _deltaSlow;
        decimal _divIndex;
        decimal _divIndNorm;
        decimal _prevDiv;
        
        //conso0lidating shit
        private TimeSpan _barPeriod = TimeSpan.FromHours(1);
        private Consolidator _consolidator;
        
        //Initialize the data and resolution you require for your strategy:
        public override void Initialize()
        {
            //Start and End Date range for the backtest:
            SetStartDate(2004, 1, 3);
            SetEndDate(DateTime.Now.AddDays(-1));
            
            //Cash allocation
            SetCash(25000);
            
            AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
            //Securities[symbol].TransactionModel = new CustomTransactionModel();
            
            //Setup Consolidator bar
            _consolidator = new Consolidator(_barPeriod);
            
            //Custom Data Indicator:
            //updated inside OnData
            _sd = new StandardDeviation(40);
            _sdNorm = new StandardDeviation(30);
            _smaNorm = new SimpleMovingAverage(30);
            _slowing = new SimpleMovingAverage(20);
            
        }

        //---------------------------------------------------------------------------------------------- ONDATA
        public void OnData(TradeBars data)
        {
            if (_consolidator.Update(data[symbol]))
            {
                try
                {
                    
                    _window.Add(data[symbol]);
                    if (!_window.IsReady) return;
                    
                    _delta =  _window[0].Close-_window[1].Close;
                    _deltaFast = _window[0].Close-_window[9].Close;
                    _deltaSlow = _window[0].Close-_window[39].Close;
                    
                    //updating custom indies
                    TradeBar bar;
                    if (data.TryGetValue(symbol, out bar))
                    {
                        _sd.Update(bar.Time, _delta);
                    }
                    
                    if(_sd != 0)
                    {
                        _divIndex = (_deltaFast*_deltaSlow)/(_sd*_sd);
                    }
                    
                    if (data.TryGetValue(symbol, out bar))
                    {
                        _sdNorm.Update(bar.Time, _divIndex);
                        _smaNorm.Update(bar.Time, _divIndex);
                        _slowing.Update(bar.Time, _divIndex);
                    }
                    
                    if(_sdNorm != 0)
                    {
                        _divIndNorm = (_divIndex - _smaNorm)/_sdNorm;
                    }
                    
                    // watchdog plots
                    Plot("Divergence Index", "Ratio", _divIndex);
                    Plot("Divergence Index", "Slowing", _slowing);
                    Plot("Divergence Index Norm", "Ratio", _divIndNorm);
                    
                    //exits
                    if(Portfolio.HoldStock)
                    {
                        if(Portfolio[symbol].IsLong && _slowing < 0)
                        {
                            Liquidate(symbol);
                        }/* else
                        if(Portfolio[symbol].IsShort && _slowing > 0)
                        {
                            Liquidate(symbol);
                        }*/
                    }
                    
                    //entries
                    if(!Portfolio.HoldStock && _divIndex < -20)
                    {
                        SetHoldings(symbol, 0.8);
                        lastTradeTime = data[symbol].Time;
                    }/* else
                    if(!Portfolio.HoldStock && _divIndex > 20)
                    {
                        SetHoldings(symbol, -0.8);
                        lastTradeTime = data[symbol].Time;
                    }*/
                    
                    //prevstuff
                    _prevDiv = _divIndNorm;
                
                    
                
                } catch(Exception err)
                {
                    Debug(err.Message);
                }
                
        
                
            }// end of consolidator
        
        } // end of trabers ond
        
    }// end of algo
    
    
}//end of namespace