| Overall Statistics |
|
Total Trades 248 Average Win 0.14% Average Loss -0.19% Compounding Annual Return -86.052% Drawdown 12.500% Expectancy -0.565 Net Profit -12.484% Sharpe Ratio -7.719 Probabilistic Sharpe Ratio 0% Loss Rate 75% Win Rate 25% Profit-Loss Ratio 0.74 Alpha -0.471 Beta -0.278 Annual Standard Deviation 0.095 Annual Variance 0.009 Information Ratio -10.794 Tracking Error 0.154 Treynor Ratio 2.63 Total Fees $1239.50 Estimated Strategy Capacity $340000.00 Lowest Capacity Asset GC VL5E74HP3EE5 |
class UncoupledVentralPrism(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 10, 8)
self.SetEndDate(2013, 11, 1)
#self.SetEndDate(2017, 5, 19)
self.SetCash(100000)
self.tickers = ['ZW',
'ZN',
'CL',
'GC']
self.future_data_by_future = {}
for ticker in self.tickers:
future = self.AddFuture(ticker)
future.SetFilter(lambda x: x.FrontMonth().OnlyApplyFilterAtMarketOpen())
self.future_data_by_future[future.Symbol.ID.Symbol] = FutureData()
def OnData(self, data):
for future, future_data in self.future_data_by_future.items():
if not data.ContainsKey(future_data.symbol):
continue
holding = None if future_data.symbol is None else self.Portfolio.get(future_data.symbol)
if holding is not None:
# Buy the futures' front contract when the fast EMA is above the slow one
if future_data.fast.Current.Value > future_data.slow.Current.Value:
if not holding.Invested:
self.SetHoldings(future_data.symbol, .1)
elif holding.Invested:
self.Liquidate(future_data.symbol)
def OnSecuritiesChanged(self, changes):
for security in changes.RemovedSecurities:
# Remove the consolidator for the previous contract
# and reset the indicators
future_data = self.future_data_by_future[security.Symbol.ID.Symbol]
if future_data.symbol is not None and future_data.consolidator is not None:
future_data.reset(self)
for security in changes.AddedSecurities:
symbol = security.Symbol
self.future_data_by_future[symbol.ID.Symbol].setup(symbol, self)
class FutureData:
symbol = None
consolidator = None
fast = ExponentialMovingAverage(10)
slow = ExponentialMovingAverage(50)
def setup(self, symbol, algorithm):
# Only one security will be added: the new front contract
self.symbol = symbol
# Create a new consolidator and register the indicators to it
self.consolidator = algorithm.ResolveConsolidator(symbol, Resolution.Minute)
algorithm.RegisterIndicator(symbol, self.fast, self.consolidator)
algorithm.RegisterIndicator(symbol, self.slow, self.consolidator)
# Warm up the indicators
algorithm.WarmUpIndicator(symbol, self.fast, Resolution.Minute)
algorithm.WarmUpIndicator(symbol, self.slow, Resolution.Minute)
def reset(self, algorithm):
algorithm.SubscriptionManager.RemoveConsolidator(self.symbol, self.consolidator)
self.symbol = None
self.consolidator = None
self.fast.Reset()
self.slow.Reset()
# We don't need to call Liquidate(_symbol),
# since its positions are liquidated because the contract has expired.