Overall Statistics
Total Trades
675
Average Win
1.39%
Average Loss
-0.95%
Compounding Annual Return
7.162%
Drawdown
22.500%
Expectancy
0.260
Net Profit
117.868%
Sharpe Ratio
0.662
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
1.47
Alpha
0.097
Beta
-2.172
Annual Standard Deviation
0.092
Annual Variance
0.009
Information Ratio
0.484
Tracking Error
0.092
Treynor Ratio
-0.028
Total Fees
$3891.73
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel

class HorizontalMultidimensionalReplicator(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2008, 1, 23)  # Set Start Date
        self.SetCash(100000)            # Set Strategy Cash
        
        self.AddAlpha(PanicToExcuberanceAlphaModel(self))

        self.SetExecution(ImmediateExecutionModel())

        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())

        symbols = [ Symbol.Create("SPY", SecurityType.Equity, Market.USA) ]
        self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) )


class PanicToExcuberanceAlphaModel(AlphaModel):
    
        # This Alpha uses data from URC that contains the number of companies currently reaching new highs
        # in stock price, within the NASDAQ exchange. It is likely that very few companies are reaching 
        # new highs when a recession is imminent. Many companies reach new highs when market participants 
        # are exuberant. 

        # This Alpha Model uses smoothed Exponential Moving Average (EMA) to determine how many companies
        # on average are reaching a new high. If the number of companies is less than 5, then it emits 
        # insights until the number of companies reaches 200.
        
        ## More URC market data can be found at Quandl
        ## https://www.quandl.com/data/URC-Unicorn-Research-Corporation
    
    def __init__(self, algorithm):
        
        # Add Quandl data
        self.yearlyHighs = algorithm.AddData(QuandlData, 'URC/NASDAQ_52W_HI',Resolution.Daily).Symbol
        
        # Set predicition period
        self.period = timedelta(days=1)
        
        # Set lookback window for Rolling Window and EMA Indicator
        self.lookback = 50
        
        # Set resolution for EMA Indicator
        self.resolution = Resolution.Daily
        self.emitInsights = False

    
    def Update(self, algorithm, data):
        insights = []
        
        # Return if no data
        if not data.ContainsKey(self.yearlyHighs): return insights
        
        # Set emitInsights to false when the number of companies greater than 250
        if self.emaWin[0].Value > 200:
            self.emitInsights = False
        # Set emitInsights to false when the number of companies is less than 5
        elif self.emaWin[0].Value < 5:
            self.emitInsights = True
            
        # Emit insights    
        if self.emitInsights:
            insights.append(Insight.Price("SPY", self.period, InsightDirection.Up, 0.001))
            
        return insights
        
    def OnSecuritiesChanged(self,algorithm,changes):
        for added in changes.AddedSecurities:
            # Only add EMA and Rolling Window for custom data
            if added.Symbol == self.yearlyHighs:

                # Construct an EMA indicator and a rolling window for added securities
                algorithm.EMA(added.Symbol, self.lookback,self.resolution).Updated += self.emaUpdated
                self.emaWin = RollingWindow[IndicatorDataPoint](self.lookback)
            
    # Adds values to rolling window
    def emaUpdated(self, sender, updated):
        self.emaWin.Add(updated)

           
class QuandlData(PythonQuandl):
    
    def __init__(self):
        ## Retrieve the data from the the Quandl object, specifying the data field used on Quandl
        self.ValueColumnName = "NUMBERS OF STOCKS"