Overall Statistics |
Total Trades 15 Average Win 0.90% Average Loss -1.20% Compounding Annual Return -97.539% Drawdown 3.900% Expectancy -0.415 Net Profit -2.999% Sharpe Ratio -1.785 Probabilistic Sharpe Ratio 0% Loss Rate 67% Win Rate 33% Profit-Loss Ratio 0.76 Alpha -0.436 Beta -1.375 Annual Standard Deviation 0.547 Annual Variance 0.299 Information Ratio -1.449 Tracking Error 0.945 Treynor Ratio 0.71 Total Fees $0.00 Estimated Strategy Capacity $1300000.00 Lowest Capacity Asset IMPP XU3XFV9BKJTX |
#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 AdaptableMagentaLlamaDK : QCAlgorithm { //CONSTANTS and FILTERS/////////////// ////////////////////////////////////// private const int TAKE_TOP = 3; //Make sure to have an m after the number to make it a decimal private const decimal MIN_PRICE = 0m; private const decimal MAX_PRICE = 1000000m; private List<DateTime> SKIP_DAYS = new List<DateTime>{ new DateTime(2018,9,20), new DateTime(2018,9,21), new DateTime(2020,8,08), new DateTime(2020,8,09), new DateTime(2020,8,10), new DateTime(2020,8,11), new DateTime(2020,8,12), new DateTime(2020,8,13), new DateTime(2020,8,14), }; ////////////////////////////////////// public class SymbolData { public Symbol Symbol { get; set; } private int Window = 5; private int Offset = 1; //TODO: NOT USING YET, confirm 1 day offset matches private List<decimal> Rolling = new List<decimal>(); public decimal Value = 0; public decimal CurrentPrice = 0; public SymbolData(Symbol symbol) { Symbol = symbol; } public void Update(decimal price, decimal value) { CurrentPrice = price; if (Rolling.Count > Window) Rolling.RemoveAt(0); Rolling.Add(value); Value = Rolling.Median(); } } private List<SymbolData> _universe = new List<SymbolData>(); public override void Initialize() { SetStartDate(2022, 6, 1); //Set Start Date SetEndDate(2022, 6, 5); //Set End Date SetCash(1000000); //Set Strategy Cash AddUniverseSelection(new CoarseFundamentalUniverseSelectionModel(SelectCoarse)); AddEquity("SPY", Resolution.Minute); //only used for scheduling UniverseSettings.Resolution = Resolution.Minute; UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw; SetSecurityInitializer(CustomSecurityInitializer); // schedule an event to fire on certain days of the week Schedule.On(DateRules.Every(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday), TimeRules.AfterMarketOpen("SPY", -5), () => { // Log("Morning Liquidate: Fired at: " + Time); Liquidate(); }); //have to schedule 16 min before the end of the day so that market close orders are accepted Schedule.On(DateRules.Every(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday), TimeRules.BeforeMarketClose("SPY", 16), () => { // Log("End of Day Buy: Fired at: " + Time); EndOfDayBuy(); }); } private IEnumerable<Symbol> SelectCoarse(IEnumerable<CoarseFundamental> coarse) { foreach (var c in coarse.Where(c => c.HasFundamentalData)) { if (!_universe.Any(u => u.Symbol == c.Symbol)) _universe.Add(new SymbolData(c.Symbol)); _universe.First(u => u.Symbol == c.Symbol).Update(c.Price, c.Volume); Log($"{Time.Date} for {c.Symbol}: Vol={c.Volume}"); } //UNCOMMENT FOR SELECTED STOCK VALUES // foreach (var c in _universe.OrderByDescending(u => u.Value).Take(TAKE_TOP)) // { // Log($"{c.Symbol} at {c.Value}"); // } // _universe.OrderByDescending(u => u.Value).Take(TAKE_TOP).DoForEach(x => Log($"{x.Symbol} has value {x.Value}")); return _universe.Select(c => c.Symbol); } private void CustomSecurityInitializer(Security security) { security.SetFeeModel(new ConstantFeeModel(0)); security.SetDataNormalizationMode(DataNormalizationMode.SplitAdjusted); var howmany = GetParameter("howmany"); } /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// Slice object keyed by symbol containing the stock data public override void OnData(Slice data) { } public void LiquidatePortfolio() { foreach (var stock in Portfolio.Where(p => p.Value.Invested)) { MarketOnOpenOrder(stock.Value.Symbol, -stock.Value.Quantity); } } public void EndOfDayBuy() { if (SKIP_DAYS.Contains(Time.Date)) return; var currentBuys = _universe .Where(u => u.CurrentPrice >= MIN_PRICE && u.CurrentPrice <= MAX_PRICE) .OrderByDescending(u => u.Value) .Take(TAKE_TOP) .Select(u => u.Symbol).ToList(); Log(currentBuys.ToString()); var splitPct = 1M / TAKE_TOP; foreach(var stock in currentBuys) { var quantity = CalculateOrderQuantity(stock, splitPct); MarketOnCloseOrder(stock, quantity); } } } }