Overall Statistics |
Total Orders 2689 Average Win 0.48% Average Loss -0.29% Compounding Annual Return 19.631% Drawdown 17.600% Expectancy 0.265 Start Equity 100000 End Equity 236479.8 Net Profit 136.480% Sharpe Ratio 0.743 Sortino Ratio 1.359 Probabilistic Sharpe Ratio 29.870% Loss Rate 52% Win Rate 48% Profit-Loss Ratio 1.66 Alpha 0.132 Beta -0.128 Annual Standard Deviation 0.162 Annual Variance 0.026 Information Ratio 0.107 Tracking Error 0.256 Treynor Ratio -0.938 Total Fees $6295.20 Estimated Strategy Capacity $420000000.00 Lowest Capacity Asset ES YLZ9Z50BJE2P Portfolio Turnover 169.84% |
from AlgorithmImports import * class DailyESFutures(QCAlgorithm): def Initialize(self): # Set the start and end dates for the backtest self.SetStartDate(2020, 1, 1) self.SetEndDate(2024, 10, 20) # Set the initial cash balance for the algorithm self.SetCash(100000) # Add the S&P 500 E-mini futures contract to trade futureES = self.AddFuture(Futures.Indices.SP500EMini, Resolution.Minute) # Filter to select the nearest expiring contract, up to 3 months out futureES.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 = 9 # 5-minute SMA period self.sma_30min_period = 27 # 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.TradeES)) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15, 59), Action(self.SellES)) 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 TradeES(self): # Only trade if we have a contract symbol and we are not already invested if self.contractSymbol and not self.Portfolio.Invested: # Make sure both SMAs are ready (i.e., enough data points are available) if self.sma_5min.IsReady and self.sma_30min.IsReady: # Buy if 5-minute SMA is above the 30-minute SMA (bullish signal) if self.sma_5min.Current.Value > self.sma_30min.Current.Value: 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}") else: # Short if 5-minute SMA is below the 30-minute SMA (bearish signal) 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 SellES(self): # If invested in the contract, sell everything 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}")