Overall Statistics |
Total Trades
28
Average Win
8.09%
Average Loss
-7.70%
Compounding Annual Return
3.286%
Drawdown
26.800%
Expectancy
0.319
Net Profit
50.126%
Sharpe Ratio
0.295
Probabilistic Sharpe Ratio
0.283%
Loss Rate
36%
Win Rate
64%
Profit-Loss Ratio
1.05
Alpha
0.036
Beta
-0.023
Annual Standard Deviation
0.114
Annual Variance
0.013
Information Ratio
-0.255
Tracking Error
0.225
Treynor Ratio
-1.44
Total Fees
$239.16
|
# https://quantpedia.com/strategies/riding-industry-bubbles/ # # The investment universe consists of equity industry funds (or ETFs) which are proxy for equity industry indexes. Investor uses 10 years of # past data to calculate industry’s alpha based on CAPM model (from the regression model industry_return = alpha + beta*market return, it is # possible to use alternative models like the Fama/French 3 factor model). A bubble in an industry is detected if the industry’s alpha is # statistically significant (source academic paper uses 97,5% significance threshold, but it is possible to use other values). Investor is # long in each industry experiencing a bubble by applying 1/N rule (investment is divided equally between industries in bubble). If no bubble # is detected then he/she makes no investment. Data examination, alpha calculation and portfolio rebalancing is done on monthly basis. from collections import deque import numpy as np class Riding_Industry_Bubbles(QCAlgorithm): def Initialize(self): self.SetStartDate(2008, 1, 1) self.SetCash(100000) self.spy = 'SPY' self.symbols = ['XLF', 'XLV', 'XLP', 'XLY', 'XLI', 'XLE', 'XLB', 'XLK', 'XLU'] self.period = 10 * 12 * 21 self.SetWarmUp(self.period) # Daily price data. self.data = {} for symbol in self.symbols + [self.spy]: data = self.AddEquity(symbol, Resolution.Daily) self.data[symbol] = deque(maxlen=self.period) self.Schedule.On(self.DateRules.MonthStart(self.symbols[0]), self.TimeRules.AfterMarketOpen(self.symbols[0]), self.Rebalance) def OnData(self, data): for symbol in self.symbols + [self.spy]: if self.Securities.ContainsKey(symbol): price = self.Securities[symbol].Price if price != 0: self.data[symbol].append(price) else: # Append latest price as a next one in case there's 0 as price. if len(self.data[symbol]) > 0: last_price = self.data[symbol][-1] self.data[symbol].append(last_price) def Rebalance(self): if len(self.data[self.spy]) != self.data[self.spy].maxlen: return market_closes = [x for x in self.data[self.spy]] separete_months = [market_closes[x:x+21] for x in range(0, len(market_closes),21)] market_monthly_returns = [] for month in separete_months: market_monthly_returns.append(self.Return([x for x in month])) market_returns_mean = np.mean(market_monthly_returns) t_stat = {} for symbol in self.symbols: if len(self.data[symbol]) == self.data[symbol].maxlen: closes = [x for x in self.data[symbol]] separete_months = [closes[x:x+21] for x in range(0, len(closes),21)] etf_monthly_returns = [] for month in separete_months: etf_monthly_returns.append(self.Return([x for x in month])) etf_returns_mean = np.mean(etf_monthly_returns) # t-stat calc. diffs = [] for a,b in zip(etf_monthly_returns, market_monthly_returns): diffs.append(a-b) diff_std = np.std(diffs) t_stat[symbol] = (etf_returns_mean - market_returns_mean) / (diff_std / np.sqrt(len(etf_monthly_returns))) long = [] if len(t_stat) != 0: long = [x[0] for x in t_stat.items() if x[1] >= 2] # Trade execution. invested = [x.Key.Value for x in self.Portfolio if x.Value.Invested] for symbol in invested: if symbol not in long: self.Liquidate(symbol) for symbol in long: self.SetHoldings(symbol, 1 / len(long)) def Return(self, history): return (history[-1] - history[0]) / history[0]