| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
#This is a Template of dynamic stock selection.
#You can try your own fundamental factor and ranking method by editing the CoarseSelectionFunction and FineSelectionFunction
from System.Collections.Generic import List
from QuantConnect.Data.UniverseSelection import *
class BasicTemplateAlgorithm(QCAlgorithm):
def __init__(self):
# set the flag for rebalance
self.reb = 1
# Number of stocks to pass CoarseSelection process
self.num_coarse = 50
# Number of stocks to long/short
self.num_fine = 20
self.symbols = None
self.first_month = 0
def Initialize(self):
self.SetCash(100000)
self.SetStartDate(2015,1,1)
# if not specified, the Backtesting EndDate would be today
self.SetEndDate(2015,8,1)
self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseSelectionFunction,self.FineSelectionFunction)
# Schedule the rebalance function to execute at the begining of each month
self.Schedule.On(self.DateRules.MonthStart(self.spy),
self.TimeRules.AfterMarketOpen(self.spy,5), Action(self.Rebalance))
def CoarseSelectionFunction(self, coarse):
# Attempt to only try rebalance quarterly on the 1st day of the month
#today = self.Time
#self.Log("Day = {} Month = {}".format(today.day,today.month))
if self.reb != 1:
return
CoarseWithFundamental = [x for x in coarse if x.HasFundamentalData]
sortedByDollarVolume = sorted(CoarseWithFundamental, key=lambda x: x.DollarVolume, reverse=True)
#result = [ x.Symbol for x in sortedByDollarVolume[:self.__numberOfSymbols] ]
result = [ x.Symbol for x in sortedByDollarVolume[:self.num_coarse] ]
self.universe = result
return self.universe
def FineSelectionFunction(self, fine):
# return null list if it's not time to rebalance
if self.reb != 1:
return
self.reb = 0
# drop stocks which don't have the information we need.
# you can try replacing those factor with your own factors here
filtered_fine = [x for x in fine if x.ValuationRatios.PriceChange1M
and x.ValuationRatios.PERatio]
self.Log('remained to select %d'%(len(filtered_fine)))
# rank stocks by two factors.
sortedByfactor1 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.PriceChange1M, reverse=False)
sortedByfactor2 = sorted(filtered_fine, key=lambda x: x.ValuationRatios.PERatio, reverse=False)
stock_dict = {}
# assign a score to each stock, you can also change the rule of scoring here.
for i,ele in enumerate(sortedByfactor1):
rank1 = i
rank2 = sortedByfactor2.index(ele)
score = sum([rank1*0.5,rank2*0.5])
stock_dict[ele] = score
# sort the stocks by their scores
self.sorted_stock = sorted(stock_dict.items(), key=lambda d:d[1],reverse=False)
sorted_symbol = [x[0] for x in self.sorted_stock]
# sort the top stocks into the long_list and the bottom ones into the short_list
self.longs = [x.Symbol for x in sorted_symbol[:self.num_fine]]
#topFine = self.long
#self.universe = [ x.Symbol for x in topFine ]
#self.universe = self.long
#return self.universe
#return [i.Symbol for i in (self.long)]
return self.longs
#else:
# return []
def OnData(self, data):
pass
def Rebalance(self):
if self.first_month == 0:
self.first_month += 1
return
# if this month the stock are not going to be long/short, liquidate it.
for i in self.Portfolio.Values:
if (i.Invested) and (i.Symbol not in self.longs):
self.Liquidate(i.Symbol)
# Alternatively, you can liquidate all the stocks at the end of each month.
# Which method to choose depends on your investment philosiphy
# if you prefer to realized the gain/loss each month, you can choose this method.
#self.Liquidate()
# Assign each stock equally. Alternatively you can design your own portfolio construction method
for i in self.longs:
self.SetHoldings(i,0.99/self.num_fine)
self.reb = 1