Overall Statistics |
Total Trades 10001 Average Win 0.20% Average Loss -0.18% Compounding Annual Return 16.791% Drawdown 14.000% Expectancy 0.041 Net Profit 43.493% Sharpe Ratio 1.133 Loss Rate 50% Win Rate 50% Profit-Loss Ratio 1.07 Alpha NaN Beta NaN Annual Standard Deviation 0.147 Annual Variance 0.022 Information Ratio NaN Tracking Error NaN Treynor Ratio NaN Total Fees $10001.00 |
namespace QuantConnect { public class EMACrossLongAlgorithm : QCAlgorithm { // There's no need to create another instance of algorithm. We are already in the algorithm. // So we create all variables we need here. RollingWindow<TradeBar> History = new RollingWindow<TradeBar>(4); RollingWindow<decimal> _8EMAHistory = new RollingWindow<decimal>(3); RollingWindow<decimal> _8SMAHistory = new RollingWindow<decimal>(3); RollingWindow<decimal> _20EMAHistory = new RollingWindow<decimal>(3); public decimal AveragePriceSelector(BaseData data) { decimal emaMid = (_highEMA + _lowEMA) / 2; return emaMid; } string symbol = "PCLN"; ExponentialMovingAverage _8EMA; SimpleMovingAverage _8SMA; ExponentialMovingAverage _20EMA; ExponentialMovingAverage _highEMA; ExponentialMovingAverage _lowEMA; RateOfChange roc; int fastMAPeriod = 8; int slowEmaPeriod = 20; //algorithm PnL settings decimal targetProfit = 0.001m; // 0.1% target decimal maximumLoss = 0.00041m; // 0.041% stop // Initialize function ---------------------------------------------------------------------------- public override void Initialize() // backtest kickstart { SetStartDate(2012, 3, 12); SetEndDate(2015, 7, 28); SetCash(100000); AddSecurity(SecurityType.Equity, symbol, Resolution.Minute); var fifteenConsolidator = ResolveConsolidator(symbol, TimeSpan.FromMinutes(15)); _8EMA = new ExponentialMovingAverage(fastMAPeriod); _8SMA = new SimpleMovingAverage(fastMAPeriod); _20EMA = new ExponentialMovingAverage(slowEmaPeriod); _highEMA = new ExponentialMovingAverage(14); _lowEMA = new ExponentialMovingAverage(14); roc = new RateOfChange(18); RegisterIndicator(symbol, _8EMA, fifteenConsolidator, p => p.Value); RegisterIndicator(symbol, _8SMA, fifteenConsolidator, p => p.Value); RegisterIndicator(symbol, _20EMA, fifteenConsolidator, p => p.Value); RegisterIndicator(symbol, _highEMA, fifteenConsolidator, Field.High); RegisterIndicator(symbol, _lowEMA, fifteenConsolidator, Field.Low); RegisterIndicator(symbol, roc, fifteenConsolidator, AveragePriceSelector); fifteenConsolidator.DataConsolidated += (s, e) => OnDataFifteen((TradeBar)e); // ASK about this line and why it's like this PlotIndicator(symbol, _8EMA); PlotIndicator(symbol, _8SMA); PlotIndicator(symbol, _20EMA); } public bool MinimumProfitAchieved { get { return (Portfolio.TotalUnrealizedProfit / Portfolio.Cash) >= targetProfit; } } public bool MaximumLossAchieved { get { return (Portfolio.TotalUnrealizedProfit / Portfolio.Cash) <= -maximumLoss; } } // 15m timeframe handler ----------------------------------------------------------------------------- private void OnDataFifteen(TradeBar consolidated) // OnData apparently not necessary, look up difference between TradeBars & TradeBar type { History.Add(consolidated); _8EMAHistory.Add(_8EMA); _8SMAHistory.Add(_8SMA); _20EMAHistory.Add(_20EMA); if (_8EMA.IsReady == false || _8SMA.IsReady == false || _20EMA.IsReady == false || History.Count < 4 || _8EMAHistory.Count < 3 || _8SMAHistory.Count < 3 || _20EMAHistory.Count < 3) // important criterion return; decimal profit = Portfolio.TotalUnrealizedProfit; decimal price = consolidated.Close; decimal high = consolidated.High; int holdings = Portfolio[symbol].Quantity; decimal HLCavg = (consolidated.High + consolidated.Low + consolidated.Close) / 3; decimal percentage = 0; //Algorithm Entry Section:========================================== //Entry Scenario Criteria ========================================== // CM Check - Scenario 1: 8EMA Crossover 20EMA // I replaced 'while' with 'if'. Tradebars will be coming, just check every tradebar. if (Math.Abs(roc) > (decimal)0.0009) // Holdings will never be < 1. I think you meant 0. { if (holdings <= 0) // CONSOLIDATION CLAUSE CHECK { //Case 1: Standard EMA Crossover Quantitative Edge Trigger if (_8EMA >= _20EMA) { // Most recent bar is History[0]. So make sure this is what you meant. if (History[0].Close > History[1].Low || History[1].Close > History[2].Low) { if (HLCavg > History[0].Close || HLCavg > History[1].Close) { //percentage = 1.5m; // Holdings should have values between -1 and 1. -- 1.5 is not correct. // if you meant 1.5%, then use 0.015 for holdings value. But let's go full size. percentage = 0.95m; SetHoldings(symbol, percentage); } } } //Case 2: EMA/SMA Crossover Quantitative Edge Trigger | NEEDS REVISION if (_8EMA < _20EMA) { if (_8EMA >= _8SMA && _8EMAHistory[0] > _8SMAHistory[0] && _8EMAHistory[1] > _8SMAHistory[1]) { if (History[0].Close > History[1].Low || History[1].Close > History[2].Low) { if (HLCavg > History[0].Close || HLCavg > History[1].Close) { percentage = 0.95m; SetHoldings(symbol, percentage); } } } } } } //Algorithm Exit Section:=========================================== if (MinimumProfitAchieved) { //Order(symbol, -holdings); // Just use Liquidate // Or, equivalently SetHoldings(0). Or, close long and open short with SetHoldings(-1). Liquidate(symbol); } if (MaximumLossAchieved) { //Order(symbol, -holdings); Liquidate(symbol); } } } }