Overall Statistics
Total Orders
7430
Average Win
0.18%
Average Loss
-0.20%
Compounding Annual Return
24.293%
Drawdown
42.900%
Expectancy
0.475
Start Equity
100000
End Equity
3347888.90
Net Profit
3247.889%
Sharpe Ratio
0.727
Sortino Ratio
0.754
Probabilistic Sharpe Ratio
10.692%
Loss Rate
22%
Win Rate
78%
Profit-Loss Ratio
0.88
Alpha
0.069
Beta
1.275
Annual Standard Deviation
0.244
Annual Variance
0.06
Information Ratio
0.554
Tracking Error
0.167
Treynor Ratio
0.139
Total Fees
$26666.36
Estimated Strategy Capacity
$3500000.00
Lowest Capacity Asset
UGL U85WJOCE24BP
Portfolio Turnover
2.12%
Drawdown Recovery
826
#  Trend Rocket Strategy from LiveFolio 
#  www.livefol.io/strategies/dmZN1x3Lx8g
#  This strategy monitors the price of SPYSIM daily.
#  It holds a leveraged growth sleeve when the 5-day simple average of SPYSIM is greater than its 200-day simple average. 
#  The growth sleeve consists of 33.34% TQQQ (3x Nasdaq 100), 33.33% UGL (2x Gold), and 33.33% UPRO (3x S&P 500).
#  If the 5-day average is equal to or less than the 200-day average, it switches to a secondary sleeve consisting of 33.34% GLD, 33.33% AGG, and 33.33% SPY.


# region imports
from AlgorithmImports import *
# endregion

class TacticalAssetAllocation(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2010, 1, 31)
        self.set_cash(100000)
        self.set_warmup(200, Resolution.DAILY)
        
        # Enable seed prices to ensure indicators have data
        self.settings.seed_initial_prices = True
        
        # Add SPY for signal generation
        spy = self.add_equity("SPY", Resolution.DAILY)
        self._spy = spy.symbol
        
        # Growth sleeve (leveraged)
        self._tqqq = self.add_equity("TQQQ", Resolution.MINUTE).symbol
        self._ugl = self.add_equity("UGL", Resolution.MINUTE).symbol
        self._upro = self.add_equity("UPRO", Resolution.MINUTE).symbol
        
        # Defensive sleeve
        self._gld = self.add_equity("GLD", Resolution.MINUTE).symbol
        self._agg = self.add_equity("AGG", Resolution.MINUTE).symbol
        
        # Create moving averages for SPY
        self._sma_5 = self.sma(self._spy, 5, Resolution.DAILY)
        self._sma_200 = self.sma(self._spy, 200, Resolution.DAILY)
        
        # Schedule signal evaluation at 3:30 PM ET
        self.schedule.on(self.date_rules.every_day(self._spy),
                        self.time_rules.at(15, 30),
                        self._evaluate_signal)
        
        # Schedule order placement at 3:59 PM ET
        self.schedule.on(self.date_rules.every_day(self._spy),
                        self.time_rules.at(15, 59),
                        self._place_orders)
        
        self._targets = []
        self._initialized = False
    
    def on_data(self, data: Slice):
        """Check if indicators are ready and enter initial positions"""
        if not self._initialized and self._sma_5.is_ready and self._sma_200.is_ready:
            self._evaluate_signal()
            self._place_orders()
            self._initialized = True
    
    def _evaluate_signal(self):
        """Evaluate the moving average signal at 3:30 PM ET"""
        # Wait for indicators to be ready
        if not self._sma_5.is_ready or not self._sma_200.is_ready:
            return
        
        # Check if 5-day SMA is above 200-day SMA
        if self._sma_5.current.value > self._sma_200.current.value:
            # Growth sleeve: TQQQ, UGL, UPRO
            self._targets = [
                PortfolioTarget(self._tqqq, 0.3334),
                PortfolioTarget(self._ugl, 0.3333),
                PortfolioTarget(self._upro, 0.3333)
            ]
        else:
            # Defensive sleeve: GLD, AGG, SPY
            self._targets = [
                PortfolioTarget(self._gld, 0.3334),
                PortfolioTarget(self._agg, 0.3333),
                PortfolioTarget(self._spy, 0.3333)
            ]
    
    def _place_orders(self):
        """Place orders at 3:59 PM ET to execute at market close"""
        if len(self._targets) > 0:
            # Liquidate existing holdings and set new targets
            self.set_holdings(self._targets, liquidate_existing_holdings=True)
            self._targets = []