Overall Statistics |
Total Trades 255 Average Win 0% Average Loss -0.15% Compounding Annual Return -17.943% Drawdown 33.700% Expectancy -1 Net Profit -32.675% Sharpe Ratio -1.562 Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.167 Beta 0.063 Annual Standard Deviation 0.1 Annual Variance 0.01 Information Ratio -2.401 Tracking Error 0.137 Treynor Ratio -2.484 Total Fees $255.00 |
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 BasicTemplateAlgorithm : QCAlgorithm { private Vortex vtx; //Initialize the data and resolution you require for your strategy: public override void Initialize() { //Start and End Date range for the backtest: SetStartDate(2013, 1, 1); SetEndDate(2015, 1, 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, "SPY", Resolution.Daily); vtx = new Vortex(14); RegisterIndicator("SPY", vtx, Resolution.Daily); } //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) { if (!vtx.IsReady) { return ; } Log(vtx.HI.Current.Value.ToString()); Log(vtx.LO.Current.Value.ToString()); //Log(vtx.VMplus.Current.Value.ToString()); //Log(vtx.VMminus.Current.Value.ToString()); //Log(vtx.VIplus.Current.Value.ToString()); //Log(vtx.VIminus.Current.Value.ToString()); //Log(vtx.TrueRange.Current.Value.ToString()); Plot("Vortex", vtx.VIplus, vtx.VIminus); //var quantity = Portfolio["SPY"].Quantity; Console.WriteLine((vtx.VIplus-vtx.VIminus).ToString()); if ( vtx.VIplus > vtx.VIminus) { SetHoldings("SPY", 1.0); } else { SetHoldings("SPY", -1.0); } } } }
using System; using QuantConnect.Data.Market; namespace QuantConnect.Indicators { /// <summary> /// SumTrueRange is defined as the maximum of the following: /// High - Low /// ABS(High - PreviousClose) /// ABS(Low - PreviousClose) /// Summed over a N peridos window /// VMplus: /// /// SUM(ABS(High - previous.Low), N periods) /// VMminus: /// /// SUM(ABS(High - previous.High), N periods) /// Vortex Indicator: /// VMplus / SumTrueRange - VMminus / SumTrueRange /// /// /// </summary> public class Vortex : TradeBarIndicator { private int _period; public IndicatorBase<TradeBar> TrueRange { get; private set; } public IndicatorBase<TradeBar> HI { get; private set; } public IndicatorBase<TradeBar> LO { get; private set; } public IndicatorBase<IndicatorDataPoint> RollingSumTR { get; private set; } public IndicatorBase<IndicatorDataPoint> VMplus { get; private set; } public IndicatorBase<IndicatorDataPoint> VMminus { get; private set; } public IndicatorBase<TradeBar> VIplus { get; private set; } public IndicatorBase<TradeBar> VIminus { get; private set; } public override bool IsReady { get { return Samples > _period; } } public Vortex(string name, int period) : base(name) { _period = period; TradeBar previous = null; RollingSumTR = new Sum(name + "_SumTR", period); VMplus = new Sum(name + "_Plus", period); VMminus = new Sum(name + "_Minus", period); HI = new FunctionalIndicator<TradeBar>(name + period, currentBar => { // in our ComputeNextValue function we'll just call the ComputeTrueRange var nextValue = ComputeHI(previous, currentBar); previous = currentBar; return nextValue; } // in our IsReady function we just need at least two sample , trueRangeIndicator => trueRangeIndicator.Samples >= _period ); LO = new FunctionalIndicator<TradeBar>(name + period, currentBar => { // in our ComputeNextValue function we'll just call the ComputeTrueRange var nextValue = ComputeLO(previous, currentBar); previous = currentBar; return nextValue; } // in our IsReady function we just need at least two sample , trueRangeIndicator => trueRangeIndicator.Samples >= _period ); VIminus = new FunctionalIndicator<TradeBar>(name + period +"minus", currentBar=> ComputeVIminus(currentBar) , trueRangeIndicator => trueRangeIndicator.Samples >= _period ); VIplus = new FunctionalIndicator<TradeBar>(name + period +"plus", currentBar=> ComputeVIplus(currentBar) , trueRangeIndicator => trueRangeIndicator.Samples >= _period ); TrueRange = new FunctionalIndicator<TradeBar>(name + "_TrueRange", currentBar => { // in our ComputeNextValue function we'll just call the ComputeTrueRange var nextValue = ComputeSumTrueRange(previous, currentBar); previous = currentBar; return nextValue; } // in our IsReady function we just need at least two sample , trueRangeIndicator => trueRangeIndicator.Samples >= _period ); } public Vortex(int period) : this("Vortex" + period, period) { } public decimal ComputeSumTrueRange(TradeBar previous, TradeBar current) { if (previous == null) { return 0; } var range1 = current.High - current.Low; var range2 = Math.Abs(current.High - previous.Close); var range3 = Math.Abs(current.Low - previous.Close); return Math.Max(range1, Math.Max(range2, range3)); } public decimal ComputeHI(TradeBar previous, TradeBar current) { if (previous == null) { return 0; } var _HI = Math.Abs(current.High - previous.Low); return _HI; } public decimal ComputeLO(TradeBar previous, TradeBar current) { if (previous == null) { return 0; } var _LO = Math.Abs(current.Low - previous.High) ; return _LO; } public decimal ComputeVIplus(TradeBar input) { if(RollingSumTR.Current.Value == 0) return 0; return VMplus.Current.Value / RollingSumTR.Current.Value; } public decimal ComputeVIminus(TradeBar input) { if(RollingSumTR.Current.Value == 0) return 0; return VMminus.Current.Value / RollingSumTR.Current.Value; } protected override decimal ComputeNextValue(TradeBar input) { // update the true range and then sum it TrueRange.Update(input); RollingSumTR.Update(input.Time, TrueRange.Current.Value); HI.Update(input); LO.Update(input); VMplus.Update(input.Time, HI.Current.Value); VMminus.Update(input.Time, LO.Current.Value); VIplus.Update(input); VIminus.Update(input); return 0; } public override void Reset() { HI.Reset(); LO.Reset(); TrueRange.Reset(); VMplus.Reset(); VMminus.Reset(); RollingSumTR.Reset(); VIplus.Reset(); VIminus.Reset(); base.Reset(); } } }