Overall Statistics |
Total Trades 196 Average Win 0.79% Average Loss -0.41% Compounding Annual Return -0.386% Drawdown 5.800% Expectancy -0.013 Net Profit -0.418% Sharpe Ratio -0.033 Probabilistic Sharpe Ratio 9.890% Loss Rate 66% Win Rate 34% Profit-Loss Ratio 1.93 Alpha 0.006 Beta -0.039 Annual Standard Deviation 0.048 Annual Variance 0.002 Information Ratio -0.66 Tracking Error 0.285 Treynor Ratio 0.04 Total Fees $0.00 Estimated Strategy Capacity $12000000.00 Lowest Capacity Asset EURCAD 8G |
from datetime import timedelta from AlgorithmImports import * #from params import tp,sl STOCK = "EURCAD" class DayOpenEma(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 2, 1) # Set Start Date self.SetEndDate(2021, 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)) #overlayPlot.AddSeries(Series("Position", SeriesType.Line, 1)) ''' #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)) # if order was long if quantity>0: 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 order was short if quantity<0: self.Plot("Overlay Plot", "SELL", 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) if ema == None or ema is None: return dayOpen = self.day_open # 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.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 there is no order or the position or order is short if self.entry_ticket is None: # long signal if candleClose > dayOpen and candleClose > ema: # SIGNAL CANDLE LONG TRIGGERED self.ResetEverything() candleRange = round(Math.Abs(candleClose - candleOpen),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))