Overall Statistics |
Total Trades 1394 Average Win 0.19% Average Loss -0.07% Compounding Annual Return -2.953% Drawdown 7.800% Expectancy -0.085 Net Profit -2.534% Sharpe Ratio -0.607 Loss Rate 75% Win Rate 25% Profit-Loss Ratio 2.68 Alpha -0.024 Beta -0.031 Annual Standard Deviation 0.047 Annual Variance 0.002 Information Ratio -1.402 Tracking Error 0.123 Treynor Ratio 0.93 Total Fees $5515.88 |
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"; private bool _done = false; /// <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.1m); 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[_symbol].EndTime.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) { Log(String.Format("Difference between time and end time of bar: {0} - {1} : {2}", data.Time - data.EndTime, data.EndTime, Time)); if (Date.Day != data.Time.Day) { _ema.Reset(); Date = data.Time; } var price = data.Close; _ema.NewPeriodValue(price); if (!_ema.IsValid) return; if (data.EndTime.Hour >= 13) return; // no trading after 1pm if (data.EndTime.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 flat if (holdings <= 0) { // if the fast is greater than the slow, we'll go long if (data.Close > _ema.Value) { Log("LONG >> " + 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); } */ // we only want to go short if we're currently long or flat if (holdings >= 0) { // if the fast is greater than the slow, we'll go long if (data.Close < _ema.Value) { Log("SHORT >> " + Securities[data.Symbol].Price); SetHoldings(data.Symbol, -1.0); } } } } }
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; } } }