| Overall Statistics |
|
Total Trades 6 Average Win 0.02% Average Loss -0.03% Compounding Annual Return 0.006% Drawdown 0.000% Expectancy 0.139 Net Profit 0.013% Sharpe Ratio 0.192 Probabilistic Sharpe Ratio 8.470% Loss Rate 33% Win Rate 67% Profit-Loss Ratio 0.71 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -0.572 Tracking Error 0.227 Treynor Ratio 7.739 Total Fees $6.67 |
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Data import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from System.Collections.Generic import List
class main(QCAlgorithm):
def Initialize(self):
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
self.SetStartDate(2018, 8, 20) #Set Start Date
self.SetEndDate(2020,11,18) #Set End Date
self.initialcash=1000000 #Set Strategy Cash
self.SetCash(self.initialcash)
self.singleStockAllocationInDollars= -10000 # - , (minus) means going short. -10000 means having a target of going short for an amount of 10000 $
self.PercentageOfPortfolioToAllocateToEachSecurity = self.singleStockAllocationInDollars/self.initialcash
self.SetBrokerageModel(BrokerageName.Alpaca)
self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x)))
self.UniverseSettings.Resolution = Resolution.Hour # Timeframe to trade
self.UniverseSettings.Leverage = 1
self.benchmark="SPY"
self.benchmark= self.AddEquity(self.benchmark, self.UniverseSettings.Resolution)
self.SPY_EMA = self.EMA("SPY", 20, Resolution.Daily) # Filter of Price of SPY should be > 20 EMA to favor long entries, you can change 20
self.SymbolDataDictionary = {}
self.AddUniverse(self.CoarseSelectionFunction)
# schedule an event to fire buys on a single day of the week, specifying hours and minutes
self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.At(15, 50), self.buy_time)
#schedule an event to Liquidate (exit all positions at the day and hours specified)
self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.At(9, 10), self.sell_time)
def buy_time(self):
for kvp in self.SymbolDataDictionary:
symbol=self.SymbolDataDictionary[kvp]
if self.benchmark.Price > self.SPY_EMA.Current.Value : # Here we do the check of the condition SPY should be over EMA 20 Price of SPY should be > 20 EMA to favor long entries
self.SetHoldings(kvp, self.PercentageOfPortfolioToAllocateToEachSecurity) #here the actual positions are initiated, in this case the symbols are 10, so every symbol receives 10% of the Portfolio. In this case being the cash 100000$ every stock gets an allocation of 10000$.
def sell_time(self):
self.Liquidate()
def CoarseSelectionFunction(self, coarse):
CoarseWithFundamental = [x for x in coarse if x.HasFundamentalData and x.Price > 1 and x.Price<50] #Price range, between 1 and 50 as in Excel spreadsheet example
sortedByVolume = sorted(CoarseWithFundamental, key=lambda x: x.DollarVolume, reverse=True)
# We are going to use a dictionary to refer the object that will keep the moving averages
for kvp in sortedByVolume:
if kvp.Symbol not in self.SymbolDataDictionary:
self.SymbolDataDictionary[kvp.Symbol]=SymbolData(kvp.Symbol)
instrument=self.SymbolDataDictionary[kvp.Symbol]
instrument.update(kvp.EndTime, kvp.AdjustedPrice, kvp.DollarVolume)
values = list(self.SymbolDataDictionary.values())
############################## Returns filter
values = [x for x in values if x.percentage_change > 0.15] # 0.10 means a 10% return, 0.15 means 15% and so on, you can change this
############################### Relative Volume filter
values = [x for x in values if x.relative_volume > 0.2] #you can change this
################################# RSI filter
values = [x for x in values if x.RSI_IS_OK]
################################# EMAs filter
values = [x for x in values if x.EMAS_ARE_OK]
return [ x.symbol for x in values] # return [ x.symbol for x in values[:20] ] this to constrain the number of stocks returned, in this case 20
def OnData(self, data):
#Take profit logic
if self.Portfolio.Invested:
if self.Portfolio.TotalPortfolioValue > self.initialcash* 1.05:# means a 5% take profit target, if the initial portfolio value is 100000 with 1.05 you will take profit when the value of portfolio is greater than 105 000 $.
self.Liquidate()
#Stop loss logic
if self.Portfolio.Invested:
if self.Portfolio.TotalPortfolioValue < self.initialcash*0.90: # means a 10% stop loss. In this case 0.9 means that the portfolio is valued a 90% of the original value, so if the initial value is 100 000 $ it means 90 000$, a 10% stop loss. if you set self.initialcash*0.5 means a 50% stop loss and so on.
self.Liquidate()
#Stop loss on a single instrument logic
if self.Portfolio.Invested:
for symbol in self.ActiveSecurities:
if self.Portfolio[symbol.Key].UnrealizedProfit < -5000: #This means a stop loss of $5000 for the relative security
self.Debug(str(self.Time) + 'Stopping loss due to Unrealized Profit ' + str(self.Portfolio[symbol.Key].UnrealizedProfit) + ' on symbol '+ str(symbol.Key))
self.Liquidate(symbol.Key)
class SymbolData(object):
def __init__(self, symbol):
self.symbol = symbol
self.EMA1 = ExponentialMovingAverage (2) #here we can decide the values of EMA1, you can change this
self.EMA2 = ExponentialMovingAverage (2) #here we can decide the values of EMA2, you can change this
self.RSI = RelativeStrengthIndex(200) #here we can decide the values of RSI, you can change this
self.PriceHistory = RollingWindow[float](2)# you can't change this
self.DollarVolumeHistory = RollingWindow[float](30)# you can't change this
self.percentage_change=0# you can't change this
self.relative_volume=0# you can't change this
self.EMAS_ARE_OK=False# you can't change this
self.RSI_IS_OK=False# you can't change this
def update(self, time, value, volume):
if self.EMA1.Update(time, value) and self.EMA2.Update(time, value):# you can't change this
EMA1 = self.EMA1.Current.Value# you can't change this
EMA2 = self.EMA2.Current.Value# you can't change this
self.EMAS_ARE_OK = value > EMA1 and value > EMA2# you can't change this
if self.RSI.Update(time, value):# you can't change this
RSI = self.RSI.Current.Value# you can't change this
self.RSI_IS_OK = value > RSI# you can't change this
self.PriceHistory.Add(value)
self.DollarVolumeHistory.Add(volume)
if self.PriceHistory.IsReady:# you can't change this
self.percentage_change = (self.PriceHistory[0]-self.PriceHistory[1])/self.PriceHistory[1]# you can't change this
if self.DollarVolumeHistory.IsReady:# you can't change this
todays_volume=self.DollarVolumeHistory[0]# you can't change this
thirtydaysvolume=0# you can't change this
for i in range(0,self.DollarVolumeHistory.Count-1):# you can't change this
thirtydaysvolume=self.DollarVolumeHistory[i]+thirtydaysvolume# you can't change this
averagethirtydaysvolume=thirtydaysvolume/30 #let's divide by 30 # you can't change this
self.relative_volume=(todays_volume-averagethirtydaysvolume)/averagethirtydaysvolume # you can't change this