Overall Statistics |
Total Trades 2582 Average Win 0.13% Average Loss -0.05% Compounding Annual Return -9.528% Drawdown 9.300% Expectancy -0.124 Net Profit -8.215% Sharpe Ratio -2.364 Loss Rate 74% Win Rate 26% Profit-Loss Ratio 2.42 Alpha -0.092 Beta -0.043 Annual Standard Deviation 0.041 Annual Variance 0.002 Information Ratio -1.977 Tracking Error 0.122 Treynor Ratio 2.256 Total Fees $6621.54 |
using System; using QuantConnect.Data.Consolidators; using QuantConnect.Data.Market; using QuantConnect.Indicators; namespace QuantConnect { public class RenkoEMACrossoverAlgorithm : QCAlgorithm { private EMA _ema = new EMA(13); private string _symbol = "SPY"; /// <summary> /// Initializes the algorithm state. /// </summary> public override void Initialize() { SetStartDate(2014, 01, 01); SetEndDate(2014, 11, 10); AddSecurity(SecurityType.Equity, _symbol); // this is the simple constructor that will perform the renko logic to the Value // property of the data it receives. // break SPY into $1 renko bricks and send that data to our 'OnRenkoBar' method var renkoClose = new RenkoConsolidator(0.05m); renkoClose.DataConsolidated += (sender, consolidated) => { // call our event handler for renko data HandleRenkoClose(consolidated); }; // register the consolidator for updates SubscriptionManager.AddConsolidator(_symbol, renkoClose); } /// <summary> /// We're doing our analysis in the OnRenkoBar method, but the framework verifies that this method exists, so we define it. /// </summary> public void OnData(TradeBars data) { var holdings = Portfolio[_symbol].Quantity; if (data.Time.Hour > 13 && holdings > 0){ Log("SELL!!! After 1pm!!! >> " + Securities[_symbol].Price); Liquidate(_symbol); } } private DateTime Date {get; set;} /// <summary> /// This function is called by our renkoClose consolidator defined in Initialize() /// </summary> /// <param name="data">The new renko bar produced by the consolidator</param> public void HandleRenkoClose(RenkoBar data) { if (Date.Day != data.Time.Day) { _ema.Reset(); Date = data.Time; } var price = data.Close; _ema.NewPeriodValue(price); if (!_ema.IsValid) return; if (data.Time.Hour > 13) return; // no trading after 1pm if (data.Time.Hour < 10) return; // no trading before 10am Log(String.Format("Renko {0} - OHLC[{1}, {2}, {3}, {4}] - SMA - {5}", data.Time.ToString("o"), data.Open, data.High, data.Low, data.Close, _ema.Value)); var holdings = Portfolio[data.Symbol].Quantity; // we only want to go long if we're currently short or flat if (holdings <= 0) { // if the fast is greater than the slow, we'll go long if (data.Close > _ema.Value) { Log("BUY >> " + Securities[data.Symbol].Price); SetHoldings(data.Symbol, 1.0); } } if (holdings > 0 && data.Close < _ema.Value) { Log("SELL >> " + Securities[data.Symbol].Price); Liquidate(data.Symbol); } } } }
namespace QuantConnect { public class EMA { private int _samples = 0; private decimal _k = 0; public EMA(int period) { Period = period; _k = 2 / ((decimal)period + 1); Reset(); } public void Reset(){ Value = 0; _samples = 0; } public decimal Value { get; set; } public int Period {get; private set;} public bool IsValid { get; private set; } public void NewPeriodValue(decimal value) { if (Value == 0) { Value = value; return; } Value = _k * value + (1 - _k) * Value; _samples++; IsValid = _samples > Period; } } }