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