| Overall Statistics |
|
Total Trades 1875 Average Win 2.18% Average Loss -2.01% Compounding Annual Return 31.632% Drawdown 55.400% Expectancy 0.218 Net Profit 3057.588% Sharpe Ratio 0.781 Probabilistic Sharpe Ratio 8.569% Loss Rate 42% Win Rate 58% Profit-Loss Ratio 1.09 Alpha 0.215 Beta 0.883 Annual Standard Deviation 0.387 Annual Variance 0.15 Information Ratio 0.558 Tracking Error 0.365 Treynor Ratio 0.342 Total Fees $22371.17 Estimated Strategy Capacity $3400000.00 Lowest Capacity Asset UPRO UDQRQQYTO12D Portfolio Turnover 16.25% |
#region imports
from AlgorithmImports import *
class ParticleQuantumChamber(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2011, 1, 1)
# self.SetEndDate(2020, 6, 15)
self.SetCash(10000)
self.upro = self.AddEquity('UPRO', Resolution.Daily).Symbol # UPRO = 3x levered SPX
self.shy = self.AddEquity('SHY', Resolution.Daily).Symbol # SHY = short term Treasury ETF
self.spy = self.AddEquity('SPY', Resolution.Daily).Symbol # SPY = S&P 500 ETF
self.uvxy = self.AddEquity('UVXY', Resolution.Daily).Symbol #
self.tmf = self.AddEquity('TMF', Resolution.Daily).Symbol #
self.vix = self.AddEquity('VIX', Resolution.Daily).Symbol #
self.tecl = self.AddEquity('TECL', Resolution.Daily).Symbol #
self.sh = self.AddEquity('SH', Resolution.Daily).Symbol #
self.tlt = self.AddEquity('TLT', Resolution.Daily).Symbol #
self.spxu = self.AddEquity('SPXU', Resolution.Daily).Symbol #
self.sphb = self.AddEquity('SPHB', Resolution.Daily).Symbol
self.bsv = self.AddEquity('BSV', Resolution.Daily).Symbol
self.qqq = self.AddEquity('QQQ', Resolution.Daily).Symbol #
self.iei = self.AddEquity('IEI', Resolution.Daily).Symbol #
# Register to receive data for the 'SPY' symbol
# self.AddEquity('SPY', Resolution.Daily)
self.SetWarmup(200)
self.investpercent = 1
self.SetBenchmark(self.spy)
self.UniverseSettings.Resolution = Resolution.Daily
# self.SetAlpha(EtfSmaAlphaModel(self.spy, self.upro, self.shy))
# self.SetUniverseSelection(ManualUniverseSelectionModel([self.upro, self.shy, self.spy]))
self.SetExecution(ImmediateExecutionModel())
# self.SetBrokerageModel(AlphaStreamsBrokerageModel())
# Setting the account type in the brokerage model
# self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Cash) # 3 days for portfolio to receive cash from sale of a stock
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) # avoids simulating order settlement with margin (or simply don't use a brokerage model but may have inaccurate fees)
# self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) # all insights are equal weight
self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel()) # insights' weighting determines portfolio allocation
# Investigate backing out and resetting after 2 weeks?
# self.SetRiskManagement(MaximumDrawdownPercentPortfolio(0.1)) # Run to cash at 10% drawdown
# self.riskedSecurities = set()
# self.SetRiskManagement(MaximumDrawdownPercentPerSecurity(0.1)) # 10% drawdown
# self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Friday), self.TimeRules.At(9, 30), self.riskedSecurities.clear())
# Create a custom chart
stockPlot = Chart("Stock Plot")
stockPlot.AddSeries(Series("SPY", SeriesType.Line))
stockPlot.AddSeries(Series("UPRO", SeriesType.Line))
stockPlot.AddSeries(Series("SHY", SeriesType.Line))
stockPlot.AddSeries(Series("200d EMA", SeriesType.Line)) # Add 200d EMA series
stockPlot.AddSeries(Series("10d RSI", SeriesType.Line))
stockPlot.AddSeries(Series("60d RSI", SeriesType.Line))
stockPlot.AddSeries(Series("Cash", SeriesType.Line))
stockPlot.AddSeries(Series("Unsettled Cash", SeriesType.Line))
self.AddChart(stockPlot)
# Initialize EMA
self.ema30spy = self.EMA(self.spy, 30, Resolution.Daily)
self.ema200spy = self.EMA(self.spy, 200, Resolution.Daily)
self.rsi10spy = self.RSI(self.spy, 10, MovingAverageType.Simple, Resolution.Daily)
self.rsi10qqq = self.RSI(self.qqq, 10, MovingAverageType.Simple, Resolution.Daily)
self.rsi10tlt = self.RSI(self.tlt, 10, MovingAverageType.Simple, Resolution.Daily)
self.rsi10sh = self.RSI(self.sh, 10, MovingAverageType.Simple, Resolution.Daily)
self.rsi10spxu = self.RSI(self.spxu, 10, MovingAverageType.Simple, Resolution.Daily)
self.rsi60spy = self.RSI(self.spy, 60, MovingAverageType.Simple, Resolution.Daily)
self.rsi60tlt = self.RSI(self.tlt, 60, MovingAverageType.Simple, Resolution.Daily)
self.rsi14iei = self.RSI(self.iei, 14, MovingAverageType.Simple, Resolution.Daily)
self.rsi14sphb = self.RSI(self.sphb, 14, MovingAverageType.Simple, Resolution.Daily)
self.rsi7bsv = self.RSI(self.bsv, 7, MovingAverageType.Simple, Resolution.Daily)
self.rsi7sphb = self.RSI(self.sphb, 7, MovingAverageType.Simple, Resolution.Daily)
def liquidate_all_positions_except(self, symbol_to_keep):
for holding in self.Portfolio.Values:
if holding.Symbol != symbol_to_keep and holding.Invested:
self.Liquidate(holding.Symbol)
def OnData(self, data):
if self.IsWarmingUp:
return
# if no spy data, skip
if not data.ContainsKey(self.spy):
return
if not data.ContainsKey(self.uvxy):
return
if self.spy in data and data[self.spy] is not None:
self.Plot("Stock Plot", "SPY", data[self.spy].Close)
self.Plot("Stock Plot", "200d EMA", self.ema200spy.Current.Value) # Plot 200d EMA
self.Plot("Stock Plot", "10d RSI", self.rsi10spy.Current.Value)
self.Plot("Stock Plot", "60d RSI", self.rsi60spy.Current.Value)
if self.upro in data and data[self.upro] is not None:
self.Plot("Stock Plot", "UPRO", data[self.upro].Close)
if self.shy in data and data[self.shy] is not None:
self.Plot("Stock Plot", "SHY", data[self.shy].Close)
self.Plot("Stock Plot", "Cash", self.Portfolio.Cash)
self.Plot("Stock Plot", "Unsettled Cash", self.Portfolio.UnsettledCash)
self.invested_value = sum([x.HoldingsValue for x in self.Portfolio.Values]) # Calculate the currently invested value
self.percent_invested = (self.invested_value / self.Portfolio.TotalPortfolioValue) * 100 # Calculate the percentage invested
# allocation = self.Portfolio[stock_symbol].Percentage
# self.Log(f"{stock_symbol} allocation: {allocation * 100:.2f}%")
# Plotting Cash Amounts
self.Plot("Portfolio Info", "Cash", self.Portfolio.Cash)
self.Plot("Portfolio Info", "Unsettled Cash", self.Portfolio.UnsettledCash)
self.Plot("Portfolio Info", "Percent Invested", self.percent_invested)
# Set timedelta as an instance variable
self.timedelta = timedelta(days=1)
insights = []
if data[self.spy].Close > self.ema200spy.Current.Value:
if self.rsi10spy.Current.Value > 80: #
# invest in uxvy
insights.append(Insight.Price(self.uvxy, self.timedelta, InsightDirection.Up, weight=self.investpercent))
self.Log(f"Insight allocation: {self.investpercent * 100:.2f}% in {self.uvxy}")
else:
if self.rsi60spy.Current.Value > 60: #
# invest in tmf or vixy (add inv volatility here later)
########## ADD VOLATILITY LATER ###########
#### TMF VS VIXY HERE
insights.append(Insight.Price(self.tmf, self.timedelta, InsightDirection.Up, weight=self.investpercent))
self.Log(f"Insight allocation: {self.investpercent * 100:.2f}% in {self.tmf}")
else:
# invest in upro
insights.append(Insight.Price(self.upro, self.timedelta, InsightDirection.Up, weight=self.investpercent))
self.Log(f"Insight allocation: {self.investpercent * 100:.2f}% in {self.upro}")
else: # spy close <= ema
if self.rsi10qqq.Current.Value < 30:
# set to tecl
insights.append(Insight.Price(self.tecl, self.timedelta, InsightDirection.Up, weight=self.investpercent))
self.Log(f"Insight allocation: {self.investpercent * 100:.2f}% in {self.tecl}")
else:
if self.rsi60tlt.Current.Value < 45:
#### HALF IN THIS BLOCK ####
if data[self.spy].Close > self.ema30spy.Current.Value:
if self.rsi10spy.Current.Value > 70:
# set to SH
insights.append(Insight.Price(self.sh, self.timedelta, InsightDirection.Up, weight=self.investpercent/2))
self.Log(f"Insight allocation: {self.investpercent/2 * 100:.2f}% in {self.sh}")
else:
# set to upro
insights.append(Insight.Price(self.upro, self.timedelta, InsightDirection.Up, weight=self.investpercent/2))
self.Log(f"Insight allocation: {self.investpercent/2 * 100:.2f}% in {self.upro}")
else: # between tlt and sh 10drsi select top1
if self.rsi10tlt.Current.Value > self.rsi10sh.Current.Value:
#invest in tlt
insights.append(Insight.Price(self.tlt, self.timedelta, InsightDirection.Up, weight=self.investpercent/2))
self.Log(f"Insight allocation: {self.investpercent/2 * 100:.2f}% in {self.tlt}")
else:
insights.append(Insight.Price(self.sh, self.timedelta, InsightDirection.Up, weight=self.investpercent/2))
self.Log(f"Insight allocation: {self.investpercent/2 * 100:.2f}% in {self.sh}")
#### END HALF IN THIS BLOCK ####
#### HALF IN THIS BLOCK ####
if self.rsi14iei.Current.Value < self.rsi14sphb.Current.Value:
if self.rsi7bsv.Current.Value < self.rsi7sphb.Current.Value:
# invest in sh
insights.append(Insight.Price(self.sh, self.timedelta, InsightDirection.Up, weight=self.investpercent/2))
self.Log(f"Insight allocation: {self.investpercent/2 * 100:.2f}% in {self.sh}")
else:
#invest in upro
insights.append(Insight.Price(self.upro, self.timedelta, InsightDirection.Up, weight=self.investpercent/2))
self.Log(f"Insight allocation: {self.investpercent/2 * 100:.2f}% in {self.upro}")
else:
#invest in upro
insights.append(Insight.Price(self.upro, self.timedelta, InsightDirection.Up, weight=self.investpercent/2))
self.Log(f"Insight allocation: {self.investpercent/2 * 100:.2f}% in {self.upro}")
#### END HALF IN THIS BLOCK ####
else: #
if data[self.spy].Close > self.ema30spy.Current.Value:
if self.rsi10spy.Current.Value > 70:
# invest in sh
insights.append(Insight.Price(self.sh, self.timedelta, InsightDirection.Up, weight=self.investpercent))
self.Log(f"Insight allocation: {self.investpercent * 100:.2f}% in {self.sh}")
else:
# invest in upro
insights.append(Insight.Price(self.upro, self.timedelta, InsightDirection.Up, weight=self.investpercent))
self.Log(f"Insight allocation: {self.investpercent * 100:.2f}% in {self.upro}")
else: # between tlt and spxu 10drsi select top1
if self.rsi10tlt.Current.Value > self.rsi10spxu.Current.Value: #invest in tlt
insights.append(Insight.Price(self.tlt, self.timedelta, InsightDirection.Up, weight=self.investpercent))
self.Log(f"Insight allocation: {self.investpercent * 100:.2f}% in {self.tlt}")
else:
insights.append(Insight.Price(self.spxu, self.timedelta, InsightDirection.Up, weight=self.investpercent))
self.Log(f"Insight allocation: {self.investpercent * 100:.2f}% in {self.spxu}")
# Group insights and return
if insights:
self.EmitInsights(Insight.Group(insights))