Overall Statistics
Total Trades
75
Average Win
1.58%
Average Loss
-0.90%
Compounding Annual Return
32.801%
Drawdown
8.100%
Expectancy
0.834
Net Profit
35.301%
Sharpe Ratio
2.195
Probabilistic Sharpe Ratio
90.773%
Loss Rate
33%
Win Rate
67%
Profit-Loss Ratio
1.75
Alpha
0.253
Beta
-0.061
Annual Standard Deviation
0.109
Annual Variance
0.012
Information Ratio
0.004
Tracking Error
0.16
Treynor Ratio
-3.904
Total Fees
$265.36
# Monthly ETF Rollover Strategy
# Use 11 Sector ETFs (XLB, XLC, XLE, XLF, XLI, XLK, XLP, XLRE, XLU, XLV, and XLY), equal weight the TOP3 ETF’s on 1st Day of the Month. Hold asset class Sector ETF’s for 1 month.
# If ETF is still in the TOP3 at month end, Keep It

import numpy as np
import pandas as pd
from datetime import datetime

class EmmausAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 1, 1)
        self.SetCash(100000) 

        # choose 11 sector ETFs
        tickers = [ "XLB",  # Materials
                    "XLC",  # Communication Services
                    "XLE",  # Energy
                    "XLF",  # Financials
                    "XLI",  # Industrials
                    "XLK",  # Technology
                    "XLP",  # Staples
                    "XLRE", # Real Estate
                    "XLU",  # Utilities
                    "XLV",  # Health Care
                    "XLY"]  # Discretionary 

        self.data = {}

        for ticker in tickers:
            symbol = self.AddEquity(ticker, Resolution.Daily).Symbol
            self.data[symbol] = RateOfChangePercent(1)
            consolidator = TradeBarConsolidator(CalendarType.Monthly)
            self.RegisterIndicator(symbol, self.data[symbol], consolidator)

        self.SetWarmUp(30)

        # shcedule the function to fire at the month start 
        self.Schedule.On(
            self.DateRules.MonthStart("XLB"),
            self.TimeRules.AfterMarketOpen("XLB", 10),
            self.Rebalance)


    def Rebalance(self):
        if self.IsWarmingUp:
            return
        
        func = lambda x: x[1].Current.Value

        top3 = {x[0]: x[1].Current.Value
            for x in sorted(self.data.items(), key=func, reverse=False)[:3]}

        for kvp in self.Portfolio:
          security_hold = kvp.Value
        
        # liquidate the security which is no longer in the top3 momentum list
          if security_hold.Invested and (security_hold.Symbol.Value not in top3):
                self.Liquidate(security_hold.Symbol)

        for symbol in top3:
            self.SetHoldings(symbol, 1/3)