Overall Statistics
Total Orders
1579
Average Win
0.31%
Average Loss
-0.30%
Compounding Annual Return
15.910%
Drawdown
14.100%
Expectancy
0.129
Start Equity
1000000
End Equity
1359330.74
Net Profit
35.933%
Sharpe Ratio
0.605
Sortino Ratio
0.473
Probabilistic Sharpe Ratio
41.420%
Loss Rate
44%
Win Rate
56%
Profit-Loss Ratio
1.03
Alpha
0.052
Beta
0.467
Annual Standard Deviation
0.126
Annual Variance
0.016
Information Ratio
0.18
Tracking Error
0.132
Treynor Ratio
0.163
Total Fees
$5068.74
Estimated Strategy Capacity
$25000000.00
Lowest Capacity Asset
MTUM VFUDGZIY8ZMT
Portfolio Turnover
12.23%
#region imports
from AlgorithmImports import *
#endregion
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Orders import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Selection import *
from Alphas.HistoricalReturnsAlphaModel import HistoricalReturnsAlphaModel
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Risk import *
#from Portfolio.BlackLittermanOptimizationPortfolioConstructionModel import *
#from Portfolio.UnconstrainedMeanVariancePortfolioOptimizer import UnconstrainedMeanVariancePortfolioOptimizer
#from Risk.NullRiskManagementModel import NullRiskManagementModel
#from Alphas.EmaCrossAlphaModel import EmaCrossAlphaModel
#from Alphas.HistoricalReturnsAlphaModel import HistoricalReturnsAlphaModel
#from Alphas.MacdAlphaModel import MacdAlphaModel
#from Alphas.RsiAlphaModel import RsiAlphaModel
#from Alphas.ConstantAlphaModel import ConstantAlphaModel
from collections import deque
from AlgorithmImports import *

class EnergeticSkyBlueFrog(QCAlgorithm):

    def Initialize(self):
        
        self.SetStartDate(2022, 3, 1) 
        self.SetEndDate(2024,3,31)
        self._cash= 1000000
        self.SetCash(self._cash)  
        
        #self.SetWarmUp(5)
        
        
        
        
        self.UniverseSettings.Resolution = Resolution.Daily
        symbols = [ # OUR INVESTMENT UNIVERSE
                    # FACTORS
                    Symbol.Create("USMV", SecurityType.Equity, Market.USA),
                    Symbol.Create("DGRO", SecurityType.Equity, Market.USA),
                    Symbol.Create("QUAL", SecurityType.Equity, Market.USA),
                    Symbol.Create("DVY", SecurityType.Equity, Market.USA),
                    Symbol.Create("MTUM", SecurityType.Equity, Market.USA),
                    Symbol.Create("VLUE", SecurityType.Equity, Market.USA),
                    Symbol.Create("TLT", SecurityType.Equity, Market.USA)]
        
        
        self.SetUniverseSelection(ManualUniverseSelectionModel(symbols))

        self.AddAlpha(HistoricalReturnsAlphaModel(2, resolution = Resolution.Daily))
        self.AddAlpha(EmaCrossAlphaModel(fastPeriod=5, slowPeriod=10, resolution = Resolution.Daily ))
        self.AddAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(days = 1), 0.025, None))
       
        
        optimizer = UnconstrainedMeanVariancePortfolioOptimizer()

        
        self.SetPortfolioConstruction(BlackLittermanOptimizationPortfolioConstructionModel(optimizer = optimizer, tau=0.10))
        self.SetExecution(ImmediateExecutionModel())
        #self.AddRiskManagement(MaximumDrawdownPercentPortfolio(0.05, isTrailing=False))
        self.riskManagement = TrailingPeriodDrawdownRiskManagementModel(0.03, 10) # 10 trading days as trailing period
        self.AddRiskManagement(self.riskManagement)
        
        
        self._benchmark = self.AddEquity("SPY", Resolution.Daily).Symbol
        self._benchmarkInitial = self.History(self._benchmark, 1, Resolution.Daily)
        self._benchmarkPrice = self._benchmarkInitial['close'][0]
        
    def OnData(self,data):
        
        self.Plot("Relative Performance", "SPY", self._cash*self.Securities["SPY"].Close/self._benchmarkPrice)
        self.Plot("Relative Performance", "Portfolio Value", self.Portfolio.TotalPortfolioValue)



class TrailingPeriodDrawdownRiskManagementModel(RiskManagementModel):
    def __init__(self, maxDrawdownPercent, trailingPeriod):
        self.maxDrawdownPercent = maxDrawdownPercent
        self.trailingPeriod = trailingPeriod
        self.portfolioHighs = deque(maxlen=trailingPeriod)
        
    def ManageRisk(self, algorithm, targets):
        currentPortfolioValue = algorithm.Portfolio.TotalPortfolioValue
        self.portfolioHighs.append(currentPortfolioValue)
        
        trailingMax = max(self.portfolioHighs)
        
        if currentPortfolioValue < trailingMax * (1 - self.maxDrawdownPercent):
            # Liquidate all positions if drawdown exceeds the limit
            return [PortfolioTarget(symbol, 0) for symbol in algorithm.Portfolio.Keys]
        
        return []