Overall Statistics |
Total Trades 35 Average Win 0.99% Average Loss -0.74% Compounding Annual Return 8.314% Drawdown 3.300% Expectancy 0.654 Net Profit 8.361% Sharpe Ratio 1.173 Probabilistic Sharpe Ratio 56.003% Loss Rate 29% Win Rate 71% Profit-Loss Ratio 1.34 Alpha 0.069 Beta -0.007 Annual Standard Deviation 0.059 Annual Variance 0.004 Information Ratio 0.578 Tracking Error 0.165 Treynor Ratio -10.172 Total Fees $9288.87 |
from QuantConnect.Indicators import * import numpy as np from datetime import datetime, timedelta from sklearn import linear_model from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score, accuracy_score import sklearn as sk import pandas as pd class RSISwingRejection(QCAlgorithm): def Initialize(self): self.SetStartDate(2017, 1, 1) # Set Start Date self.SetEndDate(2019, 1, 1) #Set End Date self.SetCash(10000000) # Set Strategy Cash self.tickers = ["GOLD", "TSLA", "TREE", "YELP", "RYN"] #Selected stocks self.percent = 1/(len(self.tickers)) #Proportion of stock selection self.rsiDict = {} self.symbolDataBySymbol = {} self.returns = pd.DataFrame(columns=['Stock', 'Date', 'Holdings', 'RSI']) #Adding equity, the RSI, symbol data, and initializing a rolling window for each stock for symbol in self.tickers: self.AddEquity(symbol, Resolution.Daily) rsi = self.RSI(symbol, 14, MovingAverageType.Simple, Resolution.Daily) symbolData = SymbolData(symbol, rsi) self.symbolDataBySymbol[symbol] = symbolData self.rsiDict[symbol] = RollingWindow[float](14) #Warm-up the data for 30 days self.SetWarmUp(timedelta(days = 30)) def OnData(self, data): #Make sure nothing is going on when warming up the data if self.IsWarmingUp: return #Add the RSI values of each stock within the rolling window for symbol, symbolData in self.symbolDataBySymbol.items(): #For all securities in self.stocks rsi = symbolData.RSI self.rsiDict[symbol].Add(rsi.Current.Value) #If a stock has not been invested in if not self.Portfolio.Invested: #Overbought RSI Swing Rejection #RSI needs to surpass the 70 threshold if rsi.Current.Value > 70: #After the previous point, RSI must be between 45 and 55 (this is a self-selected range) for x in range(self.rsiDict[symbol].Count): if self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + 1)] > 45 and self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + 1)] < 55: #Thereafter, RSI returns to a range between 65 and 70 for z in range(self.rsiDict[symbol].Count - x): if self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + z + 1)] > 65 and self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + z + 1)] < 70: #Trigger! Setup a short posiiton with the percent variable self.SetHoldings(symbol, -self.percent) #Oversold RSI Swing Rejection #RSI needs to fall below the 30 threshold elif rsi.Current.Value < 30: #After the previous point, must be between 45 and 55 for x in range(self.rsiDict[symbol].Count): if self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + 1)] > 45 and self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + 1)] < 55: #Thereafter, RSI returns to a range between 30 and 35 for z in range(self.rsiDict[symbol].Count - x): if self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + z + 1)] > 30 and self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + z + 1)] < 35: #Trigger! Setup a long position with the percent variable self.SetHoldings(symbol, self.percent) #If a stock has been invested in else: #If there is a long position, liquidate when RSI returns to 45 if self.Portfolio[symbol].IsLong: if rsi.Current.Value > 45: self.Liquidate(symbol) #If there is a short position, liquidate when RSI returns to 55 if self.Portfolio[symbol].IsShort: if rsi.Current.Value < 55: self.Liquidate(symbol) new_row = ({'Stock': str(symbol), 'Date': self.Time, 'Holdings' : self.Portfolio[symbol].HoldingsValue, 'RSI' : rsi.Current.Value}) self.returns = self.returns.append(new_row, ignore_index = True)
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel from QuantConnect.Indicators import * import numpy as np from datetime import datetime, timedelta from sklearn import linear_model from sklearn.model_selection import train_test_split, cross_val_score from sklearn.metrics import mean_squared_error, r2_score, accuracy_score import sklearn as sk import pandas as pd import json class RSISwingRejection(QCAlgorithm): def Initialize(self): self.SetStartDate(2018, 1, 1) # Set Start Date self.SetEndDate(2019, 1, 1) #Set End Date self.SetCash(10000000) # Set Strategy Cash self.tickers = ["GOLD", "TSLA", "TREE", "YELP", "RYN"] #Selected stocks self.percent = 1/(len(self.tickers)) #Proportion of stock selection self.rsiDict = {} self.symbolDataBySymbol = {} self.returns = pd.DataFrame(columns=['Stock', 'Date', 'Holdings', 'Price']) #Adding equity, the RSI, symbol data, and initializing a rolling window for each stock for symbol in self.tickers: self.AddEquity(symbol, Resolution.Daily) rsi = self.RSI(symbol, 14, MovingAverageType.Simple, Resolution.Daily) symbolData = SymbolData(symbol, rsi) self.symbolDataBySymbol[symbol] = symbolData self.rsiDict[symbol] = RollingWindow[float](14) #Warm-up the data for 30 day self.SetWarmUp(timedelta(days = 30)) if self.ObjectStore.ContainsKey("MyObject"): self.ObjectStore.Delete("MyObject") def OnData(self, data): #Make sure nothing is going on when warming up the data if self.IsWarmingUp: return #Add the RSI values of each stock within the rolling window for symbol, symbolData in self.symbolDataBySymbol.items(): #For all securities in self.stocks rsi = symbolData.RSI self.rsiDict[symbol].Add(rsi.Current.Value) #If a stock has not been invested in if not self.Portfolio.Invested: #Overbought RSI Swing Rejection #RSI needs to surpass the 70 threshold if rsi.Current.Value > 70: #After the previous point, RSI must be between 45 and 55 (this is a self-selected range) for x in range(self.rsiDict[symbol].Count): if self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + 1)] > 45 and self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + 1)] < 55: #Thereafter, RSI returns to a range between 65 and 70 for z in range(self.rsiDict[symbol].Count - x): if self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + z + 1)] > 65 and self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + z + 1)] < 70: #Trigger! Setup a short posiiton with the percent variable self.SetHoldings(symbol, -self.percent) #Oversold RSI Swing Rejection #RSI needs to fall below the 30 threshold elif rsi.Current.Value < 30: #After the previous point, must be between 45 and 55 for x in range(self.rsiDict[symbol].Count): if self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + 1)] > 45 and self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + 1)] < 55: #Thereafter, RSI returns to a range between 30 and 35 for z in range(self.rsiDict[symbol].Count - x): if self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + z + 1)] > 30 and self.rsiDict[symbol][self.rsiDict[symbol].Count - (x + z + 1)] < 35: #Trigger! Setup a long position with the percent variable self.SetHoldings(symbol, self.percent) #If a stock has been invested in else: #If there is a long position, liquidate when RSI returns to 45 if self.Portfolio[symbol].IsLong: if rsi.Current.Value > 45: self.Liquidate(symbol) new_row = ({'Stock': str(symbol), 'Date': str(self.Time), 'Holdings' : self.Portfolio[symbol].HoldingsValue, 'Price': self.Securities[symbol].Price}) self.returns = self.returns.append(new_row, ignore_index = True) #self.returns = self.returns.append(new_row, ignore_index = True) #If there is a short position, liquidate when RSI returns to 55 if self.Portfolio[symbol].IsShort: if rsi.Current.Value < 55: self.Liquidate(symbol) new_row = ({'Stock': str(symbol), 'Date': str(self.Time), 'Holdings' : self.Portfolio[symbol].HoldingsValue, 'Price': self.Securities[symbol].Price}) self.returns = self.returns.append(new_row, ignore_index = True) #self.returns = self.returns.append(new_row, ignore_index = True) #new_row = ({'Stock': str(symbol), 'Date': str(self.Time), 'Holdings' : self.Portfolio[symbol].HoldingsValue, 'Price': self.Securities[symbol].Price}) #self.returns = self.returns.append(new_row, ignore_index = True) def OnEndOfAlgorithm(self): self.returns = self.returns.sort_values(by = ["Date"]) self.returns = self.returns.to_dict() save_json = json.dumps(self.returns) self.ObjectStore.Save("MyObject", save_json) load_object = json.loads(self.ObjectStore.Read("MyObject")) self.Debug(load_object) class SymbolData: #Contains data specific to a symbol required by this model def __init__(self, symbol, rsi): self.Symbol = symbol self.RSI = rsi #def Regression(self): # self.alphas_betas = {'GOLD':[a,b],'TSLA':[a,b],'TREE':[a,b],'YELP':[a,b],'RYN':[a,b]} # alpha_beta = self.alphas_betas[str(symbol)] # alpha = alpha_beta[0] # beta = alpha_beta[1] # ab_list = [results.intercept_,results.coef_[0,0], results.coef_[0,1]] # self.Debug(ab_list) # symbol = df['Stock'].iloc[0] # self.alphas_betas[symbol] = ab_list #IS Curve #returns_dfs = pd.DataFrame(new_row[3]) #ERROR #scores = [] #model_scores = [] #for df in returns_dfs: # model_one = df[["Year1"]].astype(float) # model_two = df[["Year1", "Year2"]].astype(float) # model_three = df[["Year1", "Year2", "Year3"]].astype(float) # y = df[["Returns"]].astype(float) # models = (model_one, model_two, model_three) # for x in models: # regression_model = linear_model.LinearRegression() # results_one = regression_model.fit(x,y) # model_score = results_one.score(x,y) # model_scores.append(scores) # scores = [] #models_avg=[] #avg = 0 #for i in range (0,2): # for j in range (0,5): # avg = avg + model_scores[j][i] # avg = avg / 5 # models_avg.append(avg) # avg = 0 #print(models_avg) #df = pd.DataFrame(models_avg, columns=['avgerror']) #df.plot()