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