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