Overall Statistics
Total Trades
513
Average Win
1.74%
Average Loss
-1.53%
Compounding Annual Return
81.332%
Drawdown
29.900%
Expectancy
0.188
Net Profit
89.185%
Sharpe Ratio
1.348
Loss Rate
45%
Win Rate
55%
Profit-Loss Ratio
1.14
Alpha
0.461
Beta
0.217
Annual Standard Deviation
0.349
Annual Variance
0.122
Information Ratio
1.186
Tracking Error
0.36
Treynor Ratio
2.166
Total Fees
$1548.19
using System;
using System.CodeDom;
using QuantConnect.Algorithm;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.Indicators;

namespace Sandbox.DualConsolidation
{
    public class DualConsolidation : QCAlgorithm
    {
        private const string VIX = "YAHOO/INDEX_VIX";
        private const string VXV = "CBOEFE/INDEX_VXV";
        private SimpleMovingAverage smaVIX;
        private SimpleMovingAverage smaVXV;
        private IndicatorBase<IndicatorDataPoint> ratio_VXV_VIX;
        
        private string vxx = "VXX"; 
        private string xiv = "XIV"; 

        public override void Initialize()
        {
            SetStartDate(2015, 11, 11);
			SetCash(25000);
            // request data
            AddData<Quandl>(VIX);
            AddData<Quandl>(VXV);

            // define data sources for our functional indicator, these are really just 'identities' of the closing price
            smaVIX = SMA(VIX, 10);
            smaVXV = SMA(VXV, 10);

            // the functional indicator takes as arguments two functions,
            // the first is a ComputeNextValue function
            // the second is an IsReady function
            ratio_VXV_VIX = new FunctionalIndicator<IndicatorDataPoint>("ratio",
                point => RatioIndicator_ComputeNextValue(point, smaVXV, smaVIX),
                ratioIndicator => RatioIndicator_IsReady(ratioIndicator, smaVXV, smaVIX)
                );

            // we register to the VXV and VIX symbols, so when either of these gets data updates our indicator will recompute
            var identityConsolidator = new IdentityDataConsolidator<Quandl>();
            RegisterIndicator(VXV, ratio_VXV_VIX, identityConsolidator, x => x.Value);
            RegisterIndicator(VIX, ratio_VXV_VIX, identityConsolidator, x => x.Value);
            
            AddSecurity(SecurityType.Equity, vxx, Resolution.Minute);
            AddSecurity(SecurityType.Equity, xiv, Resolution.Minute);
        }

        private DateTime previous;
        public void OnData(Quandl data)
        {
        	if (IsWarmingUp) return;
        	
            if (previous.Date != data.Time.Date && smaVIX.IsReady && smaVXV.IsReady && ratio_VXV_VIX.IsReady)
            {
                previous = data.Time;
                Plot("Data", smaVIX, smaVXV);
                Plot("Ratio", ratio_VXV_VIX);
                
                if (ratio_VXV_VIX < 0.923m) 
                {
					Liquidate(xiv);
					SetHoldings(xiv, -1);
				} else 
				{
                	Liquidate(xiv);
					SetHoldings(xiv, 1);
				}
            }
        }

        /// <summary>
        /// This code is run as part of the ratio_VXV_VIX functional indicator
        /// </summary>
        /// <remarks>
        /// This is the ComputeNextValue function implementation for IndicatorBase
        /// </remarks>
        private decimal RatioIndicator_ComputeNextValue(IndicatorDataPoint data,
            IndicatorBase<IndicatorDataPoint> vxv,
            IndicatorBase<IndicatorDataPoint> vix)
        {
            return vxv / vix;
        }

        /// <summary>
        /// This code is run as part of the ratio_VXV_VIX functional indicator
        /// </summary>
        /// <remarks>
        /// This is the IsReady function implementation for IndicatorBase
        /// </remarks>
        private bool RatioIndicator_IsReady(IndicatorBase<IndicatorDataPoint> functionalIndicator,
            IndicatorBase<IndicatorDataPoint> vxv,
            IndicatorBase<IndicatorDataPoint> vix)
        {
            return vxv.IsReady && vix.IsReady;
        }
    }
}