| 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;
}
}
}