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()