| Overall Statistics |
|
Total Trades 4852 Average Win 0.01% Average Loss 0.00% Compounding Annual Return -46.270% Drawdown 9.800% Expectancy -0.994 Net Profit -9.816% Sharpe Ratio -5.309 Probabilistic Sharpe Ratio 0.000% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 2.93 Alpha -0.473 Beta 0.03 Annual Standard Deviation 0.091 Annual Variance 0.008 Information Ratio -0.333 Tracking Error 0.256 Treynor Ratio -16.365 Total Fees $4852.00 |
class HorizontalMultidimensionalThrustAssembly(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2018, 11, 1)
self.SetEndDate(2019, 1, 1)
self.SetCash(50000)
self.AddEquity("SPY", Resolution.Minute)
# Measures the change in SPY prices between 2 minutes
self.spyMomentum = self.MOMP("SPY", 2, Resolution.Minute)
# Measures the standard deviation in SPY prices in 24 hours
self.spySD = self.STD("SPY", 10080, Resolution.Minute)
# Measures the mean SPY momentum in 24 hours
self.spyMomentumMean = SimpleMovingAverage(10080)
# Performs the operation to update the SPY momentum mean indicator by piping spyMomentum into it
self.spyMomentum.Updated += self.OnSpyMomentum
# For tracking stats
self.longstopLossTicket = None
self.shortstopLossTicket = None
self.shorttakeProfitTicket = None
self.longtakeProfitTicket = None
self.noOfTrades = 0
self.noOfSL = 0
self.noOfTP = 0
self.daysInvested = 0
def OnData(self, data):
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
Arguments:
data: Slice object keyed by symbol containing the stock data
'''
if not self.spyMomentum.IsReady or not self.spySD.IsReady:
return
# Putting 1 percent of the portfolio in a trade
self.percentageOfPortfolioPerTrade = 0.01
self.noOfSDForSL = 0.1
self.noOfSDForTP = 10
# Purchasing quantities
self.price = self.Securities["SPY"].Close
self.quantity = self.percentageOfPortfolioPerTrade * self.Portfolio.TotalPortfolioValue / self.price
self.lotSize = self.Securities["SPY"].SymbolProperties.LotSize
self.quantity = round(self.quantity/self.lotSize) * self.lotSize
# Stop losses
self.longStopLoss = self.Securities["SPY"].Close - self.noOfSDForSL*self.spySD.Current.Value
self.shortStopLoss = self.Securities["SPY"].Close + self.noOfSDForSL*self.spySD.Current.Value
# Take Profits
self.longTakeProfit = self.Securities["SPY"].Close + self.noOfSDForTP*self.spySD.Current.Value
self.shortTakeProfit = self.Securities["SPY"].Close - self.noOfSDForTP*self.spySD.Current.Value
# The current change in price is greater than the mean change in price over 24 hours
if not self.Portfolio.Invested:
if self.spyMomentum.Current.Value > self.spyMomentumMean.Current.Value:
self.MarketOrder("SPY", self.quantity)
self.longstopLossTicket = self.StopMarketOrder("SPY", -self.quantity, self.longStopLoss)
self.longtakeProfitTicket = self.StopMarketOrder("SPY", -self.quantity, self.longTakeProfit)
self.noOfTrades += 1
elif self.spyMomentum.Current.Value < self.spyMomentumMean.Current.Value:
self.MarketOrder("SPY", -self.quantity)
self.shortstopLossTicket = self.StopMarketOrder("SPY", self.quantity, self.shortStopLoss)
self.shorttakeProfitTicket = self.StopMarketOrder("SPY", self.quantity, self.shortTakeProfit)
self.noOfTrades += 1
if self.noOfTrades > 0:
self.Debug(f"Number of trades so far: {self.noOfTrades}\n\
Percentage of trades stopped out: {round(self.noOfSL/self.noOfTrades, 5)}\n\
Percent of trades profitted out: {round(self.noOfTP/self.noOfTrades, 5)}\n\n")
def OnSpyMomentum(self, sender, updated):
if self.spyMomentum.IsReady:
self.spyMomentumMean.Update(self.Time, updated.Value)
def OnEndOfDay(self):
if self.Portfolio.Invested:
self.daysInvested += 1
if self.daysInvested >= 5:
self.Liquidate()
def OnOrderEvent(self, orderEvent):
if orderEvent.Status != OrderStatus.Filled:
return
#2. Check if we hit our stop loss (Compare the orderEvent.Id with the stopMarketTicket.OrderId)
# It's important to first check if the ticket isn't null (i.e. making sure it has been submitted)
if self.longstopLossTicket is not None and self.longstopLossTicket.OrderId == orderEvent.OrderId:
self.noOfSL += 1
self.longtakeProfitTicket.Cancel()
if self.shortstopLossTicket is not None and self.shortstopLossTicket.OrderId == orderEvent.OrderId:
self.noOfSL += 1
self.shorttakeProfitTicket.Cancel()
if self.shorttakeProfitTicket is not None and self.shorttakeProfitTicket.OrderId == orderEvent.OrderId:
self.noOfTP += 1
self.shortstopLossTicket.Cancel()
if self.longtakeProfitTicket is not None and self.longtakeProfitTicket.OrderId == orderEvent.OrderId:
self.noOfTP += 1
self.longstopLossTicket.Cancel()