Overall Statistics
/*
 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
 * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/


using QuantConnect.Data;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Indicators;
using QuantConnect.Data.Custom;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Data.Consolidators;


namespace QuantConnect.Algorithm.CSharp
{

	/*
    *   Paul McKinney: CSV Guided Portfolio Balance
    *
    */
	public class BasicTemplateAlgorithm : QCAlgorithm
	{
		// algorithm settings
		// default history & universe resolution 
		const Resolution _algo_resolution = Resolution.Daily;

		// setup the algorithm indicators
		public const int _longMovingAverage = 120;
		public const int _shortMovingAverage = 10;

		// portfolio handling variables
		public const decimal _startingcash = 200000m;
		public const decimal _minimumcash = 200m;
		public const decimal _positionweight = 0.086m;
		
		// setup buy and sell limit ratios
		public const decimal _minpricedrop = 0.99m;
		public const decimal _maxpricerise = 1.01m;
		
		// backtesting ranges
		public DateTime _startdate = new DateTime(2007, 11, 23); 
		public DateTime _enddate = new DateTime(2014, 11, 23);
		// public DateTime _startdate = DateTime.Now.Date.AddDays(-60);
		// public DateTime _enddate = DateTime.Now.Date.AddDays(-0);      

		// end algorithm settings	

		// setup dictionary to hold indicators for all securities
		private readonly ConcurrentDictionary<Symbol, SelectionData> _keyindicators = new ConcurrentDictionary<Symbol, SelectionData>();
		
		// we don't want to over order for the amount of cash we have, so track orders in a day
		private decimal _todaysorders = 0m;

		// messages defaults for email notifications
		private string _notification_message = "";
		private string _notification_email = "myemail@myaddress.com";
		private string _notification_subject = "QuantConnect Algo Message";
		
		// keeps indicators updated for each symbol
		private class SelectionData
		{
			// moving averages and momentum tracking
			public ExponentialMovingAverage LongMA;
			public ExponentialMovingAverage ShortMA;

			private decimal _momentum;

			 public decimal Momentum
			 {
			 	get
			 	{
			 		return _momentum ; 
			 	}
			 }

			 public decimal longMA
			 {
			 	get
			 	{
			 		return LongMA.Current.Value;
			 	}
			 }
			 
			 public decimal shortMA
			 {
			 	get
			 	{
			 		return ShortMA.Current.Value;
			 	}
			 }

			// constructure for dictionary item that sets up indicators
			public SelectionData()
			{
				LongMA = new ExponentialMovingAverage(_longMovingAverage);
				ShortMA = new ExponentialMovingAverage(_shortMovingAverage);
			}

			// this update must be called for each value to be fed through all your indicators
			// you want to be careful not over call Update or go backwards in time and call it with
			// a previous date.
			// it get's very trick with live enviroments because events are always being fired through OnData methods
			public bool Update(TradeBar tbar)
			{
				// if enough date has been passed to an indicator to perform calculations it is ready
				// each indicator will differ depending upon the amount of history you are calculating across
				bool isreadyshort = false;
				bool isreadylong = false;

				// call all the base indicators being tracked
				isreadyshort = ShortMA.Update(tbar.Time, tbar.Close);
				isreadylong = LongMA.Update(tbar.Time, tbar.Close);


				// if the other indicators are ready then I can calculate momentum
				if (isreadylong && isreadyshort && LongMA.Current.Value > 0m) 
				 {
				 	_momentum = ShortMA.Current.Value / LongMA.Current.Value;
				 }
				 else
				 {
				 	_momentum = 0;
				 }

				return isreadyshort && isreadylong;
			}
		}

		// Initialize the data and resolution you require for your strategy:
		// this method is call automatically every day. I belive it is called at midnight
		public override void Initialize()
		{
			// for backtesting setup the date range
			SetStartDate(_startdate);
			SetEndDate(_enddate);

			// don't do any margin stuff
			SetBrokerageModel(Brokerages.BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash);

			//Cash allocation
			SetCash(_startingcash);

			UniverseSettings.Resolution = _algo_resolution;
			
			AddSecurity(SecurityType.Equity, "IJH", _algo_resolution);  // iShares Core S&P Mid-Cap
			AddSecurity(SecurityType.Equity, "IJR", _algo_resolution);  // iShares Core S&P Small-Cap
			AddSecurity(SecurityType.Equity, "JKD", _algo_resolution);  // iShares Morningstar Larg-Cap
			AddSecurity(SecurityType.Equity, "IXG", _algo_resolution);  // iShares Global Financials
			AddSecurity(SecurityType.Equity, "IWO", _algo_resolution);  // iShares Russell 2000 Growth Index
			AddSecurity(SecurityType.Equity, "FREL", _algo_resolution);  // Fidelity® MSCI Real Estate ETF
			AddSecurity(SecurityType.Equity, "GLD", _algo_resolution);  // Gold


			// Schedule an event to fire after market open
			// I only want to buy and sell once a day right after the market opens
			// I'm not sure if I'll have issue with this on holidays.  I haven't tested that yet
			Schedule.On(DateRules.Every(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday), TimeRules.At(9, 35), () => 
			{
				Log("PerformTrades: Fired at: " + Time.ToString("D"));
				
				PerformTrades();
			});

		}

		// lets look through our stock that we own and see if we are ready to sell any of them
		void SellLoosers()
		{
			foreach (QuantConnect.Symbol holding in Portfolio.Keys)
			{
				if (Portfolio[holding].HoldStock) // sell only if we hold it, I belive I've seen instances where a stock has 0 shares in Portfolio
				{
					// pull up the stock from our dictionary
					SelectionData sd = _keyindicators[holding];

					// if it is moving downward put in an order to sell
					if (
						sd.shortMA < sd.longMA 
					   )
					{
						// using our limit ratio calculate an order for the day to sell the stock
						// if for some reason it jumps too low and never comes back up it will get cancelled limiting our losses
						LimitOrder(holding, -Portfolio[holding].Quantity, Securities[holding].Price * _minpricedrop);
						
						// this line builds up the email message so we can check our email at work and discover our trades ;)
						_notification_message += string.Format("  Sell {0}  Quantity {1} at {2:C3}\r", 
								holding.Value, Portfolio[holding].Quantity, Portfolio[holding].Price);  
					}
				}
			}
		}

		// go through a list of securities and look what to buy
		void ReallocateClassification(ref IEnumerable<Security> securitylist)
		{
			// calculate how much of an investment to make for any position
			// I don't want to buy any more than _positionweight of a stock
			// if it grows or shrinks, I don't adjust the position I hold
			decimal positionsize = _positionweight * (Portfolio.TotalHoldingsValue + Portfolio.Cash);

			foreach (Security sec in securitylist)
			{
				// pickup the current indicators from the dicitonary
				// only look to buy a stock if we don't already hold it
				SelectionData sd = _keyindicators[sec.Symbol];

				if (!Portfolio[sec.Symbol].HoldStock)
				{
					if (
						sd.shortMA > sd.longMA  
					)
					{
						// based on how much cash in the porfolio subtrack any open or filled orders for the day
						// If Portfolio.Cash gets updated, I might miss an order because I don't subtract filled orders form _todaysorders
						// I also subtrack a _minimumcahs to make sure I keep a little in the account
						if (Portfolio.Cash - _minimumcash - _todaysorders > positionsize)
						{
							// based on position size figure out how many orders to buy
							// then add the order dollar amount to _todaysorders
							int shares = (int)(positionsize / sec.Price);
							_todaysorders += positionsize;
							
							// put in the order setting up the limit based on the ratio
							LimitOrder(sec.Symbol, shares, sec.Price * _maxpricerise); 

							// add more order information to our email message
							_notification_message += string.Format("  Buy {0} at {1:C3}\r", 
									sec.Symbol.Value, sec.Price); 
											
						}
					}
				}
			}
		}
		
		public void PerformTrades()
		{
			// these types of debug messages can be annoying in backtesting
			// but it's very helpful when you are trying to figure out what is happening
			// during live trading
			Debug(" Checking for buy and sell...");
			
			// here is where I reset my email message information
			// I only want 1 email a day to tell me what I ordered
			_notification_subject = string.Format("QuantConnect Report: {0} ", Time.ToString("D"));
			_notification_message = "";
			
			// reset the amount spent on today's order
			_todaysorders = 0.0m;

			// go check what to sell
			SellLoosers();

			// when searching for what to buy I want a list that prioritizes by momentum
			// the query below will include information found in the indicators dictionary

			IEnumerable<Security> securitylist = from s in Securities.Values 
													let mpcs = _keyindicators.GetOrAdd(s.Symbol, sym => new SelectionData())
													where mpcs.Momentum > 0.0m
													orderby mpcs.Momentum descending
													select s;

			// using the sorted list of stock trade bars go see what to buy AND DON'T SPENT TOO MUCH MONEY
			// ... I'm not made out of margin you know!!!
			ReallocateClassification(ref securitylist);

			// if orders were placed then send the email message that was constructed
			if (_notification_message != "")
			{
				_notification_message = "\rThe Following Orders Were Created: \r\r" + _notification_message;

				Notify.Email(_notification_email, _notification_subject, _notification_message);
				Debug(_notification_message);
			}
		}
		
		// this is probably the most challanging event method for me to understand
		// it get's called for a variaty of reasons, but I'm not 100% sure I understand all of them
		// when I do get an event I want to make sure I know what the event is for and I process it correctly
		// right now I care about 2 things the daily update to my indicators which fires at about midnight
		// the second is when anything happens to one of the stocks I'm tracking
		public override void OnData(Slice slice)
		{
			// update all of the indicators
			foreach (TradeBar s in slice.Bars.Values)
			{
				// I only want to have daily indicators
				if (Securities[s.Symbol].Resolution == Resolution.Daily)
				{
					SelectionData sc;
	
					// look for the key in the dictionary and update it's indicators
					sc = _keyindicators.GetOrAdd(s.Symbol, sym => new SelectionData());
					sc.Update(s);
				}
			}

			// if anything happened to the stocks I'm following		
			string stock_event = "";

			if (slice.Splits.Count > 0)
				foreach (Split sp in slice.Splits.Values)
					stock_event += string.Format("Date: {0} Stock: {1} Split: {2:N3} At: {3:C3} \r", sp.Time.ToString("d"), sp.Symbol.Value, sp.SplitFactor, sp.Price);

			if (slice.Delistings.Count > 0)
				foreach (Delisting dl in slice.Delistings.Values)
					stock_event += string.Format("Date: {0} Stock: {1} Delisted At: {2:C3} \r", dl.Time.ToString("d"), dl.Symbol.Value, dl.Price);

			if (slice.Dividends.Count > 0)
				foreach (Dividend dv in slice.Dividends.Values)
					stock_event += string.Format("Date: {0}  Stock: {1} Dividend: {2:C3} \r", dv.Time.ToString("d"), dv.Symbol.Value, dv.Value);

			if (slice.SymbolChangedEvents.Count > 0)
				foreach (SymbolChangedEvent sc in slice.SymbolChangedEvents.Values)
					stock_event += string.Format("Date: {0}  Old Symbol: {1} New Symbol: {2} \r", sc.Time.ToString("d"), sc.OldSymbol, sc.NewSymbol); 

			if (stock_event != "")
			{
				if (LiveMode)
				{
					stock_event = "Stock Event(s) \r" + stock_event;

					Notify.Email(_notification_email, _notification_subject, stock_event);
				}
			}
		}

		// each day the initialize function is called
		// this method responds to the securities added or removed from the list we are keeping indicators for
		// when you start the algorithm, this method will bring all the indicators up todate
		public override void OnSecuritiesChanged(SecurityChanges changes)
		{
			// each time our securities change we'll be notified here
			// if a security was removed, take it from our dictionary
			// only if we don't hold it in the portfolio
			foreach (var sec in changes.RemovedSecurities)
			{
				// if we don't hold it then remove it from the list
				// if it is not in our list of desired securities
				if (!Portfolio[sec.Symbol].HoldStock)
				{
					SelectionData sc;

					_keyindicators.TryRemove(sec.Symbol, out sc);
				}
			}

			// add the new securities to our list
			// make sure we get all the history with our default resolution
			// go through all the indicators and upate them with the history data
			foreach (var sec in changes.AddedSecurities)
			{
				SelectionData sc;

				sc = _keyindicators.GetOrAdd(sec.Symbol, sym => new SelectionData());

				IEnumerable<TradeBar> history = History(sec.Symbol, _longMovingAverage, _algo_resolution);

				foreach (TradeBar tb in history)
				{
					sc.Update(tb);
				}
			}

		}

		// I like to get an email when my orders are filled, cancelled, or partially filled 
		public override void OnOrderEvent(OrderEvent orderEvent)
		{

			string order_message = string.Format("Order: {0} {1}   Sym: {2}   Price: {3:C3} Qty: {4} Fee: {5:C3},   {6:C3}",
											 	orderEvent.UtcTime.ToString("F"),
												 orderEvent.Status,
												 orderEvent.Symbol.Value,
												orderEvent.FillPrice,
												orderEvent.FillQuantity,
												 orderEvent.OrderFee,
											 orderEvent.Message);

			Notify.Email(_notification_email, _notification_subject, order_message);
		}

	}
}