Overall Statistics
Total Trades
208
Average Win
0.83%
Average Loss
-0.54%
Compounding Annual Return
-76.282%
Drawdown
13.600%
Expectancy
-0.090
Net Profit
-5.370%
Sharpe Ratio
-1.064
Probabilistic Sharpe Ratio
28.301%
Loss Rate
64%
Win Rate
36%
Profit-Loss Ratio
1.53
Alpha
-1
Beta
2.371
Annual Standard Deviation
0.592
Annual Variance
0.351
Information Ratio
-1.399
Tracking Error
0.562
Treynor Ratio
-0.266
Total Fees
$270.53
Estimated Strategy Capacity
$97000.00
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect.Data.UniverseSelection import *
from QuantConnect.Indicators import ExponentialMovingAverage
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel

class TopGainersUniverseSelectionModel(FundamentalUniverseSelectionModel):
    
    def __init__(self,
                 Period = 1,
                 universeCount = 10,
                 universeSettings = None,
                 securityInitializer = None):
        
        super().__init__(False, universeSettings, securityInitializer)
        self.universeCount = universeCount
        
        self.stateData = { }

    def SelectCoarse(self, algorithm, coarse):
        
        for c in coarse:
            if c.Symbol not in self.stateData:
                self.stateData[c.Symbol] = self.SelectionData(c.Symbol, 1)

            avg = self.stateData[c.Symbol]
            avg.update(c.EndTime, c.Price, c.Volume)

        values = [x for x in self.stateData.values() if x.is_roc_positive and x.volume > 100000 and x.price > 1]
        
        values.sort(key=lambda x: x.roc, reverse=True)
        
        for x in values[:self.universeCount]:
            algorithm.Log('-symbol: ' + str(x.symbol.Value) + ' -Price:' + str(x.price) + '  -ROC: ' + str(x.roc))
        
        return [ x.symbol for x in values[:self.universeCount] ]

    class SelectionData:
        def __init__(self, symbol, period):
            self.symbol = symbol
            self.roc = RateOfChangePercent(period)
            self.is_roc_positive = False
            self.volume = 0
            self.price = 0 

        def update(self, time, price, volume):
            self.volume = volume
            self.price = price
            if self.roc.Update(time, price):
                self.is_roc_positive = self.roc.Current.Value > 0
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Common")

from AlphaCreation import ConstantAlphaModel
from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
from RiskManagement import MaximumDrawdownPercentPerSecurity
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
from UniverseSelection import TopGainersUniverseSelectionModel

from System import *
from QuantConnect import *
from QuantConnect.Data import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from System.Collections.Generic import List

class TopGainersUniverseSelect(QCAlgorithm):

    def Initialize(self):
        
        self.SetStartDate(2021,4,16)
        #self.SetEndDate(2021, 4, 23)    #Set End Date
        self.SetCash(10000)           #Set Strategy Cash
        self.UniverseSettings.Resolution = Resolution.Minute
        
        self.SetUniverseSelection(TopGainersUniverseSelectionModel())
        self.SetAlpha(ConstantAlphaModel())
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
        self.SetExecution(ImmediateExecutionModel())
        self.SetRiskManagement(MaximumDrawdownPercentPerSecurity())

        self.AddEquity("SPY")
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 5), self.rebalance)

    def rebalance(self):
        self.Liquidate()
from clr import AddReference
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from datetime import timedelta
from QuantConnect.Algorithm.Framework.Alphas import AlphaModel, Insight, InsightType, InsightDirection

class ConstantAlphaModel(AlphaModel):

    def __init__(self):
        self.period = timedelta(hours=6, minutes=30)
        self.securities = []
        self.insightsTimeBySymbol = {}
        self.ShouldEmitInsight = True
        self.Name = 'ConstantAlphaModel'
        
        self.symbols_by_time = {}


    def Update(self, algorithm, data):
        insights = []
        if self.ShouldEmitInsight:
            purchased_symbols = []
            for security in self.securities:
                if algorithm.Securities[security.Symbol].Price == 0:
                    continue
                if security.Symbol.Value == "SPY":
                    continue
                
                # If security bought two days in a row
                days_purchased = [security.Symbol in symbols for time, symbols in self.symbols_by_time.items()]
                if days_purchased and all(days_purchased):
                    algorithm.Debug(f"Skipping {security.Symbol} because it's been purchased 2 days in a row")
                    continue
                
                purchased_symbols.append(security.Symbol)

            if purchased_symbols:
                # Create insights
                for symbol in purchased_symbols:
                    insights.append(Insight.Price(symbol, self.period, InsightDirection.Up))
                self.ShouldEmitInsight = False
    
                # Delete old keys
                sorted_times = sorted(self.symbols_by_time.keys())
                for time in sorted_times[:-2]:
                    self.symbols_by_time.pop(time)
                self.symbols_by_time[data.Time] = purchased_symbols
                
        return insights


    def OnSecuritiesChanged(self, algorithm, changes):
        self.removedSecurities = []
        for added in changes.AddedSecurities:
            self.securities.append(added)
            self.ShouldEmitInsight = True

        # This will allow the insight to be re-sent when the security re-joins the universe
        for removed in changes.RemovedSecurities:
            self.removedSecurities.append(removed)
            self.ShouldEmitInsight = True
            if removed in self.securities:
                self.securities.remove(removed)
            if removed.Symbol in self.insightsTimeBySymbol:
                self.insightsTimeBySymbol.pop(removed.Symbol)
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Portfolio import PortfolioTarget
from QuantConnect.Algorithm.Framework.Risk import RiskManagementModel

class MaximumDrawdownPercentPerSecurity(RiskManagementModel):
    

    def __init__(self, maximumDrawdownPercent = 0.5):
        
        self.maximumDrawdownPercent = -abs(maximumDrawdownPercent)

    def ManageRisk(self, algorithm, targets):
        
        StartTime = algorithm.Time.replace(hour=9, minute=30, second=0)
            
        
            
        targets = []
        for kvp in algorithm.Securities:
            security = kvp.Value

            if not security.Invested:
                continue
            
            if algorithm.Time > StartTime:
                pnl = security.Holdings.UnrealizedProfitPercent
                if pnl <= self.maximumDrawdownPercent:
                    algorithm.Log(str(algorithm.Time) + 'Liquidating Due To MaxDrawdown: ' + str(security))
                    targets.append(PortfolioTarget(security.Symbol, 0))

        return targets
from clr import AddReference
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect import Resolution, Extensions
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from itertools import groupby
from datetime import datetime, timedelta

class EqualWeightingPortfolioConstructionModel(PortfolioConstructionModel):
    

    def __init__(self, rebalance = Resolution.Daily, portfolioBias = PortfolioBias.Long):
        
        self.portfolioBias = portfolioBias

        # If the argument is an instance of Resolution or Timedelta
        # Redefine rebalancingFunc
        rebalancingFunc = rebalance
        if isinstance(rebalance, int):
            rebalance = Extensions.ToTimeSpan(rebalance)
        if isinstance(rebalance, timedelta):
            rebalancingFunc = lambda dt: dt + rebalance
        if rebalancingFunc:
            self.SetRebalancingFunc(rebalancingFunc)

    def DetermineTargetPercent(self, activeInsights):
    
        result = {}

        # give equal weighting to each security
        count = sum(x.Direction != InsightDirection.Flat and self.RespectPortfolioBias(x) for x in activeInsights)
        percent = 0 if count == 0 else 1.0 / count
        for insight in activeInsights:
            result[insight] = (insight.Direction if self.RespectPortfolioBias(insight) else InsightDirection.Flat) * percent
        return result

    def RespectPortfolioBias(self, insight):

        return self.portfolioBias == PortfolioBias.Long or insight.Direction == self.portfolioBias