Overall Statistics |
Total Trades 365 Average Win 0.33% Average Loss -0.68% Compounding Annual Return 4.598% Drawdown 8.100% Expectancy 0.235 Net Profit 46.980% Sharpe Ratio 0.661 Probabilistic Sharpe Ratio 13.103% Loss Rate 17% Win Rate 83% Profit-Loss Ratio 0.49 Alpha 0.037 Beta 0.026 Annual Standard Deviation 0.06 Annual Variance 0.004 Information Ratio -0.472 Tracking Error 0.159 Treynor Ratio 1.5 Total Fees $514.61 |
class MovingAverageAlphaModel(AlphaModel): '''Alpha model based on Price crossing an SMA''' def __init__(self, smaLength=200, resolution=Resolution.Daily, predictionInterval=31): '''Initializes a new instance of the SmaAlphaModel class Args: period: The SMA period resolution: The reolution for the SMA''' self.smaLength = smaLength self.resolution = resolution self.predictionInterval = predictionInterval self.symbolDataBySymbol = {} self.month = -1 self.riskOffAsset = "IEF" def Update(self, algorithm, data): '''This is called each time the algorithm receives data for (@resolution of) subscribed securities Returns: The new insights generated. THIS: analysis only occurs at month start, so any signals intra-month are disregarded.''' if self.month == algorithm.Time.month: return [] self.month = algorithm.Time.month insights = [] riskOffWeight = riskOnWeight = 1 / len(self.symbolDataBySymbol) for symbol, symbolData in self.symbolDataBySymbol.items(): if symbol.Value == self.riskOffAsset: continue price = algorithm.Securities[symbol].Price # Reset indicator, get fresh historical data, pump into indicator symbolData.MovingAverage.Reset() history = algorithm.History([symbol], self.smaLength, self.resolution) for time, row in history.loc[symbol].iterrows(): symbolData.MovingAverage.Update(time, row["close"]) if price != 0 and symbolData.MovingAverage.IsReady: if price > symbolData.MovingAverage.Current.Value: insights.append( Insight.Price(symbol, timedelta(days=self.predictionInterval), InsightDirection.Up, None, None, None, riskOnWeight)) elif price < symbolData.MovingAverage.Current.Value: insights.append( Insight.Price(symbol, timedelta(days=self.predictionInterval), InsightDirection.Flat, None, None, None, 0) ) riskOffWeight += riskOnWeight insights.append( Insight.Price(self.riskOffAsset, timedelta(days=self.predictionInterval), InsightDirection.Up, None, None, None, riskOffWeight) ) return insights def OnSecuritiesChanged(self, algorithm, changes): for added in changes.AddedSecurities: # Get historical data & check for existence in symbolData history = algorithm.History([added.Symbol], self.smaLength, self.resolution) symbolData = self.symbolDataBySymbol.get(added.Symbol) if symbolData is None: # Create an instance, initialise Indicator, pump in history symbolData = SymbolData(added) symbolData.MovingAverage = algorithm.SMA(added.Symbol, self.smaLength, self.resolution) for time, row in history.loc[added.Symbol].iterrows(): symbolData.MovingAverage.Update(time, row["close"]) self.symbolDataBySymbol[added.Symbol] = symbolData else: # The security existed: reset indicators, restore history symbolData.MovingAverage.Reset() for time, row in history.loc[added.Symbol].iterrows(): symbolData.MovingAverage.Update(time, row["close"]) # TODO: Needs to be amended for when securites are removed. class SymbolData: def __init__(self, security): self.Security = security self.Symbol = security.Symbol self.MovingAverage = None
'''An implementation of Meb Faber's base model: Global Tactical Asset Allocation model (GTAA)(5) with 10-month SimpleMovingAverage Filter (200day) and (monthly rebalance), as found in the paper: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=962461 "A Quantitative Approach to Tactical Asset Allocation" published May 2006. Analysis only occurs at month End/Start, signals are NOT generated intra-month. ''' # self.Debug(str(dir( x ))) from alpha_model import MovingAverageAlphaModel class GlobalTacticalAssetAllocation(QCAlgorithm): def Initialize(self): self.SetStartDate(2011, 10, 29) # self.SetEndDate(2020, 5, 20) self.SetCash(100000) self.Settings.FreePortfolioValuePercentage = 0.02 self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.UniverseSettings.Resolution = Resolution.Daily symbols = [Symbol.Create(ticker, SecurityType.Equity, Market.USA) for ticker in [ "SPY", # US Large Cap ETF "VEA", # Developed Foreign Stocks (TradedSince: 2007/8)ETF "IEF", # US 10Y Gov.Bonds ETF "DBC", # GSCI Commodities ETF (TradedSince: 2006/3) "VNQ" # US RealEstate ETF ]] self.AddUniverseSelection( ManualUniverseSelectionModel(symbols) ) self.AddAlpha( MovingAverageAlphaModel() ) self.Settings.RebalancePortfolioOnInsightChanges = False self.Settings.RebalancePortfolioOnSecurityChanges = False self.SetPortfolioConstruction( InsightWeightingPortfolioConstructionModel(self.DateRules.MonthStart('SPY'), PortfolioBias.Long) ) self.SetExecution( ImmediateExecutionModel() ) self.AddRiskManagement( NullRiskManagementModel() )
class YourAlgorithm(QCAlgorithm): def Initialize(self): # 1) Setting a Benchmark to plot with equity self.benchmarkTicker = 'SPY' self.SetBenchmark(self.benchmarkTicker) self.initBenchmarkPrice = None def UpdateBenchmarkValue(self): ''' Simulate buy and hold the Benchmark ''' if self.initBenchmarkPrice is None: self.initBenchmarkCash = self.Portfolio.Cash self.initBenchmarkPrice = self.Benchmark.Evaluate(self.Time) self.benchmarkValue = self.initBenchmarkCash else: currentBenchmarkPrice = self.Benchmark.Evaluate(self.Time) self.benchmarkValue = (currentBenchmarkPrice / self.initBenchmarkPrice) * self.initBenchmarkCash def OnData(self, data): # 2) simulate buy and hold the benchmark and plot its daily value as we are using daily data. # Otherwise schedule when to call this function! self.UpdateBenchmarkValue() self.Plot('Strategy Equity', self.benchmarkTicker, self.benchmarkValue) ### _________________________________________________ # Plotting HoldingValues for kvp in self.Portfolio: symbol = kvp.Key holding = kvp.Value self.Debug(str(holding.Symbol)) self.Plot(f"{str(holding.Symbol)}HoldingValues", holding.HoldingsValue) ### _________________________________________________