| Overall Statistics |
|
Total Trades 31 Average Win 3.67% Average Loss -3.46% Compounding Annual Return 83.236% Drawdown 25.100% Expectancy 0.177 Net Profit 11.550% Sharpe Ratio 1.637 Probabilistic Sharpe Ratio 53.608% Loss Rate 43% Win Rate 57% Profit-Loss Ratio 1.06 Alpha 1.055 Beta -1.76 Annual Standard Deviation 0.516 Annual Variance 0.266 Information Ratio 1.148 Tracking Error 0.631 Treynor Ratio -0.48 Total Fees $57.35 |
class FuturesMovingAverageCrossOverExample2(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2018, 1, 1) #Set Start Date
self.SetEndDate(2018, 3,6) #Set End Date
self.SetCash(100000) #Set Strategy Cash
self.SetTimeZone('America/Los_Angeles') # Set timezone
self.reset = True
self.SymbolData = { }
self.AddEquity("SPY", Resolution.Minute)
futureES = self.AddFuture(Futures.Indices.SP500EMini)
futureES.SetFilter(0, 360)
self.Schedule.On(self.DateRules.Every(DayOfWeek.Tuesday), self.TimeRules.AfterMarketOpen("SPY", 10), self.ScheduleDemo)
def OnData(self, slice):
# Reset any open positions based on a contract rollover.
if self.reset:
self.reset = False
self.Log('RESET: closing all positions')
self.Liquidate()
def OnSecuritiesChanged(self, changes):
for added in changes.AddedSecurities:
# Only trade Futures
if added.Type != SecurityType.Future:
continue
symbol = added.Symbol
if symbol not in self.SymbolData:
macd = self.MACD(symbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Minute)
self.SymbolData[symbol] = AssetData(macd)
for removed in changes.RemovedSecurities:
assetData = self.SymbolData.pop(removed.Symbol, None)
if assetData:
self.Liquidate(removed.Symbol)
assetData.Dispose()
def ScheduleDemo(self):
tolerance = 0.003
for symbol, assetData in self.SymbolData.items():
security = self.Securities[symbol]
# Only new positions not invested
if security.Invested:
continue
price = security.Price
signalDeltaPercent = assetData.macd.Current.Value - assetData.macd.Signal.Current.Value
if signalDeltaPercent < -tolerance:
#Go long
self.MarketOrder(symbol, 1)
assetData.takeProfit = self.LimitOrder(symbol, -1, price*1.03)
assetData.stopLoss = self.StopMarketOrder(symbol, -1, price*0.97)
if signalDeltaPercent > tolerance:
#Go short
self.MarketOrder(symbol, -1)
assetData.takeProfit = self.LimitOrder(symbol, 1, price*0.97)
assetData.stopLoss = self.StopMarketOrder(symbol, 1, price*1.03)
def OnOrderEvent(self, orderEvent):
if orderEvent.Status != OrderStatus.Filled:
return
assetData = self.SymbolData.get(orderEvent.Symbol, None)
if assetData:
assetData.Cancel(orderEvent.OrderId)
class AssetData:
def __init__(self, macd):
self.macd = macd
self.takeProfit = None
self.stopLoss = None
def Cancel(self, id):
'''cancel one order if the other was filled'''
if self.takeProfit is not None and id == self.takeProfit.OrderId:
self.stopLoss.Cancel()
if self.stopLoss is not None and id == self.stopLoss.OrderId:
self.takeProfit.Cancel()
def Dispose(self):
'''cancel submitted orders'''
if self.takeProfit is not None:
self.takeProfit.Cancel()
if self.stopLoss is not None:
self.stopLoss.Cancel()