| 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}")