Overall Statistics |
Total Orders 2757 Average Win 0.57% Average Loss -0.36% Compounding Annual Return 32.949% Drawdown 12.800% Expectancy 0.307 Start Equity 100000 End Equity 393492.2 Net Profit 293.492% Sharpe Ratio 1.046 Sortino Ratio 1.621 Probabilistic Sharpe Ratio 56.331% Loss Rate 49% Win Rate 51% Profit-Loss Ratio 1.55 Alpha 0.236 Beta -0.206 Annual Standard Deviation 0.207 Annual Variance 0.043 Information Ratio 0.422 Tracking Error 0.295 Treynor Ratio -1.049 Total Fees $6217.80 Estimated Strategy Capacity $120000000.00 Lowest Capacity Asset NQ YOGVNNAOI1OH Portfolio Turnover 158.56% |
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) # Apply Interactive Brokers Fee Model futureNQ.SetFeeModel(InteractiveBrokersFeeModel()) # Filter to select the nearest expiring contract, up to 3 months out 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 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 and select the nearest contract nearest_contract = sorted(contracts, key=lambda x: x.Expiry)[0] # If we don't already have this contract symbol, update it and set up indicators 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 we have a contract symbol if 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): # If invested in the contract, liquidate the position at the scheduled time if self.contractSymbol and self.Portfolio[self.contractSymbol].Invested: self.Liquidate(self.contractSymbol) self.Debug(f"Liquidated position at {self.Time}")