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); } } } }