| 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 = []