Overall Statistics
Total Trades
218
Average Win
0.36%
Average Loss
-0.48%
Compounding Annual Return
-1.086%
Drawdown
16.700%
Expectancy
-0.041
Net Profit
-1.086%
Sharpe Ratio
0.053
Loss Rate
45%
Win Rate
55%
Profit-Loss Ratio
0.76
Alpha
0.013
Beta
-0.036
Annual Standard Deviation
0.196
Annual Variance
0.039
Information Ratio
-0.311
Tracking Error
0.232
Treynor Ratio
-0.288
Total Fees
$255.15
#
#   QuantConnect Basic Template:
#	Fundamentals to using a QuantConnect algorithm.
#
#	You can view the QCAlgorithm base class on Github: 
#	https://github.com/QuantConnect/Lean/tree/master/Algorithm
#
import numpy as np

class DemoAlgorithm(QCAlgorithm):
	
	def __init__(self):
		self.symbols = ['MSFT','UNH','CTAS','JNS','COG']

	def Initialize(self):
		# Set the cash we'd like to use for our backtest
		# This is ignored in live trading 
		self.SetCash(20000)
		
		# Start and end dates for the backtest.
		# These are ignored in live trading.
		self.SetStartDate(2016,1,1)
		self.SetEndDate(2017,1,1)
		
		#convert the strings in our list into QuantConnect.Symbol object for convenience. 
		for i in range(len(self.symbols)):
			# Add those symbols to our universe
			symbol = self.AddEquity(self.symbols[i],Resolution.Daily).Symbol
			# replace the original strings with QuantConnect.Symbols
			self.symbols[i] = symbol
			# self.History returns the historical price data into a pandas DataFrame, 
			# with columns['close','open','high','low']
			history = self.History(self.symbols[i],30,Resolution.Daily)
			# assign the price list to the corresponding QuantConnect.symbol instance for convenience.
			self.symbols[i].prices = [x for x in history['close']]
			# Calculate the 30 days and 10 days sma.
			self.symbols[i].sma_10 = np.mean(self.symbols[i].prices[-10:])
			self.symbols[i].sma_30 = np.mean(self.symbols[i].prices)

        # the scheduled event will be on fire every Monday after the market open
		self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Monday), 
		                 self.TimeRules.AfterMarketOpen(self.symbols[0], 2), Action(self.Rebalance))



	def OnData(self, data):
		# the 'data' contains other information besides daipy price. e.g, if there is a stock split on weekend, it would
		# returns a data at that time. we check here to ensure it's a normal data slice contains all the price information. 
		if False in [data.ContainsKey(x) for x in self.symbols]:
			return
		
		# update each stocks' price list every day
		for asset in self.symbols:
			asset.prices.append(float(data[asset].Close))
			asset.prices = asset.prices[-30:]
	
	def Rebalance(self):
		# first calculate the raw_weight for each stock
		for asset in self.symbols:
			asset.sma_10 = np.mean(asset.prices[-10:])
			asset.sma_30 = np.mean(asset.prices)
			asset.raw_weight = (asset.sma_10 - asset.sma_30)/asset.sma_30
		
		# calculate the total weight
		total_weights = sum([abs(x.raw_weight) for x in self.symbols])
		
		# calculate normalized_weights and then long/short
		for asset in self.symbols:
			asset.normalized_weights = asset.raw_weight/total_weights
			self.SetHoldings(asset,asset.normalized_weights)
			if asset.normalized_weights > 0:
				self.Log('long %s at weight %f'%(str(asset),asset.normalized_weights))
			else:
				self.Log('short %s at weight %f'%(str(asset),asset.normalized_weights))