Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-7.567
Tracking Error
0.098
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
class QuantumHorizontalRegulators(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 7, 1)  # Set Start Date
        self.SetEndDate(2020, 8, 31)
        self.SetCash(333333)  # Set Strategy Cash
        self.scaning = False
        self.lastToggle = None
        self.needs_reset = False
        
        
        self.backtestSymbolsPerDay = {}
        self.current_universe = []

        self.UniverseSettings.Resolution = Resolution.Daily
        #self.AddUniverse("my-dropbox-universe", self.selector)
        self.SetUniverseSelection(ScheduledUniverseSelectionModel(
            self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday),
            self.TimeRules.Every(timedelta(minutes = 15)),
            self.SelectSymbols
            ))

        self.AddAlpha(ShortSqueezeModel(self))
        
        self.SetExecution(ImmediateExecutionModel())

        self.SetPortfolioConstruction(AccumulativeInsightPortfolioConstructionModel(lambda time: None))
        
        self.SetRiskManagement(MaximumUnrealizedProfitPercentPerSecurity(maximumUnrealizedProfitPercent = 0.1))  
        

    def SelectSymbols(self, dateTime):
         # handle live mode file format
        if self.LiveMode:
            # fetch the file from dropbox
            str = self.Download("https://www.dropbox.com/s/f1m6kxoi9iedina/Watchlist.csv?dl=1")
            # if we have a file for today, return symbols, else leave universe unchanged
            self.current_universe = str.split(',') if len(str) > 0 else self.current_universe
            return self.current_universe

        # backtest - first cache the entire file
        if len(self.backtestSymbolsPerDay) == 0:

            # No need for headers for authorization with dropbox, these two lines are for example purposes 
            #byteKey = base64.b64encode("UserName:Password".encode('ASCII'))
            # The headers must be passed to the Download method as dictionary
            #headers = { 'Authorization' : f'Basic ({byteKey.decode("ASCII")})' }

            #str = self.Download("https://www.dropbox.com/s/f1m6kxoi9iedina/Watchlist.csv?dl=1", headers)
            csv_data = self.Download("https://www.dropbox.com/s/f1m6kxoi9iedina/Watchlist.csv?dl=1")
            for line in csv_data.splitlines():
                data = line.split(',')
                self.backtestSymbolsPerDay[data[0]] = data[1:]
        
        index = dateTime.date().strftime("%Y%m%d")
        
        if index in self.backtestSymbolsPerDay.keys():
            tickers = self.backtestSymbolsPerDay[index]
            self.current_universe = [Symbol.Create(ticker, SecurityType.Equity, Market.USA) for ticker in tickers]
        return self.current_universe
        

class ShortSqueezeModel(AlphaModel):
    symbolData = {}

    def __init__(self, algo):
        self.algo = algo
        
    
    def Update(self, algorithm, slice):
        
        return []
        
        if algorithm.IsWarmingUp:
            return []
    
        # If it's the end of the day, update the yesterday close of each indicator
        if not algorithm.Securities['my-dropbox-universe'].Exchange.ExchangeOpen:
            for symbol in self.symbolData:
                if symbol in slice.Bars:
                    self.symbolData[symbol].yest_close = slice.Bars[symbol].Close
        
        insights = []
        
        insight_seconds = 99999999999
        
        # Create insights for symbols up at least 40% on the day
        for symbol in self.symbolData:
            # If already invested, continue to next symbol
            if algorithm.Securities[symbol].Invested or symbol not in slice.Bars or self.symbolData[symbol].max.Samples == 0:
                continue
            
            # Calculate return sign yesterday's close
            yest_close = self.symbolData[symbol].yest_close
            close = slice[symbol].Close 
            ret = (close - yest_close) / yest_close
            high_of_day_break = close > self.symbolData[symbol].max.Current.Value
            if ret >= 0.4 and high_of_day_break:    # Up 40% on the day & breaks high of day
                hours = algorithm.Securities[symbol].Exchange.Hours
        # 1-minute before the close
                closeTime = hours.GetNextMarketClose(algorithm.Time, False) - timedelta(minutes=1)
                insights.append(Insight.Price(symbol, closeTime, InsightDirection.Up))
                
                
        # Update max indicator for all symbols
        for symbol in self.symbolData:
            if symbol in slice.Bars:
                self.symbolData[symbol].max.Update(slice.Time, slice.Bars[symbol].High)
                
                
        # Constantly updating 10% Trailing Stop Order        
        for symbol in self.symbolData:
            if symbol in slice.Bars and algorithm.Securities[symbol].Invested and slice[symbol].Close <= 0.9*self.symbolData[symbol].max.Current.Value:
                insights.append(Insight(symbol, timedelta(seconds=insight_seconds), InsightType.Price, InsightDirection.Flat))
        
        return Insight.Group(insights)
    
    
    
    def OnSecuritiesChanged(self, algorithm, changes):
        if len(changes.AddedSecurities) > 0:
            # Get history of symbols over lookback window
            added_symbols = [x.Symbol for x in changes.AddedSecurities]
            history = algorithm.History(added_symbols, 1, Resolution.Daily)
            if history.empty:
                    return
            history  = history['close']
            for added in changes.AddedSecurities:
                # Save yesterday's close
                closes = history.loc[[str(added.Symbol.ID)]].values
                if len(closes) < 1:
                    continue
                self.symbolData[added.Symbol] = SymbolData(closes[0], algorithm, added.Symbol)
            
        for removed in changes.RemovedSecurities:
            # Delete yesterday's close tracker
            symbol_data = self.symbolData.pop(removed.Symbol, None)
            if symbol_data:
                symbol_data.dispose()

class SymbolData:
    def __init__(self, yest_close, algo, symbol):
        self.yest_close = yest_close
        self.algo = algo
        self.symbol = symbol
        self.event = algo.Schedule.On(algo.DateRules.EveryDay(symbol), algo.TimeRules.AfterMarketOpen(symbol, 375), self.reset)
        self.max = Maximum(45*60) # 45 minutes
    
    def reset(self):
        self.max.Reset()
        
    def dispose(self):
        self.algo.Schedule.Remove(self.event)
        
        
        
class MaximumUnrealizedProfitPercentPerSecurity(RiskManagementModel):
    '''Provides an implementation of IRiskManagementModel that limits the unrealized profit per holding to the specified percentage'''

    def __init__(self, maximumUnrealizedProfitPercent = 0.1):
        '''Initializes a new instance of the MaximumUnrealizedProfitPercentPerSecurity class
        Args:
            maximumUnrealizedProfitPercent: The maximum percentage unrealized profit allowed for any single security holding, defaults to 5% drawdown per security'''
        self.maximumUnrealizedProfitPercent = abs(maximumUnrealizedProfitPercent)
        
    def ManageRisk(self, algorithm, targets):
        '''Manages the algorithm's risk at each time step
        Args:
            algorithm: The algorithm instance
            targets: The current portfolio targets to be assessed for risk'''
        targets = []
        for kvp in algorithm.Securities:
            security = kvp.Value

            if not security.Invested:
                continue

            pnl = security.Holdings.UnrealizedProfitPercent
            if pnl > self.maximumUnrealizedProfitPercent:

                ### For debugging, add this to see when it is being called
                algorithm.Log('Risk model triggered')

                # liquidate
                targets.append(PortfolioTarget(security.Symbol, 0))

        return targets