Overall Statistics
Total Trades
4626
Average Win
0.12%
Average Loss
-0.09%
Compounding Annual Return
268.385%
Drawdown
14.300%
Expectancy
0.207
Net Profit
54.604%
Sharpe Ratio
5.528
Probabilistic Sharpe Ratio
92.053%
Loss Rate
48%
Win Rate
52%
Profit-Loss Ratio
1.32
Alpha
2.103
Beta
-0.084
Annual Standard Deviation
0.383
Annual Variance
0.146
Information Ratio
3.542
Tracking Error
0.638
Treynor Ratio
-25.175
Total Fees
$17400.78
from datetime import datetime,timedelta
import numpy as np


class EMAUniverse(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020,1,22)  #Set Start Date
        self.SetEndDate(2020,5,22)    #Set End Date
        self.SetCash(1000000)         #Set Strategy Cash
        self.SetBrokerageModel(AlphaStreamsBrokerageModel())  
        self.UniverseSettings.Resolution = Resolution.Daily
        self.SetBenchmark(self.AddEquity('SPY', Resolution.Daily).Symbol)
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
        self.AddAlpha(BBAlpha())
        self.SetUniverseSelection(LiquidETFUniverse())
        self.SetExecution(ImmediateExecutionModel())
        self.coarse_count = 1
        self.averages = { };
            
class BBAlpha(AlphaModel):
    
    def __init__(self,
                 fastPeriod = 12,
                 slowPeriod = 26,
                 signalPeriod = 9,
                 movingAverageType = MovingAverageType.Simple,
                 resolution = Resolution.Daily):
        self.fastPeriod = fastPeriod
        self.slowPeriod = slowPeriod
        self.signalPeriod = signalPeriod
        self.movingAverageType = movingAverageType
        self.resolution = resolution
        self.symbolData2 = {}
        resolutionString = Extensions.GetEnumString(resolution, Resolution)
        movingAverageTypeString = Extensions.GetEnumString(movingAverageType, MovingAverageType)
        self.Name = '{}({},{},{},{},{})'.format(self.__class__.__name__, fastPeriod, slowPeriod, signalPeriod, movingAverageTypeString, resolutionString)
        self.month = None
        self.finalupperband=None
        
        self.direction = InsightDirection.Flat
        
    def Update(self, algorithm, data):
            
        insights = []
        
        for key, sd in self.symbolData2.items():
            self.symbol=sd.Security.Symbol
            
            if sd.Security.Price == 0:
                continue
            
            if not (sd.BB1Window.IsReady):
                continue
        
            if not algorithm.Portfolio[sd.Security.Symbol].Invested:
                
                
                if sd.Security.Price>sd.BB1Window[1].Value:
                    self.month = algorithm.Time.month
                    insight = Insight.Price(sd.Security.Symbol, timedelta(hours = 25), InsightDirection.Up, None,None,None,1)
                    self.direction = InsightDirection.Up
                    insights.append(insight)
                    sd.PreviousDirection = insight.Direction
        return insights

    def OnSecuritiesChanged(self, algorithm, changes):
        for added in changes.AddedSecurities:
            self.symbol=added.Symbol
            self.symbolData2[added.Symbol] = SymbolData2(algorithm, added, self.fastPeriod, self.slowPeriod, self.signalPeriod, self.movingAverageType, self.resolution)
            
        for removed in changes.RemovedSecurities:
            data = self.symbolData2.pop(removed.Symbol, None)
            if data is not None:
                algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, data.Consolidator)
                
                
class SymbolData2(object):
    def __init__(self, algorithm, security, fastPeriod, slowPeriod, signalPeriod, movingAverageType, resolution):
        self.Security = security
        
        self.Consolidator = algorithm.ResolveConsolidator(security.Symbol, resolution)
        
        self.BB1 = BollingerBands(20, 2)
        algorithm.RegisterIndicator(security.Symbol, self.BB1, self.Consolidator)
        self.BB1.Updated+=self.BB1Updated
        self.BB1Window=RollingWindow[IndicatorDataPoint](20)
        
        
        self.PreviousDirection = None
        #try:
        history = algorithm.History(security.Symbol, 50, Resolution.Daily)
        self.WarmUpIndicators2(history)
        #except KeyError:
         #   pass
    
    def WarmUpIndicators2(self, history):
        for index, row in history.loc[str(self.Security.Symbol)].iterrows():
           
            self.BB1.Update(index,row["close"])
            
    def BB1Updated(self, sender, updated):
        self.BB1Window.Add(updated)