Profile Picture

Indicators within Indicators

Posted By sambwest Last Year
Rated 5 stars based on 1 vote.
Message
QuestionMark Posted Wednesday February 24 2016
Hi,

I am trying to use the AverageTrueRange indicator in my SeriesCalculatorBaseWithValues indicator - can it be done? 

I know I somehow need to set the inputs and new bar information on the ATR indicator but I cannot figure out how to do that.

Can anyone help?

I found the following on the forum which makes sense if you are using the same type, but what if you aren't?

As Bill mentions, you need to add a reference to Indicators.dll in your RightEdge project. Then you can declare a field in your indicator class for the indicator you want to use. In your indicator's constructor, create the instance of the indicator you want to use. Then you need to forward the new bar information to the indicator you are using. There are two types of indicators, those that implement IIndicator and those that implement ISeriesCalculator. If the indicator you are using has SetBars and  AppendBarAppendBarmethods, then it is an IIndicator. If possible, the indicator you are writing should be of the same type as the indicator you are wrapping. For IIndicators, just call the wrapped indicator's SetBars method in your SetBars method, and call the  methods, then it is an IIndicator. If possible, the indicator you are writing should be of the same type as the indicator you are wrapping. For IIndicators, just call the wrapped indicator's SetBars method in your SetBars method, and call the  AppendBarAppendBarmethod in your  method in your  AppendBarAppendBarmethod. For ISeriesCalculators, you should call SetInputs on the wrapped indicator from your indicator's constructor, call NewBar() from your NewBar method, and call NewSeries() from your NewSeries method.  method. For ISeriesCalculators, you should call SetInputs on the wrapped indicator from your indicator's constructor, call NewBar() from your NewBar method, and call NewSeries() from your NewSeries method.

Thanks,
DanielDaniel



5 stars.
Posted Wednesday March 16 2016
Hi Sam,

Three weeks later and still no response or help, this forum is a little quiet! For anyone that comes across this post asking the same questions as me, yes it can be done you just have to jump through some hoops. The way I achieved it is outlined below. I by no means claim this to be anything official there is probably a better way but without any peer support or otherwise I'm basically stumbling around in the dark. I'm also new to c# which doesn't help!

The problem between the compatibility is in simple terms one uses bars, the other uses a series. You can overcome this by constructing bars out of four series'.


 
First your SeriesCalculator based indicator will have to have the Open,High,Low,Close as inputs. 


[SeriesInputAttribute("Input", 1, Value = BarElement.Open)]
[SeriesInputAttribute("Input", 2, Value = BarElement.High)]
[SeriesInputAttribute("Input", 3, Value = BarElement.Low)]
[SeriesInputAttribute("Input", 4, Value = BarElement.Close)]
public class MyIndicatorName : SeriesCalculatorBaseWithValues


Next in the class header you will need to have a variable to store the adapter

SeriesCalculatorIndicatorBaseAdapter adapter;


Next in the constructor you will have to initilise the adapter and add any IndicatorBase indicators you want to use, you can add various if needs be. 


adapter = new SeriesCalculatorIndicatorBaseAdapter(inputs);
AverageTrueRange ATR = new AverageTrueRange(50);
adapter.AddIndicator(ATR);


Next you will need to override the following methods, like so (reset isn't used as I don't know if I need to implement something)


public override void NewBar()
{

    adapter.NewBar();
    base.NewBar();
}

public override void NewSeries(int count)
{
    adapter.NewSeries(count);
    base.NewSeries(count);
}

protected override void Reset()
{
    adapter.Reset();
    numBars = 0;
}


Then you will need to include this class somewhere. 

public class SeriesCalculatorIndicatorBaseAdapter
  {
   protected ISeries[] _inputs;
   protected List<IndicatorBase> _indicators;

   public SeriesCalculatorIndicatorBaseAdapter(params ISeries[] inputs)
   {
    _inputs = inputs;
    if (inputs.Length < 4)
    {
      throw new ArgumentException("There must be at least 4 inputs. Open, High, Low, Close.");
    }

    _indicators = new List<IndicatorBase>();
   }

   public void AddIndicator(IndicatorBase indicator)
   {
    if (!_indicators.Contains(indicator))
    {
      _indicators.Add(indicator);
    }
   }

   public void NewBar()
   {
    foreach (IndicatorBase indicator in _indicators)
    {
      _addIndicatorBar(indicator);
    }
   }

   public void NewSeries(int count)
   {
    foreach (IndicatorBase indicator in _indicators)
    {
      _addIndicatorSeries(indicator, count);
    }
   }

   public void Reset()
   {
    foreach (IndicatorBase indicator in _indicators)
    {
      _resetIndicatorSeries(indicator);
    }
   }

   private void _resetIndicatorSeries(IndicatorBase indicator)
   {
    // nothing todo?
   }

   private void _addIndicatorSeries(IndicatorBase indicator, int count)
   {
    // add the series starting with the largest
    for (int index = count - 1; index >= 0; --index)
    {
      _addIndicatorBar(indicator, index);
    }
   }

   private void _addIndicatorBar(IndicatorBase indicator, int index = 0)
   {
    BarData bar = new BarData();
    bar.Open = _inputs[0].LookBack(index);
    bar.High = _inputs[1].LookBack(index);
    bar.Low = _inputs[2].LookBack(index);
    bar.Close = _inputs[3].LookBack(index);
    indicator.AppendBar(bar);
   }
  }


To Use your indicator in your system you can use it like any other, you just need to set the four inputs



MyIndicatorName indicator = new MyIndicatorName(params);
indicator.SetInputs(Open, High, Low, Close);



If anyone is out there? And they need some help, post here and  I can try. 



Posted Thursday April 28 2016
Excellent post! Thanks for contributing! 

For my custom indicators, I usually take a slightly different route. I tend break normal coding conventions by reinvesting the wheel. Well, I prefer to minimize use of any precoded indicator anyhow, but that's just me.

In this case, if I want a custom indicator that makes use of ATR, I would have four ISeries inputs in the constructor, just like you. I would then make a helper function that calculates the ATR value for me, and use that. Same for other indicators. 

You'd get the same values in the end (hopefully) so either way works just fine. I just like having full control of the logic. The issue with using precoded indicators is that you probably don't know exactly how they're calculated. There are many ways to calculate the RSI for instance, and if you get 1000 technical analysts together and ask them for the formula, I'm convinced that 980 have no idea while the remaining 20 will argue over smoothing methods and details until the cows come home.

I just threw together a simple ATR function as an example. Yes, the code is ugly and I didn't bother with smoothing methods, input variables etc, but you'll get the point.


private double AtrHelper()
{
int periods = 20;

double HighLow;
double HighClose;
double LowClose;
double tr = 0;
double result = 0;

RightEdge.Indicators.AverageQueue atrQ = new AverageQueue(periods); // using simple average 

for (int i = 0; i < (periods - 1); i++)
{
HighLow = _high.LookBack(i) - _low.LookBack(i);
HighClose = Math.Abs(_high.LookBack(i) - _close.LookBack(i+1));
LowClose = Math.Abs(_low.LookBack(i) - _close.LookBack(i+1));
tr = Math.Max(HighLow,HighClose);
tr = Math.Max(tr,LowClose);
atrQ.AddValue(tr);
}
result = atrQ.Average;
return result;
}


Posted Thursday April 28 2016
The issue with using precoded indicators is that you probably don't know exactly how they're calculated.


FYI, the source code to the RightEdge indicators is included in the samples that are installed with RightEdge.  So you can see for yourself how they're calculated.  The code is not really easy to understand though, since most of the indicators were written for a previous version of the indicator interfaces, and now use an adapter base class so that the code didn't need to be changed much.

Thanks,
Daniel
Posted Thursday April 28 2016
Hi Andreas,

Though I can completely understand wanting control of the code, I can't help preferring a nice reusable / encapsulated package. I'm happy to use the rightedge indicator system as long as it serves my needs and I can use them interchangeably (which I can now). I'm new to this RE but I've got various tweaked indicators which I can re-use in my projects (including a Clenow Plunger, A biggest Gap and a Exponential Linear Regression slope Smile).

The only problem I can see with your approach is you end up copy and pasting anytime you want to re-use the functionality which I don't like. Personally if was going to do it like you have I'd put your method in a separate class and pass in the indicator instance. That way I can keep it decoupled. But really, that is just another RE indicator structure which seems unnecessary. 

Thanks for your input!

p.s. I enjoyed your book (Stocks on the Move)! 

Posted Thursday April 28 2016
Oh, you're absolutely right of course. It should be done properly, encapsulated, reused etc. My way can lead to far too much copy/paste errors if you're not careful. Bad habit, I suppose.

I should publish my source code for the plunger and the momentum indicators actually. I just need to find some time to clean the code a little, add some comments and some flexible inputs and such.

Thanks for the comment on the book! Much appreciated. I'm pondering a new book on ETFs, but I haven't gotten started on that yet.

Daniel: Thank you, it's great to have access to the source code for the indicators. Oh, as a totally off topic side note, this forum doesn't seem to work at all on mobile, at least not on my Android.
Posted Saturday September 17 2016
Hi sambwest,

Thank you for this post. Makes things a lot easier!
One question: In the SeriesCalculatorIndicatorBaseAdapter code below, how do we add a BarStartTime value to the bar object? This information does not seem to be there in SeriesCalculatorBase.


   
    private void _addIndicatorBar(IndicatorBase indicator, int index = 0)
    {
    BarData bar = new BarData();
    bar.Open = _inputs[0].LookBack(index);
    bar.High = _inputs[1].LookBack(index);
    bar.Low = _inputs[2].LookBack(index);
    bar.Close = _inputs[3].LookBack(index);
    indicator.AppendBar(bar);
    }



Thanks & Regards,
Ishwar.

Edited: Saturday September 17 2016 by Ishwar


Similar Topics


Reading This Topic


2005-2017 © RightEdge Systems