| 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()