Back

Vortex Indicator

Hi everyone,

I'm totally new to QC and C#. My programming background is mostly in Python/R/Matlab (and some C to improve performance when necessary).
As an exercise, I tried to implement an indicator, namely the Vortex Indicator, which I believe could be useful to some of you. The Vortex Indicator is basically an "enhanced" DMI indicator (https://en.wikipedia.org/wiki/Vortex_indicator)).
Nevertheless, I am struggling a bit as I don't fully understand the Architecture of LEAN yet (and lack some C# experience). I took the ATR as a base and tried to build on that. The fact is that I am not very comfortable with the Functional indicators (is it necessary in this case?) and data structure which bothers me a bit to make the code work. Especially, I want to take the previous value of the indicator to sum it but can't help it. The Any help appreciated! Thanks in advance for your help.

Finally, one question/request does QC offer a way to call R functions (with the COM Interface)? It could could be quite useful for ML applications and other stat analysis.

Best,

L



/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

using System;
using QuantConnect.Data.Market;

namespace QuantConnect.Indicators
{
///

/// 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
///
///

///

public class Vortex : TradeBarIndicator
{

private Sum _Sum;
private int _period;

///
/// Gets the Sumtrue,VMplus and VMminus range which is the more volatile calculation to be smoothed by this indicator
///

public IndicatorBase SumTrueRange { get; private set; }
public IndicatorBase VMplus { get; private set; }
public IndicatorBase VMminus { get; private set; }

///
/// Gets a flag indicating when this indicator is ready and fully initialized
///


public override bool IsReady
{
get { return Samples > _period; }
}

///
/// Creates a new AverageTrueRange indicator using the specified period and moving average type
///

/// The name of this indicator
/// The smoothing period used to smooth the true range values

public Vortex(string name, int period)
: base(name)
{
_period = period;

TradeBar previous = null;

SumTrueRange = new FunctionalIndicator(name + "_SumTrueRange", 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
);

VMplus = new FunctionalIndicator(name + "_SumTrueRange", currentBar =>
{
// in our ComputeNextValue function we'll just call the ComputeTrueRange
var nextValue = ComputeVMplus(previous, currentBar);
previous = currentBar;
return nextValue;
} // in our IsReady function we just need at least two sample
, trueRangeIndicator => trueRangeIndicator.Samples >= _period
);

VMminus = new FunctionalIndicator(name + "_SumTrueRange", currentBar =>
{
// in our ComputeNextValue function we'll just call the ComputeTrueRange
var nextValue = ComputeVMminus(previous, currentBar);
previous = currentBar;
return nextValue;
} // in our IsReady function we just need at least two sample
, trueRangeIndicator => trueRangeIndicator.Samples >= _period
);







}

///
/// Creates a new AverageTrueRange indicator using the specified period and moving average type
///

/// The smoothing period used to smooth the true range values
/// The type of smoothing used to smooth the true range values
public Vortex(int period)
: this("Vortex" + period, period)
{
}


public static decimal ComputeSumTrueRange(TradeBar previous, TradeBar current)
{
var range1 = current.High - current.Low;
if (previous == null)
{
return 0m;
}

var range2 = Math.Abs(current.High - previous.Close);
var range3 = Math.Abs(current.Low - previous.Close);

return SumTrueRange.Current + Math.Max(range1, Math.Max(range2, range3));
}

public static decimal ComputeVMplus(TradeBar previous, TradeBar current)
{

if (previous == null)
{
return;
}

var range = Math.Abs(current.High - previous.Low);


return Current + range;
}

public static decimal ComputeVMminus(TradeBar previous, TradeBar current)
{

if (previous == null)
{
return;
}

var range = Math.Abs(current.Low - previous.High);

return Current + range;
}



///
/// Computes the next value of this indicator from the given state
///

/// The input given to the indicator
/// A new value for this indicator
protected override decimal ComputeNextValue(TradeBar input)
{
// compute the true range and then sum it
SumTrueRange.Update(input);
VMplus.Update(input);
VMminus.Update(input);

decimal VIplus= VMplus / SumTrueRange;
decimal VIminus= VMminus / SumTrueRange;
return VIplus - VIminus;
}

///
/// Resets this indicator to its initial state
///

public override void Reset()
{

TrueRange.Reset();
VMplus.Reset();
VMminus.Reset();
base.Reset();
}
}
}

Update Backtest








The main benefit of the functional indicators is that it exposes the internal values of your indicator as an indicator object. This allows those values to be used in the indicator system (such as the extension methods). If you don't require those values to be exposed as Indicator instances, then you can compute them internally without using the FunctionalIndicator type.

On first glance it looks like you've coded things up correctly. What problems are you having with it?
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks for your explanation Michael,

It comes from the function where I try to use "Current" to get the current value. Here is what I get from the compiler.:


Build Error: File: /Vortex.cs Line:135 Column:15 - An object reference is required for the non-static field, method, or property 'Vortex.SumTrueRange'

Build Error: File: /Vortex.cs Line:150 Column:19 - An object reference is required for the non-static field, method, or property 'IndicatorBase.Current'
Build Error: File: /Vortex.cs Line:163 Column:19 - An object reference is required for the non-static field, method, or property 'IndicatorBase.Current'
0

This just means it can't find the variable since its declared as a static above. To fix all I did was removed the statics and made it return 0's when it wasn't ready, and fixed the Reset method to use "SumTrueRange" instead of the "TrueRange" that was there.
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks for the fix Jared. Actually my code was totally wrong. The Vortex should results in 2 indicators (VI+ et VI-). I corrected and cleaned up a bit but now the problem is that both VI+ and VI- return the same value... I can't find what I am missing. I see in the log that both HI and LO return the same value so there must something that I missed somewhere.
0


There was one problem I found with the code. The 'previous' variable should be defined in the class scope and should only be set once at the end of ComputeNextValue. Multiple callers were setting this value which probably led to input == previous, hence the zeros.
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks for the help. Indeed that was the problem. Best, L
0

Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

This discussion is closed