Your interactive trading laboratory!
 • 
9 users online

Indicator constraint based on additional instrument

I'm struggling with an indicator constraint based on the underlying SPY. I'm trying to draw an indicator calculation only when the SPY close is over his sma100. If the close is below 100 a value of null should be assigned to the indicators time series?

public ABC(TimeSeries source, BarHistory indexBars) : base()
{
  Parameters[0].Value = source;
  Parameters[1].Value = indexBars;
  Populate();
}

protected override void GenerateParameters()
{
  AddParameter("Source", ParameterTypes.TimeSeries, PriceComponents.Close);
  AddParameter("Index Bars", ParameterTypes.BarHistory, null);
}

public override void Populate()
{
  TimeSeries source = Parameters[0].AsTimeSeries;
  BarHistory indexBars = Parameters[1].AsBarHistory;

  SymbolData indexSymbol = new SymbolData(indexBars, "SPY", PriceComponents.Close);
  SMA indexSma = new SMA(indexSymbol, 100);

  for (int bar = 0; bar < source.Count; bar++)
  {
    if (indexBars.Close[bar] > indexSma[bar])
    {
      Values = ema.Values;
    }
  }
}
Attachment

Cancel

Responses

Hey Merlin, since you're processing in a loop, assign the actual TimeSeries values using an index …

Values[bar] = ema[bar];
Hey Merlin, since you're processing in a loop, assign the actual TimeSeries values using an index … [CODE] Values[bar] = ema[bar]; [/CODE]

Hey Glitch, I'm constantly running into an annoying message saying that the index was out of range...must be non-negative or less than the size of the collection...

Here's the full code. It's a modified version of the TASC PFE. What's wrong there?

using QuantaculaCore;
using QuantaculaIndicators;
using System.Drawing;

namespace CustomIndicators
{
    public class PolarizedFractalEfficiency : IndicatorBase
    {
        //constructors
        public PolarizedFractalEfficiency() : base()
        {
        }
        public PolarizedFractalEfficiency(TimeSeries source, int period, int smoothing, BarHistory indexBars) : base()
        {
            Parameters[0].Value = source;
            Parameters[1].Value = period;
            Parameters[2].Value = smoothing;
            Parameters[3].Value = indexBars;
            Populate();
        }

        public override string Name { get { return "Polarized Fractal Efficiency"; } }

        public override string Abbreviation { get { return "PFE"; } }

        public override string HelpDescription { get { return "Polarized Fractal Efficiency from the January 1994 issue of Stocks & Commodities magazine."; } }

        public override string PaneTag { get { return "Polarized Fractal Efficiency"; } }

        public override Color DefaultColor { get { return Color.DarkGreen; } }

        //generate parameters
        protected override void GenerateParameters()
        {
            AddParameter("Source", ParameterTypes.TimeSeries, PriceComponents.Close);
            AddParameter("Period", ParameterTypes.Int32, 9);
            AddParameter("Smoothing", ParameterTypes.Int32, 5);
            AddParameter("Index Bars", ParameterTypes.BarHistory, null);
        }

        //populate
        public override void Populate()
        {
            TimeSeries source = Parameters[0].AsTimeSeries;
            int period = Parameters[1].AsInt;
            int smoothing = Parameters[2].AsInt;
            BarHistory indexBars = Parameters[3].AsBarHistory;

            if (source.Count == 0 || source.Count < 200)
                return;

            SymbolData indexSymbol = new SymbolData(indexBars, "SPY", PriceComponents.Close);
            SMA indexSma = new SMA(indexSymbol, 200);

            TimeSeries pfe = Sqrt(Pow(source - (source >> period), 2.0) + 100.0);
            TimeSeries c2c = Sum(Sqrt(Pow(source - (source >> 1), 2.0) + 1.0), period);
            TimeSeries xFrac = BooleanTest(source - (source >> period), Round(pfe / c2c * 100.0), Round(pfe / c2c * -100.0));
            TimeSeries ema = EMA.Series(xFrac, smoothing);

            for (int bar = 1; bar < source.Count; bar++)
            {
                if (indexBars.Close[bar] > indexSma[bar])
                {
                    Values[bar] = ema[bar];
                }
                else
                {
                    Values[bar] = 1000;
                }
            }

        }
    }
}
Hey Glitch, I'm constantly running into an annoying message saying that the index was out of range...must be non-negative or less than the size of the collection... Here's the full code. It's a modified version of the TASC PFE. What's wrong there? [CODE] using QuantaculaCore; using QuantaculaIndicators; using System.Drawing; namespace CustomIndicators { public class PolarizedFractalEfficiency : IndicatorBase { //constructors public PolarizedFractalEfficiency() : base() { } public PolarizedFractalEfficiency(TimeSeries source, int period, int smoothing, BarHistory indexBars) : base() { Parameters[0].Value = source; Parameters[1].Value = period; Parameters[2].Value = smoothing; Parameters[3].Value = indexBars; Populate(); } public override string Name { get { return "Polarized Fractal Efficiency"; } } public override string Abbreviation { get { return "PFE"; } } public override string HelpDescription { get { return "Polarized Fractal Efficiency from the January 1994 issue of Stocks & Commodities magazine."; } } public override string PaneTag { get { return "Polarized Fractal Efficiency"; } } public override Color DefaultColor { get { return Color.DarkGreen; } } //generate parameters protected override void GenerateParameters() { AddParameter("Source", ParameterTypes.TimeSeries, PriceComponents.Close); AddParameter("Period", ParameterTypes.Int32, 9); AddParameter("Smoothing", ParameterTypes.Int32, 5); AddParameter("Index Bars", ParameterTypes.BarHistory, null); } //populate public override void Populate() { TimeSeries source = Parameters[0].AsTimeSeries; int period = Parameters[1].AsInt; int smoothing = Parameters[2].AsInt; BarHistory indexBars = Parameters[3].AsBarHistory; if (source.Count == 0 || source.Count < 200) return; SymbolData indexSymbol = new SymbolData(indexBars, "SPY", PriceComponents.Close); SMA indexSma = new SMA(indexSymbol, 200); TimeSeries pfe = Sqrt(Pow(source - (source >> period), 2.0) + 100.0); TimeSeries c2c = Sum(Sqrt(Pow(source - (source >> 1), 2.0) + 1.0), period); TimeSeries xFrac = BooleanTest(source - (source >> period), Round(pfe / c2c * 100.0), Round(pfe / c2c * -100.0)); TimeSeries ema = EMA.Series(xFrac, smoothing); for (int bar = 1; bar < source.Count; bar++) { if (indexBars.Close[bar] > indexSma[bar]) { Values[bar] = ema[bar]; } else { Values[bar] = 1000; } } } } } [/CODE]

Hi Merlin, the only missing piece is assigning the DateTimes property. I can see this is a bit easy to overlook, we will look into somehow assigning this beforehand so indicator authors needn't worry about it. It can cause hard to track down issues as we've seen. I also changed the comparison, you were comparing the source data closing price to the EMA of SPY instead of comparing SPY close to SPY EMA.

		//populate
		public override void Populate()
		{
			TimeSeries source = Parameters[0].AsTimeSeries;
			int period = Parameters[1].AsInt;
			int smoothing = Parameters[2].AsInt;
			BarHistory indexBars = Parameters[3].AsBarHistory;
			DateTimes = source.DateTimes;

			if (source.Count == 0 || source.Count < 200)
				return;

			SymbolData indexSymbol = new SymbolData(indexBars, "SPY", PriceComponents.Close);
			SMA indexSma = new SMA(indexSymbol, 200);

			TimeSeries pfe = Sqrt(Pow(source - (source >> period), 2.0) + 100.0);
			TimeSeries c2c = Sum(Sqrt(Pow(source - (source >> 1), 2.0) + 1.0), period);
			TimeSeries xFrac = BooleanTest(source - (source >> period), Round(pfe / c2c * 100.0), Round(pfe / c2c * -100.0));
			TimeSeries ema = EMA.Series(xFrac, smoothing);

			for (int bar = 1; bar < source.Count; bar++)
			{
				if (indexSymbol[bar] > indexSma[bar])
				{
					Values[bar] = ema[bar];
				}
				else
				{
					Values[bar] = 1000;
				}
			}
		}
Hi Merlin, the only missing piece is assigning the DateTimes property. I can see this is a bit easy to overlook, we will look into somehow assigning this beforehand so indicator authors needn't worry about it. It can cause hard to track down issues as we've seen. I also changed the comparison, you were comparing the source data closing price to the EMA of SPY instead of comparing SPY close to SPY EMA. [CODE] //populate public override void Populate() { TimeSeries source = Parameters[0].AsTimeSeries; int period = Parameters[1].AsInt; int smoothing = Parameters[2].AsInt; BarHistory indexBars = Parameters[3].AsBarHistory; DateTimes = source.DateTimes; if (source.Count == 0 || source.Count < 200) return; SymbolData indexSymbol = new SymbolData(indexBars, "SPY", PriceComponents.Close); SMA indexSma = new SMA(indexSymbol, 200); TimeSeries pfe = Sqrt(Pow(source - (source >> period), 2.0) + 100.0); TimeSeries c2c = Sum(Sqrt(Pow(source - (source >> 1), 2.0) + 1.0), period); TimeSeries xFrac = BooleanTest(source - (source >> period), Round(pfe / c2c * 100.0), Round(pfe / c2c * -100.0)); TimeSeries ema = EMA.Series(xFrac, smoothing); for (int bar = 1; bar < source.Count; bar++) { if (indexSymbol[bar] > indexSma[bar]) { Values[bar] = ema[bar]; } else { Values[bar] = 1000; } } } [/CODE]

I took a long hard look at coming up with a way to avoid the DateTimes assignment, but there's really no way short of a breaking change which I'd prefer to avoid at this point. One consolation, the Indicator Builder does the job of adding that line of code correctly, so if you use that as a base you should be OK.

I took a long hard look at coming up with a way to avoid the DateTimes assignment, but there's really no way short of a breaking change which I'd prefer to avoid at this point. One consolation, the Indicator Builder does the job of adding that line of code correctly, so if you use that as a base you should be OK.

Thanks Glitch, that solved my issue. It's a typical beginners mistake. Once occurred, you'll always remember it...

Thanks Glitch, that solved my issue. It's a typical beginners mistake. Once occurred, you'll always remember it...
Forum Tips

Please sign in if you want to participate in our forum.

Our forum uses Markdown syntax to format posts.

To embed code snippets, enclose them in [CODE][/CODE] tags.