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
{

	public class StockRankAlgorithm : QCAlgorithm
	{
		// algorythm settings
		const Resolution _algo_resolution = Resolution.Daily;

		public const decimal _startingcash = 100000m;
		public const decimal _positionweight = 0.10m;
		
		private int _lastmonth = 0;

		// public DateTime _startdate = new DateTime(2007, 11, 23); 
		// public DateTime _enddate = new DateTime(2014, 11, 23);
		public DateTime _startdate = DateTime.Now.Date.AddDays(-120);
		public DateTime _enddate = DateTime.Now.Date.AddDays(-1);     

        // sort the data by daily dollar volume and take the top 'NumberOfSymbolsCoarse'
        public IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse)
        {
        	var hasmorningstar = from x in coarse
        							//where (x.HasFundamentalData && x.DollarVolume > 200000000m && x.DollarVolume > 500000000m)
        							where (x.HasFundamentalData && x.DollarVolume > 20000000m && x.DollarVolume > 70000000m)
        							orderby x.DollarVolume ascending
        							select x.Symbol;
        							
            // we need to return only the symbol objects
            return hasmorningstar.Take(100);
        }

        // calculate the f-score
        private int FScore(
        	decimal netincome, 
        	decimal operating_cashflow, 
        	decimal roa_current, decimal roa_past, 
        	decimal issued_current, decimal issued_past, 
        	decimal grossm_current, decimal grossm_past,
        	decimal longterm_current, decimal longterm_past,
        	decimal curratio_current, decimal curratio_past,
        	decimal assetturn_current, decimal assetturn_past
        	)
        {
        	int fscore = 0;
        	
        	fscore += (roa_current > 0m ? 1 : 0 );  // return on assets is positive
        	fscore += ( operating_cashflow > 0m ? 1 : 0 );  // operating cashflow in current year is positive
        	fscore += ( roa_current >= roa_past ? 1 : 0 );  // roa has increased since last Time
        	fscore += ( operating_cashflow > roa_current ? 1 : 0 );  // cashflow from current operations are greater than roa
        	fscore += ( longterm_current <= longterm_past ? 1 : 0 );  // a decrease in the long term debt ratio
        	fscore += ( curratio_current >= curratio_past ? 1 : 0 );  // an increase in the current ratio
        	fscore += ( issued_current <= issued_past ? 1 : 0 );  // no new shares have been issued
        	fscore += ( grossm_current >= grossm_past ? 1 : 0 );  // an increase in gross margin
        	fscore += ( assetturn_current >= assetturn_past ? 1 : 0 ); // a higher asset turnover ratio
        	
        	// Debug("<<<<<<");
        	//Debug("f-score :"  +fscore);
        	// Debug("roa current : " + roa_current);
        	// Debug("operating cashflow : " + operating_cashflow);
        	// Debug("roa current : " + roa_current + " past : " + roa_past);
        	// Debug("operating cashflow : " + operating_cashflow );
        	// Debug("longterm_current : " + longterm_current + " past : " + longterm_past);
        	// Debug("curratio_current : " + curratio_current + " past : " + curratio_past);
        	// Debug("issued current : " + issued_current + " : past " + issued_past);
        	// Debug("grossm current : " + grossm_current + " : past " + grossm_past);
        	// Debug("assetturn_current : " + assetturn_current + " : " + assetturn_past);
        	
        	return fscore;
        }
        
        // sort the data by P/E ratio and take the top 'NumberOfSymbolsFine'
        public IEnumerable<Symbol> FineSelectionFunction(IEnumerable<FineFundamental> fine)
        {
            // find piatroski score
            var piatroskiscore = from x in fine
						let fs = FScore(
            				x.FinancialStatements.IncomeStatement.NetIncome.TwelveMonths,
            				x.FinancialStatements.CashFlowStatement.CashFlowFromContinuingOperatingActivities.TwelveMonths,
            				x.OperationRatios.ROA.ThreeMonths, x.OperationRatios.ROA.OneYear,
            				x.FinancialStatements.BalanceSheet.ShareIssued.ThreeMonths, x.FinancialStatements.BalanceSheet.ShareIssued.TwelveMonths,  
							x.OperationRatios.GrossMargin.ThreeMonths, x.OperationRatios.GrossMargin.OneYear,
							x.OperationRatios.LongTermDebtEquityRatio.ThreeMonths, x.OperationRatios.LongTermDebtEquityRatio.OneYear, // fix need last year
							x.OperationRatios.CurrentRatio.ThreeMonths, x.OperationRatios.CurrentRatio.OneYear, // fix need last year 
							x.OperationRatios.AssetsTurnover.ThreeMonths, x.OperationRatios.AssetsTurnover.OneYear // fix need last year
            			)
            			where (fs >= 5) 
						orderby fs descending
						select x;
            
            // take the top entries from our sorted collection
            var topFine = piatroskiscore.Take(10);
            
            Debug("Found " + topFine.Count() + " possibilities");
            // foreach (var s in topFine)
            // {
            // 	Debug(s.ToString());
            // }
            
            // we need to return only the symbol objects
            return topFine.Select(x => x.Symbol);
        }


		// Initialize the data and resolution you require for your strategy:
		public override void Initialize()
		{
			SetStartDate(_startdate);
			SetEndDate(_enddate);

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

			//Cash allocation
			SetCash(_startingcash);

			UniverseSettings.Resolution = _algo_resolution;

			// this add universe method accepts two parameters:
            // - coarse selection function: accepts an IEnumerable<CoarseFundamental> and returns an IEnumerable<Symbol>
            // - fine selection function: accepts an IEnumerable<FineFundamental> and returns an IEnumerable<Symbol>
            AddUniverse(CoarseSelectionFunction, FineSelectionFunction);
		}


		public override void OnData(Slice slice)
		{
			// only rebalance every month
			if (slice.Time.Month != _lastmonth)
			{
				_lastmonth = slice.Time.Month;
				
				// sell what we are no longer interested iinterested
				foreach (var pos in Portfolio.Keys)
				{
					if (Portfolio[pos].HoldStock)
					{
						var check = from x in slice.Bars
								where (x.Value.Symbol == pos)
								select x.Value.Symbol;
								
					if (check.Count() == 0)
						SetHoldings(pos, 0m);
					}
				}
				
				// buy highly ranked stocks
				foreach ( var bar in slice.Bars)
					SetHoldings(bar.Value.Symbol, _positionweight); 
			}
		}
	}
}