Overall Statistics |
Total Orders 2350 Average Win 0.28% Average Loss -0.29% Compounding Annual Return 0.636% Drawdown 8.700% Expectancy 0.012 Start Equity 100000 End Equity 103097.5 Net Profit 3.098% Sharpe Ratio -0.384 Sortino Ratio -0.44 Probabilistic Sharpe Ratio 0.954% Loss Rate 49% Win Rate 51% Profit-Loss Ratio 0.97 Alpha -0.023 Beta 0.035 Annual Standard Deviation 0.052 Annual Variance 0.003 Information Ratio -0.63 Tracking Error 0.178 Treynor Ratio -0.573 Total Fees $5052.50 Estimated Strategy Capacity $140000000.00 Lowest Capacity Asset NQ YOGVNNAOI1OH Portfolio Turnover 368.83% |
from AlgorithmImports import * class DailyNQFutures(QCAlgorithm): def Initialize(self): # Set the start and end dates for the backtest self.SetStartDate(2020, 1, 1) #self.SetEndDate(2024, 10, 1) # Set the initial cash balance for the algorithm self.SetCash(100000) # Add the Nasdaq 100 E-mini futures contract to trade futureNQ = self.AddFuture(Futures.Indices.NASDAQ100EMini, Resolution.Minute) # Filter to select contracts that expire within 90 days from today futureNQ.SetFilter(timedelta(0), timedelta(90)) # Initialize the contract symbol to None (will be updated later) self.contractSymbol = None # Set the parameters for the SMA periods self.sma_5min_period = 7 # 5-minute SMA period self.sma_30min_period = 21 # 30-minute SMA period # Define the indicators (will be set up later) self.sma_5min = None self.sma_30min = None # Schedule the daily buy/sell event (check for weekdays and market open inside methods) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15, 54), Action(self.TradeNQ)) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15, 59), Action(self.SellNQ)) def OnData(self, slice): # Iterate through future contracts in the slice (market data for the current time step) for chain in slice.FutureChains: contracts = list(chain.Value) if len(contracts) > 0: # Sort the contracts by expiration date nearest_contract = sorted(contracts, key=lambda x: x.Expiry)[0] # Check if the current contract is expiring in less than 4 days if nearest_contract.Expiry - self.Time < timedelta(days=4): # Ensure there is a next contract available if len(contracts) > 1: next_contract = sorted(contracts, key=lambda x: x.Expiry)[1] if self.contractSymbol != next_contract.Symbol: self.contractSymbol = next_contract.Symbol self.SetupIndicators(self.contractSymbol) self.Debug(f"Rolled to new contract: {self.contractSymbol}, Expiration: {next_contract.Expiry}") else: # If not rolling, just track the nearest contract if self.contractSymbol != nearest_contract.Symbol: self.contractSymbol = nearest_contract.Symbol self.SetupIndicators(self.contractSymbol) def SetupIndicators(self, symbol): # Set up the 5-minute and 30-minute SMA indicators for the given contract symbol self.sma_5min = self.SMA(symbol, self.sma_5min_period, Resolution.Minute) self.sma_30min = self.SMA(symbol, self.sma_30min_period, Resolution.Minute) def TradeNQ(self): # Only trade if it's a weekday, the market is open, and we have a contract symbol if self.Time.weekday() < 5: # 0 = Monday, 4 = Friday if self.contractSymbol and self.IsMarketOpen(self.contractSymbol): # Make sure both SMAs are ready (i.e., enough data points are available) if self.sma_5min.IsReady and self.sma_30min.IsReady: # Check current invested position current_position = self.Portfolio[self.contractSymbol].Quantity # Long if 5-minute SMA is above the 30-minute SMA (bullish signal) if self.sma_5min.Current.Value > self.sma_30min.Current.Value: if current_position <= 0: # If not already long, buy self.MarketOrder(self.contractSymbol, 1) # Buy 1 contract self.Debug(f"Bought 1 contract at {self.Time}, 5-min SMA: {self.sma_5min.Current.Value}, 30-min SMA: {self.sma_30min.Current.Value}") # Short if 5-minute SMA is below the 30-minute SMA (bearish signal) elif self.sma_5min.Current.Value < self.sma_30min.Current.Value: if current_position >= 0: # If not already short, sell self.MarketOrder(self.contractSymbol, -1) # Short 1 contract self.Debug(f"Shorted 1 contract at {self.Time}, 5-min SMA: {self.sma_5min.Current.Value}, 30-min SMA: {self.sma_30min.Current.Value}") def SellNQ(self): # Only liquidate if it's a weekday, the market is open, and we have a contract symbol if self.Time.weekday() < 5: # 0 = Monday, 4 = Friday if self.contractSymbol and self.IsMarketOpen(self.contractSymbol): if self.Portfolio[self.contractSymbol].Invested: self.Liquidate(self.contractSymbol) self.Debug(f"Liquidated position at {self.Time}") def IsMarketOpen(self, symbol): # Check if the market for the given symbol is open at the current time exchange = self.Securities[symbol].Exchange return exchange.DateTimeIsOpen(self.Time)