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