Overall Statistics
Total Trades
8344
Average Win
0.02%
Average Loss
-0.07%
Compounding Annual Return
3.512%
Drawdown
49.900%
Expectancy
0.076
Net Profit
47.307%
Sharpe Ratio
0.288
Loss Rate
19%
Win Rate
81%
Profit-Loss Ratio
0.33
Alpha
0.124
Beta
-3.966
Annual Standard Deviation
0.163
Annual Variance
0.027
Information Ratio
0.169
Tracking Error
0.163
Treynor Ratio
-0.012
Total Fees
$0.00
class AssetClassTrendFollowingAlgorithm(QCAlgorithmFramework):

    def Initialize(self):

        self.SetStartDate(2008, 5, 1)    # Set Start Date
        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(AssetClassTrendAlphaModel())

        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) 
        self.SetExecution(ImmediateExecutionModel())
        self.SetRiskManagement(NullRiskManagementModel())
    
class AssetClassTrendAlphaModel(AlphaModel):
    '''Alpha model that uses an SMA and security price to create insights'''

    def __init__(self,
                 period = 10*21,
                 resolution = Resolution.Daily):
        '''
        Initializes a new instance of the AssetClassTrendFollowingAlphaModel class
        Args:
            period: The SMA period
            resolution: The data 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, value in history[str(symbol)].iteritems():
                data.Update(time, value)