| Overall Statistics |
|
Total Trades 461 Average Win 1.68% Average Loss -0.51% Compounding Annual Return 8.031% Drawdown 19.100% Expectancy 1.238 Net Profit 416.897% Sharpe Ratio 0.724 Probabilistic Sharpe Ratio 6.423% Loss Rate 48% Win Rate 52% Profit-Loss Ratio 3.31 Alpha 0.07 Beta 0.01 Annual Standard Deviation 0.098 Annual Variance 0.01 Information Ratio -0.008 Tracking Error 0.201 Treynor Ratio 6.77 Total Fees $461.37 Estimated Strategy Capacity $29000000.00 |
class SectorAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2000, 1, 1)
self.SetCash(10000)
self.Settings.FreePortfolioValuePercentage = 0.05
# Daily indicator data.
self.s_indicators = {}
self.b_indicators = {}
self.period = 200
self.sectors_in = 0
self.SetWarmUp(self.period)
self.sectors = [
"XRLE", # Real Estate SPDR Fund
"XLK", # Technology Select Sector SPDR Fund
"XLE", # Energy Select Sector SPDR Fund
"XLV", # Health Care Select Sector SPDR Fund
"XLF", # Financial Select Sector SPDR Fund
"XLI", # Industrials Select Sector SPDR Fund
"XLB", # Materials Select Sector SPDR Fund
"XLY", # Consumer Discretionary Select Sector SPDR Fund
"XLP", # Consumer Staples Select Sector SPDR Fund
"XLU", # Utilities Select Sector SPDR Fund
#"XLC", # Communication Services SPDR Fund
]
self.bonds = ["TLT", # iShares 20 Plus Year Treasury Bond ETF
]
self.SetBenchmark('SPY')
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
for sector in self.sectors:
symbol = self.AddEquity(sector, Resolution.Daily).Symbol
self.s_indicators[symbol] = SymbolData(self, symbol, self.period)
for bond in self.bonds:
symbol = self.AddEquity(bond, Resolution.Daily).Symbol
self.b_indicators[symbol] = SymbolData(self, symbol, self.period)
self.plot_allocation = Chart('Allocation')
self.Schedule.On(self.DateRules.MonthStart(self.sectors[0]), self.TimeRules.AfterMarketOpen(self.sectors[0]), self.Rebalance)
#self.Schedule.On(self.DateRules.WeekStart(self.sectors[0]), self.TimeRules.AfterMarketOpen(self.sectors[0]), self.Rebalance)
self.Schedule.On(self.DateRules.EveryDay(self.sectors[0]), self.TimeRules.BeforeMarketClose(self.sectors[0], 1), self.PlotData)
def Rebalance(self):
n_sectors = len(self.sectors)
n_bonds = len(self.bonds)
in_out_sectors = 0
# Sectors ETF
for sector in self.s_indicators:
if self.s_indicators[sector].sell:
if self.Portfolio[sector].Invested:
in_out_sectors -= 1
# Sell sector ETF
self.Liquidate(sector)
if self.s_indicators[sector].buy:
if not self.Portfolio[sector].Invested:
in_out_sectors += 1
# Buy sector ETF
self.SetHoldings(sector, 1 / n_sectors)
# Update number of long ETF
self.sectors_in = self.sectors_in + in_out_sectors
# Bonds
for bond in self.b_indicators:
# Sell bonds
if self.b_indicators[bond].sell and self.Portfolio[bond].Invested:
# Sell bonds
self.Liquidate(bond)
# if bond pct must change, adjust the size of position
if in_out_sectors:
if self.b_indicators[bond].buy:
# New size
bond_pct = ((n_sectors - self.sectors_in) / n_sectors) / n_bonds
self.SetHoldings(bond, bond_pct)
def PlotData(self):
cash = self.Portfolio.Cash + self.Portfolio.UnsettledCash
sectors_allocation = 0
for sector in self.s_indicators:
sectors_allocation += self.Portfolio[sector].Price * self.Portfolio[sector].Quantity
bonds_allocation = 0
for bond in self.b_indicators:
bonds_allocation += self.Portfolio[sector].Price * self.Portfolio[sector].Quantity
self.Plot("Allocation", "Cash", cash/self.Portfolio.TotalPortfolioValue * 100)
self.Plot("Allocation", "Sectors", sectors_allocation/self.Portfolio.TotalPortfolioValue * 100)
self.Plot("Allocation", "Bonds", bonds_allocation/self.Portfolio.TotalPortfolioValue * 100)
self.Plot("Sectors", "IN", self.sectors_in)
class SymbolData(object):
def __init__(self, algo, symbol, period):
self.algo = algo
self.symbol = symbol
self.slow_ema = ExponentialMovingAverage(period)
self.fast_ema = ExponentialMovingAverage(int(period/10))
algo.RegisterIndicator(symbol.Value, self.slow_ema, Resolution.Daily)
algo.RegisterIndicator(symbol.Value, self.fast_ema, Resolution.Daily)
@property
def buy2(self):
if self.slow_ema.IsReady:
price = self.algo.Securities[self.symbol].Close
indicator = self.slow_ema.Current.Value
if price > indicator:
return True
else:
return False
else:
None
@property
def buy(self):
if self.slow_ema.IsReady and self.fast_ema.IsReady:
slow = self.slow_ema.Current.Value
#fast = self.fast_ema.Current.Value
fast = self.algo.Securities[self.symbol].Close
if fast > slow:
return True
else:
return False
else:
None
@property
def sell(self):
return not self.buy