Overall Statistics |
Total Trades 2029 Average Win 0.43% Average Loss -0.48% Compounding Annual Return 8.508% Drawdown 22.100% Expectancy 0.078 Net Profit 50.453% Sharpe Ratio 0.507 Loss Rate 43% Win Rate 57% Profit-Loss Ratio 0.88 Alpha 0.036 Beta 0.389 Annual Standard Deviation 0.155 Annual Variance 0.024 Information Ratio -0.188 Tracking Error 0.169 Treynor Ratio 0.202 Total Fees $13345.04 |
using System.Collections.Concurrent; namespace QuantConnect { public class RsiEmaCrossUniverseSelectionAlgorithm : QCAlgorithm { private const int Count = 10; private const decimal Tolerance = 1.01m; // holds our coarse fundamental indicators by symbol private readonly ConcurrentDictionary<Symbol, SelectionData> _averages = new ConcurrentDictionary<Symbol, SelectionData>(); // class used to improve readability of the coarse selection function private class SelectionData { public readonly ExponentialMovingAverage Fast; public readonly ExponentialMovingAverage Slow; public readonly RelativeStrengthIndex Rsi; public SelectionData() { Fast = new ExponentialMovingAverage(100); Slow = new ExponentialMovingAverage(300); Rsi = new RelativeStrengthIndex(30); } // computes an object score of how much large the fast is than the slow public decimal ScaledDelta { get { return (Fast - Slow) / ((Fast + Slow)/2m); } } // updates the RSI30 EMA100 and EMA300 indicators, returning true when they're both ready public bool Update(DateTime time, decimal value) { return Rsi.Update(time, value) && Fast.Update(time, value) && Slow.Update(time, value); } } public override void Initialize() { UniverseSettings.Leverage = 2.0m; UniverseSettings.Resolution = Resolution.Daily; SetStartDate(2010, 01, 01); SetEndDate(2015, 01, 01); SetCash(100000); AddUniverse(coarse => { return (from cf in coarse // grab th SelectionData instance for this symbol let avg = _averages.GetOrAdd(cf.Symbol, sym => new SelectionData()) // Update returns true when the indicators are ready, so don't accept until they are where avg.Update(cf.EndTime, cf.Price) // only pick symbols who RSI less than 30 where avg.Rsi < 30 // only pick symbols who have their 50 day ema over their 100 day ema where avg.Fast > avg.Slow * Tolerance // prefer symbols with a larger delta by percentage between the two averages orderby avg.ScaledDelta descending // we only need to return the symbol and return 'Count' symbols select cf.Symbol).Take(Count); }); } public override void OnData(Slice data) { // } public override void OnSecuritiesChanged(SecurityChanges changes) { foreach (var security in changes.RemovedSecurities) { if (security.Invested) { Liquidate(security.Symbol); } } foreach (var security in changes.AddedSecurities) { SetHoldings(security.Symbol, 1m / Count); } } } }