Overall Statistics
Total Trades
1898
Average Win
0.63%
Average Loss
-0.38%
Compounding Annual Return
18.064%
Drawdown
8.900%
Expectancy
0.246
Net Profit
134.423%
Sharpe Ratio
1.752
Loss Rate
53%
Win Rate
47%
Profit-Loss Ratio
1.66
Alpha
0.169
Beta
0.086
Annual Standard Deviation
0.098
Annual Variance
0.01
Information Ratio
1.547
Tracking Error
0.098
Treynor Ratio
1.985
Total Fees
$124215.06
using System;
using QuantConnect.Algorithm;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;

namespace QuantConnect 
{   
    /*
    *   QuantConnect University: Full Basic Template:
    *
    *   The underlying QCAlgorithm class is full of helper methods which enable you to use QuantConnect.
    *   We have explained some of these here, but the full algorithm can be found at:
    *   https://github.com/QuantConnect/QCAlgorithm/blob/master/QuantConnect.Algorithm/QCAlgorithm.cs
    */
    public class BasicTemplateAlgorithm : QCAlgorithm
    {
    	/**
    	* The script appears to be using the current price, but the RSI value from the last
    	bar.  Add consolidators for all of the Index tickers.  Add a set to keep track of 
    	which tickers have been updated by the consolidator and don't do any calculations
    	until all the tickers have been updated.
    	*/
    	
    	
    	private SimpleMovingAverage uvxyAverage;
    	private SimpleMovingAverage uvxyLongAverage;
    	private bool positionOpen = false;
    	private SpreadSlippageModel slippageModel = new SpreadSlippageModel();
    	
    	//Index tickers
    	
    	private String[] indexTickers = {"SPY", "DIA", "IWM", "QQQ"};
    	
   									
	private Dictionary<string,RelativeStrengthIndex> trendMap = new Dictionary<string,RelativeStrengthIndex>();

    
    	private String volIndex = "UVXY";
    	private String volTicker = "XIV";
    	private bool closeEOD = false;
    	private String maTicker;
    	private bool allUpdated = false;
    	private HashSet<String> completedSet = new HashSet<String>();
    	
    	
        //Initialize the data and resolution you require for your strategy:
        public override void Initialize() 
        {
        	maTicker = volIndex;
			
            //Start and End Date range for the backtest:
            SetStartDate(2013, 1, 1);
            SetEndDate(DateTime.Now.Date.AddDays(-1));
            
            //Cash allocation
            SetCash(1000000);
            
            
            foreach( String indexTicker in indexTickers ) {
            	AddSecurity(SecurityType.Equity, indexTicker, Resolution.Minute);
            	Securities[indexTicker].SlippageModel = slippageModel;
            	var consolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(5));
            	consolidator.DataConsolidated += FiveMinuteHandler;
            
            	RelativeStrengthIndex trend = new RelativeStrengthIndex(3, MovingAverageType.Simple);
            	
            	RegisterIndicator(indexTicker, trend, consolidator);
            	var history = History(indexTicker, TimeSpan.FromDays(5), Resolution.Minute);
				foreach (var tradeBar in history)
                {
                	trend.Update(tradeBar.EndTime, tradeBar.Close);
                }             	
                trendMap[indexTicker] = trend;
            }
            
            AddSecurity(SecurityType.Equity, volIndex, Resolution.Minute);
            AddSecurity(SecurityType.Equity, volTicker, Resolution.Minute);
            var fiveMinuteConsolidator2 = new TradeBarConsolidator(TimeSpan.FromMinutes(5));
            fiveMinuteConsolidator2.DataConsolidated += FiveMinuteHandler;
            SetBrokerageModel(new InteractiveBrokersBrokerageModel());
           
           
           

            uvxyAverage = new SimpleMovingAverage(20);
            uvxyLongAverage = new SimpleMovingAverage(50);
            
               var tradeBarHistory = History(maTicker, TimeSpan.FromDays(5), Resolution.Minute);

                foreach (var tradeBar in tradeBarHistory)
                {
                	
                    uvxyAverage.Update(tradeBar.EndTime, tradeBar.Close);
                    uvxyLongAverage.Update(tradeBar.EndTime, tradeBar.Close);
                    
                }                 
         
            RegisterIndicator(maTicker, uvxyAverage, fiveMinuteConsolidator2);
            RegisterIndicator(maTicker, uvxyLongAverage, fiveMinuteConsolidator2);
           

        }
        
        
        private void FiveMinuteHandler(object sender, TradeBar consolidatedBar) {
        	DateTime time = consolidatedBar.Time;
        	Log( "UVXY Ready: " + uvxyAverage.IsReady + " uvxyLongAverageReady: " + uvxyLongAverage.IsReady);
        	if( uvxyAverage.IsReady && uvxyLongAverage.IsReady) {
        		Log("Short Avg: " + uvxyAverage + " Long Avg: " + uvxyLongAverage );
        		foreach(KeyValuePair<string, RelativeStrengthIndex> entry in trendMap)
					{decimal prc = Securities[entry.Key].Price;
					if(entry.Value > 0 ) {
					
						decimal amt = (prc-entry.Value)/ entry.Value;
						Log("RSI for: " + entry.Key + " is: " + entry.Value + " last: " + prc + " propValue: " + amt);
					} else {
						Log("RSI value is zero for: " +  entry.Key + " last: " + prc);
					}
				}

	
        		if( uvxyAverage < uvxyLongAverage && ! positionOpen) {
        			if( time.Hour < 15 || (time.Hour == 15 && time.Minute <= 60)  ) {
        				
						decimal lowest = 100000;
						decimal highest= 0;
						
						String lowestTicker = "";
						String highestTicker = "";
						
						foreach(KeyValuePair<string, RelativeStrengthIndex> entry in trendMap)
						{
							
							if(entry.Value > 0 ) {
							decimal price = Securities[entry.Key].Price;
							decimal amount = (price-entry.Value)/ entry.Value;
							//decimal amount = entry.Value;
							
							if(amount < lowest) {
								lowest = amount;
								lowestTicker = entry.Key;
							}
							if( amount > highest ) {
								highest = amount;
								highestTicker = entry.Key;
							
							}
							}
    						
						}
						Log("Trade triggered, selecting: " + lowestTicker);
						positionOpen = true;
						
						decimal size = 1.0m;
						
						SetHoldings(lowestTicker, size);
        			}
        			
        		} else {
        			if( uvxyAverage > uvxyLongAverage && positionOpen ) {
        				if( time.Hour < 15 || (time.Hour == 15 && time.Minute <= 60)  ) {
        				positionOpen  =false;
        				Liquidate();
        				}
        			} 
        		}
        		
					if( consolidatedBar.Time.Hour == 15 && consolidatedBar.Time.Minute >= 55 ) {
						if( closeEOD ) {
							positionOpen = false;
        					Liquidate();
						}
        			}        		
        		
        	} else {
        		Console.WriteLine("Warming up");
        	}
        }

        //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(data.ContainsKey(volIndex) ) {
        		Plot(volIndex, "Price", data[volIndex].Price);
            	Plot(volIndex, uvxyAverage, uvxyLongAverage);
        	}

            
            if (!Portfolio.HoldStock) 
            {
            }
        }
    }
}
namespace QuantConnect {

  public class SpreadSlippageModel : ISlippageModel
    {
        private readonly decimal _slippagePercent;
        /// <summary>
        /// Initializes a new instance of the <see cref="ConstantSlippageModel"/> class
        /// </summary>
        /// <param name="slippagePercent">The slippage percent for each order. Percent is ranged 0 to 1.</param>
        public SpreadSlippageModel()
        {
            
        }

        /// <summary>
        /// Slippage Model. Return a decimal cash slippage approximation on the order.
        /// </summary>
        public decimal GetSlippageApproximation(Security asset, Order order)
        {
			return 0.01m;
        }
    }

}