Overall Statistics |
Total Trades 1183 Average Win 0.22% Average Loss -0.36% Compounding Annual Return 13.866% Drawdown 8.000% Expectancy 0.026 Net Profit 18.830% Sharpe Ratio 0.878 Probabilistic Sharpe Ratio 41.119% Loss Rate 36% Win Rate 64% Profit-Loss Ratio 0.61 Alpha 0.117 Beta 0.04 Annual Standard Deviation 0.141 Annual Variance 0.02 Information Ratio -0.122 Tracking Error 0.285 Treynor Ratio 3.105 Total Fees $1281.03 |
namespace QuantConnect { public class SellHigh7s : QCAlgorithm { private int _month = -1; public override void Initialize() { SetStartDate(2019, 1, 1); SetEndDate(DateTime.Now); SetCash(100000); UniverseSettings.Resolution = Resolution.Daily; AddUniverseSelection(new FineFundamentalUniverseSelectionModel(SelectCoarse, SelectFine)); AddAlpha( new MyAlphaModel() ); SetPortfolioConstruction( new EqualWeightingPortfolioConstructionModel() ); AddRiskManagement( new MaximumDrawdownPercentPerSecurity() ); SetExecution( new ImmediateExecutionModel() ); } IEnumerable<Symbol> SelectCoarse(IEnumerable<CoarseFundamental> coarse) { const int size = 9; if (Time.Month == _month) return Universe.Unchanged; // The securities with the most dollar volume return (from x in coarse where x.Volume > 0 && x.Price > 0 orderby x.DollarVolume descending select x.Symbol).Take(size).ToList(); } IEnumerable<Symbol> SelectFine(IEnumerable<FineFundamental> fine) { _month = Time.Month; return fine.Select(f => f.Symbol); } } // Algorithm framework model that produces insights public class MyAlphaModel : IAlphaModel, INotifiedSecurityChanges { private readonly Dictionary<Symbol, RelativeStrengthIndex> _rsiBySymbol = new Dictionary<Symbol, RelativeStrengthIndex>(); private readonly int _period = 1; private readonly Resolution _resolution = Resolution.Daily; private int _month = -1; // Updates this alpha model with the latest data from the algorithm. // This is called each time the algorithm receives data for subscribed securities public IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data) { // Generate insights on the securities in universe. var insights = new List<Insight>(); if (algorithm.Time.Month == _month) return insights; _month = algorithm.Time.Month; // Insights for 22 days var insightPeriod = _resolution.ToTimeSpan().Multiply(22); // Long the lowest RSI; Short the highest RSI var i = 0; var numInsightsPerSide = _rsiBySymbol.Count / 3; foreach (KeyValuePair<Symbol, RelativeStrengthIndex> sym in _rsiBySymbol.OrderBy(key => key.Value)) { if (i < numInsightsPerSide) insights.Add(Insight.Price(sym.Key, insightPeriod, InsightDirection.Up)); else if (i >= _rsiBySymbol.Count - numInsightsPerSide) insights.Add(Insight.Price(sym.Key, insightPeriod, InsightDirection.Down)); i++; } return insights; } public void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes) { // Handle security changes in from your universe model. // clean up data for removed securities if (changes.RemovedSecurities.Count > 0) { var removed = changes.RemovedSecurities.ToHashSet(x => x.Symbol); foreach (var subscription in _rsiBySymbol.Keys.ToList()) if (removed.Contains(subscription)) _rsiBySymbol.Remove(subscription); } // initialize data for added securities var addedSymbols = new List<Symbol>(); foreach (var added in changes.AddedSecurities) if (!_rsiBySymbol.ContainsKey(added.Symbol)) { // Add RSI indicator _rsiBySymbol[added.Symbol] = algorithm.RSI(added.Symbol, _period, MovingAverageType.Simple, _resolution); addedSymbols.Add(added.Symbol); } if (addedSymbols.Count > 0) // warmup our indicators by pushing history through the consolidators algorithm.History(addedSymbols, _period, _resolution) .PushThrough(data => { RelativeStrengthIndex rsi; if (_rsiBySymbol.TryGetValue(data.Symbol, out rsi)) rsi.Update(data.EndTime, data.Value); }); } } }