Overall Statistics |
Total Trades 3 Average Win 0% Average Loss -0.02% Compounding Annual Return 1.351% Drawdown 9.800% Expectancy -1 Net Profit 2.834% Sharpe Ratio 0.196 Probabilistic Sharpe Ratio 8.147% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha 0.008 Beta 0.023 Annual Standard Deviation 0.055 Annual Variance 0.003 Information Ratio -0.595 Tracking Error 0.213 Treynor Ratio 0.469 Total Fees $0.00 Estimated Strategy Capacity $1100000.00 Lowest Capacity Asset EURUSD 8G |
from datetime import timedelta from AlgorithmImports import * #from params import tp,sl STOCK = "EURUSD" class DayOpenEma(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 2, 1) # Set Start Date self.SetEndDate(2022, 3, 1) # Set End Date self.SetCash(10000) # Set Strategy Cash #self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.AddForex(STOCK, Resolution.Minute) #constructing 3h candles self.Consolidate(STOCK,timedelta(hours=3),self.OnThreeHourCandle) self.ema = self.EMA(STOCK,72,Resolution.Hour) # warming up the ema self.SetWarmup(72, Resolution.Hour) overlayPlot = Chart("Overlay Plot") self.AddChart(overlayPlot) overlayPlot.AddSeries(Series(STOCK, SeriesType.Line, 0)) overlayPlot.AddSeries(Series("EMA",SeriesType.Line, 0)) overlayPlot.AddSeries(Series("Day Open", SeriesType.Line, 0)) overlayPlot.AddSeries(Series("BUY", SeriesType.Scatter, "$", Color.Green, ScatterMarkerSymbol.Triangle)) overlayPlot.AddSeries(Series("SELL", SeriesType.Scatter, "$", Color.Red, ScatterMarkerSymbol.TriangleDown)) #self.tp = float(self.GetParameter("tp",0.5)) #self.sl = float(self.GetParameter("sl",0.25)) #self.Log(self.tp) #self.Log(self.sl) self.tp = 80 self.sl = 40 # used to create daily open self.previous_day = 0 self.day_open = 0 # used to create bracket orders self.entry_ticket = None self.tp_order = None self.sl_order = None # used to cancel the limit order after 24h self.entry_ticket_time = None self.order_timer = False self.previous_close = None # this thing is here because quantconnect gets angry if the price # has more than 6 numbers in it # when it gets angry it does a manual conversion and somehow that # conversion creates a bug when placing tp and sl orders @staticmethod def round_price(num): return round(num, 6-(len(str(num).split(".")[0]))) # handles the orders def OnOrderEvent(self, orderEvent): if orderEvent.Status != OrderStatus.Filled: return if self.entry_ticket is not None: # if main order is filled if orderEvent.OrderId == self.entry_ticket.OrderId: # cancelling the 24h order expiration self.order_timer = False self.entry_ticket_time = None # getting price and quantity of the fill price = self.round_price(orderEvent.FillPrice) quantity = self.entry_ticket.Quantity #self.Log(str(self.Time)) #self.Log("Fill Price: "+str(price)) #self.Log("Price: "+str(self.Securities[STOCK].Price)) self.Plot("Overlay Plot", "BUY", price-0.005) # placing TP and SL self.tp_order = self.LimitOrder(STOCK, -quantity, self.round_price(price*(1+self.tp/10000))) self.sl_order = self.StopMarketOrder(STOCK, -quantity, self.round_price(price*(1-self.sl/10000))) # if TP or SL order is filled else: price = orderEvent.FillPrice if orderEvent.FillQuantity > 0: self.Plot("Overlay Plot", "BUY", price-0.005) else: self.Plot("Overlay Plot", "SELL", price+0.005) self.Transactions.CancelOpenOrders(STOCK) self.entry_ticket = None # cancels orders, closes positions and resets bools def ResetEverything(self): # cancelling the orders self.Transactions.CancelOpenOrders(STOCK) # resetting the orders self.entry_ticket = None self.tp_order = None self.sl_order = None # liquidating position if self.Portfolio.Invested: self.Liquidate(STOCK) # timer is stopped self.entry_ticket_time = None self.order_timer = False # every 3h candle def OnThreeHourCandle(self,data): # getting the data candleOpen = self.previous_close candleClose = round(self.Securities[STOCK].Price,5) self.previous_close = candleClose #self.Log("Price: "+str(self.Securities[STOCK].Price)) # warming up the ema indicator if self.IsWarmingUp: return candleTime = self.Time ema = round(self.ema.Current.Value,5) dayOpen = self.day_open # position is 1 when we are long, 0 when nothing and -1 when short position = 0 if self.entry_ticket is not None: if self.entry_ticket.Quantity > 0: position = 1 if self.entry_ticket.Quantity < 0: position = -1 # creating day open if candleTime.day != self.previous_day: self.previous_day = candleTime.day self.day_open = candleOpen dayOpen = candleOpen # showing the data self.Plot("Overlay Plot", STOCK, candleClose) self.Plot("Overlay Plot", "EMA", ema) self.Plot("Overlay Plot", "Day Open", dayOpen) #self.Plot("Overlay Plot", "Position", position) #self.Log("Candle Open:" + str(candleOpen)) #self.Log("Candle Close:" + str(candleClose)) #self.Log("EMA:" + str(ema)) #self.Log("Day Open:" + str(self.dayOpen)) # handles the order expiration if self.order_timer: # if todays day is greater than the day of the order # if today hour is equal or bigger than the hour of the order # means that 24 hours have passed from the order submission to now if candleTime.day > self.entry_ticket_time.day: if candleTime.hour >= self.entry_ticket_time.hour: # the order is cancelled self.Transactions.CancelOpenOrders(STOCK) # order is removed self.entry_ticket = None # order timer is cancelled self.order_timer = False self.entry_ticket_time = None if not self.Portfolio.Invested: # short signal if candleClose > dayOpen and candleClose > ema: # SIGNAL CANDLE SHORT TRIGGERED self.ResetEverything() candleRange = round(Math.Abs(candleOpen - candleClose),5) limitPrice = self.round_price(candleClose + 0.25 * candleRange) quantity = self.CalculateOrderQuantity(STOCK, 1) self.entry_ticket = self.LimitOrder(STOCK, -quantity, limitPrice) self.entry_ticket_time = candleTime self.order_timer = True #self.Log("Open: "+str(candleOpen)) #self.Log("Close: "+str(candleClose)) #self.Log("Candle Range: "+ str(candleRange)) #self.Log("Long opened with limit: " + str(limitPrice))