| Overall Statistics |
|
Total Trades 5 Average Win 30.29% Average Loss 0% Compounding Annual Return 92.786% Drawdown 15.800% Expectancy 0 Net Profit 92.685% Sharpe Ratio 2.441 Probabilistic Sharpe Ratio 85.622% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.191 Beta 2.206 Annual Standard Deviation 0.257 Annual Variance 0.066 Information Ratio 2.659 Tracking Error 0.161 Treynor Ratio 0.284 Total Fees $10.75 Estimated Strategy Capacity $580000.00 Lowest Capacity Asset ES XUERCWA6EWAP Portfolio Turnover 3.33% |
# 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]
hurst_exponent = self.HurstExponent()
entropy = self.Entropy()
self.Log(str(hurst_exponent[0]))
self.Log(str(hurst_exponent))
if hurst_exponent[0] > 0.5 and 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 hurst_exponent[0] < 0.5 and 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", hurst_exponent[0])
#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)
n = len(prices)
epsilon = 1e-10 # small constant
hursts = ((np.log(Rn/(S + epsilon))) / (np.log(n + epsilon))) - 0.5
return hursts
def Entropy(self):
base = 2
value,counts = np.unique(self.closingPrices, return_counts=True)
probs = counts / np.sum(counts)
return entropy(probs, 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