Overall Statistics |
Total Trades 1322 Average Win 0.28% Average Loss -0.47% Compounding Annual Return 10.867% Drawdown 27.100% Expectancy 0.355 Net Profit 237.945% Sharpe Ratio 0.857 Loss Rate 15% Win Rate 85% Profit-Loss Ratio 0.60 Alpha 0.065 Beta 0.49 Annual Standard Deviation 0.13 Annual Variance 0.017 Information Ratio 0.118 Tracking Error 0.133 Treynor Ratio 0.228 Total Fees $13859.87 |
import pandas as pd import numpy as np import scipy.optimize import talib ### <summary> ### Basic template algorithm simply initializes the date range and cash. This is a skeleton ### framework you can use for designing an algorithm. ### </summary> class BasicTemplateAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2007,1,1) #Set Start Date self.SetCash(1000000) #Set Strategy Cash # Find more symbols here: http://quantconnect.com/data self.AddEquity("SPY") self.SetBenchmark('SPY') self.stocks = [ 'SPY', # S&P 500 'EZU', # MSCI EMU 'EWJ', # Asia Pacifc ex-Japan 'EEM', # Emerging Markets 'VNQ', # US REITs 'RWX', # International REITs 'IEF', # US 10 Year Treasury 'TLT', # US 30 Year Treasury 'DBC', # Commodities 'GLD'] # Gold self.additional = [ 'QQQ', 'IWM', 'IJH', 'IJR', 'AGG', 'LQD', 'PSP' ] self.stocks = self.stocks + self.additional for x in self.stocks: self.AddEquity(x, Resolution.Minute) #self.Securities[x].SetDataNormalizationMode(DataNormalizationMode.SplitAdjusted) self.Schedule.On(self.DateRules.MonthEnd("SPY"), self.TimeRules.BeforeMarketClose("SPY", 15), Action(self.allocate)) self.Portfolio.MarginCallModel = MarginCallModel.Null self.momentum_lookback = 126 self.correlation_lookback = 126 self.volatility_lookback = 21 self.leverage = 1 def calculate_portfolio_var(self, w, V): w = np.matrix(w) return (w*V*w.T)[0,0] def allocate(self): # Find the recent returns generated by each symbol hist = self.History(self.stocks, 200, Resolution.Daily).unstack(level=0).close assets = [] for x in self.stocks: ret = ((hist[x][-1]/hist[x][-self.momentum_lookback])) - 1 assets.append([x, ret]) sort = sorted(assets, key=lambda x: x[1], reverse=True) # Select the top half of best performing symbols symbols = [] for sym in range(int(len(sort) / 2)): symbols.append(sort[sym][0]) # Create a weighted covariance matrix using the previous # 126 days for correlation and 21 days for volatility hist = hist[symbols].pct_change()[1:] vol = hist[-self.volatility_lookback:].std().values vol = vol.reshape(1, len(symbols)) * vol.reshape(len(symbols), 1) corr = hist[-self.correlation_lookback:].corr() covar_matrix = np.matrix(vol * corr) # Create an equally weighted portfolio as the initial allocation to optimise w0 = [] for w in symbols: w0.append(1 / len(symbols)) # Find the Minimum Variance Portfolio cons = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1.0}) res = scipy.optimize.minimize(self.calculate_portfolio_var, w0, args=covar_matrix, method='SLSQP', constraints=cons) allocate = pd.Series(res.x, index=corr.index) # Liquidate any holdings that are currently invested and do not form part of the new # monthly portfolio to ensure we don't exceed buying power on rebalance for stock in self.stocks: if stock not in symbols and self.Securities[stock].Invested: self.Liquidate(stock) # Purchase new Minimum Variance Portfolio for stock in allocate.index.tolist(): self.SetHoldings(stock, allocate.tolist()[allocate.index.tolist().index(stock)] * self.leverage)