Overall Statistics |
Total Trades 2005 Average Win 0.81% Average Loss -0.60% Compounding Annual Return 376.633% Drawdown 16.300% Expectancy 0.281 Net Profit 393.229% Sharpe Ratio 5.232 Probabilistic Sharpe Ratio 97.492% Loss Rate 45% Win Rate 55% Profit-Loss Ratio 1.33 Alpha 3.398 Beta -0.148 Annual Standard Deviation 0.64 Annual Variance 0.41 Information Ratio 4.567 Tracking Error 0.664 Treynor Ratio -22.662 Total Fees $8773.98 Estimated Strategy Capacity $130000000.00 Lowest Capacity Asset OEG XEEQU7AFNHPH |
//Copyright HardingSoftware.com. Granted to the public domain. //Use entirely at your own risk. //This algorithm contains open source code from other sources, //no claim is being made to such code. //Do not remove this copyright notice. using System; using System.Collections.Generic; using System.Linq; using QuantConnect.Data.Market; using QuantConnect.Data.UniverseSelection; namespace QuantConnect.Algorithm.CSharp { public class UniverseTemplate : QCAlgorithm { int TotalHighDollarVolumeStocks = 50; IDictionary<Symbol,SymbolData> HighDollarVolumeStocks = new Dictionary<Symbol, SymbolData>(); int TotalStocksToHold = 5; Resolution Resolution = Resolution.Daily; int Period = 10; decimal Leverage = 0.99m; public override void Initialize() { UniverseSettings.Resolution = Resolution; SetStartDate(2020, 6, 02); SetCash(100000); AddUniverse(coarse => { return (from stock in coarse orderby stock.DollarVolume descending select stock.Symbol).Take(TotalHighDollarVolumeStocks); }); } public void OnData(TradeBars data) { foreach(KeyValuePair<Symbol,SymbolData> kvp in HighDollarVolumeStocks){ if(data.ContainsKey(kvp.Key)){ TradeBar bar = data[kvp.Key]; HighDollarVolumeStocks[kvp.Key].Update(bar); if(HighDollarVolumeStocks[kvp.Key].IsReady){ HighDollarVolumeStocks[kvp.Key].CalculateStochastic(); } } } List<SymbolData> stocksToHold = HighDollarVolumeStocks.Values.OrderByDescending(x => x.Stochastic).Take(TotalStocksToHold).ToList(); foreach (var security in Portfolio.Values) { if (Portfolio[security.Symbol].Invested) { if (stocksToHold.Exists(x => x.symbol == security.Symbol) == false) { Liquidate(security.Symbol); } } } foreach (var security in stocksToHold) { if (Portfolio[security.symbol].Quantity >= 0) { SetHoldings(security.symbol, -Leverage / (decimal)TotalStocksToHold); } } } public class SymbolData{ public Symbol symbol; public decimal Stochastic; public Maximum max = new Maximum(10); public Minimum min = new Minimum(10); public TradeBar current = null; public bool IsReady = false; public void Update(TradeBar bar){ current = bar; max.Update(bar.Time,bar.High); min.Update(bar.Time,bar.Low); if(current!=null && max.IsReady && min.IsReady){ IsReady = true; } } public decimal CalculateStochastic(){ if(current!=null && max.IsReady && min.IsReady){ decimal low = min.Current.Value; decimal high = max.Current.Value; decimal close = current.Close; Stochastic = 100m * (close - low) / (high - low); } return Stochastic; } } public override void OnSecuritiesChanged(SecurityChanges changes) { foreach (var security in changes.RemovedSecurities) { if (HighDollarVolumeStocks.ContainsKey(security.Symbol)){ HighDollarVolumeStocks.Remove(security.Symbol); } } foreach (var security in changes.AddedSecurities) { if (!HighDollarVolumeStocks.ContainsKey(security.Symbol)){ HighDollarVolumeStocks[security.Symbol] = new SymbolData(); HighDollarVolumeStocks[security.Symbol].symbol = security.Symbol; var history = History(security.Symbol, 10, Resolution.Daily); foreach (var bar in history) { HighDollarVolumeStocks[security.Symbol].Update(bar); } } } } } }