Overall Statistics |
Total Orders 518 Average Win 2.04% Average Loss -1.99% Compounding Annual Return 8.008% Drawdown 37.100% Expectancy 0.403 Start Equity 10000 End Equity 71523.70 Net Profit 615.237% Sharpe Ratio 0.362 Sortino Ratio 0.188 Probabilistic Sharpe Ratio 0.236% Loss Rate 31% Win Rate 69% Profit-Loss Ratio 1.03 Alpha 0.022 Beta 0.236 Annual Standard Deviation 0.108 Annual Variance 0.012 Information Ratio -0.177 Tracking Error 0.195 Treynor Ratio 0.165 Total Fees $1247.31 Estimated Strategy Capacity $23000000.00 Lowest Capacity Asset QQQ RIWIV7K5Z9LX Portfolio Turnover 5.54% |
from AlgorithmImports import * class SimpleSpyClimber(QCAlgorithm): """ Inspired by quantitativo : https://www.quantitativo.com/p/turnaround-tuesdays-on-steroids Entry rules: ----------------------- - Today is Tuesday - Yesterday's close (Monday) was lower than Friday's - Friday's close was lower than Thursday's; - Go long at the opening. Exit rules ----------------------- - Exit the trade when the close is higher than yesterday's high. """ ## Initialize the algo ## ------------------------ def Initialize(self): # Init backtest params, etc self.ticker = "QQQ" # Ticker symbol to trade self.SetBenchmark(self.ticker) # Benchmark for reporting (buy and hold) self.SetStartDate(1999, 1, 1) # Backtest start date self.SetEndDate(2024, 7, 9) # Backtest end date self.SetCash(10000) # Starting portfolio balance # Subscrbe to an hourly data feed (hour bars) self.symbol = self.AddEquity(self.ticker, Resolution.Minute).symbol # Set up a rollingwindow to store consolidated daily bars self.dailyBars = RollingWindow[TradeBar](3) # Set up the daily bar consolidator self.dailyConsolidator = TradeBarConsolidator(timedelta(days=1)) self.dailyConsolidator.DataConsolidated += lambda _, dailyBar: self.dailyBars.add(dailyBar) self.SubscriptionManager.AddConsolidator(self.symbol, self.dailyConsolidator) # Schedule a weekly chron job (Tuesdays) to check for entries at the open self.Schedule.On(self.DateRules.Every(DayOfWeek.Tuesday), self.TimeRules.AfterMarketOpen(self.ticker, 5), self.CheckForEntry) # Schedule a daily chron job to check for exits at the open self.Schedule.On(self.DateRules.EveryDay(), \ self.TimeRules.AfterMarketOpen(self.ticker, 5), self.CheckForExit) ## Go long when: ## - Today is Tuesday ## - Yesterday's close (Monday) was lower than Friday's ## - Friday's close was lower than Thursday's ## ------------------------------ def CheckForEntry(self): if self.dailyBars.IsReady: if not self.Portfolio.Invested: monBar, friBar, thursBar = self.dailyBars[0],self.dailyBars[1],self.dailyBars[2] if( monBar.close < friBar.close < thursBar.close ): self.SetHoldings(self.ticker, 1) ## Exit the trade when the last daily close is higher than the previous day's high. ## ------------------------------------------------------------------------------- def CheckForExit(self): if self.Portfolio.Invested: if (self.dailyBars[0].close > self.dailyBars[1].high): self.Liquidate(tag=f"Exit @ last close > prev high: {self.dailyBars[0].close} > {self.dailyBars[1].high}")