Overall Statistics
Total Trades
392
Average Win
1.56%
Average Loss
-1.94%
Compounding Annual Return
7.210%
Drawdown
43.800%
Expectancy
0.121
Net Profit
50.145%
Sharpe Ratio
0.336
Probabilistic Sharpe Ratio
2.424%
Loss Rate
38%
Win Rate
62%
Profit-Loss Ratio
0.80
Alpha
-0.005
Beta
0.879
Annual Standard Deviation
0.23
Annual Variance
0.053
Information Ratio
-0.091
Tracking Error
0.18
Treynor Ratio
0.088
Total Fees
$1194.06
Estimated Strategy Capacity
$5700000.00
Lowest Capacity Asset
IYE RVLEALAHHC2T
#region imports
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Globalization;
    using System.Drawing;
    using QuantConnect;
    using QuantConnect.Algorithm.Framework;
    using QuantConnect.Algorithm.Framework.Selection;
    using QuantConnect.Algorithm.Framework.Alphas;
    using QuantConnect.Algorithm.Framework.Portfolio;
    using QuantConnect.Algorithm.Framework.Execution;
    using QuantConnect.Algorithm.Framework.Risk;
    using QuantConnect.Parameters;
    using QuantConnect.Benchmarks;
    using QuantConnect.Brokerages;
    using QuantConnect.Util;
    using QuantConnect.Interfaces;
    using QuantConnect.Algorithm;
    using QuantConnect.Indicators;
    using QuantConnect.Data;
    using QuantConnect.Data.Consolidators;
    using QuantConnect.Data.Custom;
    using QuantConnect.DataSource;
    using QuantConnect.Data.Fundamental;
    using QuantConnect.Data.Market;
    using QuantConnect.Data.UniverseSelection;
    using QuantConnect.Notifications;
    using QuantConnect.Orders;
    using QuantConnect.Orders.Fees;
    using QuantConnect.Orders.Fills;
    using QuantConnect.Orders.Slippage;
    using QuantConnect.Scheduling;
    using QuantConnect.Securities;
    using QuantConnect.Securities.Equity;
    using QuantConnect.Securities.Future;
    using QuantConnect.Securities.Option;
    using QuantConnect.Securities.Forex;
    using QuantConnect.Securities.Crypto;   
    using QuantConnect.Securities.Interfaces;
    using QuantConnect.Storage;
    using QuantConnect.Data.Custom.AlphaStreams;
    using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm;
    using QCAlgorithmFrameworkBridge = QuantConnect.Algorithm.QCAlgorithm;
#endregion
namespace QuantConnect.Algorithm.CSharp
{
    public class WellDressedVioletChinchilla : QCAlgorithm
    {
        private Dictionary<Symbol, MomentumPercent> _momentumBySymbol = new();
        private bool _rebalance = false;
        private Dictionary<DateTime, decimal> _portfolioValues = new();
        private int _numEtfs = 3;

        public override void Initialize()
        {
            SetStartDate(2017, 1, 1);
            SetEndDate(2022, 11, 1);
            SetCash(100000);

            // Sector ETFs from https://www.cnbc.com/sector-etfs/
            var tickers = new[]
            {
                "XLE", // Energy Select Sector SPDR Fund
                "XLF", // Financial Select Sector SPDR Fund
                "XLU", // Utilities Select Sector SPDR Fund
                "XLI", // Industrial Select Sector SPDR Fund
                "GDX", // VanEck Gold Miners ETF
                "XLK", // Technology Select Sector SPDR Fund
                "XLV", // Health Care Select Sector SPDR Fund
                "XLY", // Consumer Discretionary Select Sector SPDR Fund
                "XLP", // Consumer Staples Select Sector SPDR Fund
                "XLB", // Materials Select Sector SPDR Fund
                "XOP", // Spdr S&P Oil & Gas Exploration & Production Etf
                "IYR", // iShares U.S. Real Estate ETF
                "XHB", // Spdr S&P Homebuilders Etf
                "ITB", // iShares U.S. Home Construction ETF
                "VNQ", // Vanguard Real Estate Index Fund ETF Shares
                "GDXJ",// VanEck Junior Gold Miners ETF
                "IYE", // iShares U.S. Energy ETF
                "OIH", // VanEck Oil Services ETF
                "XME", // SPDR S&P Metals & Mining ETF
                "XRT", // Spdr S&P Retail Etf
                "SMH", // VanEck Semiconductor ETF
                "IBB", // iShares Biotechnology ETF
                "KBE", // SPDR S&P Bank ETF
                "KRE", // SPDR S&P Regional Banking ETF
                "XTL"  // SPDR S&P Telecom ETF
            };
            foreach (var ticker in tickers)
            {
                var symbol = AddEquity(ticker, Resolution.Daily).Symbol;
                var momentum = MOMP(symbol, 22);
                WarmUpIndicator(symbol, momentum);
                _momentumBySymbol[symbol] = momentum;
            }

            // Schedule the rebalance
            Schedule.On(DateRules.MonthStart(GetParameter("rebalance-day", 0)),
                TimeRules.Midnight,
                () =>
                {
                    _rebalance = true;
                });
        }

        public override void OnData(Slice data)
        {
            // Record net portfolio value
            _portfolioValues[Time] = Portfolio.TotalPortfolioValue;

            // Rebalance?
            if (!_rebalance)
            {
                return;
            }
            _rebalance = false;

            // Select target ETFs
            var targetSymbols = _momentumBySymbol.OrderByDescending(x => x.Value).Take(_numEtfs).Select(kvp => kvp.Key);;

            // Liquidate ETFs that are no longer targeted
            SetHoldings(Portfolio.Where(kvp => kvp.Value.Invested && !targetSymbols.Contains(kvp.Key)).Select(kvp => new PortfolioTarget(kvp.Key, 0)).ToList());

            // Rebalance targeted ETFs
            var weight = 1.0m / _numEtfs;
            SetHoldings(targetSymbols.Select(symbol => new PortfolioTarget(symbol, weight)).ToList());
        }

        public override void OnEndOfAlgorithm()
        {
            // Save daily portfolio values to ObjectStore
            ObjectStore.SaveJson<Dictionary<DateTime, decimal>>($"{ProjectId}/portfolioValues", _portfolioValues);
        }
    }
}