Overall Statistics |
Total Trades 470 Average Win 0.30% Average Loss -0.48% Compounding Annual Return -6.138% Drawdown 18.800% Expectancy -0.137 Net Profit -14.559% Sharpe Ratio -1.021 Loss Rate 47% Win Rate 53% Profit-Loss Ratio 0.64 Alpha -0.049 Beta -0.019 Annual Standard Deviation 0.049 Annual Variance 0.002 Information Ratio -0.856 Tracking Error 0.137 Treynor Ratio 2.595 Total Fees $470.00 |
namespace QuantConnect { internal enum MarketRegime { Bearish = -1, Uncertain = 0, Bullish = 1 } public class RsiMaStrategy : QCAlgorithm { private Security _appl; private SimpleMovingAverage _smoothedRSI; private RelativeStrengthIndex _rsi; private RollingWindow<IndicatorDataPoint> _rsiLag; private CompositeIndicator<IndicatorDataPoint> _marketRegimeIndicator; private const decimal _tol = 0.0001m; public override void Initialize() { SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage); // backtest parameters SetStartDate(2015, 01, 01); SetEndDate(DateTime.Today); // cash allocation SetCash(10000); _appl = AddEquity("AAPL"); _rsi = new RelativeStrengthIndex(14); _smoothedRSI = new SimpleMovingAverage(4).Of(_rsi); _rsiLag = new RollingWindow<IndicatorDataPoint>(2); var fiveMinuteConsolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(5)); fiveMinuteConsolidator.DataConsolidated += FiveMinuteConsolidator_DataConsolidated; SubscriptionManager.AddConsolidator(_appl.Symbol, fiveMinuteConsolidator); _marketRegimeIndicator = SMA(_appl.Symbol, 5, Resolution.Daily).Minus(SMA(_appl.Symbol, 200, Resolution.Daily)); Schedule.On(DateRules.EveryDay(), TimeRules.BeforeMarketClose(_appl.Symbol, 4), () => { CloseOpenPositions(_appl); }); SetWarmUp(TimeSpan.FromDays(100)); } private void CloseOpenPositions(Security security) { if (security.Invested) { Liquidate(security.Symbol); } } private MarketRegime GetMarketRegime() { MarketRegime marketregime = MarketRegime.Uncertain; if (Math.Abs(_marketRegimeIndicator) > _tol) { marketregime = (MarketRegime)Math.Sign(_marketRegimeIndicator); } return marketregime; } private void FiveMinuteConsolidator_DataConsolidated(object sender, TradeBar e) { _rsi.Update(new IndicatorDataPoint { Time = e.Time, Value = e.Value }); _rsiLag.Add(_rsi.Current); if (!_marketRegimeIndicator.IsReady || !_rsiLag.IsReady) return; if (_appl.Invested) { ExitLogic(); } else { EntryLogic(); } } private void ExitLogic() { var bullishRSIExit = _rsiLag[1] > 55 && _rsiLag[0] < 55; var bearishRSIExit = _rsiLag[1] < 45 && _rsiLag[0] > 45; if ( (GetMarketRegime() == MarketRegime.Bullish && bullishRSIExit) || (GetMarketRegime() == MarketRegime.Bearish && bearishRSIExit)) { Liquidate(_appl.Symbol); } } private void EntryLogic() { var bullishRSIEntry = _rsiLag[1] < 30 && _rsiLag[0] > 30; var bearishRSIEntry = _rsiLag[1] > 70 && _rsiLag[0] < 70; if (GetMarketRegime() == MarketRegime.Bullish && bullishRSIEntry) { SetHoldings(_appl.Symbol, 1); } else if (GetMarketRegime() == MarketRegime.Bearish && bearishRSIEntry) { SetHoldings(_appl.Symbol, -1); } } public override void OnData(Slice data) { } } }