| Overall Statistics |
|
Total Trades 25328 Average Win 0.02% Average Loss -0.02% Compounding Annual Return -27.824% Drawdown 29.900% Expectancy -0.121 Net Profit -28.146% Sharpe Ratio -2.974 Probabilistic Sharpe Ratio 0.000% Loss Rate 56% Win Rate 44% Profit-Loss Ratio 1.00 Alpha -0.347 Beta 0.437 Annual Standard Deviation 0.092 Annual Variance 0.008 Information Ratio -4.463 Tracking Error 0.099 Treynor Ratio -0.624 Total Fees $25513.28 |
class CalibratedHorizontalCompensator(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019, 1, 30) # Set Start Date
self.SetCash(100000) # Set Strategy Cash
# Add SPY to set scheduled events
self.AddEquity("SPY", Resolution.Minute)
# Setting Universe
self.UniverseSettings.Resolution = Resolution.Minute
self.SetUniverseSelection(QC500UniverseSelectionModel())
# Dictionary to keep track of previous close for each symbol
self.previousClose = {}
# Dictionary to keep track of weekly cumulative performance for each symbol
self.performance = {}
# Our Scheduled Events
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 30), self.Rebalance)
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 1), self.OnMarketClose)
self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday) , self.TimeRules.BeforeMarketClose("SPY", 5), self.GetTopPerformers)
# list for top performers of week
self.top = []
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
symbol = security.Symbol
# Make a history call for symbol to get last closing price
if symbol not in self.previousClose:
history = self.History(symbol, 1, Resolution.Daily)
if not history.empty:
history = history.close.unstack(0)[symbol]
if not history.empty:
self.previousClose[symbol] = history[0]
# Remove symbols from previous close as they are removed from the universe
for security in changes.RemovedSecurities:
symbol = security.Symbol
self.previousClose.pop(symbol, None)
def Rebalance(self):
# Dictionary to keep track of percent change from last close
percentChange = {}
# Populate Dictionary
for symbol, previousClose in self.previousClose.items():
if self.CurrentSlice.ContainsKey(symbol):
price = self.CurrentSlice[symbol].Close
change = (price - previousClose)/previousClose
percentChange[symbol] = change
# Symbols under consideration
symbols = list(percentChange.keys())
# Sort symbols by percent change
sortedSymbols = sorted(symbols, key=lambda x : percentChange[x], reverse = True)
# Get top 50 symbols
selected = sortedSymbols[:50]
# Set holdings equally to those symbols
for symbol in selected:
self.SetHoldings(symbol, 1 / len(selected))
def OnMarketClose(self):
# Store cumulative performance for symbols in portfolio
for kvp in self.Portfolio:
symbol = kvp.Key
holding = kvp.Value
if holding.Invested:
if symbol not in self.performance:
self.performance[symbol] = holding.UnrealizedProfitPercent
else:
self.performance[symbol] = self.performance[symbol] + holding.UnrealizedProfitPercent
# Liquidate portfolio
self.Liquidate()
# Store new previous close values
for symbol in self.previousClose:
if self.CurrentSlice.ContainsKey(symbol):
self.previousClose[symbol] = self.CurrentSlice[symbol].Close
def GetTopPerformers(self):
# Symbols under consideration
symbols = list(self.performance.keys())
# Symbols sorted by performance
sortedSymbols = sorted(symbols, key=lambda x: self.performance[x], reverse=True)
# Top 10 performers
self.top = sortedSymbols[:10]
# Reset performances
self.performance = {}