| Overall Statistics |
|
Total Trades 1364 Average Win 30.63% Average Loss -0.43% Compounding Annual Return -71.921% Drawdown 88.200% Expectancy -0.681 Net Profit -88.092% Sharpe Ratio -0.98 Probabilistic Sharpe Ratio 0.007% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 71.54 Alpha -0.636 Beta 0.603 Annual Standard Deviation 0.53 Annual Variance 0.281 Information Ratio -1.37 Tracking Error 0.52 Treynor Ratio -0.861 Total Fees $2523.40 Estimated Strategy Capacity $83000000.00 Lowest Capacity Asset ES XMXYBDF3IXHD |
from AlgorithmImports import *
class ContinuousFutureRegressionAlgorithm(QCAlgorithm):
'''Basic template algorithm simply initializes the date range and cash'''
def Initialize(self):
'''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
self.SetStartDate(2020, 1, 1)
self.SetEndDate(2022, 5, 1)
self._mappings = []
self._lastDateLog = -1
self._continuousContract = self.AddFuture(Futures.Indices.SP500EMini,
Resolution.Minute,
dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
dataMappingMode = DataMappingMode.LastTradingDay, # change to openinterest
contractDepthOffset= 0)
self._currentMappedSymbol = self._continuousContract.Symbol
self.indicators = {
'sma': self.SMA(self._continuousContract.Symbol, 11, Resolution.Minute),
'ema': self.EMA(self._continuousContract.Symbol, 60, Resolution.Minute),
# 'atr': AverageTrueRange(14)
}
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(13, 0), self.StartOfDay) # set to 13:00
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15, 0), self.EndOfDay)
self.TradingTime = False
def StartOfDay(self):
self.TradingTime = True
def EndOfDay(self):
self.TradingTime = False
# if self.Portfolio.Invested:
# self.Liquidate(tag='Liquidate all')
def OnData(self, data):
'''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
Arguments:
data: Slice object keyed by symbol containing the stock data
'''
if len(data.Keys) != 1:
raise ValueError(f"We are getting data for more than one symbols! {','.join(data.Keys)}")
for changedEvent in data.SymbolChangedEvents.Values:
if changedEvent.Symbol == self._continuousContract.Symbol:
self._mappings.append(str(changedEvent))
self.Log(f"SymbolChanged event: {changedEvent}")
if self._currentMappedSymbol == self._continuousContract.Mapped:
raise ValueError(f"Continuous contract current symbol did not change! {self._continuousContract.Mapped}")
self.Liquidate(self.Securities[self._currentMappedSymbol].Symbol, tag='Switching Symbol')
self._currentMappedSymbol = self._continuousContract.Mapped
contract = self.Securities[self._continuousContract.Mapped]
if not contract.HasData:
return
# bar = data[self._continuousContract.Mapped.Symbol]
# bar = data[self._continuousContract.Mapped]
# bar = data[contract]
# bar = data[contract.Symbol]
# bar = data.bar[contract.Symbol]
open_orders = self.Transactions.GetOpenOrders(contract.Symbol)
if self.indicators['sma'].Current.Value > self.indicators['ema'].Current.Value:
if not self.Portfolio.Invested and len(open_orders) == 0 and self.TradingTime:
quantity = 1 # make quantity dynamic ?
self.entryPrice = contract.BidPrice + 1
self.entryTicket = self.StopMarketOrder(contract.Symbol, quantity, self.entryPrice)
def OnOrderEvent(self, orderEvent):
if orderEvent.Status != OrderStatus.Filled:
return
contract = self.Securities[self._continuousContract.Mapped]
if self.entryTicket is not None and self.entryTicket.OrderId == orderEvent.OrderId:
quantity = self.Portfolio[contract.Symbol].Quantity
# stopPrice = self.entryPrice - 1 # self.entryTicket.AverageFillPrice - 1
stop_price = self.entryTicket.AverageFillPrice - 2
self.stopTicket = self.StopMarketOrder(contract.Symbol, -quantity, stop_price, 'Exit by SL')
def OnSecuritiesChanged(self, changes):
self.Debug(f"{self.Time}-{changes}")
def OnEndOfAlgorithm(self):
self.Debug(f'mappings={self._mappings}')