Overall Statistics |
Total Trades 4372 Average Win 0.16% Average Loss -0.13% Compounding Annual Return -17.757% Drawdown 19.200% Expectancy -0.065 Net Profit -17.757% Sharpe Ratio -1.093 Loss Rate 59% Win Rate 41% Profit-Loss Ratio 1.31 Alpha 0.481 Beta -33.652 Annual Standard Deviation 0.163 Annual Variance 0.027 Information Ratio -1.212 Tracking Error 0.163 Treynor Ratio 0.005 Total Fees $10506.52 |
using System.Collections.Concurrent; namespace QuantConnect.Algorithm.CSharp { public class RsiCrossUniverseSelectionAlgorithm : QCAlgorithm { // holds our coarse fundamental indicators by symbol private readonly ConcurrentDictionary<Symbol, SelectionData> _averages = new ConcurrentDictionary<Symbol, SelectionData>(); private const int Count = 10; private SecurityChanges _changes = SecurityChanges.None; public override void Initialize() { UniverseSettings.Leverage = 2.0m; UniverseSettings.Resolution = Resolution.Daily; SetStartDate(2018, 1, 1); SetEndDate(2019, 1, 1); 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.AdjustedPrice) // Cross up and price must be greater than 10 where avg.IsCrossUp && cf.Price > 10 // prefer symbols with a larger dollar volume orderby cf.DollarVolume // we only need to return the symbol and return 'Count' symbols select cf.Symbol).Take(Count); }); } public override void OnData(Slice slice) { if (_changes == SecurityChanges.None) return; // we'll simply go long each security we added to the universe foreach (var security in _changes.AddedSecurities) { if (security.Price > 0) { var symbol = security.Symbol; //Log($"{_averages[symbol]} of {symbol}"); SetHoldings(symbol, 1m/Count); } } } public override void OnSecuritiesChanged(SecurityChanges changes) { // liquidate securities removed from our universe foreach (var security in changes.RemovedSecurities) { if (security.Invested) { Liquidate(security.Symbol); } } _changes = changes; } // class used to improve readability of the coarse selection function private class SelectionData { private readonly RelativeStrengthIndex _present; private readonly Delay _past; public bool IsCrossUp => _past.IsReady && _past < 30 && _present > 30; public SelectionData() { _present = new RelativeStrengthIndex(14); _past = new Delay(1); _past.Of(_present); } public bool Update(DateTime time, decimal value) { _present.Update(time, value); return _past.IsReady; } public override string ToString() { var time = _present.Current.Time; return $"{time} :: Past: {_past} Present: {_present}"; } } } }