Overall Statistics |
Total Trades 1929 Average Win 1.11% Average Loss -1.08% Compounding Annual Return 10.097% Drawdown 37.700% Expectancy 0.045 Net Profit 44.724% Sharpe Ratio 0.363 Sortino Ratio 0.42 Probabilistic Sharpe Ratio 9.354% Loss Rate 48% Win Rate 52% Profit-Loss Ratio 1.02 Alpha 0 Beta 0 Annual Standard Deviation 0.195 Annual Variance 0.038 Information Ratio 0.457 Tracking Error 0.195 Treynor Ratio 0 Total Fees $3958.19 Estimated Strategy Capacity $2100000.00 Lowest Capacity Asset QQQ RIWIV7K5Z9LX Portfolio Turnover 137.00% |
from AlgorithmImports import * class PivotBasedTradingAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 1, 1) # self.SetEndDate(2020, 1, 1) self.SetCash(100000) self.Debug(f"The algorithm time zone is set to: {self.TimeZone}") self.SetTimeZone("America/New_York") # Set brokerage model self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) # Add symbol with 5-minute resolution # Add symbol self.symbol = self.AddEquity("QQQ", Resolution.Minute).Symbol # Create our consolidator with a period of 30 mins consolidator = TradeBarConsolidator(timedelta(minutes=5)) consolidator.DataConsolidated += self.OnDataConsolidated self.SubscriptionManager.AddConsolidator(self.symbol, consolidator) # Get the last calendar day worth of daa at the specified resolution self.tradeBarHistory = self.History([self.symbol], timedelta(1), Resolution.Daily) # Schedule CalculatePivotPoints to run every trading day before market open self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.AfterMarketOpen(self.symbol, -10), self.CalculatePivotPoints) # Schedule function to liquidate 15 minutes before market close self.Schedule.On(self.DateRules.EveryDay(self.symbol), self.TimeRules.BeforeMarketClose(self.symbol, 15), self.LiquidatePosition) self.previousDayHigh = None self.previousDayLow = None self.previousDayClose = None # Initialize pivot point attributes self.r1 = None self.r2 = None self.s1 = None self.s2 = None def OnDataConsolidated(self, sender, bar): ''' This is called for each 5-minute bar of data. If the pivot points haven't been calculated yet (they are None), it returns early. If it's the first 5-minute bar of the day (9:30 AM), it calculates the pivot points. The trading logic checks if the current bar's closing price is greater than r1 to enter a long position or if it's less than r1 to exit the position. ''' # Calculate Pivot Points at the start of the trading day if bar.Time.hour == 9 and bar.Time.minute == 30: self.CalculatePivotPoints() self.Debug(f"Processing bar for {bar.EndTime}: Close={bar.Close}") # Skip if pivot points haven't been calculated yet if self.r1 is None or self.r2 is None or self.s1 is None or self.s2 is None: self.Debug(f"Pivot points not yet calculated {self.Time}") return self.Debug(f"Pivot points: R1={self.r1}, R2={self.r2}, S1={self.s1}, S2={self.s2}") # Trading logic if bar.Close > self.r1 and not self.Portfolio.Invested: self.Debug(f"Signal to go Long: 5m Close: {bar.Close} > R1: {self.r1}") self.SetHoldings(self.symbol, 1) # Long entry elif self.Portfolio.Invested and bar.Close < self.r1: self.Debug(f"Signal to go Close: 5m Close: {bar.Close} < R1: {self.r1}") self.Liquidate() # Exit position def CalculatePivotPoints(self): ''' Calculates the pivot points using the previous day's high, low, and close prices. This method is called at the beginning of the trading day to set the r1, r2, s1, and s2 values. ''' # Fetch historical data for the previous trading day tradeBarHistory = self.tradeBarHistory self.Debug(f"History Count: {len(tradeBarHistory)}") if not tradeBarHistory.empty: self.previousDayHigh = tradeBarHistory['high'][0] self.previousDayLow = tradeBarHistory['low'][0] self.previousDayClose = tradeBarHistory['close'][0] self.Debug(f"Stored previous day's OHLC: High={self.previousDayHigh}, Low={self.previousDayLow}, Close={self.previousDayClose}") else: self.Debug("History data is empty. Cannot store previous day's OHLC.") self.Debug(f"Previous High: {self.previousDayHigh}, Low: {self.previousDayLow}, Close: {self.previousDayClose}") if self.previousDayHigh is not None and self.previousDayLow is not None and self.previousDayClose is not None: p = (self.previousDayHigh + self.previousDayLow + self.previousDayClose) / 3 self.r1 = 2 * p - self.previousDayLow self.r2 = p + (self.previousDayHigh - self.previousDayLow) self.s1 = 2 * p - self.previousDayHigh self.s2 = p - (self.previousDayHigh - self.previousDayLow) self.Debug(f"Calculated Pivot Points - R1: {self.r1}, R2: {self.r2}, S1: {self.s1}, S2: {self.s2}") else: self.Debug("Previous day OHLC values not set. Cannot calculate pivot points.") def LiquidatePosition(self): ''' Liquidates any invested position 15 minutes before the market close. ''' # Liquidate 15 minutes before market close if self.Portfolio.Invested: self.Liquidate(self.symbol)