Overall Statistics
Total Trades
1143
Average Win
3.60%
Average Loss
-3.65%
Compounding Annual Return
-6.237%
Drawdown
98.200%
Expectancy
0.042
Net Profit
-36.316%
Sharpe Ratio
0.464
Loss Rate
48%
Win Rate
52%
Profit-Loss Ratio
0.99
Alpha
-0.576
Beta
51.005
Annual Standard Deviation
0.96
Annual Variance
0.922
Information Ratio
0.443
Tracking Error
0.96
Treynor Ratio
0.009
Total Fees
$1419.49
/*
Wenbo Zhnag 9/17/17 on https://www.quantopian.com/posts/ballistic-xiv-slash-vxx-my-best-long-xiv-slash-vxx-strategy-to-date
Also read https://www.quantopian.com/posts/ballistic-xiv-slash-vxx-my-best-long-xiv-slash-vxx-strategy-to-date                                           
*/

namespace QuantConnect 
{
	public partial class TestConsolidatedIndicator : QCAlgorithm
    {
    	//Editable parameters
    	int context_xivTradePercent = 100;
    	int context_tltTradePercent = 100;
    	int context_vxxTradePercent = 100;
    	decimal context_StopLossPct = 0.25M;
    
	    //Used for logging
	    decimal context_StopPrice = 0;
	    decimal context_BuyPrice = 0;
	    decimal context_SellLossPrice = 0;
	    decimal context_SellProfitPrice = 0;
	    bool context_last_bar = false;
	    bool context_sell = false;
	    public bool context_buy = false;
	    bool context_buyVXX = false;
	    // FR#2: Delayed buy;
	    // context.buyTLT = False;
	    // FR#4: Improve buy/sell condition
	    decimal context_rsi_last = -1;
    	decimal context_newsl = 0;
    	decimal rsi_current = 0 ;
    	decimal rsi_previous = 0;
    	
            
        public void BarDetails()
        {
        	// return String.Format("{0} - {1}", pBar.Time, pBar.Price);
        	
        	if (Data["XIV"].Bars.Count > 0)
        	{
        		var bar = Data["XIV"].Bars[0];
        		LogIt(String.Format("{0} - {1}", bar.Time, bar.Price));	
        	}
        	
        	if (Data["XIV"].Bars.Count > 1)
        	{
        		var bar = Data["XIV"].Bars[1];
        		LogIt(String.Format("{0} - {1}", bar.Time, bar.Price));		
        	}
        	//return ;
        	
        }
        
		public void bar_open()
		{
			var vMethodName = "bar_open";
			LogMethodStart(vMethodName);
			
			
			
			BarDetails();
			
			//return;
			
			if ((context_buy == true) && (Transactions.GetOpenOrders().Count == 0))
			{
		
				set_fixed_stop();
				
				// TODO:  Turm the below two If statements into a loop from dictionary, and the list is where symbol in PositionType.Overnight, PositionType.Base
				// Also verify that after Liquidate the there are no more positions held.
				// #FR#2: Delayed buy
		        if (Portfolio[Symbols[PositionType.Overnight]].Quantity > 0)
		        {
		            Liquidate(Symbols[PositionType.Overnight]);
		            LogIt("Sell " + Symbols[PositionType.Overnight]);
		        }
		        if (Portfolio[Symbols[PositionType.Base]].Quantity > 0)
		        {
		            Liquidate(Symbols[PositionType.Base]);
		            LogIt("Sell " + Symbols[PositionType.Base] + " at " + Price(Symbols[PositionType.Base]));
		        }
		
				// Fill a market order immediately (before moving to next line of code)
				var newTicket = MarketOrder(Symbols[PositionType.Inverse], context_xivTradePercent);
				
		        LogIt("Buy XIV at " + context_BuyPrice);
		        context_buy = false;
		        context_sell = false;
		        context_buyVXX = false;
		        context_newsl = 0;  	
			}
			
			if ( (context_buyVXX == true) && (Portfolio[Symbols[PositionType.Base]].Quantity == 0) && (Transactions.GetOpenOrders().Count == 0) )
			{
        		var newTicket = MarketOrder(Symbols[PositionType.Base], context_vxxTradePercent);
        
        		LogIt("Buy VXX at " + Price(Symbols[PositionType.Base]));
        		context_buyVXX = false;
			
			}
			
			if ((context_sell == true) && (Portfolio[Symbols[PositionType.Inverse]].Quantity > 0))
			{
				Liquidate(Symbols[PositionType.Inverse]);
				LogIt("Sell " + Symbols[PositionType.Inverse] + " at " + Price(Symbols[PositionType.Inverse]));
        		context_sell = false;
        		context_buy = false; 
			}
			
			LogMethodEnd(vMethodName);
		}
		
		
		public void my_rebalance()
		{
			var vMethodName = "my_rebalance";
			LogMethodStart(vMethodName);
			// Get RSI for every 2 hour period for the last 10 periods.	
			
			
			rsi_current = Data[Symbols[PositionType.Inverse]].RSI_History[0].Value;
			rsi_previous = rsi_current;
			
			if (Data[Symbols[PositionType.Inverse]].RSI_History.Count > 1)
			{
				rsi_previous = Data[Symbols[PositionType.Inverse]].RSI_History[1].Value;
				if (context_rsi_last == -1)
				{
	        		context_rsi_last =  Data[Symbols[PositionType.Inverse]].RSI_History[1].Value;
				}
			}

			var vxx_price = Price(Symbols[PositionType.Base]); 
			var xiv_price = Price(Symbols[PositionType.Inverse]);
			var message = String.Format("Current XIV price {0:0.00}, VXX price {1:0.00} @ RSI_2 level {2}, previous {3}, last stored {4}"
			, xiv_price, vxx_price,	rsi_current, rsi_previous, context_rsi_last);

			LogIt(message);


			//BUY RULE
    		if ((context_buy == false) && (context_rsi_last < 70) && (rsi_current >= 70) && (Portfolio[Symbols[PositionType.Base]].Quantity == 0))
    		{
        		context_buy = true;
    		}

			
			//SELL RULE
    		if ((context_rsi_last > 85) && (rsi_current <= 85) && (HaveNoHoldingsIn(PositionType.Inverse)) && IsTransactionDone())
    		{
    			Liquidate(Symbols[PositionType.Inverse]);
    					
    			LogIt(String.Format("Sell {0} at {1:0.00}", Symbols[PositionType.Inverse],xiv_price) );
    			context_buy = false;
    		}
		    
		    if ((context_buyVXX == false) && (rsi_current <= 30) && (HaveNoHoldingsIn(PositionType.Base)))
		    {
		    	context_buyVXX = true;
		    }
		    
			//Buy VXX rule
			if ((context_buyVXX == false) && (context_rsi_last > 30) && (rsi_current <= 30) 
				&& (HaveNoHoldingsIn(PositionType.Base)) && (HaveNoHoldingsIn(PositionType.Inverse)) )
		    {
		    	context_buyVXX = true;
		    }
			
			// Sell VXX rule
			if ((context_rsi_last < 15) && (rsi_current >= 15) && ( !HaveNoHoldingsIn(PositionType.Base)))
    		{
    			Liquidate(Symbols[PositionType.Base]);
    					
    			LogIt(String.Format("Sell {0} at {1:0.00}", Symbols[PositionType.Base], vxx_price) );
    			context_buyVXX = false;
    		}

   			// panic
   			// if (Time.Hour > 12)
   			{
   				var high = -1M;
   				var long_history = History(Symbols[PositionType.Inverse], 119, Resolution.Minute );
   				// var long_history = History(Symbols[PositionType.Inverse], TimeSpan.FromMinutes(119), Resolution.Minute );
   				// LogIt(long_history.Count());

				if (long_history.Count() > 0)
				{
	   				high = long_history.Max(element => (element.High)); // 10M ;
				}
   			
	   			/*
	   			 TODO: Note this is the current implementation of context.last_bar.  Will need to understand more before I figure this out properly
	   			 */
	   			if (Time.Hour >= 16) 
				{
					high = History(Symbols[PositionType.Inverse], 29, Resolution.Minute).Max(element => (element.High));
				} 
	   			
	   			// TODO: I think the logic is, if current price is less than 10% of high --Check and confirm
	   			if (((high/xiv_price) - 1) > (decimal).1)
	   			{
	   				Liquidate(Symbols[PositionType.Inverse]);
	    			LogIt(String.Format("Panic Sell {0} at {1:0.00}", Symbols[PositionType.Inverse], xiv_price) );
	    			context_sell = false;
	        		context_buy = false;
	   			}
	   			
   			}
   			
   			context_rsi_last = rsi_current;

			LogMethodEnd(vMethodName);
		}
		
		public void set_fixed_stop()
		{
			var vMethodName = "set_fixed_stop";
			LogMethodStart(vMethodName);
			
	    	// Only call this once when the stock is bought
	    	var price = Price(Symbols[PositionType.Inverse]);   
	    	// data.current(Symbols[PositionType.Inverse], 'price'); // Quantopian code
	                                                  
	    	context_BuyPrice = price;
	    	context_SellLossPrice = Math.Max(context_StopPrice, price - (context_StopLossPct * price)); 
	    	
	    	LogMethodEnd(vMethodName);
		}
		
		public void handle_data()
		{
			var vxx_price = Price(Symbols[PositionType.Base]); 
			var xiv_price = Price(Symbols[PositionType.Inverse]); 
			
			if (context_BuyPrice > 0)
			{
				if ((HaveHoldingsIn(PositionType.Inverse)) )
				{
					// set break even
					if (((xiv_price / context_BuyPrice) >= (decimal)1.1) && ( context_BuyPrice > context_SellLossPrice))
					{
						context_SellLossPrice = context_BuyPrice;
						
						LogIt(String.Format("New {0} stop loss price {1:0.00}", Symbols[PositionType.Inverse], context_SellLossPrice));
					}
				}
				
				// 50% trailing stop
	        	// FR#1: Add profit take 50%
				if (((xiv_price / context_BuyPrice) >= (decimal)1.5) && ( context_BuyPrice > context_SellLossPrice))
				{
						context_SellLossPrice = xiv_price;
						
						LogIt(String.Format("{0} take HUGE profit at {1:0.00}", Symbols[PositionType.Inverse], context_SellLossPrice));
				}
			}
			
			// If we have a position check sell conditions
        	if ((xiv_price <= context_SellLossPrice) && IsTransactionDone())
            {
            	Liquidate(Symbols[PositionType.Inverse]);
            	LogIt(String.Format("Stop loss sell {0} at {1:0.00}", Symbols[PositionType.Inverse], xiv_price));
            
            	context_sell = false;
            	context_buy = false;
            }
			


		}
		
		// TODO: Link OnData to Handle_Data and then testS

		
		
    }
}
namespace QuantConnect
{
    /// <summary>
    /// Cloned from https://github.com/QuantConnect/Lean/blob/master/Algorithm.CSharp/MultipleSymbolConsolidationAlgorithm.cs
    /// </summary>
    
    /* Things to do:
   	1.	Add two or more symbols to be looked at.
   	2.	Get the last 10 prices for each 2 hour period.
   			This could be over multiple days, ignore weekend and holidays.
   	3.	Warmup does not seem to be working
   	4.	In the documentation I saw a line for RegisterIndicator.  Is this not required?
   	5.	How would I used Consolidators with long and short SMA.
   	6.  How would I used Consolidators withe multiple indicators - SMA, RSI - Long and short for each
   	7.	The "Bar" has two values Time and EndTime.  The data provided is for which time?
   	8.  Could the SMA be defined with 
   	symbolData.SMA = SMA(symbolData.Symbol, SimpleMovingAveragePeriod, ResolutionPeriod);
   	9.
   	*/
    /* Errors:
    
    */
    
    public partial class TestConsolidatedIndicator : QCAlgorithm
    {
    	public struct PositionType
		{
			private PositionType(string value) { Value = value; }

 			public string Value { get; set; }
 
 			public static PositionType Base { get { return new PositionType("Base"); } }
 			public static PositionType Inverse { get { return new PositionType("Inverse"); } }
 			public static PositionType Overnight { get { return new PositionType("Overnight"); } }
		}
    	
    	
    	
    	private const int BarPeriodValue = 1;
    	private const int MINUTES_IN_HOUR = 60;
    	private const string SPY = "SPY";
    	
    	/// <summary>
        /// This is the period of bars we'll be creating
        /// </summary>
        public readonly Resolution ResolutionPeriod = Resolution.Minute;

        /// <summary>
        /// This is the period of our sma SLOW indicators
        /// </summary>
        public readonly int SimpleMovingAveragePeriod_Small = 2;
        /// <summary>
        /// This is the period of our sma FAST indicators
        /// </summary>
        public readonly int SimpleMovingAveragePeriod_Large = 5;
        /// <summary>
        /// This is the number of consolidated bars we'll hold in symbol data for reference
        /// </summary>
        public readonly int RollingWindowSize = 5;
        /// <summary>
        /// Holds all of our data keyed by each symbol
        /// </summary>
        public readonly Dictionary<string, ConsolidatedIndicator> Data = new Dictionary<string, ConsolidatedIndicator>();
        /// <summary>
        /// Contains all of our equity symbols
        /// </summary>
    
        public readonly Dictionary<PositionType, string> Symbols = new Dictionary<PositionType, string> {
				{PositionType.Base, "VXX" },
				{PositionType.Inverse, "XIV" },
				{PositionType.Overnight, "TLT" }
		};
        

		/// <summary>
        /// This is the period of bars we'll be creating
        /// </summary>
		public TimeSpan GetBarPeriod()
		{
			switch (ResolutionPeriod)
	        	{
	        		case Resolution.Minute:
	        			return TimeSpan.FromMinutes(BarPeriodValue);
	        		case Resolution.Hour:
	        			return TimeSpan.FromHours(BarPeriodValue);
	        		case Resolution.Daily:
	        			return TimeSpan.FromDays(BarPeriodValue);
	        		default:
	        			throw new ArgumentOutOfRangeException();
	        	}
		}

        /// <summary>
        /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
        /// </summary>
        public override void Initialize()
        {
            SetStartDate(2011, 01, 5);  		// Set Start Date
            SetEndDate(2018, 1, 5);    			// Set End Date
            SetCash(100000);              		// Set Strategy Cash
			//SetWarmUp(RollingWindowSize + 2);		// Happens after Initalize is done.

			AddEquity(SPY, ResolutionPeriod);

		    foreach(var entry in Symbols)
            {
            	var symbol = entry.Value;
                var equity = AddEquity(symbol, ResolutionPeriod);
                Debug(symbol);
                Data.Add(symbol, new ConsolidatedIndicator(equity.Symbol, GetBarPeriod(), RollingWindowSize));
            }


			ScheduleMethods();
	
            // loop through all our symbols and request data subscriptions and initialize indicators
            foreach (var kvp in Data)
            {
                // this is required since we're using closures below, for more information
                // see: http://stackoverflow.com/questions/14907987/access-to-foreach-variable-in-closure-warning
                var symbolData = kvp.Value;

                // define a consolidator to consolidate data for this symbol on the requested period
                var consolidator = symbolData.Symbol.SecurityType == SecurityType.Equity
                    ? (IDataConsolidator)new TradeBarConsolidator(GetBarPeriod())
                    : (IDataConsolidator)new QuoteBarConsolidator(GetBarPeriod());

                // define our indicator
                // symbolData.SMA_Small = new SimpleMovingAverage(CreateIndicatorName(symbolData.Symbol, "SMA" + SimpleMovingAveragePeriod_Small, ResolutionPeriod), SimpleMovingAveragePeriod_Small);
                // symbolData.SMA_Large = new SimpleMovingAverage(CreateIndicatorName(symbolData.Symbol, "SMA" + SimpleMovingAveragePeriod_Large, ResolutionPeriod), SimpleMovingAveragePeriod_Large);
				symbolData.RSI = new RelativeStrengthIndex(CreateIndicatorName(symbolData.Symbol, "RSI" + SimpleMovingAveragePeriod_Small, ResolutionPeriod), SimpleMovingAveragePeriod_Small, MovingAverageType.Simple);	
				
			
				
                // wire up our consolidator to update the indicator
                consolidator.DataConsolidated += (sender, baseData) =>
                {
     				IReadOnlyList<string> TimesToCheck =  new List<string>{ "9:39", "11:29", "1:29", "3:29", "4:00" };
     				
     				if (!TimesToCheck.Contains(Time.ToString("h:mm")))
                    {
                    	return;
                    }
                    
                    // 'bar' here is our newly consolidated data
                    var bar = (IBaseDataBar)baseData;
                    
                    // LogIt(Time.ToString("u") + " " + bar);
                    
                    
                    // we're also going to add this bar to our rolling window so we have access to it later
                    symbolData.Bars.Add(bar);
                    
                    
                    // update the indicator
                    // symbolData.SMA_Small.Update(bar.Time, bar.Close);
                    // symbolData.SMA_Large.Update(bar.Time, bar.Close);
                    symbolData.RSI.Update(bar.Time, bar.Close);
                    symbolData.RSI_History.Add(symbolData.RSI.Current);
                    
                };
                // consolidator.DataConsolidated += HandleConsolidatedData; 

                // we need to add this consolidator so it gets auto updates
                SubscriptionManager.AddConsolidator(symbolData.Symbol, consolidator);

            }
            
            // Debug("Is the warmup done?");
        }
        
        private void ScheduleMethods()
        {
        	
			IReadOnlyList<int> MyRebalanceHours =  new List<int>{ 2, 4, 6 };
			foreach (var hour in MyRebalanceHours)
	        {
	        	// LogIt(hour);
	        	Schedule.On(DateRules.EveryDay(SPY), TimeRules.AfterMarketOpen(SPY, (MINUTES_IN_HOUR * hour) + 2), my_rebalance);
	        }
	        Schedule.On(DateRules.EveryDay(SPY), TimeRules.AfterMarketOpen(SPY, 11), my_rebalance);
	        Schedule.On(DateRules.EveryDay(SPY), TimeRules.BeforeMarketClose(SPY, 25), my_rebalance);
			
			
        	IReadOnlyList<int> BarOpenHours =  new List<int>{0, 2, 4, 6 };
			foreach (var hour in BarOpenHours)
	        {
	        	Schedule.On(DateRules.EveryDay(SPY), TimeRules.AfterMarketOpen(SPY, (MINUTES_IN_HOUR * hour) + 5), bar_open);
	        }

        }
        
        public void scheduled_test()
        {
        	Debug(Time.Hour + ":" + Time.Minute);
        }

		public void HandleConsolidatedData(object pSender, IBaseData pBaseData)
		{
			//if (IsWarmingUp) return;
			var vMethodName = "HandleConsolidatedData";
			
			LogIt(vMethodName);
            //BarDetails();

			if (Time.Hour >= 16)
			{
				// LogIt("End of Day:  No more activity");
				return;
			}

			// LogMethodStart(vMethodName);
			
			//SymbolDataDetails(vMethodName);
			
			foreach (var symbolData in Data.Values)
            {
                // this check proves that this symbol was JUST updated prior to this OnData function being called
                if (symbolData.IsReady && symbolData.WasJustUpdated(Time))
                {
                	var output = String.Format("{0} - RSI - Current: {1}; Last: {2}; Second Last: {3}", symbolData.Symbol, symbolData.RSI, symbolData.RSI_History[0].Value, symbolData.RSI_History[1].Value);
                	LogIt(output);
             	    // LogMethodStart(vMethodName + " - " + symbolData.Symbol);
             	    
             	    /*
     				LogIt("Current Period Value: " + symbolData.Bars[0].Value );
        			LogIt(symbolData.SMA_Small.ToString());
     				LogIt("SMA Small Current: " + symbolData.SMA_Small.Current );
     				LogIt("SMA Small Details: " + symbolData.SMA_Small.ToDetailedString());
        			LogIt(symbolData.SMA_Large.ToString());
     				LogIt("SMA Large Current: " + symbolData.SMA_Large.Current );
     				LogIt("SMA Large Details: " + symbolData.SMA_Large.ToDetailedString());
     				*/
     				/*
     				LogIt("RSI: " + symbolData.RSI);
     				LogIt("RSI Current: " + symbolData.RSI_Lag[0]);
     				LogIt("RSI Previous: " + symbolData.RSI_Lag[1]);
     				*/
     				/*
        			foreach(var bar in symbolData.Bars)
	            	{
	            		var message = String.Format("{4} - Time: {0:ddd} {0} ; EndTime: {1:ddd} {1} ; Value: {2} ; Price: {3}", bar.Time, bar.EndTime, bar.Value, bar.Price, vMethodName);
	            		// Debug(bar.ToString());
	            		LogIt(message);
	            	}
	            	*/
	            	
                }
            }
		}
		
		
        /// <summary>
        /// End of a trading day event handler. This method is called at the end of the algorithm day (or multiple times if trading multiple assets).
        /// </summary>
        /// <remarks>Method is called 10 minutes before closing to allow user to close out position.</remarks>
        public override void OnEndOfDay()
        {
        	// LogMethodStart("OnEndOfDay");
        	
            int i = 0;
            // foreach (var kvp in Data.OrderBy(x => x.Value.Symbol))
            foreach (var kvp in Data.Where(x => x.Value.Symbol == Symbols[PositionType.Inverse]))
            {
                // we have too many symbols to plot them all, so plot ever other
                if (kvp.Value.IsReady && ++i%2 == 0)
                {
                    // Plot(kvp.Value.Symbol.ToString(), kvp.Value.SMA_Small);
                    Plot(kvp.Value.Symbol.ToString(), kvp.Value.RSI);
                }
            }
        }

        private void SymbolDataDetails(string pMethodName)
		{
			// loop through each symbol in our structure
            foreach (var symbolData in Data.Values)
            {
                
                //if (symbolData.IsReady)// && symbolData.WasJustUpdated(Time))
                {
             	    LogMethodStart(pMethodName + " - " + symbolData.Symbol);
        			
					foreach(var bar in symbolData.Bars)
	            	{
	            		var message = String.Format("{4} - Time: {0:ddd} {0} ; EndTime: {1:ddd} {1} ; Value: {2} ; Price: {3}", bar.Time, bar.EndTime, bar.Value, bar.Price, pMethodName);
	            		// Debug(bar.ToString());
	            		Debug(message);
	            	}
                }
            }
		}
		
		
		/// <summary>
        /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        /// </summary>
        /// <param name="data">TradeBars IDictionary object with your stock data</param>
        public override void OnData(Slice data)
        {
        	// handle_data();	
        	
        	/*
            // loop through each symbol in our structure
            foreach (var symbolData in Data.Values)
            {
                // this check proves that this symbol was JUST updated prior to this OnData function being called
                if (symbolData.IsReady && symbolData.WasJustUpdated(Time))
                {
                	// If the position is currently held
                	if((Portfolio[symbolData.Symbol].Quantity > 0))
                  	{
                  	
                  	}
                }
            }
            */
        }
        
        /*
        public bool AreSymbolsReady()
        {
        	foreach (var symbolData in Data.Values)
            {
            	yield return new System.Threading.WaitUntil(() => (symbolData.IsReady && symbolData.WasJustUpdated(Time)));
                
                // this check proves that this symbol was JUST updated prior to this OnData function being called
                // if (symbolData.IsReady && symbolData.WasJustUpdated(Time))
                // {
                	
                // }
            }
            return true;
        }
        */

    }
    
}
namespace QuantConnect {

    //
    //	Make sure to change "BasicTemplateAlgorithm" to your algorithm class name, and that all
    //	files use "public partial class" if you want to split up your algorithm namespace into multiple files.
    //

    //public partial class BasicTemplateAlgorithm : QCAlgorithm, IAlgorithm
    //{
    //  Extension functions can go here...(ones that need access to QCAlgorithm functions e.g. Debug, Log etc.)
    //}

    //public class Indicator 
    //{
    //  ...or you can define whole new classes independent of the QuantConnect Context
    //}

	public partial class TestConsolidatedIndicator : QCAlgorithm, IAlgorithm
	{
		#region Log Method Start & End
        private void LogMethodStart(string pMethodName)
        {
        	return;
        	LogMethod(pMethodName);
        }
        
        private void LogMethodEnd(string pMethodName)
        {
			return;
			LogMethod(pMethodName, false);       	
        }
        
        private void LogMethod(string pMethodName, bool pIsStart = true)
        {
        	var vState = pIsStart ? "Start" : "End";
        	var vMessage = String.Format("Method: {0} {1} - {2:MM/dd/yy H:mm:ss:fff}", pMethodName, vState, Time);
        	
        	LogIt(vMessage);
        }
        #endregion Log Method Start & End
        
        private void LogIt(int pMessage)
        {
        	LogIt(pMessage.ToString());
        }
        
        private void LogIt(string pMessage)
        {
        	Debug(Time + " : " + pMessage);
        	// Log(Time + " : " + pMessage);
        }
        
        private bool IsTransactionDone()
        {
        	return (Transactions.GetOpenOrders().Count == 0);
        }
        
        private bool HaveNoHoldingsIn(PositionType pPositionType)
        {
        	return !HaveHoldingsIn(pPositionType);	
        }
        
        private bool HaveHoldingsIn(PositionType pPositionType)
        {
        	return (Portfolio[Symbols[pPositionType]].Quantity > 0);	
        }
        
        private decimal Price(String pSymbol)
        {
        	return Securities[pSymbol].Price;
        	// return Securities[pSymbol].GetLastData().Price;
        }
	}

}
namespace QuantConnect {


	/// <summary>
    /// Contains data pertaining to a symbol in our algorithm
    /// </summary>
    public class ConsolidatedIndicator
    {
       
        
        /// <summary>
        /// This symbol the other data in this class is associated with
        /// </summary>
        public readonly Symbol Symbol;
        
        #region TradeBar properties
        /// <summary>
        /// A rolling window of data, data needs to be pumped into Bars by using Bars.Update( tradeBar ) and
        /// can be accessed like:
        ///  mySymbolData.Bars[0] - most first recent piece of data
        ///  mySymbolData.Bars[5] - the sixth most recent piece of data (zero based indexing)
        /// </summary>
        public readonly RollingWindow<IBaseDataBar> Bars;
        /// <summary>
        /// The period used when population the Bars rolling window.
        /// </summary>
        public readonly TimeSpan BarPeriod;
        #endregion TradeBar properties
        
        /// <summary>
        /// The simple moving average Small indicator for our symbol
        /// </summary>
        public SimpleMovingAverage SMA_Small;
		/// <summary>
        /// The simple moving average Large indicator for our symbol
        /// </summary>
        public SimpleMovingAverage SMA_Large;

		/// <summary>
        /// The Relative Strength Index indicator for our symbol
        /// </summary>
        public RelativeStrengthIndex RSI;

		public readonly RollingWindow<IndicatorDataPoint> RSI_History;
		
		// public readonly RollingWindow<RelativeStrengthIndex> RSI_History;

	    /// <summary>
        /// Initializes a new instance of SymbolData
        /// </summary>
        public ConsolidatedIndicator(Symbol symbol, TimeSpan barPeriod, int windowSize)
        {
            Symbol = symbol;
            BarPeriod = barPeriod;
            Bars = new RollingWindow<IBaseDataBar>(windowSize);
            RSI_History = new RollingWindow<IndicatorDataPoint>(3);
        }



        /// <summary>
        /// Returns true if the most recent trade bar time matches the current time minus the bar's period, this
        /// indicates that update was just called on this instance
        /// </summary>
        /// <param name="current">The current algorithm time</param>
        /// <returns>True if this instance was just updated with new data, false otherwise</returns>
        public bool WasJustUpdated(DateTime current)
        {
            return Bars.Count > 0 && Bars[0].Time == current - BarPeriod;
        }
        
        /// <summary>
        /// Returns true if all the data in this instance is ready (indicators, rolling windows, ect...)
        /// </summary>
        public bool IsReady
        {
            get { return Bars.IsReady && SMA_Small.IsReady && SMA_Large.IsReady && RSI.IsReady; }
        }
        
    }
}