Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -0.47 Tracking Error 0.16 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset |
#Rising Assets Strategy Rules #1. On the last business day of every month, invest in the top 5 assets with the highest #momentum score. #2. Sell any asset that was previously in the top 5 but has since dropped out. #3. Weight each asset by the inverse of its 63-day historical volatility. #Momentum Score #Our momentum score is the average of the last 1mo, 3mo, 6mo and 12mo trailing total #returns. #We opt for an unoptimized average of lookbacks. This is consistent with the method #Momentum Score Example:SPY 1 Month Return = +2.0% #SPY 3 Month Return = -4.0% #SPY 6 Month Return = +11.0% #SPY 12 Month Return = +8.0% #Average Return = (2% - 4% + 11% + 8%) / 4 = 4.25% #Result is a Momentum Score of 4.25% #Inverse Volatility Asset Weights #Asset weights are equivalent to the inverse of each asset’s trailing 3-month (63 trading #days) historical volatility. Volatility here is measured by the standard deviation of each #ETF’s daily returns. #This step serves to increase diversification in the portfolio as inverse weighting every #asset avoids one volatile asset from dominating the portfolio. #The typical effect of this step, compared to equal weighting the assets, is a slight decrease in #returns but a larger decrease in risk. This increases the return / risk metrics such as the #Sharpe Ratio. #Inverse Volatility Example: #SPY Std Dev = 0.10 #EEM Std Dev = 0.20 #Take 1 divided by each Std Dev observations and sum the results: #SPY 1 / 0.10 = 10 #EEM 1 / 0.20 = 5 #10 + 5 = 15 #Divide each by the sum to get percent capital allocation: #SPY 10 / 15 = 0.666 #EEM 5 / 15 = 0.333 #Result is a 66.6% allocation to SPY and a 33.3% allocation to EEM #region imports from AlgorithmImports import * #endregion from math import ceil,floor from datetime import datetime import pandas as pd import numpy as np from sklearn.linear_model import LinearRegression class TrendFollowingAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2004, 11, 1) self.SetEndDate(datetime.now()) self.SetCash(100000) self.AddEquity("SPY", Resolution.Daily) self.SymbolData = [] self.LastRotationTime = datetime.min self.RotationInterval = timedelta(days=30) self.first = True etfs = [ # Equity 'SPY', # S&P 500 'IWM', # US Small cap 'QQQ', # NASDAQ 'EFA', #Developed Ex US 'EEM', #Emerging markets 'VNQ', #US RealEstate 'LQD', #US Inv. Grade Crops # Fixed incomet 'GLD', # Treasury Bond 'SHY', # High yield bond 'IEF', # 'TLT', # 'AGG' ] self.SymbolData = [] for symbol in etfs: self.AddSecurity(SecurityType.Equity, symbol, Resolution.Minute) self.oneMonthPerformance = self.MOMP(symbol, 30, Resolution.Daily) self.threeMonthPerformance = self.MOMP(symbol, 90, Resolution.Daily) self.sixMonthPerformance = self.MOMP(symbol, 180, Resolution.Daily) self.twelveMonthPerformance = self.MOMP(symbol, 365, Resolution.Daily) self.SymbolData.append([symbol, self.oneMonthPerformance, self.threeMonthPerformance, self.sixMonthPerformance, self.twelveMonthPerformance]) self.SetBenchmark("SPY") # perform calculations for asset weightings def OnData(self, data): if self.first: self.first = False self.LastRotationTime = self.Time return delta = self.Time - self.LastRotationTime if delta > self.RotationInterval: self.LastRotationTime = self.Time momentumObjScores = sorted(self.SymbolData, key=lambda x: MomentumScore(x[1].Current.Value,x[2].Current.Value,x[3].Current.Value,x[4].Current.Value).CalculateMomentumScore(), reverse=True) for x in momentumObjScores: self.Log(">>SCORE>>" + x[0] + ">>" + str(MomentumScore(x[1].Current.Value,x[2].Current.Value,x[3].Current.Value,x[4].Current.Value).CalculateMomentumScore())) class MomentumScore(object): def __init__(self,oneMonthPerformanceValue,threeMonthPerformanceValue, sixMonthPerformanceValue, twelveMonthPerformanceValue): self.oneMonthPerformance = oneMonthPerformanceValue self.threeMonthPerformance = threeMonthPerformanceValue self.sixMonthPerformance = sixMonthPerformanceValue self.twelveMonthPerformance = twelveMonthPerformanceValue def CalculateMomentumScore(self): weight = 4 return (self.oneMonthPerformance + self.threeMonthPerformance + self.sixMonthPerformance + self.twelveMonthPerformance) / (weight)