Overall Statistics |
Total Trades 36 Average Win 0.45% Average Loss -1.19% Compounding Annual Return -19.317% Drawdown 4.400% Expectancy -0.083 Net Profit -1.845% Sharpe Ratio -1.357 Probabilistic Sharpe Ratio 20.981% Loss Rate 33% Win Rate 67% Profit-Loss Ratio 0.38 Alpha -0.081 Beta -0.183 Annual Standard Deviation 0.114 Annual Variance 0.013 Information Ratio -3.176 Tracking Error 0.174 Treynor Ratio 0.843 Total Fees $0.00 |
from datetime import datetime,timedelta import numpy as np class ReversalAlpha(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 11, 10) self.SetEndDate(2020, 12, 21) self.SetCash(20000) # Set Strategy Cash tickers = ["EURUSD"] # Rolling Windows to hold bar close data keyed by symbol self.closingData = {} self.SMA45 = {} for ticker in tickers: symbol = self.AddForex(ticker, Resolution.Hour, Market.Oanda).Symbol self.closingData[symbol] = RollingWindow[float](100) # Warm up our rolling windows self.SMA45[symbol] = self.RC(symbol, 100, 2, Resolution.Hour) self.SetWarmUp(50) self.previous=None self.current=None self.marketTicket=None self.stopLimitTicket=None self.stopMarketTicket=None self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday), self.TimeRules.At(9,00), self.End) def OnData(self, data): for symbol, window in self.closingData.items(): if data.ContainsKey(symbol) and data[symbol] is not None: window.Add(data[symbol].Close) if self.IsWarmingUp or not all([window.IsReady for window in self.closingData.values()]): return for symbol, sma in self.SMA45.items(): self.Plot('SMA', symbol.Value, sma.Current.Value) for symbol, window in self.closingData.items(): supports, resistances = self.GetPriceLevels(window) #self.Log(f"Symbol: {symbol.Value} , Supports: {supports} , Resistances: {resistances}") #self.Debug(self.SMA45[symbol].Slope.Current.Value) try: support=supports[0] resistance=resistances[0] #support2=supports[3] #resistance2=resistances[4] self.difference=abs(support-resistance) self.Debug(self.closingData[symbol][1]) if self.previous is not None and self.previous == self.Time.date(): return if not self.Portfolio[symbol].Invested and self.Time.hour>0 and self.Time.hour<9 and self.difference>0.0040 and self.Securities[symbol].Price>support and self.Securities[symbol].Price<resistance and self.SMA45[symbol].Slope.Current.Value>0: self.marketTicket=self.MarketOrder(symbol, 100000) self.Debug(support) self.Debug(resistance) self.Debug(self.Time.date()) self.Debug(self.Time.hour) self.Debug(f"Symbol: {symbol.Value} , Supports: {supports} , Resistances: {resistances}") self.stopLimitTicket = self.LimitOrder(symbol, -100000, resistance) self.stopMarketTicket = self.StopMarketOrder(symbol, -100000, support) except IndexError: pass continue def GetPriceLevels(self, series, variation = 0.006, h = 5): supports = [] resistances = [] maxima = [] minima = [] # finding maxima and minima by looking for hills/troughs locally for i in range(h, series.Size-h): if series[i] > series[i-h] and series[i] > series[i+h]: maxima.append(series[i]) elif series[i] < series[i-h] and series[i] < series[i+h]: minima.append(series[i]) # identifying maximas which are resistances for m in maxima: r = m * variation # maxima which are near each other commonLevel = [x for x in maxima if x > m - r and x < m + r] # if 2 or more maxima are clustered near an area, it is a resistance if len(commonLevel) > 1: # we pick the highest maxima if the cluster as our resistance level = max(commonLevel) if level not in resistances: resistances.append(level) # identify minima which are supports for l in minima: r = l * variation # minima which are near each other commonLevel = [x for x in minima if x > l - r and x < l + r] # if 2 or more minima are clustered near an area, it is a support if len(commonLevel) > 1: # We pick the lowest minima of the cluster as our support level = min(commonLevel) if level not in supports: supports.append(level) return supports, resistances def OnOrderEvent(self, orderEvent): self.previous=self.Time.date() if self.stopLimitTicket !=None and self.stopLimitTicket.OrderId == orderEvent.OrderId: self.stopMarketTicket.Cancel() self.marketTicket=None if self.stopMarketTicket !=None and self.stopMarketTicket.OrderId == orderEvent.OrderId: self.stopLimitTicket.Cancel() self.marketTicket=None def End(self): self.Liquidate()