Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

How can I pass a Series<T> to a custom class as an argument?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    How can I pass a Series<T> to a custom class as an argument?

    I have been trying to make a class which accepts two Series<T> arguments then re-factors the values into two new Series<T> - I keep getting an error of Object reference not set to an instance of the object. The class methods don't return the entire series but instead return calculations to indicate shifts in relative value between the two passed Series<T>. Any thoughts?

    The class has 4 Series<T> objects - the two which are passed in and the refactored two refactored versions - so these would I hoped stay in sync with the indicator which has instantiated the class. I am pretty novice at coding.

    Code:
    namespace NinjaTrader.NinjaScript.AddOns
    {
    public class KtRelativeValueModule: IndicatorBase
    {
    
    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    
    }
    else if (State == State.Configure)
    {
    //_anchorRefactoredArray = new Series<double>(this);
    //_refRefactoredArray = new Series<double>(this);
    //_anchorArray = new Series<double>(this);
    //_refArray = new Series<double>(this);
    }
    }
    
    private Indicator _ind = new Indicator();
    private List<double> _anchorList = new List<double>(); // redondo
    private List<double> _refList = new List<double>(); // redondo
    private Series<double> _anchorArray;
    private Series<double> _refArray;
    private Series<double> _anchorRefactoredArray;
    private Series<double> _refRefactoredArray;
    //private TimeSpan _timeSpan = new TimeSpan(0);
    private int _endBarsAgo;
    private int _startBarsAgo;
    private DateTime _startTime = new DateTime(0);
    
    private const int Granularity = 1000;
    private double _aMin, _aMax, _aUnits, _aRange, _refMin, _refMax, _refUnits, _refRange;
    private int _barCount;
    private bool _newBar;
    
    public KtRelativeValueModule()
    {
    _anchorArray = new Series<double>(thisIndicator);
    _refArray = new Series<double>(thisIndicator);
    _anchorRefactoredArray = new Series<double>(thisIndicator);
    _refRefactoredArray = new Series<double>(thisIndicator);
    _barCount = Bars.Count;
    _endBarsAgo = 0;
    
    }
    
    public KtRelativeValueModule(Series<double> anchorArray, Series<double> referenceArray) : this()
    {
    _anchorArray = anchorArray;
    _refArray = referenceArray;
    _barCount = Bars.Count;
    SetTheScene();
    }

    #2
    Hello Phixl,

    Thank you for the post.

    The first item I can note is your public class, you need to remove the inheritance from that class and make it just a class. Your extra class can have any indicator properties passed in or just the indicator instance its self.

    Code:
    public class KtRelativeValueModule
    {
        public void DoACalculation(IndicatorBase myIndicator, Series<double> anchorArray, Series<double> referenceArray)
        {
            myIndicator.Print("Use indicator function from custom class");
            myIndicator.Print(anchorArray.Count);
        }
    }
    In the method above the indicator is passed in and also the series. From an indicator it would be used like the following:

    Code:
    private NinjaTrader.NinjaScript.AddOns.KtRelativeValueModule MyModule = new NinjaTrader.NinjaScript.AddOns.KtRelativeValueModule();
    
    
    protected override void OnBarUpdate()
    {
        if(MyModule != null)
        {
             MyModule.DoACalculation(this, Close, Open);
        }
    
    }


    I look forward to being of further assistance.
    JesseNinjaTrader Customer Service

    Comment


      #3
      Thanks for that swift response!
      So you don't think I need to create a constructor for the custom class? So it always has the refactored series on demand as it were? So just have a load of methods instead?

      That probably makes sense! I will have another look.

      Thanks again
      Phil

      Comment


        #4
        Hello Phixl,

        So you don't think I need to create a constructor for the custom class?
        For what I had shown you would not, you are just working with passed in data. That would be a utility class to just separate some code out of a script. The main benefit is so that it can be re used in other scripts in a fairly generic way.

        A constructor is called when you call new MyClass(), if you had variables that needed created in that class you could use a constructor for that. Constructors can be optional depending on where the class is used and if you need something to be set up as the class is created.

        Passing in data to a default C# class is going to be the most straightforward and easy way to get going. You are out of the indicator context there so using the indicator instance like I had shown is needed for indicator properties or methods but other than that aspect it is very simple to just pass in only what is needed.

        The calling script will pass the current value of whatever parameters you supply to the method when you call it.

        There are other more complex ways to set up utility classes, you could research items like static, extension methods, partial classes. These are C# topics and best learned from external resources. Keep in mind this type of development relies on your C# abilities and debugging abilities because these are not NinjaScript specific topics. Because you are creating complex structures there is more opportunity for problems. We always suggest if you don't need to separate the code to just make it as simple as possible in a single script.

        I look forward to being of further assistance.
        JesseNinjaTrader Customer Service

        Comment


          #5
          Very helpful - thanks!
          Phil

          Comment


            #6
            I'm sorry to be thick...I have re-modelled my class and calling indicator but still I hit a problem. Object reference not set to an instance of an object.
            I'd love some help:

            Sorry for dumping so much code on you - tell me if you want me to strip it back to get to the crux of the issue.
            Ignoring the constructors for now (as the methods still have the Seris<T> arrays passed to them for calculations:

            Code:
            public class KTRelativeValueModule
            {
            private IndicatorBase _indi;
            private Series<double> _anchorArray;
            private Series<double> _refArray;
            private double[] _anchorRefactoredArray;
            private double[] _refRefactoredArray;
            public int StartBarsAgo;
            
            private const int Granularity = 1000;
            private double _aMin, _aMax, _aUnits, _aRange, _refMin, _refMax, _refUnits, _refRange;
            private int _barCount;
            private bool _newBar;
            private bool _firstArraySet;
            
            public KTRelativeValueModule()
            {
            StartBarsAgo = 100;
            EndBarsAgo = 0;
            _firstArraySet = false;
            InitializeNewArrays();
            }
            
            public KTRelativeValueModule(int startBarsAgo, IndicatorBase thisIndicator)
            {
            StartBarsAgo = startBarsAgo;
            _barCount = thisIndicator.BarsArray[0].Count;
            EndBarsAgo = 0;
            _firstArraySet = false;
            _indi = thisIndicator;
            InitializeNewArrays();
            }
            
            public KTRelativeValueModule(DateTime startTime, IndicatorBase thisIndicator)
            {
            StartTime = startTime;
            _indi = thisIndicator;
            _barCount = _indi.BarsArray[0].Count;
            StartBarsAgo = _barCount - thisIndicator.BarsArray[0].GetBar(StartTime);
            EndBarsAgo = 0;
            _firstArraySet = false;
            InitializeNewArrays();
            }
            
            
            private void SetTheScene(IndicatorBase thisIndicator, Series<double> a, Series<double> b)
            {
            bool newMaxOrMin = true;
            
            if (!_firstArraySet)
            {
            var newA = _anchorArray[0];
            var newR = _refArray[0];
            
            if (newA >= _aMin && newA <= _aMax) newMaxOrMin = false;
            else
            {
            if (newA > _aMax) _aMax = newA;
            else if (newA < _aMin) _aMin = newA;
            }
            
            if (newR >= _refMin && newR <= _refMax) newMaxOrMin = false;
            else
            {
            if (newR > _refMax) _refMax = newR;
            else if (newR < _refMin) _refMin = newR;
            }
            }
            else // initialize
            {
            _aMin = _anchorArray[EndBarsAgo];
            _refMin = _refArray[EndBarsAgo];
            }
            
            if(newMaxOrMin) RecalibrateValues(thisIndicator);
            
            RefactorArrays(thisIndicator);
            
            }
            
            private void RecalibrateValues(IndicatorBase thisIndicatorBase)
            {
            
            for (int a = EndBarsAgo; a <= StartBarsAgo; a++)
            {
            var aTemp = _anchorArray[a];
            var rTemp = _refArray[a];
            if (aTemp > _aMax) _aMax = aTemp;
            if (aTemp < _aMin) _aMin = aTemp;
            if (rTemp > _refMax) _refMax = rTemp;
            if (rTemp < _refMin) _refMin = rTemp;
            }
            
            _aRange = _aMax - _aMin;
            _refRange = _refMax - _refMin;
            _aUnits = Granularity / _aRange;
            _refUnits = Granularity / _refRange;
            _newBar = true;
            }
            
            private void RefactorArrays(IndicatorBase thisIndicatorBase)
            {
            
            
            if (_newBar)
            {
            for (int i = EndBarsAgo; i <= StartBarsAgo; i++)
            {
            var aVal = (_anchorArray[i] - _aMin) * _aUnits;
            var refVal = (_refArray[i] - _refMin) * _refUnits;
            
            if (aVal >= 0) _anchorRefactoredArray[i] = aVal;
            else db.report("Refactored Anchor value can't be less than zero!");
            if (refVal >= 0) _refRefactoredArray[i] = refVal;
            else db.report("Refactored Reference value can't be less than zero!");
            }
            
            _newBar = false;
            }
            else // only update the Right hand edge
            {
            _anchorRefactoredArray[0] = (_anchorArray[0] - _aMin) * _aUnits;
            _refRefactoredArray[0] = (_refArray[0] - _refMin) * _refUnits;
            }
            
            }
            
            private void InitializeNewArrays()
            {
            _anchorRefactoredArray = new double[StartBarsAgo + EndBarsAgo];
            _refRefactoredArray = new double[StartBarsAgo + EndBarsAgo];
            }
            
            #region Class Methods
            
            private bool SetTheBasics(IndicatorBase thisIndicator, Series<double> anchorSeries, Series<double> referenceSeries)
            {
            _anchorArray = anchorSeries;
            _refArray = referenceSeries;
            _indi = thisIndicator;
            if (_indi.CurrentBars[0] <= StartBarsAgo) return false;
            if (_barCount != _indi.BarsArray[0].Count)
            {
            _newBar = true;
            _barCount = _indi.BarsArray[0].Count;
            }
            
            SetTheScene(thisIndicator, anchorSeries, referenceSeries);
            return true;
            }
            
            
            public double GetRelativeValue(IndicatorBase thisIndicator, Series<double> anchorSeries, Series<double> referenceSeries, int barsAgo = 0, bool anchorComparedToReference = true)
            {
            if (SetTheBasics(thisIndicator, anchorSeries, referenceSeries))
            {
            return anchorComparedToReference
            ? ((_anchorRefactoredArray[barsAgo] - _refRefactoredArray[barsAgo]) / Granularity) * 100
            : ((_refRefactoredArray[barsAgo] - _anchorRefactoredArray[barsAgo]) / Granularity) * 100;
            }
            else return 0;
            
            }
            
            public double GetChangeInRelativeValue(IndicatorBase thisIndicator, Series<double> anchorSeries, Series<double> referenceSeries, int startBarsAgo, int barsAgo = 0, bool anchorComparedToReference = true)
            {
            var endpoint = GetRelativeValue(thisIndicator, anchorSeries, referenceSeries, barsAgo,
            anchorComparedToReference);
            var startpoint = GetRelativeValue(thisIndicator, anchorSeries, referenceSeries, startBarsAgo,
            anchorComparedToReference);
            
            return endpoint - startpoint;
            }
            
            public double GetChangeInAnchorValue(IndicatorBase thisIndicator, Series<double> anchorSeries, Series<double> referenceSeries, int startBarsAgo, int endBarsAgo = 0, bool usingBarIndex = false)
            {
            SetTheBasics(thisIndicator,anchorSeries,referenceS eries);
            var reebStart = usingBarIndex ? thisIndicator.BarsArray[0].Count - startBarsAgo : startBarsAgo;
            var reebEnd = usingBarIndex ? thisIndicator.BarsArray[0].Count - endBarsAgo : endBarsAgo;
            return ((_anchorRefactoredArray[endBarsAgo] - _anchorRefactoredArray[startBarsAgo]) / Granularity) * 100;
            }
            
            public double GetChangeInReferenceValue(IndicatorBase thisIndicator, Series<double> anchorSeries, Series<double> referenceSeries, int startBarsAgo, int endBarsAgo = 0, bool usingBarIndex = false)
            {
            SetTheBasics(thisIndicator,anchorSeries,referenceS eries);
            var reebStart = usingBarIndex ? thisIndicator.BarsArray[0].Count - startBarsAgo : startBarsAgo;
            var reebEnd = usingBarIndex ? thisIndicator.BarsArray[0].Count - endBarsAgo : endBarsAgo;
            return ((_refRefactoredArray[endBarsAgo] - _refRefactoredArray[startBarsAgo]) / Granularity) * 100;
            }
            
            public double GetRefactoredAnchorValue(IndicatorBase thisIndicator, Series<double> anchorSeries, Series<double> referenceSeries, int barsAgo = 0, bool usingBarIndex = false)
            {
            SetTheBasics(thisIndicator,anchorSeries,referenceS eries);
            var reeb = usingBarIndex ? thisIndicator.BarsArray[0].Count - barsAgo : barsAgo;
            
            return _anchorRefactoredArray[reeb];
            }
            
            public double GetRefactoredRefValue(IndicatorBase thisIndicator, Series<double> anchorSeries, Series<double> referenceSeries, int barsAgo = 0, bool usingBarIndex = false)
            {
            SetTheBasics(thisIndicator,anchorSeries,referenceS eries);
            var reeb = usingBarIndex ? thisIndicator.BarsArray[0].Count - barsAgo : barsAgo;
            return _anchorRefactoredArray[reeb];
            }
            
            
            #endregion
            
            #region properties
            
            public int EndBarsAgo { get; set; }
            
            
            
            #endregion

            Comment


              #7
              The calling indicator is very simple...
              Code:
              public class KTRelativeValue : Indicator
              {
              private Series<double> BUB;
              private Series<double> BOB;
              private Series<double> RV1;
              private Series<double> RV2;
              private Series<double> RV3;
              private KTRelativeValueModule _bubsbob = new KTRelativeValueModule();
              
              
              else if (State == State.Configure)
              {
              AddDataSeries("UB 06-21");
              AddDataSeries("ZB 06-21");
              BUB = new Series<double>(this);
              BOB = new Series<double>(this);
              RV1 = new Series<double>(this);
              RV2 = new Series<double>(this);
              RV3 = new Series<double>(this);
              
              }
              
              protected override void OnBarUpdate()
              {
              if (CurrentBar < 1) return;
              PopulateArrays();
              
              if (BarsInProgress == 0 && CurrentBars[0] > (AnchorBarsBack))
              {
              SetRV();
              Values[0][0] = RV1[0];
              Values[1][0] = RV2[0];
              Values[2][0] = RV3[0];
              }
              }
              
              private void SetRV()
              {
              RV1[0] = _bubsbob.GetChangeInRelativeValue(this, BUB, BOB, AnchorBarsBack,ShortCheckBack);
              RV2[0] = _bubsbob.GetChangeInRelativeValue(this, BUB, BOB, AnchorBarsBack, MediumCheckBack);
              RV3[0] = _bubsbob.GetChangeInRelativeValue(this, BUB, BOB, AnchorBarsBack, LongerCheckBack);
              }
              
              private void PopulateArrays()
              {
              BUB[0] = Closes[2][0] - Closes[1][0];
              BOB[1] = Closes[2][0] * 2 - Closes[1][0];
              }

              Comment


                #8
                Hello Phixl,

                The erorr means that something being used was null. From the sample I am not certain what that may be.

                I could suggest to comment out the logic in your custom method and then run the script and make sure it works to not produce the error. Then uncomment one line at a time to find where the error starts happening. Once you know the specific line it will be more obvious what needs to happen, if not reply back here and make note of what line was throwing the error.

                I look forward to being of further assistance.
                JesseNinjaTrader Customer Service

                Comment


                  #9
                  Thanks, will do

                  Comment

                  Latest Posts

                  Collapse

                  Topics Statistics Last Post
                  Started by llanqui, 04-28-2024, 03:53 AM
                  5 responses
                  29 views
                  0 likes
                  Last Post NinjaTrader_BrandonH  
                  Started by cmtjoancolmenero, 04-29-2024, 03:40 PM
                  18 responses
                  57 views
                  0 likes
                  Last Post cmtjoancolmenero  
                  Started by llanqui, Today, 11:13 AM
                  0 responses
                  2 views
                  0 likes
                  Last Post llanqui
                  by llanqui
                   
                  Started by ETFVoyageur, 04-30-2024, 06:05 PM
                  9 responses
                  65 views
                  0 likes
                  Last Post ETFVoyageur  
                  Started by llanqui, 04-28-2024, 10:32 AM
                  9 responses
                  36 views
                  0 likes
                  Last Post NinjaTrader_ChelseaB  
                  Working...
                  X