| Overall Statistics |
|
Total Orders 1390 Average Win 0.71% Average Loss -0.39% Compounding Annual Return 30.336% Drawdown 14.500% Expectancy 0.534 Start Equity 100000 End Equity 352505.6 Net Profit 252.506% Sharpe Ratio 1.27 Sortino Ratio 1.487 Probabilistic Sharpe Ratio 85.217% Loss Rate 45% Win Rate 55% Profit-Loss Ratio 1.79 Alpha 0.167 Beta 0.233 Annual Standard Deviation 0.148 Annual Variance 0.022 Information Ratio 0.5 Tracking Error 0.197 Treynor Ratio 0.808 Total Fees $3259.40 Estimated Strategy Capacity $190000000.00 Lowest Capacity Asset NQ YOGVNNAOI1OH Portfolio Turnover 102.43% |
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 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 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}")
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}")