Overall Statistics |
Total Trades 268 Average Win 0.10% Average Loss -0.12% Compounding Annual Return 3.942% Drawdown 47.400% Expectancy 0.087 Net Profit 21.346% Sharpe Ratio 0.298 Probabilistic Sharpe Ratio 5.678% Loss Rate 41% Win Rate 59% Profit-Loss Ratio 0.83 Alpha 0.025 Beta 0.756 Annual Standard Deviation 0.212 Annual Variance 0.045 Information Ratio 0.121 Tracking Error 0.107 Treynor Ratio 0.084 Total Fees $274.90 |
from clr import AddReference AddReference("QuantConnect.Common") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Algorithm.Framework") AddReference("QuantConnect.Indicators") from QuantConnect import * from QuantConnect.Indicators import * from QuantConnect.Algorithm import * from QuantConnect.Algorithm.Framework import * from QuantConnect.Algorithm.Framework.Alphas import * class SmaAlphaModel(AlphaModel): '''Alpha model that uses an EMA cross to create insights''' 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 = {} def Update(self, algorithm, data): '''This is called each time the algorithm receives data for (@resolution of) subscribed securities Returns: The new insights generated''' insights = [] for symbol, symbolData in self.symbolDataBySymbol.items(): insights.append(Insight.Price(symbolData.Symbol, timedelta(days=self.predictionInterval), InsightDirection.Up)) return insights def OnSecuritiesChanged(self, algorithm, changes): '''Event fired each time the we add/remove securities from the data feed Args: algorithm: The algorithm instance that experienced the change in securities changes: The security additions and removals from the algorithm''' 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: has not been added to self.symbolDataBySymbol! class SymbolData: '''Contains data specific to a symbol required by this model''' 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) Buy&Hold portfolio (monthly rebalance), as found in the paper: "A Quantitative Approach to Tactical Asset Allocation" published May 2006. ''' from SmaAlphaModel import * class GlobalTacticalAssetAllocationBase(QCAlgorithm): def Initialize(self): backtestDuration = 365*10 self.SetStartDate(2008, 1, 1) # (datetime.now() - timedelta(backtestDuration)) self.SetEndDate(2013,1,1) # (datetime.now()) self.SetCash(100000) self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.UniverseSettings.Resolution = Resolution.Minute 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( SmaAlphaModel() ) self.AddAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(days = backtestDuration), None, None)) self.Settings.RebalancePortfolioOnInsightChanges = False self.Settings.RebalancePortfolioOnSecurityChanges = False self.SetPortfolioConstruction( EqualWeightingPortfolioConstructionModel(self.DateRules.MonthEnd("SPY")) ) self.SetExecution( ImmediateExecutionModel() ) self.AddRiskManagement( NullRiskManagementModel() ) # 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)