| Overall Statistics |
|
Total Trades 53 Average Win 3.90% Average Loss -4.59% Compounding Annual Return -6.354% Drawdown 24.900% Expectancy -0.017 Net Profit -6.354% Sharpe Ratio -0.015 Probabilistic Sharpe Ratio 12.957% Loss Rate 47% Win Rate 53% Profit-Loss Ratio 0.85 Alpha 0.019 Beta -0.151 Annual Standard Deviation 0.315 Annual Variance 0.099 Information Ratio -0.512 Tracking Error 0.322 Treynor Ratio 0.032 Total Fees $0.00 |
from collections import *
import math
class MulitTimeFrameForexScalping(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2017, 1, 1) #Set Start Date
self.SetEndDate(2017, 12, 31) #Set End Date
self.SetCash(10000) #Set Strategy Cash
pairs = ["EURUSD", "GBPUSD", "AUDUSD", "NZDUSD"]
self.forexPair = "EURUSD"
self.AddForex(self.forexPair, Resolution.Minute, Market.Oanda)
self.SetBrokerageModel(BrokerageName.OandaBrokerage);
self.Consolidate(self.forexPair,timedelta(minutes=5),self.fiveMinutesBarHandler)
self.Consolidate(self.forexPair, timedelta(minutes=60),self.sixtyMinutesBarHandler)
self.BarHistoryWindow = 5
#Set up EMA indicators for lookback periods 21, 13 and 8 for both five minutes and 60 minutes time frames
self.longLookBackPeriod = 21
self.mediumLookBackPeriod = 13
self.shortLookBackPeriod = 8
self.percentageOfPortfolioRiskedPerTrade = 0.01
self.emaFiveMinsLong = ExponentialMovingAverage(self.longLookBackPeriod)
self.RegisterIndicator(self.forexPair, self.emaFiveMinsLong ,timedelta(minutes=5))
self.emaFiveMinsMedium = ExponentialMovingAverage(self.mediumLookBackPeriod)
self.RegisterIndicator(self.forexPair, self.emaFiveMinsMedium ,timedelta(minutes=5))
self.emaFiveMinsShort = ExponentialMovingAverage(self.shortLookBackPeriod)
self.RegisterIndicator(self.forexPair, self.emaFiveMinsShort ,timedelta(minutes=5))
self.emaSixtyMinsLong = ExponentialMovingAverage(self.longLookBackPeriod)
self.RegisterIndicator(self.forexPair, self.emaSixtyMinsLong ,timedelta(minutes=60))
self.emaSixtyMinsShort = ExponentialMovingAverage(self.shortLookBackPeriod)
self.RegisterIndicator(self.forexPair, self.emaSixtyMinsShort ,timedelta(minutes=60))
self.historyFiveMinuteBars = deque(maxlen= self.BarHistoryWindow )
self.historySixtyMinuteBars = deque(maxlen= self.BarHistoryWindow )
self.historyEmaSixtyMinsLong = deque(maxlen= self.BarHistoryWindow)
self.historyEmaSixtyMinsShort = deque(maxlen= self.BarHistoryWindow)
self.historyEmaFiveMinsLong = deque(maxlen= self.BarHistoryWindow)
self.historyEmaFiveMinsMedium = deque(maxlen= self.BarHistoryWindow)
self.historyEmaFiveMinsShort = deque(maxlen= self.BarHistoryWindow)
self.pipsAtRiskPerTrade = 3
self.numberOfprofitTarget1Pips = 1
self.numberOfprofitTarget2Pips = 2
self.pips = 0.0001
self.stopBuyPrice = 0
self.stopLossPrice = 0
self.profitTarget1 = 0
self.profitTarget2 = 0
self.orderSize = 100000
self.entryTicket = None
self.stoplossTicket = None
self.profit1Ticket = None
self.profit2Ticket = None
def fiveMinutesBarHandler(self,consolidated):
self.historyFiveMinuteBars.append(consolidated)
self.historyEmaFiveMinsLong.append(self.emaFiveMinsLong.Current.Value)
self.historyEmaFiveMinsMedium.append(self.emaFiveMinsMedium.Current.Value)
self.historyEmaFiveMinsShort.append(self.emaFiveMinsShort.Current.Value)
self.Plot("5m","5mEMA21",self.emaFiveMinsLong.Current.Value)
self.Plot("5m","5mEMA13", self.emaFiveMinsMedium.Current.Value)
self.Plot("5m","5mEMA8", self.emaFiveMinsShort.Current.Value)
self.Plot("5m","EURUSD", consolidated.Close)
if self.entryTicket == None and self.longEntrySetup() and self.longEntryTrigger():
entryPrice = max([quoteBar.High for quoteBar in self.historyFiveMinuteBars])
self.stopBuyPrice = entryPrice + 0.0001*3
self.stopLossPrice = consolidated.Low - self.pipsAtRiskPerTrade * self.pips
R = self.stopBuyPrice - self.stopLossPrice
self.profitTarget1 = self.stopBuyPrice + self.numberOfprofitTarget1Pips * R
self.profitTarget2 = self.stopBuyPrice + self.numberOfprofitTarget2Pips * 2*R
self.orderSize = self.CalculateOrderSize()
self.entryTicket = self.StopMarketOrder( self.forexPair, self.orderSize, self.stopBuyPrice)
elif self.entryTicket is not None and not self.longEntrySetup() and self.entryTicket.Status != OrderStatus.Filled:
self.Transactions.CancelOrder(self.entryTicket.OrderId)
self.entryTicket = None
def longEntrySetup(self):
fiveMinFannedOut = all([x > y > z for x,y,z in zip(list(self.historyEmaFiveMinsShort),list(self.historyEmaFiveMinsMedium),list(self.historyEmaFiveMinsLong))])
sixtyMinFannedOut = all([x > y for x,y in zip(list(self.historyEmaSixtyMinsShort),list(self.historyEmaSixtyMinsLong))])
prevBarsAboveShortEMA = all([x > y for x,y in zip([bar.Low for bar in list(self.historyFiveMinuteBars)[0:4]],list(self.historyEmaFiveMinsShort)[:4])])
return fiveMinFannedOut and sixtyMinFannedOut and prevBarsAboveShortEMA
def longEntryTrigger(self):
return self.historyFiveMinuteBars[-1].Low <= self.historyEmaFiveMinsShort[-1]
def CalculateOrderSize(self):
#https://www.thebalance.com/how-to-determine-proper-position-size-when-forex-trading-1031023
totalPortfolioValue = self.Portfolio.TotalPortfolioValue
amountAtRisk = totalPortfolioValue * self.percentageOfPortfolioRiskedPerTrade
standardLot = 100000
pipValueForTrade = 10
lots = amountAtRisk/(self.pipsAtRiskPerTrade * pipValueForTrade ) * standardLot
rounded = math.ceil(lots / 2.) * 2
return rounded
def OnOrderEvent(self, orderevent):
if orderevent.Status != OrderStatus.Filled:
return
if self.entryTicket != None and self.entryTicket.OrderId == orderevent.OrderId:
# Enter stop loss order
self.stoplossTicket = self.StopMarketOrder(self.forexPair,-self.orderSize,self.stopLossPrice)
# Enter limit order 1
self.profit1Ticket = self.LimitOrder(self.forexPair,-self.orderSize/2,self.profitTarget1)
# Enter limit order 2
self.profit2Ticket = self.LimitOrder(self.forexPair,-self.orderSize/2,self.profitTarget2)
if self.profit1Ticket != None and self.profit1Ticket.OrderId == orderevent.OrderId:
self.stoplossTicket.UpdateQuantity(-self.orderSize/2)
if self.stoplossTicket != None and self.stoplossTicket.OrderId == orderevent.OrderId:
self.profit1Ticket.Cancel()
self.profit2Ticket.Cancel()
self.entryTicket = None
if self.profit2Ticket != None and self.profit2Ticket.OrderId == orderevent.OrderId:
self.stoplossTicket.Cancel()
self.entryTicket = None
def sixtyMinutesBarHandler(self,consolidated):
self.historySixtyMinuteBars.append(consolidated)
self.historyEmaSixtyMinsLong.append(self.emaSixtyMinsLong.Current.Value)
self.historyEmaSixtyMinsShort.append(self.emaSixtyMinsShort.Current.Value)
self.Plot("60m","EMA21",self.emaSixtyMinsLong.Current.Value)
self.Plot("60m","EMA8", self.emaSixtyMinsShort.Current.Value)
self.Plot("60m","EURUSD", consolidated.Close)