Overall Statistics
Total Trades
1
Average Win
0%
Average Loss
0%
Compounding Annual Return
16.001%
Drawdown
7.200%
Expectancy
0
Net Profit
0%
Sharpe Ratio
1.39
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0.165
Beta
-0.063
Annual Standard Deviation
0.111
Annual Variance
0.012
Information Ratio
-0.097
Tracking Error
0.163
Treynor Ratio
-2.464
Total Fees
$1.00

namespace QuantConnect.Indicators {

    /// <summary> 
    /// This indicator creates a moving average (middle band) with an upper band and lower band
    /// fixed at k average true range away from the middle band
    /// </summary>
    public class KeltnerChannels : TradeBarIndicator    
    {
       /// Set up of variables
       private IndicatorBase<IndicatorDataPoint> _MiddleBand;
       private IndicatorBase<TradeBar> _UpperBand;
       private IndicatorBase<TradeBar> _LowerBand;
       private IndicatorBase<TradeBar> _ATR;

        /// <summary>
        /// Initializes a new instance of the KeltnerChannels class
        /// </summary>
        /// <param name="period">The period of the average true range and moving average (middle band)</param>
        /// <param name="k">The number of multiplies specifying the distance between the middle band and upper or lower bands</param>
        /// <param name="movingAverageType">The type of moving average to be used</param>
        public KeltnerChannels(int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple)
            : this(string.Format("KC({0},{1})", period, k), period, k, movingAverageType)
        {
        }

        /// <summary>
        /// Initializes a new instance of the KeltnerChannels class
        /// </summary>
        /// <param name="name">The name of this indicator</param>
        /// <param name="period">The period of the average true range and moving average (middle band)</param>
        /// <param name="k">The number of multiples specifying the distance between the middle band and upper or lower bands</param>
        /// <param name="movingAverageType">The type of moving average to be used</param>
        public KeltnerChannels(string name, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple)
        : base(name)
        {
            ///Initialise ATR and SMA
            _ATR = new AverageTrueRange(name + "_AverageTrueRange", period, movingAverageType);
            _MiddleBand = new SimpleMovingAverage(name + "_SimpleMovingAverage", period);
            
            ///Compute Lower Band
            _LowerBand = new FunctionalIndicator<TradeBar>(name + "_LowerBand",
                input => ComputeLowerBand(k, period, input),
                fastStoch => _MiddleBand.IsReady,
                () => _MiddleBand.Reset()
                );
            
            ///Compute Upper Band
            _UpperBand = new FunctionalIndicator<TradeBar>(name + "_UpperBand",
                input => ComputeUpperBand(k, period, input),
                fastStoch => _MiddleBand.IsReady,
                () => _MiddleBand.Reset()
                );
        }
 		
 		
 		/// <summary>
        /// calculates the lower band
        /// </summary>
        private decimal ComputeLowerBand(decimal k, int period, TradeBar input)
        {
            var lowerBand = _MiddleBand.Samples >= period ?  _MiddleBand - Decimal.Multiply(_ATR,k): new decimal(0.0);
            
            return lowerBand;
        }
        
        /// <summary>
        /// calculates the upper band
        /// </summary>
        private decimal ComputeUpperBand(decimal k, int period, TradeBar input)
        {
            var upperBand = _MiddleBand.Samples >= period ?  _MiddleBand + Decimal.Multiply(_ATR,k): new decimal(0.0);
            
            return upperBand;
        }
       
        /// <summary>
        /// Gets a flag indicating when this indicator is ready and fully initialized
        /// </summary>
        public override bool IsReady
        {
            get { return _MiddleBand.IsReady && _UpperBand.IsReady && _LowerBand.IsReady; }
        }
		/// <summary>
        /// Returns the Upper band of the kelter channel
        /// </summary>
		public decimal UpperBand
		{
			get { return _UpperBand;}
		}
		/// <summary>
        /// Returns the Lower band of the kelter channel
        /// </summary>
		public decimal LowerBand
		{
			get { return _LowerBand;}
		}
		/// <summary>
        /// Returns the Middle band of the kelter channel
        /// </summary>
		public decimal MiddleBand
		{
			get { return _MiddleBand;}
		}
		
		/// <summary>
        /// Returns the average true range value of the Keltner Channels
        /// </summary>
		public decimal TrueRangeAverage
		{
			get { return _ATR;}
		}
     	
     	/// <summary>
        /// Computes the next value for this indicator from the given state.
        /// </summary>
        /// <param name="input">The TradeBar to this indicator on this time step</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(TradeBar input)
        {
           	_ATR.Update(input);
            _MiddleBand.Update(input.Time, input.Close);
			_LowerBand.Update(input);
            _UpperBand.Update(input);
            return _MiddleBand;
        }
     
    	public override void Reset()
        {
            _ATR.Reset();  
            _MiddleBand.Reset();
            _UpperBand.Reset();
            _LowerBand.Reset();
            base.Reset();
        }
     
    }

}                        
namespace QuantConnect 
{   
    /*
    *   Keltner Channel indicator demostration
    *
    *       
    *   
    */
    public class volatility : QCAlgorithm
    {
        ///Initialise the keltner channels
        KeltnerChannels KC;
        string _symbol = "SPY";
        
        //Initialize the data and resolution you require for your strategy:
        public override void Initialize() 
        {
			
            //Start and End Date range for the backtest:
            SetStartDate(2013, 1, 1);         
            SetEndDate(DateTime.Now.Date.AddDays(-1));
            
            //Cash allocation
            SetCash(25000);
            
            ///Set keltner channel variables
            KC = new KeltnerChannels(14, 1.5m);
            
            //Add as many securities as you like. All the data will be passed into the event handler:
            AddSecurity(SecurityType.Equity, _symbol, Resolution.Daily);
            
            //Register kelter channels for updates
            RegisterIndicator(_symbol, KC, 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) 
        {   
            ///check if indicator is ready
            if(!KC.IsReady) return;
            ///Simple volatility entry
            var holdings = Portfolio[_symbol].Quantity;
            var trigger = data[_symbol].High > KC.UpperBand ? true : false;
            
            if (holdings==0 && trigger) 
            {
               SetHoldings(_symbol, 1); 
            } 
            
            ///plot
            Plot("Keltner Channels",_symbol, Securities[_symbol].Price);
            Plot("Keltner Channels","Upper Band", KC.UpperBand);
            Plot("Keltner Channels","Lower Band", KC.LowerBand);
        }
    }
}