Overall Statistics
'''
This strategy resolves around working with fundamentals and finding the best companies based on
- Free Cash Flow Yield
- ROC value (Price Index)

It combines both of these values in necessary percentage to find the top 30 companies to invest in
All companies will have equal weightage
'''

from QuantConnect import Resolution, Extensions
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from itertools import groupby
from datetime import datetime, timedelta
class TheStrongOnes(QCAlgorithm):

'''
ROUGH GUIDELINES
1.Decide on Universe (possibly Dollar volume)
2.Sort the companies by ROC (12 monhts and then 6 monhts)
4.Take top 20% of the companies based on ROC
5.Calculate the free cash flow yield for these 200 companies
6.Sort high to Low and take the top 30 out of final 40
7.Equal investment on all companies"

ROUGH TRY FOR QUANTCONNECT GUIDANCE
1. Coarse selection -  Find all with stocks with Fundamental data and price greater than \$10 - DONE
2. Fine selection - Find all stocks with Marketcap greater than 100M - DONE
3. Check if we can run Insights generator on a monthly basis and do not run if it is not one month - NO NEED
3.1 Calculate ROC from 1000 copmpanies and get 20% sorted high to low - DONE
3.2 Calculate free cash flow on 200 companies now and find the top 30 out of it - DONE
3.3 Generate Insghts Group for these 30 companies - NOT NEEDED
4. Add Portfolio Construction to Equal weight to buy all these 30 companies - DONE
5. Rebalance should happen automatically every month based on Insights group or may be Universe selection itself
'''
def Initialize(self):
self.SetStartDate(2012, 1, 1)
self.SetEndDate(2012, 2, 15)
self.SetCash(10000)
self.UniverseSettings.Resolution = Resolution.Daily
self.Settings.RebalancePortfolioOnSecurityChanges = True
self.SetPortfolioConstruction( EqualWeightingPortfolioConstructionModel() )
self.SetExecution(ImmediateExecutionModel())
self.numberOfSymbolsCoarse = 20
self.numberOfSymbolsFine = 10
self.current = self.Time - timedelta(31)

def CoarseSelectionFilter(self, coarse):
if (self.Time - self.current).days <= 30:
return Universe.Unchanged

sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)   # sort descending by daily dollar volume
return [ x.Symbol for x in sortedByDollarVolume if x.Price > 10 and x.HasFundamentalData][:self.numberOfSymbolsCoarse]  # return the symbol objects of the top entries from our sorted collection

def FineSelectionFilter(self, fine):
if (self.Time - self.current).days <= 30:
return Universe.Unchanged

market_cap = {}

# Calculate the market cap and add the "MarketCap" property to fine universe object
for i in fine:
market_cap[i] = (i.EarningReports.BasicAverageShares.ThreeMonths * i.EarningReports.BasicEPS.TwelveMonths * i.ValuationRatios.PERatio)

filtered = [x for x in fine if market_cap[x] > 0]

marketCapFilter = sorted(filtered, key=lambda x: market_cap[x])

# marketCapFilter = [x for x in fine if x.Marketcap > 10000000]
sortedByCashReturn = sorted(marketCapFilter, key=lambda x: x.ValuationRatios.CashReturn, reverse=True)[:200]
sortedByROIC = sorted(sortedByCashReturn, key=lambda x: x.OperationRatios.ROIC.OneYear)[:40]
self.Debug('sortedByROIC -->'+ str(len(sortedByROIC)))
return [ x.Symbol for x in sortedByROIC]

def OnData(self, CoarseSelectionFilter):
if not self.Portfolio.Invested:
self.current = self.Time