Overall Statistics |
Total Trades 216 Average Win 2.21% Average Loss -0.64% Compounding Annual Return 15.804% Drawdown 10.400% Expectancy 0.240 Net Profit 15.804% Sharpe Ratio 0.815 Loss Rate 72% Win Rate 28% Profit-Loss Ratio 3.46 Alpha 0.139 Beta 0.109 Annual Standard Deviation 0.161 Annual Variance 0.026 Information Ratio 1.076 Tracking Error 0.187 Treynor Ratio 1.204 Total Fees $432.00 |
namespace QuantConnect { public static class RollingWindowExtensions { public static bool CrossAbove(this RollingWindow<decimal> window1, RollingWindow<decimal> window2, decimal tolerance = 0m) { return window1[0] > window2[0] * (1 + tolerance) && window1[1] < window2[1] * (1 - tolerance); } public static bool CrossBelow(this RollingWindow<decimal> window1, RollingWindow<decimal> window2, decimal tolerance = 0m) { return window1[0] < window2[0] * (1 - tolerance) && window1[1] > window2[1] * (1 + tolerance); } public static bool Rising(this RollingWindow<decimal> window, int lookback = 1, decimal tolerance = 0m) { return window[0] > window[lookback] * (1 + tolerance); } public static bool Falling(this RollingWindow<decimal> window, int lookback = 1, decimal tolerance = 0m) { return window[0] < window[lookback] * (1 - tolerance); } } }
namespace QuantConnect { public class EmaCrossesAlgorithm : QCAlgorithm { private const string Market = "fxcm"; private const int DefaultQuantity = 25000; private const int PeriodFast = 5; private const int PeriodSlow = 9; private Symbol _symbol = QuantConnect.Symbol.Create("EURUSD", SecurityType.Forex, Market); private ExponentialMovingAverage _emaFast; private ExponentialMovingAverage _emaSlow; private RollingWindow<decimal> _emaFastHistory = new RollingWindow<decimal>(PeriodFast + 1); private RollingWindow<decimal> _emaSlowHistory = new RollingWindow<decimal>(PeriodSlow + 1); public override void Initialize() { SetStartDate(2015, 1, 1); SetEndDate(2015, 12, 31); SetCash(10000); SetBenchmark(_symbol); AddForex(_symbol, Resolution.Hour, Market); _emaFast = EMA(_symbol, PeriodFast); _emaSlow = EMA(_symbol, PeriodSlow); } public override void OnData(Slice data) { // Add ema values to rolling windows, so we can access previous ema values _emaFastHistory.Add(_emaFast); _emaSlowHistory.Add(_emaSlow); if (!_emaSlow.IsReady) return; var bar = data[_symbol] as TradeBar; if (bar == null) return; if (Portfolio[_symbol].IsLong) { // Long exit: EmaSlow is falling if (_emaSlowHistory.Falling(PeriodSlow)) { Order(_symbol, -DefaultQuantity); } } else if (Portfolio[_symbol].IsShort) { // Short exit: EmaSlow is rising if (_emaSlowHistory.Rising(PeriodSlow)) { Order(_symbol, DefaultQuantity); } } else { // Long entry: EmaFast crosses above EmaSlow and EmaSlow not falling if (_emaFastHistory.CrossAbove(_emaSlowHistory) && !_emaSlowHistory.Falling(PeriodSlow)) { Order(_symbol, DefaultQuantity); } // Short entry: EmaFast crosses below EmaSlow and EmaSlow not rising if (_emaFastHistory.CrossBelow(_emaSlowHistory) && !_emaSlowHistory.Rising(PeriodSlow)) { Order(_symbol, -DefaultQuantity); } } } } }