Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
class DataTrader30minEURUSDStrategy(QCAlgorithm):

    def Initialize(self):
        # Define conditions for the backtest
        self.SetStartDate(2020, 1, 1)  # Set Start Date
        self.SetEndDate(2020, 1, 31) # Set End Date
        self.SetCash(5000)  # Set Strategy Cash
        
        # Define the currency pair to use to trade and set leverage to 2
        self.pair = self.AddForex("EURUSD", Resolution.Minute, Market.Oanda).Symbol
        
        # Define Broker to be used for trading
        self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
        #self.SetSecurityInitializer(self.CustomSecurityInitializer)
        #self.Securities[self.pair].SetLeverage(200)
        
        # Create 30 min consolidator
        thirtyMinuteConsolidator = QuoteBarConsolidator(timedelta(minutes=30))
        thirtyMinuteConsolidator.DataConsolidated += self.thirtyMinuteHandler
        self.SubscriptionManager.AddConsolidator(self.pair, thirtyMinuteConsolidator)
        
        # Define the Indicators needed for the strategy
        self.sto30min = Stochastic(14, 14, 3)
        self.rsi30min = RelativeStrengthIndex(14, MovingAverageType.Simple)
        self.macd30min = MovingAverageConvergenceDivergence(12, 26, 9, MovingAverageType.Exponential)
        self.atr30min = AverageTrueRange(14)
        
        # Create 10 period Rolling Windows for all the parameters we will need
        self.rsi30minWin = RollingWindow[float](10)
        self.macd30minHistWin = RollingWindow[float](10)
        self.stoK30minWin = RollingWindow[float](10)
        self.stoD30minWin = RollingWindow[float](10)
        self.atr30minWin = RollingWindow[float](10)
        self.price30minWin = RollingWindow[float](10)
        
        # Set the warm-up time
        self.SetWarmUp(10)
        
        # Create placeholders for the orders
        self.currentOrder = None
        self.stopLossOrder = None
        self.takeProfitOrder = None
        orderQuantity = 0
    
    
    def thirtyMinuteHandler(self, sender, bar):
        
        # Check if Stochastic Indicator is ready to start populating the Rolling Window
        if not self.macd30min.IsReady:
            return
        else:
            # Update all the indicators
            self.sto30min.Update(bar.EndTime, bar.Close)
            self.rsi30min.Update(bar.EndTime, bar.Close)
            self.macd30min.Update(bar.EndTime, bar.Close)
            self.atr30min.Update(bar.EndTime, bar.Close)
        
            # Update all the Rolling Windows
            self.rsi30minWin.Add(self.rsi30min.Current.Value)
            self.macd30minHistWin.Add(self.macd30min.Histogram.Current.Value)
            self.stoK30minWin.Add(self.sto30min.StochK.Current.Value)
            self.stoD30minWin.Add(self.sto30min.StochD.Current.Value)
            self.atr30minWin.Add(self.atr30min.Current.Value)
            self.price30minWin.Add(bar.Close)
        
        
    def OnData(self, data):
    
        pass    
        # Check if Stochastic Indicator is ready to start populating the Rolling Window
        if not self.macd30min.IsReady:
            return
        #else:
        #    self.stoKWin.Add(self.sto.StochK.Current.Value)
        #    self.stoDWin.Add(self.sto.StochD.Current.Value)
        #    self.rsiWin.Add(self.rsi.Current.Value)
        #    self.macdHistWin.Add(self.macd.Histogram.Current.Value)
        #    self.atrWin.Add(self.atr.Current.Value)
        #    self.priceWin.Add(data[self.pair].Close)
        
        # Let's define the entry and exit logic
        # Check if the Rolling Windows are ready (using the method)
        if self.stoK30minWin.IsReady and self.stoD30minWin.IsReady:
            
            # We want to hold only one position at the time for each currency pair
            if not self.Portfolio[self.pair].Invested:
            
            
                # The algo should take a Long position if RSI >50 and the MACD Histogram is > 0
                if self.rsi30min.Current.Value > 50 and self.rsi30minWin[1] < 50 and self.macd30min.Histogram.Current.Value > 0:
                
                    # The algo should take a Long position if both sto K & D are between 20 and 80
                    if self.sto30min.StochK.Current.Value > 20 and self.sto30min.StochK.Current.Value < 80 and self.sto30min.StochD.Current.Value > 20 and self.sto30min.StochD.Current.Value < 80:
                
                        # Looping through the Rolling Window we'll see if the crossover happened from the oversold (< 20) or the overbought (>80)
                        for i in range(1, len(list(self.stoK30minWin))):
                            
                            # Here we check if the crossover happened from below to enter a long position
                            if self.stoK30minWin[i-1] > 20 and self.stoK30minWin[i] < 20:
                                
                                for i in range (1, len(list(self.stoD30minWin))):
                                    # Here we check if the crossover happened from below to enter a long position
                                    if self.stoD30minWin[i-1] > 20 and self.stoD30minWin[i] < 20:
                                
                                
                                        # Define order quantity, entry price and exit prices
                                        orderQuantity = self.CalculateOrderQuantity(self.pair, 0.02)
                                        entryPrice = data[self.pair].Close
                                        longTakeProfitPrice = entryPrice + (1.5 * self.atr30min.Current.Value)
                                        longStopLossPrice = entryPrice - (1 * self.atr30min.Current.Value)
                    
                                        # Place Order
                                        self.currentOrder = self.MarketOrder(self.pair, orderQuantity)
                    
                                        # Stop Loss Order
                                        self.stopLossOrder = self.StopMarketOrder(self.pair, -orderQuantity, longStopLossPrice)
                    
                                        # Take Profit Order
                                        self.takeProfitOrder = self.LimitOrder(self.pair, -orderQuantity, longTakeProfitPrice)
                    
                                        # Print some useful information for the Log
                                        self.Log(" ")
                                        self.Log("Enter Long Position")
                                        self.Log("Stoch K Value: " + str(self.sto30min.StochK.Current.Value))
                                        self.Log("Stoch D Value: " + str(self.sto30min.StochD.Current.Value))
                                        self.Log("RSI: " + str(self.rsi30min.Current.Value))
                                        self.Log("MACD Histogram: " + str(self.macd30min.Histogram.Current.Value))
                                        self.Log("ATR: " + str(self.atr30min.Current.Value))
                                        self.Log("Entry Price: " + str(entryPrice))
                                        self.Log("Take Profit Price: " + str(longTakeProfitPrice))
                                        self.Log("Stop Loss Price: " + str(longStopLossPrice))
                                        self.Log("Order Quantity: " + str(orderQuantity))
                            
                            
    #            # The algo should take a Short position if RSI < 50 and the MACD Histogram is < 0
    #            elif self.rsi30min.Current.Value < 50 and self.rsi30minWin[1] > 50 and self.macd30min.Histogram.Current.Value < 0:
                
    #                # The algo should take a Long position if both sto K & D are between 20 and 80
    #                if self.sto30min.StochK.Current.Value > 20 and self.sto30min.StochK.Current.Value < 80 and self.sto30min.StochD.Current.Value > 20 and self.sto30min.StochD.Current.Value < 80:
                    
    #                    # Looping through the Rolling Window we'll see if the crossover happened from the oversold (< 20) or the overbought (>80)
    #                    for i in range(1, len(list(self.stoK30minWin))):
                            
    #                        # Here we check if the crossover happened from above to enter a short position    
    #                        if self.stoK30minWin[i-1] < 80 and self.stoK30minWin[i] > 80:
                                
    #                            for i in range (1, len(list(self.stoD30minWin))):
    #                                # Here we check if the crossover happened from below to enter a long position
    #                                if self.stoD30minWin[i-1] < 80 and self.stoD30minWin[i] > 80:
                        
    #                                    # Define order quantity, entry price and exit prices
    #                                    orderQuantity = self.CalculateOrderQuantity(self.pair, 0.02)
    #                                    entryPrice = data[self.pair].Close
    #                                    shortTakeProfitPrice = entryPrice - (1.5 * self.atr30min.Current.Value)
    #                                    shortStopLossPrice = entryPrice + (1 * self.atr30min.Current.Value)
                    
    #                                    # Place Order
    #                                    self.currentOrder = self.MarketOrder(self.pair, -orderQuantity)
                    
    #                                    # Stop Loss Order
    #                                    self.stopLossOrder = self.StopMarketOrder(self.pair, orderQuantity, shortStopLossPrice)
                    
    #                                    # Take Profit Order
    #                                    self.takeProfitOrder = self.LimitOrder(self.pair, orderQuantity, shortTakeProfitPrice)
                    
    #                                    # Print some useful information for the Log
    #                                    self.Log(" ")
    #                                    self.Log("Enter Short Position")
    #                                    self.Log("Stoch K Value: " + str(self.sto30min.StochK.Current.Value))
    #                                    self.Log("Stoch D Value: " + str(self.sto30min.StochD.Current.Value))
    #                                    self.Log("RSI: " + str(self.rsi30min.Current.Value))
    #                                    self.Log("MACD Histogram: " + str(self.macd30min.Histogram.Current.Value))
    #                                    self.Log("ATR: " + str(self.atr30min.Current.Value))
    #                                    self.Log("Entry Price: " + str(entryPrice))
    #                                    self.Log("Take Profit Price: " + str(shortTakeProfitPrice))
    #                                    self.Log("Stop Loss Price: " + str(shortStopLossPrice))
    #                                    self.Log("Order Quantity: " + str(orderQuantity))
                        
                
            
        
    def OnOrderEvent(self, orderEvent):
        # Ignore events that are not closed
        if orderEvent.Status != OrderStatus.Filled:
            return
        
        # Sanity check
        if self.takeProfitOrder == None or self.stopLossOrder == None:
            return
        
        filledOrderId = orderEvent.OrderId
        
        # If takeProfitOrder was filled, cancel stopLossOrder
        if self.takeProfitOrder.OrderId == filledOrderId and orderEvent.Status == OrderStatus.Filled:
            self.stopLossOrder.Cancel()
            
        # If stopLossOrder was filled, cancel takeProfitOrder
        if self.stopLossOrder.OrderId == filledOrderId and orderEvent.Status == OrderStatus.Filled:
            self.takeProfitOrder.Cancel()