Overall Statistics
Total Orders
340
Average Win
0.44%
Average Loss
-0.44%
Compounding Annual Return
7.715%
Drawdown
21.800%
Expectancy
0.252
Start Equity
100000
End Equity
145021.7
Net Profit
45.022%
Sharpe Ratio
0.26
Sortino Ratio
0.291
Probabilistic Sharpe Ratio
19.724%
Loss Rate
38%
Win Rate
62%
Profit-Loss Ratio
1.01
Alpha
-0.009
Beta
0.409
Annual Standard Deviation
0.085
Annual Variance
0.007
Information Ratio
-0.509
Tracking Error
0.104
Treynor Ratio
0.054
Total Fees
$411.76
Estimated Strategy Capacity
$240000000.00
Lowest Capacity Asset
EEM SNQLASP67O85
Portfolio Turnover
2.07%
Drawdown Recovery
1192
# region imports
from AlgorithmImports import *
# endregion
# https://quantpedia.com/Screener/Details/15


class CountryEquityIndexesMomentumAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.set_start_date(self.end_date - timedelta(5*365))  
        self.set_cash(100_000) 
        #self.settings.automatic_indicator_warm_up = True
        # Add the assets we'll trade and their indicators.
        periods = [1, 3, 6, 12]
        tickers = [
            "SPY", "IWM", "QQQ", "EFA", "EEM", "VNQ", 
            "LQD", "GLD", "SHY", "IEF", "TLT", "AGG"
        ] 
        for ticker in tickers:
            equity = self.add_equity(
                ticker, Resolution.DAILY, 
                data_normalization_mode=DataNormalizationMode.TOTAL_RETURN
            )
            equity.indicators = [self.momp(equity, period*21) for period in periods]
            equity.vol = IndicatorExtensions.of(StandardDeviation(3*21), self.logr(equity, 1))
        # Add a Scheduled Event to rebalance the portfolio.
        self.schedule.on(
            self.date_rules.month_end("SPY"), 
            self.time_rules.after_market_close("SPY", 60), 
            self._rebalance
        )
        self.set_warm_up(timedelta(400))
            
    def _rebalance(self):
        if self.is_warming_up:
            return
        # Calculate the combined momentum score all each asset.
        factor_by_security = {
            security: sum(i.current.value for i in security.indicators)/len(security.indicators)
            for security in self.securities.values()
            if all([i.is_ready for i in security.indicators]) and security.vol.is_ready
        }
        if not factor_by_security:
            return
        # Select the top 5 assets.
        selected = sorted(factor_by_security.keys(), key=lambda security: factor_by_security[security])[-5:]
        # Form an inverse-volaility portfolio.
        vol_sum = sum([1/security.vol.current.value for security in selected])
        targets = [PortfolioTarget(security, 1 / security.vol.current.value / vol_sum) for security in selected]
        self.set_holdings(targets, True)

    def on_warmup_finished(self):
        self._rebalance()