| Overall Statistics |
|
Total Trades 8059 Average Win 0.02% Average Loss -0.07% Compounding Annual Return 3.295% Drawdown 49.900% Expectancy 0.072 Net Profit 42.460% Sharpe Ratio 0.275 Loss Rate 20% Win Rate 80% Profit-Loss Ratio 0.34 Alpha 0.105 Beta -3.045 Annual Standard Deviation 0.165 Annual Variance 0.027 Information Ratio 0.156 Tracking Error 0.165 Treynor Ratio -0.015 Total Fees $0.00 |
import pandas as pd
from datetime import datetime
class AssetClassTrendFollowingAlgorithm(QCAlgorithmFramework):
def Initialize(self):
self.SetStartDate(2008, 5, 1)
self.SetEndDate(datetime.now())
self.SetCash(100000) # Set Strategy Cash
self.SetSecurityInitializer(lambda security: security.SetFeeModel(ConstantFeeModel(0)))
symbols = [Symbol.Create(ticker, SecurityType.Equity, Market.USA)
for ticker in ["SPY", "EFA", "BND", "VNQ", "GSG"]]
self.UniverseSettings.Resolution = Resolution.Daily
self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) )
self.SetAlpha(AssetClassTrendFollowingAlphaModel(self))
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
self.SetRiskManagement(NullRiskManagementModel())
class AssetClassTrendFollowingAlphaModel(AlphaModel):
'''Alpha model that uses an SMA and security price to create insights'''
def __init__(self,
algorithm,
period = 10*21,
resolution = Resolution.Daily):
'''
Initializes a new instance of the AssetClassTrendFollowingAlphaModel class
Args:
algorithm:
period: The SMA period
resolution:
'''
self.period = period
self.resolution = resolution
self.smaBySymbol = dict()
resolutionString = Extensions.GetEnumString(resolution, Resolution)
self.Name = f'{self.__class__.__name__}({period},{resolutionString})'
self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(resolution), period)
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,sma in self.smaBySymbol.items():
if sma.IsReady:
if algorithm.Securities[symbol].Price > sma.Current.Value:
insights.append(Insight.Price(symbol,self.predictionInterval,InsightDirection.Up))
return insights
def OnSecuritiesChanged(self, algorithm, changes):
'''
Event fired each time the we add 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
'''
addedSymbols = [ x.Symbol for x in changes.AddedSecurities ]
history = algorithm.History(addedSymbols, self.period, self.resolution)
history = history.close.unstack(level=0)
for symbol in addedSymbols:
data = self.smaBySymbol.setdefault(symbol, algorithm.SMA(symbol, self.period, self.resolution))
for time, sma in history[str(symbol)].iteritems():
data.Update(time, sma)