Overall Statistics
Total Trades
4360
Average Win
0.02%
Average Loss
-0.04%
Compounding Annual Return
-1.055%
Drawdown
2.000%
Expectancy
-0.017
Net Profit
-1.365%
Sharpe Ratio
-0.457
Probabilistic Sharpe Ratio
2.159%
Loss Rate
39%
Win Rate
61%
Profit-Loss Ratio
0.61
Alpha
0
Beta
0
Annual Standard Deviation
0.016
Annual Variance
0
Information Ratio
-0.457
Tracking Error
0.016
Treynor Ratio
0
Total Fees
$9374.00
Estimated Strategy Capacity
$33000000.00
Lowest Capacity Asset
NQ Y9CDFY0C6TXD
Portfolio Turnover
234.54%
#region imports
import pytz
from AlgorithmImports import *
from datetime import time
#endregion
class SimpleNQExample(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2022, 1, 1)  # Set Start Date
        self.SetEndDate(2023, 4, 18)  
        self.SetCash(1000000)  # Set Strategy Cash
        
        self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
        self.SetTimeZone("America/New_York")

        # Set up the future we're looking at
        future = Futures.Indices.NASDAQ100EMini
        self._continuousContract = self.AddFuture(future,
                                                  dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
                                                  dataMappingMode = DataMappingMode.OpenInterest,
                                                  contractDepthOffset = 0,
                                                  extendedMarketHours = True)
        self.commod = self._continuousContract.Symbol
        
        self._continuousContract.SetFilter(timedelta(days=1), timedelta(days=60))


        # Set up a short-period EMA on 1-minute bar
        qqqequityconsolidator = TradeBarConsolidator(timedelta(minutes = 1))
        qqqequityconsolidator.DataConsolidated += self.qqqequityHandler        
        self.qqqema = ExponentialMovingAverage(9)
        self.RegisterIndicator(self.commod, self.qqqema, qqqequityconsolidator)
        self.qqqema_past = IndicatorExtensions.Of(Delay(1), self.qqqema)
        self.qqqema_slope = IndicatorExtensions.Minus(self.qqqema, self.qqqema_past)

        # Set up a long-period EMA on 1-minute bar      
        self.qqqemalong = ExponentialMovingAverage(150)
        self.RegisterIndicator(self.commod, self.qqqemalong, qqqequityconsolidator)
        self.qqqemalong_past = IndicatorExtensions.Of(Delay(1), self.qqqemalong)
        self.qqqemalong_slope = IndicatorExtensions.Minus(self.qqqemalong, self.qqqemalong_past)

        # Set up a 14-period RSI on 1-minute bar
        self.qqqrsi = RelativeStrengthIndex(14)
        self.RegisterIndicator(self.commod, self.qqqrsi, qqqequityconsolidator)
        self.sma_qqqrsi = IndicatorExtensions.SMA(self.qqqrsi, 5) 
        self.sma_qqqrsi_past = IndicatorExtensions.Of(Delay(1), self.sma_qqqrsi)
        self.qqqrsi_slope = IndicatorExtensions.Minus(self.sma_qqqrsi, self.sma_qqqrsi_past)
        
        # Set up a Momentum indicator on 1-minute bar
        self.qqqmomentum = Momentum(9)
        self.RegisterIndicator(self.commod, self.qqqmomentum, qqqequityconsolidator)
        self.ema_qqqmom = IndicatorExtensions.EMA(self.qqqmomentum, 3) 
        self.ema_qqqmom_past = IndicatorExtensions.Of(Delay(1), self.ema_qqqmom)
        self.qqqmom_slope = IndicatorExtensions.Minus(self.ema_qqqmom, self.ema_qqqmom_past)

        # Set up an Ultimate Oscillator indicator on 1-minute bar
        self.qqqUA = UltimateOscillator(7, 14, 28)
        self.RegisterIndicator(self.commod, self.qqqUA, qqqequityconsolidator)
        self.ema_qqqUA = IndicatorExtensions.EMA(self.qqqUA, 3) 
        self.ema_qqqUA_past = IndicatorExtensions.Of(Delay(1), self.ema_qqqUA)
        self.qqqUA_slope = IndicatorExtensions.Minus(self.ema_qqqUA, self.ema_qqqUA_past)

        self.qqqequityslopeshort = dict()
        self.qqqequityslopeshort[0] = 0

        self.emaslopelong = dict()
        self.emaslopelong[0] = 0

        self.qqqslope_rsi = dict()
        self.qqqslope_rsi[0] = 0

        self.qqqslope_mom = dict()
        self.qqqslope_mom[0] = 0
       
        self.qqqslope_UA = dict()
        self.qqqslope_UA[0] = 0

        self.tradingnumber = dict()
        self.tradingnumber[0] = 0 

    def emaUpdated(self, sender, updated):
        '''Adds updated values to rolling window'''
        self.emaWin.Add(updated)    

    def qqqequityHandler(self, sender, consolidated):
        if self.IsWarmingUp or not self.qqqema_slope.IsReady: return 
        
        self.qqqequityslopeshort[0] = self.qqqema_slope.Current.Value
        self.emaslopelong[0] = self.qqqemalong_slope.Current.Value
        self.qqqslope_rsi[0] = self.qqqrsi_slope.Current.Value
        self.qqqslope_mom[0] = self.qqqmom_slope.Current.Value
        self.qqqslope_UA[0] = self.qqqUA_slope.Current.Value
        
    def OnData(self, data: Slice): 
        if not data.ContainsKey(self.commod):
            return        
        
        futures_invested = [holding.Symbol for holding in self.Portfolio.Values if holding.Type == SecurityType.Future and holding.Invested]
        futures_invested_short = [(symbol, holding.Quantity) for symbol, holding in self.Portfolio.items() if holding.Type == SecurityType.Future and holding.Symbol.SecurityType == SecurityType.Future and holding.IsShort]
        futures_invested_long = [(symbol, holding.Quantity) for symbol, holding in self.Portfolio.items() if holding.Type == SecurityType.Future and holding.Symbol.SecurityType == SecurityType.Future and holding.IsLong]
        futures_invested_long1 = [symbol for symbol, holding in self.Portfolio.items() if holding.Type == SecurityType.Future and holding.Symbol.SecurityType == SecurityType.Future and holding.IsLong]
        futures_invested_short1 = [symbol for symbol, holding in self.Portfolio.items() if holding.Type == SecurityType.Future and holding.Symbol.SecurityType == SecurityType.Future and holding.IsShort]

        slopelong = self.emaslopelong[0]
        slopeshort = self.qqqequityslopeshort[0]
        slope_rsi = self.qqqslope_rsi[0] 
        momslope = self.qqqslope_mom[0]
        UAslope = self.qqqslope_UA[0]
        RSI = self.sma_qqqrsi.Current.Value
        

        current_time = self.Time.time()

        trading_start = time(8, 0)
        trading_end = time(19, 30)
        #trading_allowed = trading_start <= current_time <= trading_end
        trading_not_allowed = current_time > trading_end
        trading_allowed = trading_start <= current_time <= trading_end and self.Time.weekday() != 6
        
        if self.tradingnumber[0] == 0 and RSI < 30:
            self.tradingnumber[0] = 1

        if self.tradingnumber[0] == 0 and RSI > 70:
            self.tradingnumber[0] = 3


        if trading_allowed and self.tradingnumber[0] == 1:
            if slopeshort > 0 and slope_rsi > 0 and not futures_invested_short1:
                    self.MarketOrder(self._continuousContract.Mapped, -1)
                    self.Log("Going long")
                    self.tradingnumber[0] = 2

        if self.tradingnumber[0] == 2 and slopeshort < 0 and slope_rsi < 0:
            for symbol, quantity in futures_invested_short:
                self.MarketOrder(symbol, -quantity)
                self.tradingnumber[0] = 0


        if trading_allowed and self.tradingnumber[0] == 3:
            if slopeshort < 0 and slope_rsi < 0 and not futures_invested_long1:
                self.MarketOrder(self._continuousContract.Mapped, 1)
                self.Log("Going short")
                self.tradingnumber[0] = 4
        
        if self.tradingnumber[0] == 4 and slopeshort > 0 and slope_rsi > 0:
            for symbol, quantity in futures_invested_long:
                self.MarketOrder(symbol, -quantity)  # Liquidate the short position
                self.tradingnumber[0] = 0

        
        friday_close_time = time(16, 58)
        if self.Time.weekday() == 4 and current_time == friday_close_time:
            for symbol in futures_invested:
                self.MarketOrder(symbol, -self.Portfolio[symbol].Quantity)  # Liquidate the position
                self.tradingnumber[0] = 0

        #self.Log("10 EMA slope: {0}, 12RSI5SMA Slope: {1}, Histo: {2}".format(round(slope, 2), round(slope_rsi, 2), round(slope_macd_histogram, 2)))