| Overall Statistics |
|
Total Trades 85 Average Win 20.64% Average Loss -2.36% Compounding Annual Return 63.691% Drawdown 47.800% Expectancy 3.992 Net Profit 2485.798% Sharpe Ratio 1.176 Probabilistic Sharpe Ratio 40.453% Loss Rate 49% Win Rate 51% Profit-Loss Ratio 8.75 Alpha 0.538 Beta 0.079 Annual Standard Deviation 0.465 Annual Variance 0.216 Information Ratio 0.894 Tracking Error 0.485 Treynor Ratio 6.908 Total Fees $84318.38 Estimated Strategy Capacity $4200000.00 Lowest Capacity Asset LGVN XLZHO3M6UH5X |
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel
from AlgorithmImports import *
class TwoWeekMagnitudeEffectOnCurrentReturns(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2015, 5, 8) # Set Start Date
self.SetCash(1000000) # Set Strategy Cash
self.AddAlpha(MyHistoricalReturnsAlphaModel(14, Resolution.Daily))
self.SetExecution(ImmediateExecutionModel())
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetUniverseSelection(CoarseFundamentalUniverseSelectionModel(self.CoarseSelectionFunction))
def CoarseSelectionFunction(self, coarse):
sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
filtered = [ x.Symbol for x in sortedByDollarVolume if x.HasFundamentalData and x.Price >= 5 and x.Price <= 1000 and x.DollarVolume > 100000000 ]
return [ x for x in filtered[:250] ]
class MyHistoricalReturnsAlphaModel(AlphaModel):
'''Uses Historical returns to create insights.'''
def __init__(self, *args, **kwargs):
'''Initializes a new default instance of the HistoricalReturnsAlphaModel class.
Args:
lookback(int): Historical return lookback period
resolution: The resolution of historical data'''
self.lookback = kwargs['lookback'] if 'lookback' in kwargs else 1
self.resolution = kwargs['resolution'] if 'resolution' in kwargs else Resolution.Daily
self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(self.resolution), self.lookback)
self.symbolDataBySymbol = {}
def Update(self, algorithm, data):
'''Updates this alpha model with the latest data from the algorithm.
This is called each time the algorithm receives data for subscribed securities
Args:
algorithm: The algorithm instance
data: The new data available
Returns:
The new insights generated'''
insights = []
for symbol, symbolData in self.symbolDataBySymbol.items():
if symbolData.CanEmit:
direction = InsightDirection.Flat
magnitude = symbolData.Return
if magnitude > .75: direction = InsightDirection.Down
if magnitude < -.75: direction = InsightDirection.Up
insights.append(Insight.Price(symbol, self.predictionInterval, direction, magnitude, None))
return insights
def OnSecuritiesChanged(self, algorithm, changes):
'''Event fired each time the we add/remove securities from the data feed
Args:
algorithm: The algorithm instance that experienced the change in securities
changes: The security additions and removals from the algorithm'''
# clean up data for removed securities
for removed in changes.RemovedSecurities:
symbolData = self.symbolDataBySymbol.pop(removed.Symbol, None)
if symbolData is not None:
symbolData.RemoveConsolidators(algorithm)
# initialize data for added securities
symbols = [ x.Symbol for x in changes.AddedSecurities ]
history = algorithm.History(symbols, self.lookback, self.resolution)
if history.empty: return
tickers = history.index.levels[0]
for ticker in tickers:
symbol = SymbolCache.GetSymbol(ticker)
if symbol not in self.symbolDataBySymbol:
symbolData = SymbolData(symbol, self.lookback)
self.symbolDataBySymbol[symbol] = symbolData
symbolData.RegisterIndicators(algorithm, self.resolution)
symbolData.WarmUpIndicators(history.loc[ticker])
class SymbolData:
'''Contains data specific to a symbol required by this model'''
def __init__(self, symbol, lookback):
self.Symbol = symbol
self.ROCP = RateOfChange('{}.ROCP({})'.format(symbol, lookback), lookback)
self.Consolidator = None
self.previous = 0
def RegisterIndicators(self, algorithm, resolution):
self.Consolidator = algorithm.ResolveConsolidator(self.Symbol, resolution)
algorithm.RegisterIndicator(self.Symbol, self.ROCP, self.Consolidator)
def RemoveConsolidators(self, algorithm):
if self.Consolidator is not None:
algorithm.SubscriptionManager.RemoveConsolidator(self.Symbol, self.Consolidator)
def WarmUpIndicators(self, history):
for tuple in history.itertuples():
self.ROCP.Update(tuple.Index, tuple.close)
@property
def Return(self):
return float(self.ROCP.Current.Value)
@property
def CanEmit(self):
if self.previous == self.ROCP.Samples:
return False
self.previous = self.ROCP.Samples
return self.ROCP.IsReady
def __str__(self, **kwargs):
return '{}: {:.2%}'.format(self.ROC.Name, (1 + self.Return)**252 - 1)