Overall Statistics
Total Trades
18
Average Win
8.40%
Average Loss
-1.74%
Compounding Annual Return
41.308%
Drawdown
19.900%
Expectancy
-0.270
Net Profit
29.019%
Sharpe Ratio
1.472
Probabilistic Sharpe Ratio
59.084%
Loss Rate
88%
Win Rate
12%
Profit-Loss Ratio
4.84
Alpha
0.38
Beta
-0.083
Annual Standard Deviation
0.253
Annual Variance
0.064
Information Ratio
0.594
Tracking Error
0.455
Treynor Ratio
-4.501
Total Fees
$0.00
using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Brokerages;
using QuantConnect.Data;
using QuantConnect.Indicators;
using QuantConnect.Orders;

namespace QuantConnect.Algorithm.CSharp
{

    public class AssetClassMomentumAlgorithm : QCAlgorithm
    {

        /// <summary>
        /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
        /// </summary>
        private int period = 12 * 21;

        private Dictionary<string, Momentum> _momentum;
        private Dictionary<string, decimal> highestPrice;
        private Dictionary<string, OrderTicket> stopMarketTicket;
        private List<string> _symbols;
        public override void Initialize()
        {
            // Set requested data resolution
            _momentum = new Dictionary<string, Momentum>();
            highestPrice = new Dictionary<string, decimal>();
            stopMarketTicket = new Dictionary<string, OrderTicket>();


            SetStartDate(2020, 1, 1);  //Set Start Date
            SetEndDate(DateTime.Now);    //Set End Date
            SetCash(100000);             //Set Strategy Cash

            // set algorithm framework models
            //SetAlpha(new ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, null));
            //SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
            //SetExecution(new ImmediateExecutionModel());
            _symbols = new List<string>()
            {
                "SPY", "EFA", "IETC", "QQQ", "XNTK","SWAN","RWGV","BTAL","CLIX","JKE","PSJ","TMFC","GLD"
            };

            SetWarmUp(period, Resolution.Daily);
            SetBrokerageModel(BrokerageName.Alpaca);
            foreach (var symbol in _symbols)
            {
                AddEquity(symbol, Resolution.Daily);
                _momentum[symbol] = MOM(symbol, period, Resolution.Daily);
            }

            Schedule.On(DateRules.MonthStart("SPY"), TimeRules.AfterMarketOpen("SPY"), ReBalance);
        }
        public override void OnData(Slice slice)
        {
            //1. Plot the current SPY price to "Data Chart" on series "Asset Price"


            foreach (var kvp in Portfolio)
            {
                var security = kvp.Value.Symbol;

                if (Portfolio[security].Invested)
                {
                    if (Securities[security].Close > highestPrice[security.Value])
                    {
                        highestPrice[security.Value] = Securities[security].Close;

                        stopMarketTicket[security.Value].Update(new UpdateOrderFields()
                        {
                            StopPrice = 0.94m * highestPrice[security.Value]
                        });
                    }
                }
                highestPrice[security.Value] = Securities[security].Close;
                stopMarketTicket[security.Value] = StopMarketOrder(security, -Portfolio[security].Quantity, highestPrice[security.Value] * 0.94m);

            }

        }

        private void ReBalance()
        {
            if (IsWarmingUp) return;
            var top3 =
                (from entry in _momentum orderby entry.Value descending select entry.Key).Take(3);


            foreach (var kvp in Portfolio)
            {
                var secutiyHold = kvp.Value;
                //iquidate the security which is no longer in the top3 momentum list
                if (secutiyHold.Invested && (!top3.Contains(secutiyHold.Symbol.Value)))
                {
                    Liquidate(secutiyHold.Symbol);
                }
            }
            var newSymbols = new List<Symbol>();
            foreach (var symbol in top3)
            {
                Debug("top3 Symbol " + symbol);
                if (!Portfolio[symbol].Invested)
                {
                    newSymbols.Add(symbol);
                }
            }

            foreach (var symbol in newSymbols)
            {
                Debug("new Symbol " + symbol.Value);
                SetHoldings(symbol, 1m / newSymbols.Count);
                highestPrice[symbol.Value] = Securities[symbol].Close;
                stopMarketTicket[symbol.Value] = StopMarketOrder(symbol, -Portfolio[symbol].Quantity, highestPrice[symbol.Value] * 0.94m);

            }
        }
    }
}