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