| Overall Statistics |
|
Total Trades 48 Average Win 3.82% Average Loss -2.30% Compounding Annual Return 85.107% Drawdown 17.200% Expectancy 0.663 Net Profit 85.016% Sharpe Ratio 2.083 Probabilistic Sharpe Ratio 77.214% Loss Rate 38% Win Rate 62% Profit-Loss Ratio 1.66 Alpha 0.193 Beta 2.028 Annual Standard Deviation 0.286 Annual Variance 0.082 Information Ratio 1.856 Tracking Error 0.214 Treynor Ratio 0.293 Total Fees $292.40 Estimated Strategy Capacity $200000000.00 Lowest Capacity Asset ES XZDYPWUWC7I9 Portfolio Turnover 54.05% |
# region imports
from AlgorithmImports import *
from scipy.stats import entropy
import numpy as np
# endregion
class SquareMagentaHamster(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 1, 1) # Set Start Date
self.SetEndDate(2022, 1, 1)
self.SetCash(100000) # Set Strategy Cash
self.ShortcontractSymbol = None
self.LongcontractSymbol = None
self.future = self.AddFuture(Futures.Indices.SP500EMini, Resolution.Hour, extendedMarketHours= True)
self.future.SetFilter(timedelta(0), timedelta(182))
self.symbol = self.future.Symbol
self.lookback = 30
self.priceWindow = RollingWindow[QuoteBar](self.lookback)
def OnData(self, data: Slice):
if not(data.ContainsKey(self.symbol) and data[self.symbol] is not None):
return
self.priceWindow.Add(data[self.symbol])
if not self.priceWindow.IsReady:
return
self.closingPrices = [bar.Close for bar in self.priceWindow]
if self.HurstExponent() > 0.5 and self.Entropy() > 2.6:
if self.Portfolio.Invested:
if self.ShortcontractSymbol != None:
self.Log("covered short for long EMA")
self.BuyFuture(data)
elif self.LongcontractSymbol != None:
return
else:
self.BuyFuture(data)
self.Log("Bought future")
elif self.HurstExponent() < 0.5 and self.Entropy() < 2.6:
if self.Portfolio.Invested:
if self.LongcontractSymbol != None:
self.Log("sold long for short EMA")
self.ShortFuture(data)
elif self.ShortcontractSymbol != None:
return
else:
self.ShortFuture(data)
self.Log("Short future")
self.Plot("Hurst", "Value", self.HurstExponent())
self.Plot("Entropy", "value", self.Entropy())
#self.Log(self.Entropy())
def HurstExponent(self):
#Hurst Exponent = (log(Rn/S) / log(n)) - 0.5
#where Rn is the range of the cumulative sum of n data points and S is the standard deviation of the n data points
prices = np.array([self.closingPrices])
Rn = np.cumsum(prices)
S = np.std(prices)
hursts = ((np.log(Rn/S)) / np.log(prices)) - 0.5
return hursts[-1][-1]
def Entropy(self):
base = 2
value,counts = np.unique(self.closingPrices, return_counts=True)
return entropy(counts, base=base)
def ShortFuture(self, data: Slice):
for chain in data.FutureChains:
# Get contracts expiring no earlier than in 90 days
contracts = list(filter(lambda x: x.Expiry > self.Time + timedelta(90), chain.Value))
# if there is any contract, trade the front contract
if len(contracts) == 0: continue
self.ShortcontractSymbol = sorted(contracts, key = lambda x: x.Expiry, reverse=True)[0]
#self.ShortcontractSymbol = front
self.SetHoldings(self.ShortcontractSymbol.Symbol, -0.20, True)
return
def BuyFuture(self, data: Slice):
for chain in data.FutureChains:
# Get contracts expiring no earlier than in 90 days
contracts = list(filter(lambda x: x.Expiry > self.Time + timedelta(90), chain.Value))
# if there is any contract, trade the front contract
if len(contracts) == 0: continue
self.LongcontractSymbol = sorted(contracts, key = lambda x: x.Expiry, reverse=True)[0]
#self.LongcontractSymbol = front
self.SetHoldings(self.LongcontractSymbol.Symbol, 0.20, True)
return