Overall Statistics
Total Orders
152
Average Win
1.04%
Average Loss
-1.85%
Compounding Annual Return
-0.696%
Drawdown
19.100%
Expectancy
-0.130
Start Equity
100000
End Equity
96564.52
Net Profit
-3.435%
Sharpe Ratio
-0.582
Sortino Ratio
-0.646
Probabilistic Sharpe Ratio
0.258%
Loss Rate
44%
Win Rate
56%
Profit-Loss Ratio
0.56
Alpha
-0.039
Beta
-0
Annual Standard Deviation
0.067
Annual Variance
0.004
Information Ratio
-0.706
Tracking Error
0.157
Treynor Ratio
116.105
Total Fees
$251.18
Estimated Strategy Capacity
$840000.00
Lowest Capacity Asset
IJT RWQR2INKP0TH
Portfolio Turnover
2.02%
Drawdown Recovery
33
#region imports
from AlgorithmImports import *
#endregion
# https://www.quantconnect.com/tutorials/strategy-library/momentum-and-style-rotation-effect
# https://quantpedia.com/Screener/Details/91


class MomentumAndStyleRotationAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(self.end_date - timedelta(5*365))
        self.set_cash(100_000)
        self.settings.seed_initial_prices = True

        tickers = ["IJJ",   # iShares S&P Mid-Cap 400 Value Index ETF
                   "IJK",   # iShares S&P Mid-Cap 400 Growth ETF
                   "IJS",   # iShares S&P Small-Cap 600 Value ETF
                   "IJT",   # iShares S&P Small-Cap 600 Growth ETF
                   "IVE",   # iShares S&P 500 Value Index ETF
                   "IVW"]   # iShares S&P 500 Growth ETF

        lookback = 12*20

        # Add assets and create momentum indicators.
        for ticker in tickers:
            equity = self.add_equity(ticker, Resolution.DAILY)
            equity.momp = self.momp(equity, lookback)

        self.set_warm_up(lookback)

        # Portfolio monthly rebalance
        self.schedule.on(self.date_rules.month_start("IJJ"), self.time_rules.midnight, self._rebalance)

    def _rebalance(self):
        '''Sort securities by momentum.
        Short the one with the lowest momentum.
        Long the one with the highest momentum.
        Liquidate positions of other securities'''
        
        # Rank the securities by their momentum scores.
        sorted_mom = sorted(self.securities.values(), key=lambda security: security.momp.current.value)

        targets = [
            PortfolioTarget(sorted_mom[0], -0.5),  # Short the ETF with lowest MOM
            PortfolioTarget(sorted_mom[-1], 0.5),  # Long the ETF with highest MOM
        ]
        self.set_holdings(targets, True)
        
    def on_warmup_finished(self):
        self._rebalance()