| Overall Statistics |
|
Total Trades 48 Average Win 3.21% Average Loss -0.33% Compounding Annual Return 5.098% Drawdown 11.300% Expectancy 0.154 Net Profit 5.168% Sharpe Ratio 0.411 Loss Rate 89% Win Rate 11% Profit-Loss Ratio 9.85 Alpha 0.06 Beta -0.092 Annual Standard Deviation 0.146 Annual Variance 0.021 Information Ratio 0.244 Tracking Error 0.224 Treynor Ratio -0.652 Total Fees $57.25 |
/* using the close>HMA
consolidated minute bar minutes bar
*/
namespace QuantConnect
{
/*
* QuantConnect University: Full Basic Template:
*
* The underlying QCAlgorithm class is full of helper methods which enable you to use QuantConnect.
* We have explained some of these here, but the full algorithm can be found at:
* https://github.com/QuantConnect/QCAlgorithm/blob/master/QuantConnect.Algorithm/QCAlgorithm.cs
*/
public class HullMA : QCAlgorithm
{
private const string Symbol = "SPY";
public HullMovingAverage HMA;
TradeBar _spyMinutes;
//Initialize the data and resolution you require for your strategy:
public override void Initialize()
{
//Start and End Date range for the backtest:
SetStartDate(2015, 1, 1);
SetEndDate(DateTime.Now.Date.AddDays(-1));
//Cash allocation
SetCash(25000);
//Add as many securities as you like. All the data will be passed into the event handler:
AddSecurity(SecurityType.Equity, Symbol, Resolution.Minute);
HMA = new HullMovingAverage(Symbol+"_HMA_",40);
var minConsolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(30));
// attach our event handler. the event handler is a function that will be called each time we produce
// a new consolidated piece of data.
minConsolidator.DataConsolidated += OnFiveMinutes;
// this call adds our daily consolidator to the manager to receive updates from the engine
SubscriptionManager.AddConsolidator(Symbol, minConsolidator);
RegisterIndicator(Symbol,HMA,minConsolidator,Field.Close);
}
private void OnFiveMinutes(object sender, TradeBar consolidated)
{
_spyMinutes = consolidated;
//Log(consolidated.Time.ToString("o") + " >> " + Symbol + ">> LONG >> 100 >> " + Portfolio[Symbol].Quantity);
// if you want code to run every five minutes then you can run it inside of here
// "TradeBars" object holds many "TradeBar" objects: it is a dictionary indexed by the symbol:
//
// e.g. data["MSFT"] data["GOOG"]
// wait for our slow ema to fully initialize
if (!HMA.IsReady) return;
// only once per day
//if (previous.Date == data.Time.Date) return;
// define a small tolerance on our checks to avoid bouncing
const decimal tolerance = 0*0.00015m;
var holdings = Portfolio[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 (Securities[Symbol].Price > HMA )
{
Log("BUY >> " + Securities[Symbol].Price + HMA);
SetHoldings(Symbol, 1);
}
}
// we only want to liquidate if we're currently long
// if the fast is less than the slow we'll liquidate our long
if (holdings > 0 && Securities[Symbol].Price < HMA)
{
Log("SELL >> " + Securities[Symbol].Price + HMA);
// Liquidate(Symbol);
SetHoldings(Symbol, -1);
}
}
//Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
public void OnData(TradeBars data)
{
}
}
public class HullMovingAverage : IndicatorBase<IndicatorDataPoint>
{
private readonly LinearWeightedMovingAverage _fast;
private readonly LinearWeightedMovingAverage _slow;
private readonly LinearWeightedMovingAverage _smooth;
public HullMovingAverage(string name, int period)
: base(name)
{
var nsquared = period*period;
_fast = new LinearWeightedMovingAverage(nsquared/2);
_slow = new LinearWeightedMovingAverage(nsquared);
_smooth = new LinearWeightedMovingAverage(period);
}
public override bool IsReady
{
get { return _smooth.IsReady; }
}
protected override decimal ComputeNextValue(IndicatorDataPoint input)
{
_fast.Update(input);
_slow.Update(input);
_smooth.Update(input.Time, 2*_fast - _slow);
return _smooth;
}
}
}