Overall Statistics
Total Trades
38
Average Win
2.77%
Average Loss
-3.36%
Compounding Annual Return
-7.663%
Drawdown
32.100%
Expectancy
-0.232
Net Profit
-27.848%
Sharpe Ratio
-0.552
Loss Rate
58%
Win Rate
42%
Profit-Loss Ratio
0.83
Alpha
-0.105
Beta
0.197
Annual Standard Deviation
0.129
Annual Variance
0.017
Information Ratio
-1.376
Tracking Error
0.176
Treynor Ratio
-0.362
using System;
using System.Collections;
using System.Collections.Generic;
using QuantConnect.Securities;
using QuantConnect.Models;

namespace QuantConnect 
{
    
    public class TrailingStop 
    {
        TradeBar mBar = new TradeBar();
        decimal mTrailingStopDollars = 0.0m;
        decimal mBuyPrice = 0.0m;
        decimal mStop = 0.0m;
        bool mWentInFavour = false;
        bool mIsLong = true;
        
        public TrailingStop(TradeBar iBar, bool iIsLong = true, decimal ADR = 0, decimal iInitialADRStopRatio = 0.1m, decimal iTrailingStopDollars = 0.10m) 
        {
            mIsLong = iIsLong;
            mBar = iBar;
            mTrailingStopDollars = iTrailingStopDollars;
            mBuyPrice = iBar.Close;
            mWentInFavour = false;
            if (mIsLong)
            {
                mStop = iBar.Low - iInitialADRStopRatio * ADR;
            }
            else
            {
                mStop = iBar.High + iInitialADRStopRatio * ADR;
            }
        }
        
        public decimal Stop {
			get{ return mStop;}
		}
		
		public bool StopSignal ()
		{
			bool wReturn;
			if(mIsLong)
			{
			    wReturn = mBar.Low <= mStop;
			}
			else
			{
			    wReturn = mBar.High >= mStop;
			}
			return wReturn;
		}
        
        public bool Update(TradeBar iNewBar)
        {
            bool wReturn = false;
            if (mIsLong)
            {
                mWentInFavour = mWentInFavour || iNewBar.Close > mBuyPrice;
                if (mWentInFavour && (iNewBar.Low - mTrailingStopDollars) > mStop)
                {
                    mStop = System.Math.Min(iNewBar.Low, mBar.Low) - mTrailingStopDollars;
                }
                wReturn = iNewBar.Low <= mStop;
            }
            else
            {
                mWentInFavour = mWentInFavour || iNewBar.Close < mBuyPrice;
                if (mWentInFavour && (iNewBar.High + mTrailingStopDollars) < mStop)
                {
                    mStop = System.Math.Max(iNewBar.High, mBar.High) + mTrailingStopDollars;
                }
                wReturn = iNewBar.High >= mStop;
            }
            mBar = iNewBar;
            
            return wReturn;
        }
        
        public void Renew(TradeBar iBar, bool iIsLong = true, decimal ADR = 0, decimal iInitialADRStopRatio = 0.1m, decimal iTrailingStopDollars = 0.10m) 
        {
            mIsLong = iIsLong;
            mBar = iBar;
            mTrailingStopDollars = iTrailingStopDollars;
            mBuyPrice = iBar.Close;
            mWentInFavour = false;
            mStop = iBar.Low - iInitialADRStopRatio * ADR;
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic; 
using QuantConnect.Securities;  
using QuantConnect.Models;

/*
See:
http://www.tradingmarkets.com/recent/a_simple_day_trading_strategy-641402.html


TODO:
- Try implementing trailing stops
- Implement other stop criterias given in the site above
- Use more stocks.
*/

namespace QuantConnect 
{   
    // Name your algorithm class anything, as long as it inherits QCAlgorithm
    public class ShortSPXUAlgorithm : QCAlgorithm
    {
        //----------------------------------------------------
        // Parameters
        //----------------------------------------------------
        static int cIntervalMinutes = 390;
        static int cExitHour = 20;
        static int cEnterHour = 0;
        static int cSellAfterNPeriods = 5;
        static bool cLiquidateAtEndOfDay = false;
        static string cSymbol = "ERX";
        static bool mAllowLonging = true;
        static bool mAllowShorting = true;
        static bool mValidateWithDailySignal = true;
        //----------------------------------------------------
        
        bool mFirstPass = true;
        Consolidator TimeFrameBar = new Consolidator(TimeSpan.FromMinutes(cIntervalMinutes)); // Custom time frame bar
        bool mIsLong = false;
        bool mIsShort = false;
        TradeBar mPreviousData = new TradeBar();
        TradeBar mDailyBar = new TradeBar();
        TrailingStop mTrailingStop;
        int mPeriodsElapsedSinceEntry = 0;
        
        //----------------------------------------------------
        // Indicators
        //----------------------------------------------------
        TradeBar                            mHeikenAshiBar              = new TradeBar(); // Heiken-Ashi bar
        MovingAverageConvergenceDivergence  MACD                        = new MovingAverageConvergenceDivergence(12,26,9); // MACD Group
        BollingerBands                      BB                          = new BollingerBands(12,1.8m); // Bollinger bands
        SimpleMovingAverage                 ADR                         = new SimpleMovingAverage(7); // Average daily range
        TradeBar                            mHeikenAshiBar_Daily        = new TradeBar(); // Heiken-Ashi bar
        MovingAverageConvergenceDivergence  MACD_Daily                  = new MovingAverageConvergenceDivergence(12,26,9); // MACD Group
        //decimal                             mYesterdaysMACDDivergence   = 0;
        BollingerBands                      BB_Daily                    = new BollingerBands(12,1.8m); // Bollinger bands
        ConnorsRSI                          CRSI                        = new ConnorsRSI(3,2,100);
        RelativeStrengthIndex               RSI2                        = new RelativeStrengthIndex(2, 1, true);
        SimpleMovingAverage                 SMA200                      = new SimpleMovingAverage(200);
        SimpleMovingAverage                 SMA5                        = new SimpleMovingAverage(5);
        AverageDirectionalIndex             ADX                         = new AverageDirectionalIndex(14);
        //----------------------------------------------------
        
        //Initialize the data and resolution you require for your strategy:
        public override void Initialize()
        {
            SetStartDate(2010, 10, 1);   
            //SetEndDate(2014, 10, 28); 
            SetEndDate(DateTime.Now.Date.AddDays(-1)); 
            SetCash(30000);
            AddSecurity(SecurityType.Equity, cSymbol, Resolution.Minute);
        }

        //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) 
        {   
            if ((mIsLong && (LongExitSignal(data[cSymbol]) || ShortEntrySignal(data[cSymbol])) ||
                (mIsShort&& (ShortExitSignal(data[cSymbol]) || LongEntrySignal(data[cSymbol])))))
            {
                Order(cSymbol, -Securities[cSymbol].Holdings.Quantity);
                mIsLong = false;
                mIsShort = false;
            }
            
            if (mDailyBar.Open == 0) mDailyBar.Open = data[cSymbol].Open;
            mDailyBar.High = Math.Max(mDailyBar.High, data[cSymbol].High);
            mDailyBar.Low = Math.Min(mDailyBar.Low, data[cSymbol].Low);
                    
            if (TimeFrameBar.Update(data[cSymbol])) 
            {
                UpdateIndicators(TimeFrameBar.Bar);                
                
                if (data[cSymbol].Time.TimeOfDay.Hours >= cEnterHour && data[cSymbol].Time.TimeOfDay.Hours < cExitHour)
                {
                    if (!mIsLong && !mIsShort && mAllowLonging && LongEntrySignal(TimeFrameBar.Bar))
                    {
                        mIsLong = true;
                        mIsShort = false;
                        Order(cSymbol, (int)Math.Floor(Portfolio.Cash / data[cSymbol].Close) );
                        mTrailingStop = new TrailingStop(TimeFrameBar.Bar, true, ADR.SMA, 0.1m, 0.10m);
                        mPeriodsElapsedSinceEntry = 0;
                    }
                    else if (!mIsLong && !mIsShort && mAllowShorting && ShortEntrySignal(TimeFrameBar.Bar))
                    {
                        mIsLong = false;
                        mIsShort = true;
                        Order(cSymbol, -(int)Math.Floor(Portfolio.Cash / data[cSymbol].Close) );
                        mTrailingStop = new TrailingStop(TimeFrameBar.Bar, false, ADR.SMA, 0.1m, 0.10m);
                        mPeriodsElapsedSinceEntry = 0;
                    }
                }
            }
            
            // End the day
            if (!mFirstPass && mPreviousData.Time.Date < data[cSymbol].Time.Date)
            {
                // Process end of day
                mDailyBar.Close = mPreviousData.Close;
                UpdateDailyIndicators(mDailyBar);
                mDailyBar.Open = 0;
                mDailyBar.High = Decimal.MinValue;
                mDailyBar.Low = Decimal.MaxValue;
                mDailyBar.Close = 0;
            }
            if (!mFirstPass && (data[cSymbol].Time.TimeOfDay.Hours >= cExitHour || mPreviousData.Time.Date < data[cSymbol].Time.Date))
            {
                // Process end of day
                myEndOfDay();
            }
            mPreviousData = data[cSymbol];
            mFirstPass = false;
        }
        
        private void myEndOfDay()
        {
            if (cLiquidateAtEndOfDay)
            {
                // Liquidate all at end of day
                Order(cSymbol, -Securities[cSymbol].Holdings.Quantity);
                mIsLong = false;
                mIsShort = false;
            }
        }
        
        private void UpdateIndicators(TradeBar Bar)
        {
            getHeikenAshi(Bar, ref mHeikenAshiBar);
            MACD.AddSample(Bar.Close);
            BB.AddSample(Bar.Close);
            CRSI.AddSample(Bar);
            RSI2.AddSample(Bar);
            SMA200.AddSample(Bar.Close);
            SMA5.AddSample(Bar.Close);
            ADX.AddSample(Bar);
            ++mPeriodsElapsedSinceEntry;
            if (mIsLong || mIsShort) mTrailingStop.Update(Bar);
        }
        
        private void UpdateDailyIndicators(TradeBar Bar)
        {
            //mYesterdaysMACDDivergence = MACD_Daily.Divergence;
            MACD_Daily.AddSample(Bar.Close);
            BB_Daily.AddSample(Bar.Close);
            getHeikenAshi(Bar, ref mHeikenAshiBar_Daily);
            ADR.AddSample(mDailyBar.High-mDailyBar.Low);
        }
        
        private bool LongEntrySignal(TradeBar Bar)
        {
            bool wSignal = true;
            wSignal &= BB.Ready;
            wSignal &= MACD.Ready;
            wSignal &= ADR.Ready;
            wSignal &= CRSI.Ready;
            wSignal &= SMA200.Ready;
            wSignal &= SMA5.Ready;
            wSignal &= ADX.Ready;
            wSignal &= Bar.Close > SMA200.SMA;
            wSignal &= Bar.Close < SMA5.SMA;
            wSignal &= CRSI.CRSI <= 5;
            //wSignal &= ADX.ADX > 30;
            //wSignal &= RSI2.RSI <= 5;
            
            bool wDailySignal = true;
            
            if (mValidateWithDailySignal) wSignal &= wDailySignal;

            return wSignal;
        }
        
        private bool LongExitSignal(TradeBar Bar)
        {
            bool wSignal = true;
            wSignal &= (mTrailingStop.StopSignal() || (mPeriodsElapsedSinceEntry >= cSellAfterNPeriods));
            //wSignal &= (mPeriodsElapsedSinceEntry >= cSellAfterNPeriods);
            
            return wSignal;
        }
        
        private bool ShortEntrySignal(TradeBar Bar)
        {
            bool wSignal = true;
            wSignal &= BB.Ready;
            wSignal &= MACD.Ready;
            wSignal &= ADR.Ready;
            wSignal &= CRSI.Ready;
            wSignal &= SMA200.Ready;
            wSignal &= SMA5.Ready;
            wSignal &= ADX.Ready;
            wSignal &= Bar.Close < SMA200.SMA;
            wSignal &= Bar.Close > SMA5.SMA;
            wSignal &= CRSI.CRSI >= 95;
            //wSignal &= ADX.ADX > 30;
            //wSignal &= RSI2.RSI >= 95;
            
            bool wDailySignal = true;

            if (mValidateWithDailySignal) wSignal &= wDailySignal;

            return wSignal;
        }
        
        private bool ShortExitSignal(TradeBar Bar)
        {
            bool wSignal = true;
            wSignal &= (mTrailingStop.StopSignal() || (mPeriodsElapsedSinceEntry >= cSellAfterNPeriods));
            //wSignal &= (mPeriodsElapsedSinceEntry >= cSellAfterNPeriods);
            
            return wSignal;
        }
        
        private bool isHammer(TradeBar Bar, decimal MaxUpperTailRatio = 0.1m)
        {
            decimal wRange = Bar.High - Bar.Low;
            decimal wMaxUpperTail = MaxUpperTailRatio * wRange;
            decimal wUpperTail = Bar.High - System.Math.Max(Bar.Open, Bar.Close);
            
            return wUpperTail <= wMaxUpperTail;
        }
        
        private bool isFallingStar(TradeBar Bar, decimal MaxLowerTailRatio = 0.1m)
        {
            decimal wRange = Bar.High - Bar.Low;
            decimal wMaxLowerTail = MaxLowerTailRatio * wRange;
            decimal wLowerTail = System.Math.Min(Bar.Open, Bar.Close) - Bar.Low;
            
            return wLowerTail <= wMaxLowerTail;
        }
        
        private bool isDoji(TradeBar Bar, decimal MaxBodyRatio = 0.5m)
        {
            if (isHammer(Bar) || isFallingStar(Bar))
            {
                return false;
            }
            else
            {
                decimal wRange = Bar.High - Bar.Low;
                decimal wMaxBody = MaxBodyRatio * wRange;
                decimal wBody = Math.Abs(Bar.Open - Bar.Close);
                
                return (wBody <= wMaxBody);
            }
        }
        
        private void getHeikenAshi(TradeBar RegularBar, ref TradeBar HeikenAshiBar)
        {
            HeikenAshiBar.Time  = RegularBar.Time;
			HeikenAshiBar.Open  = (HeikenAshiBar.Open + HeikenAshiBar.Close) / 2;
			HeikenAshiBar.Close = (RegularBar.Open + RegularBar.High + RegularBar.Low + RegularBar.Close) / 4;
			HeikenAshiBar.High  = System.Math.Max(RegularBar.High, System.Math.Max(HeikenAshiBar.Open, HeikenAshiBar.Close));
			HeikenAshiBar.Low   = System.Math.Min(RegularBar.Low,  System.Math.Min(HeikenAshiBar.Open, HeikenAshiBar.Close));
        }
    }
}
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;
        }
    }

}
using System;
using System.Collections;
using System.Collections.Generic;
using QuantConnect.Securities;
using QuantConnect.Models;

namespace QuantConnect {
    /*
    *   MACD Indicator - Moving Average Convergence Divergence 
    *   Typically called like: macd(12,26,9);
    *   Where   12 days = Fast EMA
    *           26 days = Slow EMA
    *           9  days = EMA of the difference (fastEMA - slowEMA).
    *
    *   Use in your code by calling:
    *
    *   MovingAverageConvergenceDivergence macd = MovingAverageConvergenceDivergence(12,26,9);
    *   
    *   macd.AddSample(price);
    *
    *   if (macd.Ready) { .... macd.MACD_Signal .....}
    */
    public class MovingAverageConvergenceDivergence {
        
        /*
        *   Initialize the MACD with X Period.
        */
        public MovingAverageConvergenceDivergence(int fastEMA, int slowEMA, int signalEMA) {
            this._slowPeriod = slowEMA;
            this._fastPeriod = fastEMA;
            this._signalPeriod = signalEMA;
            this._minimumSamplesBeforeReady = 4 * slowEMA;
        }
        
        /*
        *   Signal of MACD: x-EMA of MACD
        */
        public decimal MACD_Signal { 
            get {
                return _signalEMA;
            }
        }
        
        /*
        *   RAW MACD Values: emaFast - emaSlow.
        */
        public decimal MACD {
            get {
                return _fastEMA-_slowEMA;
            }
        }
        
        
        /*
        *   Divergence = MACD - Signal
        */
        public decimal Divergence { 
            get {
                return MACD - MACD_Signal;
            }
        }
        
        
        /*
        *   Flag to tell user if indicator read for usage.
        */
        public bool Ready {
            get {
                return (_samples >= _minimumSamplesBeforeReady);
            }
        }
        
        
        //Private working variables:
        private decimal _slowPeriod = 0, _fastPeriod = 0, _signalPeriod = 0;
        private decimal _slowEMA = 0, _fastEMA = 0, _signalEMA = 0;
        private long _minimumSamplesBeforeReady = 0, _samples = 0;
        
        /*
        *   Add a Price to the MACD and recalculate its values:
        */
        public void AddSample(decimal price) {
            
            //Wait till we're ready before using this indicator:
            if (_samples < _minimumSamplesBeforeReady)
                _samples++;
            
            //Calculate the updated EMA's
            if (_samples == 1) {
                   _slowEMA = price;
                   _fastEMA = price;
                   _signalEMA = 0;
            } else {
                //Now apply forumla to update all of them:
                _slowEMA = UpdateEMA(price, _slowPeriod, _slowEMA);
                _fastEMA = UpdateEMA(price, _fastPeriod, _fastEMA);
                _signalEMA = UpdateEMA(MACD, _signalPeriod, _signalEMA);
            }
        }
        
        /*
        *   Calculate and return the new EMA value:
        */
        private decimal UpdateEMA(decimal sample, decimal period, decimal previousValue) {
            decimal factor = (2m / (period + 1m));
            return factor * sample + (1-factor) * previousValue;
        }
        
        
        /*
        *   Wrapper for the decimal function to accept tradebars.
        */
        public void AddSample(TradeBar bar) {
            AddSample(bar.Close);
        }
        
    }
}
using System;
using System.Collections;
using System.Collections.Generic; 
using System.Collections.Concurrent;
using System.Text;
using System.Linq;
using QuantConnect.Models;

namespace QuantConnect {
    
    /*
    *   SMA Indicator: Online calculator for faster backtesting.
    *
    *   To use this indicator: 
    *   1. Create an instance of it in your algorithm:
    *   SMA sma10 = new SMA(10);
    *   
    *   2. Push in data with AddSample:
    *   decimal sma = sma10.AddSample(data["spy"].Close);
    *
    *   3. If you're sensitive to the precise SMA values you push wait until the indicator is Ready.
    */
    
    public class SimpleMovingAverage 
    {
        //Class Variables:
        private int period, samples;
		private decimal sma, sum, divisor;
		private FixedSizedQueue<decimal> sampleQueue;
		
		// Initialise the Simple Moving Average
        public SimpleMovingAverage(int period) {
            this.period = period;
            this.samples = 0;
            this.sampleQueue = new FixedSizedQueue<decimal>(period);
        }
		
		//Public Result Access: Current value of the SMA.
		public decimal SMA {
			get{ return sma;}
		}
		
		//Public Result Access: Track the number of samples:
		public int Samples {
		    get { return samples; }
		}
		
		//Public Result Access: We've got sufficient data samples to know its the SMA.
		public bool Ready {
		    get { return samples >= period; }
		}
		
		// Online implementation of simple moving average 
        public decimal AddSample(decimal quote)
        {
            samples++;
            sum += quote;
		  
            //Add this sample to the SMA, subtract the previous
            sampleQueue.Enqueue(quote);
            if (sampleQueue.Size == period) {
                //"last" is a dequeued item: minus it from the SMA.
                sum -= sampleQueue.LastDequeued;
            }
            
            //When less than period samples, only divide by the number of samples.
            if (samples < period) {
                divisor = samples;
            } else {
                divisor = period;
            }
            
            sma = sum / divisor;
            
		    return sma;
        }
        
        
        //Fixed length queue that dumps things off when no more space in queue.
        private class FixedSizedQueue<T> : ConcurrentQueue<T> {
            public int Size { get; private set; }
            public T LastDequeued { get; private set; }
            public FixedSizedQueue(int size) { Size = size; }
            public new void Enqueue(T obj) {
                base.Enqueue(obj);
                lock (this) {
                    if (base.Count > Size) {
                        T outObj;
                        base.TryDequeue(out outObj);
                        LastDequeued = outObj;
                    }
                }
            }
        }
        
    }
}
using System;
using System.Collections;
using System.Collections.Generic; 
using System.Collections.Concurrent;
using System.Text;
using System.Linq;
using QuantConnect.Models;

namespace QuantConnect {
    
    /*
    *   Bollinger Bands Indicator: Online calculator for faster backtesting.
    *
    *   To use this indicator: 
    *   1. Create an instance of it in your algorithm:
    *   BollingerBands BB = new BollingerBands(20,2);
    *   
    *   2. Push in data with AddSample:
    *   BB.AddSample(data["spy"].Close);
    *
    *   3. If you're sensitive to the precise Bollinger bands values you push, wait until the indicator is Ready.
    */
    
    public class BollingerBands 
    {
        //Class Variables:
        private int samples;
		private decimal Upper, Lower, Bandwidth, NumStdDevs;
		private StandardDeviation sd;
		
		// Initialise the Bollinger Bands
        public BollingerBands(int period = 20, decimal NumStdDevs = 2) {
            this.NumStdDevs = NumStdDevs;
            this.samples = 0;
            this.sd = new StandardDeviation(period);
        }
		
		//Public Result Access: Current value of the upper Bollinger band.
		public decimal UPPER {
			get{ return Upper;}
		}
		
		//Public Result Access: Current value of the lower Bollinger band.
		public decimal LOWER {
			get{ return Lower;}
		}
		
		//Public Result Access: Current value of the Bollinger bandwidth.
		public decimal BANDWIDTH {
			get{ return Bandwidth;}
		}
		
		//Public Result Access: Track the number of samples:
		public int Samples {
		    get { return samples; }
		}
		
		//Public Result Access: We've got sufficient data samples to get right values.
		public bool Ready {
		    get { return sd.Ready; }
		}
		
		// Online implementation of simple moving average 
        public void AddSample(decimal quote)
        {
            sd.AddSample(quote);
            Lower = sd.SMA - sd.SD*NumStdDevs;
            Upper = sd.SMA + sd.SD*NumStdDevs;
            Bandwidth = Upper - Lower;
            samples++;
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic; 
using System.Collections.Concurrent;
using System.Text;
using System.Linq;
using QuantConnect.Models;

namespace QuantConnect {
    
    /*
    *   Standard Deviation Indicator
    *
    *   To use this indicator: 
    *   1. Create an instance of it in your algorithm:
    *   StandardDeviation sd10 = new StandardDeviation(10);
    *   
    *   2. Push in data with AddSample:
    *   decimal sd = sd10.AddSample(data["spy"].Close);
    *
    *   3. If you're sensitive to the precise sd values you push wait until the indicator is Ready.
    */
    
    public class StandardDeviation 
    {
        //Class Variables:
        private int period, samples;
        private decimal sd;
		private double sum, divisor;
		private SimpleMovingAverage sma;
		private FixedSizedQueue<double> sampleQueue;
		
		// Initialise the StandardDeviation
        public StandardDeviation(int period) {
            this.period = period;
            this.samples = 0;
            this.sampleQueue = new FixedSizedQueue<double>(period);
            this.sma = new SimpleMovingAverage(period);
        }
		
		//Public Result Access: Current value of the SD.
		public decimal SD {
			get{ return sd;}
		}
		
		//Public Result Access: Track the number of samples:
		public int Samples {
		    get { return samples; }
		}
		
		//Public Result Access: Current value of the SMA.
		public decimal SMA {
		    get { return sma.SMA; }
		}
		
		//Public Result Access: We've got sufficient data samples to get the correct value.
		// Note that the SMA needs to be ready before the SD accumulates correct values, so we wait 
		// another period after the SMA is ready, hence period*2.
		public bool Ready {
		    get { return samples >= period*2; }
		}
		
		// Online implementation of standard deviation
        public decimal AddSample(decimal quote)
        {
            samples++;
            sma.AddSample(quote);
            
            double DeviationFromMeanSquared = (double)((quote-sma.SMA)*(quote-sma.SMA));
            
            sum += DeviationFromMeanSquared;
		  
            //Add this sample to the SD, subtract the previous
            sampleQueue.Enqueue(DeviationFromMeanSquared);
            if (sampleQueue.Size == period) {
                //"last" is a dequeued item: subtract it from the SD.
                sum -= sampleQueue.LastDequeued;
            }
            
            //When less than period samples, only divide by the number of samples.
            if (samples < period) {
                divisor = samples;
            } else {
                divisor = period;
            }
            if (divisor>1) {
                sd = (decimal)Math.Sqrt(sum / (divisor-1));
            }
            
		    return sd;
        }
        
        
        //Fixed length queue that dumps things off when no more space in queue.
        private class FixedSizedQueue<T> : ConcurrentQueue<T> {
            public int Size { get; private set; }
            public T LastDequeued { get; private set; }
            public FixedSizedQueue(int size) { Size = size; }
            public new void Enqueue(T obj) {
                base.Enqueue(obj);
                lock (this) {
                    if (base.Count > Size) {
                        T outObj;
                        base.TryDequeue(out outObj);
                        LastDequeued = outObj;
                    }
                }
            }
        }
        
    }
}
using System;
using System.Collections;
using System.Collections.Generic; 
using System.Collections.Concurrent;
using System.Text;
using System.Linq;
using QuantConnect.Models;

namespace QuantConnect {
    
    public class ConnorsRSI 
    {
        //Class Variables:
        private int samples = 0;
		private decimal mCRSI = 0;
		private RelativeStrengthIndex mRSI;
		private RelativeStrengthIndex mStreakRSI;
		private int mUpDownStreak = 0;
		private decimal mROC = 0;
		private int mROCPeriod = 0;
		private decimal mPreviousValue = 0;
		private FixedSizedQueue<decimal> mPriceChanges;
		
		// Initialise the Connors RSI
        public ConnorsRSI(int iRSIPeriod = 3, int iUpDownStreakRSIPeriod = 2, int iROCPeriod = 100) {
            this.mROCPeriod = iROCPeriod;
            this.mRSI = new RelativeStrengthIndex(iRSIPeriod);
            this.mStreakRSI = new RelativeStrengthIndex(iUpDownStreakRSIPeriod);
            mPriceChanges = new FixedSizedQueue<decimal>(mROCPeriod);
        }
		
		//Public Result Access: Current value of the Connors RSI.
		public decimal CRSI {
			get{ return mCRSI;}
		}
		
		//Public Result Access: Track the number of samples:
		public int Samples {
		    get { return samples; }
		}
		
		//Public Result Access: We've got sufficient data samples to get right values.
		public bool Ready {
		    get { return mRSI.Ready && mStreakRSI.Ready && samples >= mROCPeriod;}
		}
		
		// Online implementation of simple moving average 
        public void AddSample(TradeBar quote)
        {
            mRSI.AddSample(quote);
            
            if (mUpDownStreak <= 0 && quote.Close < mPreviousValue) --mUpDownStreak;
            if (mUpDownStreak > 0 && quote.Close < mPreviousValue) mUpDownStreak = -1;
            if (mUpDownStreak >= 0 && quote.Close > mPreviousValue) ++mUpDownStreak;
            if (mUpDownStreak < 0 && quote.Close > mPreviousValue) mUpDownStreak = 1;
            if (quote.Close == mPreviousValue) mUpDownStreak = 0;
            mStreakRSI.AddSample(mUpDownStreak);
            
            decimal wPercentChange = (quote.Close - quote.Open) / quote.Open;
            mPriceChanges.Enqueue(wPercentChange);
            
            mCRSI = (mRSI.RSI + mStreakRSI.RSI + GetROC(wPercentChange))/3;

            mPreviousValue = quote.Close;
            samples++;
        }
        
        private decimal GetROC(decimal wRefChange)
        {
            int wNumberOfLowerChange = 0;
            foreach (decimal i in mPriceChanges)
            {
                if (i < wRefChange) ++wNumberOfLowerChange;
            }
            
            mROC = (wNumberOfLowerChange / mPriceChanges.Count) * 100;
            return mROC;
        }
        
        //Fixed length queue that dumps things off when no more space in queue.
        private class FixedSizedQueue<T> : ConcurrentQueue<T> {
            public int Size { get; private set; }
            public T LastDequeued { get; private set; }
            public T LastEnqueued {get; private set;}
            public bool Dequeued { get; private set; }
            public FixedSizedQueue(int size) { Size = size; }
            public new bool Enqueue(T obj) {
                base.Enqueue(obj);
                LastEnqueued = obj;
                Dequeued = false;
                lock (this) {
                    if (base.Count > Size) {
                        T outObj;
                        Dequeued = base.TryDequeue(out outObj);
                        LastDequeued = outObj;
                    }
                }
                return Dequeued;
            }
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
using QuantConnect.Securities;
using QuantConnect.Models;

namespace QuantConnect {

    /*
    *   Relative Strength Index Indicator:
    *
    *                    100  
    *   RSI = 100 -  ------------
    *                   1 + RS
    *
    *   Where RS = Avg of X Period Close Up / Absolute(Avg) X of Period Close Down.
    *   
    */
    public class RelativeStrengthIndex
    {
        
        //Public Access to the RSI Output
        public decimal RSI {
            get {
                return (100 - (100 / (1 + _rs)));
            }
        }
        
        //Public Access to Know if RSI Indicator Ready
        public bool Ready {
            get {
                return (_upward.Count >= _period) && (_downward.Count >= _period);
            }
        }
        
        //Private Class Variables:
        private decimal _rs = 0;
        private bool _ema = false;
        private decimal _period = 14;
        private decimal _joinBars = 1;
        private Candle _superCandle = new Candle();
        private Candle _previousCandle = new Candle();
        private decimal _previousValue = 0;
        private FixedSizedQueue<decimal> _downward = new FixedSizedQueue<decimal>(0);
        private FixedSizedQueue<decimal> _upward = new FixedSizedQueue<decimal>(0);
        private decimal _upwardSum = 0, _avgUpward = 0;
        private decimal _downwardSum = 0, _avgDownward = 0;
        
        //Initialize the RSI with 'period' candles
        public RelativeStrengthIndex(int period, int joinBars = 1, bool useEMA = false) {
            
            //Range check variables:
            if (period < 2) period = 2;
            
            //Class settings:
            _period = (decimal)period;  // How many samples is the RSI?
            _ema = useEMA;              // Use the EMA average for RSI
            _joinBars = joinBars;       // Join multiple tradebars together
            
            //Remember the upward and downward movements in a FIFO queue:
            _upward = new FixedSizedQueue<decimal>(period);
            _downward = new FixedSizedQueue<decimal>(period);
            
            //Online implementation of SMA - needs moving sum of all components:
            _upwardSum = 0; _downwardSum = 0;
        }
        
        //Add a new sample to build the RSI Indicator:
        public void AddSample(TradeBar bar) { 
            
            //Build a multibar candle, until join reached return.
            _superCandle.Update(bar);
            if (_superCandle.Samples < _joinBars) return;
            
            //Initialize the first loop.
            if (_previousCandle.Samples == 0) {
                _previousCandle = _superCandle;
                _superCandle = new Candle();
                return;
            }
            
            //Get the difference between this bar and previous bar:
            decimal difference = _superCandle.Close - _previousCandle.Close;
            
            //Update the Moving Average Calculations:
            if (difference >= 0) {
                if (_ema) {
                    _avgUpward = UpdateDirectionalEMA(ref _upward, difference);
                    _avgDownward = UpdateDirectionalEMA(ref _downward, 0);
                } else {
                    _avgUpward = UpdateDirectionalSMA(ref _upward, ref _upwardSum, difference);
                    _avgDownward = UpdateDirectionalSMA(ref _downward, ref _downwardSum, 0);
                }
            }
            if (difference <= 0) {
                difference = Math.Abs(difference);
                if (_ema) {
                    _avgUpward = UpdateDirectionalEMA(ref _upward, 0);
                    _avgDownward = UpdateDirectionalEMA(ref _downward, difference);
                } else {
                    _avgUpward = UpdateDirectionalSMA(ref _upward, ref _upwardSum, 0);
                    _avgDownward = UpdateDirectionalSMA(ref _downward, ref _downwardSum, difference);
                }
            }
            
            //Refresh RS Factor:
            //RS Index Automatically Updated in the Public Property Above:
            if (_avgDownward != 0) {
                _rs = _avgUpward / _avgDownward;
            } else {
                _rs = Decimal.MaxValue - 1;
            }
            
            //Reset for next loop:
            _previousCandle = _superCandle;
            _superCandle = new Candle();
        }
        
        
        //Add a new sample to build the RSI Indicator:
        public void AddSample(decimal Value) { 
            
            //Get the difference between this bar and previous bar:
            decimal difference = Value - _previousValue;
            
            //Update the Moving Average Calculations:
            if (difference >= 0) {
                if (_ema) {
                    _avgUpward = UpdateDirectionalEMA(ref _upward, difference);
                    _avgDownward = UpdateDirectionalEMA(ref _downward, 0);
                } else {
                    _avgUpward = UpdateDirectionalSMA(ref _upward, ref _upwardSum, difference);
                    _avgDownward = UpdateDirectionalSMA(ref _downward, ref _downwardSum, 0);
                }
            }
            if (difference <= 0) {
                difference = Math.Abs(difference);
                if (_ema) {
                    _avgUpward = UpdateDirectionalEMA(ref _upward, 0);
                    _avgDownward = UpdateDirectionalEMA(ref _downward, difference);
                } else {
                    _avgUpward = UpdateDirectionalSMA(ref _upward, ref _upwardSum, 0);
                    _avgDownward = UpdateDirectionalSMA(ref _downward, ref _downwardSum, difference);
                }
            }
            
            //Refresh RS Factor:
            //RS Index Automatically Updated in the Public Property Above:
            if (_avgDownward != 0) {
                _rs = _avgUpward / _avgDownward;
            } else {
                _rs = Decimal.MaxValue - 1;
            }
            
            //Reset for next loop:
            _previousValue = Value;
        }
        
        
        // Update the moving average and fixed length queue in a generic fashion to work for up and downward movement.
        // Return the average.
        private decimal UpdateDirectionalSMA(ref FixedSizedQueue<decimal> queue, ref decimal sum, decimal sample) {
            
            //Increment Sum
            sum += sample;
            
            //If we've shuffled off queue, remove from sum:
            if(queue.Enqueue(sample)) {
                sum -= queue.LastDequeued;
            }
            
            //When less than period samples, only divide by the number of samples.
            if (queue.Count < _period) {
                return (sum / (decimal)queue.Count);
            } else {
                return (sum / _period);
            }
        } 
        
        
        // Update the moving average and fixed length queue in a generic fashion to work for up and downward movement.
        // Return the average.
        private decimal UpdateDirectionalEMA(ref FixedSizedQueue<decimal> queue, decimal sample) {
            queue.Enqueue(sample);
            if (queue.Count == 1) {
                return sample;
            } else {
                return (1m / _period) * sample  +  ((_period - 1m) / _period) * queue.LastEnqueued; 
            }
        }
        
        
        
        //Fixed length queue that dumps things off when no more space in queue.
        private class FixedSizedQueue<T> : ConcurrentQueue<T> {
            public int Size { get; private set; }
            public T LastDequeued { get; private set; }
            public T LastEnqueued {get; private set;}
            public bool Dequeued { get; private set; }
            public FixedSizedQueue(int size) { Size = size; }
            public new bool Enqueue(T obj) {
                base.Enqueue(obj);
                LastEnqueued = obj;
                Dequeued = false;
                lock (this) {
                    if (base.Count > Size) {
                        T outObj;
                        Dequeued = base.TryDequeue(out outObj);
                        LastDequeued = outObj;
                    }
                }
                return Dequeued;
            }
        }
        
        /// <summary>
        /// Simple online "super-tradebar" generator for making an OHLC from multiple bars.
        /// </summary>
        public class Candle {
            
            public decimal Open = 0;
            public decimal High = Decimal.MinValue;
            public decimal Low = Decimal.MaxValue;
            public decimal Close = 0;
            public int Samples = 0;
            
            public void Update(TradeBar bar) {
                if (Open == 0) Open = bar.Open;
                if (High < bar.High) High = bar.High;
                if (Low > bar.Low) Low = bar.Low;
                Close = bar.Close;
                Samples++;
            }
        }
        
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using QuantConnect.Securities;
using QuantConnect.Models;

namespace QuantConnect {

    /* ADX Indicator - Average Directional Index is a complicated but powerful indicator.
    *  
    *      1. Calculate the Directional Movements: +DM_t, -DM_t.
    *      2. Find the Average Directional Movement: ADM_t
    *      3. Calculate the Average True Range: ATR_t
    *      4. Calculate the Directional Indexes: DI+_t, DI-_t, 
    *         Directional Movement Index: DX_t,
    *         then Average Directional Movement Index! ADX_t
    *      
    *  Requires day to be divided into segments, periods and a running record kept of the previous value so the averages can be made.
    */
    public class AverageDirectionalIndex {
        
        //Public Result Access: Primary ADX Indicator
        public decimal ADX {
            get; private set;
        }
        
        //Public Result Access: DMI Positive:
        public decimal DMI_Pos {
            get; private set;
        }
        
        //Public Result Access: DMI Negative:
        public decimal DMI_Neg {
            get; private set;
        }
        
        //Public Result Access: Direction of the ADX Indicator:
        public decimal Decision {
            get; private set;
        }
        
        //Public Result Access: When indicator has sufficient data flags as true.
        public bool Ready {
            get; private set;
        }
        
        //Initialize
        private ADXCacheItem indicatorMemory = new ADXCacheItem();
        private decimal _expConst = 0;
        private int _samplePeriods = 0;
        private Candle _superCandle = new Candle();
        
        // Constructor: Set the sample period:
        public AverageDirectionalIndex(int samplePeriods) {
            _expConst = (2m / (decimal)(samplePeriods + 1));
            _samplePeriods = samplePeriods;
            Ready = false;
        }
        
    
        /// <summary>
        /// Calculate the ADX figure, return an indicator result.
        /// </summary>
        public decimal AddSample(TradeBar bar) {
            
            //0. Save these samples in running OHLC candle until requested samplePeriod reached:
            _superCandle.Update(bar);
            if (_superCandle.Samples < _samplePeriods) return Decision;
            
            //0. Define a result storage for this session.
            ADXCacheItem current = new ADXCacheItem();
            current.OHLC = _superCandle;
            
            //0. If this is the first candle skip it and come back for second: to calc directional index can't be relative to 0.
            if (!indicatorMemory.set) {
                current.set = true; 
                indicatorMemory = current;
                _superCandle = new Candle();
                return Decision;
            }
            
            //1. Calculate the Directional Movements: store results back into current-variable class cache
            GetDirectionalMovements(ref current);

            //2. Find the Average Directional Movement.
            GetAverageDirectionalMovements(ref current);

            //3. Get the Average True Range:
            GetAverageTrueRange(ref current);

            //4. Get the Average Directional Movement Index ADX-t, and DI+, DI-
            GetADX(ref current);

            //Strong Trend is Present, and have at least X-min data
            Decision = 0;
            if (current.adx > 40) {
                //NOW! We have an ADX result, interpret it..
                if (current.dmiPos > 40) {
                    Decision = 1;
                } else if (current.dmiNeg > 40) {
                    Decision = -1;
                }
            }

            //Save the results to publicly accessible properties.
            ADX = current.adx;
            DMI_Neg = current.dmiNeg;
            DMI_Pos = current.dmiPos;

            //Update the indicator cache - store previous result between calls.
            current.set = true; Ready = true;
            indicatorMemory = current;
            _superCandle = new Candle();

            return Decision;
        }
        
        
        /// <summary>
        /// 1. Get the pure directional movements, in DM+, DM- Form.
        /// </summary>
        /// <param name="current">ADX Cache class for easy storing for next analysis session.</param>
        private void GetDirectionalMovements(ref ADXCacheItem current) {
            //Change from the previous period to now.
            decimal deltaHigh = current.OHLC.High - indicatorMemory.OHLC.High;
            decimal deltaLow = indicatorMemory.OHLC.Low - current.OHLC.Low;

            //Allocate the Delta Movement.
            if ((deltaHigh < 0 && deltaLow < 0) || (deltaHigh == deltaLow)) {
                current.dm_plus = 0;
                current.dm_neg = 0;

            } else if (deltaHigh > deltaLow) {
                current.dm_plus = deltaHigh;
                current.dm_neg = 0;

            } else if (deltaHigh < deltaLow) {
                current.dm_plus = 0;
                current.dm_neg = deltaLow;
            }
        }
        
        
        
        /// <summary>
        /// 2. Get the Exp Average of the directional movement indexs
        /// </summary>
        private void GetAverageDirectionalMovements(ref ADXCacheItem current) {
            if (!Ready) {
                //If this is the first run,
                current.adm_plus = current.dm_plus;
                current.adm_neg = current.dm_neg;
            } else {
                //This is not our first sample
                current.adm_plus = (current.dm_plus * _expConst) + (indicatorMemory.adm_plus * (1 - _expConst));
                current.adm_neg = (current.dm_neg * _expConst) + (indicatorMemory.adm_neg * (1 - _expConst)); ;
            }
        }

        

        /// <summary>
        /// 3. Get the true range of the price.
        /// </summary>
        private void GetAverageTrueRange(ref ADXCacheItem current) {
            decimal yesterdayClose = indicatorMemory.OHLC.Close;

            decimal trueRange = System.Math.Max(Math.Abs(current.OHLC.High - current.OHLC.Low),
                                System.Math.Max(Math.Abs(current.OHLC.High - yesterdayClose),
                                                Math.Abs(yesterdayClose - current.OHLC.Low)));

            //Get the current true range:
            if (indicatorMemory.atr == 0) {
                current.atr = trueRange;
            } else {
                current.atr = (trueRange * _expConst) + ((1 - _expConst) * indicatorMemory.atr);
            }
        }
        


        /// <summary>
        /// 4. Get the Directional Movement Index
        /// </summary>
        private void GetADX(ref ADXCacheItem current) {
            decimal dmi_plus = 0;  
            decimal dmi_neg = 0;  

            if (current.atr > 0) { 
                dmi_plus = (current.adm_plus / current.atr) * 100;
                dmi_neg = (current.adm_neg / current.atr) * 100;
            }

            if ((dmi_plus + dmi_neg) != 0) {
                current.dx = (Math.Abs(dmi_plus - dmi_neg) / (dmi_plus + dmi_neg)) * 100;
            } else {
                current.dx = indicatorMemory.dx;
            }

            //Save the results.
            current.dmiPos = dmi_plus;
            current.dmiNeg = dmi_neg;
            current.adx = current.dx * _expConst + (1 - _expConst) * indicatorMemory.adx;
        }

        
        /// <summary>
        /// Provide a structure for caching the previous values of the ADX
        /// </summary>
        public class ADXCacheItem {
            public Candle OHLC = new Candle();
            public bool set = false;
            public decimal atr = 0;
            public decimal dm_plus = 0;
            public decimal dm_neg = 0;
            public decimal adm_plus = 0;
            public decimal adm_neg = 0;
            public decimal dx = 0;
            public decimal dmiPos = 0;
            public decimal dmiNeg = 0;
            public decimal adx = 0;
        }
        
        
        /// <summary>
        /// Simple online "super-tradebar" generator for making an OHLC from multiple bars.
        /// </summary>
        public class Candle {
            public Candle() { }
            public decimal Open = 0;
            public decimal High = Decimal.MinValue;
            public decimal Low = Decimal.MaxValue;
            public decimal Close = 0;
            public int Samples = 0;
            
            public void Update(TradeBar bar) {
                if (Open == 0) Open = bar.Open;
                if (High < bar.High) High = bar.High;
                if (Low > bar.Low) Low = bar.Low;
                Close = bar.Close;
                Samples++;
            }
        }
        
    } // End ADX Indicator Class
    
} // End Namespace